@camstack/addon-provider-ecowitt 0.1.5 → 0.1.6

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/addon.js CHANGED
@@ -10082,15 +10082,18 @@ var humiditySensorCapability = {
10082
10082
  runtimeState: HumiditySensorStatusSchema
10083
10083
  };
10084
10084
  /**
10085
- * Image display cap. Models HA `image.*` entities a single still image
10086
- * exposed by an integration (a snapshot, a chart, a generated picture).
10085
+ * Image display cap. Models a single still image exposed by an integration
10086
+ * a snapshot, a chart, a generated picture, or a robot's cleaning-map render.
10087
10087
  *
10088
- * Read-only: there are no setters. The provider resolves the HA
10089
- * `entity_picture` (a relative, signed-token path) into an ABSOLUTE URL
10090
- * the browser loads directly the token stays in the query string so no
10091
- * auth header is required. The slice carries that URL plus the upstream
10092
- * last-updated timestamp; the image changes when the entity state (a
10093
- * timestamp) changes.
10088
+ * Read-only: there are no setters. The provider resolves whatever upstream
10089
+ * source it has into an ABSOLUTE URL the browser loads directly:
10090
+ * - HA `image.*` entities the `entity_picture` signed-token path
10091
+ * (token stays in the query string, so no auth header is needed);
10092
+ * - a Dreame/robot map the cloud/OSS map-image URL (or an addon
10093
+ * data-plane URL serving the rendered map bytes), exposed as its own
10094
+ * Image child device grouped under the robot's container.
10095
+ * The slice carries that URL plus the upstream last-updated timestamp; the
10096
+ * image changes when the source's last-updated marker changes.
10094
10097
  */
10095
10098
  var ImageStatusSchema = object({
10096
10099
  /** Absolute signed URL the browser loads directly. Null when the
@@ -10116,18 +10119,47 @@ var imageCapability = {
10116
10119
  */
10117
10120
  runtimeState: ImageStatusSchema
10118
10121
  };
10122
+ /**
10123
+ * Robotic lawn-mower cap. Models HA `lawn_mower.*` entities — anything
10124
+ * with a mowing lifecycle plus a dock action.
10125
+ *
10126
+ * Activity follows HA's canonical lawn-mower lifecycle: `idle` /
10127
+ * `mowing` / `paused` / `docked` / `error`. `batteryLevel` (0..100) is
10128
+ * nullable — some mowers don't report a battery percentage.
10129
+ *
10130
+ * `startMowing` begins a mowing run, `pause` halts it in place, and
10131
+ * `dock` sends the mower back to its charging station.
10132
+ */
10133
+ var LawnMowerActivitySchema = _enum([
10134
+ "idle",
10135
+ "mowing",
10136
+ "paused",
10137
+ "docked",
10138
+ "error"
10139
+ ]);
10140
+ /** Severity of the current device/error code — info (status), warning, error. */
10141
+ var DeviceCodeSeveritySchema = _enum([
10142
+ "info",
10143
+ "warning",
10144
+ "error"
10145
+ ]);
10119
10146
  var LawnMowerControlStatusSchema = object({
10120
10147
  /** Lifecycle activity of the mower. */
10121
- activity: _enum([
10122
- "idle",
10123
- "mowing",
10124
- "paused",
10125
- "docked",
10126
- "error"
10127
- ]),
10148
+ activity: LawnMowerActivitySchema,
10128
10149
  /** 0..100 battery percentage. Null when the device has no battery
10129
10150
  * reading. */
10130
10151
  batteryLevel: number().min(0).max(100).nullable(),
10152
+ /** 0..100 mowing-completion percentage of the current task, or null when no
10153
+ * task is active / progress is unavailable. */
10154
+ progressPercent: number().min(0).max(100).nullable(),
10155
+ /** Current device/event code (dynamic — mostly status, sometimes an error),
10156
+ * or null when unknown. */
10157
+ currentCode: number().nullable(),
10158
+ /** Human label for {@link currentCode}, or null when undecodable. */
10159
+ currentCodeLabel: string().nullable(),
10160
+ /** Severity of {@link currentCode}. `error` (and often `warning`) warrants UI
10161
+ * attention; `info` is normal status. */
10162
+ severity: DeviceCodeSeveritySchema,
10131
10163
  /** Ms epoch when the slice was last updated. */
10132
10164
  lastChangedAt: number()
10133
10165
  });
@@ -12353,6 +12385,7 @@ var VacuumStateSchema = _enum([
12353
12385
  "paused",
12354
12386
  "returning",
12355
12387
  "docked",
12388
+ "drying",
12356
12389
  "error"
12357
12390
  ]);
12358
12391
  /**
@@ -12391,6 +12424,12 @@ var VacuumControlStatusSchema = object({
12391
12424
  detergent: TankStatusSchema.nullable(),
12392
12425
  /** Dust bin. Null when the hardware has no dust bin. */
12393
12426
  dustBin: TankStatusSchema.nullable(),
12427
+ /** 0..100 cleaning-completion percentage of the current task, or null. */
12428
+ progressPercent: number().min(0).max(100).nullable(),
12429
+ /** Current error code (0 / null = no error). */
12430
+ errorCode: number().nullable(),
12431
+ /** Human label for {@link errorCode}, or null when none / undecodable. */
12432
+ errorLabel: string().nullable(),
12394
12433
  /** Ms epoch when the slice was last updated. */
12395
12434
  lastChangedAt: number()
12396
12435
  });
