1fb726d48Sopenharmony_ci/*
2fb726d48Sopenharmony_ci * Copyright (C) 2022 Huawei Device Co., Ltd.
3fb726d48Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4fb726d48Sopenharmony_ci * you may not use this file except in compliance with the License.
5fb726d48Sopenharmony_ci * You may obtain a copy of the License at
6fb726d48Sopenharmony_ci *
7fb726d48Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8fb726d48Sopenharmony_ci *
9fb726d48Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10fb726d48Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11fb726d48Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fb726d48Sopenharmony_ci * See the License for the specific language governing permissions and
13fb726d48Sopenharmony_ci * limitations under the License.
14fb726d48Sopenharmony_ci */
15fb726d48Sopenharmony_ci
16fb726d48Sopenharmony_ciimport { SpSystemTrace } from '../SpSystemTrace';
17fb726d48Sopenharmony_ciimport { TraceRow } from '../trace/base/TraceRow';
18fb726d48Sopenharmony_ciimport { renders } from '../../database/ui-worker/ProcedureWorker';
19fb726d48Sopenharmony_ciimport { info } from '../../../log/Log';
20fb726d48Sopenharmony_ciimport { XpowerRender, XpowerStruct } from '../../database/ui-worker/ProcedureWorkerXpower';
21fb726d48Sopenharmony_ciimport { ColorUtils } from '../trace/base/ColorUtils';
22fb726d48Sopenharmony_ciimport { EmptyRender } from '../../database/ui-worker/cpu/ProcedureWorkerCPU';
23fb726d48Sopenharmony_ciimport { xpowerDataSender } from '../../database/data-trafic/XpowerDataSender';
24fb726d48Sopenharmony_ciimport { queryXpowerData, queryXpowerMeasureData } from '../../database/sql/Xpower.sql';
25fb726d48Sopenharmony_ciimport { BaseStruct } from '../../bean/BaseStruct';
26fb726d48Sopenharmony_ci
27fb726d48Sopenharmony_ciexport class SpXpowerChart {
28fb726d48Sopenharmony_ci    private readonly trace: SpSystemTrace;
29fb726d48Sopenharmony_ci    private rowFolder!: TraceRow<BaseStruct>;
30fb726d48Sopenharmony_ci    private systemFolder!: TraceRow<BaseStruct>;
31fb726d48Sopenharmony_ci
32fb726d48Sopenharmony_ci    constructor(trace: SpSystemTrace) {
33fb726d48Sopenharmony_ci        this.trace = trace;
34fb726d48Sopenharmony_ci    }
35fb726d48Sopenharmony_ci
36fb726d48Sopenharmony_ci    async init(traceId?: string): Promise<void> {
37fb726d48Sopenharmony_ci        let XpowerMeasureData = await queryXpowerMeasureData(traceId);
38fb726d48Sopenharmony_ci        if (XpowerMeasureData.length <= 0) {
39fb726d48Sopenharmony_ci            return;
40fb726d48Sopenharmony_ci        }
41fb726d48Sopenharmony_ci        let xpowerList = await queryXpowerData(traceId);
42fb726d48Sopenharmony_ci        if (xpowerList.length <= 0) {
43fb726d48Sopenharmony_ci            return;
44fb726d48Sopenharmony_ci        }
45fb726d48Sopenharmony_ci        await this.initXpowerFolder(traceId);
46fb726d48Sopenharmony_ci        await this.initSystemFolder(traceId);
47fb726d48Sopenharmony_ci        await this.initSystemData(this.systemFolder, xpowerList, traceId);
48fb726d48Sopenharmony_ci    }
49fb726d48Sopenharmony_ci
50fb726d48Sopenharmony_ci    initXpowerFolder = async (traceId?: string): Promise<void> => {
51fb726d48Sopenharmony_ci        let xpowerFolder = TraceRow.skeleton(traceId);
52fb726d48Sopenharmony_ci        xpowerFolder.rowId = 'Xpowers';
53fb726d48Sopenharmony_ci        xpowerFolder.index = 0;
54fb726d48Sopenharmony_ci        xpowerFolder.rowType = TraceRow.ROW_TYPE_XPOWER;
55fb726d48Sopenharmony_ci        xpowerFolder.rowParentId = '';
56fb726d48Sopenharmony_ci        xpowerFolder.style.height = '40px';
57fb726d48Sopenharmony_ci        xpowerFolder.folder = true;
58fb726d48Sopenharmony_ci        xpowerFolder.name = 'Xpower';
59fb726d48Sopenharmony_ci        xpowerFolder.favoriteChangeHandler = this.trace.favoriteChangeHandler;
60fb726d48Sopenharmony_ci        xpowerFolder.selectChangeHandler = this.trace.selectChangeHandler;
61fb726d48Sopenharmony_ci        xpowerFolder.supplier = (): Promise<BaseStruct[]> => new Promise<Array<BaseStruct>>((resolve) => resolve([]));
62fb726d48Sopenharmony_ci        xpowerFolder.onThreadHandler = (useCache): void => {
63fb726d48Sopenharmony_ci            xpowerFolder.canvasSave(this.trace.canvasPanelCtx!);
64fb726d48Sopenharmony_ci            if (xpowerFolder.expansion) {
65fb726d48Sopenharmony_ci                this.trace.canvasPanelCtx?.clearRect(0, 0, xpowerFolder.frame.width, xpowerFolder.frame.height);
66fb726d48Sopenharmony_ci            } else {
67fb726d48Sopenharmony_ci                (renders.empty as EmptyRender).renderMainThread(
68fb726d48Sopenharmony_ci                    {
69fb726d48Sopenharmony_ci                        context: this.trace.canvasPanelCtx,
70fb726d48Sopenharmony_ci                        useCache: useCache,
71fb726d48Sopenharmony_ci                        type: '',
72fb726d48Sopenharmony_ci                    },
73fb726d48Sopenharmony_ci                    xpowerFolder
74fb726d48Sopenharmony_ci                );
75fb726d48Sopenharmony_ci            }
76fb726d48Sopenharmony_ci            xpowerFolder.canvasRestore(this.trace.canvasPanelCtx!, this.trace);
77fb726d48Sopenharmony_ci        };
78fb726d48Sopenharmony_ci        this.rowFolder = xpowerFolder;
79fb726d48Sopenharmony_ci        this.trace.rowsEL?.appendChild(xpowerFolder);
80fb726d48Sopenharmony_ci    }
81fb726d48Sopenharmony_ci
82fb726d48Sopenharmony_ci    initSystemFolder = async (traceId?: string): Promise<void> => {
83fb726d48Sopenharmony_ci        let systemFolder = TraceRow.skeleton(traceId);
84fb726d48Sopenharmony_ci        systemFolder.rowId = 'system';
85fb726d48Sopenharmony_ci        systemFolder.rowParentId = 'Xpowers';
86fb726d48Sopenharmony_ci        systemFolder.rowHidden = !this.rowFolder.expansion;
87fb726d48Sopenharmony_ci        systemFolder.rowType = TraceRow.ROW_TYPE_XPOWER_SYSTEM;
88fb726d48Sopenharmony_ci        systemFolder.folder = true;
89fb726d48Sopenharmony_ci        systemFolder.name = 'System';
90fb726d48Sopenharmony_ci        systemFolder.folderPaddingLeft = 20;
91fb726d48Sopenharmony_ci        systemFolder.style.height = '40px';
92fb726d48Sopenharmony_ci        systemFolder.favoriteChangeHandler = this.trace.favoriteChangeHandler;
93fb726d48Sopenharmony_ci        systemFolder.selectChangeHandler = this.trace.selectChangeHandler;
94fb726d48Sopenharmony_ci        systemFolder.supplier = (): Promise<BaseStruct[]> => new Promise<Array<BaseStruct>>((resolve) => resolve([]));
95fb726d48Sopenharmony_ci        systemFolder.onThreadHandler = (useCache): void => {
96fb726d48Sopenharmony_ci            systemFolder.canvasSave(this.trace.canvasPanelCtx!);
97fb726d48Sopenharmony_ci            if (systemFolder.expansion) {
98fb726d48Sopenharmony_ci                this.trace.canvasPanelCtx?.clearRect(0, 0, systemFolder.frame.width, systemFolder.frame.height);
99fb726d48Sopenharmony_ci            } else {
100fb726d48Sopenharmony_ci                (renders.empty as EmptyRender).renderMainThread(
101fb726d48Sopenharmony_ci                    {
102fb726d48Sopenharmony_ci                        context: this.trace.canvasPanelCtx,
103fb726d48Sopenharmony_ci                        useCache: useCache,
104fb726d48Sopenharmony_ci                        type: '',
105fb726d48Sopenharmony_ci                    },
106fb726d48Sopenharmony_ci                    systemFolder
107fb726d48Sopenharmony_ci                );
108fb726d48Sopenharmony_ci            }
109fb726d48Sopenharmony_ci            systemFolder.canvasRestore(this.trace.canvasPanelCtx!, this.trace);
110fb726d48Sopenharmony_ci        };
111fb726d48Sopenharmony_ci        this.systemFolder = systemFolder;
112fb726d48Sopenharmony_ci        this.rowFolder?.addChildTraceRow(systemFolder);
113fb726d48Sopenharmony_ci    }
114fb726d48Sopenharmony_ci
115fb726d48Sopenharmony_ci    private xpowerSupplierFrame(
116fb726d48Sopenharmony_ci        traceRow: TraceRow<XpowerStruct>,
117fb726d48Sopenharmony_ci        it: {
118fb726d48Sopenharmony_ci            name: string;
119fb726d48Sopenharmony_ci            num: number;
120fb726d48Sopenharmony_ci            maxValue?: number;
121fb726d48Sopenharmony_ci        },
122fb726d48Sopenharmony_ci    ): void {
123fb726d48Sopenharmony_ci        traceRow.supplierFrame = (): Promise<XpowerStruct[]> => {
124fb726d48Sopenharmony_ci            let promiseData = null;
125fb726d48Sopenharmony_ci            // @ts-ignore
126fb726d48Sopenharmony_ci            promiseData = xpowerDataSender(it.name, traceRow);
127fb726d48Sopenharmony_ci            if (promiseData === null) {
128fb726d48Sopenharmony_ci                // @ts-ignore
129fb726d48Sopenharmony_ci                return new Promise<Array<unknown>>((resolve) => resolve([]));
130fb726d48Sopenharmony_ci            } else {
131fb726d48Sopenharmony_ci                // @ts-ignore
132fb726d48Sopenharmony_ci                return promiseData.then((resultXpower: Array<unknown>) => {
133fb726d48Sopenharmony_ci                    for (let j = 0; j < resultXpower.length; j++) {
134fb726d48Sopenharmony_ci                        // @ts-ignore
135fb726d48Sopenharmony_ci                        if ((resultXpower[j].value || 0) > it.maxValue!) {
136fb726d48Sopenharmony_ci                            // @ts-ignore
137fb726d48Sopenharmony_ci                            it.maxValue = resultXpower[j].value || 0;
138fb726d48Sopenharmony_ci                        }
139fb726d48Sopenharmony_ci                        if (j > 0) {
140fb726d48Sopenharmony_ci                            // @ts-ignore
141fb726d48Sopenharmony_ci                            resultXpower[j].delta = (resultXpower[j].value || 0) - (resultXpower[j - 1].value || 0);
142fb726d48Sopenharmony_ci                        } else {
143fb726d48Sopenharmony_ci                            // @ts-ignore
144fb726d48Sopenharmony_ci                            resultXpower[j].delta = 0;
145fb726d48Sopenharmony_ci                        }
146fb726d48Sopenharmony_ci                    }
147fb726d48Sopenharmony_ci                    return resultXpower;
148fb726d48Sopenharmony_ci                });
149fb726d48Sopenharmony_ci            }
150fb726d48Sopenharmony_ci        };
151fb726d48Sopenharmony_ci    }
152fb726d48Sopenharmony_ci
153fb726d48Sopenharmony_ci    private xpowerThreadHandler(
154fb726d48Sopenharmony_ci        traceRow: TraceRow<XpowerStruct>,
155fb726d48Sopenharmony_ci        it: {
156fb726d48Sopenharmony_ci            name: string;
157fb726d48Sopenharmony_ci            num: number;
158fb726d48Sopenharmony_ci            maxValue?: number;
159fb726d48Sopenharmony_ci        },
160fb726d48Sopenharmony_ci        xpowerId: number
161fb726d48Sopenharmony_ci    ): void {
162fb726d48Sopenharmony_ci        traceRow.onThreadHandler = (useCache): void => {
163fb726d48Sopenharmony_ci            let context: CanvasRenderingContext2D;
164fb726d48Sopenharmony_ci            if (traceRow.currentContext) {
165fb726d48Sopenharmony_ci                context = traceRow.currentContext;
166fb726d48Sopenharmony_ci            } else {
167fb726d48Sopenharmony_ci                context = traceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!;
168fb726d48Sopenharmony_ci            }
169fb726d48Sopenharmony_ci            traceRow.canvasSave(context);
170fb726d48Sopenharmony_ci            (renders.xpower as XpowerRender).renderMainThread(
171fb726d48Sopenharmony_ci                {
172fb726d48Sopenharmony_ci                    context: context,
173fb726d48Sopenharmony_ci                    useCache: useCache,
174fb726d48Sopenharmony_ci                    type: it.name,
175fb726d48Sopenharmony_ci                    maxValue: it.maxValue === 0 ? 1 : it.maxValue!,
176fb726d48Sopenharmony_ci                    index: xpowerId,
177fb726d48Sopenharmony_ci                    maxName: it.maxValue!.toString()
178fb726d48Sopenharmony_ci                },
179fb726d48Sopenharmony_ci                traceRow
180fb726d48Sopenharmony_ci            );
181fb726d48Sopenharmony_ci            traceRow.canvasRestore(context, this.trace);
182fb726d48Sopenharmony_ci        };
183fb726d48Sopenharmony_ci    }
184fb726d48Sopenharmony_ci
185fb726d48Sopenharmony_ci    async initSystemData(folder: TraceRow<BaseStruct>, xpowerList: Array<{
186fb726d48Sopenharmony_ci        name: string;
187fb726d48Sopenharmony_ci        num: number;
188fb726d48Sopenharmony_ci        maxValue?: number;
189fb726d48Sopenharmony_ci    }>, traceId?: string): Promise<void> {
190fb726d48Sopenharmony_ci        info('xpowerList data size is: ', xpowerList!.length);
191fb726d48Sopenharmony_ci        XpowerStruct.maxValue = xpowerList.map((item) => item.num).reduce((a, b) => Math.max(a, b));
192fb726d48Sopenharmony_ci        for (let i = 0; i < xpowerList.length; i++) {
193fb726d48Sopenharmony_ci            const it = xpowerList[i];
194fb726d48Sopenharmony_ci            it.maxValue = 0;
195fb726d48Sopenharmony_ci            let traceRow = TraceRow.skeleton<XpowerStruct>(traceId);
196fb726d48Sopenharmony_ci            traceRow.rowId = it.name;
197fb726d48Sopenharmony_ci            traceRow.rowType = TraceRow.ROW_TYPE_XPOWER_SYSTEM;
198fb726d48Sopenharmony_ci            traceRow.rowParentId = folder.rowId;
199fb726d48Sopenharmony_ci            traceRow.style.height = '40px';
200fb726d48Sopenharmony_ci            traceRow.name = it.name;
201fb726d48Sopenharmony_ci            traceRow.rowHidden = !folder.expansion;
202fb726d48Sopenharmony_ci            traceRow.folderTextLeft = 40;
203fb726d48Sopenharmony_ci            traceRow.xpowerRowTitle = this.convertTitle(it.name);
204fb726d48Sopenharmony_ci            traceRow.setAttribute('children', '');
205fb726d48Sopenharmony_ci            traceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler;
206fb726d48Sopenharmony_ci            traceRow.selectChangeHandler = this.trace.selectChangeHandler;
207fb726d48Sopenharmony_ci            this.xpowerSupplierFrame(traceRow, it);
208fb726d48Sopenharmony_ci            traceRow.getCacheData = (args: unknown): Promise<XpowerStruct[]> | undefined => {
209fb726d48Sopenharmony_ci                let result: Promise<XpowerStruct[]> | undefined;
210fb726d48Sopenharmony_ci                result = xpowerDataSender(it.name, traceRow, args);
211fb726d48Sopenharmony_ci                return result;
212fb726d48Sopenharmony_ci            };
213fb726d48Sopenharmony_ci            traceRow.focusHandler = (ev): void => {
214fb726d48Sopenharmony_ci                this.trace?.displayTip(
215fb726d48Sopenharmony_ci                    traceRow,
216fb726d48Sopenharmony_ci                    XpowerStruct.hoverXpowerStruct,
217fb726d48Sopenharmony_ci                    `<span>${it.name === 'ThermalReport.ShellTemp' ? XpowerStruct.hoverXpowerStruct?.value! :
218fb726d48Sopenharmony_ci                        ColorUtils.formatNumberComma(XpowerStruct.hoverXpowerStruct?.value!)}</span>`
219fb726d48Sopenharmony_ci                );
220fb726d48Sopenharmony_ci            };
221fb726d48Sopenharmony_ci            traceRow.findHoverStruct = (): void => {
222fb726d48Sopenharmony_ci                XpowerStruct.hoverXpowerStruct = traceRow.getHoverStruct();
223fb726d48Sopenharmony_ci            };
224fb726d48Sopenharmony_ci            this.xpowerThreadHandler(traceRow, it, i);
225fb726d48Sopenharmony_ci            folder.addChildTraceRow(traceRow);
226fb726d48Sopenharmony_ci        }
227fb726d48Sopenharmony_ci    }
228fb726d48Sopenharmony_ci
229fb726d48Sopenharmony_ci    convertTitle(title: string): string {
230fb726d48Sopenharmony_ci        switch (title) {
231fb726d48Sopenharmony_ci            case 'Battery.Capacity':
232fb726d48Sopenharmony_ci                return '电池容量(单位mAh)';
233fb726d48Sopenharmony_ci            case 'Battery.Charge':
234fb726d48Sopenharmony_ci                return '充电状态(充电1,非充电0)';
235fb726d48Sopenharmony_ci            case 'Battery.GasGauge':
236fb726d48Sopenharmony_ci                return '电池剩余电量(单位mAh)';
237fb726d48Sopenharmony_ci            case 'Battery.Level':
238fb726d48Sopenharmony_ci                return '电池百分比';
239fb726d48Sopenharmony_ci            case 'Battery.RealCurrent':
240fb726d48Sopenharmony_ci                return '实时电流(单位mAh,充电时为正数,耗电时为负数)';
241fb726d48Sopenharmony_ci            case 'Battery.Screen':
242fb726d48Sopenharmony_ci                return '屏幕状态(亮屏1,灭屏0)';
243fb726d48Sopenharmony_ci            case 'ThermalReport.ShellTemp':
244fb726d48Sopenharmony_ci                return '外壳温度(单位℃)';
245fb726d48Sopenharmony_ci            case 'ThermalReport.ThermalLevel':
246fb726d48Sopenharmony_ci                return '温度等级';
247fb726d48Sopenharmony_ci            default:
248fb726d48Sopenharmony_ci                return title;
249fb726d48Sopenharmony_ci        }
250fb726d48Sopenharmony_ci    }
251fb726d48Sopenharmony_ci
252fb726d48Sopenharmony_ci}
253