• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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    if (appNameFromTable.length > 0 && SpHiSysEnergyChart.app_name === '') {
388      SpHiSysEnergyChart.app_name = appNameFromTable[0].string_value;
389    }
390    this.energyTraceRow = TraceRow.skeleton<BaseStruct>();
391    this.energyTraceRow.addRowSettingPop();
392    this.energyTraceRow.rowSetting = 'enable';
393    this.energyTraceRow.rowSettingPopoverDirection = 'bottomLeft';
394    let nameList: Array<TreeItemData> = [];
395    for (let index = 0; index < appNameFromTable.length; index++) {
396      let appName = appNameFromTable[index].string_value;
397      nameList.push({
398        key: `${appName}`,
399        title: `${appName}`,
400        checked: index === 0,
401      });
402    }
403    this.energyTraceRow.rowSettingList = nameList;
404    this.energyTraceRow.onRowSettingChangeHandler = (value): void => {
405      SpHiSysEnergyChart.app_name = value[0];
406      this.trace.refreshCanvas(false);
407    };
408    this.energyTraceRow.rowId = 'energy';
409    this.energyTraceRow.rowType = TraceRow.ROW_TYPE_ENERGY;
410    this.energyTraceRow.rowParentId = '';
411    this.energyTraceRow.folder = true;
412    this.energyTraceRow.addTemplateTypes('EnergyEvent');
413    this.energyTraceRow.name = 'Energy';
414    this.energyTraceRow.style.height = '40px';
415  }
416
417  private initAnomalyChartRow(): TraceRow<EnergyAnomalyStruct> {
418    let anomalyTraceRow = TraceRow.skeleton<EnergyAnomalyStruct>();
419    anomalyTraceRow.rowParentId = 'energy';
420    anomalyTraceRow.rowHidden = true;
421    anomalyTraceRow.rowId = 'energy-anomaly';
422    anomalyTraceRow.rowType = TraceRow.ROW_TYPE_ANOMALY_ENERGY;
423    anomalyTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler;
424    anomalyTraceRow.selectChangeHandler = this.trace.selectChangeHandler;
425    anomalyTraceRow.setAttribute('height', '55px');
426    let element = anomalyTraceRow.shadowRoot?.querySelector('.root') as HTMLDivElement;
427    element!.style.height = '55px';
428    anomalyTraceRow.style.width = '100%';
429    anomalyTraceRow.setAttribute('children', '');
430    anomalyTraceRow.name = 'Anomaly Event';
431    anomalyTraceRow.focusHandler = (): void => {
432      this.trace?.displayTip(
433        anomalyTraceRow,
434        EnergyAnomalyStruct.hoverEnergyAnomalyStruct,
435        `<span>AnomalyName:${EnergyAnomalyStruct.hoverEnergyAnomalyStruct?.eventName || ''}</span>`
436      );
437    };
438    return anomalyTraceRow;
439  }
440
441  private initSystemChartRow(): TraceRow<EnergySystemStruct> {
442    let systemTraceRow = TraceRow.skeleton<EnergySystemStruct>();
443    systemTraceRow.rowParentId = 'energy';
444    systemTraceRow.rowHidden = true;
445    systemTraceRow.rowId = 'energy-system';
446    systemTraceRow.rowType = TraceRow.ROW_TYPE_SYSTEM_ENERGY;
447    systemTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler;
448    systemTraceRow.selectChangeHandler = this.trace.selectChangeHandler;
449    systemTraceRow.setAttribute('height', '80px');
450    let element = systemTraceRow.shadowRoot?.querySelector('.root') as HTMLDivElement;
451    element!.style.height = '90px';
452    systemTraceRow.style.width = '100%';
453    systemTraceRow.setAttribute('children', '');
454    systemTraceRow.name = 'System Event';
455    systemTraceRow.focusHandler = (): void => {
456      this.trace?.displayTip(systemTraceRow, EnergySystemStruct.hoverEnergySystemStruct, this.getSystemFocusHtml());
457    };
458    return systemTraceRow;
459  }
460
461  private getSystemFocusHtml(): string {
462    return `
463<div style="width: 250px">
464  <div style=" display: flex">
465    <div style="width: 75%;text-align: left">WORKSCHEDULER: </div>
466    <div style="width: 20%;text-align: left">${EnergySystemStruct.hoverEnergySystemStruct?.workScheduler! || 0}</div>
467  </div>
468  <div style="display: flex">
469    <div style="width: 75%;text-align: left">POWER_RUNNINGLOCK: </div>
470    <div style="width: 20%;text-align: left">${EnergySystemStruct.hoverEnergySystemStruct?.power! || 0}</div>
471  </div>
472  <div style="display: flex">
473    <div style="width: 75%;text-align: left">LOCATION: </div>
474    <div style="width: 20%;text-align: left">${EnergySystemStruct.hoverEnergySystemStruct?.location! || 0}</div>
475  </div>
476</div>`;
477  }
478
479  private getPowerFocusHtml(): string {
480    return `
481<div style="width: 120px">
482  <div style="display: flex">
483    <div style="width: 80%;text-align: left">CPU: </div>
484    <div style="width: 20%;text-align: left">${EnergyPowerStruct.hoverEnergyPowerStruct?.cpu! || 0}</div>
485  </div>
486  <div style="display: flex">
487    <div style="width: 80%;text-align: left">location: </div>
488    <div style="width: 20%;text-align: left">${EnergyPowerStruct.hoverEnergyPowerStruct?.location! || 0}</div>
489  </div>
490  <div style="display: flex">
491    <div style="width: 80%;text-align: left">GPU: </div>
492    <div style="width: 20%;text-align: left">${EnergyPowerStruct.hoverEnergyPowerStruct?.gpu! || 0}</div>
493  </div>
494  <div style="display: flex">
495    <div style="width: 80%;text-align: left">display: </div>
496    <div style="width: 20%;text-align: left">${EnergyPowerStruct.hoverEnergyPowerStruct?.display! || 0}</div>
497  </div>
498  <div style="display: flex">
499    <div style="width: 80%;text-align: left">camera: </div>
500    <div style="width: 20%;text-align: left">${EnergyPowerStruct.hoverEnergyPowerStruct?.camera! || 0}</div>
501  </div>
502  <div style="display: flex">
503    <div style="width: 80%;text-align: left">bluetooth: </div>
504    <div style="width: 20%;text-align: left">${EnergyPowerStruct.hoverEnergyPowerStruct?.bluetooth! || 0}</div>
505  </div>
506  <div style="display: flex">
507    <div style="width: 80%;text-align: left">flashlight: </div>
508    <div style="width: 20%;text-align: left">${EnergyPowerStruct.hoverEnergyPowerStruct?.flashlight! || 0}</div>
509  </div>
510  <div style="display: flex">
511    <div style="width: 80%;text-align: left">audio: </div>
512    <div style="width: 20%;text-align: left">${EnergyPowerStruct.hoverEnergyPowerStruct?.audio! || 0}</div>
513  </div>
514  <div style="display: flex">
515    <div style="width: 80%;text-align: left">wifiScan: </div>
516    <div style="width: 20%;text-align: left">${EnergyPowerStruct.hoverEnergyPowerStruct?.wifiscan! || 0}</div>
517  </div>
518</div>`;
519  }
520
521  private initPowerChartRow(): TraceRow<EnergyPowerStruct> {
522    let powerTraceRow = TraceRow.skeleton<EnergyPowerStruct>();
523    powerTraceRow.rowParentId = 'energy';
524    powerTraceRow.rowHidden = true;
525    powerTraceRow.rowId = 'energy-power';
526    powerTraceRow.rowType = TraceRow.ROW_TYPE_POWER_ENERGY;
527    powerTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler;
528    powerTraceRow.selectChangeHandler = this.trace.selectChangeHandler;
529    powerTraceRow.setAttribute('height', '200px');
530    let element = powerTraceRow.shadowRoot?.querySelector('.root') as HTMLDivElement;
531    element!.style.height = '200px';
532    powerTraceRow.style.width = '100%';
533    powerTraceRow.setAttribute('children', '');
534    powerTraceRow.name = 'Power';
535    powerTraceRow.focusHandler = (): void => {
536      this.trace?.displayTip(powerTraceRow, EnergyPowerStruct.hoverEnergyPowerStruct, this.getPowerFocusHtml());
537    };
538    return powerTraceRow;
539  }
540
541  private getPowerData(items: unknown): EnergyPowerStruct[] {
542    let powerDataMap: unknown = {};
543    let appNameList: string[] = []; //@ts-ignore
544    items.forEach(
545      (item: { id: number; startNS: number; eventName: string; appKey: string; eventValue: string }): void => {
546        //@ts-ignore
547        let dataItem = powerDataMap[item.startNS];
548        if (dataItem === undefined) {
549          if (item.appKey === 'APPNAME') {
550            let appMap: unknown = {};
551            let appNames = item.eventValue.split(',');
552            appNameList = appNames;
553            if (appNames.length > 0) {
554              for (let appNamesKey of appNames) {
555                //@ts-ignore
556                appMap[appNamesKey] = new EnergyPowerStruct(); //@ts-ignore
557                appMap[appNamesKey].name = appNamesKey; //@ts-ignore
558                appMap[appNamesKey].ts = item.startNS;
559              } //@ts-ignore
560              powerDataMap[item.startNS] = appMap;
561            }
562          }
563        } else {
564          if (item.appKey !== 'APPNAME') {
565            this.powerDataMap(item.eventName, item.eventValue, appNameList, dataItem);
566          } else {
567            //@ts-ignore
568            let dataMap = powerDataMap[item.startNS];
569            let appNames = item.eventValue.split(',');
570            appNameList = appNames;
571            if (appNames.length > 0) {
572              for (let appNamesKey of appNames) {
573                dataMap[appNamesKey] = new EnergyPowerStruct();
574                dataMap[appNamesKey].name = appNamesKey;
575                dataMap[appNamesKey].ts = item.startNS;
576              }
577            }
578          }
579        }
580      }
581    );
582    //@ts-ignore
583    return Object.values(powerDataMap);
584  }
585
586  private powerDataMap(name: string, eventValue: string, appNameList: string[], dataItem: unknown): void {
587    let values = eventValue.split(',');
588    for (let i = 0; i < values.length; i++) {
589      let appName = appNameList[i]; //@ts-ignore
590      let obj = dataItem[appName];
591      if (obj !== undefined) {
592        let eventName = name.split('_');
593        let s = eventName[eventName.length - 1].toLocaleLowerCase();
594        if (obj[s] === undefined) {
595          obj[s] = parseInt(values[i]);
596        } else {
597          obj[s] += parseInt(values[i]);
598        }
599      }
600    }
601  }
602
603  public static getBlueToothState(num: number | undefined): string {
604    switch (num) {
605      case 0:
606        return 'STATE_TURNING_ON';
607      case 1:
608        return 'STATE_TURN_ON';
609      case 2:
610        return 'STATE_TURNING_OFF';
611      case NUM_3:
612        return 'STATE_TURN_OFF';
613      default:
614        return 'UNKNOWN_STATE';
615    }
616  }
617}
618