myio-js-library 0.1.169 → 0.1.172

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
@@ -1318,7 +1318,8 @@ var DeviceStatusType = {
1318
1318
  FAILURE: "failure",
1319
1319
  MAINTENANCE: "maintenance",
1320
1320
  NO_INFO: "no_info",
1321
- NOT_INSTALLED: "not_installed"
1321
+ NOT_INSTALLED: "not_installed",
1322
+ OFFLINE: "offline"
1322
1323
  };
1323
1324
  var ConnectionStatusType = {
1324
1325
  CONNECTED: "connected",
@@ -1327,39 +1328,42 @@ var ConnectionStatusType = {
1327
1328
  var deviceStatusIcons = {
1328
1329
  [DeviceStatusType.POWER_ON]: "\u26A1",
1329
1330
  [DeviceStatusType.STANDBY]: "\u{1F50C}",
1330
- [DeviceStatusType.POWER_OFF]: "\u{1F534}",
1331
+ [DeviceStatusType.POWER_OFF]: "\u26AB",
1331
1332
  [DeviceStatusType.WARNING]: "\u26A0\uFE0F",
1332
1333
  [DeviceStatusType.FAILURE]: "\u{1F6A8}",
1333
1334
  [DeviceStatusType.MAINTENANCE]: "\u{1F6E0}\uFE0F",
1334
1335
  [DeviceStatusType.NO_INFO]: "\u2753\uFE0F",
1335
- [DeviceStatusType.NOT_INSTALLED]: "\u{1F4E6}"
1336
+ [DeviceStatusType.NOT_INSTALLED]: "\u{1F4E6}",
1337
+ [DeviceStatusType.OFFLINE]: "\u{1F534}"
1336
1338
  };
1337
1339
  var waterDeviceStatusIcons = {
1338
1340
  [DeviceStatusType.POWER_ON]: "\u{1F4A7}",
1339
1341
  [DeviceStatusType.STANDBY]: "\u{1F6B0}",
1340
- [DeviceStatusType.POWER_OFF]: "\u{1F534}",
1342
+ [DeviceStatusType.POWER_OFF]: "\u26AB",
1341
1343
  [DeviceStatusType.WARNING]: "\u26A0\uFE0F",
1342
1344
  [DeviceStatusType.FAILURE]: "\u{1F6A8}",
1343
1345
  [DeviceStatusType.MAINTENANCE]: "\u{1F6E0}\uFE0F",
1344
1346
  [DeviceStatusType.NO_INFO]: "\u2753\uFE0F",
1345
- [DeviceStatusType.NOT_INSTALLED]: "\u{1F4E6}"
1347
+ [DeviceStatusType.NOT_INSTALLED]: "\u{1F4E6}",
1348
+ [DeviceStatusType.OFFLINE]: "\u{1F534}"
1346
1349
  };
1347
1350
  var temperatureDeviceStatusIcons = {
1348
1351
  [DeviceStatusType.POWER_ON]: "\u{1F321}\uFE0F",
1349
1352
  [DeviceStatusType.STANDBY]: "\u{1F321}\uFE0F",
1350
- [DeviceStatusType.POWER_OFF]: "\u{1F534}",
1353
+ [DeviceStatusType.POWER_OFF]: "\u26AB",
1351
1354
  [DeviceStatusType.WARNING]: "\u26A0\uFE0F",
1352
1355
  [DeviceStatusType.FAILURE]: "\u{1F6A8}",
1353
1356
  [DeviceStatusType.MAINTENANCE]: "\u{1F6E0}\uFE0F",
1354
1357
  [DeviceStatusType.NO_INFO]: "\u2753\uFE0F",
1355
- [DeviceStatusType.NOT_INSTALLED]: "\u{1F4E6}"
1358
+ [DeviceStatusType.NOT_INSTALLED]: "\u{1F4E6}",
1359
+ [DeviceStatusType.OFFLINE]: "\u{1F534}"
1356
1360
  };
1357
1361
  var connectionStatusIcons = {
1358
1362
  [ConnectionStatusType.CONNECTED]: "\u{1F7E2}",
1359
1363
  [ConnectionStatusType.OFFLINE]: "\u{1F6AB}"
1360
1364
  };
1361
1365
  function mapDeviceToConnectionStatus(deviceStatus) {
1362
- if (deviceStatus === DeviceStatusType.NO_INFO) {
1366
+ if (deviceStatus === DeviceStatusType.NO_INFO || deviceStatus === DeviceStatusType.OFFLINE) {
1363
1367
  return ConnectionStatusType.OFFLINE;
1364
1368
  }
1365
1369
  return ConnectionStatusType.CONNECTED;
@@ -1383,15 +1387,16 @@ function mapDeviceStatusToCardStatus(deviceStatus) {
1383
1387
  [DeviceStatusType.FAILURE]: "fail",
1384
1388
  [DeviceStatusType.MAINTENANCE]: "alert",
1385
1389
  [DeviceStatusType.NO_INFO]: "unknown",
1386
- [DeviceStatusType.NOT_INSTALLED]: "not_installed"
1390
+ [DeviceStatusType.NOT_INSTALLED]: "not_installed",
1391
+ [DeviceStatusType.OFFLINE]: "offline"
1387
1392
  };
1388
1393
  return statusMap[deviceStatus] || "unknown";
1389
1394
  }
1390
1395
  function shouldFlashIcon(deviceStatus) {
1391
- return deviceStatus === DeviceStatusType.POWER_OFF || deviceStatus === DeviceStatusType.WARNING || deviceStatus === DeviceStatusType.FAILURE || deviceStatus === DeviceStatusType.MAINTENANCE;
1396
+ return deviceStatus === DeviceStatusType.POWER_OFF || deviceStatus === DeviceStatusType.WARNING || deviceStatus === DeviceStatusType.FAILURE || deviceStatus === DeviceStatusType.MAINTENANCE || deviceStatus === DeviceStatusType.OFFLINE;
1392
1397
  }
1393
1398
  function isDeviceOffline(deviceStatus) {
1394
- return deviceStatus === DeviceStatusType.NO_INFO;
1399
+ return deviceStatus === DeviceStatusType.NO_INFO || deviceStatus === DeviceStatusType.OFFLINE;
1395
1400
  }
1396
1401
  function getDeviceStatusIcon(deviceStatus, deviceType = null) {
1397
1402
  const normalizedType = deviceType?.toUpperCase() || "";
@@ -3947,15 +3952,30 @@ var CSS_STRING = `
3947
3952
  --myio-chip-alert-fg: #b45309;
3948
3953
  --myio-border-alert: rgba(245, 158, 11, 0.5);
3949
3954
 
3950
- /* Status colors - Failure (red) */
3955
+ /* Status colors - Failure (dark red) */
3951
3956
  --myio-chip-failure-bg: #fee2e2;
3952
3957
  --myio-chip-failure-fg: #b91c1c;
3953
- --myio-border-failure: rgba(239, 68, 68, 0.5);
3958
+ --myio-border-failure: rgba(153, 27, 27, 0.6);
3959
+
3960
+ /* Status colors - Power Off (light red) */
3961
+ --myio-chip-power-off-bg: #fecaca;
3962
+ --myio-chip-power-off-fg: #dc2626;
3963
+ --myio-border-power-off: rgba(239, 68, 68, 0.5);
3964
+
3965
+ /* Status colors - Offline (dark gray) */
3966
+ --myio-chip-offline-bg: #e2e8f0;
3967
+ --myio-chip-offline-fg: #475569;
3968
+ --myio-border-offline: rgba(71, 85, 105, 0.6);
3969
+
3970
+ /* Status colors - No Info (dark orange) */
3971
+ --myio-chip-no-info-bg: #fed7aa;
3972
+ --myio-chip-no-info-fg: #c2410c;
3973
+ --myio-border-no-info: rgba(194, 65, 12, 0.5);
3954
3974
 
3955
- /* Status colors - Offline (gray) */
3956
- --myio-chip-offline-bg: #f1f5f9;
3957
- --myio-chip-offline-fg: #64748b;
3958
- --myio-border-offline: rgba(100, 116, 139, 0.4);
3975
+ /* Status colors - Not Installed (purple) */
3976
+ --myio-chip-not-installed-bg: #e9d5ff;
3977
+ --myio-chip-not-installed-fg: #7c3aed;
3978
+ --myio-border-not-installed: rgba(124, 58, 237, 0.5);
3959
3979
 
3960
3980
  --myio-text-1: #0f172a;
3961
3981
  --myio-text-2: #4b5563;
@@ -4011,26 +4031,55 @@ var CSS_STRING = `
4011
4031
  }
4012
4032
 
4013
4033
  /* Card border states based on device status */
4014
- .myio-ho-card.is-ok {
4034
+
4035
+ /* POWER_ON - Blue */
4036
+ .myio-ho-card.is-power-on {
4015
4037
  border-color: var(--myio-border-ok);
4016
4038
  box-shadow: 0 0 0 2px var(--myio-border-ok), var(--myio-card-shadow);
4017
4039
  }
4018
4040
 
4041
+ /* STANDBY - Green */
4019
4042
  .myio-ho-card.is-standby {
4020
4043
  border-color: var(--myio-border-standby);
4021
4044
  box-shadow: 0 0 0 2px var(--myio-border-standby), var(--myio-card-shadow);
4022
4045
  }
4023
4046
 
4024
- .myio-ho-card.is-alert {
4047
+ /* WARNING - Yellow */
4048
+ .myio-ho-card.is-warning {
4025
4049
  border-color: var(--myio-border-alert);
4026
4050
  box-shadow: 0 0 0 2px var(--myio-border-alert), var(--myio-card-shadow);
4027
4051
  }
4028
4052
 
4053
+ /* MAINTENANCE - Yellow */
4054
+ .myio-ho-card.is-maintenance {
4055
+ border-color: var(--myio-border-alert);
4056
+ box-shadow: 0 0 0 2px var(--myio-border-alert), var(--myio-card-shadow);
4057
+ }
4058
+
4059
+ /* FAILURE - Dark Red */
4029
4060
  .myio-ho-card.is-failure {
4030
4061
  border-color: var(--myio-border-failure);
4031
4062
  box-shadow: 0 0 0 2px var(--myio-border-failure), var(--myio-card-shadow);
4032
4063
  }
4033
4064
 
4065
+ /* POWER_OFF - Light Red */
4066
+ .myio-ho-card.is-power-off {
4067
+ border-color: var(--myio-border-power-off);
4068
+ box-shadow: 0 0 0 2px var(--myio-border-power-off), var(--myio-card-shadow);
4069
+ }
4070
+
4071
+ /* NO_INFO - Dark Orange */
4072
+ .myio-ho-card.is-no-info {
4073
+ border-color: var(--myio-border-no-info);
4074
+ box-shadow: 0 0 0 2px var(--myio-border-no-info), var(--myio-card-shadow);
4075
+ }
4076
+
4077
+ /* NOT_INSTALLED - Purple */
4078
+ .myio-ho-card.is-not-installed {
4079
+ border-color: var(--myio-border-not-installed);
4080
+ box-shadow: 0 0 0 2px var(--myio-border-not-installed), var(--myio-card-shadow);
4081
+ }
4082
+
4034
4083
  /* Header section */
4035
4084
  .myio-ho-card__header {
4036
4085
  display: flex;
@@ -4048,7 +4097,9 @@ var CSS_STRING = `
4048
4097
  margin-top: 2px;
4049
4098
  }
4050
4099
 
4051
- .myio-ho-card.is-alert .myio-ho-card__icon {
4100
+ /* Icon colors based on status */
4101
+ .myio-ho-card.is-warning .myio-ho-card__icon,
4102
+ .myio-ho-card.is-maintenance .myio-ho-card__icon {
4052
4103
  color: var(--myio-chip-alert-fg);
4053
4104
  }
4054
4105
 
@@ -4056,14 +4107,28 @@ var CSS_STRING = `
4056
4107
  color: var(--myio-chip-failure-fg);
4057
4108
  }
4058
4109
 
4110
+ .myio-ho-card.is-power-off .myio-ho-card__icon {
4111
+ color: var(--myio-chip-power-off-fg);
4112
+ }
4113
+
4114
+ .myio-ho-card.is-offline .myio-ho-card__icon {
4115
+ color: var(--myio-chip-offline-fg);
4116
+ }
4117
+
4118
+ .myio-ho-card.is-no-info .myio-ho-card__icon {
4119
+ color: var(--myio-chip-no-info-fg);
4120
+ }
4121
+
4122
+ .myio-ho-card.is-not-installed .myio-ho-card__icon {
4123
+ color: var(--myio-chip-not-installed-fg);
4124
+ }
4125
+
4059
4126
  .myio-ho-card__title {
4060
4127
  flex: 1;
4061
4128
  min-width: 0;
4062
4129
  }
4063
4130
 
4064
- /* Adicione estas duas novas regras ao seu CSS_STRING */
4065
-
4066
- /* Estado Offline - borda cinza */
4131
+ /* OFFLINE - Dark Gray */
4067
4132
  .myio-ho-card.is-offline {
4068
4133
  border-color: var(--myio-border-offline);
4069
4134
  box-shadow: 0 0 0 2px var(--myio-border-offline), var(--myio-card-shadow);
@@ -4458,6 +4523,37 @@ var CSS_STRING = `
4458
4523
  color: var(--myio-chip-offline-fg);
4459
4524
  }
4460
4525
 
4526
+ /* New chip classes aligned with getCardStateClass */
4527
+ .chip--power-on {
4528
+ background: var(--myio-chip-ok-bg);
4529
+ color: var(--myio-chip-ok-fg);
4530
+ }
4531
+
4532
+ .chip--warning {
4533
+ background: var(--myio-chip-alert-bg);
4534
+ color: var(--myio-chip-alert-fg);
4535
+ }
4536
+
4537
+ .chip--maintenance {
4538
+ background: var(--myio-chip-alert-bg);
4539
+ color: var(--myio-chip-alert-fg);
4540
+ }
4541
+
4542
+ .chip--power-off {
4543
+ background: var(--myio-chip-power-off-bg);
4544
+ color: var(--myio-chip-power-off-fg);
4545
+ }
4546
+
4547
+ .chip--no-info {
4548
+ background: var(--myio-chip-no-info-bg);
4549
+ color: var(--myio-chip-no-info-fg);
4550
+ }
4551
+
4552
+ .chip--not-installed {
4553
+ background: var(--myio-chip-not-installed-bg);
4554
+ color: var(--myio-chip-not-installed-fg);
4555
+ }
4556
+
4461
4557
  /* Status indicator dot for power metric */
4462
4558
  .status-dot {
4463
4559
  width: 8px;
@@ -4491,6 +4587,31 @@ var CSS_STRING = `
4491
4587
  background: var(--myio-muted);
4492
4588
  }
4493
4589
 
4590
+ /* New dot classes aligned with getCardStateClass */
4591
+ .status-dot.dot--power-on {
4592
+ background: var(--myio-chip-ok-fg);
4593
+ }
4594
+
4595
+ .status-dot.dot--warning {
4596
+ background: var(--myio-chip-alert-fg);
4597
+ }
4598
+
4599
+ .status-dot.dot--maintenance {
4600
+ background: var(--myio-chip-alert-fg);
4601
+ }
4602
+
4603
+ .status-dot.dot--power-off {
4604
+ background: var(--myio-chip-power-off-fg);
4605
+ }
4606
+
4607
+ .status-dot.dot--no-info {
4608
+ background: var(--myio-chip-no-info-fg);
4609
+ }
4610
+
4611
+ .status-dot.dot--not-installed {
4612
+ background: var(--myio-chip-not-installed-fg);
4613
+ }
4614
+
4494
4615
  /* Primary metric */
4495
4616
  .myio-ho-card__primary {
4496
4617
  margin-bottom: 14px;
@@ -4673,6 +4794,215 @@ var CSS_STRING = `
4673
4794
  transition: none;
4674
4795
  }
4675
4796
  }
4797
+
4798
+ /* ============================================
4799
+ DEBUG TOOLTIP STYLES (Premium)
4800
+ ============================================ */
4801
+
4802
+ .has-debug-tooltip {
4803
+ cursor: help !important;
4804
+ }
4805
+
4806
+ .has-debug-tooltip::after {
4807
+ content: '\u{1F41B}';
4808
+ position: absolute;
4809
+ top: -4px;
4810
+ right: -4px;
4811
+ font-size: 10px;
4812
+ z-index: 1;
4813
+ }
4814
+
4815
+ .debug-tooltip-container {
4816
+ position: absolute;
4817
+ bottom: calc(100% + 8px);
4818
+ left: 50%;
4819
+ transform: translateX(-50%);
4820
+ z-index: 10000;
4821
+ pointer-events: none;
4822
+ opacity: 0;
4823
+ transition: opacity 0.2s ease, transform 0.2s ease;
4824
+ }
4825
+
4826
+ .has-debug-tooltip:hover .debug-tooltip-container {
4827
+ opacity: 1;
4828
+ pointer-events: auto;
4829
+ }
4830
+
4831
+ .debug-tooltip {
4832
+ background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%);
4833
+ border: 1px solid rgba(99, 102, 241, 0.3);
4834
+ border-radius: 12px;
4835
+ box-shadow:
4836
+ 0 20px 40px rgba(0, 0, 0, 0.4),
4837
+ 0 0 0 1px rgba(255, 255, 255, 0.05),
4838
+ inset 0 1px 0 rgba(255, 255, 255, 0.1);
4839
+ min-width: 340px;
4840
+ max-width: 420px;
4841
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
4842
+ font-size: 12px;
4843
+ color: #e2e8f0;
4844
+ overflow: hidden;
4845
+ }
4846
+
4847
+ .debug-tooltip__header {
4848
+ display: flex;
4849
+ align-items: center;
4850
+ gap: 8px;
4851
+ padding: 12px 16px;
4852
+ background: linear-gradient(90deg, rgba(99, 102, 241, 0.2) 0%, rgba(139, 92, 246, 0.1) 100%);
4853
+ border-bottom: 1px solid rgba(99, 102, 241, 0.2);
4854
+ }
4855
+
4856
+ .debug-tooltip__icon {
4857
+ font-size: 16px;
4858
+ }
4859
+
4860
+ .debug-tooltip__title {
4861
+ font-weight: 700;
4862
+ font-size: 13px;
4863
+ color: #f1f5f9;
4864
+ letter-spacing: 0.5px;
4865
+ text-transform: uppercase;
4866
+ }
4867
+
4868
+ .debug-tooltip__content {
4869
+ padding: 12px 16px;
4870
+ max-height: 400px;
4871
+ overflow-y: auto;
4872
+ }
4873
+
4874
+ .debug-tooltip__section {
4875
+ margin-bottom: 14px;
4876
+ padding-bottom: 12px;
4877
+ border-bottom: 1px solid rgba(148, 163, 184, 0.1);
4878
+ }
4879
+
4880
+ .debug-tooltip__section:last-child {
4881
+ margin-bottom: 0;
4882
+ padding-bottom: 0;
4883
+ border-bottom: none;
4884
+ }
4885
+
4886
+ .debug-tooltip__section-title {
4887
+ font-size: 11px;
4888
+ font-weight: 600;
4889
+ color: #94a3b8;
4890
+ text-transform: uppercase;
4891
+ letter-spacing: 0.8px;
4892
+ margin-bottom: 10px;
4893
+ display: flex;
4894
+ align-items: center;
4895
+ gap: 6px;
4896
+ }
4897
+
4898
+ .debug-tooltip__row {
4899
+ display: flex;
4900
+ justify-content: space-between;
4901
+ align-items: flex-start;
4902
+ padding: 4px 0;
4903
+ gap: 12px;
4904
+ }
4905
+
4906
+ .debug-tooltip__row--full {
4907
+ flex-direction: column;
4908
+ gap: 4px;
4909
+ }
4910
+
4911
+ .debug-tooltip__label {
4912
+ color: #94a3b8;
4913
+ font-size: 11px;
4914
+ flex-shrink: 0;
4915
+ }
4916
+
4917
+ .debug-tooltip__value {
4918
+ color: #f1f5f9;
4919
+ font-weight: 500;
4920
+ text-align: right;
4921
+ word-break: break-all;
4922
+ }
4923
+
4924
+ .debug-tooltip__row--full .debug-tooltip__value {
4925
+ text-align: left;
4926
+ background: rgba(0, 0, 0, 0.3);
4927
+ padding: 6px 10px;
4928
+ border-radius: 6px;
4929
+ font-size: 11px;
4930
+ width: 100%;
4931
+ box-sizing: border-box;
4932
+ }
4933
+
4934
+ .debug-tooltip__value--mono {
4935
+ font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace;
4936
+ font-size: 11px;
4937
+ background: rgba(0, 0, 0, 0.3);
4938
+ padding: 2px 6px;
4939
+ border-radius: 4px;
4940
+ }
4941
+
4942
+ .debug-tooltip__value--highlight {
4943
+ color: #a5b4fc;
4944
+ font-style: italic;
4945
+ }
4946
+
4947
+ .debug-tooltip__badge {
4948
+ display: inline-block;
4949
+ padding: 2px 8px;
4950
+ border-radius: 4px;
4951
+ font-size: 10px;
4952
+ font-weight: 600;
4953
+ text-transform: uppercase;
4954
+ letter-spacing: 0.5px;
4955
+ background: rgba(99, 102, 241, 0.3);
4956
+ color: #a5b4fc;
4957
+ }
4958
+
4959
+ .debug-tooltip__badge--energy {
4960
+ background: rgba(59, 130, 246, 0.3);
4961
+ color: #93c5fd;
4962
+ }
4963
+
4964
+ .debug-tooltip__badge--water {
4965
+ background: rgba(6, 182, 212, 0.3);
4966
+ color: #67e8f9;
4967
+ }
4968
+
4969
+ .debug-tooltip__badge--temperature {
4970
+ background: rgba(249, 115, 22, 0.3);
4971
+ color: #fdba74;
4972
+ }
4973
+
4974
+ /* Tooltip arrow */
4975
+ .debug-tooltip::after {
4976
+ content: '';
4977
+ position: absolute;
4978
+ bottom: -6px;
4979
+ left: 50%;
4980
+ transform: translateX(-50%) rotate(45deg);
4981
+ width: 12px;
4982
+ height: 12px;
4983
+ background: #0f172a;
4984
+ border-right: 1px solid rgba(99, 102, 241, 0.3);
4985
+ border-bottom: 1px solid rgba(99, 102, 241, 0.3);
4986
+ }
4987
+
4988
+ /* Scrollbar styling for tooltip content */
4989
+ .debug-tooltip__content::-webkit-scrollbar {
4990
+ width: 6px;
4991
+ }
4992
+
4993
+ .debug-tooltip__content::-webkit-scrollbar-track {
4994
+ background: rgba(0, 0, 0, 0.2);
4995
+ border-radius: 3px;
4996
+ }
4997
+
4998
+ .debug-tooltip__content::-webkit-scrollbar-thumb {
4999
+ background: rgba(99, 102, 241, 0.4);
5000
+ border-radius: 3px;
5001
+ }
5002
+
5003
+ .debug-tooltip__content::-webkit-scrollbar-thumb:hover {
5004
+ background: rgba(99, 102, 241, 0.6);
5005
+ }
4676
5006
  `;
4677
5007
 
4678
5008
  // src/thingsboard/main-dashboard-shopping/v-4.0.0/head-office/card-head-office.icons.ts
@@ -4827,7 +5157,246 @@ var DEFAULT_I18N = {
4827
5157
  menu_settings: "Configura\xE7\xF5es"
4828
5158
  };
4829
5159
 
5160
+ // src/components/temperature/utils.ts
5161
+ var DAY_PERIODS = [
5162
+ { id: "madrugada", label: "Madrugada (00h-06h)", startHour: 0, endHour: 6 },
5163
+ { id: "manha", label: "Manh\xE3 (06h-12h)", startHour: 6, endHour: 12 },
5164
+ { id: "tarde", label: "Tarde (12h-18h)", startHour: 12, endHour: 18 },
5165
+ { id: "noite", label: "Noite (18h-24h)", startHour: 18, endHour: 24 }
5166
+ ];
5167
+ var DEFAULT_CLAMP_RANGE = { min: 15, max: 40 };
5168
+ function getTodaySoFar() {
5169
+ const now = /* @__PURE__ */ new Date();
5170
+ const startOfDay = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0, 0);
5171
+ return {
5172
+ startTs: startOfDay.getTime(),
5173
+ endTs: now.getTime()
5174
+ };
5175
+ }
5176
+ var CHART_COLORS = [
5177
+ "#1976d2",
5178
+ // Blue
5179
+ "#FF6B6B",
5180
+ // Red
5181
+ "#4CAF50",
5182
+ // Green
5183
+ "#FF9800",
5184
+ // Orange
5185
+ "#9C27B0",
5186
+ // Purple
5187
+ "#00BCD4",
5188
+ // Cyan
5189
+ "#E91E63",
5190
+ // Pink
5191
+ "#795548"
5192
+ // Brown
5193
+ ];
5194
+ async function fetchTemperatureData(token, deviceId, startTs, endTs) {
5195
+ const url = `/api/plugins/telemetry/DEVICE/${deviceId}/values/timeseries?keys=temperature&startTs=${encodeURIComponent(startTs)}&endTs=${encodeURIComponent(endTs)}&limit=50000&agg=NONE`;
5196
+ const response = await fetch(url, {
5197
+ headers: {
5198
+ "X-Authorization": `Bearer ${token}`,
5199
+ "Content-Type": "application/json"
5200
+ }
5201
+ });
5202
+ if (!response.ok) {
5203
+ throw new Error(`Failed to fetch temperature data: ${response.status}`);
5204
+ }
5205
+ const data = await response.json();
5206
+ return data?.temperature || [];
5207
+ }
5208
+ function clampTemperature(value, range = DEFAULT_CLAMP_RANGE) {
5209
+ const num = Number(value || 0);
5210
+ if (num < range.min) return range.min;
5211
+ if (num > range.max) return range.max;
5212
+ return num;
5213
+ }
5214
+ function calculateStats(data, clampRange = DEFAULT_CLAMP_RANGE) {
5215
+ if (data.length === 0) {
5216
+ return { avg: 0, min: 0, max: 0, count: 0 };
5217
+ }
5218
+ const values = data.map((item) => clampTemperature(item.value, clampRange));
5219
+ const sum = values.reduce((acc, v) => acc + v, 0);
5220
+ return {
5221
+ avg: sum / values.length,
5222
+ min: Math.min(...values),
5223
+ max: Math.max(...values),
5224
+ count: values.length
5225
+ };
5226
+ }
5227
+ function interpolateTemperature(data, options) {
5228
+ const { intervalMinutes, startTs, endTs, clampRange = DEFAULT_CLAMP_RANGE } = options;
5229
+ const intervalMs = intervalMinutes * 60 * 1e3;
5230
+ if (data.length === 0) {
5231
+ return [];
5232
+ }
5233
+ const sortedData = [...data].sort((a, b) => a.ts - b.ts);
5234
+ const result = [];
5235
+ let lastKnownValue = clampTemperature(sortedData[0].value, clampRange);
5236
+ let dataIndex = 0;
5237
+ for (let ts = startTs; ts <= endTs; ts += intervalMs) {
5238
+ while (dataIndex < sortedData.length - 1 && sortedData[dataIndex + 1].ts <= ts) {
5239
+ dataIndex++;
5240
+ }
5241
+ const currentData = sortedData[dataIndex];
5242
+ if (currentData && Math.abs(currentData.ts - ts) < intervalMs) {
5243
+ lastKnownValue = clampTemperature(currentData.value, clampRange);
5244
+ }
5245
+ result.push({
5246
+ ts,
5247
+ value: lastKnownValue
5248
+ });
5249
+ }
5250
+ return result;
5251
+ }
5252
+ function aggregateByDay(data, clampRange = DEFAULT_CLAMP_RANGE) {
5253
+ if (data.length === 0) {
5254
+ return [];
5255
+ }
5256
+ const dayMap = /* @__PURE__ */ new Map();
5257
+ data.forEach((item) => {
5258
+ const date = new Date(item.ts);
5259
+ const dateKey = date.toISOString().split("T")[0];
5260
+ if (!dayMap.has(dateKey)) {
5261
+ dayMap.set(dateKey, []);
5262
+ }
5263
+ dayMap.get(dateKey).push(item);
5264
+ });
5265
+ const result = [];
5266
+ dayMap.forEach((dayData, dateKey) => {
5267
+ const values = dayData.map((item) => clampTemperature(item.value, clampRange));
5268
+ const sum = values.reduce((acc, v) => acc + v, 0);
5269
+ result.push({
5270
+ date: dateKey,
5271
+ dateTs: new Date(dateKey).getTime(),
5272
+ avg: sum / values.length,
5273
+ min: Math.min(...values),
5274
+ max: Math.max(...values),
5275
+ count: values.length
5276
+ });
5277
+ });
5278
+ return result.sort((a, b) => a.dateTs - b.dateTs);
5279
+ }
5280
+ function filterByDayPeriods(data, selectedPeriods) {
5281
+ if (selectedPeriods.length === 0 || selectedPeriods.length === DAY_PERIODS.length) {
5282
+ return data;
5283
+ }
5284
+ return data.filter((item) => {
5285
+ const date = new Date(item.ts);
5286
+ const hour = date.getHours();
5287
+ return selectedPeriods.some((periodId) => {
5288
+ const period = DAY_PERIODS.find((p) => p.id === periodId);
5289
+ if (!period) return false;
5290
+ return hour >= period.startHour && hour < period.endHour;
5291
+ });
5292
+ });
5293
+ }
5294
+ function getSelectedPeriodsLabel(selectedPeriods) {
5295
+ if (selectedPeriods.length === 0 || selectedPeriods.length === DAY_PERIODS.length) {
5296
+ return "Todos os per\xEDodos";
5297
+ }
5298
+ if (selectedPeriods.length === 1) {
5299
+ const period = DAY_PERIODS.find((p) => p.id === selectedPeriods[0]);
5300
+ return period?.label || "";
5301
+ }
5302
+ return `${selectedPeriods.length} per\xEDodos selecionados`;
5303
+ }
5304
+ function formatTemperature(value, decimals = 1) {
5305
+ if (value === null || value === void 0 || isNaN(value)) {
5306
+ return "\u2014";
5307
+ }
5308
+ return `${value.toFixed(decimals)}\xB0C`;
5309
+ }
5310
+ function exportTemperatureCSV(data, deviceLabel, stats, startDate, endDate) {
5311
+ if (data.length === 0) {
5312
+ console.warn("No data to export");
5313
+ return;
5314
+ }
5315
+ const BOM = "\uFEFF";
5316
+ let csvContent = BOM;
5317
+ csvContent += `Relat\xF3rio de Temperatura - ${deviceLabel}
5318
+ `;
5319
+ csvContent += `Per\xEDodo: ${startDate} at\xE9 ${endDate}
5320
+ `;
5321
+ csvContent += `M\xE9dia: ${formatTemperature(stats.avg)}
5322
+ `;
5323
+ csvContent += `M\xEDnima: ${formatTemperature(stats.min)}
5324
+ `;
5325
+ csvContent += `M\xE1xima: ${formatTemperature(stats.max)}
5326
+ `;
5327
+ csvContent += `Total de leituras: ${stats.count}
5328
+ `;
5329
+ csvContent += "\n";
5330
+ csvContent += "Data/Hora,Temperatura (\xB0C)\n";
5331
+ data.forEach((item) => {
5332
+ const date = new Date(item.ts).toLocaleString("pt-BR");
5333
+ const temp = Number(item.value).toFixed(2);
5334
+ csvContent += `"${date}",${temp}
5335
+ `;
5336
+ });
5337
+ const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" });
5338
+ const url = URL.createObjectURL(blob);
5339
+ const link = document.createElement("a");
5340
+ link.href = url;
5341
+ link.download = `temperatura_${deviceLabel.replace(/\s+/g, "_")}_${startDate}_${endDate}.csv`;
5342
+ document.body.appendChild(link);
5343
+ link.click();
5344
+ document.body.removeChild(link);
5345
+ URL.revokeObjectURL(url);
5346
+ }
5347
+ var DARK_THEME = {
5348
+ background: "rgba(0, 0, 0, 0.85)",
5349
+ surface: "#1a1f28",
5350
+ text: "#ffffff",
5351
+ textMuted: "rgba(255, 255, 255, 0.7)",
5352
+ border: "rgba(255, 255, 255, 0.1)",
5353
+ primary: "#1976d2",
5354
+ success: "#4CAF50",
5355
+ warning: "#FF9800",
5356
+ danger: "#f44336",
5357
+ chartLine: "#1976d2",
5358
+ chartGrid: "rgba(255, 255, 255, 0.1)"
5359
+ };
5360
+ var LIGHT_THEME = {
5361
+ background: "rgba(0, 0, 0, 0.6)",
5362
+ surface: "#ffffff",
5363
+ text: "#333333",
5364
+ textMuted: "#666666",
5365
+ border: "#e0e0e0",
5366
+ primary: "#1976d2",
5367
+ success: "#4CAF50",
5368
+ warning: "#FF9800",
5369
+ danger: "#f44336",
5370
+ chartLine: "#1976d2",
5371
+ chartGrid: "#e0e0e0"
5372
+ };
5373
+ function getThemeColors(theme) {
5374
+ return theme === "dark" ? DARK_THEME : LIGHT_THEME;
5375
+ }
5376
+
5377
+ // src/utils/logHelper.js
5378
+ function createLogHelper(debugActive = false) {
5379
+ return {
5380
+ log: function(...args) {
5381
+ if (debugActive) {
5382
+ console.log(...args);
5383
+ }
5384
+ },
5385
+ warn: function(...args) {
5386
+ if (debugActive) {
5387
+ console.warn(...args);
5388
+ }
5389
+ },
5390
+ error: function(...args) {
5391
+ console.error(...args);
5392
+ }
5393
+ };
5394
+ }
5395
+ var LogHelper = createLogHelper(false);
5396
+
4830
5397
  // src/thingsboard/main-dashboard-shopping/v-4.0.0/card/head-office/card-head-office.js
5398
+ var LABEL_CHAR_LIMIT = 18;
5399
+ var DEFAUL_DELAY_TIME_CONNECTION_IN_MINS = 1440;
4831
5400
  var CSS_TAG = "head-office-card-v1";
4832
5401
  function ensureCss() {
4833
5402
  if (!document.querySelector(`style[data-myio-css="${CSS_TAG}"]`)) {
@@ -4841,11 +5410,17 @@ function normalizeParams(params) {
4841
5410
  if (!params || !params.entityObject) {
4842
5411
  throw new Error("renderCardCompenteHeadOffice: entityObject is required");
4843
5412
  }
5413
+ const LogHelper2 = createLogHelper(params.debugActive ?? false);
4844
5414
  const entityObject = params.entityObject;
4845
5415
  if (!entityObject.entityId) {
4846
- console.warn("renderCardCompenteHeadOffice: entityId is missing, generating temporary ID");
5416
+ LogHelper2.warn("[CardHeadOffice] entityId is missing, generating temporary ID");
4847
5417
  entityObject.entityId = `temp-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
4848
5418
  }
5419
+ if (!params.delayTimeConnectionInMins) {
5420
+ LogHelper2.warn(
5421
+ `[CardHeadOffice] delayTimeConnectionInMins is missing, defaulting to ${DEFAUL_DELAY_TIME_CONNECTION_IN_MINS} mins`
5422
+ );
5423
+ }
4849
5424
  return {
4850
5425
  entityObject,
4851
5426
  i18n: { ...DEFAULT_I18N, ...params.i18n || {} },
@@ -4853,7 +5428,12 @@ function normalizeParams(params) {
4853
5428
  enableDragDrop: Boolean(params.enableDragDrop),
4854
5429
  useNewComponents: Boolean(params.useNewComponents),
4855
5430
  // RFC-0091: Configurable delay time for connection status check (default 15 minutes)
4856
- delayTimeConnectionInMins: params.delayTimeConnectionInMins ?? 15,
5431
+ delayTimeConnectionInMins: params.delayTimeConnectionInMins ?? DEFAUL_DELAY_TIME_CONNECTION_IN_MINS,
5432
+ // Debug options
5433
+ debugActive: params.debugActive ?? false,
5434
+ activeTooltipDebug: params.activeTooltipDebug ?? false,
5435
+ // LogHelper instance for this card
5436
+ LogHelper: LogHelper2,
4857
5437
  callbacks: {
4858
5438
  handleActionDashboard: params.handleActionDashboard,
4859
5439
  handleActionReport: params.handleActionReport,
@@ -4891,16 +5471,10 @@ function formatValueByDomain(value, domain) {
4891
5471
  return formatWaterVolumeM3(value);
4892
5472
  }
4893
5473
  if (domain === "temperature") {
4894
- return formatTemperature(value);
5474
+ return formatTemperature(value, 0);
4895
5475
  }
4896
5476
  return formatEnergy(value);
4897
5477
  }
4898
- function formatTemperature(temp) {
4899
- if (temp === null || temp === void 0 || isNaN(temp)) {
4900
- return "\u2014";
4901
- }
4902
- return `${temp.toFixed(0)}\xB0C`;
4903
- }
4904
5478
  function calculateConsumptionPercentage(target, consumption) {
4905
5479
  const numericTarget = Number(target);
4906
5480
  const numericConsumption = Number(consumption);
@@ -4915,32 +5489,32 @@ function getStatusInfo(deviceStatus, i18n, domain) {
4915
5489
  // --- Novos Status de Temperatura ---
4916
5490
  case "normal":
4917
5491
  return { chipClass: "chip--ok", label: "Normal" };
4918
- // Verde/Azul
4919
5492
  case "cold":
4920
5493
  return { chipClass: "chip--standby", label: "Frio" };
4921
- // Azul claro/Ciano
4922
5494
  case "hot":
4923
5495
  return { chipClass: "chip--alert", label: "Quente" };
4924
- // Laranja/Amarelo
4925
- // --- Status Existentes ---
5496
+ // --- Status Existentes (aligned with getCardStateClass) ---
4926
5497
  case DeviceStatusType.POWER_ON:
4927
5498
  if (domain === "water") {
4928
- return { chipClass: "chip--ok", label: i18n.in_operation_water };
5499
+ return { chipClass: "chip--power-on", label: i18n.in_operation_water };
4929
5500
  }
4930
- return { chipClass: "chip--ok", label: i18n.in_operation };
5501
+ return { chipClass: "chip--power-on", label: i18n.in_operation };
4931
5502
  case DeviceStatusType.STANDBY:
4932
5503
  return { chipClass: "chip--standby", label: i18n.standby };
4933
5504
  case DeviceStatusType.WARNING:
4934
- return { chipClass: "chip--alert", label: i18n.alert };
5505
+ return { chipClass: "chip--warning", label: i18n.alert };
5506
+ case DeviceStatusType.MAINTENANCE:
5507
+ return { chipClass: "chip--maintenance", label: i18n.maintenance };
4935
5508
  case DeviceStatusType.FAILURE:
4936
- case DeviceStatusType.POWER_OFF:
4937
5509
  return { chipClass: "chip--failure", label: i18n.failure };
4938
- case DeviceStatusType.MAINTENANCE:
4939
- return { chipClass: "chip--alert", label: i18n.maintenance };
4940
- case DeviceStatusType.NOT_INSTALLED:
4941
- return { chipClass: "chip--offline", label: i18n.not_installed };
4942
- // Default (Cai aqui se não achar 'normal', 'hot' etc)
5510
+ case DeviceStatusType.POWER_OFF:
5511
+ return { chipClass: "chip--power-off", label: i18n.power_off || i18n.failure };
5512
+ case DeviceStatusType.OFFLINE:
5513
+ return { chipClass: "chip--offline", label: i18n.offline };
4943
5514
  case DeviceStatusType.NO_INFO:
5515
+ return { chipClass: "chip--no-info", label: i18n.no_info || i18n.offline };
5516
+ case DeviceStatusType.NOT_INSTALLED:
5517
+ return { chipClass: "chip--not-installed", label: i18n.not_installed };
4944
5518
  default:
4945
5519
  return { chipClass: "chip--offline", label: i18n.offline };
4946
5520
  }
@@ -4948,23 +5522,32 @@ function getStatusInfo(deviceStatus, i18n, domain) {
4948
5522
  function getCardStateClass(deviceStatus) {
4949
5523
  switch (deviceStatus) {
4950
5524
  case DeviceStatusType.POWER_ON:
4951
- return "is-ok";
5525
+ return "is-power-on";
4952
5526
  // Blue border
4953
5527
  case DeviceStatusType.STANDBY:
4954
5528
  return "is-standby";
4955
5529
  // Green border
4956
5530
  case DeviceStatusType.WARNING:
5531
+ return "is-warning";
5532
+ // Yellow border
4957
5533
  case DeviceStatusType.MAINTENANCE:
4958
- return "is-alert";
5534
+ return "is-maintenance";
4959
5535
  // Yellow border
4960
5536
  case DeviceStatusType.FAILURE:
4961
- case DeviceStatusType.POWER_OFF:
4962
5537
  return "is-failure";
4963
- // Red border
5538
+ // Dark Red border
5539
+ case DeviceStatusType.POWER_OFF:
5540
+ return "is-power-off";
5541
+ // Light Red border
5542
+ case DeviceStatusType.OFFLINE:
5543
+ return "is-offline";
5544
+ // Dark Gray border
4964
5545
  case DeviceStatusType.NO_INFO:
5546
+ return "is-no-info";
5547
+ // Dark Orange border
4965
5548
  case DeviceStatusType.NOT_INSTALLED:
4966
- return "is-offline";
4967
- // Gray border
5549
+ return "is-not-installed";
5550
+ // Purple border
4968
5551
  default:
4969
5552
  return "";
4970
5553
  }
@@ -4978,17 +5561,25 @@ function getStatusDotClass(deviceStatus) {
4978
5561
  return "dot--standby";
4979
5562
  case "hot":
4980
5563
  return "dot--alert";
4981
- // --- Status Existentes ---
5564
+ // --- Status Existentes (aligned with getCardStateClass) ---
4982
5565
  case DeviceStatusType.POWER_ON:
4983
- return "dot--ok";
5566
+ return "dot--power-on";
4984
5567
  case DeviceStatusType.STANDBY:
4985
5568
  return "dot--standby";
4986
5569
  case DeviceStatusType.WARNING:
5570
+ return "dot--warning";
4987
5571
  case DeviceStatusType.MAINTENANCE:
4988
- return "dot--alert";
5572
+ return "dot--maintenance";
4989
5573
  case DeviceStatusType.FAILURE:
4990
- case DeviceStatusType.POWER_OFF:
4991
5574
  return "dot--failure";
5575
+ case DeviceStatusType.POWER_OFF:
5576
+ return "dot--power-off";
5577
+ case DeviceStatusType.OFFLINE:
5578
+ return "dot--offline";
5579
+ case DeviceStatusType.NO_INFO:
5580
+ return "dot--no-info";
5581
+ case DeviceStatusType.NOT_INSTALLED:
5582
+ return "dot--not-installed";
4992
5583
  default:
4993
5584
  return "dot--offline";
4994
5585
  }
@@ -5012,7 +5603,13 @@ function buildDOM(state) {
5012
5603
  titleSection.className = "myio-ho-card__title";
5013
5604
  const nameEl = document.createElement("div");
5014
5605
  nameEl.className = "myio-ho-card__name";
5015
- nameEl.textContent = entityObject.labelOrName || "Unknown Device";
5606
+ const fullName = entityObject.labelOrName || "Unknown Device";
5607
+ if (fullName.length > LABEL_CHAR_LIMIT) {
5608
+ nameEl.textContent = fullName.slice(0, LABEL_CHAR_LIMIT) + "\u2026";
5609
+ nameEl.title = fullName;
5610
+ } else {
5611
+ nameEl.textContent = fullName;
5612
+ }
5016
5613
  titleSection.appendChild(nameEl);
5017
5614
  if (entityObject.deviceIdentifier) {
5018
5615
  const codeEl = document.createElement("div");
@@ -5141,29 +5738,207 @@ function buildDOM(state) {
5141
5738
  root.appendChild(footer);
5142
5739
  return root;
5143
5740
  }
5144
- function verifyOfflineStatus(entityObject, delayTimeInMins = 15) {
5741
+ function buildDebugTooltipInfo(entityObject, statusInfo, stateClass, statusDecisionSource, delayTimeConnectionInMins) {
5742
+ const formatTimestamp = (ts) => {
5743
+ if (!ts) return "N/A";
5744
+ const d = new Date(ts);
5745
+ return d.toLocaleString("pt-BR", {
5746
+ day: "2-digit",
5747
+ month: "2-digit",
5748
+ year: "numeric",
5749
+ hour: "2-digit",
5750
+ minute: "2-digit",
5751
+ second: "2-digit"
5752
+ });
5753
+ };
5754
+ return {
5755
+ // Entity identification
5756
+ entityId: entityObject.entityId || "N/A",
5757
+ name: entityObject.name || entityObject.nameEl || "N/A",
5758
+ domain: entityObject.domain || "energy",
5759
+ // Status decision chain
5760
+ originalDeviceStatus: entityObject._originalDeviceStatus || entityObject.deviceStatus,
5761
+ finalDeviceStatus: entityObject.deviceStatus,
5762
+ connectionStatus: entityObject.connectionStatus || "N/A",
5763
+ statusDecisionSource,
5764
+ // Visual output
5765
+ stateClass,
5766
+ chipClass: statusInfo.chipClass,
5767
+ chipLabel: statusInfo.label,
5768
+ // Connection timestamps
5769
+ lastConnectTime: formatTimestamp(entityObject.lastConnectTime),
5770
+ lastDisconnectTime: formatTimestamp(entityObject.lastDisconnectTime),
5771
+ delayTimeConnectionInMins,
5772
+ // Raw values
5773
+ val: entityObject.val,
5774
+ consumptionTargetValue: entityObject.consumptionTargetValue,
5775
+ deviceType: entityObject.deviceType || "N/A"
5776
+ };
5777
+ }
5778
+ function attachDebugTooltip(element, debugInfo) {
5779
+ const existingTooltip = element.querySelector(".debug-tooltip-container");
5780
+ if (existingTooltip) {
5781
+ existingTooltip.remove();
5782
+ }
5783
+ const tooltipContainer = document.createElement("div");
5784
+ tooltipContainer.className = "debug-tooltip-container";
5785
+ const tooltip = document.createElement("div");
5786
+ tooltip.className = "debug-tooltip";
5787
+ tooltip.innerHTML = `
5788
+ <div class="debug-tooltip__header">
5789
+ <span class="debug-tooltip__icon">\u{1F50D}</span>
5790
+ <span class="debug-tooltip__title">Debug Info</span>
5791
+ </div>
5792
+ <div class="debug-tooltip__content">
5793
+ <div class="debug-tooltip__section">
5794
+ <div class="debug-tooltip__section-title">\u{1F4CB} Identifica\xE7\xE3o</div>
5795
+ <div class="debug-tooltip__row">
5796
+ <span class="debug-tooltip__label">Entity ID:</span>
5797
+ <span class="debug-tooltip__value debug-tooltip__value--mono">${debugInfo.entityId}</span>
5798
+ </div>
5799
+ <div class="debug-tooltip__row">
5800
+ <span class="debug-tooltip__label">Nome:</span>
5801
+ <span class="debug-tooltip__value">${debugInfo.name}</span>
5802
+ </div>
5803
+ <div class="debug-tooltip__row">
5804
+ <span class="debug-tooltip__label">Dom\xEDnio:</span>
5805
+ <span class="debug-tooltip__value debug-tooltip__badge debug-tooltip__badge--${debugInfo.domain}">${debugInfo.domain}</span>
5806
+ </div>
5807
+ </div>
5808
+
5809
+ <div class="debug-tooltip__section">
5810
+ <div class="debug-tooltip__section-title">\u26A1 Decis\xE3o de Status</div>
5811
+ <div class="debug-tooltip__row">
5812
+ <span class="debug-tooltip__label">connectionStatus:</span>
5813
+ <span class="debug-tooltip__value debug-tooltip__value--mono">${debugInfo.connectionStatus}</span>
5814
+ </div>
5815
+ <div class="debug-tooltip__row">
5816
+ <span class="debug-tooltip__label">deviceStatus (final):</span>
5817
+ <span class="debug-tooltip__value debug-tooltip__badge">${debugInfo.finalDeviceStatus}</span>
5818
+ </div>
5819
+ <div class="debug-tooltip__row debug-tooltip__row--full">
5820
+ <span class="debug-tooltip__label">Fonte da decis\xE3o:</span>
5821
+ <span class="debug-tooltip__value debug-tooltip__value--highlight">${debugInfo.statusDecisionSource}</span>
5822
+ </div>
5823
+ </div>
5824
+
5825
+ <div class="debug-tooltip__section">
5826
+ <div class="debug-tooltip__section-title">\u{1F3A8} Output Visual</div>
5827
+ <div class="debug-tooltip__row">
5828
+ <span class="debug-tooltip__label">stateClass:</span>
5829
+ <span class="debug-tooltip__value debug-tooltip__value--mono">${debugInfo.stateClass}</span>
5830
+ </div>
5831
+ <div class="debug-tooltip__row">
5832
+ <span class="debug-tooltip__label">chipClass:</span>
5833
+ <span class="debug-tooltip__value debug-tooltip__value--mono">${debugInfo.chipClass}</span>
5834
+ </div>
5835
+ <div class="debug-tooltip__row">
5836
+ <span class="debug-tooltip__label">chipLabel:</span>
5837
+ <span class="debug-tooltip__value">${debugInfo.chipLabel}</span>
5838
+ </div>
5839
+ </div>
5840
+
5841
+ <div class="debug-tooltip__section">
5842
+ <div class="debug-tooltip__section-title">\u{1F550} Timestamps de Conex\xE3o</div>
5843
+ <div class="debug-tooltip__row">
5844
+ <span class="debug-tooltip__label">lastConnectTime:</span>
5845
+ <span class="debug-tooltip__value debug-tooltip__value--mono">${debugInfo.lastConnectTime}</span>
5846
+ </div>
5847
+ <div class="debug-tooltip__row">
5848
+ <span class="debug-tooltip__label">lastDisconnectTime:</span>
5849
+ <span class="debug-tooltip__value debug-tooltip__value--mono">${debugInfo.lastDisconnectTime}</span>
5850
+ </div>
5851
+ <div class="debug-tooltip__row">
5852
+ <span class="debug-tooltip__label">delayTime:</span>
5853
+ <span class="debug-tooltip__value">${debugInfo.delayTimeConnectionInMins} mins</span>
5854
+ </div>
5855
+ </div>
5856
+
5857
+ <div class="debug-tooltip__section">
5858
+ <div class="debug-tooltip__section-title">\u{1F4CA} Valores</div>
5859
+ <div class="debug-tooltip__row">
5860
+ <span class="debug-tooltip__label">val (consumo):</span>
5861
+ <span class="debug-tooltip__value">${debugInfo.val ?? "N/A"}</span>
5862
+ </div>
5863
+ <div class="debug-tooltip__row">
5864
+ <span class="debug-tooltip__label">target (meta):</span>
5865
+ <span class="debug-tooltip__value">${debugInfo.consumptionTargetValue ?? "N/A"}</span>
5866
+ </div>
5867
+ <div class="debug-tooltip__row">
5868
+ <span class="debug-tooltip__label">deviceType:</span>
5869
+ <span class="debug-tooltip__value debug-tooltip__value--mono">${debugInfo.deviceType}</span>
5870
+ </div>
5871
+ </div>
5872
+ </div>
5873
+ `;
5874
+ tooltipContainer.appendChild(tooltip);
5875
+ element.style.position = "relative";
5876
+ element.style.cursor = "help";
5877
+ element.appendChild(tooltipContainer);
5878
+ element.classList.add("has-debug-tooltip");
5879
+ }
5880
+ function verifyOfflineStatus(entityObject, delayTimeInMins = 15, LogHelper2) {
5145
5881
  const lastConnectionTime = new Date(entityObject.lastConnectTime || 0);
5146
5882
  const lastDisconnectTime = new Date(entityObject.lastDisconnectTime || 0);
5147
5883
  const now = /* @__PURE__ */ new Date();
5148
5884
  const delayTimeInMs = delayTimeInMins * 60 * 1e3;
5149
5885
  const timeSinceConnection = now.getTime() - lastConnectionTime.getTime();
5886
+ let isOffline = false;
5150
5887
  if (lastDisconnectTime.getTime() > lastConnectionTime.getTime()) {
5151
- return false;
5152
- }
5153
- if (timeSinceConnection < delayTimeInMs) {
5154
- return false;
5888
+ isOffline = true;
5889
+ LogHelper2.log(
5890
+ "[CardHeadOffice][ConnectionStatus Verify] Device is OFFLINE because lastDisconnectTime is more recent than lastConnectTime",
5891
+ entityObject.nameEl
5892
+ );
5893
+ } else if (timeSinceConnection > delayTimeInMs) {
5894
+ isOffline = true;
5895
+ LogHelper2.log(
5896
+ "[CardHeadOffice][ConnectionStatus Verify] Device is OFFLINE because lastConnectTime is older than configured delayTimeConnectionInMins:",
5897
+ delayTimeInMins,
5898
+ "for device",
5899
+ entityObject.nameEl
5900
+ );
5901
+ } else {
5902
+ isOffline = false;
5903
+ LogHelper2.log(
5904
+ "[CardHeadOffice][ConnectionStatus Verify] Device is ONLINE because lastConnectTime is within configured delayTimeConnectionInMins:",
5905
+ delayTimeInMins,
5906
+ "for device",
5907
+ entityObject.nameEl
5908
+ );
5155
5909
  }
5156
- return true;
5910
+ return isOffline;
5157
5911
  }
5158
5912
  function paint(root, state) {
5159
- const { entityObject, i18n, delayTimeConnectionInMins, isSelected } = state;
5913
+ const { entityObject, i18n, delayTimeConnectionInMins, isSelected, LogHelper: LogHelper2, activeTooltipDebug } = state;
5914
+ let statusDecisionSource = "unknown";
5160
5915
  if (entityObject.connectionStatus) {
5161
5916
  if (entityObject.connectionStatus === "offline") {
5162
- entityObject.deviceStatus = DeviceStatusType.NO_INFO;
5917
+ LogHelper2.log(
5918
+ "[CardHeadOffice][ConnectionStatus Verify 01] Setting deviceStatus to OFFLINE based on connectionStatus"
5919
+ );
5920
+ entityObject.deviceStatus = DeviceStatusType.OFFLINE;
5921
+ statusDecisionSource = 'connectionStatus === "offline"';
5922
+ } else {
5923
+ LogHelper2.log(
5924
+ "[CardHeadOffice] Device is ONLINE or WAITING based on connectionStatus for device",
5925
+ entityObject.nameEl
5926
+ );
5927
+ statusDecisionSource = `connectionStatus === "${entityObject.connectionStatus}" (kept original deviceStatus)`;
5163
5928
  }
5164
5929
  } else {
5165
- if (verifyOfflineStatus(entityObject, delayTimeConnectionInMins) === false) {
5166
- entityObject.deviceStatus = DeviceStatusType.NO_INFO;
5930
+ if (verifyOfflineStatus(entityObject, delayTimeConnectionInMins, LogHelper2) === false) {
5931
+ LogHelper2.log(
5932
+ "[CardHeadOffice][ConnectionStatus Verify 02] Setting deviceStatus to OFFLINE based on timestamp verification by verifyOfflineStatus METHOD with delayTimeConnectionInMins:",
5933
+ delayTimeConnectionInMins
5934
+ );
5935
+ entityObject.deviceStatus = DeviceStatusType.OFFLINE;
5936
+ statusDecisionSource = `verifyOfflineStatus() returned false (delay: ${delayTimeConnectionInMins} mins)`;
5937
+ } else {
5938
+ LogHelper2.log(
5939
+ `[CardHeadOffice][ConnectionStatus Verify 03] Device is ONLINE with deviceStatus = ${entityObject.deviceStatus} based on timestamp verification for device ${entityObject.nameEl}`
5940
+ );
5941
+ statusDecisionSource = `verifyOfflineStatus() returned true (delay: ${delayTimeConnectionInMins} mins)`;
5167
5942
  }
5168
5943
  }
5169
5944
  const stateClass = getCardStateClass(entityObject.deviceStatus);
@@ -5172,6 +5947,10 @@ function paint(root, state) {
5172
5947
  const chip = root.querySelector(".chip");
5173
5948
  chip.className = `chip ${statusInfo.chipClass}`;
5174
5949
  chip.innerHTML = statusInfo.label;
5950
+ if (activeTooltipDebug) {
5951
+ const debugInfo = buildDebugTooltipInfo(entityObject, statusInfo, stateClass, statusDecisionSource, delayTimeConnectionInMins);
5952
+ attachDebugTooltip(chip, debugInfo);
5953
+ }
5175
5954
  const primaryValue = formatValueByDomain(entityObject.val, entityObject.domain);
5176
5955
  const numSpan = root.querySelector(".myio-ho-card__value .num");
5177
5956
  const unitSpan = root.querySelector(".myio-ho-card__value .unit");
@@ -5384,6 +6163,7 @@ function renderCardComponentHeadOffice(containerEl, params) {
5384
6163
  }
5385
6164
 
5386
6165
  // src/thingsboard/main-dashboard-shopping/v-5.2.0/card/template-card-v5.js
6166
+ var LABEL_CHAR_LIMIT2 = 18;
5387
6167
  function renderCardComponentV5({
5388
6168
  entityObject,
5389
6169
  handleActionDashboard,
@@ -5900,7 +6680,7 @@ ${rangeText}`;
5900
6680
 
5901
6681
  <div class="device-title-row" style="flex-direction: column; min-height: 38px; text-align: center; width: 100%;">
5902
6682
  <span class="device-title" title="${cardEntity.name}">
5903
- ${cardEntity.name.length > 18 ? cardEntity.name.slice(0, 18) + "\u2026" : cardEntity.name}
6683
+ ${cardEntity.name.length > LABEL_CHAR_LIMIT2 ? cardEntity.name.slice(0, LABEL_CHAR_LIMIT2) + "\u2026" : cardEntity.name}
5904
6684
  </span>
5905
6685
  ${deviceIdentifier ? `
5906
6686
  <span class="device-subtitle" title="${deviceIdentifier}">
@@ -20227,220 +21007,6 @@ function openGoalsPanel(params) {
20227
21007
  }
20228
21008
  }
20229
21009
 
20230
- // src/components/temperature/utils.ts
20231
- var DAY_PERIODS = [
20232
- { id: "madrugada", label: "Madrugada (00h-06h)", startHour: 0, endHour: 6 },
20233
- { id: "manha", label: "Manh\xE3 (06h-12h)", startHour: 6, endHour: 12 },
20234
- { id: "tarde", label: "Tarde (12h-18h)", startHour: 12, endHour: 18 },
20235
- { id: "noite", label: "Noite (18h-24h)", startHour: 18, endHour: 24 }
20236
- ];
20237
- var DEFAULT_CLAMP_RANGE = { min: 15, max: 40 };
20238
- function getTodaySoFar() {
20239
- const now = /* @__PURE__ */ new Date();
20240
- const startOfDay = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0, 0);
20241
- return {
20242
- startTs: startOfDay.getTime(),
20243
- endTs: now.getTime()
20244
- };
20245
- }
20246
- var CHART_COLORS = [
20247
- "#1976d2",
20248
- // Blue
20249
- "#FF6B6B",
20250
- // Red
20251
- "#4CAF50",
20252
- // Green
20253
- "#FF9800",
20254
- // Orange
20255
- "#9C27B0",
20256
- // Purple
20257
- "#00BCD4",
20258
- // Cyan
20259
- "#E91E63",
20260
- // Pink
20261
- "#795548"
20262
- // Brown
20263
- ];
20264
- async function fetchTemperatureData(token, deviceId, startTs, endTs) {
20265
- const url = `/api/plugins/telemetry/DEVICE/${deviceId}/values/timeseries?keys=temperature&startTs=${encodeURIComponent(startTs)}&endTs=${encodeURIComponent(endTs)}&limit=50000&agg=NONE`;
20266
- const response = await fetch(url, {
20267
- headers: {
20268
- "X-Authorization": `Bearer ${token}`,
20269
- "Content-Type": "application/json"
20270
- }
20271
- });
20272
- if (!response.ok) {
20273
- throw new Error(`Failed to fetch temperature data: ${response.status}`);
20274
- }
20275
- const data = await response.json();
20276
- return data?.temperature || [];
20277
- }
20278
- function clampTemperature(value, range = DEFAULT_CLAMP_RANGE) {
20279
- const num = Number(value || 0);
20280
- if (num < range.min) return range.min;
20281
- if (num > range.max) return range.max;
20282
- return num;
20283
- }
20284
- function calculateStats(data, clampRange = DEFAULT_CLAMP_RANGE) {
20285
- if (data.length === 0) {
20286
- return { avg: 0, min: 0, max: 0, count: 0 };
20287
- }
20288
- const values = data.map((item) => clampTemperature(item.value, clampRange));
20289
- const sum = values.reduce((acc, v) => acc + v, 0);
20290
- return {
20291
- avg: sum / values.length,
20292
- min: Math.min(...values),
20293
- max: Math.max(...values),
20294
- count: values.length
20295
- };
20296
- }
20297
- function interpolateTemperature(data, options) {
20298
- const { intervalMinutes, startTs, endTs, clampRange = DEFAULT_CLAMP_RANGE } = options;
20299
- const intervalMs = intervalMinutes * 60 * 1e3;
20300
- if (data.length === 0) {
20301
- return [];
20302
- }
20303
- const sortedData = [...data].sort((a, b) => a.ts - b.ts);
20304
- const result = [];
20305
- let lastKnownValue = clampTemperature(sortedData[0].value, clampRange);
20306
- let dataIndex = 0;
20307
- for (let ts = startTs; ts <= endTs; ts += intervalMs) {
20308
- while (dataIndex < sortedData.length - 1 && sortedData[dataIndex + 1].ts <= ts) {
20309
- dataIndex++;
20310
- }
20311
- const currentData = sortedData[dataIndex];
20312
- if (currentData && Math.abs(currentData.ts - ts) < intervalMs) {
20313
- lastKnownValue = clampTemperature(currentData.value, clampRange);
20314
- }
20315
- result.push({
20316
- ts,
20317
- value: lastKnownValue
20318
- });
20319
- }
20320
- return result;
20321
- }
20322
- function aggregateByDay(data, clampRange = DEFAULT_CLAMP_RANGE) {
20323
- if (data.length === 0) {
20324
- return [];
20325
- }
20326
- const dayMap = /* @__PURE__ */ new Map();
20327
- data.forEach((item) => {
20328
- const date = new Date(item.ts);
20329
- const dateKey = date.toISOString().split("T")[0];
20330
- if (!dayMap.has(dateKey)) {
20331
- dayMap.set(dateKey, []);
20332
- }
20333
- dayMap.get(dateKey).push(item);
20334
- });
20335
- const result = [];
20336
- dayMap.forEach((dayData, dateKey) => {
20337
- const values = dayData.map((item) => clampTemperature(item.value, clampRange));
20338
- const sum = values.reduce((acc, v) => acc + v, 0);
20339
- result.push({
20340
- date: dateKey,
20341
- dateTs: new Date(dateKey).getTime(),
20342
- avg: sum / values.length,
20343
- min: Math.min(...values),
20344
- max: Math.max(...values),
20345
- count: values.length
20346
- });
20347
- });
20348
- return result.sort((a, b) => a.dateTs - b.dateTs);
20349
- }
20350
- function filterByDayPeriods(data, selectedPeriods) {
20351
- if (selectedPeriods.length === 0 || selectedPeriods.length === DAY_PERIODS.length) {
20352
- return data;
20353
- }
20354
- return data.filter((item) => {
20355
- const date = new Date(item.ts);
20356
- const hour = date.getHours();
20357
- return selectedPeriods.some((periodId) => {
20358
- const period = DAY_PERIODS.find((p) => p.id === periodId);
20359
- if (!period) return false;
20360
- return hour >= period.startHour && hour < period.endHour;
20361
- });
20362
- });
20363
- }
20364
- function getSelectedPeriodsLabel(selectedPeriods) {
20365
- if (selectedPeriods.length === 0 || selectedPeriods.length === DAY_PERIODS.length) {
20366
- return "Todos os per\xEDodos";
20367
- }
20368
- if (selectedPeriods.length === 1) {
20369
- const period = DAY_PERIODS.find((p) => p.id === selectedPeriods[0]);
20370
- return period?.label || "";
20371
- }
20372
- return `${selectedPeriods.length} per\xEDodos selecionados`;
20373
- }
20374
- function formatTemperature2(value, decimals = 1) {
20375
- return `${value.toFixed(decimals)}\xB0C`;
20376
- }
20377
- function exportTemperatureCSV(data, deviceLabel, stats, startDate, endDate) {
20378
- if (data.length === 0) {
20379
- console.warn("No data to export");
20380
- return;
20381
- }
20382
- const BOM = "\uFEFF";
20383
- let csvContent = BOM;
20384
- csvContent += `Relat\xF3rio de Temperatura - ${deviceLabel}
20385
- `;
20386
- csvContent += `Per\xEDodo: ${startDate} at\xE9 ${endDate}
20387
- `;
20388
- csvContent += `M\xE9dia: ${formatTemperature2(stats.avg)}
20389
- `;
20390
- csvContent += `M\xEDnima: ${formatTemperature2(stats.min)}
20391
- `;
20392
- csvContent += `M\xE1xima: ${formatTemperature2(stats.max)}
20393
- `;
20394
- csvContent += `Total de leituras: ${stats.count}
20395
- `;
20396
- csvContent += "\n";
20397
- csvContent += "Data/Hora,Temperatura (\xB0C)\n";
20398
- data.forEach((item) => {
20399
- const date = new Date(item.ts).toLocaleString("pt-BR");
20400
- const temp = Number(item.value).toFixed(2);
20401
- csvContent += `"${date}",${temp}
20402
- `;
20403
- });
20404
- const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" });
20405
- const url = URL.createObjectURL(blob);
20406
- const link = document.createElement("a");
20407
- link.href = url;
20408
- link.download = `temperatura_${deviceLabel.replace(/\s+/g, "_")}_${startDate}_${endDate}.csv`;
20409
- document.body.appendChild(link);
20410
- link.click();
20411
- document.body.removeChild(link);
20412
- URL.revokeObjectURL(url);
20413
- }
20414
- var DARK_THEME = {
20415
- background: "rgba(0, 0, 0, 0.85)",
20416
- surface: "#1a1f28",
20417
- text: "#ffffff",
20418
- textMuted: "rgba(255, 255, 255, 0.7)",
20419
- border: "rgba(255, 255, 255, 0.1)",
20420
- primary: "#1976d2",
20421
- success: "#4CAF50",
20422
- warning: "#FF9800",
20423
- danger: "#f44336",
20424
- chartLine: "#1976d2",
20425
- chartGrid: "rgba(255, 255, 255, 0.1)"
20426
- };
20427
- var LIGHT_THEME = {
20428
- background: "rgba(0, 0, 0, 0.6)",
20429
- surface: "#ffffff",
20430
- text: "#333333",
20431
- textMuted: "#666666",
20432
- border: "#e0e0e0",
20433
- primary: "#1976d2",
20434
- success: "#4CAF50",
20435
- warning: "#FF9800",
20436
- danger: "#f44336",
20437
- chartLine: "#1976d2",
20438
- chartGrid: "#e0e0e0"
20439
- };
20440
- function getThemeColors(theme) {
20441
- return theme === "dark" ? DARK_THEME : LIGHT_THEME;
20442
- }
20443
-
20444
21010
  // src/components/temperature/TemperatureModal.ts
20445
21011
  async function openTemperatureModal(params) {
20446
21012
  const modalId = `myio-temp-modal-${Date.now()}`;
@@ -20680,7 +21246,7 @@ function renderModal(container, state, modalId, error) {
20680
21246
  ">
20681
21247
  <span style="color: ${colors.textMuted}; font-size: 12px; font-weight: 500;">Temperatura Atual</span>
20682
21248
  <div style="font-weight: 700; font-size: 24px; color: ${statusColor}; margin-top: 4px;">
20683
- ${state.currentTemperature !== null ? formatTemperature2(state.currentTemperature) : "N/A"}
21249
+ ${state.currentTemperature !== null ? formatTemperature(state.currentTemperature) : "N/A"}
20684
21250
  </div>
20685
21251
  <div style="font-size: 11px; color: ${statusColor}; margin-top: 2px;">${statusText}</div>
20686
21252
  </div>
@@ -20691,7 +21257,7 @@ function renderModal(container, state, modalId, error) {
20691
21257
  ">
20692
21258
  <span style="color: ${colors.textMuted}; font-size: 12px; font-weight: 500;">M\xE9dia do Per\xEDodo</span>
20693
21259
  <div id="${modalId}-avg" style="font-weight: 600; font-size: 20px; color: ${colors.text}; margin-top: 4px;">
20694
- ${state.stats.count > 0 ? formatTemperature2(state.stats.avg) : "N/A"}
21260
+ ${state.stats.count > 0 ? formatTemperature(state.stats.avg) : "N/A"}
20695
21261
  </div>
20696
21262
  <div style="font-size: 11px; color: ${colors.textMuted}; margin-top: 2px;">${startDateStr} - ${endDateStr}</div>
20697
21263
  </div>
@@ -20702,7 +21268,7 @@ function renderModal(container, state, modalId, error) {
20702
21268
  ">
20703
21269
  <span style="color: ${colors.textMuted}; font-size: 12px; font-weight: 500;">Min / Max</span>
20704
21270
  <div id="${modalId}-minmax" style="font-weight: 600; font-size: 20px; color: ${colors.text}; margin-top: 4px;">
20705
- ${state.stats.count > 0 ? `${formatTemperature2(state.stats.min)} / ${formatTemperature2(state.stats.max)}` : "N/A"}
21271
+ ${state.stats.count > 0 ? `${formatTemperature(state.stats.min)} / ${formatTemperature(state.stats.max)}` : "N/A"}
20706
21272
  </div>
20707
21273
  <div style="font-size: 11px; color: ${colors.textMuted}; margin-top: 2px;">${state.stats.count} leituras</div>
20708
21274
  </div>
@@ -21018,7 +21584,7 @@ function setupChartTooltip(canvas, container, chartData, state, colors) {
21018
21584
  }
21019
21585
  tooltip.innerHTML = `
21020
21586
  <div style="font-weight: 600; margin-bottom: 6px; color: ${colors.primary};">
21021
- ${formatTemperature2(point.y)}
21587
+ ${formatTemperature(point.y)}
21022
21588
  </div>
21023
21589
  <div style="font-size: 11px; color: ${colors.textMuted};">
21024
21590
  \u{1F4C5} ${dateStr}
@@ -21281,7 +21847,7 @@ function renderModal2(container, state, modalId) {
21281
21847
  <span style="width: 12px; height: 12px; border-radius: 50%; background: ${dd.color};"></span>
21282
21848
  <span style="color: ${colors.text}; font-size: 13px;">${dd.device.label}</span>
21283
21849
  <span style="color: ${colors.textMuted}; font-size: 11px; margin-left: auto;">
21284
- ${dd.stats.count > 0 ? formatTemperature2(dd.stats.avg) : "N/A"}
21850
+ ${dd.stats.count > 0 ? formatTemperature(dd.stats.avg) : "N/A"}
21285
21851
  </span>
21286
21852
  </div>
21287
21853
  `).join("");
@@ -21297,15 +21863,15 @@ function renderModal2(container, state, modalId) {
21297
21863
  <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 4px; font-size: 11px;">
21298
21864
  <span style="color: ${colors.textMuted};">M\xE9dia:</span>
21299
21865
  <span style="color: ${colors.text}; font-weight: 500;">
21300
- ${dd.stats.count > 0 ? formatTemperature2(dd.stats.avg) : "N/A"}
21866
+ ${dd.stats.count > 0 ? formatTemperature(dd.stats.avg) : "N/A"}
21301
21867
  </span>
21302
21868
  <span style="color: ${colors.textMuted};">Min:</span>
21303
21869
  <span style="color: ${colors.text};">
21304
- ${dd.stats.count > 0 ? formatTemperature2(dd.stats.min) : "N/A"}
21870
+ ${dd.stats.count > 0 ? formatTemperature(dd.stats.min) : "N/A"}
21305
21871
  </span>
21306
21872
  <span style="color: ${colors.textMuted};">Max:</span>
21307
21873
  <span style="color: ${colors.text};">
21308
- ${dd.stats.count > 0 ? formatTemperature2(dd.stats.max) : "N/A"}
21874
+ ${dd.stats.count > 0 ? formatTemperature(dd.stats.max) : "N/A"}
21309
21875
  </span>
21310
21876
  <span style="color: ${colors.textMuted};">Leituras:</span>
21311
21877
  <span style="color: ${colors.text};">${dd.stats.count}</span>
@@ -21841,7 +22407,7 @@ function setupComparisonChartTooltip(canvas, container, chartData, state, colors
21841
22407
  <span style="font-weight: 600;">${point.deviceLabel}</span>
21842
22408
  </div>
21843
22409
  <div style="font-weight: 600; font-size: 16px; color: ${point.deviceColor}; margin-bottom: 4px;">
21844
- ${formatTemperature2(point.y)}
22410
+ ${formatTemperature(point.y)}
21845
22411
  </div>
21846
22412
  <div style="font-size: 11px; color: ${colors.textMuted};">
21847
22413
  \u{1F4C5} ${dateStr}
@@ -26393,7 +26959,7 @@ export {
26393
26959
  formatNumberReadable,
26394
26960
  formatRelativeTime,
26395
26961
  formatTankHeadFromCm,
26396
- formatTemperature2 as formatTemperature,
26962
+ formatTemperature,
26397
26963
  formatWater,
26398
26964
  formatWaterByGroup,
26399
26965
  formatWaterVolumeM3,