@camstack/addon-provider-dreo 0.2.75 → 0.2.77

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
@@ -7885,17 +7885,29 @@ var HHMM = /^([01]\d|2[0-3]):[0-5]\d$/;
7885
7885
  /**
7886
7886
  * DERIVED per-camera storage summary — the single field cheap consumers read
7887
7887
  * (the viewer's status dot, the camera list) instead of walking `bands`:
7888
- * - `off` — no band covers the camera (or it is disabled).
7889
- * - `events` — every band records around triggers only.
7890
- * - `continuous` — at least one band records continuously.
7891
- *
7892
- * NEVER authored: the recorder stamps it from the authoritative `bands` on
7893
- * every save (`activeModeForConfig`). Writing it has no effect.
7888
+ * - `off` — no band covers the camera (or it is disabled).
7889
+ * - `events` — every band records around triggers only.
7890
+ * - `continuous` — at least one band records continuously.
7891
+ * - `on-device-decision`— the DEVICE decides: recording runs for as long as the
7892
+ * camera raises its own `recording-signal` level (a robot that cleans). There
7893
+ * is no schedule to author, because there is no hour to program — see
7894
+ * {@link RecordingConfigSchema}`.deviceDecision`.
7895
+ *
7896
+ * NEVER authored: the recorder stamps it from the authoritative intent
7897
+ * (`bands` + `deviceDecision`) on every save (`activeModeForConfig`). Writing it
7898
+ * has no effect.
7899
+ *
7900
+ * `on-device-decision` is named for WHO decides, not for how the recording is
7901
+ * requested. `on-demand` was rejected: in this repo's vocabulary a "demand" is
7902
+ * something the operator makes (the live gate is the recorder's own "demand
7903
+ * window"), and a knob whose name suggests the operator starts it while the
7904
+ * device actually does is the D62 shape — a control nobody can predict.
7894
7905
  */
7895
7906
  var RecordingStorageModeSchema = _enum([
7896
7907
  "off",
7897
7908
  "events",
7898
- "continuous"
7909
+ "continuous",
7910
+ "on-device-decision"
7899
7911
  ]);
7900
7912
  /**
7901
7913
  * Le macro classi che possono aprire una finestra di registrazione — le stesse
@@ -7945,22 +7957,7 @@ var RecordingTriggersSchema = object({
7945
7957
  * il livello: un contatto trovato già aperto al riavvio del runner non fa
7946
7958
  * registrare.
7947
7959
  */
7948
- sensorDeviceIds: array(number().int().positive()).min(1).max(16).refine(noDuplicates, { message: "sensorDeviceIds must not repeat a device" }).optional(),
7949
- /**
7950
- * La camera registra per tutta la durata del SEGNALE che lei stessa
7951
- * pubblica — la cap `recording-signal` (`active: true` mentre il device è in
7952
- * funzione: un robot che pulisce). È un LIVELLO, non un fronte: la finestra
7953
- * resta aperta finché il segnale è alto e si chiude `postBufferSec` dopo la
7954
- * caduta, così una pulizia di quaranta minuti è UNA clip.
7955
- *
7956
- * Non nomina un device: il segnale è della camera stessa, tenuto fresco dal
7957
- * suo provider (D224); il recorder lo ascolta su `DeviceStateChanged` e lo
7958
- * riconcilia leggendo la slice via RPC, con un tetto oltre il quale un
7959
- * segnale mai abbassato (un evento perso) non può tenere aperta una
7960
- * registrazione (D11). Vedi `recorder/addon/band-decision.ts`
7961
- * (`holdTrigger` / `releaseTrigger`).
7962
- */
7963
- deviceSignal: boolean().optional()
7960
+ sensorDeviceIds: array(number().int().positive()).min(1).max(16).refine(noDuplicates, { message: "sensorDeviceIds must not repeat a device" }).optional()
7964
7961
  });
