myio-js-library 0.1.143 → 0.1.145
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 +142 -48
- package/dist/index.d.cts +1 -0
- package/dist/index.js +142 -48
- package/dist/myio-js-library.umd.js +142 -48
- package/dist/myio-js-library.umd.min.js +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -4811,6 +4811,12 @@ function normalizeParams(params) {
|
|
|
4811
4811
|
function getIconSvg(deviceType) {
|
|
4812
4812
|
return ICON_MAP[deviceType] || ICON_MAP.DEFAULT;
|
|
4813
4813
|
}
|
|
4814
|
+
function formatValueByDomain(value, domain) {
|
|
4815
|
+
if (domain === "water") {
|
|
4816
|
+
return formatWaterVolumeM3(value);
|
|
4817
|
+
}
|
|
4818
|
+
return formatEnergy(value);
|
|
4819
|
+
}
|
|
4814
4820
|
function formatUpdateDate(timeVal) {
|
|
4815
4821
|
let telemetryTimeFormatted = "N/A";
|
|
4816
4822
|
let timeSinceLastTelemetry = "";
|
|
@@ -5059,7 +5065,7 @@ function paint(root, state) {
|
|
|
5059
5065
|
const chip = root.querySelector(".chip");
|
|
5060
5066
|
chip.className = `chip ${statusInfo.chipClass}`;
|
|
5061
5067
|
chip.textContent = statusInfo.label;
|
|
5062
|
-
const primaryValue =
|
|
5068
|
+
const primaryValue = formatValueByDomain(entityObject.val, entityObject.domain);
|
|
5063
5069
|
const numSpan = root.querySelector(".myio-ho-card__value .num");
|
|
5064
5070
|
const unitSpan = root.querySelector(".myio-ho-card__value .unit");
|
|
5065
5071
|
numSpan.textContent = primaryValue;
|
|
@@ -15397,7 +15403,13 @@ var SettingsModalView = class {
|
|
|
15397
15403
|
render(initialData) {
|
|
15398
15404
|
this.originalActiveElement = document.activeElement;
|
|
15399
15405
|
document.body.appendChild(this.container);
|
|
15400
|
-
|
|
15406
|
+
let formData = { ...initialData };
|
|
15407
|
+
if (initialData.deviceMapInstaneousPower && typeof initialData.deviceMapInstaneousPower === "object") {
|
|
15408
|
+
console.log("[SettingsModalView] Configura\xE7\xE3o salva encontrada (Device Scope). Processando...");
|
|
15409
|
+
const flatLimits = this.parseDeviceSavedLimits(initialData.deviceMapInstaneousPower);
|
|
15410
|
+
formData = { ...formData, ...flatLimits };
|
|
15411
|
+
}
|
|
15412
|
+
this.populateForm(formData);
|
|
15401
15413
|
this.attachEventListeners();
|
|
15402
15414
|
this.setupAccessibility();
|
|
15403
15415
|
this.setupFocusTrap();
|
|
@@ -16966,6 +16978,42 @@ var SettingsModalView = class {
|
|
|
16966
16978
|
}
|
|
16967
16979
|
}
|
|
16968
16980
|
}
|
|
16981
|
+
/**
|
|
16982
|
+
* Helper: Traduz o JSON RFC-0086 (deviceMapInstaneousPower)
|
|
16983
|
+
* para os campos planos do formulário (ex: standbyLimitUpConsumption)
|
|
16984
|
+
*/
|
|
16985
|
+
parseDeviceSavedLimits(deviceJson) {
|
|
16986
|
+
const extracted = {};
|
|
16987
|
+
try {
|
|
16988
|
+
if (!deviceJson || !deviceJson.limitsByInstantaneoustPowerType) return extracted;
|
|
16989
|
+
const consumptionGroup = deviceJson.limitsByInstantaneoustPowerType.find(
|
|
16990
|
+
(g) => g.telemetryType === "consumption"
|
|
16991
|
+
);
|
|
16992
|
+
const deviceItem = consumptionGroup?.itemsByDeviceType?.[0];
|
|
16993
|
+
if (!deviceItem?.limitsByDeviceStatus) return extracted;
|
|
16994
|
+
const mapPrefix = {
|
|
16995
|
+
"standBy": "standby",
|
|
16996
|
+
"normal": "normal",
|
|
16997
|
+
"alert": "alert",
|
|
16998
|
+
"failure": "failure"
|
|
16999
|
+
};
|
|
17000
|
+
deviceItem.limitsByDeviceStatus.forEach((status) => {
|
|
17001
|
+
const prefix = mapPrefix[status.deviceStatusName];
|
|
17002
|
+
if (prefix && status.limitsValues) {
|
|
17003
|
+
const { baseValue, topValue } = status.limitsValues;
|
|
17004
|
+
if (baseValue !== null && baseValue !== void 0) {
|
|
17005
|
+
extracted[`${prefix}LimitDownConsumption`] = baseValue;
|
|
17006
|
+
}
|
|
17007
|
+
if (topValue !== null && topValue !== void 0) {
|
|
17008
|
+
extracted[`${prefix}LimitUpConsumption`] = topValue;
|
|
17009
|
+
}
|
|
17010
|
+
}
|
|
17011
|
+
});
|
|
17012
|
+
} catch (e) {
|
|
17013
|
+
console.warn("[SettingsModalView] Erro ao processar deviceMapInstaneousPower:", e);
|
|
17014
|
+
}
|
|
17015
|
+
return extracted;
|
|
17016
|
+
}
|
|
16969
17017
|
attachEventListeners() {
|
|
16970
17018
|
this.form.addEventListener("submit", (event) => {
|
|
16971
17019
|
event.preventDefault();
|
|
@@ -17237,11 +17285,25 @@ var DefaultSettingsPersister = class {
|
|
|
17237
17285
|
}
|
|
17238
17286
|
async saveServerScopeAttributes(deviceId, attributes) {
|
|
17239
17287
|
try {
|
|
17240
|
-
const
|
|
17241
|
-
const
|
|
17242
|
-
|
|
17243
|
-
|
|
17244
|
-
|
|
17288
|
+
const payload = { ...attributes };
|
|
17289
|
+
const effectiveDeviceType = this.getEffectiveDeviceType();
|
|
17290
|
+
const deviceJson = this.buildDevicePowerJson(payload, effectiveDeviceType);
|
|
17291
|
+
if (deviceJson) {
|
|
17292
|
+
payload.deviceMapInstaneousPower = deviceJson;
|
|
17293
|
+
}
|
|
17294
|
+
const flatKeysToRemove = [
|
|
17295
|
+
"telemetryType",
|
|
17296
|
+
"standbyLimitDownConsumption",
|
|
17297
|
+
"standbyLimitUpConsumption",
|
|
17298
|
+
"normalLimitDownConsumption",
|
|
17299
|
+
"normalLimitUpConsumption",
|
|
17300
|
+
"alertLimitDownConsumption",
|
|
17301
|
+
"alertLimitUpConsumption",
|
|
17302
|
+
"failureLimitDownConsumption",
|
|
17303
|
+
"failureLimitUpConsumption"
|
|
17304
|
+
];
|
|
17305
|
+
flatKeysToRemove.forEach((key) => delete payload[key]);
|
|
17306
|
+
console.log("[SettingsPersister] Saving Server Scope Attributes:", payload);
|
|
17245
17307
|
const res = await fetch(
|
|
17246
17308
|
`${this.tbBaseUrl}/api/plugins/telemetry/DEVICE/${deviceId}/attributes/SERVER_SCOPE`,
|
|
17247
17309
|
{
|
|
@@ -17258,13 +17320,70 @@ var DefaultSettingsPersister = class {
|
|
|
17258
17320
|
}
|
|
17259
17321
|
return {
|
|
17260
17322
|
ok: true,
|
|
17261
|
-
updatedKeys:
|
|
17323
|
+
updatedKeys: Object.keys(payload)
|
|
17262
17324
|
};
|
|
17263
17325
|
} catch (error) {
|
|
17264
17326
|
console.error("[SettingsPersister] Attributes save failed:", error);
|
|
17265
17327
|
return { ok: false, error: this.mapError(error) };
|
|
17266
17328
|
}
|
|
17267
17329
|
}
|
|
17330
|
+
/**
|
|
17331
|
+
* Constrói o JSON Reduzido (apenas o deviceType atual) para salvar no Device.
|
|
17332
|
+
* Retorna null se nenhum campo de potência estiver presente.
|
|
17333
|
+
*/
|
|
17334
|
+
buildDevicePowerJson(formData, deviceType) {
|
|
17335
|
+
const statuses = ["standby", "normal", "alert", "failure"];
|
|
17336
|
+
const hasPowerData = statuses.some(
|
|
17337
|
+
(status) => formData[`${status}LimitDownConsumption`] !== void 0 && formData[`${status}LimitDownConsumption`] !== "" || formData[`${status}LimitUpConsumption`] !== void 0 && formData[`${status}LimitUpConsumption`] !== ""
|
|
17338
|
+
);
|
|
17339
|
+
if (!hasPowerData) return null;
|
|
17340
|
+
const statusMap = {
|
|
17341
|
+
"standby": "standBy",
|
|
17342
|
+
"normal": "normal",
|
|
17343
|
+
"alert": "alert",
|
|
17344
|
+
"failure": "failure"
|
|
17345
|
+
};
|
|
17346
|
+
const limitsList = [];
|
|
17347
|
+
statuses.forEach((statusKey) => {
|
|
17348
|
+
const down = formData[`${statusKey}LimitDownConsumption`];
|
|
17349
|
+
const up = formData[`${statusKey}LimitUpConsumption`];
|
|
17350
|
+
if (down !== void 0 && down !== "" || up !== void 0 && up !== "") {
|
|
17351
|
+
limitsList.push({
|
|
17352
|
+
deviceStatusName: statusMap[statusKey],
|
|
17353
|
+
limitsValues: {
|
|
17354
|
+
// Converte para Number ou null
|
|
17355
|
+
baseValue: down !== "" && down !== void 0 ? Number(down) : null,
|
|
17356
|
+
topValue: up !== "" && up !== void 0 ? Number(up) : null
|
|
17357
|
+
}
|
|
17358
|
+
});
|
|
17359
|
+
}
|
|
17360
|
+
});
|
|
17361
|
+
if (limitsList.length === 0) return null;
|
|
17362
|
+
return {
|
|
17363
|
+
version: "1.0.0",
|
|
17364
|
+
limitsByInstantaneoustPowerType: [
|
|
17365
|
+
{
|
|
17366
|
+
telemetryType: "consumption",
|
|
17367
|
+
itemsByDeviceType: [
|
|
17368
|
+
{
|
|
17369
|
+
deviceType,
|
|
17370
|
+
// Gera um nome descritivo interno
|
|
17371
|
+
name: `deviceMapInstaneousPower${this.formatDeviceTypeName(deviceType)}`,
|
|
17372
|
+
description: "Override manual configurado via Dashboard",
|
|
17373
|
+
limitsByDeviceStatus: limitsList
|
|
17374
|
+
}
|
|
17375
|
+
]
|
|
17376
|
+
}
|
|
17377
|
+
]
|
|
17378
|
+
};
|
|
17379
|
+
}
|
|
17380
|
+
/**
|
|
17381
|
+
* Helper para formatar o nome do tipo (PascalCase) para uso no campo "name" do JSON
|
|
17382
|
+
*/
|
|
17383
|
+
formatDeviceTypeName(deviceType) {
|
|
17384
|
+
if (!deviceType) return "";
|
|
17385
|
+
return deviceType.charAt(0).toUpperCase() + deviceType.slice(1).toLowerCase();
|
|
17386
|
+
}
|
|
17268
17387
|
/**
|
|
17269
17388
|
* RFC-0086: Build mapInstantaneousPower JSON structure from form data
|
|
17270
17389
|
* IMPORTANT: When saving to a DEVICE, only include entries for the specific deviceType
|
|
@@ -17321,25 +17440,6 @@ var DefaultSettingsPersister = class {
|
|
|
17321
17440
|
console.log(`[SettingsPersister] RFC-0086: Built mapInstantaneousPower for deviceType=${effectiveDeviceType}:`, result);
|
|
17322
17441
|
return result;
|
|
17323
17442
|
}
|
|
17324
|
-
/**
|
|
17325
|
-
* Format device type name for display (e.g., ELEVADOR -> Elevador)
|
|
17326
|
-
*/
|
|
17327
|
-
formatDeviceTypeName(deviceType) {
|
|
17328
|
-
const map = {
|
|
17329
|
-
"ELEVADOR": "Elevator",
|
|
17330
|
-
"ESCADA_ROLANTE": "Escalator",
|
|
17331
|
-
"MOTOR": "Motor",
|
|
17332
|
-
"BOMBA": "Pump",
|
|
17333
|
-
"3F_MEDIDOR": "3FMedidor",
|
|
17334
|
-
"CHILLER": "Chiller",
|
|
17335
|
-
"FANCOIL": "Fancoil",
|
|
17336
|
-
"AR_CONDICIONADO": "AirConditioner",
|
|
17337
|
-
"HVAC": "HVAC",
|
|
17338
|
-
"HIDROMETRO": "Hidrometro",
|
|
17339
|
-
"TERMOSTATO": "Termostato"
|
|
17340
|
-
};
|
|
17341
|
-
return map[deviceType] || deviceType;
|
|
17342
|
-
}
|
|
17343
17443
|
sanitizeLabel(label) {
|
|
17344
17444
|
return label.trim().slice(0, 255).replace(/[\x00-\x1F\x7F]/g, "");
|
|
17345
17445
|
}
|
|
@@ -17476,18 +17576,16 @@ var DefaultSettingsFetcher = class {
|
|
|
17476
17576
|
}
|
|
17477
17577
|
const attributesArray = await response.json();
|
|
17478
17578
|
const attributes = {};
|
|
17479
|
-
const settingsNamespace = "myio.settings.energy.";
|
|
17480
17579
|
for (const attr of attributesArray) {
|
|
17481
17580
|
if (attr.key && attr.value !== void 0 && attr.value !== null && attr.value !== "") {
|
|
17482
|
-
if (attr.key
|
|
17483
|
-
const key = attr.key.replace(settingsNamespace, "");
|
|
17484
|
-
if (key !== "__version") {
|
|
17485
|
-
attributes[key] = attr.value;
|
|
17486
|
-
}
|
|
17487
|
-
} else if (attr.key === "floor") {
|
|
17581
|
+
if (attr.key === "floor") {
|
|
17488
17582
|
attributes.floor = attr.value;
|
|
17489
17583
|
} else if (attr.key === "identifier") {
|
|
17490
17584
|
attributes.identifier = attr.value;
|
|
17585
|
+
} else if (attr.key === "mapInstantaneousPower") {
|
|
17586
|
+
attributes.mapInstantaneousPower = attr.value;
|
|
17587
|
+
} else if (attr.key === "deviceMapInstaneousPower") {
|
|
17588
|
+
attributes.deviceMapInstaneousPower = attr.value;
|
|
17491
17589
|
}
|
|
17492
17590
|
}
|
|
17493
17591
|
}
|
|
@@ -17509,23 +17607,12 @@ var DefaultSettingsFetcher = class {
|
|
|
17509
17607
|
}
|
|
17510
17608
|
return merged;
|
|
17511
17609
|
}
|
|
17512
|
-
/**
|
|
17513
|
-
* Utility method to validate and sanitize fetched data
|
|
17514
|
-
*/
|
|
17515
17610
|
static sanitizeFetchedData(data) {
|
|
17516
17611
|
const sanitized = {};
|
|
17517
17612
|
const stringFields = [
|
|
17518
17613
|
"label",
|
|
17519
17614
|
"floor",
|
|
17520
|
-
"identifier"
|
|
17521
|
-
"alertLimitDownConsumption",
|
|
17522
|
-
"alertLimitUpConsumption",
|
|
17523
|
-
"failureLimitDownConsumption",
|
|
17524
|
-
"failureLimitUpConsumption",
|
|
17525
|
-
"normalLimitDownConsumption",
|
|
17526
|
-
"normalLimitUpConsumption",
|
|
17527
|
-
"standbyLimitDownConsumption",
|
|
17528
|
-
"standbyLimitUpConsumption"
|
|
17615
|
+
"identifier"
|
|
17529
17616
|
];
|
|
17530
17617
|
for (const field of stringFields) {
|
|
17531
17618
|
if (data[field] && typeof data[field] === "string") {
|
|
@@ -17541,6 +17628,12 @@ var DefaultSettingsFetcher = class {
|
|
|
17541
17628
|
}
|
|
17542
17629
|
}
|
|
17543
17630
|
}
|
|
17631
|
+
const objectFields = ["mapInstantaneousPower", "deviceMapInstaneousPower"];
|
|
17632
|
+
for (const field of objectFields) {
|
|
17633
|
+
if (data[field] && typeof data[field] === "object") {
|
|
17634
|
+
sanitized[field] = data[field];
|
|
17635
|
+
}
|
|
17636
|
+
}
|
|
17544
17637
|
return sanitized;
|
|
17545
17638
|
}
|
|
17546
17639
|
};
|
|
@@ -17590,8 +17683,9 @@ var SettingsController = class {
|
|
|
17590
17683
|
// Pass connection info for display
|
|
17591
17684
|
onSave: this.handleSave.bind(this),
|
|
17592
17685
|
onClose: this.handleClose.bind(this),
|
|
17593
|
-
mapInstantaneousPower: params.mapInstantaneousPower
|
|
17594
|
-
// RFC-0077: Pass instantaneous power map for Power Limits feature
|
|
17686
|
+
mapInstantaneousPower: params.mapInstantaneousPower,
|
|
17687
|
+
// RFC-0077: Pass instantaneous power map for Power Limits feature,
|
|
17688
|
+
deviceMapInstaneousPower: params.deviceMapInstaneousPower
|
|
17595
17689
|
});
|
|
17596
17690
|
}
|
|
17597
17691
|
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
|
@@ -4703,6 +4703,12 @@ function normalizeParams(params) {
|
|
|
4703
4703
|
function getIconSvg(deviceType) {
|
|
4704
4704
|
return ICON_MAP[deviceType] || ICON_MAP.DEFAULT;
|
|
4705
4705
|
}
|
|
4706
|
+
function formatValueByDomain(value, domain) {
|
|
4707
|
+
if (domain === "water") {
|
|
4708
|
+
return formatWaterVolumeM3(value);
|
|
4709
|
+
}
|
|
4710
|
+
return formatEnergy(value);
|
|
4711
|
+
}
|
|
4706
4712
|
function formatUpdateDate(timeVal) {
|
|
4707
4713
|
let telemetryTimeFormatted = "N/A";
|
|
4708
4714
|
let timeSinceLastTelemetry = "";
|
|
@@ -4951,7 +4957,7 @@ function paint(root, state) {
|
|
|
4951
4957
|
const chip = root.querySelector(".chip");
|
|
4952
4958
|
chip.className = `chip ${statusInfo.chipClass}`;
|
|
4953
4959
|
chip.textContent = statusInfo.label;
|
|
4954
|
-
const primaryValue =
|
|
4960
|
+
const primaryValue = formatValueByDomain(entityObject.val, entityObject.domain);
|
|
4955
4961
|
const numSpan = root.querySelector(".myio-ho-card__value .num");
|
|
4956
4962
|
const unitSpan = root.querySelector(".myio-ho-card__value .unit");
|
|
4957
4963
|
numSpan.textContent = primaryValue;
|
|
@@ -15289,7 +15295,13 @@ var SettingsModalView = class {
|
|
|
15289
15295
|
render(initialData) {
|
|
15290
15296
|
this.originalActiveElement = document.activeElement;
|
|
15291
15297
|
document.body.appendChild(this.container);
|
|
15292
|
-
|
|
15298
|
+
let formData = { ...initialData };
|
|
15299
|
+
if (initialData.deviceMapInstaneousPower && typeof initialData.deviceMapInstaneousPower === "object") {
|
|
15300
|
+
console.log("[SettingsModalView] Configura\xE7\xE3o salva encontrada (Device Scope). Processando...");
|
|
15301
|
+
const flatLimits = this.parseDeviceSavedLimits(initialData.deviceMapInstaneousPower);
|
|
15302
|
+
formData = { ...formData, ...flatLimits };
|
|
15303
|
+
}
|
|
15304
|
+
this.populateForm(formData);
|
|
15293
15305
|
this.attachEventListeners();
|
|
15294
15306
|
this.setupAccessibility();
|
|
15295
15307
|
this.setupFocusTrap();
|
|
@@ -16858,6 +16870,42 @@ var SettingsModalView = class {
|
|
|
16858
16870
|
}
|
|
16859
16871
|
}
|
|
16860
16872
|
}
|
|
16873
|
+
/**
|
|
16874
|
+
* Helper: Traduz o JSON RFC-0086 (deviceMapInstaneousPower)
|
|
16875
|
+
* para os campos planos do formulário (ex: standbyLimitUpConsumption)
|
|
16876
|
+
*/
|
|
16877
|
+
parseDeviceSavedLimits(deviceJson) {
|
|
16878
|
+
const extracted = {};
|
|
16879
|
+
try {
|
|
16880
|
+
if (!deviceJson || !deviceJson.limitsByInstantaneoustPowerType) return extracted;
|
|
16881
|
+
const consumptionGroup = deviceJson.limitsByInstantaneoustPowerType.find(
|
|
16882
|
+
(g) => g.telemetryType === "consumption"
|
|
16883
|
+
);
|
|
16884
|
+
const deviceItem = consumptionGroup?.itemsByDeviceType?.[0];
|
|
16885
|
+
if (!deviceItem?.limitsByDeviceStatus) return extracted;
|
|
16886
|
+
const mapPrefix = {
|
|
16887
|
+
"standBy": "standby",
|
|
16888
|
+
"normal": "normal",
|
|
16889
|
+
"alert": "alert",
|
|
16890
|
+
"failure": "failure"
|
|
16891
|
+
};
|
|
16892
|
+
deviceItem.limitsByDeviceStatus.forEach((status) => {
|
|
16893
|
+
const prefix = mapPrefix[status.deviceStatusName];
|
|
16894
|
+
if (prefix && status.limitsValues) {
|
|
16895
|
+
const { baseValue, topValue } = status.limitsValues;
|
|
16896
|
+
if (baseValue !== null && baseValue !== void 0) {
|
|
16897
|
+
extracted[`${prefix}LimitDownConsumption`] = baseValue;
|
|
16898
|
+
}
|
|
16899
|
+
if (topValue !== null && topValue !== void 0) {
|
|
16900
|
+
extracted[`${prefix}LimitUpConsumption`] = topValue;
|
|
16901
|
+
}
|
|
16902
|
+
}
|
|
16903
|
+
});
|
|
16904
|
+
} catch (e) {
|
|
16905
|
+
console.warn("[SettingsModalView] Erro ao processar deviceMapInstaneousPower:", e);
|
|
16906
|
+
}
|
|
16907
|
+
return extracted;
|
|
16908
|
+
}
|
|
16861
16909
|
attachEventListeners() {
|
|
16862
16910
|
this.form.addEventListener("submit", (event) => {
|
|
16863
16911
|
event.preventDefault();
|
|
@@ -17129,11 +17177,25 @@ var DefaultSettingsPersister = class {
|
|
|
17129
17177
|
}
|
|
17130
17178
|
async saveServerScopeAttributes(deviceId, attributes) {
|
|
17131
17179
|
try {
|
|
17132
|
-
const
|
|
17133
|
-
const
|
|
17134
|
-
|
|
17135
|
-
|
|
17136
|
-
|
|
17180
|
+
const payload = { ...attributes };
|
|
17181
|
+
const effectiveDeviceType = this.getEffectiveDeviceType();
|
|
17182
|
+
const deviceJson = this.buildDevicePowerJson(payload, effectiveDeviceType);
|
|
17183
|
+
if (deviceJson) {
|
|
17184
|
+
payload.deviceMapInstaneousPower = deviceJson;
|
|
17185
|
+
}
|
|
17186
|
+
const flatKeysToRemove = [
|
|
17187
|
+
"telemetryType",
|
|
17188
|
+
"standbyLimitDownConsumption",
|
|
17189
|
+
"standbyLimitUpConsumption",
|
|
17190
|
+
"normalLimitDownConsumption",
|
|
17191
|
+
"normalLimitUpConsumption",
|
|
17192
|
+
"alertLimitDownConsumption",
|
|
17193
|
+
"alertLimitUpConsumption",
|
|
17194
|
+
"failureLimitDownConsumption",
|
|
17195
|
+
"failureLimitUpConsumption"
|
|
17196
|
+
];
|
|
17197
|
+
flatKeysToRemove.forEach((key) => delete payload[key]);
|
|
17198
|
+
console.log("[SettingsPersister] Saving Server Scope Attributes:", payload);
|
|
17137
17199
|
const res = await fetch(
|
|
17138
17200
|
`${this.tbBaseUrl}/api/plugins/telemetry/DEVICE/${deviceId}/attributes/SERVER_SCOPE`,
|
|
17139
17201
|
{
|
|
@@ -17150,13 +17212,70 @@ var DefaultSettingsPersister = class {
|
|
|
17150
17212
|
}
|
|
17151
17213
|
return {
|
|
17152
17214
|
ok: true,
|
|
17153
|
-
updatedKeys:
|
|
17215
|
+
updatedKeys: Object.keys(payload)
|
|
17154
17216
|
};
|
|
17155
17217
|
} catch (error) {
|
|
17156
17218
|
console.error("[SettingsPersister] Attributes save failed:", error);
|
|
17157
17219
|
return { ok: false, error: this.mapError(error) };
|
|
17158
17220
|
}
|
|
17159
17221
|
}
|
|
17222
|
+
/**
|
|
17223
|
+
* Constrói o JSON Reduzido (apenas o deviceType atual) para salvar no Device.
|
|
17224
|
+
* Retorna null se nenhum campo de potência estiver presente.
|
|
17225
|
+
*/
|
|
17226
|
+
buildDevicePowerJson(formData, deviceType) {
|
|
17227
|
+
const statuses = ["standby", "normal", "alert", "failure"];
|
|
17228
|
+
const hasPowerData = statuses.some(
|
|
17229
|
+
(status) => formData[`${status}LimitDownConsumption`] !== void 0 && formData[`${status}LimitDownConsumption`] !== "" || formData[`${status}LimitUpConsumption`] !== void 0 && formData[`${status}LimitUpConsumption`] !== ""
|
|
17230
|
+
);
|
|
17231
|
+
if (!hasPowerData) return null;
|
|
17232
|
+
const statusMap = {
|
|
17233
|
+
"standby": "standBy",
|
|
17234
|
+
"normal": "normal",
|
|
17235
|
+
"alert": "alert",
|
|
17236
|
+
"failure": "failure"
|
|
17237
|
+
};
|
|
17238
|
+
const limitsList = [];
|
|
17239
|
+
statuses.forEach((statusKey) => {
|
|
17240
|
+
const down = formData[`${statusKey}LimitDownConsumption`];
|
|
17241
|
+
const up = formData[`${statusKey}LimitUpConsumption`];
|
|
17242
|
+
if (down !== void 0 && down !== "" || up !== void 0 && up !== "") {
|
|
17243
|
+
limitsList.push({
|
|
17244
|
+
deviceStatusName: statusMap[statusKey],
|
|
17245
|
+
limitsValues: {
|
|
17246
|
+
// Converte para Number ou null
|
|
17247
|
+
baseValue: down !== "" && down !== void 0 ? Number(down) : null,
|
|
17248
|
+
topValue: up !== "" && up !== void 0 ? Number(up) : null
|
|
17249
|
+
}
|
|
17250
|
+
});
|
|
17251
|
+
}
|
|
17252
|
+
});
|
|
17253
|
+
if (limitsList.length === 0) return null;
|
|
17254
|
+
return {
|
|
17255
|
+
version: "1.0.0",
|
|
17256
|
+
limitsByInstantaneoustPowerType: [
|
|
17257
|
+
{
|
|
17258
|
+
telemetryType: "consumption",
|
|
17259
|
+
itemsByDeviceType: [
|
|
17260
|
+
{
|
|
17261
|
+
deviceType,
|
|
17262
|
+
// Gera um nome descritivo interno
|
|
17263
|
+
name: `deviceMapInstaneousPower${this.formatDeviceTypeName(deviceType)}`,
|
|
17264
|
+
description: "Override manual configurado via Dashboard",
|
|
17265
|
+
limitsByDeviceStatus: limitsList
|
|
17266
|
+
}
|
|
17267
|
+
]
|
|
17268
|
+
}
|
|
17269
|
+
]
|
|
17270
|
+
};
|
|
17271
|
+
}
|
|
17272
|
+
/**
|
|
17273
|
+
* Helper para formatar o nome do tipo (PascalCase) para uso no campo "name" do JSON
|
|
17274
|
+
*/
|
|
17275
|
+
formatDeviceTypeName(deviceType) {
|
|
17276
|
+
if (!deviceType) return "";
|
|
17277
|
+
return deviceType.charAt(0).toUpperCase() + deviceType.slice(1).toLowerCase();
|
|
17278
|
+
}
|
|
17160
17279
|
/**
|
|
17161
17280
|
* RFC-0086: Build mapInstantaneousPower JSON structure from form data
|
|
17162
17281
|
* IMPORTANT: When saving to a DEVICE, only include entries for the specific deviceType
|
|
@@ -17213,25 +17332,6 @@ var DefaultSettingsPersister = class {
|
|
|
17213
17332
|
console.log(`[SettingsPersister] RFC-0086: Built mapInstantaneousPower for deviceType=${effectiveDeviceType}:`, result);
|
|
17214
17333
|
return result;
|
|
17215
17334
|
}
|
|
17216
|
-
/**
|
|
17217
|
-
* Format device type name for display (e.g., ELEVADOR -> Elevador)
|
|
17218
|
-
*/
|
|
17219
|
-
formatDeviceTypeName(deviceType) {
|
|
17220
|
-
const map = {
|
|
17221
|
-
"ELEVADOR": "Elevator",
|
|
17222
|
-
"ESCADA_ROLANTE": "Escalator",
|
|
17223
|
-
"MOTOR": "Motor",
|
|
17224
|
-
"BOMBA": "Pump",
|
|
17225
|
-
"3F_MEDIDOR": "3FMedidor",
|
|
17226
|
-
"CHILLER": "Chiller",
|
|
17227
|
-
"FANCOIL": "Fancoil",
|
|
17228
|
-
"AR_CONDICIONADO": "AirConditioner",
|
|
17229
|
-
"HVAC": "HVAC",
|
|
17230
|
-
"HIDROMETRO": "Hidrometro",
|
|
17231
|
-
"TERMOSTATO": "Termostato"
|
|
17232
|
-
};
|
|
17233
|
-
return map[deviceType] || deviceType;
|
|
17234
|
-
}
|
|
17235
17335
|
sanitizeLabel(label) {
|
|
17236
17336
|
return label.trim().slice(0, 255).replace(/[\x00-\x1F\x7F]/g, "");
|
|
17237
17337
|
}
|
|
@@ -17368,18 +17468,16 @@ var DefaultSettingsFetcher = class {
|
|
|
17368
17468
|
}
|
|
17369
17469
|
const attributesArray = await response.json();
|
|
17370
17470
|
const attributes = {};
|
|
17371
|
-
const settingsNamespace = "myio.settings.energy.";
|
|
17372
17471
|
for (const attr of attributesArray) {
|
|
17373
17472
|
if (attr.key && attr.value !== void 0 && attr.value !== null && attr.value !== "") {
|
|
17374
|
-
if (attr.key
|
|
17375
|
-
const key = attr.key.replace(settingsNamespace, "");
|
|
17376
|
-
if (key !== "__version") {
|
|
17377
|
-
attributes[key] = attr.value;
|
|
17378
|
-
}
|
|
17379
|
-
} else if (attr.key === "floor") {
|
|
17473
|
+
if (attr.key === "floor") {
|
|
17380
17474
|
attributes.floor = attr.value;
|
|
17381
17475
|
} else if (attr.key === "identifier") {
|
|
17382
17476
|
attributes.identifier = attr.value;
|
|
17477
|
+
} else if (attr.key === "mapInstantaneousPower") {
|
|
17478
|
+
attributes.mapInstantaneousPower = attr.value;
|
|
17479
|
+
} else if (attr.key === "deviceMapInstaneousPower") {
|
|
17480
|
+
attributes.deviceMapInstaneousPower = attr.value;
|
|
17383
17481
|
}
|
|
17384
17482
|
}
|
|
17385
17483
|
}
|
|
@@ -17401,23 +17499,12 @@ var DefaultSettingsFetcher = class {
|
|
|
17401
17499
|
}
|
|
17402
17500
|
return merged;
|
|
17403
17501
|
}
|
|
17404
|
-
/**
|
|
17405
|
-
* Utility method to validate and sanitize fetched data
|
|
17406
|
-
*/
|
|
17407
17502
|
static sanitizeFetchedData(data) {
|
|
17408
17503
|
const sanitized = {};
|
|
17409
17504
|
const stringFields = [
|
|
17410
17505
|
"label",
|
|
17411
17506
|
"floor",
|
|
17412
|
-
"identifier"
|
|
17413
|
-
"alertLimitDownConsumption",
|
|
17414
|
-
"alertLimitUpConsumption",
|
|
17415
|
-
"failureLimitDownConsumption",
|
|
17416
|
-
"failureLimitUpConsumption",
|
|
17417
|
-
"normalLimitDownConsumption",
|
|
17418
|
-
"normalLimitUpConsumption",
|
|
17419
|
-
"standbyLimitDownConsumption",
|
|
17420
|
-
"standbyLimitUpConsumption"
|
|
17507
|
+
"identifier"
|
|
17421
17508
|
];
|
|
17422
17509
|
for (const field of stringFields) {
|
|
17423
17510
|
if (data[field] && typeof data[field] === "string") {
|
|
@@ -17433,6 +17520,12 @@ var DefaultSettingsFetcher = class {
|
|
|
17433
17520
|
}
|
|
17434
17521
|
}
|
|
17435
17522
|
}
|
|
17523
|
+
const objectFields = ["mapInstantaneousPower", "deviceMapInstaneousPower"];
|
|
17524
|
+
for (const field of objectFields) {
|
|
17525
|
+
if (data[field] && typeof data[field] === "object") {
|
|
17526
|
+
sanitized[field] = data[field];
|
|
17527
|
+
}
|
|
17528
|
+
}
|
|
17436
17529
|
return sanitized;
|
|
17437
17530
|
}
|
|
17438
17531
|
};
|
|
@@ -17482,8 +17575,9 @@ var SettingsController = class {
|
|
|
17482
17575
|
// Pass connection info for display
|
|
17483
17576
|
onSave: this.handleSave.bind(this),
|
|
17484
17577
|
onClose: this.handleClose.bind(this),
|
|
17485
|
-
mapInstantaneousPower: params.mapInstantaneousPower
|
|
17486
|
-
// RFC-0077: Pass instantaneous power map for Power Limits feature
|
|
17578
|
+
mapInstantaneousPower: params.mapInstantaneousPower,
|
|
17579
|
+
// RFC-0077: Pass instantaneous power map for Power Limits feature,
|
|
17580
|
+
deviceMapInstaneousPower: params.deviceMapInstaneousPower
|
|
17487
17581
|
});
|
|
17488
17582
|
}
|
|
17489
17583
|
async show() {
|