myio-js-library 0.1.144 → 0.1.146
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 +164 -50
- package/dist/index.d.cts +1 -0
- package/dist/index.js +164 -50
- package/dist/myio-js-library.umd.js +164 -50
- package/dist/myio-js-library.umd.min.js +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -5043,15 +5043,41 @@ function buildDOM(state) {
|
|
|
5043
5043
|
function verifyOfflineStatus(entityObject) {
|
|
5044
5044
|
const lastConnectionTime = new Date(entityObject.lastConnectTime || 0);
|
|
5045
5045
|
const lastDisconnectTime = new Date(entityObject.lastDisconnectTime || 0);
|
|
5046
|
-
if (lastDisconnectTime.getTime() > lastConnectionTime.getTime()) {
|
|
5047
|
-
return false;
|
|
5048
|
-
}
|
|
5049
5046
|
const now = /* @__PURE__ */ new Date();
|
|
5050
5047
|
const fifteenMinutesInMs = 15 * 60 * 1e3;
|
|
5051
5048
|
const timeSinceConnection = now.getTime() - lastConnectionTime.getTime();
|
|
5049
|
+
if (String(entityObject.labelOrName || "").toLowerCase().includes("chiller 1")) {
|
|
5050
|
+
console.log("[DEBUG CHILLER 1 - verifyOfflineStatus] ========================================");
|
|
5051
|
+
console.log("[DEBUG CHILLER 1 - verifyOfflineStatus] label:", entityObject.labelOrName);
|
|
5052
|
+
console.log("[DEBUG CHILLER 1 - verifyOfflineStatus] deviceStatus (before):", entityObject.deviceStatus);
|
|
5053
|
+
console.log("[DEBUG CHILLER 1 - verifyOfflineStatus] lastConnectTime (raw):", entityObject.lastConnectTime);
|
|
5054
|
+
console.log("[DEBUG CHILLER 1 - verifyOfflineStatus] lastDisconnectTime (raw):", entityObject.lastDisconnectTime);
|
|
5055
|
+
console.log("[DEBUG CHILLER 1 - verifyOfflineStatus] lastConnectionTime (Date):", lastConnectionTime.toISOString());
|
|
5056
|
+
console.log("[DEBUG CHILLER 1 - verifyOfflineStatus] lastDisconnectTime (Date):", lastDisconnectTime.toISOString());
|
|
5057
|
+
console.log("[DEBUG CHILLER 1 - verifyOfflineStatus] now:", now.toISOString());
|
|
5058
|
+
console.log("[DEBUG CHILLER 1 - verifyOfflineStatus] timeSinceConnection (ms):", timeSinceConnection);
|
|
5059
|
+
console.log("[DEBUG CHILLER 1 - verifyOfflineStatus] timeSinceConnection (min):", (timeSinceConnection / 6e4).toFixed(2));
|
|
5060
|
+
console.log("[DEBUG CHILLER 1 - verifyOfflineStatus] disconnect > connect?", lastDisconnectTime.getTime() > lastConnectionTime.getTime());
|
|
5061
|
+
console.log("[DEBUG CHILLER 1 - verifyOfflineStatus] timeSinceConnection < 15min?", timeSinceConnection < fifteenMinutesInMs);
|
|
5062
|
+
}
|
|
5063
|
+
if (lastDisconnectTime.getTime() > lastConnectionTime.getTime()) {
|
|
5064
|
+
if (String(entityObject.labelOrName || "").toLowerCase().includes("chiller 1")) {
|
|
5065
|
+
console.log("[DEBUG CHILLER 1 - verifyOfflineStatus] RESULT: false (disconnect > connect)");
|
|
5066
|
+
console.log("[DEBUG CHILLER 1 - verifyOfflineStatus] ========================================");
|
|
5067
|
+
}
|
|
5068
|
+
return false;
|
|
5069
|
+
}
|
|
5052
5070
|
if (timeSinceConnection < fifteenMinutesInMs) {
|
|
5071
|
+
if (String(entityObject.labelOrName || "").toLowerCase().includes("chiller 1")) {
|
|
5072
|
+
console.log("[DEBUG CHILLER 1 - verifyOfflineStatus] RESULT: false (connection < 15min ago)");
|
|
5073
|
+
console.log("[DEBUG CHILLER 1 - verifyOfflineStatus] ========================================");
|
|
5074
|
+
}
|
|
5053
5075
|
return false;
|
|
5054
5076
|
}
|
|
5077
|
+
if (String(entityObject.labelOrName || "").toLowerCase().includes("chiller 1")) {
|
|
5078
|
+
console.log("[DEBUG CHILLER 1 - verifyOfflineStatus] RESULT: true (online)");
|
|
5079
|
+
console.log("[DEBUG CHILLER 1 - verifyOfflineStatus] ========================================");
|
|
5080
|
+
}
|
|
5055
5081
|
return true;
|
|
5056
5082
|
}
|
|
5057
5083
|
function paint(root, state) {
|
|
@@ -15403,7 +15429,13 @@ var SettingsModalView = class {
|
|
|
15403
15429
|
render(initialData) {
|
|
15404
15430
|
this.originalActiveElement = document.activeElement;
|
|
15405
15431
|
document.body.appendChild(this.container);
|
|
15406
|
-
|
|
15432
|
+
let formData = { ...initialData };
|
|
15433
|
+
if (initialData.deviceMapInstaneousPower && typeof initialData.deviceMapInstaneousPower === "object") {
|
|
15434
|
+
console.log("[SettingsModalView] Configura\xE7\xE3o salva encontrada (Device Scope). Processando...");
|
|
15435
|
+
const flatLimits = this.parseDeviceSavedLimits(initialData.deviceMapInstaneousPower);
|
|
15436
|
+
formData = { ...formData, ...flatLimits };
|
|
15437
|
+
}
|
|
15438
|
+
this.populateForm(formData);
|
|
15407
15439
|
this.attachEventListeners();
|
|
15408
15440
|
this.setupAccessibility();
|
|
15409
15441
|
this.setupFocusTrap();
|
|
@@ -16972,6 +17004,42 @@ var SettingsModalView = class {
|
|
|
16972
17004
|
}
|
|
16973
17005
|
}
|
|
16974
17006
|
}
|
|
17007
|
+
/**
|
|
17008
|
+
* Helper: Traduz o JSON RFC-0086 (deviceMapInstaneousPower)
|
|
17009
|
+
* para os campos planos do formulário (ex: standbyLimitUpConsumption)
|
|
17010
|
+
*/
|
|
17011
|
+
parseDeviceSavedLimits(deviceJson) {
|
|
17012
|
+
const extracted = {};
|
|
17013
|
+
try {
|
|
17014
|
+
if (!deviceJson || !deviceJson.limitsByInstantaneoustPowerType) return extracted;
|
|
17015
|
+
const consumptionGroup = deviceJson.limitsByInstantaneoustPowerType.find(
|
|
17016
|
+
(g) => g.telemetryType === "consumption"
|
|
17017
|
+
);
|
|
17018
|
+
const deviceItem = consumptionGroup?.itemsByDeviceType?.[0];
|
|
17019
|
+
if (!deviceItem?.limitsByDeviceStatus) return extracted;
|
|
17020
|
+
const mapPrefix = {
|
|
17021
|
+
"standBy": "standby",
|
|
17022
|
+
"normal": "normal",
|
|
17023
|
+
"alert": "alert",
|
|
17024
|
+
"failure": "failure"
|
|
17025
|
+
};
|
|
17026
|
+
deviceItem.limitsByDeviceStatus.forEach((status) => {
|
|
17027
|
+
const prefix = mapPrefix[status.deviceStatusName];
|
|
17028
|
+
if (prefix && status.limitsValues) {
|
|
17029
|
+
const { baseValue, topValue } = status.limitsValues;
|
|
17030
|
+
if (baseValue !== null && baseValue !== void 0) {
|
|
17031
|
+
extracted[`${prefix}LimitDownConsumption`] = baseValue;
|
|
17032
|
+
}
|
|
17033
|
+
if (topValue !== null && topValue !== void 0) {
|
|
17034
|
+
extracted[`${prefix}LimitUpConsumption`] = topValue;
|
|
17035
|
+
}
|
|
17036
|
+
}
|
|
17037
|
+
});
|
|
17038
|
+
} catch (e) {
|
|
17039
|
+
console.warn("[SettingsModalView] Erro ao processar deviceMapInstaneousPower:", e);
|
|
17040
|
+
}
|
|
17041
|
+
return extracted;
|
|
17042
|
+
}
|
|
16975
17043
|
attachEventListeners() {
|
|
16976
17044
|
this.form.addEventListener("submit", (event) => {
|
|
16977
17045
|
event.preventDefault();
|
|
@@ -17243,11 +17311,25 @@ var DefaultSettingsPersister = class {
|
|
|
17243
17311
|
}
|
|
17244
17312
|
async saveServerScopeAttributes(deviceId, attributes) {
|
|
17245
17313
|
try {
|
|
17246
|
-
const
|
|
17247
|
-
const
|
|
17248
|
-
|
|
17249
|
-
|
|
17250
|
-
|
|
17314
|
+
const payload = { ...attributes };
|
|
17315
|
+
const effectiveDeviceType = this.getEffectiveDeviceType();
|
|
17316
|
+
const deviceJson = this.buildDevicePowerJson(payload, effectiveDeviceType);
|
|
17317
|
+
if (deviceJson) {
|
|
17318
|
+
payload.deviceMapInstaneousPower = deviceJson;
|
|
17319
|
+
}
|
|
17320
|
+
const flatKeysToRemove = [
|
|
17321
|
+
"telemetryType",
|
|
17322
|
+
"standbyLimitDownConsumption",
|
|
17323
|
+
"standbyLimitUpConsumption",
|
|
17324
|
+
"normalLimitDownConsumption",
|
|
17325
|
+
"normalLimitUpConsumption",
|
|
17326
|
+
"alertLimitDownConsumption",
|
|
17327
|
+
"alertLimitUpConsumption",
|
|
17328
|
+
"failureLimitDownConsumption",
|
|
17329
|
+
"failureLimitUpConsumption"
|
|
17330
|
+
];
|
|
17331
|
+
flatKeysToRemove.forEach((key) => delete payload[key]);
|
|
17332
|
+
console.log("[SettingsPersister] Saving Server Scope Attributes:", payload);
|
|
17251
17333
|
const res = await fetch(
|
|
17252
17334
|
`${this.tbBaseUrl}/api/plugins/telemetry/DEVICE/${deviceId}/attributes/SERVER_SCOPE`,
|
|
17253
17335
|
{
|
|
@@ -17264,13 +17346,70 @@ var DefaultSettingsPersister = class {
|
|
|
17264
17346
|
}
|
|
17265
17347
|
return {
|
|
17266
17348
|
ok: true,
|
|
17267
|
-
updatedKeys:
|
|
17349
|
+
updatedKeys: Object.keys(payload)
|
|
17268
17350
|
};
|
|
17269
17351
|
} catch (error) {
|
|
17270
17352
|
console.error("[SettingsPersister] Attributes save failed:", error);
|
|
17271
17353
|
return { ok: false, error: this.mapError(error) };
|
|
17272
17354
|
}
|
|
17273
17355
|
}
|
|
17356
|
+
/**
|
|
17357
|
+
* Constrói o JSON Reduzido (apenas o deviceType atual) para salvar no Device.
|
|
17358
|
+
* Retorna null se nenhum campo de potência estiver presente.
|
|
17359
|
+
*/
|
|
17360
|
+
buildDevicePowerJson(formData, deviceType) {
|
|
17361
|
+
const statuses = ["standby", "normal", "alert", "failure"];
|
|
17362
|
+
const hasPowerData = statuses.some(
|
|
17363
|
+
(status) => formData[`${status}LimitDownConsumption`] !== void 0 && formData[`${status}LimitDownConsumption`] !== "" || formData[`${status}LimitUpConsumption`] !== void 0 && formData[`${status}LimitUpConsumption`] !== ""
|
|
17364
|
+
);
|
|
17365
|
+
if (!hasPowerData) return null;
|
|
17366
|
+
const statusMap = {
|
|
17367
|
+
"standby": "standBy",
|
|
17368
|
+
"normal": "normal",
|
|
17369
|
+
"alert": "alert",
|
|
17370
|
+
"failure": "failure"
|
|
17371
|
+
};
|
|
17372
|
+
const limitsList = [];
|
|
17373
|
+
statuses.forEach((statusKey) => {
|
|
17374
|
+
const down = formData[`${statusKey}LimitDownConsumption`];
|
|
17375
|
+
const up = formData[`${statusKey}LimitUpConsumption`];
|
|
17376
|
+
if (down !== void 0 && down !== "" || up !== void 0 && up !== "") {
|
|
17377
|
+
limitsList.push({
|
|
17378
|
+
deviceStatusName: statusMap[statusKey],
|
|
17379
|
+
limitsValues: {
|
|
17380
|
+
// Converte para Number ou null
|
|
17381
|
+
baseValue: down !== "" && down !== void 0 ? Number(down) : null,
|
|
17382
|
+
topValue: up !== "" && up !== void 0 ? Number(up) : null
|
|
17383
|
+
}
|
|
17384
|
+
});
|
|
17385
|
+
}
|
|
17386
|
+
});
|
|
17387
|
+
if (limitsList.length === 0) return null;
|
|
17388
|
+
return {
|
|
17389
|
+
version: "1.0.0",
|
|
17390
|
+
limitsByInstantaneoustPowerType: [
|
|
17391
|
+
{
|
|
17392
|
+
telemetryType: "consumption",
|
|
17393
|
+
itemsByDeviceType: [
|
|
17394
|
+
{
|
|
17395
|
+
deviceType,
|
|
17396
|
+
// Gera um nome descritivo interno
|
|
17397
|
+
name: `deviceMapInstaneousPower${this.formatDeviceTypeName(deviceType)}`,
|
|
17398
|
+
description: "Override manual configurado via Dashboard",
|
|
17399
|
+
limitsByDeviceStatus: limitsList
|
|
17400
|
+
}
|
|
17401
|
+
]
|
|
17402
|
+
}
|
|
17403
|
+
]
|
|
17404
|
+
};
|
|
17405
|
+
}
|
|
17406
|
+
/**
|
|
17407
|
+
* Helper para formatar o nome do tipo (PascalCase) para uso no campo "name" do JSON
|
|
17408
|
+
*/
|
|
17409
|
+
formatDeviceTypeName(deviceType) {
|
|
17410
|
+
if (!deviceType) return "";
|
|
17411
|
+
return deviceType.charAt(0).toUpperCase() + deviceType.slice(1).toLowerCase();
|
|
17412
|
+
}
|
|
17274
17413
|
/**
|
|
17275
17414
|
* RFC-0086: Build mapInstantaneousPower JSON structure from form data
|
|
17276
17415
|
* IMPORTANT: When saving to a DEVICE, only include entries for the specific deviceType
|
|
@@ -17327,25 +17466,6 @@ var DefaultSettingsPersister = class {
|
|
|
17327
17466
|
console.log(`[SettingsPersister] RFC-0086: Built mapInstantaneousPower for deviceType=${effectiveDeviceType}:`, result);
|
|
17328
17467
|
return result;
|
|
17329
17468
|
}
|
|
17330
|
-
/**
|
|
17331
|
-
* Format device type name for display (e.g., ELEVADOR -> Elevador)
|
|
17332
|
-
*/
|
|
17333
|
-
formatDeviceTypeName(deviceType) {
|
|
17334
|
-
const map = {
|
|
17335
|
-
"ELEVADOR": "Elevator",
|
|
17336
|
-
"ESCADA_ROLANTE": "Escalator",
|
|
17337
|
-
"MOTOR": "Motor",
|
|
17338
|
-
"BOMBA": "Pump",
|
|
17339
|
-
"3F_MEDIDOR": "3FMedidor",
|
|
17340
|
-
"CHILLER": "Chiller",
|
|
17341
|
-
"FANCOIL": "Fancoil",
|
|
17342
|
-
"AR_CONDICIONADO": "AirConditioner",
|
|
17343
|
-
"HVAC": "HVAC",
|
|
17344
|
-
"HIDROMETRO": "Hidrometro",
|
|
17345
|
-
"TERMOSTATO": "Termostato"
|
|
17346
|
-
};
|
|
17347
|
-
return map[deviceType] || deviceType;
|
|
17348
|
-
}
|
|
17349
17469
|
sanitizeLabel(label) {
|
|
17350
17470
|
return label.trim().slice(0, 255).replace(/[\x00-\x1F\x7F]/g, "");
|
|
17351
17471
|
}
|
|
@@ -17482,18 +17602,16 @@ var DefaultSettingsFetcher = class {
|
|
|
17482
17602
|
}
|
|
17483
17603
|
const attributesArray = await response.json();
|
|
17484
17604
|
const attributes = {};
|
|
17485
|
-
const settingsNamespace = "myio.settings.energy.";
|
|
17486
17605
|
for (const attr of attributesArray) {
|
|
17487
17606
|
if (attr.key && attr.value !== void 0 && attr.value !== null && attr.value !== "") {
|
|
17488
|
-
if (attr.key
|
|
17489
|
-
const key = attr.key.replace(settingsNamespace, "");
|
|
17490
|
-
if (key !== "__version") {
|
|
17491
|
-
attributes[key] = attr.value;
|
|
17492
|
-
}
|
|
17493
|
-
} else if (attr.key === "floor") {
|
|
17607
|
+
if (attr.key === "floor") {
|
|
17494
17608
|
attributes.floor = attr.value;
|
|
17495
17609
|
} else if (attr.key === "identifier") {
|
|
17496
17610
|
attributes.identifier = attr.value;
|
|
17611
|
+
} else if (attr.key === "mapInstantaneousPower") {
|
|
17612
|
+
attributes.mapInstantaneousPower = attr.value;
|
|
17613
|
+
} else if (attr.key === "deviceMapInstaneousPower") {
|
|
17614
|
+
attributes.deviceMapInstaneousPower = attr.value;
|
|
17497
17615
|
}
|
|
17498
17616
|
}
|
|
17499
17617
|
}
|
|
@@ -17515,23 +17633,12 @@ var DefaultSettingsFetcher = class {
|
|
|
17515
17633
|
}
|
|
17516
17634
|
return merged;
|
|
17517
17635
|
}
|
|
17518
|
-
/**
|
|
17519
|
-
* Utility method to validate and sanitize fetched data
|
|
17520
|
-
*/
|
|
17521
17636
|
static sanitizeFetchedData(data) {
|
|
17522
17637
|
const sanitized = {};
|
|
17523
17638
|
const stringFields = [
|
|
17524
17639
|
"label",
|
|
17525
17640
|
"floor",
|
|
17526
|
-
"identifier"
|
|
17527
|
-
"alertLimitDownConsumption",
|
|
17528
|
-
"alertLimitUpConsumption",
|
|
17529
|
-
"failureLimitDownConsumption",
|
|
17530
|
-
"failureLimitUpConsumption",
|
|
17531
|
-
"normalLimitDownConsumption",
|
|
17532
|
-
"normalLimitUpConsumption",
|
|
17533
|
-
"standbyLimitDownConsumption",
|
|
17534
|
-
"standbyLimitUpConsumption"
|
|
17641
|
+
"identifier"
|
|
17535
17642
|
];
|
|
17536
17643
|
for (const field of stringFields) {
|
|
17537
17644
|
if (data[field] && typeof data[field] === "string") {
|
|
@@ -17547,6 +17654,12 @@ var DefaultSettingsFetcher = class {
|
|
|
17547
17654
|
}
|
|
17548
17655
|
}
|
|
17549
17656
|
}
|
|
17657
|
+
const objectFields = ["mapInstantaneousPower", "deviceMapInstaneousPower"];
|
|
17658
|
+
for (const field of objectFields) {
|
|
17659
|
+
if (data[field] && typeof data[field] === "object") {
|
|
17660
|
+
sanitized[field] = data[field];
|
|
17661
|
+
}
|
|
17662
|
+
}
|
|
17550
17663
|
return sanitized;
|
|
17551
17664
|
}
|
|
17552
17665
|
};
|
|
@@ -17596,8 +17709,9 @@ var SettingsController = class {
|
|
|
17596
17709
|
// Pass connection info for display
|
|
17597
17710
|
onSave: this.handleSave.bind(this),
|
|
17598
17711
|
onClose: this.handleClose.bind(this),
|
|
17599
|
-
mapInstantaneousPower: params.mapInstantaneousPower
|
|
17600
|
-
// RFC-0077: Pass instantaneous power map for Power Limits feature
|
|
17712
|
+
mapInstantaneousPower: params.mapInstantaneousPower,
|
|
17713
|
+
// RFC-0077: Pass instantaneous power map for Power Limits feature,
|
|
17714
|
+
deviceMapInstaneousPower: params.deviceMapInstaneousPower
|
|
17601
17715
|
});
|
|
17602
17716
|
}
|
|
17603
17717
|
async show() {
|
package/dist/index.d.cts
CHANGED
|
@@ -1634,6 +1634,7 @@ interface OpenDashboardPopupSettingsParams {
|
|
|
1634
1634
|
customerName?: string;
|
|
1635
1635
|
customerId?: string;
|
|
1636
1636
|
mapInstantaneousPower?: object;
|
|
1637
|
+
deviceMapInstaneousPower?: object;
|
|
1637
1638
|
connectionData?: {
|
|
1638
1639
|
centralName?: string;
|
|
1639
1640
|
connectionStatusTime?: string;
|
package/dist/index.js
CHANGED
|
@@ -4935,15 +4935,41 @@ function buildDOM(state) {
|
|
|
4935
4935
|
function verifyOfflineStatus(entityObject) {
|
|
4936
4936
|
const lastConnectionTime = new Date(entityObject.lastConnectTime || 0);
|
|
4937
4937
|
const lastDisconnectTime = new Date(entityObject.lastDisconnectTime || 0);
|
|
4938
|
-
if (lastDisconnectTime.getTime() > lastConnectionTime.getTime()) {
|
|
4939
|
-
return false;
|
|
4940
|
-
}
|
|
4941
4938
|
const now = /* @__PURE__ */ new Date();
|
|
4942
4939
|
const fifteenMinutesInMs = 15 * 60 * 1e3;
|
|
4943
4940
|
const timeSinceConnection = now.getTime() - lastConnectionTime.getTime();
|
|
4941
|
+
if (String(entityObject.labelOrName || "").toLowerCase().includes("chiller 1")) {
|
|
4942
|
+
console.log("[DEBUG CHILLER 1 - verifyOfflineStatus] ========================================");
|
|
4943
|
+
console.log("[DEBUG CHILLER 1 - verifyOfflineStatus] label:", entityObject.labelOrName);
|
|
4944
|
+
console.log("[DEBUG CHILLER 1 - verifyOfflineStatus] deviceStatus (before):", entityObject.deviceStatus);
|
|
4945
|
+
console.log("[DEBUG CHILLER 1 - verifyOfflineStatus] lastConnectTime (raw):", entityObject.lastConnectTime);
|
|
4946
|
+
console.log("[DEBUG CHILLER 1 - verifyOfflineStatus] lastDisconnectTime (raw):", entityObject.lastDisconnectTime);
|
|
4947
|
+
console.log("[DEBUG CHILLER 1 - verifyOfflineStatus] lastConnectionTime (Date):", lastConnectionTime.toISOString());
|
|
4948
|
+
console.log("[DEBUG CHILLER 1 - verifyOfflineStatus] lastDisconnectTime (Date):", lastDisconnectTime.toISOString());
|
|
4949
|
+
console.log("[DEBUG CHILLER 1 - verifyOfflineStatus] now:", now.toISOString());
|
|
4950
|
+
console.log("[DEBUG CHILLER 1 - verifyOfflineStatus] timeSinceConnection (ms):", timeSinceConnection);
|
|
4951
|
+
console.log("[DEBUG CHILLER 1 - verifyOfflineStatus] timeSinceConnection (min):", (timeSinceConnection / 6e4).toFixed(2));
|
|
4952
|
+
console.log("[DEBUG CHILLER 1 - verifyOfflineStatus] disconnect > connect?", lastDisconnectTime.getTime() > lastConnectionTime.getTime());
|
|
4953
|
+
console.log("[DEBUG CHILLER 1 - verifyOfflineStatus] timeSinceConnection < 15min?", timeSinceConnection < fifteenMinutesInMs);
|
|
4954
|
+
}
|
|
4955
|
+
if (lastDisconnectTime.getTime() > lastConnectionTime.getTime()) {
|
|
4956
|
+
if (String(entityObject.labelOrName || "").toLowerCase().includes("chiller 1")) {
|
|
4957
|
+
console.log("[DEBUG CHILLER 1 - verifyOfflineStatus] RESULT: false (disconnect > connect)");
|
|
4958
|
+
console.log("[DEBUG CHILLER 1 - verifyOfflineStatus] ========================================");
|
|
4959
|
+
}
|
|
4960
|
+
return false;
|
|
4961
|
+
}
|
|
4944
4962
|
if (timeSinceConnection < fifteenMinutesInMs) {
|
|
4963
|
+
if (String(entityObject.labelOrName || "").toLowerCase().includes("chiller 1")) {
|
|
4964
|
+
console.log("[DEBUG CHILLER 1 - verifyOfflineStatus] RESULT: false (connection < 15min ago)");
|
|
4965
|
+
console.log("[DEBUG CHILLER 1 - verifyOfflineStatus] ========================================");
|
|
4966
|
+
}
|
|
4945
4967
|
return false;
|
|
4946
4968
|
}
|
|
4969
|
+
if (String(entityObject.labelOrName || "").toLowerCase().includes("chiller 1")) {
|
|
4970
|
+
console.log("[DEBUG CHILLER 1 - verifyOfflineStatus] RESULT: true (online)");
|
|
4971
|
+
console.log("[DEBUG CHILLER 1 - verifyOfflineStatus] ========================================");
|
|
4972
|
+
}
|
|
4947
4973
|
return true;
|
|
4948
4974
|
}
|
|
4949
4975
|
function paint(root, state) {
|
|
@@ -15295,7 +15321,13 @@ var SettingsModalView = class {
|
|
|
15295
15321
|
render(initialData) {
|
|
15296
15322
|
this.originalActiveElement = document.activeElement;
|
|
15297
15323
|
document.body.appendChild(this.container);
|
|
15298
|
-
|
|
15324
|
+
let formData = { ...initialData };
|
|
15325
|
+
if (initialData.deviceMapInstaneousPower && typeof initialData.deviceMapInstaneousPower === "object") {
|
|
15326
|
+
console.log("[SettingsModalView] Configura\xE7\xE3o salva encontrada (Device Scope). Processando...");
|
|
15327
|
+
const flatLimits = this.parseDeviceSavedLimits(initialData.deviceMapInstaneousPower);
|
|
15328
|
+
formData = { ...formData, ...flatLimits };
|
|
15329
|
+
}
|
|
15330
|
+
this.populateForm(formData);
|
|
15299
15331
|
this.attachEventListeners();
|
|
15300
15332
|
this.setupAccessibility();
|
|
15301
15333
|
this.setupFocusTrap();
|
|
@@ -16864,6 +16896,42 @@ var SettingsModalView = class {
|
|
|
16864
16896
|
}
|
|
16865
16897
|
}
|
|
16866
16898
|
}
|
|
16899
|
+
/**
|
|
16900
|
+
* Helper: Traduz o JSON RFC-0086 (deviceMapInstaneousPower)
|
|
16901
|
+
* para os campos planos do formulário (ex: standbyLimitUpConsumption)
|
|
16902
|
+
*/
|
|
16903
|
+
parseDeviceSavedLimits(deviceJson) {
|
|
16904
|
+
const extracted = {};
|
|
16905
|
+
try {
|
|
16906
|
+
if (!deviceJson || !deviceJson.limitsByInstantaneoustPowerType) return extracted;
|
|
16907
|
+
const consumptionGroup = deviceJson.limitsByInstantaneoustPowerType.find(
|
|
16908
|
+
(g) => g.telemetryType === "consumption"
|
|
16909
|
+
);
|
|
16910
|
+
const deviceItem = consumptionGroup?.itemsByDeviceType?.[0];
|
|
16911
|
+
if (!deviceItem?.limitsByDeviceStatus) return extracted;
|
|
16912
|
+
const mapPrefix = {
|
|
16913
|
+
"standBy": "standby",
|
|
16914
|
+
"normal": "normal",
|
|
16915
|
+
"alert": "alert",
|
|
16916
|
+
"failure": "failure"
|
|
16917
|
+
};
|
|
16918
|
+
deviceItem.limitsByDeviceStatus.forEach((status) => {
|
|
16919
|
+
const prefix = mapPrefix[status.deviceStatusName];
|
|
16920
|
+
if (prefix && status.limitsValues) {
|
|
16921
|
+
const { baseValue, topValue } = status.limitsValues;
|
|
16922
|
+
if (baseValue !== null && baseValue !== void 0) {
|
|
16923
|
+
extracted[`${prefix}LimitDownConsumption`] = baseValue;
|
|
16924
|
+
}
|
|
16925
|
+
if (topValue !== null && topValue !== void 0) {
|
|
16926
|
+
extracted[`${prefix}LimitUpConsumption`] = topValue;
|
|
16927
|
+
}
|
|
16928
|
+
}
|
|
16929
|
+
});
|
|
16930
|
+
} catch (e) {
|
|
16931
|
+
console.warn("[SettingsModalView] Erro ao processar deviceMapInstaneousPower:", e);
|
|
16932
|
+
}
|
|
16933
|
+
return extracted;
|
|
16934
|
+
}
|
|
16867
16935
|
attachEventListeners() {
|
|
16868
16936
|
this.form.addEventListener("submit", (event) => {
|
|
16869
16937
|
event.preventDefault();
|
|
@@ -17135,11 +17203,25 @@ var DefaultSettingsPersister = class {
|
|
|
17135
17203
|
}
|
|
17136
17204
|
async saveServerScopeAttributes(deviceId, attributes) {
|
|
17137
17205
|
try {
|
|
17138
|
-
const
|
|
17139
|
-
const
|
|
17140
|
-
|
|
17141
|
-
|
|
17142
|
-
|
|
17206
|
+
const payload = { ...attributes };
|
|
17207
|
+
const effectiveDeviceType = this.getEffectiveDeviceType();
|
|
17208
|
+
const deviceJson = this.buildDevicePowerJson(payload, effectiveDeviceType);
|
|
17209
|
+
if (deviceJson) {
|
|
17210
|
+
payload.deviceMapInstaneousPower = deviceJson;
|
|
17211
|
+
}
|
|
17212
|
+
const flatKeysToRemove = [
|
|
17213
|
+
"telemetryType",
|
|
17214
|
+
"standbyLimitDownConsumption",
|
|
17215
|
+
"standbyLimitUpConsumption",
|
|
17216
|
+
"normalLimitDownConsumption",
|
|
17217
|
+
"normalLimitUpConsumption",
|
|
17218
|
+
"alertLimitDownConsumption",
|
|
17219
|
+
"alertLimitUpConsumption",
|
|
17220
|
+
"failureLimitDownConsumption",
|
|
17221
|
+
"failureLimitUpConsumption"
|
|
17222
|
+
];
|
|
17223
|
+
flatKeysToRemove.forEach((key) => delete payload[key]);
|
|
17224
|
+
console.log("[SettingsPersister] Saving Server Scope Attributes:", payload);
|
|
17143
17225
|
const res = await fetch(
|
|
17144
17226
|
`${this.tbBaseUrl}/api/plugins/telemetry/DEVICE/${deviceId}/attributes/SERVER_SCOPE`,
|
|
17145
17227
|
{
|
|
@@ -17156,13 +17238,70 @@ var DefaultSettingsPersister = class {
|
|
|
17156
17238
|
}
|
|
17157
17239
|
return {
|
|
17158
17240
|
ok: true,
|
|
17159
|
-
updatedKeys:
|
|
17241
|
+
updatedKeys: Object.keys(payload)
|
|
17160
17242
|
};
|
|
17161
17243
|
} catch (error) {
|
|
17162
17244
|
console.error("[SettingsPersister] Attributes save failed:", error);
|
|
17163
17245
|
return { ok: false, error: this.mapError(error) };
|
|
17164
17246
|
}
|
|
17165
17247
|
}
|
|
17248
|
+
/**
|
|
17249
|
+
* Constrói o JSON Reduzido (apenas o deviceType atual) para salvar no Device.
|
|
17250
|
+
* Retorna null se nenhum campo de potência estiver presente.
|
|
17251
|
+
*/
|
|
17252
|
+
buildDevicePowerJson(formData, deviceType) {
|
|
17253
|
+
const statuses = ["standby", "normal", "alert", "failure"];
|
|
17254
|
+
const hasPowerData = statuses.some(
|
|
17255
|
+
(status) => formData[`${status}LimitDownConsumption`] !== void 0 && formData[`${status}LimitDownConsumption`] !== "" || formData[`${status}LimitUpConsumption`] !== void 0 && formData[`${status}LimitUpConsumption`] !== ""
|
|
17256
|
+
);
|
|
17257
|
+
if (!hasPowerData) return null;
|
|
17258
|
+
const statusMap = {
|
|
17259
|
+
"standby": "standBy",
|
|
17260
|
+
"normal": "normal",
|
|
17261
|
+
"alert": "alert",
|
|
17262
|
+
"failure": "failure"
|
|
17263
|
+
};
|
|
17264
|
+
const limitsList = [];
|
|
17265
|
+
statuses.forEach((statusKey) => {
|
|
17266
|
+
const down = formData[`${statusKey}LimitDownConsumption`];
|
|
17267
|
+
const up = formData[`${statusKey}LimitUpConsumption`];
|
|
17268
|
+
if (down !== void 0 && down !== "" || up !== void 0 && up !== "") {
|
|
17269
|
+
limitsList.push({
|
|
17270
|
+
deviceStatusName: statusMap[statusKey],
|
|
17271
|
+
limitsValues: {
|
|
17272
|
+
// Converte para Number ou null
|
|
17273
|
+
baseValue: down !== "" && down !== void 0 ? Number(down) : null,
|
|
17274
|
+
topValue: up !== "" && up !== void 0 ? Number(up) : null
|
|
17275
|
+
}
|
|
17276
|
+
});
|
|
17277
|
+
}
|
|
17278
|
+
});
|
|
17279
|
+
if (limitsList.length === 0) return null;
|
|
17280
|
+
return {
|
|
17281
|
+
version: "1.0.0",
|
|
17282
|
+
limitsByInstantaneoustPowerType: [
|
|
17283
|
+
{
|
|
17284
|
+
telemetryType: "consumption",
|
|
17285
|
+
itemsByDeviceType: [
|
|
17286
|
+
{
|
|
17287
|
+
deviceType,
|
|
17288
|
+
// Gera um nome descritivo interno
|
|
17289
|
+
name: `deviceMapInstaneousPower${this.formatDeviceTypeName(deviceType)}`,
|
|
17290
|
+
description: "Override manual configurado via Dashboard",
|
|
17291
|
+
limitsByDeviceStatus: limitsList
|
|
17292
|
+
}
|
|
17293
|
+
]
|
|
17294
|
+
}
|
|
17295
|
+
]
|
|
17296
|
+
};
|
|
17297
|
+
}
|
|
17298
|
+
/**
|
|
17299
|
+
* Helper para formatar o nome do tipo (PascalCase) para uso no campo "name" do JSON
|
|
17300
|
+
*/
|
|
17301
|
+
formatDeviceTypeName(deviceType) {
|
|
17302
|
+
if (!deviceType) return "";
|
|
17303
|
+
return deviceType.charAt(0).toUpperCase() + deviceType.slice(1).toLowerCase();
|
|
17304
|
+
}
|
|
17166
17305
|
/**
|
|
17167
17306
|
* RFC-0086: Build mapInstantaneousPower JSON structure from form data
|
|
17168
17307
|
* IMPORTANT: When saving to a DEVICE, only include entries for the specific deviceType
|
|
@@ -17219,25 +17358,6 @@ var DefaultSettingsPersister = class {
|
|
|
17219
17358
|
console.log(`[SettingsPersister] RFC-0086: Built mapInstantaneousPower for deviceType=${effectiveDeviceType}:`, result);
|
|
17220
17359
|
return result;
|
|
17221
17360
|
}
|
|
17222
|
-
/**
|
|
17223
|
-
* Format device type name for display (e.g., ELEVADOR -> Elevador)
|
|
17224
|
-
*/
|
|
17225
|
-
formatDeviceTypeName(deviceType) {
|
|
17226
|
-
const map = {
|
|
17227
|
-
"ELEVADOR": "Elevator",
|
|
17228
|
-
"ESCADA_ROLANTE": "Escalator",
|
|
17229
|
-
"MOTOR": "Motor",
|
|
17230
|
-
"BOMBA": "Pump",
|
|
17231
|
-
"3F_MEDIDOR": "3FMedidor",
|
|
17232
|
-
"CHILLER": "Chiller",
|
|
17233
|
-
"FANCOIL": "Fancoil",
|
|
17234
|
-
"AR_CONDICIONADO": "AirConditioner",
|
|
17235
|
-
"HVAC": "HVAC",
|
|
17236
|
-
"HIDROMETRO": "Hidrometro",
|
|
17237
|
-
"TERMOSTATO": "Termostato"
|
|
17238
|
-
};
|
|
17239
|
-
return map[deviceType] || deviceType;
|
|
17240
|
-
}
|
|
17241
17361
|
sanitizeLabel(label) {
|
|
17242
17362
|
return label.trim().slice(0, 255).replace(/[\x00-\x1F\x7F]/g, "");
|
|
17243
17363
|
}
|
|
@@ -17374,18 +17494,16 @@ var DefaultSettingsFetcher = class {
|
|
|
17374
17494
|
}
|
|
17375
17495
|
const attributesArray = await response.json();
|
|
17376
17496
|
const attributes = {};
|
|
17377
|
-
const settingsNamespace = "myio.settings.energy.";
|
|
17378
17497
|
for (const attr of attributesArray) {
|
|
17379
17498
|
if (attr.key && attr.value !== void 0 && attr.value !== null && attr.value !== "") {
|
|
17380
|
-
if (attr.key
|
|
17381
|
-
const key = attr.key.replace(settingsNamespace, "");
|
|
17382
|
-
if (key !== "__version") {
|
|
17383
|
-
attributes[key] = attr.value;
|
|
17384
|
-
}
|
|
17385
|
-
} else if (attr.key === "floor") {
|
|
17499
|
+
if (attr.key === "floor") {
|
|
17386
17500
|
attributes.floor = attr.value;
|
|
17387
17501
|
} else if (attr.key === "identifier") {
|
|
17388
17502
|
attributes.identifier = attr.value;
|
|
17503
|
+
} else if (attr.key === "mapInstantaneousPower") {
|
|
17504
|
+
attributes.mapInstantaneousPower = attr.value;
|
|
17505
|
+
} else if (attr.key === "deviceMapInstaneousPower") {
|
|
17506
|
+
attributes.deviceMapInstaneousPower = attr.value;
|
|
17389
17507
|
}
|
|
17390
17508
|
}
|
|
17391
17509
|
}
|
|
@@ -17407,23 +17525,12 @@ var DefaultSettingsFetcher = class {
|
|
|
17407
17525
|
}
|
|
17408
17526
|
return merged;
|
|
17409
17527
|
}
|
|
17410
|
-
/**
|
|
17411
|
-
* Utility method to validate and sanitize fetched data
|
|
17412
|
-
*/
|
|
17413
17528
|
static sanitizeFetchedData(data) {
|
|
17414
17529
|
const sanitized = {};
|
|
17415
17530
|
const stringFields = [
|
|
17416
17531
|
"label",
|
|
17417
17532
|
"floor",
|
|
17418
|
-
"identifier"
|
|
17419
|
-
"alertLimitDownConsumption",
|
|
17420
|
-
"alertLimitUpConsumption",
|
|
17421
|
-
"failureLimitDownConsumption",
|
|
17422
|
-
"failureLimitUpConsumption",
|
|
17423
|
-
"normalLimitDownConsumption",
|
|
17424
|
-
"normalLimitUpConsumption",
|
|
17425
|
-
"standbyLimitDownConsumption",
|
|
17426
|
-
"standbyLimitUpConsumption"
|
|
17533
|
+
"identifier"
|
|
17427
17534
|
];
|
|
17428
17535
|
for (const field of stringFields) {
|
|
17429
17536
|
if (data[field] && typeof data[field] === "string") {
|
|
@@ -17439,6 +17546,12 @@ var DefaultSettingsFetcher = class {
|
|
|
17439
17546
|
}
|
|
17440
17547
|
}
|
|
17441
17548
|
}
|
|
17549
|
+
const objectFields = ["mapInstantaneousPower", "deviceMapInstaneousPower"];
|
|
17550
|
+
for (const field of objectFields) {
|
|
17551
|
+
if (data[field] && typeof data[field] === "object") {
|
|
17552
|
+
sanitized[field] = data[field];
|
|
17553
|
+
}
|
|
17554
|
+
}
|
|
17442
17555
|
return sanitized;
|
|
17443
17556
|
}
|
|
17444
17557
|
};
|
|
@@ -17488,8 +17601,9 @@ var SettingsController = class {
|
|
|
17488
17601
|
// Pass connection info for display
|
|
17489
17602
|
onSave: this.handleSave.bind(this),
|
|
17490
17603
|
onClose: this.handleClose.bind(this),
|
|
17491
|
-
mapInstantaneousPower: params.mapInstantaneousPower
|
|
17492
|
-
// RFC-0077: Pass instantaneous power map for Power Limits feature
|
|
17604
|
+
mapInstantaneousPower: params.mapInstantaneousPower,
|
|
17605
|
+
// RFC-0077: Pass instantaneous power map for Power Limits feature,
|
|
17606
|
+
deviceMapInstaneousPower: params.deviceMapInstaneousPower
|
|
17493
17607
|
});
|
|
17494
17608
|
}
|
|
17495
17609
|
async show() {
|