@camstack/addon-provider-dreo 0.1.3 → 0.1.4

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.
Files changed (3) hide show
  1. package/dist/addon.js +113 -25
  2. package/dist/addon.mjs +113 -25
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -10099,15 +10099,18 @@ var humiditySensorCapability = {
10099
10099
  runtimeState: HumiditySensorStatusSchema
10100
10100
  };
10101
10101
  /**
10102
- * Image display cap. Models HA `image.*` entities a single still image
10103
- * exposed by an integration (a snapshot, a chart, a generated picture).
10102
+ * Image display cap. Models a single still image exposed by an integration
10103
+ * a snapshot, a chart, a generated picture, or a robot's cleaning-map render.
10104
10104
  *
10105
- * Read-only: there are no setters. The provider resolves the HA
10106
- * `entity_picture` (a relative, signed-token path) into an ABSOLUTE URL
10107
- * the browser loads directly the token stays in the query string so no
10108
- * auth header is required. The slice carries that URL plus the upstream
10109
- * last-updated timestamp; the image changes when the entity state (a
10110
- * timestamp) changes.
10105
+ * Read-only: there are no setters. The provider resolves whatever upstream
10106
+ * source it has into an ABSOLUTE URL the browser loads directly:
10107
+ * - HA `image.*` entities the `entity_picture` signed-token path
10108
+ * (token stays in the query string, so no auth header is needed);
10109
+ * - a Dreame/robot map the cloud/OSS map-image URL (or an addon
10110
+ * data-plane URL serving the rendered map bytes), exposed as its own
10111
+ * Image child device grouped under the robot's container.
10112
+ * The slice carries that URL plus the upstream last-updated timestamp; the
10113
+ * image changes when the source's last-updated marker changes.
10111
10114
  */
10112
10115
  var ImageStatusSchema = object({
10113
10116
  /** Absolute signed URL the browser loads directly. Null when the
@@ -10133,18 +10136,47 @@ var imageCapability = {
10133
10136
  */
10134
10137
  runtimeState: ImageStatusSchema
10135
10138
  };
10139
+ /**
10140
+ * Robotic lawn-mower cap. Models HA `lawn_mower.*` entities — anything
10141
+ * with a mowing lifecycle plus a dock action.
10142
+ *
10143
+ * Activity follows HA's canonical lawn-mower lifecycle: `idle` /
10144
+ * `mowing` / `paused` / `docked` / `error`. `batteryLevel` (0..100) is
10145
+ * nullable — some mowers don't report a battery percentage.
10146
+ *
10147
+ * `startMowing` begins a mowing run, `pause` halts it in place, and
10148
+ * `dock` sends the mower back to its charging station.
10149
+ */
10150
+ var LawnMowerActivitySchema = _enum([
10151
+ "idle",
10152
+ "mowing",
10153
+ "paused",
10154
+ "docked",
10155
+ "error"
10156
+ ]);
10157
+ /** Severity of the current device/error code — info (status), warning, error. */
10158
+ var DeviceCodeSeveritySchema = _enum([
10159
+ "info",
10160
+ "warning",
10161
+ "error"
10162
+ ]);
10136
10163
  var LawnMowerControlStatusSchema = object({
10137
10164
  /** Lifecycle activity of the mower. */
10138
- activity: _enum([
10139
- "idle",
10140
- "mowing",
10141
- "paused",
10142
- "docked",
10143
- "error"
10144
- ]),
10165
+ activity: LawnMowerActivitySchema,
10145
10166
  /** 0..100 battery percentage. Null when the device has no battery
10146
10167
  * reading. */
10147
10168
  batteryLevel: number().min(0).max(100).nullable(),
10169
+ /** 0..100 mowing-completion percentage of the current task, or null when no
10170
+ * task is active / progress is unavailable. */
10171
+ progressPercent: number().min(0).max(100).nullable(),
10172
+ /** Current device/event code (dynamic — mostly status, sometimes an error),
10173
+ * or null when unknown. */
10174
+ currentCode: number().nullable(),
10175
+ /** Human label for {@link currentCode}, or null when undecodable. */
10176
+ currentCodeLabel: string().nullable(),
10177
+ /** Severity of {@link currentCode}. `error` (and often `warning`) warrants UI
10178
+ * attention; `info` is normal status. */
10179
+ severity: DeviceCodeSeveritySchema,
10148
10180
  /** Ms epoch when the slice was last updated. */
10149
10181
  lastChangedAt: number()
10150
10182
  });
@@ -12370,6 +12402,7 @@ var VacuumStateSchema = _enum([
12370
12402
  "paused",
12371
12403
  "returning",
12372
12404
  "docked",
12405
+ "drying",
12373
12406
  "error"
12374
12407
  ]);
12375
12408
  /**
@@ -12408,6 +12441,12 @@ var VacuumControlStatusSchema = object({
12408
12441
  detergent: TankStatusSchema.nullable(),
12409
12442
  /** Dust bin. Null when the hardware has no dust bin. */
12410
12443
  dustBin: TankStatusSchema.nullable(),
12444
+ /** 0..100 cleaning-completion percentage of the current task, or null. */
12445
+ progressPercent: number().min(0).max(100).nullable(),
12446
+ /** Current error code (0 / null = no error). */
12447
+ errorCode: number().nullable(),
12448
+ /** Human label for {@link errorCode}, or null when none / undecodable. */
12449
+ errorLabel: string().nullable(),
12411
12450
  /** Ms epoch when the slice was last updated. */
12412
12451
  lastChangedAt: number()
12413
12452
  });
