myio-js-library 0.1.144 → 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.
@@ -15119,7 +15119,13 @@ ${rangeText}`;
15119
15119
  render(initialData) {
15120
15120
  this.originalActiveElement = document.activeElement;
15121
15121
  document.body.appendChild(this.container);
15122
- this.populateForm(initialData);
15122
+ let formData = { ...initialData };
15123
+ if (initialData.deviceMapInstaneousPower && typeof initialData.deviceMapInstaneousPower === "object") {
15124
+ console.log("[SettingsModalView] Configura\xE7\xE3o salva encontrada (Device Scope). Processando...");
15125
+ const flatLimits = this.parseDeviceSavedLimits(initialData.deviceMapInstaneousPower);
15126
+ formData = { ...formData, ...flatLimits };
15127
+ }
15128
+ this.populateForm(formData);
15123
15129
  this.attachEventListeners();
15124
15130
  this.setupAccessibility();
15125
15131
  this.setupFocusTrap();
@@ -16688,6 +16694,42 @@ ${rangeText}`;
16688
16694
  }
16689
16695
  }
16690
16696
  }
16697
+ /**
16698
+ * Helper: Traduz o JSON RFC-0086 (deviceMapInstaneousPower)
16699
+ * para os campos planos do formulário (ex: standbyLimitUpConsumption)
16700
+ */
16701
+ parseDeviceSavedLimits(deviceJson) {
16702
+ const extracted = {};
16703
+ try {
16704
+ if (!deviceJson || !deviceJson.limitsByInstantaneoustPowerType) return extracted;
16705
+ const consumptionGroup = deviceJson.limitsByInstantaneoustPowerType.find(
16706
+ (g) => g.telemetryType === "consumption"
16707
+ );
16708
+ const deviceItem = consumptionGroup?.itemsByDeviceType?.[0];
16709
+ if (!deviceItem?.limitsByDeviceStatus) return extracted;
16710
+ const mapPrefix = {
16711
+ "standBy": "standby",
16712
+ "normal": "normal",
16713
+ "alert": "alert",
16714
+ "failure": "failure"
16715
+ };
16716
+ deviceItem.limitsByDeviceStatus.forEach((status) => {
16717
+ const prefix = mapPrefix[status.deviceStatusName];
16718
+ if (prefix && status.limitsValues) {
16719
+ const { baseValue, topValue } = status.limitsValues;
16720
+ if (baseValue !== null && baseValue !== void 0) {
16721
+ extracted[`${prefix}LimitDownConsumption`] = baseValue;
16722
+ }
16723
+ if (topValue !== null && topValue !== void 0) {
16724
+ extracted[`${prefix}LimitUpConsumption`] = topValue;
16725
+ }
16726
+ }
16727
+ });
16728
+ } catch (e) {
16729
+ console.warn("[SettingsModalView] Erro ao processar deviceMapInstaneousPower:", e);
16730
+ }
16731
+ return extracted;
16732
+ }
16691
16733
  attachEventListeners() {
16692
16734
  this.form.addEventListener("submit", (event) => {
16693
16735
  event.preventDefault();
@@ -16959,11 +17001,25 @@ ${rangeText}`;
16959
17001
  }
16960
17002
  async saveServerScopeAttributes(deviceId, attributes) {
16961
17003
  try {
16962
- const mapInstantaneousPower = this.buildMapInstantaneousPower(attributes);
16963
- const payload = {
16964
- mapInstantaneousPower
16965
- };
16966
- console.log("[SettingsPersister] RFC-0080: Saving mapInstantaneousPower as JSON:", payload);
17004
+ const payload = { ...attributes };
17005
+ const effectiveDeviceType = this.getEffectiveDeviceType();
17006
+ const deviceJson = this.buildDevicePowerJson(payload, effectiveDeviceType);
17007
+ if (deviceJson) {
17008
+ payload.deviceMapInstaneousPower = deviceJson;
17009
+ }
17010
+ const flatKeysToRemove = [
17011
+ "telemetryType",
17012
+ "standbyLimitDownConsumption",
17013
+ "standbyLimitUpConsumption",
17014
+ "normalLimitDownConsumption",
17015
+ "normalLimitUpConsumption",
17016
+ "alertLimitDownConsumption",
17017
+ "alertLimitUpConsumption",
17018
+ "failureLimitDownConsumption",
17019
+ "failureLimitUpConsumption"
17020
+ ];
17021
+ flatKeysToRemove.forEach((key) => delete payload[key]);
17022
+ console.log("[SettingsPersister] Saving Server Scope Attributes:", payload);
16967
17023
  const res = await fetch(
16968
17024
  `${this.tbBaseUrl}/api/plugins/telemetry/DEVICE/${deviceId}/attributes/SERVER_SCOPE`,
16969
17025
  {
@@ -16980,13 +17036,70 @@ ${rangeText}`;
16980
17036
  }
16981
17037
  return {
16982
17038
  ok: true,
16983
- updatedKeys: ["mapInstantaneousPower"]
17039
+ updatedKeys: Object.keys(payload)
16984
17040
  };
16985
17041
  } catch (error) {
16986
17042
  console.error("[SettingsPersister] Attributes save failed:", error);
16987
17043
  return { ok: false, error: this.mapError(error) };
16988
17044
  }
16989
17045
  }