@@ -16906,6 +16945,9 @@ method(object({
16906
16945
  }), method(ReleaseInputSchema.extend({ addonId: string() }), _void(), {
16907
16946
  kind: "mutation",
16908
16947
  auth: "admin"
16948
+ }), method(ResyncInputSchema, ResyncResultSchema, {
16949
+ kind: "mutation",
16950
+ auth: "admin"
16909
16951
  }), method(object({
16910
16952
  deviceId: number(),
16911
16953
  key: string(),
@@ -20668,6 +20710,12 @@ Object.freeze({
20668
20710
  addonId: null,
20669
20711
  access: "create"
20670
20712
  },
20713
+ "deviceManager.adoptionResync": {
20714
+ capName: "device-manager",
20715
+ capScope: "system",
20716
+ addonId: null,
20717
+ access: "create"
20718
+ },
20671
20719
  "deviceManager.allocateDeviceId": {
20672
20720
  capName: "device-manager",
20673
20721
  capScope: "system",
@@ -44576,7 +44624,8 @@ function classifyKey(key) {
44576
44624
  const hex = lookupHexId(key);
44577
44625
  if (hex !== void 0) return {
44578
44626
  kind: "measurement",
44579
- quantity: hex.quantity
44627
+ quantity: hex.quantity,
44628
+ name: hex.name
44580
44629
  };
44581
44630
  const named = Object.prototype.hasOwnProperty.call(NAMED_QUANTITY, key) ? NAMED_QUANTITY[key] : void 0;
44582
44631
  if (named !== void 0) return {
@@ -44612,6 +44661,7 @@ var Station = class {
44612
44661
  ...owner !== void 0 ? { hardwareId: owner } : {},
44613
44662
  ...info?.model ? { model: info.model } : {},
44614
44663
  ...info?.channel !== void 0 ? { channel: info.channel } : {},
44664
+ ...cls.name !== void 0 ? { name: cls.name } : {},
44615
44665
  quantity: cls.quantity,
44616
44666
  value: r.value,
44617
44667
  unit: r.unit,
@@ -44645,6 +44695,7 @@ var Station = class {
44645
44695
  this.upsert(id, {
44646
44696
  id,
44647
44697
  ...r.channel !== void 0 ? { channel: r.channel } : {},
44698
+ ...cls.name !== void 0 ? { name: cls.name } : {},
44648
44699
  quantity: cls.quantity,
44649
44700
  value: r.value,
44650
44701
  unit: r.unit,
@@ -45670,15 +45721,18 @@ function valueFieldForCap(cap) {
45670
45721
  }
45671
45722
  }
45672
45723
  /**
45673
- * Build a human label for a sensor from its quantity + optional channel.
45674
- * `temperature` + channel 2 `Temperature CH2`; channel-less → `Temperature`.
45724
+ * Build a human label for a sensor. Prefers the SPECIFIC measurement `name` when
45725
+ * the library resolved one (e.g. "Outdoor Temperature", "Dewpoint Temperature",
45726
+ * "Wind Gust") so same-quantity sensors are distinguishable; otherwise falls back
45727
+ * to the quantity label. A channel suffix is appended when present
45728
+ * (`temperature` + channel 2 → `Temperature CH2`).
45675
45729
  *
45676
45730
  * Accepts a plain `string` (not just {@link Quantity}) so a persisted config
45677
45731
  * value flows through without a cast; an unknown quantity falls back to its raw
45678
45732
  * string label.
45679
45733
  */
45680
- function sensorLabel(quantity, channel) {
45681
- const base = isKnownQuantity(quantity) ? QUANTITY_LABEL[quantity] : quantity;
45734
+ function sensorLabel(quantity, channel, name) {
45735
+ const base = name !== void 0 && name.length > 0 ? name : isKnownQuantity(quantity) ? QUANTITY_LABEL[quantity] : quantity;
45682
45736
  return channel !== void 0 ? `${base} CH${channel}` : base;
45683
45737
  }
45684
45738
  /** Type guard: is `q` one of the known {@link Quantity} union members? */
@@ -45712,7 +45766,7 @@ var QUANTITY_LABEL = {
45712
45766
  function buildEcowittGatewayCandidate(input) {
45713
45767
  const children = input.sensors.map((sensor) => ({
45714
45768
  childNativeId: sensor.id,
45715
- name: sensorLabel(sensor.quantity, sensor.channel),
45769
+ name: sensorLabel(sensor.quantity, sensor.channel, sensor.name),
45716
45770
  type: DeviceType.Sensor,
45717
45771
  status: "online",
45718
45772
  metadata: sensor.model !== void 0 ? { model: sensor.model } : {},
@@ -46187,7 +46241,8 @@ function clampForCap(cap, value) {
46187
46241
  var ecowittSensorEntrySchema = object({
46188
46242
  sensorId: string(),
46189
46243
  quantity: string(),
46190
- channel: number().optional()
46244
+ channel: number().optional(),
46245
+ name: string().optional()
46191
46246
  });
46192
46247
  /**
46193
46248
  * Persisted config for an Ecowitt gateway Container. `brokerId` selects the
@@ -46230,7 +46285,7 @@ var EcowittContainerDevice = class extends BaseDevice {
46230
46285
  const meta = {
46231
46286
  type: DeviceType.Sensor,
46232
46287
  role: roleForQuantity(sensor.quantity),
46233
- name: sensorLabel(sensor.quantity, sensor.channel),
46288
+ name: sensorLabel(sensor.quantity, sensor.channel, sensor.name),
46234
46289
  linkDeviceId: this.id,
46235
46290
  ...this.integrationId !== void 0 ? { integrationId: this.integrationId } : {}
46236
46291
  };
@@ -46385,7 +46440,8 @@ var EcowittProviderAddon = class extends BaseDeviceProvider {
46385
46440
  const nextSensors = sensors.map((s) => ({
46386
46441
  sensorId: s.id,
46387
46442
  quantity: s.quantity,
46388
- ...s.channel !== void 0 ? { channel: s.channel } : {}
46443
+ ...s.channel !== void 0 ? { channel: s.channel } : {},
46444
+ ...s.name !== void 0 ? { name: s.name } : {}
46389
46445
  }));
46390
46446
  const cfg = await devices.loadConfig(containerId).catch(() => ({}));
46391
46447
  if (sensorsEqual(Array.isArray(cfg["sensors"]) ? cfg["sensors"] : [], nextSensors)) return;
@@ -46506,7 +46562,8 @@ var EcowittProviderAddon = class extends BaseDeviceProvider {
46506
46562
  sensors: ecowittFacades.getSensors(brokerId).map((s) => ({
46507
46563
  sensorId: s.id,
46508
46564
  quantity: s.quantity,
46509
- ...s.channel !== void 0 ? { channel: s.channel } : {}
46565
+ ...s.channel !== void 0 ? { channel: s.channel } : {},
46566
+ ...s.name !== void 0 ? { name: s.name } : {}
46510
46567
  })),
46511
46568
  system: "ecowitt",
46512
46569
  integrationId,
@@ -46574,12 +46631,18 @@ var EcowittProviderAddon = class extends BaseDeviceProvider {
46574
46631
  /** Structural equality of two persisted sensor lists (order-independent by id). */
46575
46632
  function sensorsEqual(a, b) {
46576
46633
  if (a.length !== b.length) return false;
46577
- const aIds = /* @__PURE__ */ new Set();
46634
+ const aById = /* @__PURE__ */ new Map();
46578
46635
  for (const entry of a) if (typeof entry === "object" && entry !== null && "sensorId" in entry) {
46579
46636
  const id = entry.sensorId;
46580
- if (typeof id === "string") aIds.add(id);
46637
+ if (typeof id === "string") {
46638
+ const name = "name" in entry && typeof entry.name === "string" ? entry.name : void 0;
46639
+ aById.set(id, name);
46640
+ }
46641
+ }
46642
+ for (const entry of b) {
46643
+ if (!aById.has(entry.sensorId)) return false;
46644
+ if (aById.get(entry.sensorId) !== entry.name) return false;
46581
46645
  }
46582
- for (const entry of b) if (!aIds.has(entry.sensorId)) return false;
46583
46646
  return true;
46584
46647
  }
46585
46648
  //#endregion
package/dist/addon.mjs CHANGED
@@ -10083,15 +10083,18 @@ var humiditySensorCapability = {
10083
10083
  runtimeState: HumiditySensorStatusSchema
10084
10084
  };
10085
10085
  /**
10086
- * Image display cap. Models HA `image.*` entities a single still image
10087
- * exposed by an integration (a snapshot, a chart, a generated picture).
10086
+ * Image display cap. Models a single still image exposed by an integration
10087
+ * a snapshot, a chart, a generated picture, or a robot's cleaning-map render.
10088
10088
  *
10089
- * Read-only: there are no setters. The provider resolves the HA
10090
- * `entity_picture` (a relative, signed-token path) into an ABSOLUTE URL
10091
- * the browser loads directly the token stays in the query string so no
10092
- * auth header is required. The slice carries that URL plus the upstream
10093
- * last-updated timestamp; the image changes when the entity state (a
10094
- * timestamp) changes.
10089
+ * Read-only: there are no setters. The provider resolves whatever upstream
10090
+ * source it has into an ABSOLUTE URL the browser loads directly:
10091
+ * - HA `image.*` entities the `entity_picture` signed-token path
10092
+ * (token stays in the query string, so no auth header is needed);
10093
+ * - a Dreame/robot map the cloud/OSS map-image URL (or an addon
10094
+ * data-plane URL serving the rendered map bytes), exposed as its own
10095
+ * Image child device grouped under the robot's container.
10096
+ * The slice carries that URL plus the upstream last-updated timestamp; the
10097
+ * image changes when the source's last-updated marker changes.
10095
10098
  */
10096
10099
  var ImageStatusSchema = object({
10097
10100
  /** Absolute signed URL the browser loads directly. Null when the
@@ -10117,18 +10120,47 @@ var imageCapability = {
10117
10120
  */
10118
10121
  runtimeState: ImageStatusSchema
10119
10122
  };
10123
+ /**
10124
+ * Robotic lawn-mower cap. Models HA `lawn_mower.*` entities — anything
10125
+ * with a mowing lifecycle plus a dock action.
10126
+ *
10127
+ * Activity follows HA's canonical lawn-mower lifecycle: `idle` /
10128
+ * `mowing` / `paused` / `docked` / `error`. `batteryLevel` (0..100) is
10129
+ * nullable — some mowers don't report a battery percentage.
10130
+ *
10131
+ * `startMowing` begins a mowing run, `pause` halts it in place, and
10132
+ * `dock` sends the mower back to its charging station.
10133
+ */
10134
+ var LawnMowerActivitySchema = _enum([
10135
+ "idle",
10136
+ "mowing",
10137
+ "paused",
10138
+ "docked",
10139
+ "error"
10140
+ ]);
10141
+ /** Severity of the current device/error code — info (status), warning, error. */
10142
+ var DeviceCodeSeveritySchema = _enum([
10143
+ "info",
10144
+ "warning",
10145
+ "error"
10146
+ ]);
10120
10147
  var LawnMowerControlStatusSchema = object({
10121
10148
  /** Lifecycle activity of the mower. */
10122
- activity: _enum([
10123
- "idle",
10124
- "mowing",
10125
- "paused",
10126
- "docked",
10127
- "error"
10128
- ]),
10149
+ activity: LawnMowerActivitySchema,
10129
10150
  /** 0..100 battery percentage. Null when the device has no battery
10130
10151
  * reading. */
10131
10152
  batteryLevel: number().min(0).max(100).nullable(),
10153
+ /** 0..100 mowing-completion percentage of the current task, or null when no
10154
+ * task is active / progress is unavailable. */
10155
+ progressPercent: number().min(0).max(100).nullable(),
10156
+ /** Current device/event code (dynamic — mostly status, sometimes an error),
10157
+ * or null when unknown. */
10158
+ currentCode: number().nullable(),
10159
+ /** Human label for {@link currentCode}, or null when undecodable. */
10160
+ currentCodeLabel: string().nullable(),
10161
+ /** Severity of {@link currentCode}. `error` (and often `warning`) warrants UI
10162
+ * attention; `info` is normal status. */
10163
+ severity: DeviceCodeSeveritySchema,
10132
10164
  /** Ms epoch when the slice was last updated. */
10133
10165
  lastChangedAt: number()
10134
10166
  });
@@ -12354,6 +12386,7 @@ var VacuumStateSchema = _enum([
12354
12386
  "paused",
12355
12387
  "returning",
12356
12388
  "docked",
12389
+ "drying",
12357
12390
  "error"
12358
12391
  ]);
12359
12392
  /**
@@ -12392,6 +12425,12 @@ var VacuumControlStatusSchema = object({
12392
12425
  detergent: TankStatusSchema.nullable(),
12393
12426
  /** Dust bin. Null when the hardware has no dust bin. */
12394
12427
  dustBin: TankStatusSchema.nullable(),
12428
+ /** 0..100 cleaning-completion percentage of the current task, or null. */
12429
+ progressPercent: number().min(0).max(100).nullable(),
12430
+ /** Current error code (0 / null = no error). */
12431
+ errorCode: number().nullable(),
12432
+ /** Human label for {@link errorCode}, or null when none / undecodable. */
12433
+ errorLabel: string().nullable(),
12395
12434
  /** Ms epoch when the slice was last updated. */
12396
12435
  lastChangedAt: number()
12397
12436
  });
@@ -16907,6 +16946,9 @@ method(object({
16907
16946
  }), method(ReleaseInputSchema.extend({ addonId: string() }), _void(), {
16908
16947
  kind: "mutation",
16909
16948
  auth: "admin"
16949
+ }), method(ResyncInputSchema, ResyncResultSchema, {
16950
+ kind: "mutation",
16951
+ auth: "admin"
16910
16952
  }), method(object({
16911
16953
  deviceId: number(),
16912
16954
  key: string(),
@@ -20669,6 +20711,12 @@ Object.freeze({
20669
20711
  addonId: null,
20670
20712
  access: "create"
20671
20713
  },
20714
+ "deviceManager.adoptionResync": {
20715
+ capName: "device-manager",
20716
+ capScope: "system",
20717
+ addonId: null,
20718
+ access: "create"
20719
+ },
20672
20720
  "deviceManager.allocateDeviceId": {
20673
20721
  capName: "device-manager",
20674
20722
  capScope: "system",
@@ -44577,7 +44625,8 @@ function classifyKey(key) {
44577
44625
  const hex = lookupHexId(key);
44578
44626
  if (hex !== void 0) return {
44579
44627
  kind: "measurement",
44580
- quantity: hex.quantity
44628
+ quantity: hex.quantity,
44629
+ name: hex.name
44581
44630
  };
44582
44631
  const named = Object.prototype.hasOwnProperty.call(NAMED_QUANTITY, key) ? NAMED_QUANTITY[key] : void 0;
44583
44632
  if (named !== void 0) return {
@@ -44613,6 +44662,7 @@ var Station = class {
44613
44662
  ...owner !== void 0 ? { hardwareId: owner } : {},
44614
44663
  ...info?.model ? { model: info.model } : {},
44615
44664
  ...info?.channel !== void 0 ? { channel: info.channel } : {},
44665
+ ...cls.name !== void 0 ? { name: cls.name } : {},
44616
44666
  quantity: cls.quantity,
44617
44667
  value: r.value,
44618
44668
  unit: r.unit,
@@ -44646,6 +44696,7 @@ var Station = class {
44646
44696
  this.upsert(id, {
44647
44697
  id,
44648
44698
  ...r.channel !== void 0 ? { channel: r.channel } : {},
44699
+ ...cls.name !== void 0 ? { name: cls.name } : {},
44649
44700
  quantity: cls.quantity,
44650
44701
  value: r.value,
44651
44702
  unit: r.unit,
@@ -45671,15 +45722,18 @@ function valueFieldForCap(cap) {
45671
45722
  }
45672
45723
  }
45673
45724
  /**
45674
- * Build a human label for a sensor from its quantity + optional channel.
45675
- * `temperature` + channel 2 `Temperature CH2`; channel-less → `Temperature`.
45725
+ * Build a human label for a sensor. Prefers the SPECIFIC measurement `name` when
45726
+ * the library resolved one (e.g. "Outdoor Temperature", "Dewpoint Temperature",
45727
+ * "Wind Gust") so same-quantity sensors are distinguishable; otherwise falls back
45728
+ * to the quantity label. A channel suffix is appended when present
45729
+ * (`temperature` + channel 2 → `Temperature CH2`).
45676
45730
  *
45677
45731
  * Accepts a plain `string` (not just {@link Quantity}) so a persisted config
45678
45732
  * value flows through without a cast; an unknown quantity falls back to its raw
45679
45733
  * string label.
45680
45734
  */
45681
- function sensorLabel(quantity, channel) {
45682
- const base = isKnownQuantity(quantity) ? QUANTITY_LABEL[quantity] : quantity;
45735
+ function sensorLabel(quantity, channel, name) {
45736
+ const base = name !== void 0 && name.length > 0 ? name : isKnownQuantity(quantity) ? QUANTITY_LABEL[quantity] : quantity;
45683
45737
  return channel !== void 0 ? `${base} CH${channel}` : base;
45684
45738
  }
45685
45739
  /** Type guard: is `q` one of the known {@link Quantity} union members? */
@@ -45713,7 +45767,7 @@ var QUANTITY_LABEL = {
45713
45767
  function buildEcowittGatewayCandidate(input) {
45714
45768
  const children = input.sensors.map((sensor) => ({
45715
45769
  childNativeId: sensor.id,
45716
- name: sensorLabel(sensor.quantity, sensor.channel),
45770
+ name: sensorLabel(sensor.quantity, sensor.channel, sensor.name),
45717
45771
  type: DeviceType.Sensor,
45718
45772
  status: "online",
45719
45773
  metadata: sensor.model !== void 0 ? { model: sensor.model } : {},
@@ -46188,7 +46242,8 @@ function clampForCap(cap, value) {
46188
46242
  var ecowittSensorEntrySchema = object({
46189
46243
  sensorId: string(),
46190
46244
  quantity: string(),
46191
- channel: number().optional()
46245
+ channel: number().optional(),
46246
+ name: string().optional()
46192
46247
  });
46193
46248
  /**
46194
46249
  * Persisted config for an Ecowitt gateway Container. `brokerId` selects the
@@ -46231,7 +46286,7 @@ var EcowittContainerDevice = class extends BaseDevice {
46231
46286
  const meta = {
46232
46287
  type: DeviceType.Sensor,
46233
46288
  role: roleForQuantity(sensor.quantity),
46234
- name: sensorLabel(sensor.quantity, sensor.channel),
46289
+ name: sensorLabel(sensor.quantity, sensor.channel, sensor.name),
46235
46290
  linkDeviceId: this.id,
46236
46291
  ...this.integrationId !== void 0 ? { integrationId: this.integrationId } : {}
46237
46292
  };
@@ -46386,7 +46441,8 @@ var EcowittProviderAddon = class extends BaseDeviceProvider {
46386
46441
  const nextSensors = sensors.map((s) => ({
46387
46442
  sensorId: s.id,
46388
46443
  quantity: s.quantity,
46389
- ...s.channel !== void 0 ? { channel: s.channel } : {}
46444
+ ...s.channel !== void 0 ? { channel: s.channel } : {},
46445
+ ...s.name !== void 0 ? { name: s.name } : {}
46390
46446
  }));
46391
46447
  const cfg = await devices.loadConfig(containerId).catch(() => ({}));
46392
46448
  if (sensorsEqual(Array.isArray(cfg["sensors"]) ? cfg["sensors"] : [], nextSensors)) return;
@@ -46507,7 +46563,8 @@ var EcowittProviderAddon = class extends BaseDeviceProvider {
46507
46563
  sensors: ecowittFacades.getSensors(brokerId).map((s) => ({
46508
46564
  sensorId: s.id,
46509
46565
  quantity: s.quantity,
46510
- ...s.channel !== void 0 ? { channel: s.channel } : {}
46566
+ ...s.channel !== void 0 ? { channel: s.channel } : {},
46567
+ ...s.name !== void 0 ? { name: s.name } : {}
46511
46568
  })),
46512
46569
  system: "ecowitt",
46513
46570
  integrationId,
@@ -46575,12 +46632,18 @@ var EcowittProviderAddon = class extends BaseDeviceProvider {
46575
46632
  /** Structural equality of two persisted sensor lists (order-independent by id). */
46576
46633
  function sensorsEqual(a, b) {
46577
46634
  if (a.length !== b.length) return false;
46578
- const aIds = /* @__PURE__ */ new Set();
46635
+ const aById = /* @__PURE__ */ new Map();
46579
46636
  for (const entry of a) if (typeof entry === "object" && entry !== null && "sensorId" in entry) {
46580
46637
  const id = entry.sensorId;
46581
- if (typeof id === "string") aIds.add(id);
46638
+ if (typeof id === "string") {
46639
+ const name = "name" in entry && typeof entry.name === "string" ? entry.name : void 0;
46640
+ aById.set(id, name);
46641
+ }
46642
+ }
46643
+ for (const entry of b) {
46644
+ if (!aById.has(entry.sensorId)) return false;
46645
+ if (aById.get(entry.sensorId) !== entry.name) return false;
46582
46646
  }
46583
- for (const entry of b) if (!aIds.has(entry.sensorId)) return false;
46584
46647
  return true;
46585
46648
  }
46586
46649
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-ecowitt",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "Ecowitt weather-station device-provider addon for CamStack — wraps the @apocaliss92/nodewitt local-poll / push client",
5
5
  "keywords": [
6
6
  "camstack",
@@ -71,7 +71,7 @@
71
71
  "publish": "npm publish --access public"
72
72
  },
73
73
  "devDependencies": {
74
- "@apocaliss92/nodewitt": "^1.1.1",
74
+ "@apocaliss92/nodewitt": "^1.2.0",
75
75
  "@camstack/types": "*",
76
76
  "typescript": "~6.0.3",
77
77
  "vite": "^8.0.11",