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.js CHANGED
@@ -6985,8 +6985,8 @@ var TELEMETRY_CONFIG = {
6985
6985
  total_current: { label: "Corrente Total", unit: "A", icon: "\u{1F50C}", decimals: 2 },
6986
6986
  current: { label: "Corrente", unit: "A", icon: "\u{1F50C}", decimals: 2 },
6987
6987
  // Power and Energy
6988
- consumption: { label: "Consumo", unit: "kW", icon: "\u2699\uFE0F", decimals: 2 },
6989
- power: { label: "Pot\xEAncia", unit: "kW", icon: "\u2699\uFE0F", decimals: 2 },
6988
+ consumption: { label: "Pot\xEAncia", unit: "W", icon: "\u2699\uFE0F", decimals: 0 },
6989
+ power: { label: "Pot\xEAncia", unit: "W", icon: "\u2699\uFE0F", decimals: 0 },
6990
6990
  energy: { label: "Energia", unit: "kWh", icon: "\u{1F4CA}", decimals: 1 },
6991
6991
  activePower: { label: "Pot\xEAncia Ativa", unit: "kW", icon: "\u2699\uFE0F", decimals: 2 },
6992
6992
  reactivePower: { label: "Pot\xEAncia Reativa", unit: "kVAr", icon: "\u{1F504}", decimals: 2 },
@@ -7042,7 +7042,9 @@ async function openRealTimeTelemetryModal(params) {
7042
7042
  let refreshIntervalId = null;
7043
7043
  let isPaused = false;
7044
7044
  let telemetryHistory = /* @__PURE__ */ new Map();
7045
+ let lastKnownValues = /* @__PURE__ */ new Map();
7045
7046
  let chart = null;
7047
+ let selectedChartKey = "consumption";
7046
7048
  const overlay = document.createElement("div");
7047
7049
  overlay.className = "myio-realtime-telemetry-overlay";
7048
7050
  overlay.innerHTML = `
@@ -7193,6 +7195,8 @@ async function openRealTimeTelemetryModal(params) {
7193
7195
  padding: 20px;
7194
7196
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
7195
7197
  margin-bottom: 20px;
7198
+ max-height: 520px;
7199
+ overflow: hidden;
7196
7200
  }
7197
7201
 
7198
7202
  .myio-telemetry-chart-title {
@@ -7203,7 +7207,29 @@ async function openRealTimeTelemetryModal(params) {
7203
7207
  }
7204
7208
 
7205
7209
  .myio-telemetry-chart {
7206
- height: 200px;
7210
+ height: 300px;
7211
+ max-height: 450px;
7212
+ width: 100%;
7213
+ }
7214
+
7215
+ .myio-telemetry-selector {
7216
+ padding: 8px 12px;
7217
+ border: 1px solid #ddd;
7218
+ border-radius: 6px;
7219
+ font-size: 14px;
7220
+ background: white;
7221
+ cursor: pointer;
7222
+ transition: border-color 0.2s;
7223
+ }
7224
+
7225
+ .myio-telemetry-selector:hover {
7226
+ border-color: #667eea;
7227
+ }
7228
+
7229
+ .myio-telemetry-selector:focus {
7230
+ outline: none;
7231
+ border-color: #667eea;
7232
+ box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
7207
7233
  }
7208
7234
 
7209
7235
  .myio-realtime-telemetry-footer {
@@ -7313,7 +7339,16 @@ async function openRealTimeTelemetryModal(params) {
7313
7339
  <div class="myio-telemetry-cards-grid" id="telemetry-cards"></div>
7314
7340
 
7315
7341
  <div class="myio-telemetry-chart-container" id="chart-container" style="display: none;">
7316
- <h3 class="myio-telemetry-chart-title" id="chart-title">Pot\xEAncia (\xFAltimos 5 min)</h3>
7342
+ <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px;">
7343
+ <h3 class="myio-telemetry-chart-title" id="chart-title" style="margin: 0;">Hist\xF3rico de Telemetria</h3>
7344
+ <select id="chart-key-selector" class="myio-telemetry-selector">
7345
+ <option value="consumption">Pot\xEAncia</option>
7346
+ <option value="total_current">Corrente Total</option>
7347
+ <option value="voltage_a">Tens\xE3o Fase A</option>
7348
+ <option value="voltage_b">Tens\xE3o Fase B</option>
7349
+ <option value="voltage_c">Tens\xE3o Fase C</option>
7350
+ </select>
7351
+ </div>
7317
7352
  <canvas class="myio-telemetry-chart" id="telemetry-chart"></canvas>
7318
7353
  </div>
7319
7354
  </div>
@@ -7344,20 +7379,21 @@ async function openRealTimeTelemetryModal(params) {
7344
7379
  </div>
7345
7380
  `;
7346
7381
  document.body.appendChild(overlay);
7347
- const closeBtn = document.getElementById("close-btn");
7348
- const pauseBtn = document.getElementById("pause-btn");
7349
- const pauseBtnIcon = document.getElementById("pause-btn-icon");
7350
- const pauseBtnText = document.getElementById("pause-btn-text");
7351
- const exportBtn = document.getElementById("export-btn");
7352
- const loadingState = document.getElementById("loading-state");
7353
- const telemetryContent = document.getElementById("telemetry-content");
7354
- const errorState = document.getElementById("error-state");
7355
- const telemetryCards = document.getElementById("telemetry-cards");
7356
- const chartContainer = document.getElementById("chart-container");
7357
- const chartCanvas = document.getElementById("telemetry-chart");
7358
- const statusIndicator = document.getElementById("status-indicator");
7359
- const statusText = document.getElementById("status-text");
7360
- const lastUpdateText = document.getElementById("last-update-text");
7382
+ const closeBtn = overlay.querySelector("#close-btn");
7383
+ const pauseBtn = overlay.querySelector("#pause-btn");
7384
+ const pauseBtnIcon = overlay.querySelector("#pause-btn-icon");
7385
+ const pauseBtnText = overlay.querySelector("#pause-btn-text");
7386
+ const exportBtn = overlay.querySelector("#export-btn");
7387
+ const loadingState = overlay.querySelector("#loading-state");
7388
+ const telemetryContent = overlay.querySelector("#telemetry-content");
7389
+ const errorState = overlay.querySelector("#error-state");
7390
+ const telemetryCards = overlay.querySelector("#telemetry-cards");
7391
+ const chartContainer = overlay.querySelector("#chart-container");
7392
+ const chartCanvas = overlay.querySelector("#telemetry-chart");
7393
+ const chartKeySelector = overlay.querySelector("#chart-key-selector");
7394
+ const statusIndicator = overlay.querySelector("#status-indicator");
7395
+ const statusText = overlay.querySelector("#status-text");
7396
+ const lastUpdateText = overlay.querySelector("#last-update-text");
7361
7397
  function closeModal() {
7362
7398
  if (refreshIntervalId) {
7363
7399
  clearInterval(refreshIntervalId);
@@ -7446,16 +7482,42 @@ async function openRealTimeTelemetryModal(params) {
7446
7482
  }
7447
7483
  const history = telemetryHistory.get(tel.key);
7448
7484
  history.push({ x: now, y: tel.value });
7485
+ lastKnownValues.set(tel.key, tel.value);
7449
7486
  if (history.length > historyPoints) {
7450
7487
  history.shift();
7451
7488
  }
7452
7489
  }
7453
- if (telemetryHistory.has("power") && chart) {
7454
- const powerHistory = telemetryHistory.get("power");
7455
- chart.data.datasets[0].data = powerHistory;
7490
+ for (const key of telemetryKeys) {
7491
+ const receivedKeys = values.map((v) => v.key);
7492
+ if (!receivedKeys.includes(key) && lastKnownValues.has(key)) {
7493
+ if (!telemetryHistory.has(key)) {
7494
+ telemetryHistory.set(key, []);
7495
+ }
7496
+ const history = telemetryHistory.get(key);
7497
+ const lastValue = lastKnownValues.get(key);
7498
+ history.push({ x: now, y: lastValue });
7499
+ if (history.length > historyPoints) {
7500
+ history.shift();
7501
+ }
7502
+ }
7503
+ }
7504
+ if (telemetryHistory.has(selectedChartKey) && chart) {
7505
+ const selectedHistory = telemetryHistory.get(selectedChartKey);
7506
+ chart.data.datasets[0].data = selectedHistory;
7456
7507
  chart.update("none");
7457
7508
  }
7458
7509
  }
7510
+ function getFormattedValue(key, value) {
7511
+ const config = TELEMETRY_CONFIG[key];
7512
+ if (!config) return value.toFixed(2);
7513
+ if (key === "consumption" || key === "power") {
7514
+ if (value >= 1e3) {
7515
+ return `${(value / 1e3).toFixed(2)} kW`;
7516
+ }
7517
+ return `${value.toFixed(0)} W`;
7518
+ }
7519
+ return `${value.toFixed(config.decimals)} ${config.unit}`;
7520
+ }
7459
7521
  function initializeChart() {
7460
7522
  const Chart = window.Chart;
7461
7523
  if (!Chart) {
@@ -7463,23 +7525,26 @@ async function openRealTimeTelemetryModal(params) {
7463
7525
  return;
7464
7526
  }
7465
7527
  chartContainer.style.display = "block";
7528
+ const config = TELEMETRY_CONFIG[selectedChartKey] || { label: selectedChartKey, unit: "" };
7466
7529
  chart = new Chart(chartCanvas, {
7467
7530
  type: "line",
7468
7531
  data: {
7469
7532
  datasets: [{
7470
- label: "Pot\xEAncia",
7533
+ label: config.label,
7471
7534
  data: [],
7472
7535
  borderColor: "#667eea",
7473
7536
  backgroundColor: "rgba(102, 126, 234, 0.1)",
7474
7537
  borderWidth: 2,
7475
7538
  fill: true,
7476
7539
  tension: 0.4,
7477
- pointRadius: 0
7540
+ pointRadius: 3,
7541
+ pointHoverRadius: 5
7478
7542
  }]
7479
7543
  },
7480
7544
  options: {
7481
7545
  responsive: true,
7482
7546
  maintainAspectRatio: false,
7547
+ animation: false,
7483
7548
  plugins: {
7484
7549
  legend: { display: false },
7485
7550
  tooltip: {
@@ -7487,10 +7552,18 @@ async function openRealTimeTelemetryModal(params) {
7487
7552
  title: function(context) {
7488
7553
  const timestamp = context[0].parsed.x;
7489
7554
  const date = new Date(timestamp);
7490
- return date.toLocaleTimeString(locale);
7555
+ return date.toLocaleString(locale, {
7556
+ day: "2-digit",
7557
+ month: "2-digit",
7558
+ year: "numeric",
7559
+ hour: "2-digit",
7560
+ minute: "2-digit",
7561
+ second: "2-digit"
7562
+ });
7491
7563
  },
7492
7564
  label: function(context) {
7493
- return `${context.parsed.y.toFixed(2)} kW`;
7565
+ const value = context.parsed.y;
7566
+ return getFormattedValue(selectedChartKey, value);
7494
7567
  }
7495
7568
  }
7496
7569
  }
@@ -7499,23 +7572,57 @@ async function openRealTimeTelemetryModal(params) {
7499
7572
  x: {
7500
7573
  type: "linear",
7501
7574
  ticks: {
7575
+ maxRotation: 45,
7576
+ minRotation: 0,
7502
7577
  callback: function(value) {
7503
7578
  const date = new Date(value);
7504
- return date.toLocaleTimeString(locale, { hour: "2-digit", minute: "2-digit" });
7579
+ return date.toLocaleTimeString(locale, {
7580
+ hour: "2-digit",
7581
+ minute: "2-digit",
7582
+ second: "2-digit"
7583
+ });
7505
7584
  }
7585
+ },
7586
+ title: {
7587
+ display: true,
7588
+ text: "Hora"
7506
7589
  }
7507
7590
  },
7508
7591
  y: {
7509
7592
  beginAtZero: true,
7593
+ ticks: {
7594
+ callback: function(value) {
7595
+ if (selectedChartKey === "consumption" || selectedChartKey === "power") {
7596
+ if (value >= 1e3) {
7597
+ return `${(value / 1e3).toFixed(1)} kW`;
7598
+ }
7599
+ return `${value} W`;
7600
+ }
7601
+ return `${value} ${config.unit}`;
7602
+ }
7603
+ },
7510
7604
  title: {
7511
7605
  display: true,
7512
- text: "kW"
7606
+ text: selectedChartKey === "consumption" || selectedChartKey === "power" ? "W" : config.unit
7513
7607
  }
7514
7608
  }
7515
7609
  }
7516
7610
  }
7517
7611
  });
7518
7612
  }
7613
+ function updateChartKey(newKey) {
7614
+ selectedChartKey = newKey;
7615
+ if (chart) {
7616
+ chart.destroy();
7617
+ chart = null;
7618
+ }
7619
+ initializeChart();
7620
+ if (telemetryHistory.has(selectedChartKey)) {
7621
+ const selectedHistory = telemetryHistory.get(selectedChartKey);
7622
+ chart.data.datasets[0].data = selectedHistory;
7623
+ chart.update("none");
7624
+ }
7625
+ }
7519
7626
  async function refreshData() {
7520
7627
  try {
7521
7628
  const data = await fetchLatestTelemetry();
@@ -7527,9 +7634,7 @@ async function openRealTimeTelemetryModal(params) {
7527
7634
  if (loadingState.style.display !== "none") {
7528
7635
  loadingState.style.display = "none";
7529
7636
  telemetryContent.style.display = "block";
7530
- if (telemetryKeys.includes("power")) {
7531
- initializeChart();
7532
- }
7637
+ initializeChart();
7533
7638
  }
7534
7639
  } catch (error) {
7535
7640
  console.error("[RealTimeTelemetry] Error fetching data:", error);
@@ -7597,6 +7702,10 @@ async function openRealTimeTelemetryModal(params) {
7597
7702
  closeBtn.addEventListener("click", closeModal);
7598
7703
  pauseBtn.addEventListener("click", togglePause);
7599
7704
  exportBtn.addEventListener("click", exportToCSV2);
7705
+ chartKeySelector.addEventListener("change", (e) => {
7706
+ const newKey = e.target.value;
7707
+ updateChartKey(newKey);
7708
+ });
7600
7709
  overlay.addEventListener("click", (e) => {
7601
7710
  if (e.target === overlay) {
7602
7711
  closeModal();
@@ -8722,18 +8831,20 @@ var FALLBACK_PATHS = [
8722
8831
  "/assets/vendor/moment.min.js",
8723
8832
  "/assets/vendor/daterangepicker.min.js"
8724
8833
  ];
8725
- var PT_BR_LOCALE = {
8726
- format: "DD/MM/YY HH:mm",
8727
- separator: " at\xE9 ",
8728
- applyLabel: "Aplicar",
8729
- cancelLabel: "Cancelar",
8730
- fromLabel: "De",
8731
- toLabel: "At\xE9",
8732
- customRangeLabel: "Personalizado",
8733
- daysOfWeek: ["Do", "Se", "Te", "Qa", "Qi", "Se", "Sa"],
8734
- monthNames: ["Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"],
8735
- firstDay: 1
8736
- };
8834
+ function getLocaleConfig(includeTime = false) {
8835
+ return {
8836
+ format: includeTime ? "DD/MM/YY HH:mm" : "DD/MM/YYYY",
8837
+ separator: " at\xE9 ",
8838
+ applyLabel: "Aplicar",
8839
+ cancelLabel: "Cancelar",
8840
+ fromLabel: "De",
8841
+ toLabel: "At\xE9",
8842
+ customRangeLabel: "Personalizado",
8843
+ daysOfWeek: ["Do", "Se", "Te", "Qa", "Qi", "Se", "Sa"],
8844
+ monthNames: ["Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"],
8845
+ firstDay: 1
8846
+ };
8847
+ }
8737
8848
  var CDNLoader = class {
8738
8849
  static jQueryInstance = null;
8739
8850
  static loadingPromise = null;
@@ -8854,14 +8965,46 @@ function createDateRangePicker($2, input, opts) {
8854
8965
  helpText.style.display = "flex";
8855
8966
  helpText.style.alignItems = "center";
8856
8967
  input.parentNode?.appendChild(helpText);
8968
+ const includeTime = opts.includeTime === true;
8969
+ const timePrecision = opts.timePrecision || "minute";
8970
+ const localeConfig = getLocaleConfig(includeTime);
8857
8971
  const moment = window.moment;
8858
- const startDate = opts.presetStart ? moment(opts.presetStart).startOf("day") : moment().startOf("month");
8859
- const endDate = opts.presetEnd ? moment(opts.presetEnd).endOf("day") : moment().endOf("day");
8972
+ let startDate, endDate;
8973
+ if (includeTime) {
8974
+ startDate = opts.presetStart ? moment(opts.presetStart) : moment().startOf("day");
8975
+ endDate = opts.presetEnd ? moment(opts.presetEnd) : moment();
8976
+ } else {
8977
+ startDate = opts.presetStart ? moment(opts.presetStart).startOf("day") : moment().startOf("month");
8978
+ endDate = opts.presetEnd ? moment(opts.presetEnd).endOf("day") : moment().endOf("day");
8979
+ }
8980
+ let ranges;
8981
+ if (includeTime) {
8982
+ const now = moment();
8983
+ ranges = {
8984
+ "\xDAltima hora": [moment().subtract(1, "hours"), now.clone()],
8985
+ "\xDAltimas 6 horas": [moment().subtract(6, "hours"), now.clone()],
8986
+ "\xDAltimas 12 horas": [moment().subtract(12, "hours"), now.clone()],
8987
+ "\xDAltimas 24 horas": [moment().subtract(24, "hours"), now.clone()],
8988
+ "Hoje": [moment().startOf("day"), now.clone()],
8989
+ "Ontem": [moment().subtract(1, "day").startOf("day"), moment().subtract(1, "day").endOf("day")],
8990
+ "\xDAltimos 7 dias": [moment().subtract(6, "days").startOf("day"), now.clone()],
8991
+ "Este m\xEAs": [moment().startOf("month"), now.clone()]
8992
+ };
8993
+ } else {
8994
+ ranges = {
8995
+ "Hoje": [moment().startOf("day"), moment().endOf("day")],
8996
+ "\xDAltimos 7 dias": [moment().subtract(6, "days").startOf("day"), moment().endOf("day")],
8997
+ "\xDAltimos 30 dias": [moment().subtract(29, "days").startOf("day"), moment().endOf("day")],
8998
+ "M\xEAs Anterior": [moment().subtract(1, "month").startOf("month"), moment().subtract(1, "month").endOf("month")]
8999
+ };
9000
+ }
8860
9001
  $input.daterangepicker({
8861
9002
  parentEl: opts.parentEl || document.body,
8862
- timePicker: true,
9003
+ timePicker: includeTime,
9004
+ // RFC-0086: Conditional time picker
8863
9005
  timePicker24Hour: true,
8864
- timePickerIncrement: 1,
9006
+ timePickerIncrement: timePrecision === "hour" ? 60 : 1,
9007
+ // RFC-0086: Hour vs minute precision
8865
9008
  autoApply: true,
8866
9009
  autoUpdateInput: true,
8867
9010
  linkedCalendars: true,
@@ -8872,15 +9015,12 @@ function createDateRangePicker($2, input, opts) {
8872
9015
  endDate,
8873
9016
  opens: "right",
8874
9017
  drops: "down",
8875
- locale: PT_BR_LOCALE,
9018
+ locale: localeConfig,
9019
+ // RFC-0086: Dynamic locale format
8876
9020
  applyButtonClasses: "btn btn-primary",
8877
9021
  cancelClass: "btn btn-muted",
8878
- ranges: {
8879
- "Hoje": [moment().startOf("day"), moment().endOf("day")],
8880
- "\xDAltimos 7 dias": [moment().subtract(6, "days").startOf("day"), moment().endOf("day")],
8881
- "\xDAltimos 30 dias": [moment().subtract(29, "days").startOf("day"), moment().endOf("day")],
8882
- "M\xEAs Anterior": [moment().subtract(1, "month").startOf("month"), moment().subtract(1, "month").endOf("month")]
8883
- }
9022
+ ranges
9023
+ // RFC-0086: Dynamic ranges
8884
9024
  });
8885
9025
  updateInputDisplay();
8886
9026
  $input.on("apply.daterangepicker.myio", () => {
@@ -8899,7 +9039,7 @@ function createDateRangePicker($2, input, opts) {
8899
9039
  function updateInputDisplay() {
8900
9040
  const picker = $input.data("daterangepicker");
8901
9041
  if (picker) {
8902
- const formatted = `${picker.startDate.format(PT_BR_LOCALE.format)}${PT_BR_LOCALE.separator}${picker.endDate.format(PT_BR_LOCALE.format)}`;
9042
+ const formatted = `${picker.startDate.format(localeConfig.format)}${localeConfig.separator}${picker.endDate.format(localeConfig.format)}`;
8903
9043
  $input.val(formatted);
8904
9044
  }
8905
9045
  }
@@ -8907,8 +9047,8 @@ function createDateRangePicker($2, input, opts) {
8907
9047
  const picker = $input.data("daterangepicker");
8908
9048
  const startISO = picker.startDate.format("YYYY-MM-DD[T]HH:mm:ssZ");
8909
9049
  const endISO = picker.endDate.format("YYYY-MM-DD[T]HH:mm:ssZ");
8910
- const startLabel = picker.startDate.format(PT_BR_LOCALE.format);
8911
- const endLabel = picker.endDate.format(PT_BR_LOCALE.format);
9050
+ const startLabel = picker.startDate.format(localeConfig.format);
9051
+ const endLabel = picker.endDate.format(localeConfig.format);
8912
9052
  return { startISO, endISO, startLabel, endLabel };
8913
9053
  }
8914
9054
  function setDates(startISO, endISO) {
@@ -9879,10 +10019,7 @@ async function openDemandModal(params) {
9879
10019
  <button class="myio-demand-modal-btn-update" type="button">
9880
10020
  ${strings.updatePeriod}
9881
10021
  </button>
9882
- <button id="realtime-toggle-btn" class="myio-demand-modal-btn-realtime" type="button" title="Ativar modo tempo real (atualiza\xE7\xE3o a cada 8 segundos)">
9883
- <span class="realtime-indicator"></span>
9884
- <span class="realtime-text">REAL TIME</span>
9885
- </button>
10022
+ <!-- RFC-0084: REAL TIME button removed - use RealTimeTelemetryModal instead -->
9886
10023
  <div class="myio-demand-modal-period-error" style="display: none;"></div>
9887
10024
  </div>
9888
10025
 
@@ -9930,7 +10067,6 @@ async function openDemandModal(params) {
9930
10067
  const dateStartInput = overlay.querySelector(".myio-demand-modal-date-start");
9931
10068
  const dateEndInput = overlay.querySelector(".myio-demand-modal-date-end");
9932
10069
  const updateBtn = overlay.querySelector(".myio-demand-modal-btn-update");
9933
- const realTimeToggleBtn = overlay.querySelector("#realtime-toggle-btn");
9934
10070
  const periodErrorEl = overlay.querySelector(".myio-demand-modal-period-error");
9935
10071
  const telemetryTypeSelect = overlay.querySelector("#telemetry-type-select");
9936
10072
  const intervalSelect = overlay.querySelector("#demand-interval-select");
@@ -10123,7 +10259,6 @@ async function openDemandModal(params) {
10123
10259
  console.error("[DemandModal] Real-time update failed:", error);
10124
10260
  }
10125
10261
  }, intervalMs);
10126
- realTimeToggleBtn.classList.add("active");
10127
10262
  isRealTimeMode = true;
10128
10263
  console.log(`[DemandModal] Real-time mode started (${intervalMs}ms interval)`);
10129
10264
  } catch (error) {
@@ -10206,7 +10341,6 @@ async function openDemandModal(params) {
10206
10341
  isRealTimeMode = false;
10207
10342
  lastFetchedTimestamp = null;
10208
10343
  realTimeDataBuffer = [];
10209
- realTimeToggleBtn.classList.remove("active");
10210
10344
  console.log("[DemandModal] Real-time mode stopped");
10211
10345
  }
10212
10346
  function initializeDateInputs() {
@@ -10289,13 +10423,6 @@ async function openDemandModal(params) {
10289
10423
  pdfBtn.addEventListener("click", exportPdf);
10290
10424
  csvBtn.addEventListener("click", exportCsv);
10291
10425
  updateBtn.addEventListener("click", updatePeriod);
10292
- realTimeToggleBtn.addEventListener("click", async () => {
10293
- if (isRealTimeMode) {
10294
- await disableRealTimeMode();
10295
- } else {
10296
- await enableRealTimeMode();
10297
- }
10298
- });
10299
10426
  if (telemetryTypeSelect && allowTelemetrySwitch) {
10300
10427
  const debouncedSwitch = debounce(switchTelemetryType, 300);
10301
10428
  telemetryTypeSelect.addEventListener("change", (e) => {