7965
7962
  /**
7966
7963
  * Mode of a single recording band — the recorder per-band vocabulary.
@@ -7990,13 +7987,28 @@ var RecordingBandSchema = object({
7990
7987
  end: string().regex(HHMM),
7991
7988
  mode: RecordingBandModeSchema,
7992
7989
  triggers: RecordingBandTriggersSchema.optional(),
7990
+ /**
7991
+ * RETIRED (D381). A band no longer carries a pre-buffer of its own.
7992
+ *
7993
+ * It was the retroactive KEEP bound — which already-written segments survive
7994
+ * a trigger — and it had to be at least as wide as the widest pre-roll the
7995
+ * broker could serve, or the gate would delete the seconds the ring had just
7996
+ * handed the writer. That "at least as wide as" is the tell: it was a second
7997
+ * expression of the broker's retention, in different units, in a different
7998
+ * addon, with an invariant the operator had to maintain by hand. The keep
7999
+ * bound is now derived from the one prebuffer ceiling and there is nothing
8000
+ * left to configure here.
8001
+ *
8002
+ * The key survives in the SHAPE so a config written before that record still
8003
+ * parses and can be migrated deliberately — `RecordingBandSchema` is not
8004
+ * strict, so simply deleting it would strip an operator's value in silence on
8005
+ * the next save (the failure D380 came one commit from shipping). Nothing
8006
+ * reads it: {@link stripRetiredBandPreBufferSec} removes it on load.
8007
+ */
7993
8008
  preBufferSec: number().min(0).optional(),
7994
8009
  postBufferSec: number().min(0).optional()
7995
8010
  });
7996
- ({
7997
- preBufferSec: 15,
7998
- postBufferSec: 30
7999
- }).postBufferSec * 1e3;
8011
+ ({ postBufferSec: 30 }).postBufferSec * 1e3;
8000
8012
  /**
8001
8013
  * Per-device retention overrides. Every field is optional; an unset or `0`
8002
8014
  * value inherits the node-wide recorder default. Only footage-lifetime limits
@@ -8044,8 +8056,29 @@ var RecordingConfigSchema = object({
8044
8056
  * "off" is the absence of a covering band, never a band value.
8045
8057
  */
8046
8058
  bands: array(RecordingBandSchema).default([]),
8059
+ /**
8060
+ * THE device-decided intent: record for as long as the camera itself raises
8061
+ * `recording-signal` (`active: true` while the device is in function — a
8062
+ * robot that cleans). AUTHORED, unlike `mode`, and the only authored
8063
+ * recording intent that is not a band.
8064
+ *
8065
+ * It carries NO schedule on purpose. A band is an HOUR, and this feature has
8066
+ * no hour to program: the device decides. What it costs the operator is one
8067
+ * flag — "this camera can record on its own" — and what it buys is the same
8068
+ * hold/release the recorder already implements (D371, `holdTrigger` /
8069
+ * `releaseTrigger`): the window opens on the rise, stays open for the whole
8070
+ * job however long it is, and closes one pad after the fall.
8071
+ *
8072
+ * EXCLUSIVE with `bands` (below): two authorities deciding when the same
8073
+ * camera records is the D62 failure. `off` remains `enabled: false`, so an
8074
+ * operator switching this camera off is REPORTED off, never as broken.
8075
+ */
8076
+ deviceDecision: boolean().optional(),
8047
8077
  retention: RecordingRetentionSchema.optional()
8048
- }).strict();
8078
+ }).strict().refine((config) => config.deviceDecision !== true || config.bands.length === 0, {
8079
+ message: "deviceDecision is a whole-config mode and carries no schedule: it cannot be combined with bands",
8080
+ path: ["bands"]
8081
+ });
8049
8082
  /**
8050
8083
  * Entity-relocation job state (storage entity-routing spec, Phase 4).
8051
8084
  *
@@ -21078,11 +21111,7 @@ var CameraAudioStatusSchema = object({
21078
21111
  });
21079
21112
  /** Recording block — null when no recording cap is active for this device. */
21080
21113
  var CameraRecordingStatusSchema = object({
21081
- mode: _enum([
21082
- "off",
21083
- "continuous",
21084
- "events"
21085
- ]),
21114
+ mode: RecordingStorageModeSchema,
21086
21115
  active: boolean(),
21087
21116
  storageBytes: number()
21088
21117
  });