17046
+ /**
17047
+ * Constrói o JSON Reduzido (apenas o deviceType atual) para salvar no Device.
17048
+ * Retorna null se nenhum campo de potência estiver presente.
17049
+ */
17050
+ buildDevicePowerJson(formData, deviceType) {
17051
+ const statuses = ["standby", "normal", "alert", "failure"];
17052
+ const hasPowerData = statuses.some(
17053
+ (status) => formData[`${status}LimitDownConsumption`] !== void 0 && formData[`${status}LimitDownConsumption`] !== "" || formData[`${status}LimitUpConsumption`] !== void 0 && formData[`${status}LimitUpConsumption`] !== ""
17054
+ );
17055
+ if (!hasPowerData) return null;
17056
+ const statusMap = {
17057
+ "standby": "standBy",
17058
+ "normal": "normal",
17059
+ "alert": "alert",
17060
+ "failure": "failure"
17061
+ };
17062
+ const limitsList = [];
17063
+ statuses.forEach((statusKey) => {
17064
+ const down = formData[`${statusKey}LimitDownConsumption`];
17065
+ const up = formData[`${statusKey}LimitUpConsumption`];
17066
+ if (down !== void 0 && down !== "" || up !== void 0 && up !== "") {
17067
+ limitsList.push({
17068
+ deviceStatusName: statusMap[statusKey],
17069
+ limitsValues: {
17070
+ // Converte para Number ou null
17071
+ baseValue: down !== "" && down !== void 0 ? Number(down) : null,
17072
+ topValue: up !== "" && up !== void 0 ? Number(up) : null
17073
+ }
17074
+ });
17075
+ }
17076
+ });
17077
+ if (limitsList.length === 0) return null;
17078
+ return {
17079
+ version: "1.0.0",
17080
+ limitsByInstantaneoustPowerType: [
17081
+ {
17082
+ telemetryType: "consumption",
17083
+ itemsByDeviceType: [
17084
+ {
17085
+ deviceType,
17086
+ // Gera um nome descritivo interno
17087
+ name: `deviceMapInstaneousPower${this.formatDeviceTypeName(deviceType)}`,
17088
+ description: "Override manual configurado via Dashboard",
17089
+ limitsByDeviceStatus: limitsList
17090
+ }
17091
+ ]
17092
+ }
17093
+ ]
17094
+ };
17095
+ }
17096
+ /**
17097
+ * Helper para formatar o nome do tipo (PascalCase) para uso no campo "name" do JSON
17098
+ */
17099
+ formatDeviceTypeName(deviceType) {
17100
+ if (!deviceType) return "";
17101
+ return deviceType.charAt(0).toUpperCase() + deviceType.slice(1).toLowerCase();
17102
+ }
16990
17103
  /**
16991
17104
  * RFC-0086: Build mapInstantaneousPower JSON structure from form data
16992
17105
  * IMPORTANT: When saving to a DEVICE, only include entries for the specific deviceType
@@ -17043,25 +17156,6 @@ ${rangeText}`;
17043
17156
  console.log(`[SettingsPersister] RFC-0086: Built mapInstantaneousPower for deviceType=${effectiveDeviceType}:`, result);
17044
17157
  return result;
17045
17158
  }
17046
- /**
17047
- * Format device type name for display (e.g., ELEVADOR -> Elevador)
17048
- */
17049
- formatDeviceTypeName(deviceType) {
17050
- const map = {
17051
- "ELEVADOR": "Elevator",
17052
- "ESCADA_ROLANTE": "Escalator",
17053
- "MOTOR": "Motor",
17054
- "BOMBA": "Pump",
17055
- "3F_MEDIDOR": "3FMedidor",
17056
- "CHILLER": "Chiller",
17057
- "FANCOIL": "Fancoil",
17058
- "AR_CONDICIONADO": "AirConditioner",
17059
- "HVAC": "HVAC",
17060
- "HIDROMETRO": "Hidrometro",
17061
- "TERMOSTATO": "Termostato"
17062
- };
17063
- return map[deviceType] || deviceType;
17064
- }
17065
17159
  sanitizeLabel(label) {
17066
17160
  return label.trim().slice(0, 255).replace(/[\x00-\x1F\x7F]/g, "");
17067
17161
  }
