@camstack/addon-provider-homeassistant 1.2.151 → 1.2.153

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.
@@ -7480,7 +7480,7 @@ function errMsg(err) {
7480
7480
  return String(err);
7481
7481
  }
7482
7482
  //#endregion
7483
- //#region ../types/dist/composition-43aqsZQj.mjs
7483
+ //#region ../types/dist/composition-Bzr7GwgP.mjs
7484
7484
  /**
7485
7485
  * The ffmpeg build every CamStack node downloads, per platform and arch.
7486
7486
  *
@@ -7534,20 +7534,20 @@ function portable(target) {
7534
7534
  }
7535
7535
  portable("linux64"), portable("linuxarm64"), portable("macarm64"), portable("mac64");
7536
7536
  /**
7537
- * LA tabella "quale booleano di questo tipo di device conta come ALTO", e il
7538
- * valutatore puro del suo FRONTE.
7537
+ * THE table "which boolean of this device type counts as HIGH", and the
7538
+ * pure evaluator of its EDGE.
7539
7539
  *
7540
- * UNA tabella per tutti quelli che chiedono "questo device è ALTO?": il
7541
- * trigger `RecordingTriggers.sensorDeviceIds` del recorder, i marker dei
7542
- * sensori della post-analysis, il bridge camera-sensors dell'orchestratore e
7543
- * le sorgenti di un campanello composto (`doorbellFeatureSources`, D671).
7544
- * Una seconda copia divergerebbe alla prima cap aggiunta, e il sintomo — "il
7545
- * sensore fa suonare il campanello ma non registra" — è esattamente D62.
7540
+ * ONE table for everyone who asks "is this device HIGH?": the
7541
+ * recorder's `RecordingTriggers.sensorDeviceIds` trigger, the post-analysis
7542
+ * sensor markers, the orchestrator's camera-sensors bridge and
7543
+ * the sources of a composite doorbell (`doorbellFeatureSources`, D671).
7544
+ * A second copy would diverge at the first cap added, and the symptom — "the
7545
+ * sensor rings the doorbell but does not record" — is exactly D62.
7546
7546
  *
7547
- * ⚠ NON è `DEVICE_STATE_READERS` (`catalogs/device-state-vocabulary.ts`), e le
7548
- * due non vanno unificate: quella risponde a "qual è la PAROLA di stato per una
7549
- * regola" (e include `presence`, `cover`, `alarm-panel`), questa a "qual è il
7550
- * booleano il cui FRONTE conta". Vocabolari deliberatamente diversi.
7547
+ * ⚠ NOT `DEVICE_STATE_READERS` (`catalogs/device-state-vocabulary.ts`), and the
7548
+ * two must not be unified: that one answers "what is the state WORD for a
7549
+ * rule" (and includes `presence`, `cover`, `alarm-panel`), this one "which
7550
+ * boolean's EDGE counts". Deliberately different vocabularies.
7551
7551
  */
7552
7552
  /**
7553
7553
  * Known binary / switch source caps → the boolean slice field whose
@@ -7568,6 +7568,8 @@ var SOURCE_CAP_ACTIVE_FIELD = {
7568
7568
  vibration: "detected",
7569
7569
  tamper: "tampered"
7570
7570
  };
7571
+ /** Cap names whose presence in a device's bindings qualify it as a source. */
7572
+ var SOURCE_CAPS = Object.keys(SOURCE_CAP_ACTIVE_FIELD);
7571
7573
  /**
7572
7574
  * Error types for the safe expression engine. Two distinct classes so callers
7573
7575
  * can tell a compile-time (grammar) failure from a runtime (evaluation)
@@ -9298,22 +9300,22 @@ var CLASS_MAP_MACRO_TARGETS = [
9298
9300
  "package"
9299
9301
  ];
9300
9302
  /**
9301
- * Le macro classi di PRIMO LIVELLO: quelle che un object detector emette e che
9302
- * un operatore può selezionare.
9303
+ * The FIRST-LEVEL macro classes: those an object detector emits and that
9304
+ * an operator can select.
9303
9305
  *
9304
- * Sono le tre offerte dallo step `object-detection`
9306
+ * They are the three offered by the `object-detection` step
9305
9307
  * (`addon-pipeline/src/detection-pipeline/registry/step-definitions.ts`,
9306
- * `enabledMacroClasses`). `package` sta in {@link CLASS_MAP_MACRO_TARGETS} e in
9307
- * `MACRO_LABELS` — è una macro vera — ma NON qui: appartiene allo step
9308
- * `package-detection`, la cui abilitazione è guidata dalle zone, e offrire la
9309
- * stessa parola due volte ha già fatto accendere a un operatore il proxy COCO
9308
+ * `enabledMacroClasses`). `package` is in {@link CLASS_MAP_MACRO_TARGETS} and in
9309
+ * `MACRO_LABELS` — it is a true macro — but NOT here: it belongs to the step
9310
+ * `package-detection`, whose enablement is driven by zones, and offering the
9311
+ * same word twice has already made an operator turn on the COCO proxy
9310
9312
  * (suitcase/backpack/handbag) lasciando spento il detector dedicato.
9311
9313
  *
9312
- * UNA lista. Prima di oggi le stesse tre erano scritte a mano nell'offerta
9313
- * dello step e una seconda volta come union `FirstLevelMacro`
9314
- * (`types/detection.ts`); una terza copia per il trigger di registrazione
9315
- * (`RecordingTriggers.objectClasses`) avrebbe reso invisibile la divergenza
9316
- * successiva.
9314
+ * ONE list. Before today the same three were hand-written in the step's offer
9315
+ * and a second time as the union `FirstLevelMacro`
9316
+ * (`types/detection.ts`); a third copy for the recording trigger
9317
+ * (`RecordingTriggers.objectClasses`) would have made the later divergence
9318
+ * invisible.
9317
9319
  */