@@ -29344,11 +29373,10 @@ DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch, method(object({ deviceI
29344
29373
  var RecordingStatusSchema = object({
29345
29374
  deviceId: number(),
29346
29375
  enabled: boolean(),
29347
- activeMode: _enum([
29348
- "off",
29349
- "continuous",
29350
- "events"
29351
- ]),
29376
+ /** THE derived storage mode, from the one definition
29377
+ * (`deriveRecordingMode`) — never a second enum. A duplicated list is how
29378
+ * `on-device-decision` could have reached the recorder and not the status. */
29379
+ activeMode: RecordingStorageModeSchema,
29352
29380
  nodeId: string(),
29353
29381
  storageBytes: number()
29354
29382
  });
package/dist/addon.mjs CHANGED
@@ -7886,17 +7886,29 @@ var HHMM = /^([01]\d|2[0-3]):[0-5]\d$/;
7886
7886
  /**
7887
7887
  * DERIVED per-camera storage summary — the single field cheap consumers read
7888
7888
  * (the viewer's status dot, the camera list) instead of walking `bands`:
7889
- * - `off` — no band covers the camera (or it is disabled).
7890
- * - `events` — every band records around triggers only.
7891
- * - `continuous` — at least one band records continuously.
7892
- *
7893
- * NEVER authored: the recorder stamps it from the authoritative `bands` on
7894
- * every save (`activeModeForConfig`). Writing it has no effect.
7889
+ * - `off` — no band covers the camera (or it is disabled).
7890
+ * - `events` — every band records around triggers only.
7891
+ * - `continuous` — at least one band records continuously.
7892
+ * - `on-device-decision`— the DEVICE decides: recording runs for as long as the
7893
+ * camera raises its own `recording-signal` level (a robot that cleans). There
7894
+ * is no schedule to author, because there is no hour to program — see
7895
+ * {@link RecordingConfigSchema}`.deviceDecision`.
7896
+ *
7897
+ * NEVER authored: the recorder stamps it from the authoritative intent
7898
+ * (`bands` + `deviceDecision`) on every save (`activeModeForConfig`). Writing it
7899
+ * has no effect.
7900
+ *
7901
+ * `on-device-decision` is named for WHO decides, not for how the recording is
7902
+ * requested. `on-demand` was rejected: in this repo's vocabulary a "demand" is
7903
+ * something the operator makes (the live gate is the recorder's own "demand
7904
+ * window"), and a knob whose name suggests the operator starts it while the
7905
+ * device actually does is the D62 shape — a control nobody can predict.
7895
7906
  */
7896
7907
  var RecordingStorageModeSchema = _enum([
7897
7908
  "off",
7898
7909
  "events",
7899
- "continuous"
7910
+ "continuous",
7911
+ "on-device-decision"
7900
7912
  ]);
7901
7913
  /**
7902
7914
  * Le macro classi che possono aprire una finestra di registrazione — le stesse
@@ -7946,22 +7958,7 @@ var RecordingTriggersSchema = object({
7946
7958
  * il livello: un contatto trovato già aperto al riavvio del runner non fa
7947
7959
  * registrare.
7948
7960
  */
7949
- sensorDeviceIds: array(number().int().positive()).min(1).max(16).refine(noDuplicates, { message: "sensorDeviceIds must not repeat a device" }).optional(),
7950
- /**
7951
- * La camera registra per tutta la durata del SEGNALE che lei stessa
7952
- * pubblica — la cap `recording-signal` (`active: true` mentre il device è in
7953
- * funzione: un robot che pulisce). È un LIVELLO, non un fronte: la finestra
7954
- * resta aperta finché il segnale è alto e si chiude `postBufferSec` dopo la
7955
- * caduta, così una pulizia di quaranta minuti è UNA clip.
7956
- *
7957
- * Non nomina un device: il segnale è della camera stessa, tenuto fresco dal
7958
- * suo provider (D224); il recorder lo ascolta su `DeviceStateChanged` e lo
7959
- * riconcilia leggendo la slice via RPC, con un tetto oltre il quale un
7960
- * segnale mai abbassato (un evento perso) non può tenere aperta una
7961
- * registrazione (D11). Vedi `recorder/addon/band-decision.ts`
7962
- * (`holdTrigger` / `releaseTrigger`).
7963
- */
7964
- deviceSignal: boolean().optional()
7961
+ sensorDeviceIds: array(number().int().positive()).min(1).max(16).refine(noDuplicates, { message: "sensorDeviceIds must not repeat a device" }).optional()
7965
7962
  });
7966
7963
  /**
7967
7964
  * Mode of a single recording band — the recorder per-band vocabulary.
@@ -7991,13 +7988,28 @@ var RecordingBandSchema = object({
7991
7988
  end: string().regex(HHMM),
7992
7989
  mode: RecordingBandModeSchema,
7993
7990
  triggers: RecordingBandTriggersSchema.optional(),
7991
+ /**
7992
+ * RETIRED (D381). A band no longer carries a pre-buffer of its own.
7993
+ *
7994
+ * It was the retroactive KEEP bound — which already-written segments survive
7995
+ * a trigger — and it had to be at least as wide as the widest pre-roll the
7996
+ * broker could serve, or the gate would delete the seconds the ring had just
7997
+ * handed the writer. That "at least as wide as" is the tell: it was a second
7998
+ * expression of the broker's retention, in different units, in a different
7999
+ * addon, with an invariant the operator had to maintain by hand. The keep
8000
+ * bound is now derived from the one prebuffer ceiling and there is nothing
8001
+ * left to configure here.
8002
+ *
8003
+ * The key survives in the SHAPE so a config written before that record still
8004
+ * parses and can be migrated deliberately — `RecordingBandSchema` is not
8005
+ * strict, so simply deleting it would strip an operator's value in silence on
8006
+ * the next save (the failure D380 came one commit from shipping). Nothing
8007
+ * reads it: {@link stripRetiredBandPreBufferSec} removes it on load.
8008
+ */
7994
8009
  preBufferSec: number().min(0).optional(),
7995
8010
  postBufferSec: number().min(0).optional()
7996
8011
  });