@@ -17198,18 +17292,16 @@ ${rangeText}`;
17198
17292
  }
17199
17293
  const attributesArray = await response.json();
17200
17294
  const attributes = {};
17201
- const settingsNamespace = "myio.settings.energy.";
17202
17295
  for (const attr of attributesArray) {
17203
17296
  if (attr.key && attr.value !== void 0 && attr.value !== null && attr.value !== "") {
17204
- if (attr.key.startsWith(settingsNamespace)) {
17205
- const key = attr.key.replace(settingsNamespace, "");
17206
- if (key !== "__version") {
17207
- attributes[key] = attr.value;
17208
- }
17209
- } else if (attr.key === "floor") {
17297
+ if (attr.key === "floor") {
17210
17298
  attributes.floor = attr.value;
17211
17299
  } else if (attr.key === "identifier") {
17212
17300
  attributes.identifier = attr.value;
17301
+ } else if (attr.key === "mapInstantaneousPower") {
17302
+ attributes.mapInstantaneousPower = attr.value;
17303
+ } else if (attr.key === "deviceMapInstaneousPower") {
17304
+ attributes.deviceMapInstaneousPower = attr.value;
17213
17305
  }
17214
17306
  }
17215
17307
  }
@@ -17231,23 +17323,12 @@ ${rangeText}`;
17231
17323
  }
17232
17324
  return merged;
17233
17325
  }
17234
- /**
17235
- * Utility method to validate and sanitize fetched data
17236
- */
17237
17326
  static sanitizeFetchedData(data) {
17238
17327
  const sanitized = {};
17239
17328
  const stringFields = [
17240
17329
  "label",
17241
17330
  "floor",
17242
- "identifier",
17243
- "alertLimitDownConsumption",
17244
- "alertLimitUpConsumption",
17245
- "failureLimitDownConsumption",
17246
- "failureLimitUpConsumption",
17247
- "normalLimitDownConsumption",
17248
- "normalLimitUpConsumption",
17249
- "standbyLimitDownConsumption",
17250
- "standbyLimitUpConsumption"
17331
+ "identifier"
17251
17332
  ];
17252
17333
  for (const field of stringFields) {
17253
17334
  if (data[field] && typeof data[field] === "string") {
@@ -17263,6 +17344,12 @@ ${rangeText}`;
17263
17344
  }
17264
17345
  }
17265
17346
  }
17347
+ const objectFields = ["mapInstantaneousPower", "deviceMapInstaneousPower"];
17348
+ for (const field of objectFields) {
17349
+ if (data[field] && typeof data[field] === "object") {
17350
+ sanitized[field] = data[field];
17351
+ }
17352
+ }
17266
17353
  return sanitized;
17267
17354
  }
17268
17355
  };
@@ -17312,8 +17399,9 @@ ${rangeText}`;
17312
17399
  // Pass connection info for display
17313
17400
  onSave: this.handleSave.bind(this),
17314
17401
  onClose: this.handleClose.bind(this),
17315
- mapInstantaneousPower: params.mapInstantaneousPower
17316
- // RFC-0077: Pass instantaneous power map for Power Limits feature
17402
+ mapInstantaneousPower: params.mapInstantaneousPower,
17403
+ // RFC-0077: Pass instantaneous power map for Power Limits feature,
17404
+ deviceMapInstaneousPower: params.deviceMapInstaneousPower
17317
17405
  });
17318
17406
  }
17319
17407
  async show() {