9318
9320
  var FIRST_LEVEL_MACRO_CLASSES = [
9319
9321
  "person",
@@ -9378,17 +9380,17 @@ var RecordingStorageModeSchema = _enum([
9378
9380
  "on-device-decision"
9379
9381
  ]);
9380
9382
  /**
9381
- * Le macro classi che possono aprire una finestra di registrazione — le stesse
9382
- * tre offerte dallo step `object-detection`, da UNA lista
9383
+ * The macro classes that can open a recording window — the same
9384
+ * three offered by the `object-detection` step, from ONE list
9383
9385
  * ({@link FIRST_LEVEL_MACRO_CLASSES}).
9384
9386
  */
9385
9387
  var RecordingObjectTriggerClassSchema = _enum(FIRST_LEVEL_MACRO_CLASSES);
9386
9388
  /**
9387
- * True quando `values` non ripete un elemento.
9389
+ * True when `values` does not repeat an element.
9388
9390
  *
9389
- * Un duplicato non è innocuo: ogni voce di `objectClasses` / `sensorDeviceIds`
9390
- * diventa una SORGENTE in `bandTriggerSources`, e la stessa sorgente due volte
9391
- * conterebbe due volte le sue finestre in `segmentMissedByMs`.
9391
+ * A duplicate is not harmless: every entry of `objectClasses` / `sensorDeviceIds`
9392
+ * becomes a SOURCE in `bandTriggerSources`, and the same source twice
9393
+ * would count its windows twice in `segmentMissedByMs`.
9392
9394
  */
9393
9395
  var noDuplicates = (values) => new Set(values).size === values.length;
9394
9396
  /** Which detectors trigger an `events`-mode band. */
@@ -9396,34 +9398,34 @@ var RecordingTriggersSchema = object({
9396
9398
  motion: boolean().optional(),
9397
9399
  audioThresholdDbfs: number().optional(),
9398
9400
  /**
9399
- * Le macro classi la cui detection apre una finestra. ASSENTE = la sorgente
9400
- * non è ascoltata; un array VUOTO è rifiutato, perché "banda events, trigger
9401
- * object acceso, nessuna classe" è la stessa forma "abilitata e non registra
9402
- * nulla, per sempre" contro cui è scritto `eventsBandCanEverDemand`.
9401
+ * The macro classes whose detection opens a window. ABSENT = the source
9402
+ * is not listened to; an EMPTY array is rejected, because "events band, object
9403
+ * trigger on, no class" is the same shape "enabled and records
9404
+ * nothing, forever" that `eventsBandCanEverDemand` is written against.
9403
9405
  *
9404
- * Il segnale letto è GIÀ FILTRATO: solo detection `source: 'pipeline'`, cioè
9405
- * quelle che hanno attraversato `enabledMacroClasses`, i
9406
- * `minConfidence<Macro>` e il full-frame guard. L'AI a bordo camera
9407
- * (`source: 'onboard'`) non attraversa nessuno di quei gate e NON apre
9408
- * finestre — vedi `recorder/object-trigger.ts`.
9406
+ * The signal read is ALREADY FILTERED: only `source: 'pipeline'` detections, i.e.
9407
+ * those that went through `enabledMacroClasses`, the
9408
+ * `minConfidence<Macro>` and the full-frame guard. The camera's onboard AI
9409
+ * (`source: 'onboard'`) goes through none of those gates and does NOT open
9410
+ * windows — see `recorder/object-trigger.ts`.
9409
9411
  */
9410
9412
  objectClasses: array(RecordingObjectTriggerClassSchema).min(1).refine(noDuplicates, { message: "objectClasses must not repeat a class" }).optional(),
9411
9413
  /**
9412
- * I device LINKED il cui FRONTE ALTO apre una finestra. Assente = la sorgente
9413
- * non è ascoltata; un array vuoto è rifiutato per la stessa ragione di
9414
+ * The LINKED devices whose RISING EDGE opens a window. Absent = the source
9415
+ * is not listened to; an empty array is rejected for the same reason as
9414
9416
  * `objectClasses`.
9415
9417
  *
9416
- * Sono id di device SORGENTE, non camere: la banda li nomina, quindi il
9417
- * percorso caldo (`DeviceStateChanged`, a ritmo di bus su tutta la flotta)
9418
- * non fa RPC. L'OFFERTA da cui l'operatore li sceglie è un'altra domanda, e
9419
- * si risolve con `deviceManager.getLinkedDevices` + `getBindingsBatch` per
9420
- * device (D12) — mai un elenco globale di cap.
9418
+ * These are SOURCE device ids, not cameras: the band names them, so the
9419
+ * hot path (`DeviceStateChanged`, at bus rate across the whole fleet)
9420
+ * does no RPC. The OFFER from which the operator picks them is another question, and
9421
+ * is resolved with `deviceManager.getLinkedDevices` + `getBindingsBatch` per
9422
+ * device (D12) — never a global list of caps.
9421
9423
  *
9422
- * Cosa vuol dire "alto" dipende dal TIPO di device e non è deciso qui:
9423
- * `SOURCE_CAP_ACTIVE_FIELD` (`catalogs/sensor-active-state.ts`) è LA tabella,
9424
- * la stessa del campanello composto (D671). Ed è il FRONTE, non
9425
- * il livello: un contatto trovato già aperto al riavvio del runner non fa
9426
- * registrare.
9424
+ * What "high" means depends on the device TYPE and is not decided here:
9425
+ * `SOURCE_CAP_ACTIVE_FIELD` (`catalogs/sensor-active-state.ts`) is THE table,
9426
+ * the same one as the composite doorbell (D671). And it is the EDGE, not
9427
+ * the level: a contact found already open at runner restart does not
9428
+ * record.
9427
9429
  */
9428
9430
  sensorDeviceIds: array(number().int().positive()).min(1).max(16).refine(noDuplicates, { message: "sensorDeviceIds must not repeat a device" }).optional()
9429
9431
  });
@@ -10500,7 +10502,7 @@ var DecoderSessionConfigSchema = object({
10500
10502
  * - **VALUE** — at which level, for which scope, until when. That stays ONE
10501
10503
  * thing: the logging settings document on the `system` cap. Two authorities
10502
10504
  * over the values is the exact defect
10503
- * `docs/design/plans/2026-08-26-logging-per-componente.md` was written to
10505
+ * `docs/design/plans/2026-08-26-per-component-logging.md` was written to
10504
10506
  * remove; re-introducing it from the cure side would be grotesque.
10505
10507
  *
10506
10508
  * Nothing in this file reads a clock, an env var or a store. The registry is
@@ -12230,7 +12232,7 @@ var BrokerStatusEnum = _enum([
12230
12232
  "unreachable",
12231
12233
  "error"
12232
12234
  ]);
12233
- var BrokerInfoSchema$1 = object({
12235
+ var BrokerInfoSchema = object({
12234
12236
  /** Stable broker id. Persisted; survives addon restarts. */
12235
12237
  id: string(),
12236
12238
  /** Addon id of the provider that OWNS this broker.
@@ -12373,8 +12375,8 @@ var brokerCapability = {
12373
12375
  kind: "poll"
12374
12376
  },
12375
12377
  methods: {
12376
- list: method(ListInputSchema, array(BrokerInfoSchema$1)),
12377
- get: method(GetInputSchema, BrokerInfoSchema$1.nullable()),
12378
+ list: method(ListInputSchema, array(BrokerInfoSchema)),
12379
+ get: method(GetInputSchema, BrokerInfoSchema.nullable()),
12378
12380
  /** Enumerate which addon provides which broker kind(s) for the
12379
12381
  * unified create picker. The auto-mount fans this array across
12380
12382
  * every registered `broker` provider (array-output method), so the
@@ -14123,7 +14125,7 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
14123
14125
  *
14124
14126
  * ⚠ An earlier version of this comment blamed Zod stripping, and that
14125
14127
  * was wrong — corrected 2026-08-26 after the hop map
14126
- * (`docs/design/2026-08-26-mappa-hop-argomenti.md`) traced the path.
14128
+ * (`docs/design/2026-08-26-topic-hop-map.md`) traced the path.
14127
14129
  * There is **no Zod parse at all** between the door and the engine: the
14128
14130
  * dispatcher forwards the payload verbatim and UDS carries it whole. A
14129
14131
  * field declared here reaches `SqliteSettingsBackend` either way.
@@ -15220,7 +15222,17 @@ var SiteZoneSchema = object({
15220
15222
  var ProviderStatusSchema = object({
15221
15223
  connected: boolean(),
15222
15224
  deviceCount: number(),
15223
- error: string().optional()
15225
+ error: string().optional(),
15226
+ /**
15227
+ * `'orchestrator'`: this provider writes NO camera's `motion` runtime slice
15228
+ * — the orchestrator is its only writer (D696). Set by `BaseDeviceProvider`,
15229
+ * which every provider bundles, so only a provider BUILT from D696-amended
15230
+ * code says it. ABSENT means an older provider that may still write it (raw
15231
+ * VMD writes, a boot seed), and the orchestrator's provider gate keeps that
15232
+ * provider's cameras unwritten (`camera-sensors/motion-slice-provider-gate.ts`)
15233
+ * — the provider twin of the runner's `getLocalLoad().motionSliceWriter`.
15234
+ */
15235
+ motionSliceWriter: literal("orchestrator").optional()
15224
15236
  });
15225
15237
  object({
15226
15238
  externalId: string(),
@@ -16437,7 +16449,7 @@ method(object({
16437
16449
  * per-device window, `KeyFrameCaptureLog`, `bumpCropMetric`. Every one of them
16438
16450
  * ends in a log line, and a log line is the thing the operator asked to stop
16439
16451
  * needing: *"possiamo armare questi errori intanto? Così al prossimo giro
16440
- * ricontrolliamo tutti questi punti"*. Reading them meant grepping Loki and
16452
+ * ricontrolliamo tutti questi punti"* [can we instrument these errors in the meantime? That way next round we recheck all these points]. Reading them meant grepping Loki and
16441
16453
  * hand-correlating timestamps, which is how a 22% thumbnail gap and a 3-hour
16442
16454
  * media blackout were both diagnosed. The counters stay; this is where they can
16443
16455
  * be READ.
@@ -17813,7 +17825,7 @@ var BrokerStatusSchema$1 = _enum([
17813
17825
  "unreachable",
17814
17826
  "tls-error"
17815
17827
  ]);
17816
- var BrokerInfoSchema = object({
17828
+ var BrokerInfoSchema$1 = object({
17817
17829
  id: string(),
17818
17830
  name: string(),
17819
17831
  url: string(),
@@ -17876,7 +17888,7 @@ var StatusSchema = object({
17876
17888
  brokerCount: number(),
17877
17889
  embeddedRunning: boolean()
17878
17890
  });
17879
- method(_void(), array(BrokerInfoSchema)), method(IdInputSchema, BrokerConnectionDetailsSchema, { auth: "admin" }), method(AddBrokerInputSchema, AddBrokerResultSchema, {
17891
+ method(_void(), array(BrokerInfoSchema$1)), method(IdInputSchema, BrokerConnectionDetailsSchema, { auth: "admin" }), method(AddBrokerInputSchema, AddBrokerResultSchema, {
17880
17892
  kind: "mutation",
17881
17893
  auth: "admin"
17882
17894
  }), method(IdInputSchema, _void(), {
@@ -20104,78 +20116,16 @@ var NcRuleInputSchema = object({
20104
20116
  */
20105
20117
  confirm: NcConfirmSchema.optional(),
20106
20118
  /**
20107
- * WAIT for face/plate recognition before saying anything.
20108
- *
20109
- * A notification's TEXT is frozen at enqueue and its media is re-resolved at
20110
- * send; the identity is neither. A face is confirmed after `confirmFrames`
20111
- * agreeing observations — p50 **11.4 s** after the track was first seen,
20112
- * measured on this hub — and an `immediate` rule enqueues on the first object
20113
- * event, seconds before that. So "Gianluca è arrivato" is unsayable on the
20114
- * immediate path, and no amount of media re-resolution fixes a sentence.
20115
- *
20116
- * Only two honest answers exist, and this flag picks between them. It has
20117
- * effect ONLY on a rule that declares a recognition scope
20118
- * ({@link NcConditions.identities} or {@link NcConditions.plates}) — on any
20119
- * other rule there is nothing to wait for and the flag is inert.
20120
- *
20121
- * | value | what happens |
20122
- * | --- | --- |
20123
- * | `true` | the rule stops firing on the object event and fires at TRACK CLOSE instead, once, with the name — later, and complete |
20124
- * | absent / `false` | it fires at once WITHOUT the name, and if recognition lands before the track closes a SECOND, "…is Gianluca" notification follows (one per track, per rule, per target) |
20125
- *
20126
- * `.optional()` and deliberately NOT `.default()`: a Zod default does not run
20127
- * on the addon cap path, and absent has to keep meaning exactly what every
20128
- * rule authored before this field meant.
20129
- *
20130
- * The cost of `true` is stated here because the editor states it too: a rule
20131
- * that waits also inherits track-close SEMANTICS — its `zones` condition
20132
- * tests every zone the track visited and a `crossing` condition can no longer
20133
- * be satisfied, because a closed track carries no crossing.
20134
- */
20135
- waitForEnhancement: boolean().optional(),
20136
- /**
20137
- * GROUP a burst of subjects into ONE notification that grows.
20138
- *
20139
- * Seconds of quiet after the last matching subject before the burst is
20140
- * considered over. While it is open, the first subject enqueues immediately —
20141
- * **exactly as today, with no added latency** — and every real growth (a new
20142
- * subject, or a name confirmed on one already in it) REPLACES that
20143
- * notification with an updated one naming everybody. The push carries the
20144
- * group's own coalescing tag, so the phone replaces rather than stacks.
20145
- *
20146
- * `0` / absent = off, and off is today's behaviour byte for byte.
20147
- *
20148
- * ### Why an idle cutoff and not a window
20149
- *
20150
- * The measured seven-person arrival on device 590 spans 110 s with every
20151
- * internal gap under 30 s. A 12 s fixed window cuts it into three groups; an
20152
- * idle cutoff holds it as one and ends it when the arrival actually ends.
20153
- * 30 s is a widely shipped value for the same decision.
20154
- *
20155
- * ### What it replaces
20156
- *
20157
- * The blind cooldown, which collapses a burst by DISCARDING it. Measured on
20158
- * device 615 / *Persona su Uscio* over six days: 116 qualifying tracks → 74
20159
- * notifications, **44 (37.9%) suppressed outright**, 23 of them overlapping a
20160
- * track that did fire and 7 carrying a confirmed identity nobody heard about.
20161
- * A group collapses the same volume by MERGING, so the cooldown becomes a
20162
- * budget over GROUPS — which is what it always meant — and a growth is never
20163
- * throttled by the window its own first member spent.
20164
- *
20165
- * ### Interaction with {@link waitForEnhancement}
20166
- *
20167
- * They compose, and the order matters. `waitForEnhancement` defers the rule to
20168
- * TRACK CLOSE, so with both set the group is opened by the first member to
20169
- * CLOSE — already carrying its name — and grows as later members close. That
20170
- * is later, and complete. With grouping alone the group opens on the first
20171
- * object event and picks up names as they are confirmed, through the growth
20172
- * path. Neither combination fires twice for one subject.
20173
- *
20174
- * `.optional()` and deliberately NOT `.default()`: a Zod default does not run
20175
- * on the addon cap path, so absent must keep meaning what it meant before this
20176
- * field existed.
20119
+ * IMMEDIATE GROUPED (D692): the first matching subject opens a window of this many
20120
+ * seconds; the rule sends ONE message when the window closes — early, once every
20121
+ * subject in it is final, never before {@link NC_GROUPING_MIN_SEC} — naming everybody
20122
+ * the rule matched, with one mosaic tile per subject.
20123
+ * Absent = plain immediate (one message per track, at the first match).
20124
+ * Only an `immediate` DETECTION rule may carry it (`ruleGroupingApplies`, enforced on
20125
+ * save by the hub's grouping guard). `.optional()`, never `.default()`: the addon cap
20126
+ * path does not run Zod defaults.
20177
20127
  */
20178
- groupIdleSec: number().int().min(0).max(600).optional()
20128
+ groupingSec: number().int().min(5).max(60).optional()
20179
20129
  });
20180
20130
  /**
20181
20131
  * Partial patch for `updateRule` — any subset of the input fields, plus the
@@ -20223,9 +20173,10 @@ var NcRuleClearableKeySchema = _enum([
20223
20173
  "targetUsers",
20224
20174
  "snoozeOptions",
20225
20175
  "snoozeAllowGlobal",
20226
- "waitForEnhancement",
20227
20176
  "actions",
20228
20177
  "confirm",
20178
+ "groupingSec",
20179
+ "waitForEnhancement",
20229
20180
  "groupIdleSec"
20230
20181
  ]);
20231
20182
  var NcRuleUpdateInputSchema = object({
@@ -20247,9 +20198,25 @@ var NcRuleSchema = NcRuleInputSchema.extend({
20247
20198
  */
20248
20199
  disabledTargetIds: array(string()).default([])
20249
20200
  });
20201
+ /**
20202
+ * The state-summary SECTIONS (D647 / D698): the D637 kind groups that report a
20203
+ * still-true state. `backups-exports` and `alarm` are not sections — a completed
20204
+ * job is not an open state, and the alarm stays instant.
20205
+ */
20206
+ var NcStateSummarySectionIdSchema = _enum([
20207
+ "device-state",
20208
+ "streams",
20209
+ "battery",
20210
+ "consumables",
20211
+ "tanks",
20212
+ "detection-blind",
20213
+ "nodes",
20214
+ "addons",
20215
+ "updates"
20216
+ ]);
20250
20217
  /** One section of a previewed state summary. `unavailable` = its state could not be read. */
20251
20218
  var NcStateSummaryPreviewSectionSchema = object({
20252
- id: string(),
20219
+ id: NcStateSummarySectionIdSchema,
20253
20220
  status: _enum(["read", "unavailable"]),
20254
20221
  items: number().int().nonnegative(),
20255
20222
  reason: string().optional()
@@ -20259,7 +20226,7 @@ var NcStateSummaryPreviewSectionSchema = object({
20259
20226
  * a `rule` split (no `section`), one section's on a `section` split.
20260
20227
  */
20261
20228
  var NcStateSummaryPreviewRowSchema = object({
20262
- section: string().optional(),
20229
+ section: NcStateSummarySectionIdSchema.optional(),
20263
20230
  /** The section's name on a per-section row; every reported section's, joined, on a combined one. */
20264
20231
  title: string(),
20265
20232
  text: string(),
@@ -20696,6 +20663,29 @@ object({
20696
20663
  firstAt: number(),
20697
20664
  lastAt: number()
20698
20665
  });
20666
+ var NC_ALARM_TRIGGERED_MAX_SEC = 3600;
20667
+ var NcAlarmDelaySecSchema = number().int().min(0).max(600);
20668
+ var NcAlarmTriggeredSecSchema = number().int().min(0).max(NC_ALARM_TRIGGERED_MAX_SEC);
20669
+ var uniqueModes = (entries) => new Set(entries.map((e) => e.mode)).size === entries.length;
20670
+ var NcAlarmModeDelaysListSchema = array(object({
20671
+ mode: AlarmArmModeSchema,
20672
+ exitDelaySec: NcAlarmDelaySecSchema.optional(),
20673
+ entryDelaySec: NcAlarmDelaySecSchema.optional(),
20674
+ triggeredDurationSec: NcAlarmTriggeredSecSchema.optional()
20675
+ })).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
20676
+ var NcAlarmModeDelaysEditListSchema = array(object({
20677
+ mode: AlarmArmModeSchema,
20678
+ exitDelaySec: NcAlarmDelaySecSchema.nullable().optional(),
20679
+ entryDelaySec: NcAlarmDelaySecSchema.nullable().optional(),
20680
+ triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional()
20681
+ })).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
20682
+ /** One switch of the alarm table: put ONE device on, or take it off, ONE mode's list. */
20683
+ var NcAlarmNonBlockingEditSchema = object({
20684
+ mode: AlarmArmModeSchema,
20685
+ deviceId: number().int().positive(),
20686
+ /** true = on the list (may be open, does not block); false = off the list (blocks). */
20687
+ nonBlocking: boolean()
20688
+ });
20699
20689
  /**
20700
20690
  * The per-mode lists, at most one per mode. Two lists for one mode have no
20701
20691
  * meaning a reader could agree on (union? the last one?), so they are refused
@@ -20704,10 +20694,10 @@ object({
20704
20694
  var NcAlarmNonBlockingListSchema = array(object({
20705
20695
  mode: AlarmArmModeSchema,
20706
20696
  deviceIds: array(number().int()).max(200)
20707
- })).max(8).refine((lists) => new Set(lists.map((l) => l.mode)).size === lists.length, { message: "nonBlocking: at most one list per arm mode" });
20697
+ })).max(8).refine(uniqueModes, { message: "nonBlocking: at most one list per arm mode" });
20708
20698
  /**
20709
- * The three durations the panel's state machine runs on, who hears about its
20710
- * transitions, and which openings each mode tolerates.
20699
+ * The three durations — global, and per mode since D697 — the panel's state
20700
+ * machine runs on, who hears about its transitions, and which openings each mode tolerates.
20711
20701
  *
20712
20702
  * They live on the NOTIFICATION-RULES cap, not on `alarm-panel`, on purpose:
20713
20703
  * `alarm-panel` is `deviceNative` and its other provider mirrors somebody
@@ -20717,15 +20707,15 @@ var NcAlarmNonBlockingListSchema = array(object({
20717
20707
  */
20718
20708
  var NcAlarmSettingsSchema = object({
20719
20709
  /** Grace period between arming and the mode taking effect. 0 = immediate. */
20720
- exitDelaySec: number().int().min(0).max(600),
20710
+ exitDelaySec: NcAlarmDelaySecSchema,
20721
20711
  /** Grace period between a trigger and the alarm firing. 0 = immediate. */
20722
- entryDelaySec: number().int().min(0).max(600),
20712
+ entryDelaySec: NcAlarmDelaySecSchema,
20723
20713
  /**
20724
20714
  * How long `triggered` lasts before the panel re-arms itself.
20725
20715
  * **0 = until an operator disarms it** — the behaviour before this field
20726
20716
  * existed, and therefore what an untouched install keeps doing.
20727
20717
  */
20728
- triggeredDurationSec: number().int().min(0).max(3600),
20718
+ triggeredDurationSec: NcAlarmTriggeredSecSchema,
20729
20719
  /**
20730
20720
  * Deprecated by D630 — every transition is announced. Parsed, never read;
20731
20721
  * remove after one release. Optional so an older admin's patch (which still
@@ -20748,17 +20738,30 @@ var NcAlarmSettingsSchema = object({
20748
20738
  * per mode is meaningful. Defaulted to `[]` so a blob stored before D630
20749
20739
  * parses as "every opening blocks" — the behaviour it was written under.
20750
20740
  */
20751
- nonBlocking: NcAlarmNonBlockingListSchema.default([])
20741
+ nonBlocking: NcAlarmNonBlockingListSchema.default([]),
20742
+ /**
20743
+ * Per arm mode, the delays that mode OVERRIDES (D697). A mode with no entry, or an entry
20744
+ * without a field, uses the global value above — so `[]`, the default, is exactly the
20745
+ * behaviour of a blob stored before this field existed. Read through `resolveModeDelays`.
20746
+ */
20747
+ modeDelays: NcAlarmModeDelaysListSchema.default([])
20752
20748
  });
20753
20749
  /**
20754
20750
  * Every field optional — a tab edits one control at a time.
20755
20751
  *
20756
- * `nonBlocking` is re-declared WITHOUT its default: `.partial()` does not
20757
- * remove an inner `.default()`, so a patch that never named the field would
20758
- * parse to `nonBlocking: []` and wipe every mode's list on an unrelated edit
20759
- * (the same trap {@link NcRulePatchSchema} documents).
20752
+ * `nonBlocking` and `modeDelays` are re-declared WITHOUT their defaults:
20753
+ * `.partial()` does not remove an inner `.default()`, so a patch that never
20754
+ * named the field would parse to `[]` and wipe every mode's list on an
20755
+ * unrelated edit (the same trap {@link NcRulePatchSchema} documents). Here
20756
+ * `modeDelays` means EDITS, not the stored overrides.
20760
20757
  */
20761
- var NcAlarmSettingsPatchSchema = NcAlarmSettingsSchema.extend({ nonBlocking: NcAlarmNonBlockingListSchema }).partial();
20758
+ var NcAlarmSettingsPatchSchema = NcAlarmSettingsSchema.extend({
20759
+ nonBlocking: NcAlarmNonBlockingListSchema,
20760
+ /** Per-mode, per-field edits — NOT the whole list (see NcAlarmModeDelaysEditSchema). */
20761
+ modeDelays: NcAlarmModeDelaysEditListSchema,
20762
+ /** ONE membership change; the panel applies it to the list it holds at its turn. */
20763
+ nonBlockingEdit: NcAlarmNonBlockingEditSchema
20764
+ }).partial().refine((p) => p.nonBlocking === void 0 || p.nonBlockingEdit === void 0, { message: "nonBlocking and nonBlockingEdit are exclusive — send the whole lists or one edit" });
20762
20765
  /**
20763
20766
  * What one arm mode actually arms, DERIVED from the enabled rules gated on it.
20764
20767
  * Never authored, never stored — see `alarm-mode-coverage.ts` for why a stored
@@ -20858,6 +20861,28 @@ var NcAlarmConfigSchema = object({
20858
20861
  */
20859
20862
  live: NcAlarmLiveSchema.optional()
20860
20863
  });
20864
+ var NcAlarmSensorReadingSchema = _enum([
20865
+ "open",
20866
+ "closed",
20867
+ "unknown",
20868
+ "not-opening"
20869
+ ]);
20870
+ /** One device's state as the alarm reads it — the classifier the arm check uses. */
20871
+ var NcAlarmSensorStateSchema = object({
20872
+ deviceId: number().int().positive(),
20873
+ reading: NcAlarmSensorReadingSchema,
20874
+ /** The word as read (`open`, `closed`, `unlocked`, `stopped`, …); null when unknown / not an opening. */
20875
+ state: string().nullable(),
20876
+ /** Why `unknown`: the read failed, or the slice holds no word its cap defines (a placeholder included). */
20877
+ unknownWhy: _enum(["read-failed", "unknown-word"]).nullable(),
20878
+ /** The device manager's liveness as the centre mirrors it; null = not known. */
20879
+ online: boolean().nullable()
20880
+ });
20881
+ var NcAlarmSensorsInputSchema = object({ deviceIds: array(number().int().positive()).max(500) });
20882
+ var NcAlarmSensorsSchema = object({
20883
+ sensors: array(NcAlarmSensorStateSchema),
20884
+ readAt: number().int().nonnegative()
20885
+ });
20861
20886
  /**
20862
20887
  * ONE rule's demand on ONE camera's clip ring.
20863
20888
  *
@@ -20948,7 +20973,7 @@ method(object({}), object({ rules: array(NcRuleSchema) }), { auth: "admin" }), m
20948
20973
  }), method(object({}), NcAlarmConfigSchema, { auth: "admin" }), method(object({ patch: NcAlarmSettingsPatchSchema }), NcAlarmConfigSchema, {
20949
20974
  kind: "mutation",
20950
20975
  auth: "admin"
20951
- });
20976
+ }), method(NcAlarmSensorsInputSchema, NcAlarmSensorsSchema, { auth: "admin" });
20952
20977
  /**
20953
20978
  * Zod schemas for persisted record types.
20954
20979
  *
@@ -22116,14 +22141,14 @@ var TrackSchema = object({
22116
22141
  * `derive-returned-null tile=standin`,
22117
22142
  * `native-tile tile=native no-key-frame-at-close`, …) written at close and
22118
22143
  * CLEARED by the late-keyFrame upgrade when a native tile lands after all.
22119
- * The operator-facing answer to "perché manca l'immagine?" on a track whose
22144
+ * The operator-facing answer to "perché manca l'immagine?" [why is the image missing?] on a track whose
22120
22145
  * tile is a face/plate stand-in, a raster crop, or an icon.
22121
22146
  *
22122
22147
  * **`no-key-frame-at-close` (D400).** The line used to be written ONLY when
22123
22148
  * the TILE ranked below native, so a track whose thumbnail landed natively
22124
22149
  * while its key frame missed carried no reason at all — three of the four
22125
22150
  * `MISSING_KEYFRAME` tracks in the 2026-09-07 operator audit were exactly
22126
- * that shape, and their "niente ultimo" had no cause anywhere on the row.
22151
+ * that shape, and their "niente ultimo" [no last frame] had no cause anywhere on the row.
22127
22152
  * The key frame is the head of a cascade (`keyFrame ⇒ keyFrameSmall ⇒ the
22128
22153
  * lastFrame copy source`), so its absence is now on this line whatever the
22129
22154
  * tile ended up being.
@@ -22210,7 +22235,7 @@ var MotionEventSchema = object({
22210
22235
  /**
22211
22236
  * Ms offsets from `timestamp` (the episode's own first rising edge, so the
22212
22237
  * first entry is always `0`) of every genuine off→on transition the
22213
- * episode saw — "ogni evento on si deve salvare" (D475). NOT one entry per
22238
+ * episode saw — "ogni evento on si deve salvare" [every ON event must be saved] (D475). NOT one entry per
22214
22239
  * push: a firmware source that keepalives at ~1 Hz for the whole burst
22215
22240
  * (Reolink, Hikvision) produces exactly one edge; a source that reports an
22216
22241
  * explicit `false` mid-episode and then resumes before the quiet window
@@ -22734,6 +22759,7 @@ var KeyEventSchema = object({
22734
22759
  bestEventId: string(),
22735
22760
  /** Track lifetime in ms (lastSeen - firstSeen). */
22736
22761
  windowMs: number().optional(),
22762
+ audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
22737
22763
  ...TrackFlagFields,
22738
22764
  ...TrackRetrainFields
22739
22765
  });
@@ -27515,7 +27541,7 @@ var ClipPlaybackSchema = object({
27515
27541
  * **One authorised yes is one wake.** `next-natural` — take the clip the next
27516
27542
  * time the camera is awake for its own reasons — is deliberately not a member:
27517
27543
  * it was proposed, it is free on the battery, and the operator declined it on
27518
- * 2026-09-20 (*"Quando un export viene richiesto si sveglia la camera."*,
27544
+ * 2026-09-20 (*"Quando un export viene richiesto si sveglia la camera."* [When an export is requested the camera wakes up],
27519
27545
  * D558 "Considered and not taken").
27520
27546
  */
27521
27547
  var ClipWakeSchema = _enum(["authorised"]);
@@ -27776,7 +27802,7 @@ DeviceType.Camera, method(object({
27776
27802
  * It replaced `sources?: string[]`, a VIEW filter over source ids that
27777
27803
  * assumed the answer was a fan-out over everything a camera has. The
27778
27804
  * operator settled otherwise on 2026-09-20 — *"l'utilizzatore è uno
27779
- * solo"* — so the list is asked of one provider at a time and there is
27805
+ * solo"* [there is only one user] — so the list is asked of one provider at a time and there is
27780
27806
  * nothing to filter out of it.
27781
27807
  */
27782
27808
  provider: string().min(1)
@@ -35855,7 +35881,7 @@ var ReadGopBytesResultSchema = object({
35855
35881
  /**
35856
35882
  * A time WINDOW of one finalized segment, cut by byte range — the multi-GOP
35857
35883
  * twin of {@link ReadGopBytesResultSchema}'s single instant. Built for the
35858
- * replay clip's `recording` source (`docs/design/plans/2026-08-26-replay-clip-su-pipeline.md`):
35884
+ * replay clip's `recording` source (`docs/design/plans/2026-08-26-clip-replay-on-pipeline.md`):
35859
35885
  * a replay needs several seconds of native pixels, not one frame.
35860
35886
  *
35861
35887
  * `ok.data` is standalone-demuxable, same as a GOP read. `ok.reachesRequestedEnd`
@@ -39219,6 +39245,7 @@ var zoneRulesCapability = {
39219
39245
  */
39220
39246
  durability: "restored"
39221
39247
  };
39248
+ SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
39222
39249
  /**
39223
39250
  * Accessory device helpers — shared across drivers.
39224
39251
  *
@@ -40278,13 +40305,14 @@ var BaseDeviceProvider = class extends BaseAddon {
40278
40305
  async getStatus() {
40279
40306
  const all = await this.ctx.kernel.devices?.getAll() ?? [];
40280
40307
  const summary = this.restoreFailureSummary();
40281
- if (summary === null) return {
40308
+ const base = {
40282
40309
  connected: true,
40283
- deviceCount: all.length
40310
+ deviceCount: all.length,
40311
+ motionSliceWriter: "orchestrator"
40284
40312
  };
40313
+ if (summary === null) return base;
40285
40314
  return {
40286
- connected: true,
40287
- deviceCount: all.length,
40315
+ ...base,
40288
40316
  error: summary
40289
40317
  };
40290
40318
  }
@@ -45720,6 +45748,12 @@ Object.freeze({
45720
45748
  addonId: null,
45721
45749
  access: "view"
45722
45750
  },
45751
+ "notificationRules.getAlarmSensors": {
45752
+ capName: "notification-rules",
45753
+ capScope: "system",
45754
+ addonId: null,
45755
+ access: "view"
45756
+ },
45723
45757
  "notificationRules.getClipRetentionAsks": {
45724
45758
  capName: "notification-rules",
45725
45759
  capScope: "system",
@@ -49298,6 +49332,11 @@ Object.freeze({
49298
49332
  }
49299
49333
  });
49300
49334
  Object.freeze({
49335
+ "accessories.getStatus": [{
49336
+ name: "deviceId",
49337
+ form: "single",
49338
+ optional: false
49339
+ }],
49301
49340
  "accessories.setChildHidden": [{
49302
49341
  name: "childDeviceId",
49303
49342
  form: "single",
@@ -49317,6 +49356,11 @@ Object.freeze({
49317
49356
  form: "single",
49318
49357
  optional: false
49319
49358
  }],
49359
+ "airQualitySensor.getStatus": [{
49360
+ name: "deviceId",
49361
+ form: "single",
49362
+ optional: false
49363
+ }],
49320
49364
  "alarmPanel.arm": [{
49321
49365
  name: "deviceId",
49322
49366
  form: "single",
@@ -49327,11 +49371,36 @@ Object.freeze({
49327
49371
  form: "single",
49328
49372
  optional: false
49329
49373
  }],
49374
+ "alarmPanel.getStatus": [{
49375
+ name: "deviceId",
49376
+ form: "single",
49377
+ optional: false
49378
+ }],
49330
49379
  "alarmPanel.trigger": [{
49331
49380
  name: "deviceId",
49332
49381
  form: "single",
49333
49382
  optional: false
49334
49383
  }],
49384
+ "ambientLightSensor.getStatus": [{
49385
+ name: "deviceId",
49386
+ form: "single",
49387
+ optional: false
49388
+ }],
49389
+ "audioAnalysis.applyDeviceSettingsPatch": [{
49390
+ name: "deviceId",
49391
+ form: "single",
49392
+ optional: false
49393
+ }],
49394
+ "audioAnalysis.getDeviceLiveContribution": [{
49395
+ name: "deviceId",
49396
+ form: "single",
49397
+ optional: false
49398
+ }],
49399
+ "audioAnalysis.getDeviceSettingsContribution": [{
49400
+ name: "deviceId",
49401
+ form: "single",
49402
+ optional: false
49403
+ }],
49335
49404
  "audioAnalysis.resolveDeviceSettings": [{
49336
49405
  name: "deviceId",
49337
49406
  form: "single",
@@ -49372,16 +49441,36 @@ Object.freeze({
49372
49441
  form: "single",
49373
49442
  optional: false
49374
49443
  }],
49444
+ "automationControl.getStatus": [{
49445
+ name: "deviceId",
49446
+ form: "single",
49447
+ optional: false
49448
+ }],
49375
49449
  "automationControl.trigger": [{
49376
49450
  name: "deviceId",
49377
49451
  form: "single",
49378
49452
  optional: false
49379
49453
  }],
49454
+ "battery.getStatus": [{
49455
+ name: "deviceId",
49456
+ form: "single",
49457
+ optional: false
49458
+ }],
49380
49459
  "battery.wakeForStream": [{
49381
49460
  name: "deviceId",
49382
49461
  form: "single",
49383
49462
  optional: false
49384
49463
  }],
49464
+ "binary.getStatus": [{
49465
+ name: "deviceId",
49466
+ form: "single",
49467
+ optional: false
49468
+ }],
49469
+ "brightness.getStatus": [{
49470
+ name: "deviceId",
49471
+ form: "single",
49472
+ optional: false
49473
+ }],
49385
49474
  "brightness.setBrightness": [{
49386
49475
  name: "deviceId",
49387
49476
  form: "single",
@@ -49397,6 +49486,26 @@ Object.freeze({
49397
49486
  form: "single",
49398
49487
  optional: false
49399
49488
  }],
49489
+ "cameraCredentials.getStatus": [{
49490
+ name: "deviceId",
49491
+ form: "single",
49492
+ optional: false
49493
+ }],
49494
+ "cameraGridLayout.applyDeviceSettingsPatch": [{
49495
+ name: "deviceId",
49496
+ form: "single",
49497
+ optional: false
49498
+ }],
49499
+ "cameraGridLayout.getDeviceLiveContribution": [{
49500
+ name: "deviceId",
49501
+ form: "single",
49502
+ optional: false
49503
+ }],
49504
+ "cameraGridLayout.getDeviceSettingsContribution": [{
49505
+ name: "deviceId",
49506
+ form: "single",
49507
+ optional: false
49508
+ }],
49400
49509
  "cameraGridLayout.getLayout": [{
49401
49510
  name: "deviceId",
49402
49511
  form: "single",
@@ -49412,6 +49521,21 @@ Object.freeze({
49412
49521
  form: "single",
49413
49522
  optional: false
49414
49523
  }],
49524
+ "cameraPipelineConfig.applyDeviceSettingsPatch": [{
49525
+ name: "deviceId",
49526
+ form: "single",
49527
+ optional: false
49528
+ }],
49529
+ "cameraPipelineConfig.getDeviceLiveContribution": [{
49530
+ name: "deviceId",
49531
+ form: "single",
49532
+ optional: false
49533
+ }],
49534
+ "cameraPipelineConfig.getDeviceSettingsContribution": [{
49535
+ name: "deviceId",
49536
+ form: "single",
49537
+ optional: false
49538
+ }],
49415
49539
  "cameraStreams.getBrokerStreams": [{
49416
49540
  name: "deviceId",
49417
49541
  form: "single",
@@ -49437,6 +49561,16 @@ Object.freeze({
49437
49561
  form: "single",
49438
49562
  optional: false
49439
49563
  }],
49564
+ "carbonMonoxide.getStatus": [{
49565
+ name: "deviceId",
49566
+ form: "single",
49567
+ optional: false
49568
+ }],
49569
+ "climateControl.getStatus": [{
49570
+ name: "deviceId",
49571
+ form: "single",
49572
+ optional: false
49573
+ }],
49440
49574
  "climateControl.setFanMode": [{
49441
49575
  name: "deviceId",
49442
49576
  form: "single",
@@ -49477,16 +49611,41 @@ Object.freeze({
49477
49611
  form: "single",
49478
49612
  optional: false
49479
49613
  }],
49614
+ "color.getStatus": [{
49615
+ name: "deviceId",
49616
+ form: "single",
49617
+ optional: false
49618
+ }],
49480
49619
  "color.setColor": [{
49481
49620
  name: "deviceId",
49482
49621
  form: "single",
49483
49622
  optional: false
49484
49623
  }],
49624
+ "connectivity.getStatus": [{
49625
+ name: "deviceId",
49626
+ form: "single",
49627
+ optional: false
49628
+ }],
49629
+ "consumables.getStatus": [{
49630
+ name: "deviceId",
49631
+ form: "single",
49632
+ optional: false
49633
+ }],
49485
49634
  "consumables.reset": [{
49486
49635
  name: "deviceId",
49487
49636
  form: "single",
49488
49637
  optional: false
49489
49638
  }],
49639
+ "contact.getStatus": [{
49640
+ name: "deviceId",
49641
+ form: "single",
49642
+ optional: false
49643
+ }],
49644
+ "control.getStatus": [{
49645
+ name: "deviceId",
49646
+ form: "single",
49647
+ optional: false
49648
+ }],
49490
49649
  "control.setValue": [{
49491
49650
  name: "deviceId",
49492
49651
  form: "single",
@@ -49497,6 +49656,11 @@ Object.freeze({
49497
49656
  form: "single",
49498
49657
  optional: false
49499
49658
  }],
49659
+ "cover.getStatus": [{
49660
+ name: "deviceId",
49661
+ form: "single",
49662
+ optional: false
49663
+ }],
49500
49664
  "cover.open": [{
49501
49665
  name: "deviceId",
49502
49666
  form: "single",
@@ -49522,6 +49686,11 @@ Object.freeze({
49522
49686
  form: "single",
49523
49687
  optional: false
49524
49688
  }],
49689
+ "dayNight.getStatus": [{
49690
+ name: "deviceId",
49691
+ form: "single",
49692
+ optional: false
49693
+ }],
49525
49694
  "dayNight.setSettings": [{
49526
49695
  name: "deviceId",
49527
49696
  form: "single",
@@ -49532,11 +49701,31 @@ Object.freeze({
49532
49701
  form: "single",
49533
49702
  optional: true
49534
49703
  }],
49704
+ "detectionPipeline.applyDeviceSettingsPatch": [{
49705
+ name: "deviceId",
49706
+ form: "single",
49707
+ optional: false
49708
+ }],
49709
+ "detectionPipeline.getDeviceLiveContribution": [{
49710
+ name: "deviceId",
49711
+ form: "single",
49712
+ optional: false
49713
+ }],
49714
+ "detectionPipeline.getDeviceSettingsContribution": [{
49715
+ name: "deviceId",
49716
+ form: "single",
49717
+ optional: false
49718
+ }],
49535
49719
  "deviceAdminLink.getAdminLink": [{
49536
49720
  name: "deviceId",
49537
49721
  form: "single",
49538
49722
  optional: false
49539
49723
  }],
49724
+ "deviceAdoption.getStatus": [{
49725
+ name: "deviceId",
49726
+ form: "single",
49727
+ optional: false
49728
+ }],
49540
49729
  "deviceAdoption.release": [{
49541
49730
  name: "camDeviceId",
49542
49731
  form: "single",
@@ -49552,6 +49741,11 @@ Object.freeze({
49552
49741
  form: "single",
49553
49742
  optional: false
49554
49743
  }],
49744
+ "deviceDiscovery.getStatus": [{
49745
+ name: "deviceId",
49746
+ form: "single",
49747
+ optional: false
49748
+ }],
49555
49749
  "deviceDiscovery.listDiscovered": [{
49556
49750
  name: "deviceId",
49557
49751
  form: "single",
@@ -49571,6 +49765,21 @@ Object.freeze({
49571
49765
  form: "single",
49572
49766
  optional: false
49573
49767
  }],
49768
+ "deviceExport.applyDeviceSettingsPatch": [{
49769
+ name: "deviceId",
49770
+ form: "single",
49771
+ optional: false
49772
+ }],
49773
+ "deviceExport.getDeviceLiveContribution": [{
49774
+ name: "deviceId",
49775
+ form: "single",
49776
+ optional: false
49777
+ }],
49778
+ "deviceExport.getDeviceSettingsContribution": [{
49779
+ name: "deviceId",
49780
+ form: "single",
49781
+ optional: false
49782
+ }],
49574
49783
  "deviceExtension.listCandidates": [{
49575
49784
  name: "deviceId",
49576
49785
  form: "single",
@@ -49919,6 +50128,26 @@ Object.freeze({
49919
50128
  form: "single",
49920
50129
  optional: false
49921
50130
  }],
50131
+ "deviceStatus.getStatus": [{
50132
+ name: "deviceId",
50133
+ form: "single",
50134
+ optional: false
50135
+ }],
50136
+ "doorbell.getStatus": [{
50137
+ name: "deviceId",
50138
+ form: "single",
50139
+ optional: false
50140
+ }],
50141
+ "enumSensor.getStatus": [{
50142
+ name: "deviceId",
50143
+ form: "single",
50144
+ optional: false
50145
+ }],
50146
+ "eventEmitter.getStatus": [{
50147
+ name: "deviceId",
50148
+ form: "single",
50149
+ optional: false
50150
+ }],
49922
50151
  "faceGallery.getFaceByTrack": [{
49923
50152
  name: "deviceId",
49924
50153
  form: "single",
@@ -49933,6 +50162,11 @@ Object.freeze({
49933
50162
  form: "array",
49934
50163
  optional: true
49935
50164
  }],
50165
+ "fanControl.getStatus": [{
50166
+ name: "deviceId",
50167
+ form: "single",
50168
+ optional: false
50169
+ }],
49936
50170
  "fanControl.setDirection": [{
49937
50171
  name: "deviceId",
49938
50172
  form: "single",
@@ -49953,6 +50187,26 @@ Object.freeze({
49953
50187
  form: "single",
49954
50188
  optional: false
49955
50189
  }],
50190
+ "featureProbe.getStatus": [{
50191
+ name: "deviceId",
50192
+ form: "single",
50193
+ optional: false
50194
+ }],
50195
+ "flood.getStatus": [{
50196
+ name: "deviceId",
50197
+ form: "single",
50198
+ optional: false
50199
+ }],
50200
+ "gas.getStatus": [{
50201
+ name: "deviceId",
50202
+ form: "single",
50203
+ optional: false
50204
+ }],
50205
+ "humidifier.getStatus": [{
50206
+ name: "deviceId",
50207
+ form: "single",
50208
+ optional: false
50209
+ }],
49956
50210
  "humidifier.setMode": [{
49957
50211
  name: "deviceId",
49958
50212
  form: "single",
@@ -49968,11 +50222,26 @@ Object.freeze({
49968
50222
  form: "single",
49969
50223
  optional: false
49970
50224
  }],
50225
+ "humiditySensor.getStatus": [{
50226
+ name: "deviceId",
50227
+ form: "single",
50228
+ optional: false
50229
+ }],
50230
+ "image.getStatus": [{
50231
+ name: "deviceId",
50232
+ form: "single",
50233
+ optional: false
50234
+ }],
49971
50235
  "imageSettings.getOptions": [{
49972
50236
  name: "deviceId",
49973
50237
  form: "single",
49974
50238
  optional: false
49975
50239
  }],
50240
+ "imageSettings.getStatus": [{
50241
+ name: "deviceId",
50242
+ form: "single",
50243
+ optional: false
50244
+ }],
49976
50245
  "imageSettings.setSettings": [{
49977
50246
  name: "deviceId",
49978
50247
  form: "single",
@@ -49983,6 +50252,11 @@ Object.freeze({
49983
50252
  form: "single",
49984
50253
  optional: false
49985
50254
  }],
50255
+ "intercom.getStatus": [{
50256
+ name: "deviceId",
50257
+ form: "single",
50258
+ optional: false
50259
+ }],
49986
50260
  "intercom.handleAnswer": [{
49987
50261
  name: "deviceId",
49988
50262
  form: "single",
@@ -50013,6 +50287,11 @@ Object.freeze({
50013
50287
  form: "single",
50014
50288
  optional: false
50015
50289
  }],
50290
+ "lawnMowerControl.getStatus": [{
50291
+ name: "deviceId",
50292
+ form: "single",
50293
+ optional: false
50294
+ }],
50016
50295
  "lawnMowerControl.pause": [{
50017
50296
  name: "deviceId",
50018
50297
  form: "single",
@@ -50023,6 +50302,11 @@ Object.freeze({
50023
50302
  form: "single",
50024
50303
  optional: false
50025
50304
  }],
50305
+ "lockControl.getStatus": [{
50306
+ name: "deviceId",
50307
+ form: "single",
50308
+ optional: false
50309
+ }],
50026
50310
  "lockControl.lock": [{
50027
50311
  name: "deviceId",
50028
50312
  form: "single",
@@ -50038,6 +50322,11 @@ Object.freeze({
50038
50322
  form: "single",
50039
50323
  optional: false
50040
50324
  }],
50325
+ "mediaPlayer.getStatus": [{
50326
+ name: "deviceId",
50327
+ form: "single",
50328
+ optional: false
50329
+ }],
50041
50330
  "mediaPlayer.next": [{
50042
50331
  name: "deviceId",
50043
50332
  form: "single",
@@ -50098,6 +50387,11 @@ Object.freeze({
50098
50387
  form: "single",
50099
50388
  optional: false
50100
50389
  }],
50390
+ "motion.getStatus": [{
50391
+ name: "deviceId",
50392
+ form: "single",
50393
+ optional: false
50394
+ }],
50101
50395
  "motion.isDetected": [{
50102
50396
  name: "deviceId",
50103
50397
  form: "single",
@@ -50108,11 +50402,31 @@ Object.freeze({
50108
50402
  form: "single",
50109
50403
  optional: false
50110
50404
  }],
50405
+ "motionDetection.applyDeviceSettingsPatch": [{
50406
+ name: "deviceId",
50407
+ form: "single",
50408
+ optional: false
50409
+ }],
50410
+ "motionDetection.getDeviceLiveContribution": [{
50411
+ name: "deviceId",
50412
+ form: "single",
50413
+ optional: false
50414
+ }],
50415
+ "motionDetection.getDeviceSettingsContribution": [{
50416
+ name: "deviceId",
50417
+ form: "single",
50418
+ optional: false
50419
+ }],
50111
50420
  "motionDetection.removeCamera": [{
50112
50421
  name: "deviceId",
50113
50422
  form: "single",
50114
50423
  optional: false
50115
50424
  }],
50425
+ "motionTrigger.getStatus": [{
50426
+ name: "deviceId",
50427
+ form: "single",
50428
+ optional: false
50429
+ }],
50116
50430
  "motionTrigger.setMotionTrigger": [{
50117
50431
  name: "deviceId",
50118
50432
  form: "single",
@@ -50123,6 +50437,11 @@ Object.freeze({
50123
50437
  form: "single",
50124
50438
  optional: false
50125
50439
  }],
50440
+ "motionZones.getStatus": [{
50441
+ name: "deviceId",
50442
+ form: "single",
50443
+ optional: false
50444
+ }],
50126
50445
  "motionZones.setZone": [{
50127
50446
  name: "deviceId",
50128
50447
  form: "single",
@@ -50133,6 +50452,11 @@ Object.freeze({
50133
50452
  form: "single",
50134
50453
  optional: false
50135
50454
  }],
50455
+ "nativeObjectDetection.getStatus": [{
50456
+ name: "deviceId",
50457
+ form: "single",
50458
+ optional: false
50459
+ }],
50136
50460
  "nativeObjectDetection.setEnabled": [{
50137
50461
  name: "deviceId",
50138
50462
  form: "single",
@@ -50148,6 +50472,11 @@ Object.freeze({
50148
50472
  form: "single",
50149
50473
  optional: false
50150
50474
  }],
50475
+ "navigation.getStatus": [{
50476
+ name: "deviceId",
50477
+ form: "single",
50478
+ optional: false
50479
+ }],
50151
50480
  "navigation.goToPoint": [{
50152
50481
  name: "deviceId",
50153
50482
  form: "single",
@@ -50193,6 +50522,11 @@ Object.freeze({
50193
50522
  form: "single",
50194
50523
  optional: false
50195
50524
  }],
50525
+ "networkLink.getStatus": [{
50526
+ name: "deviceId",
50527
+ form: "single",
50528
+ optional: false
50529
+ }],
50196
50530
  "networkQuality.getDeviceStats": [{
50197
50531
  name: "deviceId",
50198
50532
  form: "single",
@@ -50203,6 +50537,11 @@ Object.freeze({
50203
50537
  form: "single",
50204
50538
  optional: false
50205
50539
  }],
50540
+ "notificationRules.getAlarmSensors": [{
50541
+ name: "deviceIds",
50542
+ form: "array",
50543
+ optional: false
50544
+ }],
50206
50545
  "notificationRules.setDeviceMuted": [{
50207
50546
  name: "deviceId",
50208
50547
  form: "single",
@@ -50213,11 +50552,26 @@ Object.freeze({
50213
50552
  form: "single",
50214
50553
  optional: false
50215
50554
  }],
50555
+ "notifier.getStatus": [{
50556
+ name: "deviceId",
50557
+ form: "single",
50558
+ optional: false
50559
+ }],
50216
50560
  "notifier.send": [{
50217
50561
  name: "deviceId",
50218
50562
  form: "single",
50219
50563
  optional: false
50220
50564
  }],
50565
+ "numericSensor.getStatus": [{
50566
+ name: "deviceId",
50567
+ form: "single",
50568
+ optional: false
50569
+ }],
50570
+ "osd.getStatus": [{
50571
+ name: "deviceId",
50572
+ form: "single",
50573
+ optional: false
50574
+ }],
50221
50575
  "osd.setOverlay": [{
50222
50576
  name: "deviceId",
50223
50577
  form: "single",
@@ -50277,6 +50631,11 @@ Object.freeze({
50277
50631
  form: "single",
50278
50632
  optional: false
50279
50633
  }],
50634
+ "petFeeder.getStatus": [{
50635
+ name: "deviceId",
50636
+ form: "single",
50637
+ optional: false
50638
+ }],
50280
50639
  "petFeeder.markFoodReplenished": [{
50281
50640
  name: "deviceId",
50282
50641
  form: "single",
@@ -50312,6 +50671,11 @@ Object.freeze({
50312
50671
  form: "single",
50313
50672
  optional: false
50314
50673
  }],
50674
+ "pipelineAnalytics.applyDeviceSettingsPatch": [{
50675
+ name: "deviceId",
50676
+ form: "single",
50677
+ optional: false
50678
+ }],
50315
50679
  "pipelineAnalytics.clearTrackRelation": [{
50316
50680
  name: "deviceId",
50317
50681
  form: "single",
@@ -50352,6 +50716,16 @@ Object.freeze({
50352
50716
  form: "single",
50353
50717
  optional: false
50354
50718
  }],
50719
+ "pipelineAnalytics.getDeviceLiveContribution": [{
50720
+ name: "deviceId",
50721
+ form: "single",
50722
+ optional: false
50723
+ }],
50724
+ "pipelineAnalytics.getDeviceSettingsContribution": [{
50725
+ name: "deviceId",
50726
+ form: "single",
50727
+ optional: false
50728
+ }],
50355
50729
  "pipelineAnalytics.getEventDensity": [{
50356
50730
  name: "deviceId",
50357
50731
  form: "single",
@@ -50567,6 +50941,11 @@ Object.freeze({
50567
50941
  form: "single",
50568
50942
  optional: true
50569
50943
  }],
50944
+ "pipelineOrchestrator.applyDeviceSettingsPatch": [{
50945
+ name: "deviceId",
50946
+ form: "single",
50947
+ optional: false
50948
+ }],
50570
50949
  "pipelineOrchestrator.assignAudio": [{
50571
50950
  name: "deviceId",
50572
50951
  form: "single",
@@ -50612,6 +50991,16 @@ Object.freeze({
50612
50991
  form: "single",
50613
50992
  optional: false
50614
50993
  }],
50994
+ "pipelineOrchestrator.getDeviceLiveContribution": [{
50995
+ name: "deviceId",
50996
+ form: "single",
50997
+ optional: false
50998
+ }],
50999
+ "pipelineOrchestrator.getDeviceSettingsContribution": [{
51000
+ name: "deviceId",
51001
+ form: "single",
51002
+ optional: false
51003
+ }],
50615
51004
  "pipelineOrchestrator.getPipelineAssignment": [{
50616
51005
  name: "deviceId",
50617
51006
  form: "single",
@@ -50732,11 +51121,31 @@ Object.freeze({
50732
51121
  form: "single",
50733
51122
  optional: true
50734
51123
  }],
51124
+ "powerMeter.getStatus": [{
51125
+ name: "deviceId",
51126
+ form: "single",
51127
+ optional: false
51128
+ }],
51129
+ "presence.getStatus": [{
51130
+ name: "deviceId",
51131
+ form: "single",
51132
+ optional: false
51133
+ }],
51134
+ "pressureSensor.getStatus": [{
51135
+ name: "deviceId",
51136
+ form: "single",
51137
+ optional: false
51138
+ }],
50735
51139
  "privacyMask.getOptions": [{
50736
51140
  name: "deviceId",
50737
51141
  form: "single",
50738
51142
  optional: false
50739
51143
  }],
51144
+ "privacyMask.getStatus": [{
51145
+ name: "deviceId",
51146
+ form: "single",
51147
+ optional: false
51148
+ }],
50740
51149
  "privacyMask.setAudioEnabled": [{
50741
51150
  name: "deviceId",
50742
51151
  form: "single",
@@ -50787,6 +51196,11 @@ Object.freeze({
50787
51196
  form: "single",
50788
51197
  optional: false
50789
51198
  }],
51199
+ "ptz.getStatus": [{
51200
+ name: "deviceId",
51201
+ form: "single",
51202
+ optional: false
51203
+ }],
50790
51204
  "ptz.goHome": [{
50791
51205
  name: "deviceId",
50792
51206
  form: "single",
@@ -50877,6 +51291,11 @@ Object.freeze({
50877
51291
  form: "single",
50878
51292
  optional: false
50879
51293
  }],
51294
+ "recordingArchive.applyDeviceSettingsPatch": [{
51295
+ name: "deviceId",
51296
+ form: "single",
51297
+ optional: false
51298
+ }],
50880
51299
  "recordingArchive.deleteFootprint": [{
50881
51300
  name: "deviceId",
50882
51301
  form: "single",
@@ -50897,6 +51316,21 @@ Object.freeze({
50897
51316
  form: "single",
50898
51317
  optional: false
50899
51318
  }],
51319
+ "recordingArchive.getDeviceLiveContribution": [{
51320
+ name: "deviceId",
51321
+ form: "single",
51322
+ optional: false
51323
+ }],
51324
+ "recordingArchive.getDeviceSettingsContribution": [{
51325
+ name: "deviceId",
51326
+ form: "single",
51327
+ optional: false
51328
+ }],
51329
+ "recordingArchive.getStatus": [{
51330
+ name: "deviceId",
51331
+ form: "single",
51332
+ optional: false
51333
+ }],
50900
51334
  "recordingArchive.listOpsLog": [{
50901
51335
  name: "deviceId",
50902
51336
  form: "single",
@@ -50982,6 +51416,11 @@ Object.freeze({
50982
51416
  form: "single",
50983
51417
  optional: false
50984
51418
  }],
51419
+ "recordingOnboard.getStatus": [{
51420
+ name: "deviceId",
51421
+ form: "single",
51422
+ optional: false
51423
+ }],
50985
51424
  "recordingOnboard.setSettings": [{
50986
51425
  name: "deviceId",
50987
51426
  form: "single",
@@ -51012,6 +51451,11 @@ Object.freeze({
51012
51451
  form: "single",
51013
51452
  optional: false
51014
51453
  }],
51454
+ "sceneMonitor.getStatus": [{
51455
+ name: "deviceId",
51456
+ form: "single",
51457
+ optional: false
51458
+ }],
51015
51459
  "sceneMonitor.listScenes": [{
51016
51460
  name: "deviceId",
51017
51461
  form: "single",
@@ -51037,6 +51481,11 @@ Object.freeze({
51037
51481
  form: "single",
51038
51482
  optional: false
51039
51483
  }],
51484
+ "scriptRunner.getStatus": [{
51485
+ name: "deviceId",
51486
+ form: "single",
51487
+ optional: false
51488
+ }],
51040
51489
  "scriptRunner.run": [{
51041
51490
  name: "deviceId",
51042
51491
  form: "single",
@@ -51047,11 +51496,31 @@ Object.freeze({
51047
51496
  form: "single",
51048
51497
  optional: false
51049
51498
  }],
51499
+ "smoke.getStatus": [{
51500
+ name: "deviceId",
51501
+ form: "single",
51502
+ optional: false
51503
+ }],
51504
+ "snapshot.applyDeviceSettingsPatch": [{
51505
+ name: "deviceId",
51506
+ form: "single",
51507
+ optional: false
51508
+ }],
51050
51509
  "snapshot.getDebugState": [{
51051
51510
  name: "deviceId",
51052
51511
  form: "single",
51053
51512
  optional: false
51054
51513
  }],
51514
+ "snapshot.getDeviceLiveContribution": [{
51515
+ name: "deviceId",
51516
+ form: "single",
51517
+ optional: false
51518
+ }],
51519
+ "snapshot.getDeviceSettingsContribution": [{
51520
+ name: "deviceId",
51521
+ form: "single",
51522
+ optional: false
51523
+ }],
51055
51524
  "snapshot.getSnapshot": [{
51056
51525
  name: "deviceId",
51057
51526
  form: "single",
@@ -51068,6 +51537,11 @@ Object.freeze({
51068
51537
  form: "array",
51069
51538
  optional: false
51070
51539
  }],
51540
+ "snapshot.getStatus": [{
51541
+ name: "deviceId",
51542
+ form: "single",
51543
+ optional: false
51544
+ }],
51071
51545
  "snapshot.invalidateCache": [{
51072
51546
  name: "deviceId",
51073
51547
  form: "single",
@@ -51078,6 +51552,11 @@ Object.freeze({
51078
51552
  form: "single",
51079
51553
  optional: false
51080
51554
  }],
51555
+ "streamBroker.applyDeviceSettingsPatch": [{
51556
+ name: "deviceId",
51557
+ form: "single",
51558
+ optional: false
51559
+ }],
51081
51560
  "streamBroker.assignProfile": [{
51082
51561
  name: "deviceId",
51083
51562
  form: "single",
@@ -51093,6 +51572,16 @@ Object.freeze({
51093
51572
  form: "single",
51094
51573
  optional: false
51095
51574
  }],
51575
+ "streamBroker.getDeviceLiveContribution": [{
51576
+ name: "deviceId",
51577
+ form: "single",
51578
+ optional: false
51579
+ }],
51580
+ "streamBroker.getDeviceSettingsContribution": [{
51581
+ name: "deviceId",
51582
+ form: "single",
51583
+ optional: false
51584
+ }],
51096
51585
  "streamBroker.getStreamWithCodec": [{
51097
51586
  name: "deviceId",
51098
51587
  form: "single",
@@ -51153,16 +51642,46 @@ Object.freeze({
51153
51642
  form: "single",
51154
51643
  optional: false
51155
51644
  }],
51645
+ "streamParams.getStatus": [{
51646
+ name: "deviceId",
51647
+ form: "single",
51648
+ optional: false
51649
+ }],
51156
51650
  "streamParams.setProfile": [{
51157
51651
  name: "deviceId",
51158
51652
  form: "single",
51159
51653
  optional: false
51160
51654
  }],
51655
+ "switch.getStatus": [{
51656
+ name: "deviceId",
51657
+ form: "single",
51658
+ optional: false
51659
+ }],
51161
51660
  "switch.setState": [{
51162
51661
  name: "deviceId",
51163
51662
  form: "single",
51164
51663
  optional: false
51165
51664
  }],
51665
+ "tamper.getStatus": [{
51666
+ name: "deviceId",
51667
+ form: "single",
51668
+ optional: false
51669
+ }],
51670
+ "temperatureSensor.getStatus": [{
51671
+ name: "deviceId",
51672
+ form: "single",
51673
+ optional: false
51674
+ }],
51675
+ "update.getStatus": [{
51676
+ name: "deviceId",
51677
+ form: "single",
51678
+ optional: false
51679
+ }],
51680
+ "vacuumControl.getStatus": [{
51681
+ name: "deviceId",
51682
+ form: "single",
51683
+ optional: false
51684
+ }],
51166
51685
  "vacuumControl.locate": [{
51167
51686
  name: "deviceId",
51168
51687
  form: "single",
@@ -51198,6 +51717,11 @@ Object.freeze({
51198
51717
  form: "single",
51199
51718
  optional: false
51200
51719
  }],
51720
+ "valve.getStatus": [{
51721
+ name: "deviceId",
51722
+ form: "single",
51723
+ optional: false
51724
+ }],
51201
51725
  "valve.open": [{
51202
51726
  name: "deviceId",
51203
51727
  form: "single",
@@ -51213,6 +51737,11 @@ Object.freeze({
51213
51737
  form: "single",
51214
51738
  optional: false
51215
51739
  }],
51740
+ "vibration.getStatus": [{
51741
+ name: "deviceId",
51742
+ form: "single",
51743
+ optional: false
51744
+ }],
51216
51745
  "videoclips.dialClipStream": [{
51217
51746
  name: "deviceId",
51218
51747
  form: "single",
@@ -51248,6 +51777,11 @@ Object.freeze({
51248
51777
  form: "single",
51249
51778
  optional: false
51250
51779
  }],
51780
+ "waterHeater.getStatus": [{
51781
+ name: "deviceId",
51782
+ form: "single",
51783
+ optional: false
51784
+ }],
51251
51785
  "waterHeater.setAway": [{
51252
51786
  name: "deviceId",
51253
51787
  form: "single",
@@ -51263,6 +51797,11 @@ Object.freeze({
51263
51797
  form: "single",
51264
51798
  optional: false
51265
51799
  }],
51800
+ "weather.getStatus": [{
51801
+ name: "deviceId",
51802
+ form: "single",
51803
+ optional: false
51804
+ }],
51266
51805
  "webrtcSession.addIceCandidate": [{
51267
51806
  name: "deviceId",
51268
51807
  form: "single",
@@ -52207,7 +52746,7 @@ var PreviewTextField = string().max(200);
52207
52746
  * Whether the notification's preview is a STILL or a short animation.
52208
52747
  *
52209
52748
  * The operator's ask, verbatim: *"inviato come gif o video (come per le altre
52210
- * rule)"* — the other rules already offer an animated preview, and a ten-hour
52749
+ * rule)"* [sent as a gif or video (as for the other rules)] — the other rules already offer an animated preview, and a ten-hour
52211
52750
  * night reads better as three seconds of motion than as one frame of it. Both
52212
52751
  * modes get the SAME treatment (blurred frame, large centred title); `'gif'`
52213
52752
  * simply applies it to a dozen frames sampled across the render and assembles