@@ -13374,9 +13413,29 @@ var BaseDevice$1 = class {
13374
13413
  * is open (Reolink writes `hasPtz/hasIntercom`, Hikvision writes
13375
13414
  * `hasSupplementalLight/hasAlarmIo`, etc).
13376
13415
  *
13377
- * Default: no-op (driver had no probe to run).
13378
- */
13379
- async onProbe() {}
13416
+ * Default: nothing to probe mark the device PROBED (set `lastProbedAt`) so
13417
+ * the kernel treats it as ready immediately. A device that derives its shape
13418
+ * from a spec (a container, or an accessory sensor) rather than from a
13419
+ * hardware probe has no probe to "complete"; without stamping `lastProbedAt`
13420
+ * it would look perpetually un-probed — logging "Initial probe did not
13421
+ * complete" on every boot and spinning a pointless retry chain. Drivers that
13422
+ * DO probe override this and write their own `feature-probe` slice (including
13423
+ * `lastProbedAt`) once their probe actually succeeds.
13424
+ */
13425
+ async onProbe() {
13426
+ const base = this.runtimeState.getCapState("feature-probe") ?? {
13427
+ flags: {},
13428
+ deviceType: null,
13429
+ model: null,
13430
+ channelCount: null,
13431
+ lastProbedAt: 0,
13432
+ lastFetchedAt: 0
13433
+ };
13434
+ this.runtimeState.setCapState("feature-probe", {
13435
+ ...base,
13436
+ lastProbedAt: Date.now()
13437
+ });
13438
+ }
13380
13439
  /**
13381
13440
  * Phase 5 — fired after the device + its accessories are registered.
13382
13441
  * Drivers publish streams to the broker, kick off background tasks,
@@ -14838,17 +14897,32 @@ var ReleaseInputSchema = object({
14838
14897
  * the parent cascades into every accessory. */
14839
14898
  camDeviceId: number().int().nonnegative()
14840
14899
  });
