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.cjs +857 -291
- package/dist/index.d.cts +8 -3
- package/dist/index.js +857 -291
- package/dist/myio-js-library.umd.js +856 -291
- package/dist/myio-js-library.umd.min.js +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -642,7 +642,7 @@ __export(index_exports, {
|
|
|
642
642
|
formatNumberReadable: () => formatNumberReadable,
|
|
643
643
|
formatRelativeTime: () => formatRelativeTime,
|
|
644
644
|
formatTankHeadFromCm: () => formatTankHeadFromCm,
|
|
645
|
-
formatTemperature: () =>
|
|
645
|
+
formatTemperature: () => formatTemperature,
|
|
646
646
|
formatWater: () => formatWater,
|
|
647
647
|
formatWaterByGroup: () => formatWaterByGroup,
|
|
648
648
|
formatWaterVolumeM3: () => formatWaterVolumeM3,
|
|
@@ -1459,7 +1459,8 @@ var DeviceStatusType = {
|
|
|
1459
1459
|
FAILURE: "failure",
|
|
1460
1460
|
MAINTENANCE: "maintenance",
|
|
1461
1461
|
NO_INFO: "no_info",
|
|
1462
|
-
NOT_INSTALLED: "not_installed"
|
|
1462
|
+
NOT_INSTALLED: "not_installed",
|
|
1463
|
+
OFFLINE: "offline"
|
|
1463
1464
|
};
|
|
1464
1465
|
var ConnectionStatusType = {
|
|
1465
1466
|
CONNECTED: "connected",
|
|
@@ -1468,39 +1469,42 @@ var ConnectionStatusType = {
|
|
|
1468
1469
|
var deviceStatusIcons = {
|
|
1469
1470
|
[DeviceStatusType.POWER_ON]: "\u26A1",
|
|
1470
1471
|
[DeviceStatusType.STANDBY]: "\u{1F50C}",
|
|
1471
|
-
[DeviceStatusType.POWER_OFF]: "\
|
|
1472
|
+
[DeviceStatusType.POWER_OFF]: "\u26AB",
|
|
1472
1473
|
[DeviceStatusType.WARNING]: "\u26A0\uFE0F",
|
|
1473
1474
|
[DeviceStatusType.FAILURE]: "\u{1F6A8}",
|
|
1474
1475
|
[DeviceStatusType.MAINTENANCE]: "\u{1F6E0}\uFE0F",
|
|
1475
1476
|
[DeviceStatusType.NO_INFO]: "\u2753\uFE0F",
|
|
1476
|
-
[DeviceStatusType.NOT_INSTALLED]: "\u{1F4E6}"
|
|
1477
|
+
[DeviceStatusType.NOT_INSTALLED]: "\u{1F4E6}",
|
|
1478
|
+
[DeviceStatusType.OFFLINE]: "\u{1F534}"
|
|
1477
1479
|
};
|
|
1478
1480
|
var waterDeviceStatusIcons = {
|
|
1479
1481
|
[DeviceStatusType.POWER_ON]: "\u{1F4A7}",
|
|
1480
1482
|
[DeviceStatusType.STANDBY]: "\u{1F6B0}",
|
|
1481
|
-
[DeviceStatusType.POWER_OFF]: "\
|
|
1483
|
+
[DeviceStatusType.POWER_OFF]: "\u26AB",
|
|
1482
1484
|
[DeviceStatusType.WARNING]: "\u26A0\uFE0F",
|
|
1483
1485
|
[DeviceStatusType.FAILURE]: "\u{1F6A8}",
|
|
1484
1486
|
[DeviceStatusType.MAINTENANCE]: "\u{1F6E0}\uFE0F",
|
|
1485
1487
|
[DeviceStatusType.NO_INFO]: "\u2753\uFE0F",
|
|
1486
|
-
[DeviceStatusType.NOT_INSTALLED]: "\u{1F4E6}"
|
|
1488
|
+
[DeviceStatusType.NOT_INSTALLED]: "\u{1F4E6}",
|
|
1489
|
+
[DeviceStatusType.OFFLINE]: "\u{1F534}"
|
|
1487
1490
|
};
|
|
1488
1491
|
var temperatureDeviceStatusIcons = {
|
|
1489
1492
|
[DeviceStatusType.POWER_ON]: "\u{1F321}\uFE0F",
|
|
1490
1493
|
[DeviceStatusType.STANDBY]: "\u{1F321}\uFE0F",
|
|
1491
|
-
[DeviceStatusType.POWER_OFF]: "\
|
|
1494
|
+
[DeviceStatusType.POWER_OFF]: "\u26AB",
|
|
1492
1495
|
[DeviceStatusType.WARNING]: "\u26A0\uFE0F",
|
|
1493
1496
|
[DeviceStatusType.FAILURE]: "\u{1F6A8}",
|
|
1494
1497
|
[DeviceStatusType.MAINTENANCE]: "\u{1F6E0}\uFE0F",
|
|
1495
1498
|
[DeviceStatusType.NO_INFO]: "\u2753\uFE0F",
|
|
1496
|
-
[DeviceStatusType.NOT_INSTALLED]: "\u{1F4E6}"
|
|
1499
|
+
[DeviceStatusType.NOT_INSTALLED]: "\u{1F4E6}",
|
|
1500
|
+
[DeviceStatusType.OFFLINE]: "\u{1F534}"
|
|
1497
1501
|
};
|
|
1498
1502
|
var connectionStatusIcons = {
|
|
1499
1503
|
[ConnectionStatusType.CONNECTED]: "\u{1F7E2}",
|
|
1500
1504
|
[ConnectionStatusType.OFFLINE]: "\u{1F6AB}"
|
|
1501
1505
|
};
|
|
1502
1506
|
function mapDeviceToConnectionStatus(deviceStatus) {
|
|
1503
|
-
if (deviceStatus === DeviceStatusType.NO_INFO) {
|
|
1507
|
+
if (deviceStatus === DeviceStatusType.NO_INFO || deviceStatus === DeviceStatusType.OFFLINE) {
|
|
1504
1508
|
return ConnectionStatusType.OFFLINE;
|
|
1505
1509
|
}
|
|
1506
1510
|
return ConnectionStatusType.CONNECTED;
|
|
@@ -1524,15 +1528,16 @@ function mapDeviceStatusToCardStatus(deviceStatus) {
|
|
|
1524
1528
|
[DeviceStatusType.FAILURE]: "fail",
|
|
1525
1529
|
[DeviceStatusType.MAINTENANCE]: "alert",
|
|
1526
1530
|
[DeviceStatusType.NO_INFO]: "unknown",
|
|
1527
|
-
[DeviceStatusType.NOT_INSTALLED]: "not_installed"
|
|
1531
|
+
[DeviceStatusType.NOT_INSTALLED]: "not_installed",
|
|
1532
|
+
[DeviceStatusType.OFFLINE]: "offline"
|
|
1528
1533
|
};
|
|
1529
1534
|
return statusMap[deviceStatus] || "unknown";
|
|
1530
1535
|
}
|
|
1531
1536
|
function shouldFlashIcon(deviceStatus) {
|
|
1532
|
-
return deviceStatus === DeviceStatusType.POWER_OFF || deviceStatus === DeviceStatusType.WARNING || deviceStatus === DeviceStatusType.FAILURE || deviceStatus === DeviceStatusType.MAINTENANCE;
|
|
1537
|
+
return deviceStatus === DeviceStatusType.POWER_OFF || deviceStatus === DeviceStatusType.WARNING || deviceStatus === DeviceStatusType.FAILURE || deviceStatus === DeviceStatusType.MAINTENANCE || deviceStatus === DeviceStatusType.OFFLINE;
|
|
1533
1538
|
}
|
|
1534
1539
|
function isDeviceOffline(deviceStatus) {
|
|
1535
|
-
return deviceStatus === DeviceStatusType.NO_INFO;
|
|
1540
|
+
return deviceStatus === DeviceStatusType.NO_INFO || deviceStatus === DeviceStatusType.OFFLINE;
|
|
1536
1541
|
}
|
|
1537
1542
|
function getDeviceStatusIcon(deviceStatus, deviceType = null) {
|
|
1538
1543
|
const normalizedType = deviceType?.toUpperCase() || "";
|
|
@@ -4088,15 +4093,30 @@ var CSS_STRING = `
|
|
|
4088
4093
|
--myio-chip-alert-fg: #b45309;
|
|
4089
4094
|
--myio-border-alert: rgba(245, 158, 11, 0.5);
|
|
4090
4095
|
|
|
4091
|
-
/* Status colors - Failure (red) */
|
|
4096
|
+
/* Status colors - Failure (dark red) */
|
|
4092
4097
|
--myio-chip-failure-bg: #fee2e2;
|
|
4093
4098
|
--myio-chip-failure-fg: #b91c1c;
|
|
4094
|
-
--myio-border-failure: rgba(
|
|
4099
|
+
--myio-border-failure: rgba(153, 27, 27, 0.6);
|
|
4100
|
+
|
|
4101
|
+
/* Status colors - Power Off (light red) */
|
|
4102
|
+
--myio-chip-power-off-bg: #fecaca;
|
|
4103
|
+
--myio-chip-power-off-fg: #dc2626;
|
|
4104
|
+
--myio-border-power-off: rgba(239, 68, 68, 0.5);
|
|
4105
|
+
|
|
4106
|
+
/* Status colors - Offline (dark gray) */
|
|
4107
|
+
--myio-chip-offline-bg: #e2e8f0;
|
|
4108
|
+
--myio-chip-offline-fg: #475569;
|
|
4109
|
+
--myio-border-offline: rgba(71, 85, 105, 0.6);
|
|
4110
|
+
|
|
4111
|
+
/* Status colors - No Info (dark orange) */
|
|
4112
|
+
--myio-chip-no-info-bg: #fed7aa;
|
|
4113
|
+
--myio-chip-no-info-fg: #c2410c;
|
|
4114
|
+
--myio-border-no-info: rgba(194, 65, 12, 0.5);
|
|
4095
4115
|
|
|
4096
|
-
/* Status colors -
|
|
4097
|
-
--myio-chip-
|
|
4098
|
-
--myio-chip-
|
|
4099
|
-
--myio-border-
|
|
4116
|
+
/* Status colors - Not Installed (purple) */
|
|
4117
|
+
--myio-chip-not-installed-bg: #e9d5ff;
|
|
4118
|
+
--myio-chip-not-installed-fg: #7c3aed;
|
|
4119
|
+
--myio-border-not-installed: rgba(124, 58, 237, 0.5);
|
|
4100
4120
|
|
|
4101
4121
|
--myio-text-1: #0f172a;
|
|
4102
4122
|
--myio-text-2: #4b5563;
|
|
@@ -4152,26 +4172,55 @@ var CSS_STRING = `
|
|
|
4152
4172
|
}
|
|
4153
4173
|
|
|
4154
4174
|
/* Card border states based on device status */
|
|
4155
|
-
|
|
4175
|
+
|
|
4176
|
+
/* POWER_ON - Blue */
|
|
4177
|
+
.myio-ho-card.is-power-on {
|
|
4156
4178
|
border-color: var(--myio-border-ok);
|
|
4157
4179
|
box-shadow: 0 0 0 2px var(--myio-border-ok), var(--myio-card-shadow);
|
|
4158
4180
|
}
|
|
4159
4181
|
|
|
4182
|
+
/* STANDBY - Green */
|
|
4160
4183
|
.myio-ho-card.is-standby {
|
|
4161
4184
|
border-color: var(--myio-border-standby);
|
|
4162
4185
|
box-shadow: 0 0 0 2px var(--myio-border-standby), var(--myio-card-shadow);
|
|
4163
4186
|
}
|
|
4164
4187
|
|
|
4165
|
-
|
|
4188
|
+
/* WARNING - Yellow */
|
|
4189
|
+
.myio-ho-card.is-warning {
|
|
4166
4190
|
border-color: var(--myio-border-alert);
|
|
4167
4191
|
box-shadow: 0 0 0 2px var(--myio-border-alert), var(--myio-card-shadow);
|
|
4168
4192
|
}
|
|
4169
4193
|
|
|
4194
|
+
/* MAINTENANCE - Yellow */
|
|
4195
|
+
.myio-ho-card.is-maintenance {
|
|
4196
|
+
border-color: var(--myio-border-alert);
|
|
4197
|
+
box-shadow: 0 0 0 2px var(--myio-border-alert), var(--myio-card-shadow);
|
|
4198
|
+
}
|
|
4199
|
+
|
|
4200
|
+
/* FAILURE - Dark Red */
|
|
4170
4201
|
.myio-ho-card.is-failure {
|
|
4171
4202
|
border-color: var(--myio-border-failure);
|
|
4172
4203
|
box-shadow: 0 0 0 2px var(--myio-border-failure), var(--myio-card-shadow);
|
|
4173
4204
|
}
|
|
4174
4205
|
|
|
4206
|
+
/* POWER_OFF - Light Red */
|
|
4207
|
+
.myio-ho-card.is-power-off {
|
|
4208
|
+
border-color: var(--myio-border-power-off);
|
|
4209
|
+
box-shadow: 0 0 0 2px var(--myio-border-power-off), var(--myio-card-shadow);
|
|
4210
|
+
}
|
|
4211
|
+
|
|
4212
|
+
/* NO_INFO - Dark Orange */
|
|
4213
|
+
.myio-ho-card.is-no-info {
|
|
4214
|
+
border-color: var(--myio-border-no-info);
|
|
4215
|
+
box-shadow: 0 0 0 2px var(--myio-border-no-info), var(--myio-card-shadow);
|
|
4216
|
+
}
|
|
4217
|
+
|
|
4218
|
+
/* NOT_INSTALLED - Purple */
|
|
4219
|
+
.myio-ho-card.is-not-installed {
|
|
4220
|
+
border-color: var(--myio-border-not-installed);
|
|
4221
|
+
box-shadow: 0 0 0 2px var(--myio-border-not-installed), var(--myio-card-shadow);
|
|
4222
|
+
}
|
|
4223
|
+
|
|
4175
4224
|
/* Header section */
|
|
4176
4225
|
.myio-ho-card__header {
|
|
4177
4226
|
display: flex;
|
|
@@ -4189,7 +4238,9 @@ var CSS_STRING = `
|
|
|
4189
4238
|
margin-top: 2px;
|
|
4190
4239
|
}
|
|
4191
4240
|
|
|
4192
|
-
|
|
4241
|
+
/* Icon colors based on status */
|
|
4242
|
+
.myio-ho-card.is-warning .myio-ho-card__icon,
|
|
4243
|
+
.myio-ho-card.is-maintenance .myio-ho-card__icon {
|
|
4193
4244
|
color: var(--myio-chip-alert-fg);
|
|
4194
4245
|
}
|
|
4195
4246
|
|
|
@@ -4197,14 +4248,28 @@ var CSS_STRING = `
|
|
|
4197
4248
|
color: var(--myio-chip-failure-fg);
|
|
4198
4249
|
}
|
|
4199
4250
|
|
|
4251
|
+
.myio-ho-card.is-power-off .myio-ho-card__icon {
|
|
4252
|
+
color: var(--myio-chip-power-off-fg);
|
|
4253
|
+
}
|
|
4254
|
+
|
|
4255
|
+
.myio-ho-card.is-offline .myio-ho-card__icon {
|
|
4256
|
+
color: var(--myio-chip-offline-fg);
|
|
4257
|
+
}
|
|
4258
|
+
|
|
4259
|
+
.myio-ho-card.is-no-info .myio-ho-card__icon {
|
|
4260
|
+
color: var(--myio-chip-no-info-fg);
|
|
4261
|
+
}
|
|
4262
|
+
|
|
4263
|
+
.myio-ho-card.is-not-installed .myio-ho-card__icon {
|
|
4264
|
+
color: var(--myio-chip-not-installed-fg);
|
|
4265
|
+
}
|
|
4266
|
+
|
|
4200
4267
|
.myio-ho-card__title {
|
|
4201
4268
|
flex: 1;
|
|
4202
4269
|
min-width: 0;
|
|
4203
4270
|
}
|
|
4204
4271
|
|
|
4205
|
-
/*
|
|
4206
|
-
|
|
4207
|
-
/* Estado Offline - borda cinza */
|
|
4272
|
+
/* OFFLINE - Dark Gray */
|
|
4208
4273
|
.myio-ho-card.is-offline {
|
|
4209
4274
|
border-color: var(--myio-border-offline);
|
|
4210
4275
|
box-shadow: 0 0 0 2px var(--myio-border-offline), var(--myio-card-shadow);
|
|
@@ -4599,6 +4664,37 @@ var CSS_STRING = `
|
|
|
4599
4664
|
color: var(--myio-chip-offline-fg);
|
|
4600
4665
|
}
|
|
4601
4666
|
|
|
4667
|
+
/* New chip classes aligned with getCardStateClass */
|
|
4668
|
+
.chip--power-on {
|
|
4669
|
+
background: var(--myio-chip-ok-bg);
|
|
4670
|
+
color: var(--myio-chip-ok-fg);
|
|
4671
|
+
}
|
|
4672
|
+
|
|
4673
|
+
.chip--warning {
|
|
4674
|
+
background: var(--myio-chip-alert-bg);
|
|
4675
|
+
color: var(--myio-chip-alert-fg);
|
|
4676
|
+
}
|
|
4677
|
+
|
|
4678
|
+
.chip--maintenance {
|
|
4679
|
+
background: var(--myio-chip-alert-bg);
|
|
4680
|
+
color: var(--myio-chip-alert-fg);
|
|
4681
|
+
}
|
|
4682
|
+
|
|
4683
|
+
.chip--power-off {
|
|
4684
|
+
background: var(--myio-chip-power-off-bg);
|
|
4685
|
+
color: var(--myio-chip-power-off-fg);
|
|
4686
|
+
}
|
|
4687
|
+
|
|
4688
|
+
.chip--no-info {
|
|
4689
|
+
background: var(--myio-chip-no-info-bg);
|
|
4690
|
+
color: var(--myio-chip-no-info-fg);
|
|
4691
|
+
}
|
|
4692
|
+
|
|
4693
|
+
.chip--not-installed {
|
|
4694
|
+
background: var(--myio-chip-not-installed-bg);
|
|
4695
|
+
color: var(--myio-chip-not-installed-fg);
|
|
4696
|
+
}
|
|
4697
|
+
|
|
4602
4698
|
/* Status indicator dot for power metric */
|
|
4603
4699
|
.status-dot {
|
|
4604
4700
|
width: 8px;
|
|
@@ -4632,6 +4728,31 @@ var CSS_STRING = `
|
|
|
4632
4728
|
background: var(--myio-muted);
|
|
4633
4729
|
}
|
|
4634
4730
|
|
|
4731
|
+
/* New dot classes aligned with getCardStateClass */
|
|
4732
|
+
.status-dot.dot--power-on {
|
|
4733
|
+
background: var(--myio-chip-ok-fg);
|
|
4734
|
+
}
|
|
4735
|
+
|
|
4736
|
+
.status-dot.dot--warning {
|
|
4737
|
+
background: var(--myio-chip-alert-fg);
|
|
4738
|
+
}
|
|
4739
|
+
|
|
4740
|
+
.status-dot.dot--maintenance {
|
|
4741
|
+
background: var(--myio-chip-alert-fg);
|
|
4742
|
+
}
|
|
4743
|
+
|
|
4744
|
+
.status-dot.dot--power-off {
|
|
4745
|
+
background: var(--myio-chip-power-off-fg);
|
|
4746
|
+
}
|
|
4747
|
+
|
|
4748
|
+
.status-dot.dot--no-info {
|
|
4749
|
+
background: var(--myio-chip-no-info-fg);
|
|
4750
|
+
}
|
|
4751
|
+
|
|
4752
|
+
.status-dot.dot--not-installed {
|
|
4753
|
+
background: var(--myio-chip-not-installed-fg);
|
|
4754
|
+
}
|
|
4755
|
+
|
|
4635
4756
|
/* Primary metric */
|
|
4636
4757
|
.myio-ho-card__primary {
|
|
4637
4758
|
margin-bottom: 14px;
|
|
@@ -4814,6 +4935,215 @@ var CSS_STRING = `
|
|
|
4814
4935
|
transition: none;
|
|
4815
4936
|
}
|
|
4816
4937
|
}
|
|
4938
|
+
|
|
4939
|
+
/* ============================================
|
|
4940
|
+
DEBUG TOOLTIP STYLES (Premium)
|
|
4941
|
+
============================================ */
|
|
4942
|
+
|
|
4943
|
+
.has-debug-tooltip {
|
|
4944
|
+
cursor: help !important;
|
|
4945
|
+
}
|
|
4946
|
+
|
|
4947
|
+
.has-debug-tooltip::after {
|
|
4948
|
+
content: '\u{1F41B}';
|
|
4949
|
+
position: absolute;
|
|
4950
|
+
top: -4px;
|
|
4951
|
+
right: -4px;
|
|
4952
|
+
font-size: 10px;
|
|
4953
|
+
z-index: 1;
|
|
4954
|
+
}
|
|
4955
|
+
|
|
4956
|
+
.debug-tooltip-container {
|
|
4957
|
+
position: absolute;
|
|
4958
|
+
bottom: calc(100% + 8px);
|
|
4959
|
+
left: 50%;
|
|
4960
|
+
transform: translateX(-50%);
|
|
4961
|
+
z-index: 10000;
|
|
4962
|
+
pointer-events: none;
|
|
4963
|
+
opacity: 0;
|
|
4964
|
+
transition: opacity 0.2s ease, transform 0.2s ease;
|
|
4965
|
+
}
|
|
4966
|
+
|
|
4967
|
+
.has-debug-tooltip:hover .debug-tooltip-container {
|
|
4968
|
+
opacity: 1;
|
|
4969
|
+
pointer-events: auto;
|
|
4970
|
+
}
|
|
4971
|
+
|
|
4972
|
+
.debug-tooltip {
|
|
4973
|
+
background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%);
|
|
4974
|
+
border: 1px solid rgba(99, 102, 241, 0.3);
|
|
4975
|
+
border-radius: 12px;
|
|
4976
|
+
box-shadow:
|
|
4977
|
+
0 20px 40px rgba(0, 0, 0, 0.4),
|
|
4978
|
+
0 0 0 1px rgba(255, 255, 255, 0.05),
|
|
4979
|
+
inset 0 1px 0 rgba(255, 255, 255, 0.1);
|
|
4980
|
+
min-width: 340px;
|
|
4981
|
+
max-width: 420px;
|
|
4982
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
4983
|
+
font-size: 12px;
|
|
4984
|
+
color: #e2e8f0;
|
|
4985
|
+
overflow: hidden;
|
|
4986
|
+
}
|
|
4987
|
+
|
|
4988
|
+
.debug-tooltip__header {
|
|
4989
|
+
display: flex;
|
|
4990
|
+
align-items: center;
|
|
4991
|
+
gap: 8px;
|
|
4992
|
+
padding: 12px 16px;
|
|
4993
|
+
background: linear-gradient(90deg, rgba(99, 102, 241, 0.2) 0%, rgba(139, 92, 246, 0.1) 100%);
|
|
4994
|
+
border-bottom: 1px solid rgba(99, 102, 241, 0.2);
|
|
4995
|
+
}
|
|
4996
|
+
|
|
4997
|
+
.debug-tooltip__icon {
|
|
4998
|
+
font-size: 16px;
|
|
4999
|
+
}
|
|
5000
|
+
|
|
5001
|
+
.debug-tooltip__title {
|
|
5002
|
+
font-weight: 700;
|
|
5003
|
+
font-size: 13px;
|
|
5004
|
+
color: #f1f5f9;
|
|
5005
|
+
letter-spacing: 0.5px;
|
|
5006
|
+
text-transform: uppercase;
|
|
5007
|
+
}
|
|
5008
|
+
|
|
5009
|
+
.debug-tooltip__content {
|
|
5010
|
+
padding: 12px 16px;
|
|
5011
|
+
max-height: 400px;
|
|
5012
|
+
overflow-y: auto;
|
|
5013
|
+
}
|
|
5014
|
+
|
|
5015
|
+
.debug-tooltip__section {
|
|
5016
|
+
margin-bottom: 14px;
|
|
5017
|
+
padding-bottom: 12px;
|
|
5018
|
+
border-bottom: 1px solid rgba(148, 163, 184, 0.1);
|
|
5019
|
+
}
|
|
5020
|
+
|
|
5021
|
+
.debug-tooltip__section:last-child {
|
|
5022
|
+
margin-bottom: 0;
|
|
5023
|
+
padding-bottom: 0;
|
|
5024
|
+
border-bottom: none;
|
|
5025
|
+
}
|
|
5026
|
+
|
|
5027
|
+
.debug-tooltip__section-title {
|
|
5028
|
+
font-size: 11px;
|
|
5029
|
+
font-weight: 600;
|
|
5030
|
+
color: #94a3b8;
|
|
5031
|
+
text-transform: uppercase;
|
|
5032
|
+
letter-spacing: 0.8px;
|
|
5033
|
+
margin-bottom: 10px;
|
|
5034
|
+
display: flex;
|
|
5035
|
+
align-items: center;
|
|
5036
|
+
gap: 6px;
|
|
5037
|
+
}
|
|
5038
|
+
|
|
5039
|
+
.debug-tooltip__row {
|
|
5040
|
+
display: flex;
|
|
5041
|
+
justify-content: space-between;
|
|
5042
|
+
align-items: flex-start;
|
|
5043
|
+
padding: 4px 0;
|
|
5044
|
+
gap: 12px;
|
|
5045
|
+
}
|
|
5046
|
+
|
|
5047
|
+
.debug-tooltip__row--full {
|
|
5048
|
+
flex-direction: column;
|
|
5049
|
+
gap: 4px;
|
|
5050
|
+
}
|
|
5051
|
+
|
|
5052
|
+
.debug-tooltip__label {
|
|
5053
|
+
color: #94a3b8;
|
|
5054
|
+
font-size: 11px;
|
|
5055
|
+
flex-shrink: 0;
|
|
5056
|
+
}
|
|
5057
|
+
|
|
5058
|
+
.debug-tooltip__value {
|
|
5059
|
+
color: #f1f5f9;
|
|
5060
|
+
font-weight: 500;
|
|
5061
|
+
text-align: right;
|
|
5062
|
+
word-break: break-all;
|
|
5063
|
+
}
|
|
5064
|
+
|
|
5065
|
+
.debug-tooltip__row--full .debug-tooltip__value {
|
|
5066
|
+
text-align: left;
|
|
5067
|
+
background: rgba(0, 0, 0, 0.3);
|
|
5068
|
+
padding: 6px 10px;
|
|
5069
|
+
border-radius: 6px;
|
|
5070
|
+
font-size: 11px;
|
|
5071
|
+
width: 100%;
|
|
5072
|
+
box-sizing: border-box;
|
|
5073
|
+
}
|
|
5074
|
+
|
|
5075
|
+
.debug-tooltip__value--mono {
|
|
5076
|
+
font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace;
|
|
5077
|
+
font-size: 11px;
|
|
5078
|
+
background: rgba(0, 0, 0, 0.3);
|
|
5079
|
+
padding: 2px 6px;
|
|
5080
|
+
border-radius: 4px;
|
|
5081
|
+
}
|
|
5082
|
+
|
|
5083
|
+
.debug-tooltip__value--highlight {
|
|
5084
|
+
color: #a5b4fc;
|
|
5085
|
+
font-style: italic;
|
|
5086
|
+
}
|
|
5087
|
+
|
|
5088
|
+
.debug-tooltip__badge {
|
|
5089
|
+
display: inline-block;
|
|
5090
|
+
padding: 2px 8px;
|
|
5091
|
+
border-radius: 4px;
|
|
5092
|
+
font-size: 10px;
|
|
5093
|
+
font-weight: 600;
|
|
5094
|
+
text-transform: uppercase;
|
|
5095
|
+
letter-spacing: 0.5px;
|
|
5096
|
+
background: rgba(99, 102, 241, 0.3);
|
|
5097
|
+
color: #a5b4fc;
|
|
5098
|
+
}
|
|
5099
|
+
|
|
5100
|
+
.debug-tooltip__badge--energy {
|
|
5101
|
+
background: rgba(59, 130, 246, 0.3);
|
|
5102
|
+
color: #93c5fd;
|
|
5103
|
+
}
|
|
5104
|
+
|
|
5105
|
+
.debug-tooltip__badge--water {
|
|
5106
|
+
background: rgba(6, 182, 212, 0.3);
|
|
5107
|
+
color: #67e8f9;
|
|
5108
|
+
}
|
|
5109
|
+
|
|
5110
|
+
.debug-tooltip__badge--temperature {
|
|
5111
|
+
background: rgba(249, 115, 22, 0.3);
|
|
5112
|
+
color: #fdba74;
|
|
5113
|
+
}
|
|
5114
|
+
|
|
5115
|
+
/* Tooltip arrow */
|
|
5116
|
+
.debug-tooltip::after {
|
|
5117
|
+
content: '';
|
|
5118
|
+
position: absolute;
|
|
5119
|
+
bottom: -6px;
|
|
5120
|
+
left: 50%;
|
|
5121
|
+
transform: translateX(-50%) rotate(45deg);
|
|
5122
|
+
width: 12px;
|
|
5123
|
+
height: 12px;
|
|
5124
|
+
background: #0f172a;
|
|
5125
|
+
border-right: 1px solid rgba(99, 102, 241, 0.3);
|
|
5126
|
+
border-bottom: 1px solid rgba(99, 102, 241, 0.3);
|
|
5127
|
+
}
|
|
5128
|
+
|
|
5129
|
+
/* Scrollbar styling for tooltip content */
|
|
5130
|
+
.debug-tooltip__content::-webkit-scrollbar {
|
|
5131
|
+
width: 6px;
|
|
5132
|
+
}
|
|
5133
|
+
|
|
5134
|
+
.debug-tooltip__content::-webkit-scrollbar-track {
|
|
5135
|
+
background: rgba(0, 0, 0, 0.2);
|
|
5136
|
+
border-radius: 3px;
|
|
5137
|
+
}
|
|
5138
|
+
|
|
5139
|
+
.debug-tooltip__content::-webkit-scrollbar-thumb {
|
|
5140
|
+
background: rgba(99, 102, 241, 0.4);
|
|
5141
|
+
border-radius: 3px;
|
|
5142
|
+
}
|
|
5143
|
+
|
|
5144
|
+
.debug-tooltip__content::-webkit-scrollbar-thumb:hover {
|
|
5145
|
+
background: rgba(99, 102, 241, 0.6);
|
|
5146
|
+
}
|
|
4817
5147
|
`;
|
|
4818
5148
|
|
|
4819
5149
|
// src/thingsboard/main-dashboard-shopping/v-4.0.0/head-office/card-head-office.icons.ts
|
|
@@ -4968,7 +5298,246 @@ var DEFAULT_I18N = {
|
|
|
4968
5298
|
menu_settings: "Configura\xE7\xF5es"
|
|
4969
5299
|
};
|
|
4970
5300
|
|
|
5301
|
+
// src/components/temperature/utils.ts
|
|
5302
|
+
var DAY_PERIODS = [
|
|
5303
|
+
{ id: "madrugada", label: "Madrugada (00h-06h)", startHour: 0, endHour: 6 },
|
|
5304
|
+
{ id: "manha", label: "Manh\xE3 (06h-12h)", startHour: 6, endHour: 12 },
|
|
5305
|
+
{ id: "tarde", label: "Tarde (12h-18h)", startHour: 12, endHour: 18 },
|
|
5306
|
+
{ id: "noite", label: "Noite (18h-24h)", startHour: 18, endHour: 24 }
|
|
5307
|
+
];
|
|
5308
|
+
var DEFAULT_CLAMP_RANGE = { min: 15, max: 40 };
|
|
5309
|
+
function getTodaySoFar() {
|
|
5310
|
+
const now = /* @__PURE__ */ new Date();
|
|
5311
|
+
const startOfDay = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0, 0);
|
|
5312
|
+
return {
|
|
5313
|
+
startTs: startOfDay.getTime(),
|
|
5314
|
+
endTs: now.getTime()
|
|
5315
|
+
};
|
|
5316
|
+
}
|
|
5317
|
+
var CHART_COLORS = [
|
|
5318
|
+
"#1976d2",
|
|
5319
|
+
// Blue
|
|
5320
|
+
"#FF6B6B",
|
|
5321
|
+
// Red
|
|
5322
|
+
"#4CAF50",
|
|
5323
|
+
// Green
|
|
5324
|
+
"#FF9800",
|
|
5325
|
+
// Orange
|
|
5326
|
+
"#9C27B0",
|
|
5327
|
+
// Purple
|
|
5328
|
+
"#00BCD4",
|
|
5329
|
+
// Cyan
|
|
5330
|
+
"#E91E63",
|
|
5331
|
+
// Pink
|
|
5332
|
+
"#795548"
|
|
5333
|
+
// Brown
|
|
5334
|
+
];
|
|
5335
|
+
async function fetchTemperatureData(token, deviceId, startTs, endTs) {
|
|
5336
|
+
const url = `/api/plugins/telemetry/DEVICE/${deviceId}/values/timeseries?keys=temperature&startTs=${encodeURIComponent(startTs)}&endTs=${encodeURIComponent(endTs)}&limit=50000&agg=NONE`;
|
|
5337
|
+
const response = await fetch(url, {
|
|
5338
|
+
headers: {
|
|
5339
|
+
"X-Authorization": `Bearer ${token}`,
|
|
5340
|
+
"Content-Type": "application/json"
|
|
5341
|
+
}
|
|
5342
|
+
});
|
|
5343
|
+
if (!response.ok) {
|
|
5344
|
+
throw new Error(`Failed to fetch temperature data: ${response.status}`);
|
|
5345
|
+
}
|
|
5346
|
+
const data = await response.json();
|
|
5347
|
+
return data?.temperature || [];
|
|
5348
|
+
}
|
|
5349
|
+
function clampTemperature(value, range = DEFAULT_CLAMP_RANGE) {
|
|
5350
|
+
const num = Number(value || 0);
|
|
5351
|
+
if (num < range.min) return range.min;
|
|
5352
|
+
if (num > range.max) return range.max;
|
|
5353
|
+
return num;
|
|
5354
|
+
}
|
|
5355
|
+
function calculateStats(data, clampRange = DEFAULT_CLAMP_RANGE) {
|
|
5356
|
+
if (data.length === 0) {
|
|
5357
|
+
return { avg: 0, min: 0, max: 0, count: 0 };
|
|
5358
|
+
}
|
|
5359
|
+
const values = data.map((item) => clampTemperature(item.value, clampRange));
|
|
5360
|
+
const sum = values.reduce((acc, v) => acc + v, 0);
|
|
5361
|
+
return {
|
|
5362
|
+
avg: sum / values.length,
|
|
5363
|
+
min: Math.min(...values),
|
|
5364
|
+
max: Math.max(...values),
|
|
5365
|
+
count: values.length
|
|
5366
|
+
};
|
|
5367
|
+
}
|
|
5368
|
+
function interpolateTemperature(data, options) {
|
|
5369
|
+
const { intervalMinutes, startTs, endTs, clampRange = DEFAULT_CLAMP_RANGE } = options;
|
|
5370
|
+
const intervalMs = intervalMinutes * 60 * 1e3;
|
|
5371
|
+
if (data.length === 0) {
|
|
5372
|
+
return [];
|
|
5373
|
+
}
|
|
5374
|
+
const sortedData = [...data].sort((a, b) => a.ts - b.ts);
|
|
5375
|
+
const result = [];
|
|
5376
|
+
let lastKnownValue = clampTemperature(sortedData[0].value, clampRange);
|
|
5377
|
+
let dataIndex = 0;
|
|
5378
|
+
for (let ts = startTs; ts <= endTs; ts += intervalMs) {
|
|
5379
|
+
while (dataIndex < sortedData.length - 1 && sortedData[dataIndex + 1].ts <= ts) {
|
|
5380
|
+
dataIndex++;
|
|
5381
|
+
}
|
|
5382
|
+
const currentData = sortedData[dataIndex];
|
|
5383
|
+
if (currentData && Math.abs(currentData.ts - ts) < intervalMs) {
|
|
5384
|
+
lastKnownValue = clampTemperature(currentData.value, clampRange);
|
|
5385
|
+
}
|
|
5386
|
+
result.push({
|
|
5387
|
+
ts,
|
|
5388
|
+
value: lastKnownValue
|
|
5389
|
+
});
|
|
5390
|
+
}
|
|
5391
|
+
return result;
|
|
5392
|
+
}
|
|
5393
|
+
function aggregateByDay(data, clampRange = DEFAULT_CLAMP_RANGE) {
|
|
5394
|
+
if (data.length === 0) {
|
|
5395
|
+
return [];
|
|
5396
|
+
}
|
|
5397
|
+
const dayMap = /* @__PURE__ */ new Map();
|
|
5398
|
+
data.forEach((item) => {
|
|
5399
|
+
const date = new Date(item.ts);
|
|
5400
|
+
const dateKey = date.toISOString().split("T")[0];
|
|
5401
|
+
if (!dayMap.has(dateKey)) {
|
|
5402
|
+
dayMap.set(dateKey, []);
|
|
5403
|
+
}
|
|
5404
|
+
dayMap.get(dateKey).push(item);
|
|
5405
|
+
});
|
|
5406
|
+
const result = [];
|
|
5407
|
+
dayMap.forEach((dayData, dateKey) => {
|
|
5408
|
+
const values = dayData.map((item) => clampTemperature(item.value, clampRange));
|
|
5409
|
+
const sum = values.reduce((acc, v) => acc + v, 0);
|
|
5410
|
+
result.push({
|
|
5411
|
+
date: dateKey,
|
|
5412
|
+
dateTs: new Date(dateKey).getTime(),
|
|
5413
|
+
avg: sum / values.length,
|
|
5414
|
+
min: Math.min(...values),
|
|
5415
|
+
max: Math.max(...values),
|
|
5416
|
+
count: values.length
|
|
5417
|
+
});
|
|
5418
|
+
});
|
|
5419
|
+
return result.sort((a, b) => a.dateTs - b.dateTs);
|
|
5420
|
+
}
|
|
5421
|
+
function filterByDayPeriods(data, selectedPeriods) {
|
|
5422
|
+
if (selectedPeriods.length === 0 || selectedPeriods.length === DAY_PERIODS.length) {
|
|
5423
|
+
return data;
|
|
5424
|
+
}
|
|
5425
|
+
return data.filter((item) => {
|
|
5426
|
+
const date = new Date(item.ts);
|
|
5427
|
+
const hour = date.getHours();
|
|
5428
|
+
return selectedPeriods.some((periodId) => {
|
|
5429
|
+
const period = DAY_PERIODS.find((p) => p.id === periodId);
|
|
5430
|
+
if (!period) return false;
|
|
5431
|
+
return hour >= period.startHour && hour < period.endHour;
|
|
5432
|
+
});
|
|
5433
|
+
});
|
|
5434
|
+
}
|
|
5435
|
+
function getSelectedPeriodsLabel(selectedPeriods) {
|
|
5436
|
+
if (selectedPeriods.length === 0 || selectedPeriods.length === DAY_PERIODS.length) {
|
|
5437
|
+
return "Todos os per\xEDodos";
|
|
5438
|
+
}
|
|
5439
|
+
if (selectedPeriods.length === 1) {
|
|
5440
|
+
const period = DAY_PERIODS.find((p) => p.id === selectedPeriods[0]);
|
|
5441
|
+
return period?.label || "";
|
|
5442
|
+
}
|
|
5443
|
+
return `${selectedPeriods.length} per\xEDodos selecionados`;
|
|
5444
|
+
}
|
|
5445
|
+
function formatTemperature(value, decimals = 1) {
|
|
5446
|
+
if (value === null || value === void 0 || isNaN(value)) {
|
|
5447
|
+
return "\u2014";
|
|
5448
|
+
}
|
|
5449
|
+
return `${value.toFixed(decimals)}\xB0C`;
|
|
5450
|
+
}
|
|
5451
|
+
function exportTemperatureCSV(data, deviceLabel, stats, startDate, endDate) {
|
|
5452
|
+
if (data.length === 0) {
|
|
5453
|
+
console.warn("No data to export");
|
|
5454
|
+
return;
|
|
5455
|
+
}
|
|
5456
|
+
const BOM = "\uFEFF";
|
|
5457
|
+
let csvContent = BOM;
|
|
5458
|
+
csvContent += `Relat\xF3rio de Temperatura - ${deviceLabel}
|
|
5459
|
+
`;
|
|
5460
|
+
csvContent += `Per\xEDodo: ${startDate} at\xE9 ${endDate}
|
|
5461
|
+
`;
|
|
5462
|
+
csvContent += `M\xE9dia: ${formatTemperature(stats.avg)}
|
|
5463
|
+
`;
|
|
5464
|
+
csvContent += `M\xEDnima: ${formatTemperature(stats.min)}
|
|
5465
|
+
`;
|
|
5466
|
+
csvContent += `M\xE1xima: ${formatTemperature(stats.max)}
|
|
5467
|
+
`;
|
|
5468
|
+
csvContent += `Total de leituras: ${stats.count}
|
|
5469
|
+
`;
|
|
5470
|
+
csvContent += "\n";
|
|
5471
|
+
csvContent += "Data/Hora,Temperatura (\xB0C)\n";
|
|
5472
|
+
data.forEach((item) => {
|
|
5473
|
+
const date = new Date(item.ts).toLocaleString("pt-BR");
|
|
5474
|
+
const temp = Number(item.value).toFixed(2);
|
|
5475
|
+
csvContent += `"${date}",${temp}
|
|
5476
|
+
`;
|
|
5477
|
+
});
|
|
5478
|
+
const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" });
|
|
5479
|
+
const url = URL.createObjectURL(blob);
|
|
5480
|
+
const link = document.createElement("a");
|
|
5481
|
+
link.href = url;
|
|
5482
|
+
link.download = `temperatura_${deviceLabel.replace(/\s+/g, "_")}_${startDate}_${endDate}.csv`;
|
|
5483
|
+
document.body.appendChild(link);
|
|
5484
|
+
link.click();
|
|
5485
|
+
document.body.removeChild(link);
|
|
5486
|
+
URL.revokeObjectURL(url);
|
|
5487
|
+
}
|
|
5488
|
+
var DARK_THEME = {
|
|
5489
|
+
background: "rgba(0, 0, 0, 0.85)",
|
|
5490
|
+
surface: "#1a1f28",
|
|
5491
|
+
text: "#ffffff",
|
|
5492
|
+
textMuted: "rgba(255, 255, 255, 0.7)",
|
|
5493
|
+
border: "rgba(255, 255, 255, 0.1)",
|
|
5494
|
+
primary: "#1976d2",
|
|
5495
|
+
success: "#4CAF50",
|
|
5496
|
+
warning: "#FF9800",
|
|
5497
|
+
danger: "#f44336",
|
|
5498
|
+
chartLine: "#1976d2",
|
|
5499
|
+
chartGrid: "rgba(255, 255, 255, 0.1)"
|
|
5500
|
+
};
|
|
5501
|
+
var LIGHT_THEME = {
|
|
5502
|
+
background: "rgba(0, 0, 0, 0.6)",
|
|
5503
|
+
surface: "#ffffff",
|
|
5504
|
+
text: "#333333",
|
|
5505
|
+
textMuted: "#666666",
|
|
5506
|
+
border: "#e0e0e0",
|
|
5507
|
+
primary: "#1976d2",
|
|
5508
|
+
success: "#4CAF50",
|
|
5509
|
+
warning: "#FF9800",
|
|
5510
|
+
danger: "#f44336",
|
|
5511
|
+
chartLine: "#1976d2",
|
|
5512
|
+
chartGrid: "#e0e0e0"
|
|
5513
|
+
};
|
|
5514
|
+
function getThemeColors(theme) {
|
|
5515
|
+
return theme === "dark" ? DARK_THEME : LIGHT_THEME;
|
|
5516
|
+
}
|
|
5517
|
+
|
|
5518
|
+
// src/utils/logHelper.js
|
|
5519
|
+
function createLogHelper(debugActive = false) {
|
|
5520
|
+
return {
|
|
5521
|
+
log: function(...args) {
|
|
5522
|
+
if (debugActive) {
|
|
5523
|
+
console.log(...args);
|
|
5524
|
+
}
|
|
5525
|
+
},
|
|
5526
|
+
warn: function(...args) {
|
|
5527
|
+
if (debugActive) {
|
|
5528
|
+
console.warn(...args);
|
|
5529
|
+
}
|
|
5530
|
+
},
|
|
5531
|
+
error: function(...args) {
|
|
5532
|
+
console.error(...args);
|
|
5533
|
+
}
|
|
5534
|
+
};
|
|
5535
|
+
}
|
|
5536
|
+
var LogHelper = createLogHelper(false);
|
|
5537
|
+
|
|
4971
5538
|
// src/thingsboard/main-dashboard-shopping/v-4.0.0/card/head-office/card-head-office.js
|
|
5539
|
+
var LABEL_CHAR_LIMIT = 18;
|
|
5540
|
+
var DEFAUL_DELAY_TIME_CONNECTION_IN_MINS = 1440;
|
|
4972
5541
|
var CSS_TAG = "head-office-card-v1";
|
|
4973
5542
|
function ensureCss() {
|
|
4974
5543
|
if (!document.querySelector(`style[data-myio-css="${CSS_TAG}"]`)) {
|
|
@@ -4982,11 +5551,17 @@ function normalizeParams(params) {
|
|
|
4982
5551
|
if (!params || !params.entityObject) {
|
|
4983
5552
|
throw new Error("renderCardCompenteHeadOffice: entityObject is required");
|
|
4984
5553
|
}
|
|
5554
|
+
const LogHelper2 = createLogHelper(params.debugActive ?? false);
|
|
4985
5555
|
const entityObject = params.entityObject;
|
|
4986
5556
|
if (!entityObject.entityId) {
|
|
4987
|
-
|
|
5557
|
+
LogHelper2.warn("[CardHeadOffice] entityId is missing, generating temporary ID");
|
|
4988
5558
|
entityObject.entityId = `temp-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
4989
5559
|
}
|
|
5560
|
+
if (!params.delayTimeConnectionInMins) {
|
|
5561
|
+
LogHelper2.warn(
|
|
5562
|
+
`[CardHeadOffice] delayTimeConnectionInMins is missing, defaulting to ${DEFAUL_DELAY_TIME_CONNECTION_IN_MINS} mins`
|
|
5563
|
+
);
|
|
5564
|
+
}
|
|
4990
5565
|
return {
|
|
4991
5566
|
entityObject,
|
|
4992
5567
|
i18n: { ...DEFAULT_I18N, ...params.i18n || {} },
|
|
@@ -4994,7 +5569,12 @@ function normalizeParams(params) {
|
|
|
4994
5569
|
enableDragDrop: Boolean(params.enableDragDrop),
|
|
4995
5570
|
useNewComponents: Boolean(params.useNewComponents),
|
|
4996
5571
|
// RFC-0091: Configurable delay time for connection status check (default 15 minutes)
|
|
4997
|
-
delayTimeConnectionInMins: params.delayTimeConnectionInMins ??
|
|
5572
|
+
delayTimeConnectionInMins: params.delayTimeConnectionInMins ?? DEFAUL_DELAY_TIME_CONNECTION_IN_MINS,
|
|
5573
|
+
// Debug options
|
|
5574
|
+
debugActive: params.debugActive ?? false,
|
|
5575
|
+
activeTooltipDebug: params.activeTooltipDebug ?? false,
|
|
5576
|
+
// LogHelper instance for this card
|
|
5577
|
+
LogHelper: LogHelper2,
|
|
4998
5578
|
callbacks: {
|
|
4999
5579
|
handleActionDashboard: params.handleActionDashboard,
|
|
5000
5580
|
handleActionReport: params.handleActionReport,
|
|
@@ -5032,16 +5612,10 @@ function formatValueByDomain(value, domain) {
|
|
|
5032
5612
|
return formatWaterVolumeM3(value);
|
|
5033
5613
|
}
|
|
5034
5614
|
if (domain === "temperature") {
|
|
5035
|
-
return formatTemperature(value);
|
|
5615
|
+
return formatTemperature(value, 0);
|
|
5036
5616
|
}
|
|
5037
5617
|
return formatEnergy(value);
|
|
5038
5618
|
}
|
|
5039
|
-
function formatTemperature(temp) {
|
|
5040
|
-
if (temp === null || temp === void 0 || isNaN(temp)) {
|
|
5041
|
-
return "\u2014";
|
|
5042
|
-
}
|
|
5043
|
-
return `${temp.toFixed(0)}\xB0C`;
|
|
5044
|
-
}
|
|
5045
5619
|
function calculateConsumptionPercentage(target, consumption) {
|
|
5046
5620
|
const numericTarget = Number(target);
|
|
5047
5621
|
const numericConsumption = Number(consumption);
|
|
@@ -5056,32 +5630,32 @@ function getStatusInfo(deviceStatus, i18n, domain) {
|
|
|
5056
5630
|
// --- Novos Status de Temperatura ---
|
|
5057
5631
|
case "normal":
|
|
5058
5632
|
return { chipClass: "chip--ok", label: "Normal" };
|
|
5059
|
-
// Verde/Azul
|
|
5060
5633
|
case "cold":
|
|
5061
5634
|
return { chipClass: "chip--standby", label: "Frio" };
|
|
5062
|
-
// Azul claro/Ciano
|
|
5063
5635
|
case "hot":
|
|
5064
5636
|
return { chipClass: "chip--alert", label: "Quente" };
|
|
5065
|
-
//
|
|
5066
|
-
// --- Status Existentes ---
|
|
5637
|
+
// --- Status Existentes (aligned with getCardStateClass) ---
|
|
5067
5638
|
case DeviceStatusType.POWER_ON:
|
|
5068
5639
|
if (domain === "water") {
|
|
5069
|
-
return { chipClass: "chip--
|
|
5640
|
+
return { chipClass: "chip--power-on", label: i18n.in_operation_water };
|
|
5070
5641
|
}
|
|
5071
|
-
return { chipClass: "chip--
|
|
5642
|
+
return { chipClass: "chip--power-on", label: i18n.in_operation };
|
|
5072
5643
|
case DeviceStatusType.STANDBY:
|
|
5073
5644
|
return { chipClass: "chip--standby", label: i18n.standby };
|
|
5074
5645
|
case DeviceStatusType.WARNING:
|
|
5075
|
-
return { chipClass: "chip--
|
|
5646
|
+
return { chipClass: "chip--warning", label: i18n.alert };
|
|
5647
|
+
case DeviceStatusType.MAINTENANCE:
|
|
5648
|
+
return { chipClass: "chip--maintenance", label: i18n.maintenance };
|
|
5076
5649
|
case DeviceStatusType.FAILURE:
|
|
5077
|
-
case DeviceStatusType.POWER_OFF:
|
|
5078
5650
|
return { chipClass: "chip--failure", label: i18n.failure };
|
|
5079
|
-
case DeviceStatusType.
|
|
5080
|
-
return { chipClass: "chip--
|
|
5081
|
-
case DeviceStatusType.
|
|
5082
|
-
return { chipClass: "chip--offline", label: i18n.
|
|
5083
|
-
// Default (Cai aqui se não achar 'normal', 'hot' etc)
|
|
5651
|
+
case DeviceStatusType.POWER_OFF:
|
|
5652
|
+
return { chipClass: "chip--power-off", label: i18n.power_off || i18n.failure };
|
|
5653
|
+
case DeviceStatusType.OFFLINE:
|
|
5654
|
+
return { chipClass: "chip--offline", label: i18n.offline };
|
|
5084
5655
|
case DeviceStatusType.NO_INFO:
|
|
5656
|
+
return { chipClass: "chip--no-info", label: i18n.no_info || i18n.offline };
|
|
5657
|
+
case DeviceStatusType.NOT_INSTALLED:
|
|
5658
|
+
return { chipClass: "chip--not-installed", label: i18n.not_installed };
|
|
5085
5659
|
default:
|
|
5086
5660
|
return { chipClass: "chip--offline", label: i18n.offline };
|
|
5087
5661
|
}
|
|
@@ -5089,23 +5663,32 @@ function getStatusInfo(deviceStatus, i18n, domain) {
|
|
|
5089
5663
|
function getCardStateClass(deviceStatus) {
|
|
5090
5664
|
switch (deviceStatus) {
|
|
5091
5665
|
case DeviceStatusType.POWER_ON:
|
|
5092
|
-
return "is-
|
|
5666
|
+
return "is-power-on";
|
|
5093
5667
|
// Blue border
|
|
5094
5668
|
case DeviceStatusType.STANDBY:
|
|
5095
5669
|
return "is-standby";
|
|
5096
5670
|
// Green border
|
|
5097
5671
|
case DeviceStatusType.WARNING:
|
|
5672
|
+
return "is-warning";
|
|
5673
|
+
// Yellow border
|
|
5098
5674
|
case DeviceStatusType.MAINTENANCE:
|
|
5099
|
-
return "is-
|
|
5675
|
+
return "is-maintenance";
|
|
5100
5676
|
// Yellow border
|
|
5101
5677
|
case DeviceStatusType.FAILURE:
|
|
5102
|
-
case DeviceStatusType.POWER_OFF:
|
|
5103
5678
|
return "is-failure";
|
|
5104
|
-
// Red border
|
|
5679
|
+
// Dark Red border
|
|
5680
|
+
case DeviceStatusType.POWER_OFF:
|
|
5681
|
+
return "is-power-off";
|
|
5682
|
+
// Light Red border
|
|
5683
|
+
case DeviceStatusType.OFFLINE:
|
|
5684
|
+
return "is-offline";
|
|
5685
|
+
// Dark Gray border
|
|
5105
5686
|
case DeviceStatusType.NO_INFO:
|
|
5687
|
+
return "is-no-info";
|
|
5688
|
+
// Dark Orange border
|
|
5106
5689
|
case DeviceStatusType.NOT_INSTALLED:
|
|
5107
|
-
return "is-
|
|
5108
|
-
//
|
|
5690
|
+
return "is-not-installed";
|
|
5691
|
+
// Purple border
|
|
5109
5692
|
default:
|
|
5110
5693
|
return "";
|
|
5111
5694
|
}
|
|
@@ -5119,17 +5702,25 @@ function getStatusDotClass(deviceStatus) {
|
|
|
5119
5702
|
return "dot--standby";
|
|
5120
5703
|
case "hot":
|
|
5121
5704
|
return "dot--alert";
|
|
5122
|
-
// --- Status Existentes ---
|
|
5705
|
+
// --- Status Existentes (aligned with getCardStateClass) ---
|
|
5123
5706
|
case DeviceStatusType.POWER_ON:
|
|
5124
|
-
return "dot--
|
|
5707
|
+
return "dot--power-on";
|
|
5125
5708
|
case DeviceStatusType.STANDBY:
|
|
5126
5709
|
return "dot--standby";
|
|
5127
5710
|
case DeviceStatusType.WARNING:
|
|
5711
|
+
return "dot--warning";
|
|
5128
5712
|
case DeviceStatusType.MAINTENANCE:
|
|
5129
|
-
return "dot--
|
|
5713
|
+
return "dot--maintenance";
|
|
5130
5714
|
case DeviceStatusType.FAILURE:
|
|
5131
|
-
case DeviceStatusType.POWER_OFF:
|
|
5132
5715
|
return "dot--failure";
|
|
5716
|
+
case DeviceStatusType.POWER_OFF:
|
|
5717
|
+
return "dot--power-off";
|
|
5718
|
+
case DeviceStatusType.OFFLINE:
|
|
5719
|
+
return "dot--offline";
|
|
5720
|
+
case DeviceStatusType.NO_INFO:
|
|
5721
|
+
return "dot--no-info";
|
|
5722
|
+
case DeviceStatusType.NOT_INSTALLED:
|
|
5723
|
+
return "dot--not-installed";
|
|
5133
5724
|
default:
|
|
5134
5725
|
return "dot--offline";
|
|
5135
5726
|
}
|
|
@@ -5153,7 +5744,13 @@ function buildDOM(state) {
|
|
|
5153
5744
|
titleSection.className = "myio-ho-card__title";
|
|
5154
5745
|
const nameEl = document.createElement("div");
|
|
5155
5746
|
nameEl.className = "myio-ho-card__name";
|
|
5156
|
-
|
|
5747
|
+
const fullName = entityObject.labelOrName || "Unknown Device";
|
|
5748
|
+
if (fullName.length > LABEL_CHAR_LIMIT) {
|
|
5749
|
+
nameEl.textContent = fullName.slice(0, LABEL_CHAR_LIMIT) + "\u2026";
|
|
5750
|
+
nameEl.title = fullName;
|
|
5751
|
+
} else {
|
|
5752
|
+
nameEl.textContent = fullName;
|
|
5753
|
+
}
|
|
5157
5754
|
titleSection.appendChild(nameEl);
|
|
5158
5755
|
if (entityObject.deviceIdentifier) {
|
|
5159
5756
|
const codeEl = document.createElement("div");
|
|
@@ -5282,29 +5879,207 @@ function buildDOM(state) {
|
|
|
5282
5879
|
root.appendChild(footer);
|
|
5283
5880
|
return root;
|
|
5284
5881
|
}
|
|
5285
|
-
function
|
|
5882
|
+
function buildDebugTooltipInfo(entityObject, statusInfo, stateClass, statusDecisionSource, delayTimeConnectionInMins) {
|
|
5883
|
+
const formatTimestamp = (ts) => {
|
|
5884
|
+
if (!ts) return "N/A";
|
|
5885
|
+
const d = new Date(ts);
|
|
5886
|
+
return d.toLocaleString("pt-BR", {
|
|
5887
|
+
day: "2-digit",
|
|
5888
|
+
month: "2-digit",
|
|
5889
|
+
year: "numeric",
|
|
5890
|
+
hour: "2-digit",
|
|
5891
|
+
minute: "2-digit",
|
|
5892
|
+
second: "2-digit"
|
|
5893
|
+
});
|
|
5894
|
+
};
|
|
5895
|
+
return {
|
|
5896
|
+
// Entity identification
|
|
5897
|
+
entityId: entityObject.entityId || "N/A",
|
|
5898
|
+
name: entityObject.name || entityObject.nameEl || "N/A",
|
|
5899
|
+
domain: entityObject.domain || "energy",
|
|
5900
|
+
// Status decision chain
|
|
5901
|
+
originalDeviceStatus: entityObject._originalDeviceStatus || entityObject.deviceStatus,
|
|
5902
|
+
finalDeviceStatus: entityObject.deviceStatus,
|
|
5903
|
+
connectionStatus: entityObject.connectionStatus || "N/A",
|
|
5904
|
+
statusDecisionSource,
|
|
5905
|
+
// Visual output
|
|
5906
|
+
stateClass,
|
|
5907
|
+
chipClass: statusInfo.chipClass,
|
|
5908
|
+
chipLabel: statusInfo.label,
|
|
5909
|
+
// Connection timestamps
|
|
5910
|
+
lastConnectTime: formatTimestamp(entityObject.lastConnectTime),
|
|
5911
|
+
lastDisconnectTime: formatTimestamp(entityObject.lastDisconnectTime),
|
|
5912
|
+
delayTimeConnectionInMins,
|
|
5913
|
+
// Raw values
|
|
5914
|
+
val: entityObject.val,
|
|
5915
|
+
consumptionTargetValue: entityObject.consumptionTargetValue,
|
|
5916
|
+
deviceType: entityObject.deviceType || "N/A"
|
|
5917
|
+
};
|
|
5918
|
+
}
|
|
5919
|
+
function attachDebugTooltip(element, debugInfo) {
|
|
5920
|
+
const existingTooltip = element.querySelector(".debug-tooltip-container");
|
|
5921
|
+
if (existingTooltip) {
|
|
5922
|
+
existingTooltip.remove();
|
|
5923
|
+
}
|
|
5924
|
+
const tooltipContainer = document.createElement("div");
|
|
5925
|
+
tooltipContainer.className = "debug-tooltip-container";
|
|
5926
|
+
const tooltip = document.createElement("div");
|
|
5927
|
+
tooltip.className = "debug-tooltip";
|
|
5928
|
+
tooltip.innerHTML = `
|
|
5929
|
+
<div class="debug-tooltip__header">
|
|
5930
|
+
<span class="debug-tooltip__icon">\u{1F50D}</span>
|
|
5931
|
+
<span class="debug-tooltip__title">Debug Info</span>
|
|
5932
|
+
</div>
|
|
5933
|
+
<div class="debug-tooltip__content">
|
|
5934
|
+
<div class="debug-tooltip__section">
|
|
5935
|
+
<div class="debug-tooltip__section-title">\u{1F4CB} Identifica\xE7\xE3o</div>
|
|
5936
|
+
<div class="debug-tooltip__row">
|
|
5937
|
+
<span class="debug-tooltip__label">Entity ID:</span>
|
|
5938
|
+
<span class="debug-tooltip__value debug-tooltip__value--mono">${debugInfo.entityId}</span>
|
|
5939
|
+
</div>
|
|
5940
|
+
<div class="debug-tooltip__row">
|
|
5941
|
+
<span class="debug-tooltip__label">Nome:</span>
|
|
5942
|
+
<span class="debug-tooltip__value">${debugInfo.name}</span>
|
|
5943
|
+
</div>
|
|
5944
|
+
<div class="debug-tooltip__row">
|
|
5945
|
+
<span class="debug-tooltip__label">Dom\xEDnio:</span>
|
|
5946
|
+
<span class="debug-tooltip__value debug-tooltip__badge debug-tooltip__badge--${debugInfo.domain}">${debugInfo.domain}</span>
|
|
5947
|
+
</div>
|
|
5948
|
+
</div>
|
|
5949
|
+
|
|
5950
|
+
<div class="debug-tooltip__section">
|
|
5951
|
+
<div class="debug-tooltip__section-title">\u26A1 Decis\xE3o de Status</div>
|
|
5952
|
+
<div class="debug-tooltip__row">
|
|
5953
|
+
<span class="debug-tooltip__label">connectionStatus:</span>
|
|
5954
|
+
<span class="debug-tooltip__value debug-tooltip__value--mono">${debugInfo.connectionStatus}</span>
|
|
5955
|
+
</div>
|
|
5956
|
+
<div class="debug-tooltip__row">
|
|
5957
|
+
<span class="debug-tooltip__label">deviceStatus (final):</span>
|
|
5958
|
+
<span class="debug-tooltip__value debug-tooltip__badge">${debugInfo.finalDeviceStatus}</span>
|
|
5959
|
+
</div>
|
|
5960
|
+
<div class="debug-tooltip__row debug-tooltip__row--full">
|
|
5961
|
+
<span class="debug-tooltip__label">Fonte da decis\xE3o:</span>
|
|
5962
|
+
<span class="debug-tooltip__value debug-tooltip__value--highlight">${debugInfo.statusDecisionSource}</span>
|
|
5963
|
+
</div>
|
|
5964
|
+
</div>
|
|
5965
|
+
|
|
5966
|
+
<div class="debug-tooltip__section">
|
|
5967
|
+
<div class="debug-tooltip__section-title">\u{1F3A8} Output Visual</div>
|
|
5968
|
+
<div class="debug-tooltip__row">
|
|
5969
|
+
<span class="debug-tooltip__label">stateClass:</span>
|
|
5970
|
+
<span class="debug-tooltip__value debug-tooltip__value--mono">${debugInfo.stateClass}</span>
|
|
5971
|
+
</div>
|
|
5972
|
+
<div class="debug-tooltip__row">
|
|
5973
|
+
<span class="debug-tooltip__label">chipClass:</span>
|
|
5974
|
+
<span class="debug-tooltip__value debug-tooltip__value--mono">${debugInfo.chipClass}</span>
|
|
5975
|
+
</div>
|
|
5976
|
+
<div class="debug-tooltip__row">
|
|
5977
|
+
<span class="debug-tooltip__label">chipLabel:</span>
|
|
5978
|
+
<span class="debug-tooltip__value">${debugInfo.chipLabel}</span>
|
|
5979
|
+
</div>
|
|
5980
|
+
</div>
|
|
5981
|
+
|
|
5982
|
+
<div class="debug-tooltip__section">
|
|
5983
|
+
<div class="debug-tooltip__section-title">\u{1F550} Timestamps de Conex\xE3o</div>
|
|
5984
|
+
<div class="debug-tooltip__row">
|
|
5985
|
+
<span class="debug-tooltip__label">lastConnectTime:</span>
|
|
5986
|
+
<span class="debug-tooltip__value debug-tooltip__value--mono">${debugInfo.lastConnectTime}</span>
|
|
5987
|
+
</div>
|
|
5988
|
+
<div class="debug-tooltip__row">
|
|
5989
|
+
<span class="debug-tooltip__label">lastDisconnectTime:</span>
|
|
5990
|
+
<span class="debug-tooltip__value debug-tooltip__value--mono">${debugInfo.lastDisconnectTime}</span>
|
|
5991
|
+
</div>
|
|
5992
|
+
<div class="debug-tooltip__row">
|
|
5993
|
+
<span class="debug-tooltip__label">delayTime:</span>
|
|
5994
|
+
<span class="debug-tooltip__value">${debugInfo.delayTimeConnectionInMins} mins</span>
|
|
5995
|
+
</div>
|
|
5996
|
+
</div>
|
|
5997
|
+
|
|
5998
|
+
<div class="debug-tooltip__section">
|
|
5999
|
+
<div class="debug-tooltip__section-title">\u{1F4CA} Valores</div>
|
|
6000
|
+
<div class="debug-tooltip__row">
|
|
6001
|
+
<span class="debug-tooltip__label">val (consumo):</span>
|
|
6002
|
+
<span class="debug-tooltip__value">${debugInfo.val ?? "N/A"}</span>
|
|
6003
|
+
</div>
|
|
6004
|
+
<div class="debug-tooltip__row">
|
|
6005
|
+
<span class="debug-tooltip__label">target (meta):</span>
|
|
6006
|
+
<span class="debug-tooltip__value">${debugInfo.consumptionTargetValue ?? "N/A"}</span>
|
|
6007
|
+
</div>
|
|
6008
|
+
<div class="debug-tooltip__row">
|
|
6009
|
+
<span class="debug-tooltip__label">deviceType:</span>
|
|
6010
|
+
<span class="debug-tooltip__value debug-tooltip__value--mono">${debugInfo.deviceType}</span>
|
|
6011
|
+
</div>
|
|
6012
|
+
</div>
|
|
6013
|
+
</div>
|
|
6014
|
+
`;
|
|
6015
|
+
tooltipContainer.appendChild(tooltip);
|
|
6016
|
+
element.style.position = "relative";
|
|
6017
|
+
element.style.cursor = "help";
|
|
6018
|
+
element.appendChild(tooltipContainer);
|
|
6019
|
+
element.classList.add("has-debug-tooltip");
|
|
6020
|
+
}
|
|
6021
|
+
function verifyOfflineStatus(entityObject, delayTimeInMins = 15, LogHelper2) {
|
|
5286
6022
|
const lastConnectionTime = new Date(entityObject.lastConnectTime || 0);
|
|
5287
6023
|
const lastDisconnectTime = new Date(entityObject.lastDisconnectTime || 0);
|
|
5288
6024
|
const now = /* @__PURE__ */ new Date();
|
|
5289
6025
|
const delayTimeInMs = delayTimeInMins * 60 * 1e3;
|
|
5290
6026
|
const timeSinceConnection = now.getTime() - lastConnectionTime.getTime();
|
|
6027
|
+
let isOffline = false;
|
|
5291
6028
|
if (lastDisconnectTime.getTime() > lastConnectionTime.getTime()) {
|
|
5292
|
-
|
|
5293
|
-
|
|
5294
|
-
|
|
5295
|
-
|
|
6029
|
+
isOffline = true;
|
|
6030
|
+
LogHelper2.log(
|
|
6031
|
+
"[CardHeadOffice][ConnectionStatus Verify] Device is OFFLINE because lastDisconnectTime is more recent than lastConnectTime",
|
|
6032
|
+
entityObject.nameEl
|
|
6033
|
+
);
|
|
6034
|
+
} else if (timeSinceConnection > delayTimeInMs) {
|
|
6035
|
+
isOffline = true;
|
|
6036
|
+
LogHelper2.log(
|
|
6037
|
+
"[CardHeadOffice][ConnectionStatus Verify] Device is OFFLINE because lastConnectTime is older than configured delayTimeConnectionInMins:",
|
|
6038
|
+
delayTimeInMins,
|
|
6039
|
+
"for device",
|
|
6040
|
+
entityObject.nameEl
|
|
6041
|
+
);
|
|
6042
|
+
} else {
|
|
6043
|
+
isOffline = false;
|
|
6044
|
+
LogHelper2.log(
|
|
6045
|
+
"[CardHeadOffice][ConnectionStatus Verify] Device is ONLINE because lastConnectTime is within configured delayTimeConnectionInMins:",
|
|
6046
|
+
delayTimeInMins,
|
|
6047
|
+
"for device",
|
|
6048
|
+
entityObject.nameEl
|
|
6049
|
+
);
|
|
5296
6050
|
}
|
|
5297
|
-
return
|
|
6051
|
+
return isOffline;
|
|
5298
6052
|
}
|
|
5299
6053
|
function paint(root, state) {
|
|
5300
|
-
const { entityObject, i18n, delayTimeConnectionInMins, isSelected } = state;
|
|
6054
|
+
const { entityObject, i18n, delayTimeConnectionInMins, isSelected, LogHelper: LogHelper2, activeTooltipDebug } = state;
|
|
6055
|
+
let statusDecisionSource = "unknown";
|
|
5301
6056
|
if (entityObject.connectionStatus) {
|
|
5302
6057
|
if (entityObject.connectionStatus === "offline") {
|
|
5303
|
-
|
|
6058
|
+
LogHelper2.log(
|
|
6059
|
+
"[CardHeadOffice][ConnectionStatus Verify 01] Setting deviceStatus to OFFLINE based on connectionStatus"
|
|
6060
|
+
);
|
|
6061
|
+
entityObject.deviceStatus = DeviceStatusType.OFFLINE;
|
|
6062
|
+
statusDecisionSource = 'connectionStatus === "offline"';
|
|
6063
|
+
} else {
|
|
6064
|
+
LogHelper2.log(
|
|
6065
|
+
"[CardHeadOffice] Device is ONLINE or WAITING based on connectionStatus for device",
|
|
6066
|
+
entityObject.nameEl
|
|
6067
|
+
);
|
|
6068
|
+
statusDecisionSource = `connectionStatus === "${entityObject.connectionStatus}" (kept original deviceStatus)`;
|
|
5304
6069
|
}
|
|
5305
6070
|
} else {
|
|
5306
|
-
if (verifyOfflineStatus(entityObject, delayTimeConnectionInMins) === false) {
|
|
5307
|
-
|
|
6071
|
+
if (verifyOfflineStatus(entityObject, delayTimeConnectionInMins, LogHelper2) === false) {
|
|
6072
|
+
LogHelper2.log(
|
|
6073
|
+
"[CardHeadOffice][ConnectionStatus Verify 02] Setting deviceStatus to OFFLINE based on timestamp verification by verifyOfflineStatus METHOD with delayTimeConnectionInMins:",
|
|
6074
|
+
delayTimeConnectionInMins
|
|
6075
|
+
);
|
|
6076
|
+
entityObject.deviceStatus = DeviceStatusType.OFFLINE;
|
|
6077
|
+
statusDecisionSource = `verifyOfflineStatus() returned false (delay: ${delayTimeConnectionInMins} mins)`;
|
|
6078
|
+
} else {
|
|
6079
|
+
LogHelper2.log(
|
|
6080
|
+
`[CardHeadOffice][ConnectionStatus Verify 03] Device is ONLINE with deviceStatus = ${entityObject.deviceStatus} based on timestamp verification for device ${entityObject.nameEl}`
|
|
6081
|
+
);
|
|
6082
|
+
statusDecisionSource = `verifyOfflineStatus() returned true (delay: ${delayTimeConnectionInMins} mins)`;
|
|
5308
6083
|
}
|
|
5309
6084
|
}
|
|
5310
6085
|
const stateClass = getCardStateClass(entityObject.deviceStatus);
|
|
@@ -5313,6 +6088,10 @@ function paint(root, state) {
|
|
|
5313
6088
|
const chip = root.querySelector(".chip");
|
|
5314
6089
|
chip.className = `chip ${statusInfo.chipClass}`;
|
|
5315
6090
|
chip.innerHTML = statusInfo.label;
|
|
6091
|
+
if (activeTooltipDebug) {
|
|
6092
|
+
const debugInfo = buildDebugTooltipInfo(entityObject, statusInfo, stateClass, statusDecisionSource, delayTimeConnectionInMins);
|
|
6093
|
+
attachDebugTooltip(chip, debugInfo);
|
|
6094
|
+
}
|
|
5316
6095
|
const primaryValue = formatValueByDomain(entityObject.val, entityObject.domain);
|
|
5317
6096
|
const numSpan = root.querySelector(".myio-ho-card__value .num");
|
|
5318
6097
|
const unitSpan = root.querySelector(".myio-ho-card__value .unit");
|
|
@@ -5525,6 +6304,7 @@ function renderCardComponentHeadOffice(containerEl, params) {
|
|
|
5525
6304
|
}
|
|
5526
6305
|
|
|
5527
6306
|
// src/thingsboard/main-dashboard-shopping/v-5.2.0/card/template-card-v5.js
|
|
6307
|
+
var LABEL_CHAR_LIMIT2 = 18;
|
|
5528
6308
|
function renderCardComponentV5({
|
|
5529
6309
|
entityObject,
|
|
5530
6310
|
handleActionDashboard,
|
|
@@ -6041,7 +6821,7 @@ ${rangeText}`;
|
|
|
6041
6821
|
|
|
6042
6822
|
<div class="device-title-row" style="flex-direction: column; min-height: 38px; text-align: center; width: 100%;">
|
|
6043
6823
|
<span class="device-title" title="${cardEntity.name}">
|
|
6044
|
-
${cardEntity.name.length >
|
|
6824
|
+
${cardEntity.name.length > LABEL_CHAR_LIMIT2 ? cardEntity.name.slice(0, LABEL_CHAR_LIMIT2) + "\u2026" : cardEntity.name}
|
|
6045
6825
|
</span>
|
|
6046
6826
|
${deviceIdentifier ? `
|
|
6047
6827
|
<span class="device-subtitle" title="${deviceIdentifier}">
|
|
@@ -20368,220 +21148,6 @@ function openGoalsPanel(params) {
|
|
|
20368
21148
|
}
|
|
20369
21149
|
}
|
|
20370
21150
|
|
|
20371
|
-
// src/components/temperature/utils.ts
|
|
20372
|
-
var DAY_PERIODS = [
|
|
20373
|
-
{ id: "madrugada", label: "Madrugada (00h-06h)", startHour: 0, endHour: 6 },
|
|
20374
|
-
{ id: "manha", label: "Manh\xE3 (06h-12h)", startHour: 6, endHour: 12 },
|
|
20375
|
-
{ id: "tarde", label: "Tarde (12h-18h)", startHour: 12, endHour: 18 },
|
|
20376
|
-
{ id: "noite", label: "Noite (18h-24h)", startHour: 18, endHour: 24 }
|
|
20377
|
-
];
|
|
20378
|
-
var DEFAULT_CLAMP_RANGE = { min: 15, max: 40 };
|
|
20379
|
-
function getTodaySoFar() {
|
|
20380
|
-
const now = /* @__PURE__ */ new Date();
|
|
20381
|
-
const startOfDay = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0, 0);
|
|
20382
|
-
return {
|
|
20383
|
-
startTs: startOfDay.getTime(),
|
|
20384
|
-
endTs: now.getTime()
|
|
20385
|
-
};
|
|
20386
|
-
}
|
|
20387
|
-
var CHART_COLORS = [
|
|
20388
|
-
"#1976d2",
|
|
20389
|
-
// Blue
|
|
20390
|
-
"#FF6B6B",
|
|
20391
|
-
// Red
|
|
20392
|
-
"#4CAF50",
|
|
20393
|
-
// Green
|
|
20394
|
-
"#FF9800",
|
|
20395
|
-
// Orange
|
|
20396
|
-
"#9C27B0",
|
|
20397
|
-
// Purple
|
|
20398
|
-
"#00BCD4",
|
|
20399
|
-
// Cyan
|
|
20400
|
-
"#E91E63",
|
|
20401
|
-
// Pink
|
|
20402
|
-
"#795548"
|
|
20403
|
-
// Brown
|
|
20404
|
-
];
|
|
20405
|
-
async function fetchTemperatureData(token, deviceId, startTs, endTs) {
|
|
20406
|
-
const url = `/api/plugins/telemetry/DEVICE/${deviceId}/values/timeseries?keys=temperature&startTs=${encodeURIComponent(startTs)}&endTs=${encodeURIComponent(endTs)}&limit=50000&agg=NONE`;
|
|
20407
|
-
const response = await fetch(url, {
|
|
20408
|
-
headers: {
|
|
20409
|
-
"X-Authorization": `Bearer ${token}`,
|
|
20410
|
-
"Content-Type": "application/json"
|
|
20411
|
-
}
|
|
20412
|
-
});
|
|
20413
|
-
if (!response.ok) {
|
|
20414
|
-
throw new Error(`Failed to fetch temperature data: ${response.status}`);
|
|
20415
|
-
}
|
|
20416
|
-
const data = await response.json();
|
|
20417
|
-
return data?.temperature || [];
|
|
20418
|
-
}
|
|
20419
|
-
function clampTemperature(value, range = DEFAULT_CLAMP_RANGE) {
|
|
20420
|
-
const num = Number(value || 0);
|
|
20421
|
-
if (num < range.min) return range.min;
|
|
20422
|
-
if (num > range.max) return range.max;
|
|
20423
|
-
return num;
|
|
20424
|
-
}
|
|
20425
|
-
function calculateStats(data, clampRange = DEFAULT_CLAMP_RANGE) {
|
|
20426
|
-
if (data.length === 0) {
|
|
20427
|
-
return { avg: 0, min: 0, max: 0, count: 0 };
|
|
20428
|
-
}
|
|
20429
|
-
const values = data.map((item) => clampTemperature(item.value, clampRange));
|
|
20430
|
-
const sum = values.reduce((acc, v) => acc + v, 0);
|
|
20431
|
-
return {
|
|
20432
|
-
avg: sum / values.length,
|
|
20433
|
-
min: Math.min(...values),
|
|
20434
|
-
max: Math.max(...values),
|
|
20435
|
-
count: values.length
|
|
20436
|
-
};
|
|
20437
|
-
}
|
|
20438
|
-
function interpolateTemperature(data, options) {
|
|
20439
|
-
const { intervalMinutes, startTs, endTs, clampRange = DEFAULT_CLAMP_RANGE } = options;
|
|
20440
|
-
const intervalMs = intervalMinutes * 60 * 1e3;
|
|
20441
|
-
if (data.length === 0) {
|
|
20442
|
-
return [];
|
|
20443
|
-
}
|
|
20444
|
-
const sortedData = [...data].sort((a, b) => a.ts - b.ts);
|
|
20445
|
-
const result = [];
|
|
20446
|
-
let lastKnownValue = clampTemperature(sortedData[0].value, clampRange);
|
|
20447
|
-
let dataIndex = 0;
|
|
20448
|
-
for (let ts = startTs; ts <= endTs; ts += intervalMs) {
|
|
20449
|
-
while (dataIndex < sortedData.length - 1 && sortedData[dataIndex + 1].ts <= ts) {
|
|
20450
|
-
dataIndex++;
|
|
20451
|
-
}
|
|
20452
|
-
const currentData = sortedData[dataIndex];
|
|
20453
|
-
if (currentData && Math.abs(currentData.ts - ts) < intervalMs) {
|
|
20454
|
-
lastKnownValue = clampTemperature(currentData.value, clampRange);
|
|
20455
|
-
}
|
|
20456
|
-
result.push({
|
|
20457
|
-
ts,
|
|
20458
|
-
value: lastKnownValue
|
|
20459
|
-
});
|
|
20460
|
-
}
|
|
20461
|
-
return result;
|
|
20462
|
-
}
|
|
20463
|
-
function aggregateByDay(data, clampRange = DEFAULT_CLAMP_RANGE) {
|
|
20464
|
-
if (data.length === 0) {
|
|
20465
|
-
return [];
|
|
20466
|
-
}
|
|
20467
|
-
const dayMap = /* @__PURE__ */ new Map();
|
|
20468
|
-
data.forEach((item) => {
|
|
20469
|
-
const date = new Date(item.ts);
|
|
20470
|
-
const dateKey = date.toISOString().split("T")[0];
|
|
20471
|
-
if (!dayMap.has(dateKey)) {
|
|
20472
|
-
dayMap.set(dateKey, []);
|
|
20473
|
-
}
|
|
20474
|
-
dayMap.get(dateKey).push(item);
|
|
20475
|
-
});
|
|
20476
|
-
const result = [];
|
|
20477
|
-
dayMap.forEach((dayData, dateKey) => {
|
|
20478
|
-
const values = dayData.map((item) => clampTemperature(item.value, clampRange));
|
|
20479
|
-
const sum = values.reduce((acc, v) => acc + v, 0);
|
|
20480
|
-
result.push({
|
|
20481
|
-
date: dateKey,
|
|
20482
|
-
dateTs: new Date(dateKey).getTime(),
|
|
20483
|
-
avg: sum / values.length,
|
|
20484
|
-
min: Math.min(...values),
|
|
20485
|
-
max: Math.max(...values),
|
|
20486
|
-
count: values.length
|
|
20487
|
-
});
|
|
20488
|
-
});
|
|
20489
|
-
return result.sort((a, b) => a.dateTs - b.dateTs);
|
|
20490
|
-
}
|
|
20491
|
-
function filterByDayPeriods(data, selectedPeriods) {
|
|
20492
|
-
if (selectedPeriods.length === 0 || selectedPeriods.length === DAY_PERIODS.length) {
|
|
20493
|
-
return data;
|
|
20494
|
-
}
|
|
20495
|
-
return data.filter((item) => {
|
|
20496
|
-
const date = new Date(item.ts);
|
|
20497
|
-
const hour = date.getHours();
|
|
20498
|
-
return selectedPeriods.some((periodId) => {
|
|
20499
|
-
const period = DAY_PERIODS.find((p) => p.id === periodId);
|
|
20500
|
-
if (!period) return false;
|
|
20501
|
-
return hour >= period.startHour && hour < period.endHour;
|
|
20502
|
-
});
|
|
20503
|
-
});
|
|
20504
|
-
}
|
|
20505
|
-
function getSelectedPeriodsLabel(selectedPeriods) {
|
|
20506
|
-
if (selectedPeriods.length === 0 || selectedPeriods.length === DAY_PERIODS.length) {
|
|
20507
|
-
return "Todos os per\xEDodos";
|
|
20508
|
-
}
|
|
20509
|
-
if (selectedPeriods.length === 1) {
|
|
20510
|
-
const period = DAY_PERIODS.find((p) => p.id === selectedPeriods[0]);
|
|
20511
|
-
return period?.label || "";
|
|
20512
|
-
}
|
|
20513
|
-
return `${selectedPeriods.length} per\xEDodos selecionados`;
|
|
20514
|
-
}
|
|
20515
|
-
function formatTemperature2(value, decimals = 1) {
|
|
20516
|
-
return `${value.toFixed(decimals)}\xB0C`;
|
|
20517
|
-
}
|
|
20518
|
-
function exportTemperatureCSV(data, deviceLabel, stats, startDate, endDate) {
|
|
20519
|
-
if (data.length === 0) {
|
|
20520
|
-
console.warn("No data to export");
|
|
20521
|
-
return;
|
|
20522
|
-
}
|
|
20523
|
-
const BOM = "\uFEFF";
|
|
20524
|
-
let csvContent = BOM;
|
|
20525
|
-
csvContent += `Relat\xF3rio de Temperatura - ${deviceLabel}
|
|
20526
|
-
`;
|
|
20527
|
-
csvContent += `Per\xEDodo: ${startDate} at\xE9 ${endDate}
|
|
20528
|
-
`;
|
|
20529
|
-
csvContent += `M\xE9dia: ${formatTemperature2(stats.avg)}
|
|
20530
|
-
`;
|
|
20531
|
-
csvContent += `M\xEDnima: ${formatTemperature2(stats.min)}
|
|
20532
|
-
`;
|
|
20533
|
-
csvContent += `M\xE1xima: ${formatTemperature2(stats.max)}
|
|
20534
|
-
`;
|
|
20535
|
-
csvContent += `Total de leituras: ${stats.count}
|
|
20536
|
-
`;
|
|
20537
|
-
csvContent += "\n";
|
|
20538
|
-
csvContent += "Data/Hora,Temperatura (\xB0C)\n";
|
|
20539
|
-
data.forEach((item) => {
|
|
20540
|
-
const date = new Date(item.ts).toLocaleString("pt-BR");
|
|
20541
|
-
const temp = Number(item.value).toFixed(2);
|
|
20542
|
-
csvContent += `"${date}",${temp}
|
|
20543
|
-
`;
|
|
20544
|
-
});
|
|
20545
|
-
const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" });
|
|
20546
|
-
const url = URL.createObjectURL(blob);
|
|
20547
|
-
const link = document.createElement("a");
|
|
20548
|
-
link.href = url;
|
|
20549
|
-
link.download = `temperatura_${deviceLabel.replace(/\s+/g, "_")}_${startDate}_${endDate}.csv`;
|
|
20550
|
-
document.body.appendChild(link);
|
|
20551
|
-
link.click();
|
|
20552
|
-
document.body.removeChild(link);
|
|
20553
|
-
URL.revokeObjectURL(url);
|
|
20554
|
-
}
|
|
20555
|
-
var DARK_THEME = {
|
|
20556
|
-
background: "rgba(0, 0, 0, 0.85)",
|
|
20557
|
-
surface: "#1a1f28",
|
|
20558
|
-
text: "#ffffff",
|
|
20559
|
-
textMuted: "rgba(255, 255, 255, 0.7)",
|
|
20560
|
-
border: "rgba(255, 255, 255, 0.1)",
|
|
20561
|
-
primary: "#1976d2",
|
|
20562
|
-
success: "#4CAF50",
|
|
20563
|
-
warning: "#FF9800",
|
|
20564
|
-
danger: "#f44336",
|
|
20565
|
-
chartLine: "#1976d2",
|
|
20566
|
-
chartGrid: "rgba(255, 255, 255, 0.1)"
|
|
20567
|
-
};
|
|
20568
|
-
var LIGHT_THEME = {
|
|
20569
|
-
background: "rgba(0, 0, 0, 0.6)",
|
|
20570
|
-
surface: "#ffffff",
|
|
20571
|
-
text: "#333333",
|
|
20572
|
-
textMuted: "#666666",
|
|
20573
|
-
border: "#e0e0e0",
|
|
20574
|
-
primary: "#1976d2",
|
|
20575
|
-
success: "#4CAF50",
|
|
20576
|
-
warning: "#FF9800",
|
|
20577
|
-
danger: "#f44336",
|
|
20578
|
-
chartLine: "#1976d2",
|
|
20579
|
-
chartGrid: "#e0e0e0"
|
|
20580
|
-
};
|
|
20581
|
-
function getThemeColors(theme) {
|
|
20582
|
-
return theme === "dark" ? DARK_THEME : LIGHT_THEME;
|
|
20583
|
-
}
|
|
20584
|
-
|
|
20585
21151
|
// src/components/temperature/TemperatureModal.ts
|
|
20586
21152
|
async function openTemperatureModal(params) {
|
|
20587
21153
|
const modalId = `myio-temp-modal-${Date.now()}`;
|
|
@@ -20821,7 +21387,7 @@ function renderModal(container, state, modalId, error) {
|
|
|
20821
21387
|
">
|
|
20822
21388
|
<span style="color: ${colors.textMuted}; font-size: 12px; font-weight: 500;">Temperatura Atual</span>
|
|
20823
21389
|
<div style="font-weight: 700; font-size: 24px; color: ${statusColor}; margin-top: 4px;">
|
|
20824
|
-
${state.currentTemperature !== null ?
|
|
21390
|
+
${state.currentTemperature !== null ? formatTemperature(state.currentTemperature) : "N/A"}
|
|
20825
21391
|
</div>
|
|
20826
21392
|
<div style="font-size: 11px; color: ${statusColor}; margin-top: 2px;">${statusText}</div>
|
|
20827
21393
|
</div>
|
|
@@ -20832,7 +21398,7 @@ function renderModal(container, state, modalId, error) {
|
|
|
20832
21398
|
">
|
|
20833
21399
|
<span style="color: ${colors.textMuted}; font-size: 12px; font-weight: 500;">M\xE9dia do Per\xEDodo</span>
|
|
20834
21400
|
<div id="${modalId}-avg" style="font-weight: 600; font-size: 20px; color: ${colors.text}; margin-top: 4px;">
|
|
20835
|
-
${state.stats.count > 0 ?
|
|
21401
|
+
${state.stats.count > 0 ? formatTemperature(state.stats.avg) : "N/A"}
|
|
20836
21402
|
</div>
|
|
20837
21403
|
<div style="font-size: 11px; color: ${colors.textMuted}; margin-top: 2px;">${startDateStr} - ${endDateStr}</div>
|
|
20838
21404
|
</div>
|
|
@@ -20843,7 +21409,7 @@ function renderModal(container, state, modalId, error) {
|
|
|
20843
21409
|
">
|
|
20844
21410
|
<span style="color: ${colors.textMuted}; font-size: 12px; font-weight: 500;">Min / Max</span>
|
|
20845
21411
|
<div id="${modalId}-minmax" style="font-weight: 600; font-size: 20px; color: ${colors.text}; margin-top: 4px;">
|
|
20846
|
-
${state.stats.count > 0 ? `${
|
|
21412
|
+
${state.stats.count > 0 ? `${formatTemperature(state.stats.min)} / ${formatTemperature(state.stats.max)}` : "N/A"}
|
|
20847
21413
|
</div>
|
|
20848
21414
|
<div style="font-size: 11px; color: ${colors.textMuted}; margin-top: 2px;">${state.stats.count} leituras</div>
|
|
20849
21415
|
</div>
|
|
@@ -21159,7 +21725,7 @@ function setupChartTooltip(canvas, container, chartData, state, colors) {
|
|
|
21159
21725
|
}
|
|
21160
21726
|
tooltip.innerHTML = `
|
|
21161
21727
|
<div style="font-weight: 600; margin-bottom: 6px; color: ${colors.primary};">
|
|
21162
|
-
${
|
|
21728
|
+
${formatTemperature(point.y)}
|
|
21163
21729
|
</div>
|
|
21164
21730
|
<div style="font-size: 11px; color: ${colors.textMuted};">
|
|
21165
21731
|
\u{1F4C5} ${dateStr}
|
|
@@ -21422,7 +21988,7 @@ function renderModal2(container, state, modalId) {
|
|
|
21422
21988
|
<span style="width: 12px; height: 12px; border-radius: 50%; background: ${dd.color};"></span>
|
|
21423
21989
|
<span style="color: ${colors.text}; font-size: 13px;">${dd.device.label}</span>
|
|
21424
21990
|
<span style="color: ${colors.textMuted}; font-size: 11px; margin-left: auto;">
|
|
21425
|
-
${dd.stats.count > 0 ?
|
|
21991
|
+
${dd.stats.count > 0 ? formatTemperature(dd.stats.avg) : "N/A"}
|
|
21426
21992
|
</span>
|
|
21427
21993
|
</div>
|
|
21428
21994
|
`).join("");
|
|
@@ -21438,15 +22004,15 @@ function renderModal2(container, state, modalId) {
|
|
|
21438
22004
|
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 4px; font-size: 11px;">
|
|
21439
22005
|
<span style="color: ${colors.textMuted};">M\xE9dia:</span>
|
|
21440
22006
|
<span style="color: ${colors.text}; font-weight: 500;">
|
|
21441
|
-
${dd.stats.count > 0 ?
|
|
22007
|
+
${dd.stats.count > 0 ? formatTemperature(dd.stats.avg) : "N/A"}
|
|
21442
22008
|
</span>
|
|
21443
22009
|
<span style="color: ${colors.textMuted};">Min:</span>
|
|
21444
22010
|
<span style="color: ${colors.text};">
|
|
21445
|
-
${dd.stats.count > 0 ?
|
|
22011
|
+
${dd.stats.count > 0 ? formatTemperature(dd.stats.min) : "N/A"}
|
|
21446
22012
|
</span>
|
|
21447
22013
|
<span style="color: ${colors.textMuted};">Max:</span>
|
|
21448
22014
|
<span style="color: ${colors.text};">
|
|
21449
|
-
${dd.stats.count > 0 ?
|
|
22015
|
+
${dd.stats.count > 0 ? formatTemperature(dd.stats.max) : "N/A"}
|
|
21450
22016
|
</span>
|
|
21451
22017
|
<span style="color: ${colors.textMuted};">Leituras:</span>
|
|
21452
22018
|
<span style="color: ${colors.text};">${dd.stats.count}</span>
|
|
@@ -21982,7 +22548,7 @@ function setupComparisonChartTooltip(canvas, container, chartData, state, colors
|
|
|
21982
22548
|
<span style="font-weight: 600;">${point.deviceLabel}</span>
|
|
21983
22549
|
</div>
|
|
21984
22550
|
<div style="font-weight: 600; font-size: 16px; color: ${point.deviceColor}; margin-bottom: 4px;">
|
|
21985
|
-
${
|
|
22551
|
+
${formatTemperature(point.y)}
|
|
21986
22552
|
</div>
|
|
21987
22553
|
<div style="font-size: 11px; color: ${colors.textMuted};">
|
|
21988
22554
|
\u{1F4C5} ${dateStr}
|