myio-js-library 0.1.549 → 0.1.550
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +43 -15
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +43 -15
- package/dist/myio-js-library.umd.js +43 -15
- package/dist/myio-js-library.umd.min.js +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -899,7 +899,7 @@ module.exports = __toCommonJS(src_exports);
|
|
|
899
899
|
// package.json
|
|
900
900
|
var package_default = {
|
|
901
901
|
name: "myio-js-library",
|
|
902
|
-
version: "0.1.
|
|
902
|
+
version: "0.1.550",
|
|
903
903
|
description: "A clean, standalone JS SDK for MYIO projects",
|
|
904
904
|
license: "MIT",
|
|
905
905
|
repository: "github:gh-myio/myio-js-library",
|
|
@@ -35502,7 +35502,8 @@ var DeviceReportModal = class {
|
|
|
35502
35502
|
baseUrl: this.params.api.dataApiBaseUrl || "https://api.data.apps.myio-bas.com",
|
|
35503
35503
|
ingestionId: this.params.ingestionId,
|
|
35504
35504
|
startISO,
|
|
35505
|
-
endISO
|
|
35505
|
+
endISO,
|
|
35506
|
+
granularity: this.granularity
|
|
35506
35507
|
});
|
|
35507
35508
|
this.data = this.processApiResponse(apiResponse, dateRange);
|
|
35508
35509
|
this.renderSummary();
|
|
@@ -35532,10 +35533,25 @@ var DeviceReportModal = class {
|
|
|
35532
35533
|
if (!Array.isArray(dataArray) || dataArray.length === 0) {
|
|
35533
35534
|
console.warn("[DeviceReportModal] API returned empty or invalid response, zero-filling date range");
|
|
35534
35535
|
if (isHourly) return [];
|
|
35535
|
-
|
|
35536
|
+
const noData = this.domainConfig.summaryType === "average";
|
|
35537
|
+
return dateRange.map((date) => ({ date, consumption: 0, ...noData ? { noData: true } : {} }));
|
|
35536
35538
|
}
|
|
35537
35539
|
const deviceData = dataArray[0];
|
|
35538
35540
|
const consumption = deviceData.consumption || [];
|
|
35541
|
+
if (!isHourly && this.domainConfig.summaryType === "average") {
|
|
35542
|
+
const acc = {};
|
|
35543
|
+
consumption.forEach((item) => {
|
|
35544
|
+
if (item.timestamp && item.value != null && Number.isFinite(Number(item.value))) {
|
|
35545
|
+
const date = String(item.timestamp).slice(0, 10);
|
|
35546
|
+
const a = acc[date] || (acc[date] = { sum: 0, n: 0 });
|
|
35547
|
+
a.sum += Number(item.value);
|
|
35548
|
+
a.n += 1;
|
|
35549
|
+
}
|
|
35550
|
+
});
|
|
35551
|
+
return dateRange.map(
|
|
35552
|
+
(date) => acc[date] ? { date, consumption: acc[date].sum / acc[date].n } : { date, consumption: 0, noData: true }
|
|
35553
|
+
);
|
|
35554
|
+
}
|
|
35539
35555
|
if (isHourly) {
|
|
35540
35556
|
return consumption.filter((item) => item.timestamp && item.value != null).map((item) => ({
|
|
35541
35557
|
date: item.timestamp,
|
|
@@ -35597,14 +35613,15 @@ var DeviceReportModal = class {
|
|
|
35597
35613
|
const isHourly = this.granularity === "1h";
|
|
35598
35614
|
const isTemperature = this.domainConfig.summaryType === "average";
|
|
35599
35615
|
const total = this.calculateTotal();
|
|
35600
|
-
const
|
|
35601
|
-
const
|
|
35616
|
+
const rows = this.validRows;
|
|
35617
|
+
const summaryValue = isTemperature ? rows.length > 0 ? total / rows.length : 0 : total;
|
|
35618
|
+
const dayKeys = new Set(rows.map((r) => r.date.slice(0, 10)));
|
|
35602
35619
|
const dayCount = Math.max(1, dayKeys.size);
|
|
35603
|
-
const maxRow =
|
|
35620
|
+
const maxRow = rows.reduce(
|
|
35604
35621
|
(best, r) => !best || r.consumption > best.consumption ? r : best,
|
|
35605
35622
|
null
|
|
35606
35623
|
);
|
|
35607
|
-
const minPool = isTemperature ?
|
|
35624
|
+
const minPool = isTemperature ? rows : rows.filter((r) => r.consumption > 0);
|
|
35608
35625
|
const minRow = minPool.reduce(
|
|
35609
35626
|
(best, r) => !best || r.consumption < best.consumption ? r : best,
|
|
35610
35627
|
null
|
|
@@ -35616,7 +35633,7 @@ var DeviceReportModal = class {
|
|
|
35616
35633
|
{ value: fmt2(total / dayCount), label: `M\xE9dia por Dia (${unit})` }
|
|
35617
35634
|
];
|
|
35618
35635
|
if (isHourly) {
|
|
35619
|
-
kpis.push({ value: fmt2(total /
|
|
35636
|
+
kpis.push({ value: fmt2(rows.length ? total / rows.length : 0), label: `M\xE9dia por Hora (${unit})` });
|
|
35620
35637
|
}
|
|
35621
35638
|
kpis.push(
|
|
35622
35639
|
{
|
|
@@ -35632,6 +35649,9 @@ var DeviceReportModal = class {
|
|
|
35632
35649
|
);
|
|
35633
35650
|
if (!isTemperature) {
|
|
35634
35651
|
kpis.push({ value: String(zeroCount), label: isHourly ? "Horas sem Consumo" : "Dias sem Consumo" });
|
|
35652
|
+
} else {
|
|
35653
|
+
const noData = this.data.length - rows.length;
|
|
35654
|
+
if (noData > 0) kpis.push({ value: String(noData), label: isHourly ? "Horas sem Leitura" : "Dias sem Leitura" });
|
|
35635
35655
|
}
|
|
35636
35656
|
return kpis;
|
|
35637
35657
|
}
|
|
@@ -35717,7 +35737,7 @@ var DeviceReportModal = class {
|
|
|
35717
35737
|
${this.data.map((row) => `
|
|
35718
35738
|
<tr>
|
|
35719
35739
|
<td>${this.formatDate(row.date)}</td>
|
|
35720
|
-
<td style="text-align: right;">${this.domainConfig.formatter(row.consumption)}</td>
|
|
35740
|
+
<td style="text-align: right;${row.noData ? " color: var(--myio-text-muted);" : ""}">${row.noData ? "Sem leitura" : this.domainConfig.formatter(row.consumption)}</td>
|
|
35721
35741
|
</tr>
|
|
35722
35742
|
`).join("")}
|
|
35723
35743
|
</tbody>
|
|
@@ -35748,13 +35768,18 @@ var DeviceReportModal = class {
|
|
|
35748
35768
|
if (key === "date") {
|
|
35749
35769
|
comparison = new Date(a.date).getTime() - new Date(b.date).getTime();
|
|
35750
35770
|
} else {
|
|
35771
|
+
if (!!a.noData !== !!b.noData) return a.noData ? 1 : -1;
|
|
35751
35772
|
comparison = a.consumption - b.consumption;
|
|
35752
35773
|
}
|
|
35753
35774
|
return this.sortState.direction === "desc" ? -comparison : comparison;
|
|
35754
35775
|
});
|
|
35755
35776
|
}
|
|
35777
|
+
// Linhas com leitura (temperatura: dia sem leitura fica fora de totais/médias/KPIs)
|
|
35778
|
+
get validRows() {
|
|
35779
|
+
return this.data.filter((r) => !r.noData);
|
|
35780
|
+
}
|
|
35756
35781
|
calculateTotal() {
|
|
35757
|
-
return this.
|
|
35782
|
+
return this.validRows.reduce((sum2, row) => sum2 + row.consumption, 0);
|
|
35758
35783
|
}
|
|
35759
35784
|
formatDate(dateStr) {
|
|
35760
35785
|
if (!dateStr) return "";
|
|
@@ -35767,7 +35792,8 @@ var DeviceReportModal = class {
|
|
|
35767
35792
|
}
|
|
35768
35793
|
exportCSV() {
|
|
35769
35794
|
const total = this.calculateTotal();
|
|
35770
|
-
const
|
|
35795
|
+
const valid = this.validRows.length;
|
|
35796
|
+
const summaryValue = this.domainConfig.summaryType === "average" ? valid > 0 ? total / valid : 0 : total;
|
|
35771
35797
|
const now = /* @__PURE__ */ new Date();
|
|
35772
35798
|
const timestamp = now.toLocaleDateString("pt-BR") + " - " + now.toLocaleTimeString("pt-BR", { hour: "2-digit", minute: "2-digit" });
|
|
35773
35799
|
const csvData = [
|
|
@@ -35775,7 +35801,7 @@ var DeviceReportModal = class {
|
|
|
35775
35801
|
["DATA EMISS\xC3O", timestamp, ""],
|
|
35776
35802
|
[this.domainConfig.summaryLabel, this.domainConfig.formatter(summaryValue), this.domainConfig.unit],
|
|
35777
35803
|
[this.granularity === "1h" ? "Data/Hora" : "Data", this.domainConfig.label, ""],
|
|
35778
|
-
...this.data.map((row) => [this.formatDate(row.date), this.domainConfig.formatter(row.consumption)])
|
|
35804
|
+
...this.data.map((row) => [this.formatDate(row.date), row.noData ? "Sem leitura" : this.domainConfig.formatter(row.consumption)])
|
|
35779
35805
|
];
|
|
35780
35806
|
const csvContent = toCsv(csvData);
|
|
35781
35807
|
const granSuffix = this.granularity === "1h" ? "-1h" : "";
|
|
@@ -35806,7 +35832,7 @@ var DeviceReportModal = class {
|
|
|
35806
35832
|
return this.data.map((row) => ({
|
|
35807
35833
|
labelOrName: this.formatDate(row.date),
|
|
35808
35834
|
name: this.formatDate(row.date),
|
|
35809
|
-
val: row.consumption,
|
|
35835
|
+
val: row.noData ? null : row.consumption,
|
|
35810
35836
|
...isTemperature || total <= 0 ? {} : { perc: row.consumption / total * 100 }
|
|
35811
35837
|
}));
|
|
35812
35838
|
}
|
|
@@ -39003,10 +39029,12 @@ var AllReportModal = class {
|
|
|
39003
39029
|
// em total_value (in-place). Sensores sem série ficam com o 0 original.
|
|
39004
39030
|
async enrichTemperatureAverages(data, startISO, endISO, token, baseUrl) {
|
|
39005
39031
|
const rows = Array.isArray(data?.data) ? data.data : [];
|
|
39006
|
-
let tempRows
|
|
39032
|
+
let tempRows;
|
|
39007
39033
|
if (this.params.itemsList) {
|
|
39008
39034
|
const ids = new Set(this.params.itemsList.map((i) => String(i.id)));
|
|
39009
|
-
tempRows =
|
|
39035
|
+
tempRows = rows.filter((d) => ids.has(String(d?.id)));
|
|
39036
|
+
} else {
|
|
39037
|
+
tempRows = rows.filter((d) => String(d?.deviceType || "").toLowerCase() === "temperature");
|
|
39010
39038
|
}
|
|
39011
39039
|
if (!tempRows.length) return;
|
|
39012
39040
|
const startTime = encodeURIComponent(startISO);
|
package/dist/index.d.cts
CHANGED
|
@@ -5639,6 +5639,8 @@ type EnergyFetcher = (args: {
|
|
|
5639
5639
|
ingestionId: string;
|
|
5640
5640
|
startISO: string;
|
|
5641
5641
|
endISO: string;
|
|
5642
|
+
/** Granularidade selecionada na modal (fetchers customizados podem honrar 1h/1d). */
|
|
5643
|
+
granularity?: '1d' | '1h';
|
|
5642
5644
|
}) => Promise<any>;
|
|
5643
5645
|
interface OpenDeviceReportParams {
|
|
5644
5646
|
ingestionId: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -5639,6 +5639,8 @@ type EnergyFetcher = (args: {
|
|
|
5639
5639
|
ingestionId: string;
|
|
5640
5640
|
startISO: string;
|
|
5641
5641
|
endISO: string;
|
|
5642
|
+
/** Granularidade selecionada na modal (fetchers customizados podem honrar 1h/1d). */
|
|
5643
|
+
granularity?: '1d' | '1h';
|
|
5642
5644
|
}) => Promise<any>;
|
|
5643
5645
|
interface OpenDeviceReportParams {
|
|
5644
5646
|
ingestionId: string;
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
// package.json
|
|
11
11
|
var package_default = {
|
|
12
12
|
name: "myio-js-library",
|
|
13
|
-
version: "0.1.
|
|
13
|
+
version: "0.1.550",
|
|
14
14
|
description: "A clean, standalone JS SDK for MYIO projects",
|
|
15
15
|
license: "MIT",
|
|
16
16
|
repository: "github:gh-myio/myio-js-library",
|
|
@@ -33888,7 +33888,8 @@ var DeviceReportModal = class {
|
|
|
33888
33888
|
baseUrl: this.params.api.dataApiBaseUrl || "https://api.data.apps.myio-bas.com",
|
|
33889
33889
|
ingestionId: this.params.ingestionId,
|
|
33890
33890
|
startISO,
|
|
33891
|
-
endISO
|
|
33891
|
+
endISO,
|
|
33892
|
+
granularity: this.granularity
|
|
33892
33893
|
});
|
|
33893
33894
|
this.data = this.processApiResponse(apiResponse, dateRange);
|
|
33894
33895
|
this.renderSummary();
|
|
@@ -33918,10 +33919,25 @@ var DeviceReportModal = class {
|
|
|
33918
33919
|
if (!Array.isArray(dataArray) || dataArray.length === 0) {
|
|
33919
33920
|
console.warn("[DeviceReportModal] API returned empty or invalid response, zero-filling date range");
|
|
33920
33921
|
if (isHourly) return [];
|
|
33921
|
-
|
|
33922
|
+
const noData = this.domainConfig.summaryType === "average";
|
|
33923
|
+
return dateRange.map((date) => ({ date, consumption: 0, ...noData ? { noData: true } : {} }));
|
|
33922
33924
|
}
|
|
33923
33925
|
const deviceData = dataArray[0];
|
|
33924
33926
|
const consumption = deviceData.consumption || [];
|
|
33927
|
+
if (!isHourly && this.domainConfig.summaryType === "average") {
|
|
33928
|
+
const acc = {};
|
|
33929
|
+
consumption.forEach((item) => {
|
|
33930
|
+
if (item.timestamp && item.value != null && Number.isFinite(Number(item.value))) {
|
|
33931
|
+
const date = String(item.timestamp).slice(0, 10);
|
|
33932
|
+
const a = acc[date] || (acc[date] = { sum: 0, n: 0 });
|
|
33933
|
+
a.sum += Number(item.value);
|
|
33934
|
+
a.n += 1;
|
|
33935
|
+
}
|
|
33936
|
+
});
|
|
33937
|
+
return dateRange.map(
|
|
33938
|
+
(date) => acc[date] ? { date, consumption: acc[date].sum / acc[date].n } : { date, consumption: 0, noData: true }
|
|
33939
|
+
);
|
|
33940
|
+
}
|
|
33925
33941
|
if (isHourly) {
|
|
33926
33942
|
return consumption.filter((item) => item.timestamp && item.value != null).map((item) => ({
|
|
33927
33943
|
date: item.timestamp,
|
|
@@ -33983,14 +33999,15 @@ var DeviceReportModal = class {
|
|
|
33983
33999
|
const isHourly = this.granularity === "1h";
|
|
33984
34000
|
const isTemperature = this.domainConfig.summaryType === "average";
|
|
33985
34001
|
const total = this.calculateTotal();
|
|
33986
|
-
const
|
|
33987
|
-
const
|
|
34002
|
+
const rows = this.validRows;
|
|
34003
|
+
const summaryValue = isTemperature ? rows.length > 0 ? total / rows.length : 0 : total;
|
|
34004
|
+
const dayKeys = new Set(rows.map((r) => r.date.slice(0, 10)));
|
|
33988
34005
|
const dayCount = Math.max(1, dayKeys.size);
|
|
33989
|
-
const maxRow =
|
|
34006
|
+
const maxRow = rows.reduce(
|
|
33990
34007
|
(best, r) => !best || r.consumption > best.consumption ? r : best,
|
|
33991
34008
|
null
|
|
33992
34009
|
);
|
|
33993
|
-
const minPool = isTemperature ?
|
|
34010
|
+
const minPool = isTemperature ? rows : rows.filter((r) => r.consumption > 0);
|
|
33994
34011
|
const minRow = minPool.reduce(
|
|
33995
34012
|
(best, r) => !best || r.consumption < best.consumption ? r : best,
|
|
33996
34013
|
null
|
|
@@ -34002,7 +34019,7 @@ var DeviceReportModal = class {
|
|
|
34002
34019
|
{ value: fmt2(total / dayCount), label: `M\xE9dia por Dia (${unit})` }
|
|
34003
34020
|
];
|
|
34004
34021
|
if (isHourly) {
|
|
34005
|
-
kpis.push({ value: fmt2(total /
|
|
34022
|
+
kpis.push({ value: fmt2(rows.length ? total / rows.length : 0), label: `M\xE9dia por Hora (${unit})` });
|
|
34006
34023
|
}
|
|
34007
34024
|
kpis.push(
|
|
34008
34025
|
{
|
|
@@ -34018,6 +34035,9 @@ var DeviceReportModal = class {
|
|
|
34018
34035
|
);
|
|
34019
34036
|
if (!isTemperature) {
|
|
34020
34037
|
kpis.push({ value: String(zeroCount), label: isHourly ? "Horas sem Consumo" : "Dias sem Consumo" });
|
|
34038
|
+
} else {
|
|
34039
|
+
const noData = this.data.length - rows.length;
|
|
34040
|
+
if (noData > 0) kpis.push({ value: String(noData), label: isHourly ? "Horas sem Leitura" : "Dias sem Leitura" });
|
|
34021
34041
|
}
|
|
34022
34042
|
return kpis;
|
|
34023
34043
|
}
|
|
@@ -34103,7 +34123,7 @@ var DeviceReportModal = class {
|
|
|
34103
34123
|
${this.data.map((row) => `
|
|
34104
34124
|
<tr>
|
|
34105
34125
|
<td>${this.formatDate(row.date)}</td>
|
|
34106
|
-
<td style="text-align: right;">${this.domainConfig.formatter(row.consumption)}</td>
|
|
34126
|
+
<td style="text-align: right;${row.noData ? " color: var(--myio-text-muted);" : ""}">${row.noData ? "Sem leitura" : this.domainConfig.formatter(row.consumption)}</td>
|
|
34107
34127
|
</tr>
|
|
34108
34128
|
`).join("")}
|
|
34109
34129
|
</tbody>
|
|
@@ -34134,13 +34154,18 @@ var DeviceReportModal = class {
|
|
|
34134
34154
|
if (key === "date") {
|
|
34135
34155
|
comparison = new Date(a.date).getTime() - new Date(b.date).getTime();
|
|
34136
34156
|
} else {
|
|
34157
|
+
if (!!a.noData !== !!b.noData) return a.noData ? 1 : -1;
|
|
34137
34158
|
comparison = a.consumption - b.consumption;
|
|
34138
34159
|
}
|
|
34139
34160
|
return this.sortState.direction === "desc" ? -comparison : comparison;
|
|
34140
34161
|
});
|
|
34141
34162
|
}
|
|
34163
|
+
// Linhas com leitura (temperatura: dia sem leitura fica fora de totais/médias/KPIs)
|
|
34164
|
+
get validRows() {
|
|
34165
|
+
return this.data.filter((r) => !r.noData);
|
|
34166
|
+
}
|
|
34142
34167
|
calculateTotal() {
|
|
34143
|
-
return this.
|
|
34168
|
+
return this.validRows.reduce((sum2, row) => sum2 + row.consumption, 0);
|
|
34144
34169
|
}
|
|
34145
34170
|
formatDate(dateStr) {
|
|
34146
34171
|
if (!dateStr) return "";
|
|
@@ -34153,7 +34178,8 @@ var DeviceReportModal = class {
|
|
|
34153
34178
|
}
|
|
34154
34179
|
exportCSV() {
|
|
34155
34180
|
const total = this.calculateTotal();
|
|
34156
|
-
const
|
|
34181
|
+
const valid = this.validRows.length;
|
|
34182
|
+
const summaryValue = this.domainConfig.summaryType === "average" ? valid > 0 ? total / valid : 0 : total;
|
|
34157
34183
|
const now = /* @__PURE__ */ new Date();
|
|
34158
34184
|
const timestamp = now.toLocaleDateString("pt-BR") + " - " + now.toLocaleTimeString("pt-BR", { hour: "2-digit", minute: "2-digit" });
|
|
34159
34185
|
const csvData = [
|
|
@@ -34161,7 +34187,7 @@ var DeviceReportModal = class {
|
|
|
34161
34187
|
["DATA EMISS\xC3O", timestamp, ""],
|
|
34162
34188
|
[this.domainConfig.summaryLabel, this.domainConfig.formatter(summaryValue), this.domainConfig.unit],
|
|
34163
34189
|
[this.granularity === "1h" ? "Data/Hora" : "Data", this.domainConfig.label, ""],
|
|
34164
|
-
...this.data.map((row) => [this.formatDate(row.date), this.domainConfig.formatter(row.consumption)])
|
|
34190
|
+
...this.data.map((row) => [this.formatDate(row.date), row.noData ? "Sem leitura" : this.domainConfig.formatter(row.consumption)])
|
|
34165
34191
|
];
|
|
34166
34192
|
const csvContent = toCsv(csvData);
|
|
34167
34193
|
const granSuffix = this.granularity === "1h" ? "-1h" : "";
|
|
@@ -34192,7 +34218,7 @@ var DeviceReportModal = class {
|
|
|
34192
34218
|
return this.data.map((row) => ({
|
|
34193
34219
|
labelOrName: this.formatDate(row.date),
|
|
34194
34220
|
name: this.formatDate(row.date),
|
|
34195
|
-
val: row.consumption,
|
|
34221
|
+
val: row.noData ? null : row.consumption,
|
|
34196
34222
|
...isTemperature || total <= 0 ? {} : { perc: row.consumption / total * 100 }
|
|
34197
34223
|
}));
|
|
34198
34224
|
}
|
|
@@ -37389,10 +37415,12 @@ var AllReportModal = class {
|
|
|
37389
37415
|
// em total_value (in-place). Sensores sem série ficam com o 0 original.
|
|
37390
37416
|
async enrichTemperatureAverages(data, startISO, endISO, token, baseUrl) {
|
|
37391
37417
|
const rows = Array.isArray(data?.data) ? data.data : [];
|
|
37392
|
-
let tempRows
|
|
37418
|
+
let tempRows;
|
|
37393
37419
|
if (this.params.itemsList) {
|
|
37394
37420
|
const ids = new Set(this.params.itemsList.map((i) => String(i.id)));
|
|
37395
|
-
tempRows =
|
|
37421
|
+
tempRows = rows.filter((d) => ids.has(String(d?.id)));
|
|
37422
|
+
} else {
|
|
37423
|
+
tempRows = rows.filter((d) => String(d?.deviceType || "").toLowerCase() === "temperature");
|
|
37396
37424
|
}
|
|
37397
37425
|
if (!tempRows.length) return;
|
|
37398
37426
|
const startTime = encodeURIComponent(startISO);
|
|
@@ -5455,7 +5455,7 @@
|
|
|
5455
5455
|
|
|
5456
5456
|
// package.json
|
|
5457
5457
|
var package_default = {
|
|
5458
|
-
version: "0.1.
|
|
5458
|
+
version: "0.1.550"};
|
|
5459
5459
|
|
|
5460
5460
|
// src/utils/format/energy.ts
|
|
5461
5461
|
function formatPower(value, decimals = 2) {
|
|
@@ -39211,7 +39211,8 @@
|
|
|
39211
39211
|
baseUrl: this.params.api.dataApiBaseUrl || "https://api.data.apps.myio-bas.com",
|
|
39212
39212
|
ingestionId: this.params.ingestionId,
|
|
39213
39213
|
startISO,
|
|
39214
|
-
endISO
|
|
39214
|
+
endISO,
|
|
39215
|
+
granularity: this.granularity
|
|
39215
39216
|
});
|
|
39216
39217
|
this.data = this.processApiResponse(apiResponse, dateRange);
|
|
39217
39218
|
this.renderSummary();
|
|
@@ -39241,10 +39242,25 @@
|
|
|
39241
39242
|
if (!Array.isArray(dataArray) || dataArray.length === 0) {
|
|
39242
39243
|
console.warn("[DeviceReportModal] API returned empty or invalid response, zero-filling date range");
|
|
39243
39244
|
if (isHourly) return [];
|
|
39244
|
-
|
|
39245
|
+
const noData = this.domainConfig.summaryType === "average";
|
|
39246
|
+
return dateRange.map((date) => ({ date, consumption: 0, ...noData ? { noData: true } : {} }));
|
|
39245
39247
|
}
|
|
39246
39248
|
const deviceData = dataArray[0];
|
|
39247
39249
|
const consumption = deviceData.consumption || [];
|
|
39250
|
+
if (!isHourly && this.domainConfig.summaryType === "average") {
|
|
39251
|
+
const acc = {};
|
|
39252
|
+
consumption.forEach((item) => {
|
|
39253
|
+
if (item.timestamp && item.value != null && Number.isFinite(Number(item.value))) {
|
|
39254
|
+
const date = String(item.timestamp).slice(0, 10);
|
|
39255
|
+
const a = acc[date] || (acc[date] = { sum: 0, n: 0 });
|
|
39256
|
+
a.sum += Number(item.value);
|
|
39257
|
+
a.n += 1;
|
|
39258
|
+
}
|
|
39259
|
+
});
|
|
39260
|
+
return dateRange.map(
|
|
39261
|
+
(date) => acc[date] ? { date, consumption: acc[date].sum / acc[date].n } : { date, consumption: 0, noData: true }
|
|
39262
|
+
);
|
|
39263
|
+
}
|
|
39248
39264
|
if (isHourly) {
|
|
39249
39265
|
return consumption.filter((item) => item.timestamp && item.value != null).map((item) => ({
|
|
39250
39266
|
date: item.timestamp,
|
|
@@ -39306,14 +39322,15 @@
|
|
|
39306
39322
|
const isHourly = this.granularity === "1h";
|
|
39307
39323
|
const isTemperature = this.domainConfig.summaryType === "average";
|
|
39308
39324
|
const total = this.calculateTotal();
|
|
39309
|
-
const
|
|
39310
|
-
const
|
|
39325
|
+
const rows = this.validRows;
|
|
39326
|
+
const summaryValue = isTemperature ? rows.length > 0 ? total / rows.length : 0 : total;
|
|
39327
|
+
const dayKeys = new Set(rows.map((r) => r.date.slice(0, 10)));
|
|
39311
39328
|
const dayCount = Math.max(1, dayKeys.size);
|
|
39312
|
-
const maxRow =
|
|
39329
|
+
const maxRow = rows.reduce(
|
|
39313
39330
|
(best, r) => !best || r.consumption > best.consumption ? r : best,
|
|
39314
39331
|
null
|
|
39315
39332
|
);
|
|
39316
|
-
const minPool = isTemperature ?
|
|
39333
|
+
const minPool = isTemperature ? rows : rows.filter((r) => r.consumption > 0);
|
|
39317
39334
|
const minRow = minPool.reduce(
|
|
39318
39335
|
(best, r) => !best || r.consumption < best.consumption ? r : best,
|
|
39319
39336
|
null
|
|
@@ -39325,7 +39342,7 @@
|
|
|
39325
39342
|
{ value: fmt2(total / dayCount), label: `M\xE9dia por Dia (${unit})` }
|
|
39326
39343
|
];
|
|
39327
39344
|
if (isHourly) {
|
|
39328
|
-
kpis.push({ value: fmt2(total /
|
|
39345
|
+
kpis.push({ value: fmt2(rows.length ? total / rows.length : 0), label: `M\xE9dia por Hora (${unit})` });
|
|
39329
39346
|
}
|
|
39330
39347
|
kpis.push(
|
|
39331
39348
|
{
|
|
@@ -39341,6 +39358,9 @@
|
|
|
39341
39358
|
);
|
|
39342
39359
|
if (!isTemperature) {
|
|
39343
39360
|
kpis.push({ value: String(zeroCount), label: isHourly ? "Horas sem Consumo" : "Dias sem Consumo" });
|
|
39361
|
+
} else {
|
|
39362
|
+
const noData = this.data.length - rows.length;
|
|
39363
|
+
if (noData > 0) kpis.push({ value: String(noData), label: isHourly ? "Horas sem Leitura" : "Dias sem Leitura" });
|
|
39344
39364
|
}
|
|
39345
39365
|
return kpis;
|
|
39346
39366
|
}
|
|
@@ -39426,7 +39446,7 @@
|
|
|
39426
39446
|
${this.data.map((row) => `
|
|
39427
39447
|
<tr>
|
|
39428
39448
|
<td>${this.formatDate(row.date)}</td>
|
|
39429
|
-
<td style="text-align: right;">${this.domainConfig.formatter(row.consumption)}</td>
|
|
39449
|
+
<td style="text-align: right;${row.noData ? " color: var(--myio-text-muted);" : ""}">${row.noData ? "Sem leitura" : this.domainConfig.formatter(row.consumption)}</td>
|
|
39430
39450
|
</tr>
|
|
39431
39451
|
`).join("")}
|
|
39432
39452
|
</tbody>
|
|
@@ -39457,13 +39477,18 @@
|
|
|
39457
39477
|
if (key === "date") {
|
|
39458
39478
|
comparison = new Date(a.date).getTime() - new Date(b.date).getTime();
|
|
39459
39479
|
} else {
|
|
39480
|
+
if (!!a.noData !== !!b.noData) return a.noData ? 1 : -1;
|
|
39460
39481
|
comparison = a.consumption - b.consumption;
|
|
39461
39482
|
}
|
|
39462
39483
|
return this.sortState.direction === "desc" ? -comparison : comparison;
|
|
39463
39484
|
});
|
|
39464
39485
|
}
|
|
39486
|
+
// Linhas com leitura (temperatura: dia sem leitura fica fora de totais/médias/KPIs)
|
|
39487
|
+
get validRows() {
|
|
39488
|
+
return this.data.filter((r) => !r.noData);
|
|
39489
|
+
}
|
|
39465
39490
|
calculateTotal() {
|
|
39466
|
-
return this.
|
|
39491
|
+
return this.validRows.reduce((sum2, row) => sum2 + row.consumption, 0);
|
|
39467
39492
|
}
|
|
39468
39493
|
formatDate(dateStr) {
|
|
39469
39494
|
if (!dateStr) return "";
|
|
@@ -39476,7 +39501,8 @@
|
|
|
39476
39501
|
}
|
|
39477
39502
|
exportCSV() {
|
|
39478
39503
|
const total = this.calculateTotal();
|
|
39479
|
-
const
|
|
39504
|
+
const valid = this.validRows.length;
|
|
39505
|
+
const summaryValue = this.domainConfig.summaryType === "average" ? valid > 0 ? total / valid : 0 : total;
|
|
39480
39506
|
const now = /* @__PURE__ */ new Date();
|
|
39481
39507
|
const timestamp = now.toLocaleDateString("pt-BR") + " - " + now.toLocaleTimeString("pt-BR", { hour: "2-digit", minute: "2-digit" });
|
|
39482
39508
|
const csvData = [
|
|
@@ -39484,7 +39510,7 @@
|
|
|
39484
39510
|
["DATA EMISS\xC3O", timestamp, ""],
|
|
39485
39511
|
[this.domainConfig.summaryLabel, this.domainConfig.formatter(summaryValue), this.domainConfig.unit],
|
|
39486
39512
|
[this.granularity === "1h" ? "Data/Hora" : "Data", this.domainConfig.label, ""],
|
|
39487
|
-
...this.data.map((row) => [this.formatDate(row.date), this.domainConfig.formatter(row.consumption)])
|
|
39513
|
+
...this.data.map((row) => [this.formatDate(row.date), row.noData ? "Sem leitura" : this.domainConfig.formatter(row.consumption)])
|
|
39488
39514
|
];
|
|
39489
39515
|
const csvContent = toCsv(csvData);
|
|
39490
39516
|
const granSuffix = this.granularity === "1h" ? "-1h" : "";
|
|
@@ -39515,7 +39541,7 @@
|
|
|
39515
39541
|
return this.data.map((row) => ({
|
|
39516
39542
|
labelOrName: this.formatDate(row.date),
|
|
39517
39543
|
name: this.formatDate(row.date),
|
|
39518
|
-
val: row.consumption,
|
|
39544
|
+
val: row.noData ? null : row.consumption,
|
|
39519
39545
|
...isTemperature || total <= 0 ? {} : { perc: row.consumption / total * 100 }
|
|
39520
39546
|
}));
|
|
39521
39547
|
}
|
|
@@ -42712,10 +42738,12 @@
|
|
|
42712
42738
|
// em total_value (in-place). Sensores sem série ficam com o 0 original.
|
|
42713
42739
|
async enrichTemperatureAverages(data, startISO, endISO, token, baseUrl) {
|
|
42714
42740
|
const rows = Array.isArray(data?.data) ? data.data : [];
|
|
42715
|
-
let tempRows
|
|
42741
|
+
let tempRows;
|
|
42716
42742
|
if (this.params.itemsList) {
|
|
42717
42743
|
const ids = new Set(this.params.itemsList.map((i) => String(i.id)));
|
|
42718
|
-
tempRows =
|
|
42744
|
+
tempRows = rows.filter((d) => ids.has(String(d?.id)));
|
|
42745
|
+
} else {
|
|
42746
|
+
tempRows = rows.filter((d) => String(d?.deviceType || "").toLowerCase() === "temperature");
|
|
42719
42747
|
}
|
|
42720
42748
|
if (!tempRows.length) return;
|
|
42721
42749
|
const startTime = encodeURIComponent(startISO);
|