14841
- var ResyncInputSchema = object({
14842
- /** Parent CamStack device id of an adopted device. The provider resolves its
14843
- * source (integration/broker + native id) and re-aligns the device's
14844
- * structural spec (type/role/capabilities/units) with the live mapping,
14845
- * rebuilding any child whose class changed while preserving operator edits. */
14846
- camDeviceId: number().int().nonnegative() });
14900
+ var ResyncInputSchema = object({
14901
+ /** Parent CamStack device id of an adopted device. The provider resolves its
14902
+ * source (integration/broker + native id) and re-aligns the device's
14903
+ * structural spec (type/role/capabilities/units) with the live mapping,
14904
+ * rebuilding any child whose class changed while preserving operator edits. */
14905
+ camDeviceId: number().int().nonnegative(),
14906
+ /** "Resync from zero" (#19). When true, the kernel PURGES every accessory
14907
+ * child of `camDeviceId` BEFORE the provider re-derives the device, so the
14908
+ * children are rebuilt fresh from source — correct names, coords, and units —
14909
+ * instead of being preserved by the incremental reconcile. Use to recover from
14910
+ * legacy generic/placeholder names that the normal name-precedence keeps frozen
14911
+ * (the operator's explicit reset). Push-driven integrations (no-op resync)
14912
+ * rebuild on their next snapshot; pull/command integrations rebuild in `resync`.
14913
+ * Operator edits on the PARENT (its name, layout, primary-child pick) survive —
14914
+ * only the children are torn down. Omitted/false ⇒ the normal incremental
14915
+ * re-sync that preserves children. */
14916
+ resetToSource: boolean().optional()
14917
+ });
14847
14918
  var ResyncResultSchema = object({
14848
14919
  /** True when the persisted spec actually changed (children may have been rebuilt). */
14849
14920
  changed: boolean(),
14850
14921
  /** Number of child devices rebuilt into a new class by this re-sync. */
14851
- rebuiltChildren: number().int().nonnegative()
14922
+ rebuiltChildren: number().int().nonnegative(),
14923
+ /** Number of accessory children torn down by a `resetToSource` purge before the
14924
+ * provider re-derived the device. 0/absent for a normal incremental re-sync. */
14925
+ removedChildren: number().int().nonnegative().optional()
14852
14926
  });
