@camstack/addon-provider-velux 0.2.71 → 0.2.73

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
@@ -5406,6 +5406,12 @@ Object.fromEntries([
5406
5406
  icon: "move",
5407
5407
  order: 40
5408
5408
  },
5409
+ {
5410
+ id: "navigation",
5411
+ label: "Navigation",
5412
+ icon: "compass",
5413
+ order: 41
5414
+ },
5409
5415
  {
5410
5416
  id: "consumables",
5411
5417
  label: "Consumables",
@@ -6439,6 +6445,21 @@ var CameraStreamSchema = object({
6439
6445
  */
6440
6446
  autoEligible: boolean().optional(),
6441
6447
  /**
6448
+ * The profile slot the PUBLISHER says this stream is: `low` for a stream
6449
+ * whose only sensible role is the low-bandwidth one, `high` for a main
6450
+ * stream. Consulted by the broker's automatic ranking
6451
+ * (`rankInitialAssignment`) BEFORE the pixel-count heuristic, and only there:
6452
+ * an operator's manual assignment still wins, and an absent hint is the
6453
+ * pixel-ranked default every camera had before this field existed.
6454
+ *
6455
+ * Why it exists: a camera with ONE stream ranked to `mid` — the slot no
6456
+ * storage class is written for on its own (`recordings` is high|mid,
6457
+ * `recordingsLow` is low) and the one profile scrub does not read. The robot
6458
+ * camera's single 720p relay is a `low` in every respect except the slot the
6459
+ * heuristic put it in.
6460
+ */
6461
+ profileHint: CamProfileSchema.optional(),
6462
+ /**
6442
6463
  * Transport-specific opaque metadata. The broker passes it through to
6443
6464
  * the source reader without inspecting it. Currently used by
6444
6465
  * `pull-rfc4571` streams to carry the upstream SDP (so the reader can
@@ -7888,7 +7909,22 @@ var RecordingTriggersSchema = object({
7888
7909
  * il livello: un contatto trovato già aperto al riavvio del runner non fa
7889
7910
  * registrare.
7890
7911
  */
7891
- sensorDeviceIds: array(number().int().positive()).min(1).max(16).refine(noDuplicates, { message: "sensorDeviceIds must not repeat a device" }).optional()
7912
+ sensorDeviceIds: array(number().int().positive()).min(1).max(16).refine(noDuplicates, { message: "sensorDeviceIds must not repeat a device" }).optional(),
7913
+ /**
7914
+ * La camera registra per tutta la durata del SEGNALE che lei stessa
7915
+ * pubblica — la cap `recording-signal` (`active: true` mentre il device è in
7916
+ * funzione: un robot che pulisce). È un LIVELLO, non un fronte: la finestra
7917
+ * resta aperta finché il segnale è alto e si chiude `postBufferSec` dopo la
7918
+ * caduta, così una pulizia di quaranta minuti è UNA clip.
7919
+ *
7920
+ * Non nomina un device: il segnale è della camera stessa, tenuto fresco dal
7921
+ * suo provider (D224); il recorder lo ascolta su `DeviceStateChanged` e lo
7922
+ * riconcilia leggendo la slice via RPC, con un tetto oltre il quale un
7923
+ * segnale mai abbassato (un evento perso) non può tenere aperta una
7924
+ * registrazione (D11). Vedi `recorder/addon/band-decision.ts`
7925
+ * (`holdTrigger` / `releaseTrigger`).
7926
+ */
7927
+ deviceSignal: boolean().optional()
7892
7928
  });
7893
7929
  /**
7894
7930
  * Mode of a single recording band — the recorder per-band vocabulary.
@@ -11352,6 +11388,8 @@ method(object({
11352
11388
  label: string().optional(),
11353
11389
  deviceFeatures: array(string()).optional(),
11354
11390
  autoEligible: boolean().optional(),
11391
+ /** The slot the publisher says this stream IS — see `CameraStreamSchema.profileHint`. */
11392
+ profileHint: CamProfileSchema.optional(),
11355
11393
  metadata: record(string(), unknown()).optional(),
11356
11394
  /** Required when kind === 'derived' — the source camStreamId the
11357
11395
  * derived broker reads its encoded plane from.
@@ -29877,6 +29915,77 @@ method(object({
29877
29915
  auth: "protected"
29878
29916
  });
29879
29917
  /**
29918
+ * A camera's own "record me NOW" LEVEL — a signal the device raises while
29919
+ * something it knows about is happening (a robot vacuum cleaning, a machine
29920
+ * running, a gate open) and lowers when it stops.
29921
+ *
29922
+ * It is a level, not an edge. The sensor triggers the recorder already listens
29923
+ * to (`SOURCE_CAP_ACTIVE_FIELD`) fire on a rising edge and record for a fixed
29924
+ * post-buffer; a cleaning lasts forty minutes, and forty minutes of "this is
29925
+ * still happening" cannot be expressed as an edge plus a post-buffer without
29926
+ * either re-triggering on a timer (polling — D224 forbids the consumer keeping
29927
+ * the fact fresh) or picking a post-buffer long enough to cover every job,
29928
+ * which records the dock for that long after every short one. So the recorder
29929
+ * reads the LEVEL: it records for as long as `active` is true, plus the band's
29930
+ * own post-buffer once it falls.
29931
+ *
29932
+ * Who owns the fact: the PROVIDER of the device, which already reads the state
29933
+ * the signal is derived from (the vacuum's lifecycle state, for Dreame). It
29934
+ * writes this slice on every change; consumers subscribe to the kernel's
29935
+ * `DeviceStateChanged` for it and read it back through
29936
+ * `deviceState.getCapSlice` to reconcile — never a second copy, never a poll
29937
+ * against the device (D224, D8/D11).
29938
+ *
29939
+ * Deliberately NOT a `binary` sensor on the camera: a binary sensor is exported
29940
+ * to Home Assistant, HomeKit and the sensor picker as a thing an operator can
29941
+ * bind, and "the camera wants to record" is not a room sensor. It is a fact
29942
+ * about the camera, on the camera.
29943
+ */
29944
+ var RecordingSignalStatusSchema = object({
29945
+ /** True while the device asks to be recorded. */
29946
+ active: boolean(),
29947
+ /**
29948
+ * Why, in the provider's own vocabulary (a vacuum's `cleaning` / `docked`,
29949
+ * …). Free text for the log line and the UI badge; the recorder never
29950
+ * branches on it.
29951
+ */
29952
+ reason: string(),
29953
+ /** Ms epoch of the last `active` transition. 0 if never observed. */
29954
+ lastChangedAt: number()
29955
+ });
29956
+ /** The runtime-state slice: the status plus the clock every slice carries. */
29957
+ var RecordingSignalRuntimeStateSchema = RecordingSignalStatusSchema.extend({ lastFetchedAt: number() });
29958
+ var recordingSignalCapability = {
29959
+ name: "recording-signal",
29960
+ scope: "device",
29961
+ deviceNative: true,
29962
+ mode: "singleton",
29963
+ deviceTypes: [DeviceType.Camera],
29964
+ methods: {
29965
+ /** The current level, straight from the slice the provider keeps fresh. */
29966
+ getStatus: method(object({ deviceId: number() }), RecordingSignalStatusSchema) },
29967
+ status: {
29968
+ schema: RecordingSignalStatusSchema,
29969
+ kind: "push",
29970
+ empty: {
29971
+ active: false,
29972
+ reason: "unknown",
29973
+ lastChangedAt: 0
29974
+ }
29975
+ },
29976
+ runtimeState: RecordingSignalRuntimeStateSchema,
29977
+ /**
29978
+ * Runtime-state durability: **session** — a restored `active: true` from
29979
+ * before a restart is exactly the stale level the recorder's reconcile bound
29980
+ * exists to end, and the provider re-derives the true level on activation
29981
+ * anyway. Nothing is lost by forgetting it; a lie is avoided.
29982
+ *
29983
+ * See `RuntimeStateDurability`. Enforced by
29984
+ * `scripts/check-runtime-state-durability.ts`.
29985
+ */
29986
+ durability: "session"
29987
+ };
29988
+ /**
29880
29989
  * scene-monitor — device-scoped reference-region state cap. An operator marks
29881
29990
  * a rect ROI on a camera frame and names one or more states; the engine
29882
29991
  * (pipeline-analytics, designated post-processing node) reports which state is
@@ -30374,6 +30483,8 @@ var CamStreamDescriptorSchema = object({
30374
30483
  deviceFeatures: array(string()).optional(),
30375
30484
  /** Eligible for automatic profile assignment. Absent = `true`. */
30376
30485
  autoEligible: boolean().optional(),
30486
+ /** The slot the publisher says this stream IS — see `CameraStreamSchema.profileHint`. */
30487
+ profileHint: CamProfileSchema.optional(),
30377
30488
  /** Transport-specific opaque metadata (e.g. rfc4571 SDP). */
30378
30489
  metadata: record(string(), unknown()).optional()
30379
30490
  });