7997
- ({
7998
- preBufferSec: 15,
7999
- postBufferSec: 30
8000
- }).postBufferSec * 1e3;
8012
+ ({ postBufferSec: 30 }).postBufferSec * 1e3;
8001
8013
  /**
8002
8014
  * Per-device retention overrides. Every field is optional; an unset or `0`
8003
8015
  * value inherits the node-wide recorder default. Only footage-lifetime limits
@@ -8045,8 +8057,29 @@ var RecordingConfigSchema = object({
8045
8057
  * "off" is the absence of a covering band, never a band value.
8046
8058
  */
8047
8059
  bands: array(RecordingBandSchema).default([]),
8060
+ /**
8061
+ * THE device-decided intent: record for as long as the camera itself raises
8062
+ * `recording-signal` (`active: true` while the device is in function — a
8063
+ * robot that cleans). AUTHORED, unlike `mode`, and the only authored
8064
+ * recording intent that is not a band.
8065
+ *
8066
+ * It carries NO schedule on purpose. A band is an HOUR, and this feature has
8067
+ * no hour to program: the device decides. What it costs the operator is one
8068
+ * flag — "this camera can record on its own" — and what it buys is the same
8069
+ * hold/release the recorder already implements (D371, `holdTrigger` /
8070
+ * `releaseTrigger`): the window opens on the rise, stays open for the whole
8071
+ * job however long it is, and closes one pad after the fall.
8072
+ *
8073
+ * EXCLUSIVE with `bands` (below): two authorities deciding when the same
8074
+ * camera records is the D62 failure. `off` remains `enabled: false`, so an
8075
+ * operator switching this camera off is REPORTED off, never as broken.
8076
+ */
8077
+ deviceDecision: boolean().optional(),
8048
8078
  retention: RecordingRetentionSchema.optional()
8049
- }).strict();
8079
+ }).strict().refine((config) => config.deviceDecision !== true || config.bands.length === 0, {
8080
+ message: "deviceDecision is a whole-config mode and carries no schedule: it cannot be combined with bands",
8081
+ path: ["bands"]
8082
+ });
8050
8083
  /**
8051
8084
  * Entity-relocation job state (storage entity-routing spec, Phase 4).
8052
8085
  *
@@ -21079,11 +21112,7 @@ var CameraAudioStatusSchema = object({
21079
21112
  });
21080
21113
  /** Recording block — null when no recording cap is active for this device. */
21081
21114
  var CameraRecordingStatusSchema = object({
21082
- mode: _enum([
21083
- "off",
21084
- "continuous",
21085
- "events"
21086
- ]),
21115
+ mode: RecordingStorageModeSchema,
21087
21116
  active: boolean(),
21088
21117
  storageBytes: number()
21089
21118
  });
@@ -29345,11 +29374,10 @@ DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch, method(object({ deviceI
29345
29374
  var RecordingStatusSchema = object({
29346
29375
  deviceId: number(),
29347
29376
  enabled: boolean(),
29348
- activeMode: _enum([
29349
- "off",
29350
- "continuous",
29351
- "events"
29352
- ]),
29377
+ /** THE derived storage mode, from the one definition
29378
+ * (`deriveRecordingMode`) — never a second enum. A duplicated list is how
29379
+ * `on-device-decision` could have reached the recorder and not the status. */
29380
+ activeMode: RecordingStorageModeSchema,
29353
29381
  nodeId: string(),
29354
29382
  storageBytes: number()
29355
29383
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-dreo",
3
- "version": "0.2.75",
3
+ "version": "0.2.77",
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",