myio-js-library 0.1.136 → 0.1.139
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 +197 -70
- package/dist/index.d.cts +6 -0
- package/dist/index.js +197 -70
- package/dist/myio-js-library.umd.js +198 -193
- package/dist/myio-js-library.umd.min.js +1 -1
- package/package.json +1 -1
|
@@ -6983,8 +6983,8 @@ ${rangeText}`;
|
|
|
6983
6983
|
total_current: { label: "Corrente Total", unit: "A", icon: "\u{1F50C}", decimals: 2 },
|
|
6984
6984
|
current: { label: "Corrente", unit: "A", icon: "\u{1F50C}", decimals: 2 },
|
|
6985
6985
|
// Power and Energy
|
|
6986
|
-
consumption: { label: "
|
|
6987
|
-
power: { label: "Pot\xEAncia", unit: "
|
|
6986
|
+
consumption: { label: "Pot\xEAncia", unit: "W", icon: "\u2699\uFE0F", decimals: 0 },
|
|
6987
|
+
power: { label: "Pot\xEAncia", unit: "W", icon: "\u2699\uFE0F", decimals: 0 },
|
|
6988
6988
|
energy: { label: "Energia", unit: "kWh", icon: "\u{1F4CA}", decimals: 1 },
|
|
6989
6989
|
activePower: { label: "Pot\xEAncia Ativa", unit: "kW", icon: "\u2699\uFE0F", decimals: 2 },
|
|
6990
6990
|
reactivePower: { label: "Pot\xEAncia Reativa", unit: "kVAr", icon: "\u{1F504}", decimals: 2 },
|
|
@@ -7040,7 +7040,9 @@ ${rangeText}`;
|
|
|
7040
7040
|
let refreshIntervalId = null;
|
|
7041
7041
|
let isPaused = false;
|
|
7042
7042
|
let telemetryHistory = /* @__PURE__ */ new Map();
|
|
7043
|
+
let lastKnownValues = /* @__PURE__ */ new Map();
|
|
7043
7044
|
let chart = null;
|
|
7045
|
+
let selectedChartKey = "consumption";
|
|
7044
7046
|
const overlay = document.createElement("div");
|
|
7045
7047
|
overlay.className = "myio-realtime-telemetry-overlay";
|
|
7046
7048
|
overlay.innerHTML = `
|
|
@@ -7191,6 +7193,8 @@ ${rangeText}`;
|
|
|
7191
7193
|
padding: 20px;
|
|
7192
7194
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
7193
7195
|
margin-bottom: 20px;
|
|
7196
|
+
max-height: 520px;
|
|
7197
|
+
overflow: hidden;
|
|
7194
7198
|
}
|
|
7195
7199
|
|
|
7196
7200
|
.myio-telemetry-chart-title {
|
|
@@ -7201,7 +7205,29 @@ ${rangeText}`;
|
|
|
7201
7205
|
}
|
|
7202
7206
|
|
|
7203
7207
|
.myio-telemetry-chart {
|
|
7204
|
-
height:
|
|
7208
|
+
height: 300px;
|
|
7209
|
+
max-height: 450px;
|
|
7210
|
+
width: 100%;
|
|
7211
|
+
}
|
|
7212
|
+
|
|
7213
|
+
.myio-telemetry-selector {
|
|
7214
|
+
padding: 8px 12px;
|
|
7215
|
+
border: 1px solid #ddd;
|
|
7216
|
+
border-radius: 6px;
|
|
7217
|
+
font-size: 14px;
|
|
7218
|
+
background: white;
|
|
7219
|
+
cursor: pointer;
|
|
7220
|
+
transition: border-color 0.2s;
|
|
7221
|
+
}
|
|
7222
|
+
|
|
7223
|
+
.myio-telemetry-selector:hover {
|
|
7224
|
+
border-color: #667eea;
|
|
7225
|
+
}
|
|
7226
|
+
|
|
7227
|
+
.myio-telemetry-selector:focus {
|
|
7228
|
+
outline: none;
|
|
7229
|
+
border-color: #667eea;
|
|
7230
|
+
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
|
|
7205
7231
|
}
|
|
7206
7232
|
|
|
7207
7233
|
.myio-realtime-telemetry-footer {
|
|
@@ -7311,7 +7337,16 @@ ${rangeText}`;
|
|
|
7311
7337
|
<div class="myio-telemetry-cards-grid" id="telemetry-cards"></div>
|
|
7312
7338
|
|
|
7313
7339
|
<div class="myio-telemetry-chart-container" id="chart-container" style="display: none;">
|
|
7314
|
-
<
|
|
7340
|
+
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px;">
|
|
7341
|
+
<h3 class="myio-telemetry-chart-title" id="chart-title" style="margin: 0;">Hist\xF3rico de Telemetria</h3>
|
|
7342
|
+
<select id="chart-key-selector" class="myio-telemetry-selector">
|
|
7343
|
+
<option value="consumption">Pot\xEAncia</option>
|
|
7344
|
+
<option value="total_current">Corrente Total</option>
|
|
7345
|
+
<option value="voltage_a">Tens\xE3o Fase A</option>
|
|
7346
|
+
<option value="voltage_b">Tens\xE3o Fase B</option>
|
|
7347
|
+
<option value="voltage_c">Tens\xE3o Fase C</option>
|
|
7348
|
+
</select>
|
|
7349
|
+
</div>
|
|
7315
7350
|
<canvas class="myio-telemetry-chart" id="telemetry-chart"></canvas>
|
|
7316
7351
|
</div>
|
|
7317
7352
|
</div>
|
|
@@ -7342,20 +7377,21 @@ ${rangeText}`;
|
|
|
7342
7377
|
</div>
|
|
7343
7378
|
`;
|
|
7344
7379
|
document.body.appendChild(overlay);
|
|
7345
|
-
const closeBtn =
|
|
7346
|
-
const pauseBtn =
|
|
7347
|
-
const pauseBtnIcon =
|
|
7348
|
-
const pauseBtnText =
|
|
7349
|
-
const exportBtn =
|
|
7350
|
-
const loadingState =
|
|
7351
|
-
const telemetryContent =
|
|
7352
|
-
const errorState =
|
|
7353
|
-
const telemetryCards =
|
|
7354
|
-
const chartContainer =
|
|
7355
|
-
const chartCanvas =
|
|
7356
|
-
const
|
|
7357
|
-
const
|
|
7358
|
-
const
|
|
7380
|
+
const closeBtn = overlay.querySelector("#close-btn");
|
|
7381
|
+
const pauseBtn = overlay.querySelector("#pause-btn");
|
|
7382
|
+
const pauseBtnIcon = overlay.querySelector("#pause-btn-icon");
|
|
7383
|
+
const pauseBtnText = overlay.querySelector("#pause-btn-text");
|
|
7384
|
+
const exportBtn = overlay.querySelector("#export-btn");
|
|
7385
|
+
const loadingState = overlay.querySelector("#loading-state");
|
|
7386
|
+
const telemetryContent = overlay.querySelector("#telemetry-content");
|
|
7387
|
+
const errorState = overlay.querySelector("#error-state");
|
|
7388
|
+
const telemetryCards = overlay.querySelector("#telemetry-cards");
|
|
7389
|
+
const chartContainer = overlay.querySelector("#chart-container");
|
|
7390
|
+
const chartCanvas = overlay.querySelector("#telemetry-chart");
|
|
7391
|
+
const chartKeySelector = overlay.querySelector("#chart-key-selector");
|
|
7392
|
+
const statusIndicator = overlay.querySelector("#status-indicator");
|
|
7393
|
+
const statusText = overlay.querySelector("#status-text");
|
|
7394
|
+
const lastUpdateText = overlay.querySelector("#last-update-text");
|
|
7359
7395
|
function closeModal() {
|
|
7360
7396
|
if (refreshIntervalId) {
|
|
7361
7397
|
clearInterval(refreshIntervalId);
|
|
@@ -7444,16 +7480,42 @@ ${rangeText}`;
|
|
|
7444
7480
|
}
|
|
7445
7481
|
const history = telemetryHistory.get(tel.key);
|
|
7446
7482
|
history.push({ x: now, y: tel.value });
|
|
7483
|
+
lastKnownValues.set(tel.key, tel.value);
|
|
7447
7484
|
if (history.length > historyPoints) {
|
|
7448
7485
|
history.shift();
|
|
7449
7486
|
}
|
|
7450
7487
|
}
|
|
7451
|
-
|
|
7452
|
-
const
|
|
7453
|
-
|
|
7488
|
+
for (const key of telemetryKeys) {
|
|
7489
|
+
const receivedKeys = values.map((v) => v.key);
|
|
7490
|
+
if (!receivedKeys.includes(key) && lastKnownValues.has(key)) {
|
|
7491
|
+
if (!telemetryHistory.has(key)) {
|
|
7492
|
+
telemetryHistory.set(key, []);
|
|
7493
|
+
}
|
|
7494
|
+
const history = telemetryHistory.get(key);
|
|
7495
|
+
const lastValue = lastKnownValues.get(key);
|
|
7496
|
+
history.push({ x: now, y: lastValue });
|
|
7497
|
+
if (history.length > historyPoints) {
|
|
7498
|
+
history.shift();
|
|
7499
|
+
}
|
|
7500
|
+
}
|
|
7501
|
+
}
|
|
7502
|
+
if (telemetryHistory.has(selectedChartKey) && chart) {
|
|
7503
|
+
const selectedHistory = telemetryHistory.get(selectedChartKey);
|
|
7504
|
+
chart.data.datasets[0].data = selectedHistory;
|
|
7454
7505
|
chart.update("none");
|
|
7455
7506
|
}
|
|
7456
7507
|
}
|
|
7508
|
+
function getFormattedValue(key, value) {
|
|
7509
|
+
const config = TELEMETRY_CONFIG[key];
|
|
7510
|
+
if (!config) return value.toFixed(2);
|
|
7511
|
+
if (key === "consumption" || key === "power") {
|
|
7512
|
+
if (value >= 1e3) {
|
|
7513
|
+
return `${(value / 1e3).toFixed(2)} kW`;
|
|
7514
|
+
}
|
|
7515
|
+
return `${value.toFixed(0)} W`;
|
|
7516
|
+
}
|
|
7517
|
+
return `${value.toFixed(config.decimals)} ${config.unit}`;
|
|
7518
|
+
}
|
|
7457
7519
|
function initializeChart() {
|
|
7458
7520
|
const Chart = window.Chart;
|
|
7459
7521
|
if (!Chart) {
|
|
@@ -7461,23 +7523,26 @@ ${rangeText}`;
|
|
|
7461
7523
|
return;
|
|
7462
7524
|
}
|
|
7463
7525
|
chartContainer.style.display = "block";
|
|
7526
|
+
const config = TELEMETRY_CONFIG[selectedChartKey] || { label: selectedChartKey, unit: "" };
|
|
7464
7527
|
chart = new Chart(chartCanvas, {
|
|
7465
7528
|
type: "line",
|
|
7466
7529
|
data: {
|
|
7467
7530
|
datasets: [{
|
|
7468
|
-
label:
|
|
7531
|
+
label: config.label,
|
|
7469
7532
|
data: [],
|
|
7470
7533
|
borderColor: "#667eea",
|
|
7471
7534
|
backgroundColor: "rgba(102, 126, 234, 0.1)",
|
|
7472
7535
|
borderWidth: 2,
|
|
7473
7536
|
fill: true,
|
|
7474
7537
|
tension: 0.4,
|
|
7475
|
-
pointRadius:
|
|
7538
|
+
pointRadius: 3,
|
|
7539
|
+
pointHoverRadius: 5
|
|
7476
7540
|
}]
|
|
7477
7541
|
},
|
|
7478
7542
|
options: {
|
|
7479
7543
|
responsive: true,
|
|
7480
7544
|
maintainAspectRatio: false,
|
|
7545
|
+
animation: false,
|
|
7481
7546
|
plugins: {
|
|
7482
7547
|
legend: { display: false },
|
|
7483
7548
|
tooltip: {
|
|
@@ -7485,10 +7550,18 @@ ${rangeText}`;
|
|
|
7485
7550
|
title: function(context) {
|
|
7486
7551
|
const timestamp = context[0].parsed.x;
|
|
7487
7552
|
const date = new Date(timestamp);
|
|
7488
|
-
return date.
|
|
7553
|
+
return date.toLocaleString(locale, {
|
|
7554
|
+
day: "2-digit",
|
|
7555
|
+
month: "2-digit",
|
|
7556
|
+
year: "numeric",
|
|
7557
|
+
hour: "2-digit",
|
|
7558
|
+
minute: "2-digit",
|
|
7559
|
+
second: "2-digit"
|
|
7560
|
+
});
|
|
7489
7561
|
},
|
|
7490
7562
|
label: function(context) {
|
|
7491
|
-
|
|
7563
|
+
const value = context.parsed.y;
|
|
7564
|
+
return getFormattedValue(selectedChartKey, value);
|
|
7492
7565
|
}
|
|
7493
7566
|
}
|
|
7494
7567
|
}
|
|
@@ -7497,23 +7570,57 @@ ${rangeText}`;
|
|
|
7497
7570
|
x: {
|
|
7498
7571
|
type: "linear",
|
|
7499
7572
|
ticks: {
|
|
7573
|
+
maxRotation: 45,
|
|
7574
|
+
minRotation: 0,
|
|
7500
7575
|
callback: function(value) {
|
|
7501
7576
|
const date = new Date(value);
|
|
7502
|
-
return date.toLocaleTimeString(locale, {
|
|
7577
|
+
return date.toLocaleTimeString(locale, {
|
|
7578
|
+
hour: "2-digit",
|
|
7579
|
+
minute: "2-digit",
|
|
7580
|
+
second: "2-digit"
|
|
7581
|
+
});
|
|
7503
7582
|
}
|
|
7583
|
+
},
|
|
7584
|
+
title: {
|
|
7585
|
+
display: true,
|
|
7586
|
+
text: "Hora"
|
|
7504
7587
|
}
|
|
7505
7588
|
},
|
|
7506
7589
|
y: {
|
|
7507
7590
|
beginAtZero: true,
|
|
7591
|
+
ticks: {
|
|
7592
|
+
callback: function(value) {
|
|
7593
|
+
if (selectedChartKey === "consumption" || selectedChartKey === "power") {
|
|
7594
|
+
if (value >= 1e3) {
|
|
7595
|
+
return `${(value / 1e3).toFixed(1)} kW`;
|
|
7596
|
+
}
|
|
7597
|
+
return `${value} W`;
|
|
7598
|
+
}
|
|
7599
|
+
return `${value} ${config.unit}`;
|
|
7600
|
+
}
|
|
7601
|
+
},
|
|
7508
7602
|
title: {
|
|
7509
7603
|
display: true,
|
|
7510
|
-
text: "
|
|
7604
|
+
text: selectedChartKey === "consumption" || selectedChartKey === "power" ? "W" : config.unit
|
|
7511
7605
|
}
|
|
7512
7606
|
}
|
|
7513
7607
|
}
|
|
7514
7608
|
}
|
|
7515
7609
|
});
|
|
7516
7610
|
}
|
|
7611
|
+
function updateChartKey(newKey) {
|
|
7612
|
+
selectedChartKey = newKey;
|
|
7613
|
+
if (chart) {
|
|
7614
|
+
chart.destroy();
|
|
7615
|
+
chart = null;
|
|
7616
|
+
}
|
|
7617
|
+
initializeChart();
|
|
7618
|
+
if (telemetryHistory.has(selectedChartKey)) {
|
|
7619
|
+
const selectedHistory = telemetryHistory.get(selectedChartKey);
|
|
7620
|
+
chart.data.datasets[0].data = selectedHistory;
|
|
7621
|
+
chart.update("none");
|
|
7622
|
+
}
|
|
7623
|
+
}
|
|
7517
7624
|
async function refreshData() {
|
|
7518
7625
|
try {
|
|
7519
7626
|
const data = await fetchLatestTelemetry();
|
|
@@ -7525,9 +7632,7 @@ ${rangeText}`;
|
|
|
7525
7632
|
if (loadingState.style.display !== "none") {
|
|
7526
7633
|
loadingState.style.display = "none";
|
|
7527
7634
|
telemetryContent.style.display = "block";
|
|
7528
|
-
|
|
7529
|
-
initializeChart();
|
|
7530
|
-
}
|
|
7635
|
+
initializeChart();
|
|
7531
7636
|
}
|
|
7532
7637
|
} catch (error) {
|
|
7533
7638
|
console.error("[RealTimeTelemetry] Error fetching data:", error);
|
|
@@ -7595,6 +7700,10 @@ ${rangeText}`;
|
|
|
7595
7700
|
closeBtn.addEventListener("click", closeModal);
|
|
7596
7701
|
pauseBtn.addEventListener("click", togglePause);
|
|
7597
7702
|
exportBtn.addEventListener("click", exportToCSV2);
|
|
7703
|
+
chartKeySelector.addEventListener("change", (e) => {
|
|
7704
|
+
const newKey = e.target.value;
|
|
7705
|
+
updateChartKey(newKey);
|
|
7706
|
+
});
|
|
7598
7707
|
overlay.addEventListener("click", (e) => {
|
|
7599
7708
|
if (e.target === overlay) {
|
|
7600
7709
|
closeModal();
|
|
@@ -8717,18 +8826,20 @@ ${rangeText}`;
|
|
|
8717
8826
|
"/assets/vendor/moment.min.js",
|
|
8718
8827
|
"/assets/vendor/daterangepicker.min.js"
|
|
8719
8828
|
];
|
|
8720
|
-
|
|
8721
|
-
|
|
8722
|
-
|
|
8723
|
-
|
|
8724
|
-
|
|
8725
|
-
|
|
8726
|
-
|
|
8727
|
-
|
|
8728
|
-
|
|
8729
|
-
|
|
8730
|
-
|
|
8731
|
-
|
|
8829
|
+
function getLocaleConfig(includeTime = false) {
|
|
8830
|
+
return {
|
|
8831
|
+
format: includeTime ? "DD/MM/YY HH:mm" : "DD/MM/YYYY",
|
|
8832
|
+
separator: " at\xE9 ",
|
|
8833
|
+
applyLabel: "Aplicar",
|
|
8834
|
+
cancelLabel: "Cancelar",
|
|
8835
|
+
fromLabel: "De",
|
|
8836
|
+
toLabel: "At\xE9",
|
|
8837
|
+
customRangeLabel: "Personalizado",
|
|
8838
|
+
daysOfWeek: ["Do", "Se", "Te", "Qa", "Qi", "Se", "Sa"],
|
|
8839
|
+
monthNames: ["Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"],
|
|
8840
|
+
firstDay: 1
|
|
8841
|
+
};
|
|
8842
|
+
}
|
|
8732
8843
|
var CDNLoader = class {
|
|
8733
8844
|
static jQueryInstance = null;
|
|
8734
8845
|
static loadingPromise = null;
|
|
@@ -8849,14 +8960,46 @@ ${rangeText}`;
|
|
|
8849
8960
|
helpText.style.display = "flex";
|
|
8850
8961
|
helpText.style.alignItems = "center";
|
|
8851
8962
|
input.parentNode?.appendChild(helpText);
|
|
8963
|
+
const includeTime = opts.includeTime === true;
|
|
8964
|
+
const timePrecision = opts.timePrecision || "minute";
|
|
8965
|
+
const localeConfig = getLocaleConfig(includeTime);
|
|
8852
8966
|
const moment = window.moment;
|
|
8853
|
-
|
|
8854
|
-
|
|
8967
|
+
let startDate, endDate;
|
|
8968
|
+
if (includeTime) {
|
|
8969
|
+
startDate = opts.presetStart ? moment(opts.presetStart) : moment().startOf("day");
|
|
8970
|
+
endDate = opts.presetEnd ? moment(opts.presetEnd) : moment();
|
|
8971
|
+
} else {
|
|
8972
|
+
startDate = opts.presetStart ? moment(opts.presetStart).startOf("day") : moment().startOf("month");
|
|
8973
|
+
endDate = opts.presetEnd ? moment(opts.presetEnd).endOf("day") : moment().endOf("day");
|
|
8974
|
+
}
|
|
8975
|
+
let ranges;
|
|
8976
|
+
if (includeTime) {
|
|
8977
|
+
const now = moment();
|
|
8978
|
+
ranges = {
|
|
8979
|
+
"\xDAltima hora": [moment().subtract(1, "hours"), now.clone()],
|
|
8980
|
+
"\xDAltimas 6 horas": [moment().subtract(6, "hours"), now.clone()],
|
|
8981
|
+
"\xDAltimas 12 horas": [moment().subtract(12, "hours"), now.clone()],
|
|
8982
|
+
"\xDAltimas 24 horas": [moment().subtract(24, "hours"), now.clone()],
|
|
8983
|
+
"Hoje": [moment().startOf("day"), now.clone()],
|
|
8984
|
+
"Ontem": [moment().subtract(1, "day").startOf("day"), moment().subtract(1, "day").endOf("day")],
|
|
8985
|
+
"\xDAltimos 7 dias": [moment().subtract(6, "days").startOf("day"), now.clone()],
|
|
8986
|
+
"Este m\xEAs": [moment().startOf("month"), now.clone()]
|
|
8987
|
+
};
|
|
8988
|
+
} else {
|
|
8989
|
+
ranges = {
|
|
8990
|
+
"Hoje": [moment().startOf("day"), moment().endOf("day")],
|
|
8991
|
+
"\xDAltimos 7 dias": [moment().subtract(6, "days").startOf("day"), moment().endOf("day")],
|
|
8992
|
+
"\xDAltimos 30 dias": [moment().subtract(29, "days").startOf("day"), moment().endOf("day")],
|
|
8993
|
+
"M\xEAs Anterior": [moment().subtract(1, "month").startOf("month"), moment().subtract(1, "month").endOf("month")]
|
|
8994
|
+
};
|
|
8995
|
+
}
|
|
8855
8996
|
$input.daterangepicker({
|
|
8856
8997
|
parentEl: opts.parentEl || document.body,
|
|
8857
|
-
timePicker:
|
|
8998
|
+
timePicker: includeTime,
|
|
8999
|
+
// RFC-0086: Conditional time picker
|
|
8858
9000
|
timePicker24Hour: true,
|
|
8859
|
-
timePickerIncrement: 1,
|
|
9001
|
+
timePickerIncrement: timePrecision === "hour" ? 60 : 1,
|
|
9002
|
+
// RFC-0086: Hour vs minute precision
|
|
8860
9003
|
autoApply: true,
|
|
8861
9004
|
autoUpdateInput: true,
|
|
8862
9005
|
linkedCalendars: true,
|
|
@@ -8867,15 +9010,12 @@ ${rangeText}`;
|
|
|
8867
9010
|
endDate,
|
|
8868
9011
|
opens: "right",
|
|
8869
9012
|
drops: "down",
|
|
8870
|
-
locale:
|
|
9013
|
+
locale: localeConfig,
|
|
9014
|
+
// RFC-0086: Dynamic locale format
|
|
8871
9015
|
applyButtonClasses: "btn btn-primary",
|
|
8872
9016
|
cancelClass: "btn btn-muted",
|
|
8873
|
-
ranges
|
|
8874
|
-
|
|
8875
|
-
"\xDAltimos 7 dias": [moment().subtract(6, "days").startOf("day"), moment().endOf("day")],
|
|
8876
|
-
"\xDAltimos 30 dias": [moment().subtract(29, "days").startOf("day"), moment().endOf("day")],
|
|
8877
|
-
"M\xEAs Anterior": [moment().subtract(1, "month").startOf("month"), moment().subtract(1, "month").endOf("month")]
|
|
8878
|
-
}
|
|
9017
|
+
ranges
|
|
9018
|
+
// RFC-0086: Dynamic ranges
|
|
8879
9019
|
});
|
|
8880
9020
|
updateInputDisplay();
|
|
8881
9021
|
$input.on("apply.daterangepicker.myio", () => {
|
|
@@ -8894,7 +9034,7 @@ ${rangeText}`;
|
|
|
8894
9034
|
function updateInputDisplay() {
|
|
8895
9035
|
const picker = $input.data("daterangepicker");
|
|
8896
9036
|
if (picker) {
|
|
8897
|
-
const formatted = `${picker.startDate.format(
|
|
9037
|
+
const formatted = `${picker.startDate.format(localeConfig.format)}${localeConfig.separator}${picker.endDate.format(localeConfig.format)}`;
|
|
8898
9038
|
$input.val(formatted);
|
|
8899
9039
|
}
|
|
8900
9040
|
}
|
|
@@ -8902,8 +9042,8 @@ ${rangeText}`;
|
|
|
8902
9042
|
const picker = $input.data("daterangepicker");
|
|
8903
9043
|
const startISO = picker.startDate.format("YYYY-MM-DD[T]HH:mm:ssZ");
|
|
8904
9044
|
const endISO = picker.endDate.format("YYYY-MM-DD[T]HH:mm:ssZ");
|
|
8905
|
-
const startLabel = picker.startDate.format(
|
|
8906
|
-
const endLabel = picker.endDate.format(
|
|
9045
|
+
const startLabel = picker.startDate.format(localeConfig.format);
|
|
9046
|
+
const endLabel = picker.endDate.format(localeConfig.format);
|
|
8907
9047
|
return { startISO, endISO, startLabel, endLabel };
|
|
8908
9048
|
}
|
|
8909
9049
|
function setDates(startISO, endISO) {
|
|
@@ -9699,7 +9839,7 @@ ${rangeText}`;
|
|
|
9699
9839
|
isEmpty = false;
|
|
9700
9840
|
const sortedData = rawSeries.sort((a, b) => a.ts - b.ts);
|
|
9701
9841
|
const points = [];
|
|
9702
|
-
const isAggregated = aggregation
|
|
9842
|
+
const isAggregated = aggregation !== "NONE";
|
|
9703
9843
|
if (isAggregated) {
|
|
9704
9844
|
for (let i = 0; i < sortedData.length; i++) {
|
|
9705
9845
|
const current = sortedData[i];
|
|
@@ -9874,10 +10014,7 @@ ${rangeText}`;
|
|
|
9874
10014
|
<button class="myio-demand-modal-btn-update" type="button">
|
|
9875
10015
|
${strings.updatePeriod}
|
|
9876
10016
|
</button>
|
|
9877
|
-
|
|
9878
|
-
<span class="realtime-indicator"></span>
|
|
9879
|
-
<span class="realtime-text">REAL TIME</span>
|
|
9880
|
-
</button>
|
|
10017
|
+
<!-- RFC-0084: REAL TIME button removed - use RealTimeTelemetryModal instead -->
|
|
9881
10018
|
<div class="myio-demand-modal-period-error" style="display: none;"></div>
|
|
9882
10019
|
</div>
|
|
9883
10020
|
|
|
@@ -9925,7 +10062,6 @@ ${rangeText}`;
|
|
|
9925
10062
|
const dateStartInput = overlay.querySelector(".myio-demand-modal-date-start");
|
|
9926
10063
|
const dateEndInput = overlay.querySelector(".myio-demand-modal-date-end");
|
|
9927
10064
|
const updateBtn = overlay.querySelector(".myio-demand-modal-btn-update");
|
|
9928
|
-
const realTimeToggleBtn = overlay.querySelector("#realtime-toggle-btn");
|
|
9929
10065
|
const periodErrorEl = overlay.querySelector(".myio-demand-modal-period-error");
|
|
9930
10066
|
const telemetryTypeSelect = overlay.querySelector("#telemetry-type-select");
|
|
9931
10067
|
const intervalSelect = overlay.querySelector("#demand-interval-select");
|
|
@@ -9936,16 +10072,10 @@ ${rangeText}`;
|
|
|
9936
10072
|
let currentStartDate = params.startDate;
|
|
9937
10073
|
let currentEndDate = params.endDate;
|
|
9938
10074
|
let activeTelemetryType = currentTelemetryType;
|
|
9939
|
-
let isRealTimeMode = false;
|
|
9940
|
-
let realTimeIntervalId = null;
|
|
9941
|
-
let lastFetchedTimestamp = null;
|
|
9942
10075
|
const originalOverflow = document.body.style.overflow;
|
|
9943
10076
|
document.body.style.overflow = "hidden";
|
|
9944
10077
|
const releaseFocusTrap = createFocusTrap(overlay);
|
|
9945
10078
|
function closeModal() {
|
|
9946
|
-
if (isRealTimeMode && realTimeIntervalId) {
|
|
9947
|
-
window.clearInterval(realTimeIntervalId);
|
|
9948
|
-
}
|
|
9949
10079
|
if (chart) {
|
|
9950
10080
|
chart.destroy();
|
|
9951
10081
|
}
|
|
@@ -10078,124 +10208,6 @@ ${rangeText}`;
|
|
|
10078
10208
|
btn.innerHTML = originalHtml;
|
|
10079
10209
|
}
|
|
10080
10210
|
}
|
|
10081
|
-
function getTodayStart() {
|
|
10082
|
-
const today = /* @__PURE__ */ new Date();
|
|
10083
|
-
today.setHours(0, 0, 0, 0);
|
|
10084
|
-
return today.toISOString();
|
|
10085
|
-
}
|
|
10086
|
-
async function enableRealTimeMode() {
|
|
10087
|
-
try {
|
|
10088
|
-
currentStartDate = getTodayStart();
|
|
10089
|
-
currentEndDate = (/* @__PURE__ */ new Date()).toISOString();
|
|
10090
|
-
initializeDateInputs();
|
|
10091
|
-
dateStartInput.disabled = true;
|
|
10092
|
-
dateEndInput.disabled = true;
|
|
10093
|
-
dateStartInput.style.opacity = "0.5";
|
|
10094
|
-
dateEndInput.style.opacity = "0.5";
|
|
10095
|
-
if (intervalSelect) {
|
|
10096
|
-
intervalSelect.disabled = true;
|
|
10097
|
-
intervalSelect.style.opacity = "0.5";
|
|
10098
|
-
}
|
|
10099
|
-
if (aggSelect) {
|
|
10100
|
-
aggSelect.disabled = true;
|
|
10101
|
-
aggSelect.style.opacity = "0.5";
|
|
10102
|
-
}
|
|
10103
|
-
if (intervalSelect) intervalSelect.value = "8000";
|
|
10104
|
-
if (aggSelect) aggSelect.value = "AVG";
|
|
10105
|
-
await loadData();
|
|
10106
|
-
lastFetchedTimestamp = Date.now();
|
|
10107
|
-
const intervalMs = params.realTimeInterval || 8e3;
|
|
10108
|
-
realTimeIntervalId = window.setInterval(async () => {
|
|
10109
|
-
try {
|
|
10110
|
-
await fetchIncrementalData();
|
|
10111
|
-
} catch (error) {
|
|
10112
|
-
console.error("[DemandModal] Real-time update failed:", error);
|
|
10113
|
-
}
|
|
10114
|
-
}, intervalMs);
|
|
10115
|
-
realTimeToggleBtn.classList.add("active");
|
|
10116
|
-
isRealTimeMode = true;
|
|
10117
|
-
console.log(`[DemandModal] Real-time mode started (${intervalMs}ms interval)`);
|
|
10118
|
-
} catch (error) {
|
|
10119
|
-
console.error("[DemandModal] Failed to enable real-time mode:", error);
|
|
10120
|
-
await disableRealTimeMode();
|
|
10121
|
-
alert("Erro ao ativar modo tempo real. Tente novamente.");
|
|
10122
|
-
}
|
|
10123
|
-
}
|
|
10124
|
-
async function fetchIncrementalData() {
|
|
10125
|
-
if (!lastFetchedTimestamp) {
|
|
10126
|
-
throw new Error("No last fetched timestamp available");
|
|
10127
|
-
}
|
|
10128
|
-
const startTs = lastFetchedTimestamp;
|
|
10129
|
-
const endTs = Date.now();
|
|
10130
|
-
const startDate = new Date(startTs).toISOString();
|
|
10131
|
-
const endDate = new Date(endTs).toISOString();
|
|
10132
|
-
const keysStr = Array.isArray(activeTelemetryType.keys) ? activeTelemetryType.keys.join(",") : activeTelemetryType.keys;
|
|
10133
|
-
const telemetryQuery = {
|
|
10134
|
-
keys: keysStr,
|
|
10135
|
-
interval: 8e3,
|
|
10136
|
-
// 8 seconds (fixed for real-time mode)
|
|
10137
|
-
agg: "AVG",
|
|
10138
|
-
// Average (fixed for real-time mode)
|
|
10139
|
-
intervalType: "MILLISECONDS",
|
|
10140
|
-
orderBy: "ASC"
|
|
10141
|
-
};
|
|
10142
|
-
const newRawData = params.fetcher ? await params.fetcher({ token: params.token, deviceId: params.deviceId, startDate, endDate, telemetryQuery }) : await fetchTelemetryData(params.token, params.deviceId, startDate, endDate, telemetryQuery);
|
|
10143
|
-
const newChartData = processMultiSeriesChartData(
|
|
10144
|
-
newRawData,
|
|
10145
|
-
keysStr,
|
|
10146
|
-
params.correctionFactor || 1,
|
|
10147
|
-
locale,
|
|
10148
|
-
"AVG",
|
|
10149
|
-
params.timezoneOffset
|
|
10150
|
-
);
|
|
10151
|
-
if (!newChartData.isEmpty && chart && chartData) {
|
|
10152
|
-
newChartData.series.forEach((newSeries, seriesIndex) => {
|
|
10153
|
-
if (newSeries.points.length > 0 && chart.data.datasets[seriesIndex]) {
|
|
10154
|
-
newSeries.points.forEach((point) => {
|
|
10155
|
-
chart.data.datasets[seriesIndex].data.push({
|
|
10156
|
-
x: point.x,
|
|
10157
|
-
y: point.y
|
|
10158
|
-
});
|
|
10159
|
-
chart.data.labels.push(point.x);
|
|
10160
|
-
});
|
|
10161
|
-
}
|
|
10162
|
-
});
|
|
10163
|
-
chart.update("none");
|
|
10164
|
-
if (params.realTimeAutoScroll !== false) {
|
|
10165
|
-
const latestTimestamp = newChartData.series[0]?.points[newChartData.series[0].points.length - 1]?.x;
|
|
10166
|
-
if (latestTimestamp && chart.options.scales?.x) {
|
|
10167
|
-
const visibleRange = 3e5;
|
|
10168
|
-
chart.options.scales.x.min = latestTimestamp - visibleRange;
|
|
10169
|
-
chart.options.scales.x.max = latestTimestamp;
|
|
10170
|
-
chart.update("none");
|
|
10171
|
-
}
|
|
10172
|
-
}
|
|
10173
|
-
}
|
|
10174
|
-
lastFetchedTimestamp = endTs;
|
|
10175
|
-
console.log(`[DemandModal] Incremental fetch completed (${newChartData.series.reduce((sum, s) => sum + s.points.length, 0)} new points)`);
|
|
10176
|
-
}
|
|
10177
|
-
async function disableRealTimeMode() {
|
|
10178
|
-
if (realTimeIntervalId) {
|
|
10179
|
-
window.clearInterval(realTimeIntervalId);
|
|
10180
|
-
realTimeIntervalId = null;
|
|
10181
|
-
}
|
|
10182
|
-
dateStartInput.disabled = false;
|
|
10183
|
-
dateEndInput.disabled = false;
|
|
10184
|
-
dateStartInput.style.opacity = "1";
|
|
10185
|
-
dateEndInput.style.opacity = "1";
|
|
10186
|
-
if (intervalSelect) {
|
|
10187
|
-
intervalSelect.disabled = false;
|
|
10188
|
-
intervalSelect.style.opacity = "1";
|
|
10189
|
-
}
|
|
10190
|
-
if (aggSelect) {
|
|
10191
|
-
aggSelect.disabled = false;
|
|
10192
|
-
aggSelect.style.opacity = "1";
|
|
10193
|
-
}
|
|
10194
|
-
isRealTimeMode = false;
|
|
10195
|
-
lastFetchedTimestamp = null;
|
|
10196
|
-
realTimeToggleBtn.classList.remove("active");
|
|
10197
|
-
console.log("[DemandModal] Real-time mode stopped");
|
|
10198
|
-
}
|
|
10199
10211
|
function initializeDateInputs() {
|
|
10200
10212
|
const startDate = new Date(currentStartDate);
|
|
10201
10213
|
const endDate = new Date(currentEndDate);
|
|
@@ -10276,13 +10288,6 @@ ${rangeText}`;
|
|
|
10276
10288
|
pdfBtn.addEventListener("click", exportPdf);
|
|
10277
10289
|
csvBtn.addEventListener("click", exportCsv);
|
|
10278
10290
|
updateBtn.addEventListener("click", updatePeriod);
|
|
10279
|
-
realTimeToggleBtn.addEventListener("click", async () => {
|
|
10280
|
-
if (isRealTimeMode) {
|
|
10281
|
-
await disableRealTimeMode();
|
|
10282
|
-
} else {
|
|
10283
|
-
await enableRealTimeMode();
|
|
10284
|
-
}
|
|
10285
|
-
});
|
|
10286
10291
|
if (telemetryTypeSelect && allowTelemetrySwitch) {
|
|
10287
10292
|
const debouncedSwitch = debounce(switchTelemetryType, 300);
|
|
10288
10293
|
telemetryTypeSelect.addEventListener("change", (e) => {
|