1/*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import { SpSystemTrace } from '../SpSystemTrace';
17import { info } from '../../../log/Log';
18import { TraceRow } from '../trace/base/TraceRow';
19import { BaseStruct } from '../../bean/BaseStruct';
20import { EnergyAnomalyRender, EnergyAnomalyStruct } from '../../database/ui-worker/ProcedureWorkerEnergyAnomaly';
21import { EnergySystemStruct, EnergySystemRender } from '../../database/ui-worker/ProcedureWorkerEnergySystem';
22import { EnergyPowerStruct, EnergyPowerRender } from '../../database/ui-worker/ProcedureWorkerEnergyPower';
23import { EnergyStateStruct, EnergyStateRender } from '../../database/ui-worker/ProcedureWorkerEnergyState';
24import { renders } from '../../database/ui-worker/ProcedureWorker';
25import { EmptyRender } from '../../database/ui-worker/cpu/ProcedureWorkerCPU';
26import { TreeItemData } from '../../../base-ui/tree/LitTree';
27import {
28  energySysEventSender,
29  hiSysEnergyAnomalyDataSender,
30  hiSysEnergyPowerSender,
31  hiSysEnergyStateSender,
32} from '../../database/data-trafic/EnergySysEventSender';
33import {
34  queryAnomalyData,
35  queryConfigEnergyAppName,
36  queryEnergyAppName,
37  queryEnergyEventExits,
38  queryMaxStateValue,
39  queryStateInitValue,
40} from '../../database/sql/SqlLite.sql';
41import { queryPowerData } from '../../database/sql/ProcessThread.sql';
42import { NUM_200, NUM_3 } from '../../bean/NumBean';
43
44export class SpHiSysEnergyChart {
45  static app_name: string | null;
46  trace: SpSystemTrace;
47  private energyTraceRow: TraceRow<BaseStruct> | undefined;
48  private timer: number | undefined;
49  private eventNameMap: Map<number, string> = new Map();
50  private appKeyMap: Map<number, string> = new Map();
51  private eventValueMap: Map<number, string> = new Map();
52  private powerEventNameMap: Map<number, string> = new Map();
53  private powerAppKeyNameMap: Map<number, string> = new Map();
54  private powerEventValueMap: Map<number, string> = new Map();
55  private stateName: Array<string> = [
56    'BRIGHTNESS_NIT',
57    'SIGNAL_LEVEL',
58    'WIFI_EVENT_RECEIVED',
59    'AUDIO_STREAM_CHANGE',
60    'AUDIO_VOLUME_CHANGE',
61    'WIFI_STATE',
62    'BLUETOOTH_BR_SWITCH_STATE',
63    'BR_SWITCH_STATE',
64    'LOCATION_SWITCH_STATE',
65    'SENSOR_STATE',
66  ];
67  private initValueList: Array<string> = [
68    'brightness',
69    'nocolumn',
70    'nocolumn',
71    'nocolumn',
72    'nocolumn',
73    'wifi',
74    'bt_state',
75    'bt_state',
76    'location',
77    'nocolumn',
78  ];
79  private stateList: Array<string> = [
80    'Brightness Nit',
81    'Signal Level',
82    'Wifi Event Received',
83    'Audio Stream Change',
84    'Audio Volume Change',
85    'Wifi State',
86    'Bluetooth Br Switch State',
87    'Br Switch State',
88    'Location Switch State',
89    'Sensor State',
90  ];
91
92  constructor(trace: SpSystemTrace) {
93    this.trace = trace;
94  }
95
96  async init(): Promise<void> {
97    let result = await queryEnergyEventExits();
98    if (result.length <= 0) {
99      return;
100    }
101    let anomalyData = await queryAnomalyData();
102    let powerData = await queryPowerData();
103    for (let index = 0; index < anomalyData.length; index++) {
104      let item = anomalyData[index];
105      this.eventNameMap.set(item.id!, item.eventName ?? '');
106      this.appKeyMap.set(item.id!, item.appKey ?? '');
107      this.eventValueMap.set(item.id!, item.eventValue ?? '');
108    }
109    for (let index = 0; index < powerData.length; index++) {
110      let item = powerData[index];
111      this.powerEventNameMap.set(item.id, item.eventName ?? '');
112      this.powerAppKeyNameMap.set(item.id, item.appKey ?? '');
113      this.powerEventValueMap.set(item.id, item.eventValue ?? '');
114    }
115    await this.initEnergyRow();
116    this.initAnomaly();
117    this.initSystem();
118    this.initPower();
119    await this.initState();
120  }
121
122  private async initEnergyRow(): Promise<void> {
123    await this.initEnergyChartRow();
124    this.energyTraceRow!.favoriteChangeHandler = this.trace.favoriteChangeHandler;
125    this.energyTraceRow!.selectChangeHandler = this.trace.selectChangeHandler;
126    this.energyTraceRow!.supplier = (): Promise<BaseStruct[]> =>
127      new Promise<Array<BaseStruct>>((resolve) => resolve([]));
128    this.energyTraceRow!.onThreadHandler = (useCache: boolean): void => {
129      this.energyTraceRow?.canvasSave(this.trace.canvasPanelCtx!);
130      if (this.energyTraceRow!.expansion) {
131        // @ts-ignore
132        this.trace.canvasPanelCtx?.clearRect(0, 0, this.energyTraceRow!.frame.width, this.energyTraceRow!.frame.height);
133      } else {
134        (renders.empty as EmptyRender).renderMainThread(
135          {
136            context: this.trace.canvasPanelCtx,
137            useCache: useCache,
138            type: '',
139          },
140          this.energyTraceRow!
141        );
142      }
143      this.energyTraceRow?.canvasRestore(this.trace.canvasPanelCtx!, this.trace);
144    };
145    this.energyTraceRow!.addEventListener('expansion-change', () => {
146      TraceRow.range!.refresh = true;
147      this.trace.refreshCanvas(false);
148      if (this.timer) {
149        clearTimeout(this.timer);
150      }
151      this.timer = window.setTimeout((): void => {
152        TraceRow.range!.refresh = false;
153      }, NUM_200);
154    });
155    this.trace.rowsEL?.appendChild(this.energyTraceRow!);
156  }
157
158  private initAnomaly = (): void => {
159    let time = new Date().getTime();
160    let anomalyTraceRow = this.initAnomalyChartRow();
161    anomalyTraceRow.supplierFrame = async (): Promise<EnergyAnomalyStruct[]> => {
162      return hiSysEnergyAnomalyDataSender(anomalyTraceRow).then((res: EnergyAnomalyStruct[]) => {
163        for (let index = 0; index < res.length; index++) {
164          let item = res[index];
165          item.eventName = this.eventNameMap.get(res[index].id!);
166          item.appKey = this.appKeyMap.get(res[index].id!);
167          item.eventValue = this.eventValueMap.get(res[index].id!);
168        }
169        return res;
170      });
171    };
172    anomalyTraceRow.findHoverStruct = (): void => {
173      EnergyAnomalyStruct.hoverEnergyAnomalyStruct = anomalyTraceRow.getHoverStruct();
174    };
175    anomalyTraceRow.onThreadHandler = (useCache: boolean): void => {
176      let context: CanvasRenderingContext2D;
177      if (anomalyTraceRow.currentContext) {
178        context = anomalyTraceRow.currentContext;
179      } else {
180        context = anomalyTraceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!;
181      }
182      anomalyTraceRow.canvasSave(context);
183      (renders.energyAnomaly as EnergyAnomalyRender).renderMainThread(
184        {
185          context: context,
186          useCache: useCache,
187          type: 'energyAnomaly',
188          appName: SpHiSysEnergyChart.app_name || '',
189          canvasWidth: this.trace.canvasPanel?.width || 0,
190        },
191        anomalyTraceRow
192      );
193      anomalyTraceRow.canvasRestore(context, this.trace);
194    };
195    this.energyTraceRow?.addChildTraceRow(anomalyTraceRow);
196    let durTime = new Date().getTime() - time;
197    info('The time to load the anomaly is: ', durTime);
198  };
199
200  private initSystem = (): void => {
201    let time = new Date().getTime();
202    let systemTraceRow = this.initSystemChartRow();
203    systemTraceRow.supplierFrame = async (): Promise<EnergySystemStruct[]> => {
204      return energySysEventSender(systemTraceRow).then((res: EnergySystemStruct[]) => {
205        return res;
206      });
207    };
208    systemTraceRow.findHoverStruct = (): void => {
209      EnergySystemStruct.hoverEnergySystemStruct = systemTraceRow.getHoverStruct();
210    };
211    systemTraceRow.onThreadHandler = (useCache: boolean): void => {
212      let context: CanvasRenderingContext2D;
213      if (systemTraceRow.currentContext) {
214        context = systemTraceRow.currentContext;
215      } else {
216        context = systemTraceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!;
217      }
218      systemTraceRow.canvasSave(context);
219      (renders.energySystem as EnergySystemRender).renderMainThread(
220        {
221          context: context,
222          useCache: useCache,
223          type: 'energySystem',
224        },
225        systemTraceRow
226      );
227      systemTraceRow.canvasRestore(context, this.trace);
228    };
229    this.energyTraceRow?.addChildTraceRow(systemTraceRow);
230    let durTime = new Date().getTime() - time;
231    info('The time to load the Ability Memory is: ', durTime);
232  };
233
234  private initPower = (): void => {
235    let time = new Date().getTime();
236    let powerTraceRow = this.initPowerChartRow();
237    powerTraceRow.supplierFrame = async (): Promise<EnergyPowerStruct[]> => {
238      return hiSysEnergyPowerSender(powerTraceRow).then((res) => {
239        for (let index = 0; index < res.length; index++) {
240          let item = res[index];
241          item.eventName = this.powerEventNameMap.get(res[index].id!);
242          item.appKey = this.powerAppKeyNameMap.get(res[index].id!);
243          item.eventValue = this.powerEventValueMap.get(res[index].id!);
244        }
245        return this.getPowerData(res);
246      });
247    };
248    powerTraceRow.onThreadHandler = (useCache: boolean): void => {
249      let context: CanvasRenderingContext2D;
250      if (powerTraceRow.currentContext) {
251        context = powerTraceRow.currentContext;
252      } else {
253        context = powerTraceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!;
254      }
255      powerTraceRow.canvasSave(context);
256      (renders.energyPower as EnergyPowerRender).renderMainThread(
257        {
258          context: context,
259          useCache: useCache,
260          type: 'energyPower',
261          appName: SpHiSysEnergyChart.app_name || '',
262        },
263        powerTraceRow!
264      );
265      powerTraceRow!.canvasRestore(context, this.trace);
266    };
267    this.energyTraceRow?.addChildTraceRow(powerTraceRow);
268    let durTime = new Date().getTime() - time;
269    info('The time to load the energy power is: ', durTime);
270  };
271
272  private initState = async (): Promise<void> => {
273    let time = new Date().getTime();
274    for (let index = 0; index < this.stateList.length; index++) {
275      let stateResult = await queryStateInitValue(this.stateName[index], this.initValueList[index]);
276      let maxStateData = await queryMaxStateValue(this.stateName[index]);
277      if (!maxStateData[0]) {
278        continue;
279      }
280      let maxStateTotal = this.getMaxStateTotal(maxStateData);
281      let stateTraceRow = this.initStatChartRow(index);
282      stateTraceRow.supplierFrame = async (): Promise<EnergyStateStruct[]> => {
283        const res = await hiSysEnergyStateSender(this.stateName, index, stateTraceRow);
284        let stateInitValue = this.initValueList[index] === 'nocolumn' ? [] : stateResult;
285        for (let i = 0; i < res.length; i++) {
286          let item = res[i];
287          item.type = this.stateName[index];
288        }
289        return stateInitValue.concat(res);
290      };
291      stateTraceRow.onThreadHandler = (useCache: boolean): void => {
292        let context: CanvasRenderingContext2D;
293        if (stateTraceRow.currentContext) {
294          context = stateTraceRow.currentContext;
295        } else {
296          context = stateTraceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!;
297        }
298        stateTraceRow.canvasSave(context);
299        (renders.energyState as EnergyStateRender).renderMainThread(
300          {
301            context: context,
302            useCache: useCache,
303            type: `energyState${index}`,
304            maxState: maxStateData[0].maxValue,
305            maxStateName: maxStateData[0].type.toLocaleLowerCase().endsWith('br_switch_state')
306              ? '-1'
307              : maxStateTotal.toString(),
308          },
309          stateTraceRow
310        );
311        stateTraceRow.canvasRestore(context, this.trace);
312      };
313      this.energyTraceRow?.addChildTraceRow(stateTraceRow);
314      let durTime = new Date().getTime() - time;
315      info('The time to load the Ability Memory is: ', durTime);
316    }
317  };
318
319  private getMaxStateTotal(
320    maxStateData: Array<{
321      type: string;
322      maxValue: number;
323    }>
324  ): string {
325    let maxStateTotal = maxStateData[0].maxValue.toString();
326    let statType = maxStateData[0].type.toLocaleLowerCase();
327    if (statType.includes('state') && !statType.endsWith('br_switch_state')) {
328      if (maxStateData[0].maxValue === 0) {
329        maxStateTotal = 'enable';
330      } else {
331        maxStateTotal = 'disable';
332      }
333    } else if (statType.includes('sensor')) {
334      if (statType.includes('enable')) {
335        maxStateTotal = 'enable';
336      } else {
337        maxStateTotal = 'disable';
338      }
339    }
340    return maxStateTotal;
341  }
342
343  private initStatChartRow(index: number): TraceRow<EnergyStateStruct> {
344    let stateTraceRow = TraceRow.skeleton<EnergyStateStruct>();
345    stateTraceRow.rowParentId = 'energy';
346    stateTraceRow.rowHidden = true;
347    stateTraceRow.rowId = `energy-state-${this.stateList[index]}`;
348    stateTraceRow.rowType = TraceRow.ROW_TYPE_STATE_ENERGY;
349    stateTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler;
350    stateTraceRow.selectChangeHandler = this.trace.selectChangeHandler;
351    stateTraceRow.style.height = '40px';
352    stateTraceRow.style.width = '100%';
353    stateTraceRow.setAttribute('children', '');
354    stateTraceRow.name = `${this.stateList[index]}`;
355    stateTraceRow.focusHandler = (): void => {
356      let tip;
357      if (EnergyStateStruct.hoverEnergyStateStruct?.type!.toLocaleLowerCase().includes('state')) {
358        tip = `<span>Switch Status: ${
359          EnergyStateStruct.hoverEnergyStateStruct?.value === 1 ? 'disable' : 'enable'
360        }</span>`;
361        if (EnergyStateStruct.hoverEnergyStateStruct?.type!.toLocaleLowerCase().endsWith('br_switch_state')) {
362          tip = `<span>${SpHiSysEnergyChart.getBlueToothState(EnergyStateStruct.hoverEnergyStateStruct?.value)}</span>`;
363        }
364      } else {
365        tip = `<span>value: ${EnergyStateStruct.hoverEnergyStateStruct?.value?.toFixed(2) || 0}</span>`;
366      }
367      this.trace?.displayTip(stateTraceRow, EnergyStateStruct.hoverEnergyStateStruct, tip);
368    };
369    return stateTraceRow;
370  }
371
372  private async initEnergyChartRow(): Promise<void> {
373    SpHiSysEnergyChart.app_name = '';
374    let appNameFromTable = await queryEnergyAppName();
375    let configAppName = await queryConfigEnergyAppName();
376    if (configAppName.length > 0 && appNameFromTable.length > 0) {
377      let name = configAppName[0].process_name;
378      if (name !== null) {
379        let filterList = appNameFromTable.filter((appNameFromTableElement) => {
380          return appNameFromTableElement.string_value?.trim() === name;
381        });
382        if (filterList.length > 0) {
383          SpHiSysEnergyChart.app_name = name;
384        }
385      }
386    }
387    appNameFromTable.sort((a, b) => {
388      return a.string_value!.localeCompare(b.string_value!);
389    });
390    if (appNameFromTable.length > 0 && SpHiSysEnergyChart.app_name === '') {
391      SpHiSysEnergyChart.app_name = appNameFromTable[0].string_value;
392    }
393    this.energyTraceRow = TraceRow.skeleton<BaseStruct>();
394    this.energyTraceRow.addRowSettingPop();
395    this.energyTraceRow.rowSetting = 'enable';
396    this.energyTraceRow.rowSettingPopoverDirection = 'bottomLeft';
397    let nameList: Array<TreeItemData> = [];
398    for (let index = 0; index < appNameFromTable.length; index++) {
399      let appName = appNameFromTable[index].string_value;
400      nameList.push({
401        key: `${appName}`,
402        title: `${appName}`,
403        checked: index === 0,
404      });
405    }
406    this.energyTraceRow.rowSettingList = nameList;
407    this.energyTraceRow.onRowSettingChangeHandler = (value): void => {
408      SpHiSysEnergyChart.app_name = value[0];
409      this.trace.refreshCanvas(false);
410    };
411    this.energyTraceRow.rowId = 'energy';
412    this.energyTraceRow.rowType = TraceRow.ROW_TYPE_ENERGY;
413    this.energyTraceRow.rowParentId = '';
414    this.energyTraceRow.folder = true;
415    this.energyTraceRow.addTemplateTypes('EnergyEvent');
416    this.energyTraceRow.name = 'Energy';
417    this.energyTraceRow.style.height = '40px';
418  }
419
420  private initAnomalyChartRow(): TraceRow<EnergyAnomalyStruct> {
421    let anomalyTraceRow = TraceRow.skeleton<EnergyAnomalyStruct>();
422    anomalyTraceRow.rowParentId = 'energy';
423    anomalyTraceRow.rowHidden = true;
424    anomalyTraceRow.rowId = 'energy-anomaly';
425    anomalyTraceRow.rowType = TraceRow.ROW_TYPE_ANOMALY_ENERGY;
426    anomalyTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler;
427    anomalyTraceRow.selectChangeHandler = this.trace.selectChangeHandler;
428    anomalyTraceRow.setAttribute('height', '55px');
429    let element = anomalyTraceRow.shadowRoot?.querySelector('.root') as HTMLDivElement;
430    element!.style.height = '55px';
431    anomalyTraceRow.style.width = '100%';
432    anomalyTraceRow.setAttribute('children', '');
433    anomalyTraceRow.name = 'Anomaly Event';
434    anomalyTraceRow.focusHandler = (): void => {
435      this.trace?.displayTip(
436        anomalyTraceRow,
437        EnergyAnomalyStruct.hoverEnergyAnomalyStruct,
438        `<span>AnomalyName:${EnergyAnomalyStruct.hoverEnergyAnomalyStruct?.eventName || ''}</span>`
439      );
440    };
441    return anomalyTraceRow;
442  }
443
444  private initSystemChartRow(): TraceRow<EnergySystemStruct> {
445    let systemTraceRow = TraceRow.skeleton<EnergySystemStruct>();
446    systemTraceRow.rowParentId = 'energy';
447    systemTraceRow.rowHidden = true;
448    systemTraceRow.rowId = 'energy-system';
449    systemTraceRow.rowType = TraceRow.ROW_TYPE_SYSTEM_ENERGY;
450    systemTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler;
451    systemTraceRow.selectChangeHandler = this.trace.selectChangeHandler;
452    systemTraceRow.setAttribute('height', '80px');
453    let element = systemTraceRow.shadowRoot?.querySelector('.root') as HTMLDivElement;
454    element!.style.height = '90px';
455    systemTraceRow.style.width = '100%';
456    systemTraceRow.setAttribute('children', '');
457    systemTraceRow.name = 'System Event';
458    systemTraceRow.focusHandler = (): void => {
459      this.trace?.displayTip(systemTraceRow, EnergySystemStruct.hoverEnergySystemStruct, this.getSystemFocusHtml());
460    };
461    return systemTraceRow;
462  }
463
464  private getSystemFocusHtml(): string {
465    return `
466<div style="width: 250px">
467  <div style=" display: flex">
468    <div style="width: 75%;text-align: left">WORKSCHEDULER: </div>
469    <div style="width: 20%;text-align: left">${EnergySystemStruct.hoverEnergySystemStruct?.workScheduler! || 0}</div>
470  </div>
471  <div style="display: flex">
472    <div style="width: 75%;text-align: left">POWER_RUNNINGLOCK: </div>
473    <div style="width: 20%;text-align: left">${EnergySystemStruct.hoverEnergySystemStruct?.power! || 0}</div>
474  </div>
475  <div style="display: flex">
476    <div style="width: 75%;text-align: left">LOCATION: </div>
477    <div style="width: 20%;text-align: left">${EnergySystemStruct.hoverEnergySystemStruct?.location! || 0}</div>
478  </div>
479</div>`;
480  }
481
482  private getPowerFocusHtml(): string {
483    return `
484<div style="width: 120px">
485  <div style="display: flex">
486    <div style="width: 80%;text-align: left">CPU: </div>
487    <div style="width: 20%;text-align: left">${EnergyPowerStruct.hoverEnergyPowerStruct?.cpu! || 0}</div>
488  </div>
489  <div style="display: flex">
490    <div style="width: 80%;text-align: left">location: </div>
491    <div style="width: 20%;text-align: left">${EnergyPowerStruct.hoverEnergyPowerStruct?.location! || 0}</div>
492  </div>
493  <div style="display: flex">
494    <div style="width: 80%;text-align: left">GPU: </div>
495    <div style="width: 20%;text-align: left">${EnergyPowerStruct.hoverEnergyPowerStruct?.gpu! || 0}</div>
496  </div>
497  <div style="display: flex">
498    <div style="width: 80%;text-align: left">display: </div>
499    <div style="width: 20%;text-align: left">${EnergyPowerStruct.hoverEnergyPowerStruct?.display! || 0}</div>
500  </div>
501  <div style="display: flex">
502    <div style="width: 80%;text-align: left">camera: </div>
503    <div style="width: 20%;text-align: left">${EnergyPowerStruct.hoverEnergyPowerStruct?.camera! || 0}</div>
504  </div>
505  <div style="display: flex">
506    <div style="width: 80%;text-align: left">bluetooth: </div>
507    <div style="width: 20%;text-align: left">${EnergyPowerStruct.hoverEnergyPowerStruct?.bluetooth! || 0}</div>
508  </div>
509  <div style="display: flex">
510    <div style="width: 80%;text-align: left">flashlight: </div>
511    <div style="width: 20%;text-align: left">${EnergyPowerStruct.hoverEnergyPowerStruct?.flashlight! || 0}</div>
512  </div>
513  <div style="display: flex">
514    <div style="width: 80%;text-align: left">audio: </div>
515    <div style="width: 20%;text-align: left">${EnergyPowerStruct.hoverEnergyPowerStruct?.audio! || 0}</div>
516  </div>
517  <div style="display: flex">
518    <div style="width: 80%;text-align: left">wifiScan: </div>
519    <div style="width: 20%;text-align: left">${EnergyPowerStruct.hoverEnergyPowerStruct?.wifiscan! || 0}</div>
520  </div>
521</div>`;
522  }
523
524  private initPowerChartRow(): TraceRow<EnergyPowerStruct> {
525    let powerTraceRow = TraceRow.skeleton<EnergyPowerStruct>();
526    powerTraceRow.rowParentId = 'energy';
527    powerTraceRow.rowHidden = true;
528    powerTraceRow.rowId = 'energy-power';
529    powerTraceRow.rowType = TraceRow.ROW_TYPE_POWER_ENERGY;
530    powerTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler;
531    powerTraceRow.selectChangeHandler = this.trace.selectChangeHandler;
532    powerTraceRow.setAttribute('height', '200px');
533    let element = powerTraceRow.shadowRoot?.querySelector('.root') as HTMLDivElement;
534    element!.style.height = '200px';
535    powerTraceRow.style.width = '100%';
536    powerTraceRow.setAttribute('children', '');
537    powerTraceRow.name = 'Power';
538    powerTraceRow.focusHandler = (): void => {
539      this.trace?.displayTip(powerTraceRow, EnergyPowerStruct.hoverEnergyPowerStruct, this.getPowerFocusHtml());
540    };
541    return powerTraceRow;
542  }
543
544  private getPowerData(items: unknown): EnergyPowerStruct[] {
545    let powerDataMap: unknown = {};
546    let appNameList: string[] = []; //@ts-ignore
547    items.forEach(
548      (item: { id: number; startNS: number; eventName: string; appKey: string; eventValue: string }): void => {
549        //@ts-ignore
550        let dataItem = powerDataMap[item.startNS];
551        if (dataItem === undefined) {
552          if (item.appKey === 'APPNAME') {
553            let appMap: unknown = {};
554            let appNames = item.eventValue.split(',');
555            appNameList = appNames;
556            if (appNames.length > 0) {
557              for (let appNamesKey of appNames) {
558                //@ts-ignore
559                appMap[appNamesKey] = new EnergyPowerStruct(); //@ts-ignore
560                appMap[appNamesKey].name = appNamesKey; //@ts-ignore
561                appMap[appNamesKey].ts = item.startNS;
562              } //@ts-ignore
563              powerDataMap[item.startNS] = appMap;
564            }
565          }
566        } else {
567          if (item.appKey !== 'APPNAME') {
568            this.powerDataMap(item.eventName, item.eventValue, appNameList, dataItem);
569          } else {
570            //@ts-ignore
571            let dataMap = powerDataMap[item.startNS];
572            let appNames = item.eventValue.split(',');
573            appNameList = appNames;
574            if (appNames.length > 0) {
575              for (let appNamesKey of appNames) {
576                dataMap[appNamesKey] = new EnergyPowerStruct();
577                dataMap[appNamesKey].name = appNamesKey;
578                dataMap[appNamesKey].ts = item.startNS;
579              }
580            }
581          }
582        }
583      }
584    );
585    //@ts-ignore
586    return Object.values(powerDataMap);
587  }
588
589  private powerDataMap(name: string, eventValue: string, appNameList: string[], dataItem: unknown): void {
590    let values = eventValue.split(',');
591    for (let i = 0; i < values.length; i++) {
592      let appName = appNameList[i]; //@ts-ignore
593      let obj = dataItem[appName];
594      if (obj !== undefined) {
595        let eventName = name.split('_');
596        let s = eventName[eventName.length - 1].toLocaleLowerCase();
597        if (obj[s] === undefined) {
598          obj[s] = parseInt(values[i]);
599        } else {
600          obj[s] += parseInt(values[i]);
601        }
602      }
603    }
604  }
605
606  public static getBlueToothState(num: number | undefined): string {
607    switch (num) {
608      case 0:
609        return 'STATE_TURNING_ON';
610      case 1:
611        return 'STATE_TURN_ON';
612      case 2:
613        return 'STATE_TURNING_OFF';
614      case NUM_3:
615        return 'STATE_TURN_OFF';
616      default:
617        return 'UNKNOWN_STATE';
618    }
619  }
620}
621