14853
14927
  var deviceAdoptionCapability = {
14854
14928
  name: "device-adoption",
@@ -16613,6 +16687,11 @@ var DeviceMetaSchema = object({
16613
16687
  addonId: string(),
16614
16688
  type: string(),
16615
16689
  name: string(),
16690
+ /** True once an operator explicitly renamed the device via `setName`. Drives
16691
+ * reconcile name-precedence (preserve operator name vs adopt fresh provider
16692
+ * name). Absent ⇒ treated as user-named (PRESERVE) for legacy rows. See
16693
+ * `DeviceMeta.userNamed`. */
16694
+ userNamed: boolean().optional(),
16616
16695
  location: string().nullable(),
16617
16696
  disabled: boolean(),
16618
16697
  parentDeviceId: number().nullable(),
@@ -16923,6 +17002,9 @@ method(object({
16923
17002
  }), method(ReleaseInputSchema.extend({ addonId: string() }), _void(), {
16924
17003
  kind: "mutation",
16925
17004
  auth: "admin"
17005
+ }), method(ResyncInputSchema, ResyncResultSchema, {
17006
+ kind: "mutation",
17007
+ auth: "admin"
16926
17008
  }), method(object({
16927
17009
  deviceId: number(),
16928
17010
  key: string(),
@@ -20685,6 +20767,12 @@ Object.freeze({
20685
20767
  addonId: null,
20686
20768
  access: "create"
20687
20769
  },
20770
+ "deviceManager.adoptionResync": {
20771
+ capName: "device-manager",
20772
+ capScope: "system",
20773
+ addonId: null,
20774
+ access: "create"
20775
+ },
20688
20776
  "deviceManager.allocateDeviceId": {
20689
20777
  capName: "device-manager",
20690
20778
  capScope: "system",
package/dist/addon.mjs CHANGED
@@ -10100,15 +10100,18 @@ var humiditySensorCapability = {
10100
10100
  runtimeState: HumiditySensorStatusSchema
10101
10101
  };
10102
10102
  /**
10103
- * Image display cap. Models HA `image.*` entities a single still image
10104
- * exposed by an integration (a snapshot, a chart, a generated picture).
10103
+ * Image display cap. Models a single still image exposed by an integration
10104
+ * a snapshot, a chart, a generated picture, or a robot's cleaning-map render.
10105
10105
  *
10106
- * Read-only: there are no setters. The provider resolves the HA
10107
- * `entity_picture` (a relative, signed-token path) into an ABSOLUTE URL
10108
- * the browser loads directly the token stays in the query string so no
10109
- * auth header is required. The slice carries that URL plus the upstream
10110
- * last-updated timestamp; the image changes when the entity state (a
10111
- * timestamp) changes.
10106
+ * Read-only: there are no setters. The provider resolves whatever upstream
10107
+ * source it has into an ABSOLUTE URL the browser loads directly:
10108
+ * - HA `image.*` entities the `entity_picture` signed-token path
10109
+ * (token stays in the query string, so no auth header is needed);
10110
+ * - a Dreame/robot map the cloud/OSS map-image URL (or an addon
10111
+ * data-plane URL serving the rendered map bytes), exposed as its own
10112
+ * Image child device grouped under the robot's container.
10113
+ * The slice carries that URL plus the upstream last-updated timestamp; the
10114
+ * image changes when the source's last-updated marker changes.
10112
10115
  */
10113
10116
  var ImageStatusSchema = object({
10114
10117
  /** Absolute signed URL the browser loads directly. Null when the
@@ -10134,18 +10137,47 @@ var imageCapability = {
10134
10137
  */
10135
10138
  runtimeState: ImageStatusSchema
10136
10139
  };
10140
+ /**
10141
+ * Robotic lawn-mower cap. Models HA `lawn_mower.*` entities — anything
10142
+ * with a mowing lifecycle plus a dock action.
10143
+ *
10144
+ * Activity follows HA's canonical lawn-mower lifecycle: `idle` /
10145
+ * `mowing` / `paused` / `docked` / `error`. `batteryLevel` (0..100) is
10146
+ * nullable — some mowers don't report a battery percentage.
10147
+ *
10148
+ * `startMowing` begins a mowing run, `pause` halts it in place, and
10149
+ * `dock` sends the mower back to its charging station.
10150
+ */
10151
+ var LawnMowerActivitySchema = _enum([
10152
+ "idle",
10153
+ "mowing",
10154
+ "paused",
10155
+ "docked",
10156
+ "error"
10157
+ ]);
10158
+ /** Severity of the current device/error code — info (status), warning, error. */
10159
+ var DeviceCodeSeveritySchema = _enum([
10160
+ "info",
10161
+ "warning",
10162
+ "error"
10163
+ ]);
10137
10164
  var LawnMowerControlStatusSchema = object({
10138
10165
  /** Lifecycle activity of the mower. */
10139
- activity: _enum([
10140
- "idle",
10141
- "mowing",
10142
- "paused",
10143
- "docked",
10144
- "error"
10145
- ]),
10166
+ activity: LawnMowerActivitySchema,
10146
10167
  /** 0..100 battery percentage. Null when the device has no battery
10147
10168
  * reading. */
10148
10169
  batteryLevel: number().min(0).max(100).nullable(),
10170
+ /** 0..100 mowing-completion percentage of the current task, or null when no
10171
+ * task is active / progress is unavailable. */
10172
+ progressPercent: number().min(0).max(100).nullable(),
10173
+ /** Current device/event code (dynamic — mostly status, sometimes an error),
10174
+ * or null when unknown. */
10175
+ currentCode: number().nullable(),
10176
+ /** Human label for {@link currentCode}, or null when undecodable. */
10177
+ currentCodeLabel: string().nullable(),
10178
+ /** Severity of {@link currentCode}. `error` (and often `warning`) warrants UI
10179
+ * attention; `info` is normal status. */
10180
+ severity: DeviceCodeSeveritySchema,
10149
10181
  /** Ms epoch when the slice was last updated. */
10150
10182
  lastChangedAt: number()
10151
10183
  });
@@ -12371,6 +12403,7 @@ var VacuumStateSchema = _enum([
12371
12403
  "paused",
12372
12404
  "returning",
12373
12405
  "docked",
12406
+ "drying",
12374
12407
  "error"
12375
12408
  ]);
12376
12409
  /**
@@ -12409,6 +12442,12 @@ var VacuumControlStatusSchema = object({
12409
12442
  detergent: TankStatusSchema.nullable(),
12410
12443
  /** Dust bin. Null when the hardware has no dust bin. */
12411
12444
  dustBin: TankStatusSchema.nullable(),
12445
+ /** 0..100 cleaning-completion percentage of the current task, or null. */
12446
+ progressPercent: number().min(0).max(100).nullable(),
12447
+ /** Current error code (0 / null = no error). */
12448
+ errorCode: number().nullable(),
12449
+ /** Human label for {@link errorCode}, or null when none / undecodable. */
12450
+ errorLabel: string().nullable(),
12412
12451
  /** Ms epoch when the slice was last updated. */
12413
12452
  lastChangedAt: number()
12414
12453
  });
@@ -13375,9 +13414,29 @@ var BaseDevice$1 = class {
13375
13414
  * is open (Reolink writes `hasPtz/hasIntercom`, Hikvision writes
13376
13415
  * `hasSupplementalLight/hasAlarmIo`, etc).
13377
13416
  *
13378
- * Default: no-op (driver had no probe to run).
13379
- */
13380
- async onProbe() {}
13417
+ * Default: nothing to probe mark the device PROBED (set `lastProbedAt`) so
13418
+ * the kernel treats it as ready immediately. A device that derives its shape
13419
+ * from a spec (a container, or an accessory sensor) rather than from a
13420
+ * hardware probe has no probe to "complete"; without stamping `lastProbedAt`
13421
+ * it would look perpetually un-probed — logging "Initial probe did not
13422
+ * complete" on every boot and spinning a pointless retry chain. Drivers that
13423
+ * DO probe override this and write their own `feature-probe` slice (including
13424
+ * `lastProbedAt`) once their probe actually succeeds.
13425
+ */
13426
+ async onProbe() {
13427
+ const base = this.runtimeState.getCapState("feature-probe") ?? {
13428
+ flags: {},
13429
+ deviceType: null,
13430
+ model: null,
13431
+ channelCount: null,
13432
+ lastProbedAt: 0,
13433
+ lastFetchedAt: 0
13434
+ };
13435
+ this.runtimeState.setCapState("feature-probe", {
13436
+ ...base,
13437
+ lastProbedAt: Date.now()
13438
+ });
13439
+ }
13381
13440
  /**
13382
13441
  * Phase 5 — fired after the device + its accessories are registered.
13383
13442
  * Drivers publish streams to the broker, kick off background tasks,
@@ -14839,17 +14898,32 @@ var ReleaseInputSchema = object({
14839
14898
  * the parent cascades into every accessory. */
14840
14899
  camDeviceId: number().int().nonnegative()
14841
14900
  });
14842
- var ResyncInputSchema = object({
14843
- /** Parent CamStack device id of an adopted device. The provider resolves its
14844
- * source (integration/broker + native id) and re-aligns the device's
14845
- * structural spec (type/role/capabilities/units) with the live mapping,
14846
- * rebuilding any child whose class changed while preserving operator edits. */
14847
- camDeviceId: number().int().nonnegative() });
14901
+ var ResyncInputSchema = object({
14902
+ /** Parent CamStack device id of an adopted device. The provider resolves its
14903
+ * source (integration/broker + native id) and re-aligns the device's
14904
+ * structural spec (type/role/capabilities/units) with the live mapping,
14905
+ * rebuilding any child whose class changed while preserving operator edits. */
14906
+ camDeviceId: number().int().nonnegative(),
14907
+ /** "Resync from zero" (#19). When true, the kernel PURGES every accessory
14908
+ * child of `camDeviceId` BEFORE the provider re-derives the device, so the
14909
+ * children are rebuilt fresh from source — correct names, coords, and units —
14910
+ * instead of being preserved by the incremental reconcile. Use to recover from
14911
+ * legacy generic/placeholder names that the normal name-precedence keeps frozen
14912
+ * (the operator's explicit reset). Push-driven integrations (no-op resync)
14913
+ * rebuild on their next snapshot; pull/command integrations rebuild in `resync`.
14914
+ * Operator edits on the PARENT (its name, layout, primary-child pick) survive —
14915
+ * only the children are torn down. Omitted/false ⇒ the normal incremental
14916
+ * re-sync that preserves children. */
14917
+ resetToSource: boolean().optional()
14918
+ });
14848
14919
  var ResyncResultSchema = object({
14849
14920
  /** True when the persisted spec actually changed (children may have been rebuilt). */
14850
14921
  changed: boolean(),
14851
14922
  /** Number of child devices rebuilt into a new class by this re-sync. */
14852
- rebuiltChildren: number().int().nonnegative()
14923
+ rebuiltChildren: number().int().nonnegative(),
14924
+ /** Number of accessory children torn down by a `resetToSource` purge before the
14925
+ * provider re-derived the device. 0/absent for a normal incremental re-sync. */
14926
+ removedChildren: number().int().nonnegative().optional()
14853
14927
  });
14854
14928
  var deviceAdoptionCapability = {
14855
14929
  name: "device-adoption",
@@ -16614,6 +16688,11 @@ var DeviceMetaSchema = object({
16614
16688
  addonId: string(),
16615
16689
  type: string(),
16616
16690
  name: string(),
16691
+ /** True once an operator explicitly renamed the device via `setName`. Drives
16692
+ * reconcile name-precedence (preserve operator name vs adopt fresh provider
16693
+ * name). Absent ⇒ treated as user-named (PRESERVE) for legacy rows. See
16694
+ * `DeviceMeta.userNamed`. */
16695
+ userNamed: boolean().optional(),
16617
16696
  location: string().nullable(),
16618
16697
  disabled: boolean(),
16619
16698
  parentDeviceId: number().nullable(),
@@ -16924,6 +17003,9 @@ method(object({
16924
17003
  }), method(ReleaseInputSchema.extend({ addonId: string() }), _void(), {
16925
17004
  kind: "mutation",
16926
17005
  auth: "admin"
17006
+ }), method(ResyncInputSchema, ResyncResultSchema, {
17007
+ kind: "mutation",
17008
+ auth: "admin"
16927
17009
  }), method(object({
16928
17010
  deviceId: number(),
16929
17011
  key: string(),
@@ -20686,6 +20768,12 @@ Object.freeze({
20686
20768
  addonId: null,
20687
20769
  access: "create"
20688
20770
  },
20771
+ "deviceManager.adoptionResync": {
20772
+ capName: "device-manager",
20773
+ capScope: "system",
20774
+ addonId: null,
20775
+ access: "create"
20776
+ },
20689
20777
  "deviceManager.allocateDeviceId": {
20690
20778
  capName: "device-manager",
20691
20779
  capScope: "system",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-dreo",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "Dreo smart-device (fan / air-circulator / purifier / heater / humidifier) device-provider addon for CamStack — wraps the @apocaliss92/nodedreo Dreo cloud client (REST + WebSocket)",
5
5
  "keywords": [
6
6
  "camstack",