@@ -32513,6 +32624,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
32513
32624
  pressureSensor: pressureSensorCapability,
32514
32625
  privacyMask: privacyMaskCapability,
32515
32626
  ptzAutotrack: ptzAutotrackCapability,
32627
+ recordingSignal: recordingSignalCapability,
32516
32628
  sceneMonitor: sceneMonitorCapability,
32517
32629
  scriptRunner: scriptRunnerCapability,
32518
32630
  smoke: smokeCapability,
@@ -38260,6 +38372,12 @@ Object.freeze({
38260
38372
  addonId: null,
38261
38373
  access: "view"
38262
38374
  },
38375
+ "recordingSignal.getStatus": {
38376
+ capName: "recording-signal",
38377
+ capScope: "device",
38378
+ addonId: null,
38379
+ access: "view"
38380
+ },
38263
38381
  "sceneMonitor.captureReference": {
38264
38382
  capName: "scene-monitor",
38265
38383
  capScope: "device",
@@ -41252,6 +41370,11 @@ Object.freeze({
41252
41370
  form: "single",
41253
41371
  optional: true
41254
41372
  }],
41373
+ "recordingSignal.getStatus": [{
41374
+ name: "deviceId",
41375
+ form: "single",
41376
+ optional: false
41377
+ }],
41255
41378
  "sceneMonitor.captureReference": [{
41256
41379
  name: "deviceId",
41257
41380
  form: "single",
package/dist/addon.mjs CHANGED
@@ -5405,6 +5405,12 @@ Object.fromEntries([
5405
5405
  icon: "move",
5406
5406
  order: 40
5407
5407
  },
5408
+ {
5409
+ id: "navigation",
5410
+ label: "Navigation",
5411
+ icon: "compass",
5412
+ order: 41
5413
+ },
5408
5414
  {
5409
5415
  id: "consumables",
5410
5416
  label: "Consumables",
@@ -6438,6 +6444,21 @@ var CameraStreamSchema = object({
6438
6444
  */
6439
6445
  autoEligible: boolean().optional(),
6440
6446
  /**
6447
+ * The profile slot the PUBLISHER says this stream is: `low` for a stream
6448
+ * whose only sensible role is the low-bandwidth one, `high` for a main
6449
+ * stream. Consulted by the broker's automatic ranking
6450
+ * (`rankInitialAssignment`) BEFORE the pixel-count heuristic, and only there:
6451
+ * an operator's manual assignment still wins, and an absent hint is the
6452
+ * pixel-ranked default every camera had before this field existed.
6453
+ *
6454
+ * Why it exists: a camera with ONE stream ranked to `mid` — the slot no
6455
+ * storage class is written for on its own (`recordings` is high|mid,
6456
+ * `recordingsLow` is low) and the one profile scrub does not read. The robot
6457
+ * camera's single 720p relay is a `low` in every respect except the slot the
6458
+ * heuristic put it in.
6459
+ */
6460
+ profileHint: CamProfileSchema.optional(),
6461
+ /**
6441
6462
  * Transport-specific opaque metadata. The broker passes it through to
6442
6463
  * the source reader without inspecting it. Currently used by
6443
6464
  * `pull-rfc4571` streams to carry the upstream SDP (so the reader can
@@ -7887,7 +7908,22 @@ var RecordingTriggersSchema = object({
7887
7908
  * il livello: un contatto trovato già aperto al riavvio del runner non fa
7888
7909
  * registrare.
7889
7910
  */
7890
- sensorDeviceIds: array(number().int().positive()).min(1).max(16).refine(noDuplicates, { message: "sensorDeviceIds must not repeat a device" }).optional()
7911
+ sensorDeviceIds: array(number().int().positive()).min(1).max(16).refine(noDuplicates, { message: "sensorDeviceIds must not repeat a device" }).optional(),
7912
+ /**
7913
+ * La camera registra per tutta la durata del SEGNALE che lei stessa
7914
+ * pubblica — la cap `recording-signal` (`active: true` mentre il device è in
7915
+ * funzione: un robot che pulisce). È un LIVELLO, non un fronte: la finestra
7916
+ * resta aperta finché il segnale è alto e si chiude `postBufferSec` dopo la
7917
+ * caduta, così una pulizia di quaranta minuti è UNA clip.
7918
+ *
7919
+ * Non nomina un device: il segnale è della camera stessa, tenuto fresco dal
7920
+ * suo provider (D224); il recorder lo ascolta su `DeviceStateChanged` e lo
7921
+ * riconcilia leggendo la slice via RPC, con un tetto oltre il quale un
7922
+ * segnale mai abbassato (un evento perso) non può tenere aperta una
7923
+ * registrazione (D11). Vedi `recorder/addon/band-decision.ts`
7924
+ * (`holdTrigger` / `releaseTrigger`).
7925
+ */
7926
+ deviceSignal: boolean().optional()
7891
7927
  });
7892
7928
  /**
7893
7929
  * Mode of a single recording band — the recorder per-band vocabulary.
@@ -11351,6 +11387,8 @@ method(object({
11351
11387
  label: string().optional(),
11352
11388
  deviceFeatures: array(string()).optional(),
11353
11389
  autoEligible: boolean().optional(),
11390
+ /** The slot the publisher says this stream IS — see `CameraStreamSchema.profileHint`. */
11391
+ profileHint: CamProfileSchema.optional(),
11354
11392
  metadata: record(string(), unknown()).optional(),
11355
11393
  /** Required when kind === 'derived' — the source camStreamId the
11356
11394
  * derived broker reads its encoded plane from.
@@ -29876,6 +29914,77 @@ method(object({
29876
29914
  auth: "protected"
29877
29915
  });
29878
29916
  /**
29917
+ * A camera's own "record me NOW" LEVEL — a signal the device raises while
29918
+ * something it knows about is happening (a robot vacuum cleaning, a machine
29919
+ * running, a gate open) and lowers when it stops.
29920
+ *
29921
+ * It is a level, not an edge. The sensor triggers the recorder already listens
29922
+ * to (`SOURCE_CAP_ACTIVE_FIELD`) fire on a rising edge and record for a fixed
29923
+ * post-buffer; a cleaning lasts forty minutes, and forty minutes of "this is
29924
+ * still happening" cannot be expressed as an edge plus a post-buffer without
29925
+ * either re-triggering on a timer (polling — D224 forbids the consumer keeping
29926
+ * the fact fresh) or picking a post-buffer long enough to cover every job,
29927
+ * which records the dock for that long after every short one. So the recorder
29928
+ * reads the LEVEL: it records for as long as `active` is true, plus the band's
29929
+ * own post-buffer once it falls.
29930
+ *
29931
+ * Who owns the fact: the PROVIDER of the device, which already reads the state
29932
+ * the signal is derived from (the vacuum's lifecycle state, for Dreame). It
29933
+ * writes this slice on every change; consumers subscribe to the kernel's
29934
+ * `DeviceStateChanged` for it and read it back through
29935
+ * `deviceState.getCapSlice` to reconcile — never a second copy, never a poll
29936
+ * against the device (D224, D8/D11).
29937
+ *
29938
+ * Deliberately NOT a `binary` sensor on the camera: a binary sensor is exported
29939
+ * to Home Assistant, HomeKit and the sensor picker as a thing an operator can
29940
+ * bind, and "the camera wants to record" is not a room sensor. It is a fact
29941
+ * about the camera, on the camera.
29942
+ */
29943
+ var RecordingSignalStatusSchema = object({
29944
+ /** True while the device asks to be recorded. */
29945
+ active: boolean(),
29946
+ /**
29947
+ * Why, in the provider's own vocabulary (a vacuum's `cleaning` / `docked`,
29948
+ * …). Free text for the log line and the UI badge; the recorder never
29949
+ * branches on it.
29950
+ */
29951
+ reason: string(),
29952
+ /** Ms epoch of the last `active` transition. 0 if never observed. */
29953
+ lastChangedAt: number()
29954
+ });
29955
+ /** The runtime-state slice: the status plus the clock every slice carries. */
29956
+ var RecordingSignalRuntimeStateSchema = RecordingSignalStatusSchema.extend({ lastFetchedAt: number() });
29957
+ var recordingSignalCapability = {
29958
+ name: "recording-signal",
29959
+ scope: "device",
29960
+ deviceNative: true,
29961
+ mode: "singleton",
29962
+ deviceTypes: [DeviceType.Camera],
29963
+ methods: {
29964
+ /** The current level, straight from the slice the provider keeps fresh. */
29965
+ getStatus: method(object({ deviceId: number() }), RecordingSignalStatusSchema) },
29966
+ status: {
29967
+ schema: RecordingSignalStatusSchema,
29968
+ kind: "push",
29969
+ empty: {
29970
+ active: false,
29971
+ reason: "unknown",
29972
+ lastChangedAt: 0
29973
+ }
29974
+ },
29975
+ runtimeState: RecordingSignalRuntimeStateSchema,
29976
+ /**
29977
+ * Runtime-state durability: **session** — a restored `active: true` from
29978
+ * before a restart is exactly the stale level the recorder's reconcile bound
29979
+ * exists to end, and the provider re-derives the true level on activation
29980
+ * anyway. Nothing is lost by forgetting it; a lie is avoided.
29981
+ *
29982
+ * See `RuntimeStateDurability`. Enforced by
29983
+ * `scripts/check-runtime-state-durability.ts`.
29984
+ */
29985
+ durability: "session"
29986
+ };
29987
+ /**
29879
29988
  * scene-monitor — device-scoped reference-region state cap. An operator marks
29880
29989
  * a rect ROI on a camera frame and names one or more states; the engine
29881
29990
  * (pipeline-analytics, designated post-processing node) reports which state is
@@ -30373,6 +30482,8 @@ var CamStreamDescriptorSchema = object({
30373
30482
  deviceFeatures: array(string()).optional(),
30374
30483
  /** Eligible for automatic profile assignment. Absent = `true`. */
30375
30484
  autoEligible: boolean().optional(),
30485
+ /** The slot the publisher says this stream IS — see `CameraStreamSchema.profileHint`. */
30486
+ profileHint: CamProfileSchema.optional(),
30376
30487
  /** Transport-specific opaque metadata (e.g. rfc4571 SDP). */
30377
30488
  metadata: record(string(), unknown()).optional()
30378
30489
  });
@@ -32512,6 +32623,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
32512
32623
  pressureSensor: pressureSensorCapability,
32513
32624
  privacyMask: privacyMaskCapability,
32514
32625
  ptzAutotrack: ptzAutotrackCapability,
32626
+ recordingSignal: recordingSignalCapability,
32515
32627
  sceneMonitor: sceneMonitorCapability,
32516
32628
  scriptRunner: scriptRunnerCapability,
32517
32629
  smoke: smokeCapability,
@@ -38259,6 +38371,12 @@ Object.freeze({
38259
38371
  addonId: null,
38260
38372
  access: "view"
38261
38373
  },
38374
+ "recordingSignal.getStatus": {
38375
+ capName: "recording-signal",
38376
+ capScope: "device",
38377
+ addonId: null,
38378
+ access: "view"
38379
+ },
38262
38380
  "sceneMonitor.captureReference": {
38263
38381
  capName: "scene-monitor",
38264
38382
  capScope: "device",
@@ -41251,6 +41369,11 @@ Object.freeze({
41251
41369
  form: "single",
41252
41370
  optional: true
41253
41371
  }],
41372
+ "recordingSignal.getStatus": [{
41373
+ name: "deviceId",
41374
+ form: "single",
41375
+ optional: false
41376
+ }],
41254
41377
  "sceneMonitor.captureReference": [{
41255
41378
  name: "deviceId",
41256
41379
  form: "single",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-velux",
3
- "version": "0.2.71",
3
+ "version": "0.2.73",
4
4
  "description": "Velux KLF-200 device-provider addon for CamStack — local-gateway window + shutter covers (positional, no tilt)",
5
5
  "keywords": [
6
6
  "camstack",