@camstack/addon-provider-hikvision 1.2.136 → 1.2.138

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/addon.js +698 -159
  2. package/dist/addon.mjs +698 -159
  3. package/package.json +1 -3
package/dist/addon.js CHANGED
@@ -7458,7 +7458,7 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
7458
7458
  return DeviceRole;
7459
7459
  }({});
7460
7460
  //#endregion
7461
- //#region ../types/dist/composition-43aqsZQj.mjs
7461
+ //#region ../types/dist/composition-Bzr7GwgP.mjs
7462
7462
  /**
7463
7463
  * The ffmpeg build every CamStack node downloads, per platform and arch.
7464
7464
  *
@@ -7512,20 +7512,20 @@ function portable(target) {
7512
7512
  }
7513
7513
  portable("linux64"), portable("linuxarm64"), portable("macarm64"), portable("mac64");
7514
7514
  /**
7515
- * LA tabella "quale booleano di questo tipo di device conta come ALTO", e il
7516
- * valutatore puro del suo FRONTE.
7515
+ * THE table "which boolean of this device type counts as HIGH", and the
7516
+ * pure evaluator of its EDGE.
7517
7517
  *
7518
- * UNA tabella per tutti quelli che chiedono "questo device è ALTO?": il
7519
- * trigger `RecordingTriggers.sensorDeviceIds` del recorder, i marker dei
7520
- * sensori della post-analysis, il bridge camera-sensors dell'orchestratore e
7521
- * le sorgenti di un campanello composto (`doorbellFeatureSources`, D671).
7522
- * Una seconda copia divergerebbe alla prima cap aggiunta, e il sintomo — "il
7523
- * sensore fa suonare il campanello ma non registra" — è esattamente D62.
7518
+ * ONE table for everyone who asks "is this device HIGH?": the
7519
+ * recorder's `RecordingTriggers.sensorDeviceIds` trigger, the post-analysis
7520
+ * sensor markers, the orchestrator's camera-sensors bridge and
7521
+ * the sources of a composite doorbell (`doorbellFeatureSources`, D671).
7522
+ * A second copy would diverge at the first cap added, and the symptom — "the
7523
+ * sensor rings the doorbell but does not record" — is exactly D62.
7524
7524
  *
7525
- * ⚠ NON è `DEVICE_STATE_READERS` (`catalogs/device-state-vocabulary.ts`), e le
7526
- * due non vanno unificate: quella risponde a "qual è la PAROLA di stato per una
7527
- * regola" (e include `presence`, `cover`, `alarm-panel`), questa a "qual è il
7528
- * booleano il cui FRONTE conta". Vocabolari deliberatamente diversi.
7525
+ * ⚠ NOT `DEVICE_STATE_READERS` (`catalogs/device-state-vocabulary.ts`), and the
7526
+ * two must not be unified: that one answers "what is the state WORD for a
7527
+ * rule" (and includes `presence`, `cover`, `alarm-panel`), this one "which
7528
+ * boolean's EDGE counts". Deliberately different vocabularies.
7529
7529
  */
7530
7530
  /**
7531
7531
  * Known binary / switch source caps → the boolean slice field whose
@@ -7546,6 +7546,8 @@ var SOURCE_CAP_ACTIVE_FIELD = {
7546
7546
  vibration: "detected",
7547
7547
  tamper: "tampered"
7548
7548
  };
7549
+ /** Cap names whose presence in a device's bindings qualify it as a source. */
7550
+ var SOURCE_CAPS = Object.keys(SOURCE_CAP_ACTIVE_FIELD);
7549
7551
  /**
7550
7552
  * Error types for the safe expression engine. Two distinct classes so callers
7551
7553
  * can tell a compile-time (grammar) failure from a runtime (evaluation)
@@ -9152,22 +9154,22 @@ var CLASS_MAP_MACRO_TARGETS = [
9152
9154
  "package"
9153
9155
  ];
9154
9156
  /**
9155
- * Le macro classi di PRIMO LIVELLO: quelle che un object detector emette e che
9156
- * un operatore può selezionare.
9157
+ * The FIRST-LEVEL macro classes: those an object detector emits and that
9158
+ * an operator can select.
9157
9159
  *
9158
- * Sono le tre offerte dallo step `object-detection`
9160
+ * They are the three offered by the `object-detection` step
9159
9161
  * (`addon-pipeline/src/detection-pipeline/registry/step-definitions.ts`,
9160
- * `enabledMacroClasses`). `package` sta in {@link CLASS_MAP_MACRO_TARGETS} e in
9161
- * `MACRO_LABELS` — è una macro vera — ma NON qui: appartiene allo step
9162
- * `package-detection`, la cui abilitazione è guidata dalle zone, e offrire la
9163
- * stessa parola due volte ha già fatto accendere a un operatore il proxy COCO
9162
+ * `enabledMacroClasses`). `package` is in {@link CLASS_MAP_MACRO_TARGETS} and in
9163
+ * `MACRO_LABELS` — it is a true macro — but NOT here: it belongs to the step
9164
+ * `package-detection`, whose enablement is driven by zones, and offering the
9165
+ * same word twice has already made an operator turn on the COCO proxy
9164
9166
  * (suitcase/backpack/handbag) lasciando spento il detector dedicato.
9165
9167
  *
9166
- * UNA lista. Prima di oggi le stesse tre erano scritte a mano nell'offerta
9167
- * dello step e una seconda volta come union `FirstLevelMacro`
9168
- * (`types/detection.ts`); una terza copia per il trigger di registrazione
9169
- * (`RecordingTriggers.objectClasses`) avrebbe reso invisibile la divergenza
9170
- * successiva.
9168
+ * ONE list. Before today the same three were hand-written in the step's offer
9169
+ * and a second time as the union `FirstLevelMacro`
9170
+ * (`types/detection.ts`); a third copy for the recording trigger
9171
+ * (`RecordingTriggers.objectClasses`) would have made the later divergence
9172
+ * invisible.
9171
9173
  */
9172
9174
  var FIRST_LEVEL_MACRO_CLASSES = [
9173
9175
  "person",
@@ -9232,17 +9234,17 @@ var RecordingStorageModeSchema = _enum([
9232
9234
  "on-device-decision"
9233
9235
  ]);
9234
9236
  /**
9235
- * Le macro classi che possono aprire una finestra di registrazione — le stesse
9236
- * tre offerte dallo step `object-detection`, da UNA lista
9237
+ * The macro classes that can open a recording window — the same
9238
+ * three offered by the `object-detection` step, from ONE list
9237
9239
  * ({@link FIRST_LEVEL_MACRO_CLASSES}).
9238
9240
  */
9239
9241
  var RecordingObjectTriggerClassSchema = _enum(FIRST_LEVEL_MACRO_CLASSES);
9240
9242
  /**
9241
- * True quando `values` non ripete un elemento.
9243
+ * True when `values` does not repeat an element.
9242
9244
  *
9243
- * Un duplicato non è innocuo: ogni voce di `objectClasses` / `sensorDeviceIds`
9244
- * diventa una SORGENTE in `bandTriggerSources`, e la stessa sorgente due volte
9245
- * conterebbe due volte le sue finestre in `segmentMissedByMs`.
9245
+ * A duplicate is not harmless: every entry of `objectClasses` / `sensorDeviceIds`
9246
+ * becomes a SOURCE in `bandTriggerSources`, and the same source twice
9247
+ * would count its windows twice in `segmentMissedByMs`.
9246
9248
  */
9247
9249
  var noDuplicates = (values) => new Set(values).size === values.length;
9248
9250
  /** Which detectors trigger an `events`-mode band. */
@@ -9250,34 +9252,34 @@ var RecordingTriggersSchema = object({
9250
9252
  motion: boolean().optional(),
9251
9253
  audioThresholdDbfs: number().optional(),
9252
9254
  /**
9253
- * Le macro classi la cui detection apre una finestra. ASSENTE = la sorgente
9254
- * non è ascoltata; un array VUOTO è rifiutato, perché "banda events, trigger
9255
- * object acceso, nessuna classe" è la stessa forma "abilitata e non registra
9256
- * nulla, per sempre" contro cui è scritto `eventsBandCanEverDemand`.
9255
+ * The macro classes whose detection opens a window. ABSENT = the source
9256
+ * is not listened to; an EMPTY array is rejected, because "events band, object
9257
+ * trigger on, no class" is the same shape "enabled and records
9258
+ * nothing, forever" that `eventsBandCanEverDemand` is written against.
9257
9259
  *
9258
- * Il segnale letto è GIÀ FILTRATO: solo detection `source: 'pipeline'`, cioè
9259
- * quelle che hanno attraversato `enabledMacroClasses`, i
9260
- * `minConfidence<Macro>` e il full-frame guard. L'AI a bordo camera
9261
- * (`source: 'onboard'`) non attraversa nessuno di quei gate e NON apre
9262
- * finestre — vedi `recorder/object-trigger.ts`.
9260
+ * The signal read is ALREADY FILTERED: only `source: 'pipeline'` detections, i.e.
9261
+ * those that went through `enabledMacroClasses`, the
9262
+ * `minConfidence<Macro>` and the full-frame guard. The camera's onboard AI
9263
+ * (`source: 'onboard'`) goes through none of those gates and does NOT open
9264
+ * windows — see `recorder/object-trigger.ts`.
9263
9265
  */
9264
9266
  objectClasses: array(RecordingObjectTriggerClassSchema).min(1).refine(noDuplicates, { message: "objectClasses must not repeat a class" }).optional(),
9265
9267
  /**
9266
- * I device LINKED il cui FRONTE ALTO apre una finestra. Assente = la sorgente
9267
- * non è ascoltata; un array vuoto è rifiutato per la stessa ragione di
9268
+ * The LINKED devices whose RISING EDGE opens a window. Absent = the source
9269
+ * is not listened to; an empty array is rejected for the same reason as
9268
9270
  * `objectClasses`.
9269
9271
  *
9270
- * Sono id di device SORGENTE, non camere: la banda li nomina, quindi il
9271
- * percorso caldo (`DeviceStateChanged`, a ritmo di bus su tutta la flotta)
9272
- * non fa RPC. L'OFFERTA da cui l'operatore li sceglie è un'altra domanda, e
9273
- * si risolve con `deviceManager.getLinkedDevices` + `getBindingsBatch` per
9274
- * device (D12) — mai un elenco globale di cap.
9272
+ * These are SOURCE device ids, not cameras: the band names them, so the
9273
+ * hot path (`DeviceStateChanged`, at bus rate across the whole fleet)
9274
+ * does no RPC. The OFFER from which the operator picks them is another question, and
9275
+ * is resolved with `deviceManager.getLinkedDevices` + `getBindingsBatch` per
9276
+ * device (D12) — never a global list of caps.
9275
9277
  *
9276
- * Cosa vuol dire "alto" dipende dal TIPO di device e non è deciso qui:
9277
- * `SOURCE_CAP_ACTIVE_FIELD` (`catalogs/sensor-active-state.ts`) è LA tabella,
9278
- * la stessa del campanello composto (D671). Ed è il FRONTE, non
9279
- * il livello: un contatto trovato già aperto al riavvio del runner non fa
9280
- * registrare.
9278
+ * What "high" means depends on the device TYPE and is not decided here:
9279
+ * `SOURCE_CAP_ACTIVE_FIELD` (`catalogs/sensor-active-state.ts`) is THE table,
9280
+ * the same one as the composite doorbell (D671). And it is the EDGE, not
9281
+ * the level: a contact found already open at runner restart does not
9282
+ * record.
9281
9283
  */
9282
9284
  sensorDeviceIds: array(number().int().positive()).min(1).max(16).refine(noDuplicates, { message: "sensorDeviceIds must not repeat a device" }).optional()
9283
9285
  });
@@ -10529,7 +10531,7 @@ function findTimezone(id) {
10529
10531
  * - **VALUE** — at which level, for which scope, until when. That stays ONE
10530
10532
  * thing: the logging settings document on the `system` cap. Two authorities
10531
10533
  * over the values is the exact defect
10532
- * `docs/design/plans/2026-08-26-logging-per-componente.md` was written to
10534
+ * `docs/design/plans/2026-08-26-per-component-logging.md` was written to
10533
10535
  * remove; re-introducing it from the cure side would be grotesque.
10534
10536
  *
10535
10537
  * Nothing in this file reads a clock, an env var or a store. The registry is
@@ -12346,7 +12348,7 @@ var BrokerStatusEnum = _enum([
12346
12348
  "unreachable",
12347
12349
  "error"
12348
12350
  ]);
12349
- var BrokerInfoSchema$1 = object({
12351
+ var BrokerInfoSchema = object({
12350
12352
  /** Stable broker id. Persisted; survives addon restarts. */
12351
12353
  id: string(),
12352
12354
  /** Addon id of the provider that OWNS this broker.
@@ -12479,7 +12481,7 @@ var GetStateInputSchema = object({
12479
12481
  * HA: entity_id (returns the cached entity state). */
12480
12482
  key: string()
12481
12483
  });
12482
- method(ListInputSchema, array(BrokerInfoSchema$1)), method(GetInputSchema, BrokerInfoSchema$1.nullable()), method(_void(), array(BrokerProviderInfoSchema), { auth: "admin" }), method(AddInputSchema, AddResultSchema, {
12484
+ method(ListInputSchema, array(BrokerInfoSchema)), method(GetInputSchema, BrokerInfoSchema.nullable()), method(_void(), array(BrokerProviderInfoSchema), { auth: "admin" }), method(AddInputSchema, AddResultSchema, {
12483
12485
  kind: "mutation",
12484
12486
  auth: "admin"
12485
12487
  }), method(RemoveInputSchema, _void(), {
@@ -14190,7 +14192,7 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
14190
14192
  *
14191
14193
  * ⚠ An earlier version of this comment blamed Zod stripping, and that
14192
14194
  * was wrong — corrected 2026-08-26 after the hop map
14193
- * (`docs/design/2026-08-26-mappa-hop-argomenti.md`) traced the path.
14195
+ * (`docs/design/2026-08-26-topic-hop-map.md`) traced the path.
14194
14196
  * There is **no Zod parse at all** between the door and the engine: the
14195
14197
  * dispatcher forwards the payload verbatim and UDS carries it whole. A
14196
14198
  * field declared here reaches `SqliteSettingsBackend` either way.
@@ -15166,7 +15168,17 @@ var SiteZoneSchema = object({
15166
15168
  var ProviderStatusSchema = object({
15167
15169
  connected: boolean(),
15168
15170
  deviceCount: number(),
15169
- error: string().optional()
15171
+ error: string().optional(),
15172
+ /**
15173
+ * `'orchestrator'`: this provider writes NO camera's `motion` runtime slice
15174
+ * — the orchestrator is its only writer (D696). Set by `BaseDeviceProvider`,
15175
+ * which every provider bundles, so only a provider BUILT from D696-amended
15176
+ * code says it. ABSENT means an older provider that may still write it (raw
15177
+ * VMD writes, a boot seed), and the orchestrator's provider gate keeps that
15178
+ * provider's cameras unwritten (`camera-sensors/motion-slice-provider-gate.ts`)
15179
+ * — the provider twin of the runner's `getLocalLoad().motionSliceWriter`.
15180
+ */
15181
+ motionSliceWriter: literal("orchestrator").optional()
15170
15182
  });
15171
15183
  object({
15172
15184
  externalId: string(),
@@ -16383,7 +16395,7 @@ method(object({
16383
16395
  * per-device window, `KeyFrameCaptureLog`, `bumpCropMetric`. Every one of them
16384
16396
  * ends in a log line, and a log line is the thing the operator asked to stop
16385
16397
  * needing: *"possiamo armare questi errori intanto? Così al prossimo giro
16386
- * ricontrolliamo tutti questi punti"*. Reading them meant grepping Loki and
16398
+ * 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
16387
16399
  * hand-correlating timestamps, which is how a 22% thumbnail gap and a 3-hour
16388
16400
  * media blackout were both diagnosed. The counters stay; this is where they can
16389
16401
  * be READ.
@@ -17778,7 +17790,7 @@ var BrokerStatusSchema$1 = _enum([
17778
17790
  "unreachable",
17779
17791
  "tls-error"
17780
17792
  ]);
17781
- var BrokerInfoSchema = object({
17793
+ var BrokerInfoSchema$1 = object({
17782
17794
  id: string(),
17783
17795
  name: string(),
17784
17796
  url: string(),
@@ -17841,7 +17853,7 @@ var StatusSchema = object({
17841
17853
  brokerCount: number(),
17842
17854
  embeddedRunning: boolean()
17843
17855
  });
17844
- method(_void(), array(BrokerInfoSchema)), method(IdInputSchema, BrokerConnectionDetailsSchema, { auth: "admin" }), method(AddBrokerInputSchema, AddBrokerResultSchema, {
17856
+ method(_void(), array(BrokerInfoSchema$1)), method(IdInputSchema, BrokerConnectionDetailsSchema, { auth: "admin" }), method(AddBrokerInputSchema, AddBrokerResultSchema, {
17845
17857
  kind: "mutation",
17846
17858
  auth: "admin"
17847
17859
  }), method(IdInputSchema, _void(), {
@@ -20055,78 +20067,16 @@ var NcRuleInputSchema = object({
20055
20067
  */
20056
20068
  confirm: NcConfirmSchema.optional(),
20057
20069
  /**
20058
- * WAIT for face/plate recognition before saying anything.
20059
- *
20060
- * A notification's TEXT is frozen at enqueue and its media is re-resolved at
20061
- * send; the identity is neither. A face is confirmed after `confirmFrames`
20062
- * agreeing observations — p50 **11.4 s** after the track was first seen,
20063
- * measured on this hub — and an `immediate` rule enqueues on the first object
20064
- * event, seconds before that. So "Gianluca è arrivato" is unsayable on the
20065
- * immediate path, and no amount of media re-resolution fixes a sentence.
20066
- *
20067
- * Only two honest answers exist, and this flag picks between them. It has
20068
- * effect ONLY on a rule that declares a recognition scope
20069
- * ({@link NcConditions.identities} or {@link NcConditions.plates}) — on any
20070
- * other rule there is nothing to wait for and the flag is inert.
20071
- *
20072
- * | value | what happens |
20073
- * | --- | --- |
20074
- * | `true` | the rule stops firing on the object event and fires at TRACK CLOSE instead, once, with the name — later, and complete |
20075
- * | 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) |
20076
- *
20077
- * `.optional()` and deliberately NOT `.default()`: a Zod default does not run
20078
- * on the addon cap path, and absent has to keep meaning exactly what every
20079
- * rule authored before this field meant.
20080
- *
20081
- * The cost of `true` is stated here because the editor states it too: a rule
20082
- * that waits also inherits track-close SEMANTICS — its `zones` condition
20083
- * tests every zone the track visited and a `crossing` condition can no longer
20084
- * be satisfied, because a closed track carries no crossing.
20085
- */
20086
- waitForEnhancement: boolean().optional(),
20087
- /**
20088
- * GROUP a burst of subjects into ONE notification that grows.
20089
- *
20090
- * Seconds of quiet after the last matching subject before the burst is
20091
- * considered over. While it is open, the first subject enqueues immediately —
20092
- * **exactly as today, with no added latency** — and every real growth (a new
20093
- * subject, or a name confirmed on one already in it) REPLACES that
20094
- * notification with an updated one naming everybody. The push carries the
20095
- * group's own coalescing tag, so the phone replaces rather than stacks.
20096
- *
20097
- * `0` / absent = off, and off is today's behaviour byte for byte.
20098
- *
20099
- * ### Why an idle cutoff and not a window
20100
- *
20101
- * The measured seven-person arrival on device 590 spans 110 s with every
20102
- * internal gap under 30 s. A 12 s fixed window cuts it into three groups; an
20103
- * idle cutoff holds it as one and ends it when the arrival actually ends.
20104
- * 30 s is a widely shipped value for the same decision.
20105
- *
20106
- * ### What it replaces
20107
- *
20108
- * The blind cooldown, which collapses a burst by DISCARDING it. Measured on
20109
- * device 615 / *Persona su Uscio* over six days: 116 qualifying tracks → 74
20110
- * notifications, **44 (37.9%) suppressed outright**, 23 of them overlapping a
20111
- * track that did fire and 7 carrying a confirmed identity nobody heard about.
20112
- * A group collapses the same volume by MERGING, so the cooldown becomes a
20113
- * budget over GROUPS — which is what it always meant — and a growth is never
20114
- * throttled by the window its own first member spent.
20115
- *
20116
- * ### Interaction with {@link waitForEnhancement}
20117
- *
20118
- * They compose, and the order matters. `waitForEnhancement` defers the rule to
20119
- * TRACK CLOSE, so with both set the group is opened by the first member to
20120
- * CLOSE — already carrying its name — and grows as later members close. That
20121
- * is later, and complete. With grouping alone the group opens on the first
20122
- * object event and picks up names as they are confirmed, through the growth
20123
- * path. Neither combination fires twice for one subject.
20124
- *
20125
- * `.optional()` and deliberately NOT `.default()`: a Zod default does not run
20126
- * on the addon cap path, so absent must keep meaning what it meant before this
20127
- * field existed.
20070
+ * IMMEDIATE GROUPED (D692): the first matching subject opens a window of this many
20071
+ * seconds; the rule sends ONE message when the window closes — early, once every
20072
+ * subject in it is final, never before {@link NC_GROUPING_MIN_SEC} — naming everybody
20073
+ * the rule matched, with one mosaic tile per subject.
20074
+ * Absent = plain immediate (one message per track, at the first match).
20075
+ * Only an `immediate` DETECTION rule may carry it (`ruleGroupingApplies`, enforced on
20076
+ * save by the hub's grouping guard). `.optional()`, never `.default()`: the addon cap
20077
+ * path does not run Zod defaults.
20128
20078
  */
20129
- groupIdleSec: number().int().min(0).max(600).optional()
20079
+ groupingSec: number().int().min(5).max(60).optional()
20130
20080
  });
20131
20081
  /**
20132
20082
  * Partial patch for `updateRule` — any subset of the input fields, plus the
@@ -20174,9 +20124,10 @@ var NcRuleClearableKeySchema = _enum([
20174
20124
  "targetUsers",
20175
20125
  "snoozeOptions",
20176
20126
  "snoozeAllowGlobal",
20177
- "waitForEnhancement",
20178
20127
  "actions",
20179
20128
  "confirm",
20129
+ "groupingSec",
20130
+ "waitForEnhancement",
20180
20131
  "groupIdleSec"
20181
20132
  ]);
20182
20133
  var NcRuleUpdateInputSchema = object({
@@ -20198,9 +20149,25 @@ var NcRuleSchema = NcRuleInputSchema.extend({
20198
20149
  */
20199
20150
  disabledTargetIds: array(string()).default([])
20200
20151
  });
20152
+ /**
20153
+ * The state-summary SECTIONS (D647 / D698): the D637 kind groups that report a
20154
+ * still-true state. `backups-exports` and `alarm` are not sections — a completed
20155
+ * job is not an open state, and the alarm stays instant.
20156
+ */
20157
+ var NcStateSummarySectionIdSchema = _enum([
20158
+ "device-state",
20159
+ "streams",
20160
+ "battery",
20161
+ "consumables",
20162
+ "tanks",
20163
+ "detection-blind",
20164
+ "nodes",
20165
+ "addons",
20166
+ "updates"
20167
+ ]);
20201
20168
  /** One section of a previewed state summary. `unavailable` = its state could not be read. */
20202
20169
  var NcStateSummaryPreviewSectionSchema = object({
20203
- id: string(),
20170
+ id: NcStateSummarySectionIdSchema,
20204
20171
  status: _enum(["read", "unavailable"]),
20205
20172
  items: number().int().nonnegative(),
20206
20173
  reason: string().optional()
@@ -20210,7 +20177,7 @@ var NcStateSummaryPreviewSectionSchema = object({
20210
20177
  * a `rule` split (no `section`), one section's on a `section` split.
20211
20178
  */
20212
20179
  var NcStateSummaryPreviewRowSchema = object({
20213
- section: string().optional(),
20180
+ section: NcStateSummarySectionIdSchema.optional(),
20214
20181
  /** The section's name on a per-section row; every reported section's, joined, on a combined one. */
20215
20182
  title: string(),
20216
20183
  text: string(),
@@ -20647,6 +20614,29 @@ object({
20647
20614
  firstAt: number(),
20648
20615
  lastAt: number()
20649
20616
  });
20617
+ var NC_ALARM_TRIGGERED_MAX_SEC = 3600;
20618
+ var NcAlarmDelaySecSchema = number().int().min(0).max(600);
20619
+ var NcAlarmTriggeredSecSchema = number().int().min(0).max(NC_ALARM_TRIGGERED_MAX_SEC);
20620
+ var uniqueModes = (entries) => new Set(entries.map((e) => e.mode)).size === entries.length;
20621
+ var NcAlarmModeDelaysListSchema = array(object({
20622
+ mode: AlarmArmModeSchema,
20623
+ exitDelaySec: NcAlarmDelaySecSchema.optional(),
20624
+ entryDelaySec: NcAlarmDelaySecSchema.optional(),
20625
+ triggeredDurationSec: NcAlarmTriggeredSecSchema.optional()
20626
+ })).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
20627
+ var NcAlarmModeDelaysEditListSchema = array(object({
20628
+ mode: AlarmArmModeSchema,
20629
+ exitDelaySec: NcAlarmDelaySecSchema.nullable().optional(),
20630
+ entryDelaySec: NcAlarmDelaySecSchema.nullable().optional(),
20631
+ triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional()
20632
+ })).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
20633
+ /** One switch of the alarm table: put ONE device on, or take it off, ONE mode's list. */
20634
+ var NcAlarmNonBlockingEditSchema = object({
20635
+ mode: AlarmArmModeSchema,
20636
+ deviceId: number().int().positive(),
20637
+ /** true = on the list (may be open, does not block); false = off the list (blocks). */
20638
+ nonBlocking: boolean()
20639
+ });
20650
20640
  /**
20651
20641
  * The per-mode lists, at most one per mode. Two lists for one mode have no
20652
20642
  * meaning a reader could agree on (union? the last one?), so they are refused
@@ -20655,10 +20645,10 @@ object({
20655
20645
  var NcAlarmNonBlockingListSchema = array(object({
20656
20646
  mode: AlarmArmModeSchema,
20657
20647
  deviceIds: array(number().int()).max(200)
20658
- })).max(8).refine((lists) => new Set(lists.map((l) => l.mode)).size === lists.length, { message: "nonBlocking: at most one list per arm mode" });
20648
+ })).max(8).refine(uniqueModes, { message: "nonBlocking: at most one list per arm mode" });
20659
20649
  /**
20660
- * The three durations the panel's state machine runs on, who hears about its
20661
- * transitions, and which openings each mode tolerates.
20650
+ * The three durations — global, and per mode since D697 — the panel's state
20651
+ * machine runs on, who hears about its transitions, and which openings each mode tolerates.
20662
20652
  *
20663
20653
  * They live on the NOTIFICATION-RULES cap, not on `alarm-panel`, on purpose:
20664
20654
  * `alarm-panel` is `deviceNative` and its other provider mirrors somebody
@@ -20668,15 +20658,15 @@ var NcAlarmNonBlockingListSchema = array(object({
20668
20658
  */
20669
20659
  var NcAlarmSettingsSchema = object({
20670
20660
  /** Grace period between arming and the mode taking effect. 0 = immediate. */
20671
- exitDelaySec: number().int().min(0).max(600),
20661
+ exitDelaySec: NcAlarmDelaySecSchema,
20672
20662
  /** Grace period between a trigger and the alarm firing. 0 = immediate. */
20673
- entryDelaySec: number().int().min(0).max(600),
20663
+ entryDelaySec: NcAlarmDelaySecSchema,
20674
20664
  /**
20675
20665
  * How long `triggered` lasts before the panel re-arms itself.
20676
20666
  * **0 = until an operator disarms it** — the behaviour before this field
20677
20667
  * existed, and therefore what an untouched install keeps doing.
20678
20668
  */
20679
- triggeredDurationSec: number().int().min(0).max(3600),
20669
+ triggeredDurationSec: NcAlarmTriggeredSecSchema,
20680
20670
  /**
20681
20671
  * Deprecated by D630 — every transition is announced. Parsed, never read;
20682
20672
  * remove after one release. Optional so an older admin's patch (which still
@@ -20699,17 +20689,30 @@ var NcAlarmSettingsSchema = object({
20699
20689
  * per mode is meaningful. Defaulted to `[]` so a blob stored before D630
20700
20690
  * parses as "every opening blocks" — the behaviour it was written under.
20701
20691
  */
20702
- nonBlocking: NcAlarmNonBlockingListSchema.default([])
20692
+ nonBlocking: NcAlarmNonBlockingListSchema.default([]),
20693
+ /**
20694
+ * Per arm mode, the delays that mode OVERRIDES (D697). A mode with no entry, or an entry
20695
+ * without a field, uses the global value above — so `[]`, the default, is exactly the
20696
+ * behaviour of a blob stored before this field existed. Read through `resolveModeDelays`.
20697
+ */
20698
+ modeDelays: NcAlarmModeDelaysListSchema.default([])
20703
20699
  });
20704
20700
  /**
20705
20701
  * Every field optional — a tab edits one control at a time.
20706
20702
  *
20707
- * `nonBlocking` is re-declared WITHOUT its default: `.partial()` does not
20708
- * remove an inner `.default()`, so a patch that never named the field would
20709
- * parse to `nonBlocking: []` and wipe every mode's list on an unrelated edit
20710
- * (the same trap {@link NcRulePatchSchema} documents).
20703
+ * `nonBlocking` and `modeDelays` are re-declared WITHOUT their defaults:
20704
+ * `.partial()` does not remove an inner `.default()`, so a patch that never
20705
+ * named the field would parse to `[]` and wipe every mode's list on an
20706
+ * unrelated edit (the same trap {@link NcRulePatchSchema} documents). Here
20707
+ * `modeDelays` means EDITS, not the stored overrides.
20711
20708
  */
20712
- var NcAlarmSettingsPatchSchema = NcAlarmSettingsSchema.extend({ nonBlocking: NcAlarmNonBlockingListSchema }).partial();
20709
+ var NcAlarmSettingsPatchSchema = NcAlarmSettingsSchema.extend({
20710
+ nonBlocking: NcAlarmNonBlockingListSchema,
20711
+ /** Per-mode, per-field edits — NOT the whole list (see NcAlarmModeDelaysEditSchema). */
20712
+ modeDelays: NcAlarmModeDelaysEditListSchema,
20713
+ /** ONE membership change; the panel applies it to the list it holds at its turn. */
20714
+ nonBlockingEdit: NcAlarmNonBlockingEditSchema
20715
+ }).partial().refine((p) => p.nonBlocking === void 0 || p.nonBlockingEdit === void 0, { message: "nonBlocking and nonBlockingEdit are exclusive — send the whole lists or one edit" });
20713
20716
  /**
20714
20717
  * What one arm mode actually arms, DERIVED from the enabled rules gated on it.
20715
20718
  * Never authored, never stored — see `alarm-mode-coverage.ts` for why a stored
@@ -20809,6 +20812,28 @@ var NcAlarmConfigSchema = object({
20809
20812
  */
20810
20813
  live: NcAlarmLiveSchema.optional()
20811
20814
  });
20815
+ var NcAlarmSensorReadingSchema = _enum([
20816
+ "open",
20817
+ "closed",
20818
+ "unknown",
20819
+ "not-opening"
20820
+ ]);
20821
+ /** One device's state as the alarm reads it — the classifier the arm check uses. */
20822
+ var NcAlarmSensorStateSchema = object({
20823
+ deviceId: number().int().positive(),
20824
+ reading: NcAlarmSensorReadingSchema,
20825
+ /** The word as read (`open`, `closed`, `unlocked`, `stopped`, …); null when unknown / not an opening. */
20826
+ state: string().nullable(),
20827
+ /** Why `unknown`: the read failed, or the slice holds no word its cap defines (a placeholder included). */
20828
+ unknownWhy: _enum(["read-failed", "unknown-word"]).nullable(),
20829
+ /** The device manager's liveness as the centre mirrors it; null = not known. */
20830
+ online: boolean().nullable()
20831
+ });
20832
+ var NcAlarmSensorsInputSchema = object({ deviceIds: array(number().int().positive()).max(500) });
20833
+ var NcAlarmSensorsSchema = object({
20834
+ sensors: array(NcAlarmSensorStateSchema),
20835
+ readAt: number().int().nonnegative()
20836
+ });
20812
20837
  /**
20813
20838
  * ONE rule's demand on ONE camera's clip ring.
20814
20839
  *
@@ -20899,7 +20924,7 @@ method(object({}), object({ rules: array(NcRuleSchema) }), { auth: "admin" }), m
20899
20924
  }), method(object({}), NcAlarmConfigSchema, { auth: "admin" }), method(object({ patch: NcAlarmSettingsPatchSchema }), NcAlarmConfigSchema, {
20900
20925
  kind: "mutation",
20901
20926
  auth: "admin"
20902
- });
20927
+ }), method(NcAlarmSensorsInputSchema, NcAlarmSensorsSchema, { auth: "admin" });
20903
20928
  /**
20904
20929
  * Zod schemas for persisted record types.
20905
20930
  *
@@ -22051,14 +22076,14 @@ var TrackSchema = object({
22051
22076
  * `derive-returned-null tile=standin`,
22052
22077
  * `native-tile tile=native no-key-frame-at-close`, …) written at close and
22053
22078
  * CLEARED by the late-keyFrame upgrade when a native tile lands after all.
22054
- * The operator-facing answer to "perché manca l'immagine?" on a track whose
22079
+ * The operator-facing answer to "perché manca l'immagine?" [why is the image missing?] on a track whose
22055
22080
  * tile is a face/plate stand-in, a raster crop, or an icon.
22056
22081
  *
22057
22082
  * **`no-key-frame-at-close` (D400).** The line used to be written ONLY when
22058
22083
  * the TILE ranked below native, so a track whose thumbnail landed natively
22059
22084
  * while its key frame missed carried no reason at all — three of the four
22060
22085
  * `MISSING_KEYFRAME` tracks in the 2026-09-07 operator audit were exactly
22061
- * that shape, and their "niente ultimo" had no cause anywhere on the row.
22086
+ * that shape, and their "niente ultimo" [no last frame] had no cause anywhere on the row.
22062
22087
  * The key frame is the head of a cascade (`keyFrame ⇒ keyFrameSmall ⇒ the
22063
22088
  * lastFrame copy source`), so its absence is now on this line whatever the
22064
22089
  * tile ended up being.
@@ -22145,7 +22170,7 @@ var MotionEventSchema = object({
22145
22170
  /**
22146
22171
  * Ms offsets from `timestamp` (the episode's own first rising edge, so the
22147
22172
  * first entry is always `0`) of every genuine off→on transition the
22148
- * episode saw — "ogni evento on si deve salvare" (D475). NOT one entry per
22173
+ * episode saw — "ogni evento on si deve salvare" [every ON event must be saved] (D475). NOT one entry per
22149
22174
  * push: a firmware source that keepalives at ~1 Hz for the whole burst
22150
22175
  * (Reolink, Hikvision) produces exactly one edge; a source that reports an
22151
22176
  * explicit `false` mid-episode and then resumes before the quiet window
@@ -22669,6 +22694,7 @@ var KeyEventSchema = object({
22669
22694
  bestEventId: string(),
22670
22695
  /** Track lifetime in ms (lastSeen - firstSeen). */
22671
22696
  windowMs: number().optional(),
22697
+ audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
22672
22698
  ...TrackFlagFields,
22673
22699
  ...TrackRetrainFields
22674
22700
  });
@@ -27602,7 +27628,7 @@ var ClipPlaybackSchema = object({
27602
27628
  * **One authorised yes is one wake.** `next-natural` — take the clip the next
27603
27629
  * time the camera is awake for its own reasons — is deliberately not a member:
27604
27630
  * it was proposed, it is free on the battery, and the operator declined it on
27605
- * 2026-09-20 (*"Quando un export viene richiesto si sveglia la camera."*,
27631
+ * 2026-09-20 (*"Quando un export viene richiesto si sveglia la camera."* [When an export is requested the camera wakes up],
27606
27632
  * D558 "Considered and not taken").
27607
27633
  */
27608
27634
  var ClipWakeSchema = _enum(["authorised"]);
@@ -27998,7 +28024,7 @@ var videoclipsCapability = {
27998
28024
  * **It is a SECTION of the Recording tab, at the end of it — not a tab of
27999
28025
  * its own.** It shipped as a `clips` top-tab and the operator rejected the
28000
28026
  * placement: *"utilizzerei la stessa tab recordings, lì abbiamo già tutto il
28001
- * necessario, una nuova sezione alla fine per le clips"*. The Recording tab
28027
+ * necessario, una nuova sezione alla fine per le clips"* [I would use the same recordings tab, there we already have everything necessary, a new section at the end for the clips]. The Recording tab
28002
28028
  * already holds the recorder's panel, the schedule bands and the unified
28003
28029
  * retention policy; footage the camera itself holds is the same question,
28004
28030
  * asked of a different store. `order: 100` puts it after all of them with
@@ -28059,7 +28085,7 @@ var videoclipsCapability = {
28059
28085
  * It replaced `sources?: string[]`, a VIEW filter over source ids that
28060
28086
  * assumed the answer was a fan-out over everything a camera has. The
28061
28087
  * operator settled otherwise on 2026-09-20 — *"l'utilizzatore è uno
28062
- * solo"* — so the list is asked of one provider at a time and there is
28088
+ * solo"* [there is only one user] — so the list is asked of one provider at a time and there is
28063
28089
  * nothing to filter out of it.
28064
28090
  */
28065
28091
  provider: string().min(1)
@@ -36406,7 +36432,7 @@ var ReadGopBytesResultSchema = object({
36406
36432
  /**
36407
36433
  * A time WINDOW of one finalized segment, cut by byte range — the multi-GOP
36408
36434
  * twin of {@link ReadGopBytesResultSchema}'s single instant. Built for the
36409
- * replay clip's `recording` source (`docs/design/plans/2026-08-26-replay-clip-su-pipeline.md`):
36435
+ * replay clip's `recording` source (`docs/design/plans/2026-08-26-clip-replay-on-pipeline.md`):
36410
36436
  * a replay needs several seconds of native pixels, not one frame.
36411
36437
  *
36412
36438
  * `ok.data` is standalone-demuxable, same as a GOP read. `ok.reachesRequestedEnd`
@@ -40148,6 +40174,7 @@ var zoneRulesCapability = {
40148
40174
  */
40149
40175
  durability: "restored"
40150
40176
  };
40177
+ SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
40151
40178
  /**
40152
40179
  * Accessory device helpers — shared across drivers.
40153
40180
  *
@@ -41222,13 +41249,14 @@ var BaseDeviceProvider = class extends BaseAddon {
41222
41249
  async getStatus() {
41223
41250
  const all = await this.ctx.kernel.devices?.getAll() ?? [];
41224
41251
  const summary = this.restoreFailureSummary();
41225
- if (summary === null) return {
41252
+ const base = {
41226
41253
  connected: true,
41227
- deviceCount: all.length
41254
+ deviceCount: all.length,
41255
+ motionSliceWriter: "orchestrator"
41228
41256
  };
41257
+ if (summary === null) return base;
41229
41258
  return {
41230
- connected: true,
41231
- deviceCount: all.length,
41259
+ ...base,
41232
41260
  error: summary
41233
41261
  };
41234
41262
  }
@@ -46882,6 +46910,12 @@ Object.freeze({
46882
46910
  addonId: null,
46883
46911
  access: "view"
46884
46912
  },
46913
+ "notificationRules.getAlarmSensors": {
46914
+ capName: "notification-rules",
46915
+ capScope: "system",
46916
+ addonId: null,
46917
+ access: "view"
46918
+ },
46885
46919
  "notificationRules.getClipRetentionAsks": {
46886
46920
  capName: "notification-rules",
46887
46921
  capScope: "system",
@@ -50460,6 +50494,11 @@ Object.freeze({
50460
50494
  }
50461
50495
  });
50462
50496
  Object.freeze({
50497
+ "accessories.getStatus": [{
50498
+ name: "deviceId",
50499
+ form: "single",
50500
+ optional: false
50501
+ }],
50463
50502
  "accessories.setChildHidden": [{
50464
50503
  name: "childDeviceId",
50465
50504
  form: "single",
@@ -50479,6 +50518,11 @@ Object.freeze({
50479
50518
  form: "single",
50480
50519
  optional: false
50481
50520
  }],
50521
+ "airQualitySensor.getStatus": [{
50522
+ name: "deviceId",
50523
+ form: "single",
50524
+ optional: false
50525
+ }],
50482
50526
  "alarmPanel.arm": [{
50483
50527
  name: "deviceId",
50484
50528
  form: "single",
@@ -50489,11 +50533,36 @@ Object.freeze({
50489
50533
  form: "single",
50490
50534
  optional: false
50491
50535
  }],
50536
+ "alarmPanel.getStatus": [{
50537
+ name: "deviceId",
50538
+ form: "single",
50539
+ optional: false
50540
+ }],
50492
50541
  "alarmPanel.trigger": [{
50493
50542
  name: "deviceId",
50494
50543
  form: "single",
50495
50544
  optional: false
50496
50545
  }],
50546
+ "ambientLightSensor.getStatus": [{
50547
+ name: "deviceId",
50548
+ form: "single",
50549
+ optional: false
50550
+ }],
50551
+ "audioAnalysis.applyDeviceSettingsPatch": [{
50552
+ name: "deviceId",
50553
+ form: "single",
50554
+ optional: false
50555
+ }],
50556
+ "audioAnalysis.getDeviceLiveContribution": [{
50557
+ name: "deviceId",
50558
+ form: "single",
50559
+ optional: false
50560
+ }],
50561
+ "audioAnalysis.getDeviceSettingsContribution": [{
50562
+ name: "deviceId",
50563
+ form: "single",
50564
+ optional: false
50565
+ }],
50497
50566
  "audioAnalysis.resolveDeviceSettings": [{
50498
50567
  name: "deviceId",
50499
50568
  form: "single",
@@ -50534,16 +50603,36 @@ Object.freeze({
50534
50603
  form: "single",
50535
50604
  optional: false
50536
50605
  }],
50606
+ "automationControl.getStatus": [{
50607
+ name: "deviceId",
50608
+ form: "single",
50609
+ optional: false
50610
+ }],
50537
50611
  "automationControl.trigger": [{
50538
50612
  name: "deviceId",
50539
50613
  form: "single",
50540
50614
  optional: false
50541
50615
  }],
50616
+ "battery.getStatus": [{
50617
+ name: "deviceId",
50618
+ form: "single",
50619
+ optional: false
50620
+ }],
50542
50621
  "battery.wakeForStream": [{
50543
50622
  name: "deviceId",
50544
50623
  form: "single",
50545
50624
  optional: false
50546
50625
  }],
50626
+ "binary.getStatus": [{
50627
+ name: "deviceId",
50628
+ form: "single",
50629
+ optional: false
50630
+ }],
50631
+ "brightness.getStatus": [{
50632
+ name: "deviceId",
50633
+ form: "single",
50634
+ optional: false
50635
+ }],
50547
50636
  "brightness.setBrightness": [{
50548
50637
  name: "deviceId",
50549
50638
  form: "single",
@@ -50559,6 +50648,26 @@ Object.freeze({
50559
50648
  form: "single",
50560
50649
  optional: false
50561
50650
  }],
50651
+ "cameraCredentials.getStatus": [{
50652
+ name: "deviceId",
50653
+ form: "single",
50654
+ optional: false
50655
+ }],
50656
+ "cameraGridLayout.applyDeviceSettingsPatch": [{
50657
+ name: "deviceId",
50658
+ form: "single",
50659
+ optional: false
50660
+ }],
50661
+ "cameraGridLayout.getDeviceLiveContribution": [{
50662
+ name: "deviceId",
50663
+ form: "single",
50664
+ optional: false
50665
+ }],
50666
+ "cameraGridLayout.getDeviceSettingsContribution": [{
50667
+ name: "deviceId",
50668
+ form: "single",
50669
+ optional: false
50670
+ }],
50562
50671
  "cameraGridLayout.getLayout": [{
50563
50672
  name: "deviceId",
50564
50673
  form: "single",
@@ -50574,6 +50683,21 @@ Object.freeze({
50574
50683
  form: "single",
50575
50684
  optional: false
50576
50685
  }],
50686
+ "cameraPipelineConfig.applyDeviceSettingsPatch": [{
50687
+ name: "deviceId",
50688
+ form: "single",
50689
+ optional: false
50690
+ }],
50691
+ "cameraPipelineConfig.getDeviceLiveContribution": [{
50692
+ name: "deviceId",
50693
+ form: "single",
50694
+ optional: false
50695
+ }],
50696
+ "cameraPipelineConfig.getDeviceSettingsContribution": [{
50697
+ name: "deviceId",
50698
+ form: "single",
50699
+ optional: false
50700
+ }],
50577
50701
  "cameraStreams.getBrokerStreams": [{
50578
50702
  name: "deviceId",
50579
50703
  form: "single",
@@ -50599,6 +50723,16 @@ Object.freeze({
50599
50723
  form: "single",
50600
50724
  optional: false
50601
50725
  }],
50726
+ "carbonMonoxide.getStatus": [{
50727
+ name: "deviceId",
50728
+ form: "single",
50729
+ optional: false
50730
+ }],
50731
+ "climateControl.getStatus": [{
50732
+ name: "deviceId",
50733
+ form: "single",
50734
+ optional: false
50735
+ }],
50602
50736
  "climateControl.setFanMode": [{
50603
50737
  name: "deviceId",
50604
50738
  form: "single",
@@ -50639,16 +50773,41 @@ Object.freeze({
50639
50773
  form: "single",
50640
50774
  optional: false
50641
50775
  }],
50776
+ "color.getStatus": [{
50777
+ name: "deviceId",
50778
+ form: "single",
50779
+ optional: false
50780
+ }],
50642
50781
  "color.setColor": [{
50643
50782
  name: "deviceId",
50644
50783
  form: "single",
50645
50784
  optional: false
50646
50785
  }],
50786
+ "connectivity.getStatus": [{
50787
+ name: "deviceId",
50788
+ form: "single",
50789
+ optional: false
50790
+ }],
50791
+ "consumables.getStatus": [{
50792
+ name: "deviceId",
50793
+ form: "single",
50794
+ optional: false
50795
+ }],
50647
50796
  "consumables.reset": [{
50648
50797
  name: "deviceId",
50649
50798
  form: "single",
50650
50799
  optional: false
50651
50800
  }],
50801
+ "contact.getStatus": [{
50802
+ name: "deviceId",
50803
+ form: "single",
50804
+ optional: false
50805
+ }],
50806
+ "control.getStatus": [{
50807
+ name: "deviceId",
50808
+ form: "single",
50809
+ optional: false
50810
+ }],
50652
50811
  "control.setValue": [{
50653
50812
  name: "deviceId",
50654
50813
  form: "single",
@@ -50659,6 +50818,11 @@ Object.freeze({
50659
50818
  form: "single",
50660
50819
  optional: false
50661
50820
  }],
50821
+ "cover.getStatus": [{
50822
+ name: "deviceId",
50823
+ form: "single",
50824
+ optional: false
50825
+ }],
50662
50826
  "cover.open": [{
50663
50827
  name: "deviceId",
50664
50828
  form: "single",
@@ -50684,6 +50848,11 @@ Object.freeze({
50684
50848
  form: "single",
50685
50849
  optional: false
50686
50850
  }],
50851
+ "dayNight.getStatus": [{
50852
+ name: "deviceId",
50853
+ form: "single",
50854
+ optional: false
50855
+ }],
50687
50856
  "dayNight.setSettings": [{
50688
50857
  name: "deviceId",
50689
50858
  form: "single",
@@ -50694,11 +50863,31 @@ Object.freeze({
50694
50863
  form: "single",
50695
50864
  optional: true
50696
50865
  }],
50866
+ "detectionPipeline.applyDeviceSettingsPatch": [{
50867
+ name: "deviceId",
50868
+ form: "single",
50869
+ optional: false
50870
+ }],
50871
+ "detectionPipeline.getDeviceLiveContribution": [{
50872
+ name: "deviceId",
50873
+ form: "single",
50874
+ optional: false
50875
+ }],
50876
+ "detectionPipeline.getDeviceSettingsContribution": [{
50877
+ name: "deviceId",
50878
+ form: "single",
50879
+ optional: false
50880
+ }],
50697
50881
  "deviceAdminLink.getAdminLink": [{
50698
50882
  name: "deviceId",
50699
50883
  form: "single",
50700
50884
  optional: false
50701
50885
  }],
50886
+ "deviceAdoption.getStatus": [{
50887
+ name: "deviceId",
50888
+ form: "single",
50889
+ optional: false
50890
+ }],
50702
50891
  "deviceAdoption.release": [{
50703
50892
  name: "camDeviceId",
50704
50893
  form: "single",
@@ -50714,6 +50903,11 @@ Object.freeze({
50714
50903
  form: "single",
50715
50904
  optional: false
50716
50905
  }],
50906
+ "deviceDiscovery.getStatus": [{
50907
+ name: "deviceId",
50908
+ form: "single",
50909
+ optional: false
50910
+ }],
50717
50911
  "deviceDiscovery.listDiscovered": [{
50718
50912
  name: "deviceId",
50719
50913
  form: "single",
@@ -50733,6 +50927,21 @@ Object.freeze({
50733
50927
  form: "single",
50734
50928
  optional: false
50735
50929
  }],
50930
+ "deviceExport.applyDeviceSettingsPatch": [{
50931
+ name: "deviceId",
50932
+ form: "single",
50933
+ optional: false
50934
+ }],
50935
+ "deviceExport.getDeviceLiveContribution": [{
50936
+ name: "deviceId",
50937
+ form: "single",
50938
+ optional: false
50939
+ }],
50940
+ "deviceExport.getDeviceSettingsContribution": [{
50941
+ name: "deviceId",
50942
+ form: "single",
50943
+ optional: false
50944
+ }],
50736
50945
  "deviceExtension.listCandidates": [{
50737
50946
  name: "deviceId",
50738
50947
  form: "single",
@@ -51081,6 +51290,26 @@ Object.freeze({
51081
51290
  form: "single",
51082
51291
  optional: false
51083
51292
  }],
51293
+ "deviceStatus.getStatus": [{
51294
+ name: "deviceId",
51295
+ form: "single",
51296
+ optional: false
51297
+ }],
51298
+ "doorbell.getStatus": [{
51299
+ name: "deviceId",
51300
+ form: "single",
51301
+ optional: false
51302
+ }],
51303
+ "enumSensor.getStatus": [{
51304
+ name: "deviceId",
51305
+ form: "single",
51306
+ optional: false
51307
+ }],
51308
+ "eventEmitter.getStatus": [{
51309
+ name: "deviceId",
51310
+ form: "single",
51311
+ optional: false
51312
+ }],
51084
51313
  "faceGallery.getFaceByTrack": [{
51085
51314
  name: "deviceId",
51086
51315
  form: "single",
@@ -51095,6 +51324,11 @@ Object.freeze({
51095
51324
  form: "array",
51096
51325
  optional: true
51097
51326
  }],
51327
+ "fanControl.getStatus": [{
51328
+ name: "deviceId",
51329
+ form: "single",
51330
+ optional: false
51331
+ }],
51098
51332
  "fanControl.setDirection": [{
51099
51333
  name: "deviceId",
51100
51334
  form: "single",
@@ -51115,6 +51349,26 @@ Object.freeze({
51115
51349
  form: "single",
51116
51350
  optional: false
51117
51351
  }],
51352
+ "featureProbe.getStatus": [{
51353
+ name: "deviceId",
51354
+ form: "single",
51355
+ optional: false
51356
+ }],
51357
+ "flood.getStatus": [{
51358
+ name: "deviceId",
51359
+ form: "single",
51360
+ optional: false
51361
+ }],
51362
+ "gas.getStatus": [{
51363
+ name: "deviceId",
51364
+ form: "single",
51365
+ optional: false
51366
+ }],
51367
+ "humidifier.getStatus": [{
51368
+ name: "deviceId",
51369
+ form: "single",
51370
+ optional: false
51371
+ }],
51118
51372
  "humidifier.setMode": [{
51119
51373
  name: "deviceId",
51120
51374
  form: "single",
@@ -51130,11 +51384,26 @@ Object.freeze({
51130
51384
  form: "single",
51131
51385
  optional: false
51132
51386
  }],
51387
+ "humiditySensor.getStatus": [{
51388
+ name: "deviceId",
51389
+ form: "single",
51390
+ optional: false
51391
+ }],
51392
+ "image.getStatus": [{
51393
+ name: "deviceId",
51394
+ form: "single",
51395
+ optional: false
51396
+ }],
51133
51397
  "imageSettings.getOptions": [{
51134
51398
  name: "deviceId",
51135
51399
  form: "single",
51136
51400
  optional: false
51137
51401
  }],
51402
+ "imageSettings.getStatus": [{
51403
+ name: "deviceId",
51404
+ form: "single",
51405
+ optional: false
51406
+ }],
51138
51407
  "imageSettings.setSettings": [{
51139
51408
  name: "deviceId",
51140
51409
  form: "single",
@@ -51145,6 +51414,11 @@ Object.freeze({
51145
51414
  form: "single",
51146
51415
  optional: false
51147
51416
  }],
51417
+ "intercom.getStatus": [{
51418
+ name: "deviceId",
51419
+ form: "single",
51420
+ optional: false
51421
+ }],
51148
51422
  "intercom.handleAnswer": [{
51149
51423
  name: "deviceId",
51150
51424
  form: "single",
@@ -51175,6 +51449,11 @@ Object.freeze({
51175
51449
  form: "single",
51176
51450
  optional: false
51177
51451
  }],
51452
+ "lawnMowerControl.getStatus": [{
51453
+ name: "deviceId",
51454
+ form: "single",
51455
+ optional: false
51456
+ }],
51178
51457
  "lawnMowerControl.pause": [{
51179
51458
  name: "deviceId",
51180
51459
  form: "single",
@@ -51185,6 +51464,11 @@ Object.freeze({
51185
51464
  form: "single",
51186
51465
  optional: false
51187
51466
  }],
51467
+ "lockControl.getStatus": [{
51468
+ name: "deviceId",
51469
+ form: "single",
51470
+ optional: false
51471
+ }],
51188
51472
  "lockControl.lock": [{
51189
51473
  name: "deviceId",
51190
51474
  form: "single",
@@ -51200,6 +51484,11 @@ Object.freeze({
51200
51484
  form: "single",
51201
51485
  optional: false
51202
51486
  }],
51487
+ "mediaPlayer.getStatus": [{
51488
+ name: "deviceId",
51489
+ form: "single",
51490
+ optional: false
51491
+ }],
51203
51492
  "mediaPlayer.next": [{
51204
51493
  name: "deviceId",
51205
51494
  form: "single",
@@ -51260,6 +51549,11 @@ Object.freeze({
51260
51549
  form: "single",
51261
51550
  optional: false
51262
51551
  }],
51552
+ "motion.getStatus": [{
51553
+ name: "deviceId",
51554
+ form: "single",
51555
+ optional: false
51556
+ }],
51263
51557
  "motion.isDetected": [{
51264
51558
  name: "deviceId",
51265
51559
  form: "single",
@@ -51270,11 +51564,31 @@ Object.freeze({
51270
51564
  form: "single",
51271
51565
  optional: false
51272
51566
  }],
51567
+ "motionDetection.applyDeviceSettingsPatch": [{
51568
+ name: "deviceId",
51569
+ form: "single",
51570
+ optional: false
51571
+ }],
51572
+ "motionDetection.getDeviceLiveContribution": [{
51573
+ name: "deviceId",
51574
+ form: "single",
51575
+ optional: false
51576
+ }],
51577
+ "motionDetection.getDeviceSettingsContribution": [{
51578
+ name: "deviceId",
51579
+ form: "single",
51580
+ optional: false
51581
+ }],
51273
51582
  "motionDetection.removeCamera": [{
51274
51583
  name: "deviceId",
51275
51584
  form: "single",
51276
51585
  optional: false
51277
51586
  }],
51587
+ "motionTrigger.getStatus": [{
51588
+ name: "deviceId",
51589
+ form: "single",
51590
+ optional: false
51591
+ }],
51278
51592
  "motionTrigger.setMotionTrigger": [{
51279
51593
  name: "deviceId",
51280
51594
  form: "single",
@@ -51285,6 +51599,11 @@ Object.freeze({
51285
51599
  form: "single",
51286
51600
  optional: false
51287
51601
  }],
51602
+ "motionZones.getStatus": [{
51603
+ name: "deviceId",
51604
+ form: "single",
51605
+ optional: false
51606
+ }],
51288
51607
  "motionZones.setZone": [{
51289
51608
  name: "deviceId",
51290
51609
  form: "single",
@@ -51295,6 +51614,11 @@ Object.freeze({
51295
51614
  form: "single",
51296
51615
  optional: false
51297
51616
  }],
51617
+ "nativeObjectDetection.getStatus": [{
51618
+ name: "deviceId",
51619
+ form: "single",
51620
+ optional: false
51621
+ }],
51298
51622
  "nativeObjectDetection.setEnabled": [{
51299
51623
  name: "deviceId",
51300
51624
  form: "single",
@@ -51310,6 +51634,11 @@ Object.freeze({
51310
51634
  form: "single",
51311
51635
  optional: false
51312
51636
  }],
51637
+ "navigation.getStatus": [{
51638
+ name: "deviceId",
51639
+ form: "single",
51640
+ optional: false
51641
+ }],
51313
51642
  "navigation.goToPoint": [{
51314
51643
  name: "deviceId",
51315
51644
  form: "single",
@@ -51355,6 +51684,11 @@ Object.freeze({
51355
51684
  form: "single",
51356
51685
  optional: false
51357
51686
  }],
51687
+ "networkLink.getStatus": [{
51688
+ name: "deviceId",
51689
+ form: "single",
51690
+ optional: false
51691
+ }],
51358
51692
  "networkQuality.getDeviceStats": [{
51359
51693
  name: "deviceId",
51360
51694
  form: "single",
@@ -51365,6 +51699,11 @@ Object.freeze({
51365
51699
  form: "single",
51366
51700
  optional: false
51367
51701
  }],
51702
+ "notificationRules.getAlarmSensors": [{
51703
+ name: "deviceIds",
51704
+ form: "array",
51705
+ optional: false
51706
+ }],
51368
51707
  "notificationRules.setDeviceMuted": [{
51369
51708
  name: "deviceId",
51370
51709
  form: "single",
@@ -51375,11 +51714,26 @@ Object.freeze({
51375
51714
  form: "single",
51376
51715
  optional: false
51377
51716
  }],
51717
+ "notifier.getStatus": [{
51718
+ name: "deviceId",
51719
+ form: "single",
51720
+ optional: false
51721
+ }],
51378
51722
  "notifier.send": [{
51379
51723
  name: "deviceId",
51380
51724
  form: "single",
51381
51725
  optional: false
51382
51726
  }],
51727
+ "numericSensor.getStatus": [{
51728
+ name: "deviceId",
51729
+ form: "single",
51730
+ optional: false
51731
+ }],
51732
+ "osd.getStatus": [{
51733
+ name: "deviceId",
51734
+ form: "single",
51735
+ optional: false
51736
+ }],
51383
51737
  "osd.setOverlay": [{
51384
51738
  name: "deviceId",
51385
51739
  form: "single",
@@ -51439,6 +51793,11 @@ Object.freeze({
51439
51793
  form: "single",
51440
51794
  optional: false
51441
51795
  }],
51796
+ "petFeeder.getStatus": [{
51797
+ name: "deviceId",
51798
+ form: "single",
51799
+ optional: false
51800
+ }],
51442
51801
  "petFeeder.markFoodReplenished": [{
51443
51802
  name: "deviceId",
51444
51803
  form: "single",
@@ -51474,6 +51833,11 @@ Object.freeze({
51474
51833
  form: "single",
51475
51834
  optional: false
51476
51835
  }],
51836
+ "pipelineAnalytics.applyDeviceSettingsPatch": [{
51837
+ name: "deviceId",
51838
+ form: "single",
51839
+ optional: false
51840
+ }],
51477
51841
  "pipelineAnalytics.clearTrackRelation": [{
51478
51842
  name: "deviceId",
51479
51843
  form: "single",
@@ -51514,6 +51878,16 @@ Object.freeze({
51514
51878
  form: "single",
51515
51879
  optional: false
51516
51880
  }],
51881
+ "pipelineAnalytics.getDeviceLiveContribution": [{
51882
+ name: "deviceId",
51883
+ form: "single",
51884
+ optional: false
51885
+ }],
51886
+ "pipelineAnalytics.getDeviceSettingsContribution": [{
51887
+ name: "deviceId",
51888
+ form: "single",
51889
+ optional: false
51890
+ }],
51517
51891
  "pipelineAnalytics.getEventDensity": [{
51518
51892
  name: "deviceId",
51519
51893
  form: "single",
@@ -51729,6 +52103,11 @@ Object.freeze({
51729
52103
  form: "single",
51730
52104
  optional: true
51731
52105
  }],
52106
+ "pipelineOrchestrator.applyDeviceSettingsPatch": [{
52107
+ name: "deviceId",
52108
+ form: "single",
52109
+ optional: false
52110
+ }],
51732
52111
  "pipelineOrchestrator.assignAudio": [{
51733
52112
  name: "deviceId",
51734
52113
  form: "single",
@@ -51774,6 +52153,16 @@ Object.freeze({
51774
52153
  form: "single",
51775
52154
  optional: false
51776
52155
  }],
52156
+ "pipelineOrchestrator.getDeviceLiveContribution": [{
52157
+ name: "deviceId",
52158
+ form: "single",
52159
+ optional: false
52160
+ }],
52161
+ "pipelineOrchestrator.getDeviceSettingsContribution": [{
52162
+ name: "deviceId",
52163
+ form: "single",
52164
+ optional: false
52165
+ }],
51777
52166
  "pipelineOrchestrator.getPipelineAssignment": [{
51778
52167
  name: "deviceId",
51779
52168
  form: "single",
@@ -51894,11 +52283,31 @@ Object.freeze({
51894
52283
  form: "single",
51895
52284
  optional: true
51896
52285
  }],
52286
+ "powerMeter.getStatus": [{
52287
+ name: "deviceId",
52288
+ form: "single",
52289
+ optional: false
52290
+ }],
52291
+ "presence.getStatus": [{
52292
+ name: "deviceId",
52293
+ form: "single",
52294
+ optional: false
52295
+ }],
52296
+ "pressureSensor.getStatus": [{
52297
+ name: "deviceId",
52298
+ form: "single",
52299
+ optional: false
52300
+ }],
51897
52301
  "privacyMask.getOptions": [{
51898
52302
  name: "deviceId",
51899
52303
  form: "single",
51900
52304
  optional: false
51901
52305
  }],
52306
+ "privacyMask.getStatus": [{
52307
+ name: "deviceId",
52308
+ form: "single",
52309
+ optional: false
52310
+ }],
51902
52311
  "privacyMask.setAudioEnabled": [{
51903
52312
  name: "deviceId",
51904
52313
  form: "single",
@@ -51949,6 +52358,11 @@ Object.freeze({
51949
52358
  form: "single",
51950
52359
  optional: false
51951
52360
  }],
52361
+ "ptz.getStatus": [{
52362
+ name: "deviceId",
52363
+ form: "single",
52364
+ optional: false
52365
+ }],
51952
52366
  "ptz.goHome": [{
51953
52367
  name: "deviceId",
51954
52368
  form: "single",
@@ -52039,6 +52453,11 @@ Object.freeze({
52039
52453
  form: "single",
52040
52454
  optional: false
52041
52455
  }],
52456
+ "recordingArchive.applyDeviceSettingsPatch": [{
52457
+ name: "deviceId",
52458
+ form: "single",
52459
+ optional: false
52460
+ }],
52042
52461
  "recordingArchive.deleteFootprint": [{
52043
52462
  name: "deviceId",
52044
52463
  form: "single",
@@ -52059,6 +52478,21 @@ Object.freeze({
52059
52478
  form: "single",
52060
52479
  optional: false
52061
52480
  }],
52481
+ "recordingArchive.getDeviceLiveContribution": [{
52482
+ name: "deviceId",
52483
+ form: "single",
52484
+ optional: false
52485
+ }],
52486
+ "recordingArchive.getDeviceSettingsContribution": [{
52487
+ name: "deviceId",
52488
+ form: "single",
52489
+ optional: false
52490
+ }],
52491
+ "recordingArchive.getStatus": [{
52492
+ name: "deviceId",
52493
+ form: "single",
52494
+ optional: false
52495
+ }],
52062
52496
  "recordingArchive.listOpsLog": [{
52063
52497
  name: "deviceId",
52064
52498
  form: "single",
@@ -52144,6 +52578,11 @@ Object.freeze({
52144
52578
  form: "single",
52145
52579
  optional: false
52146
52580
  }],
52581
+ "recordingOnboard.getStatus": [{
52582
+ name: "deviceId",
52583
+ form: "single",
52584
+ optional: false
52585
+ }],
52147
52586
  "recordingOnboard.setSettings": [{
52148
52587
  name: "deviceId",
52149
52588
  form: "single",
@@ -52174,6 +52613,11 @@ Object.freeze({
52174
52613
  form: "single",
52175
52614
  optional: false
52176
52615
  }],
52616
+ "sceneMonitor.getStatus": [{
52617
+ name: "deviceId",
52618
+ form: "single",
52619
+ optional: false
52620
+ }],
52177
52621
  "sceneMonitor.listScenes": [{
52178
52622
  name: "deviceId",
52179
52623
  form: "single",
@@ -52199,6 +52643,11 @@ Object.freeze({
52199
52643
  form: "single",
52200
52644
  optional: false
52201
52645
  }],
52646
+ "scriptRunner.getStatus": [{
52647
+ name: "deviceId",
52648
+ form: "single",
52649
+ optional: false
52650
+ }],
52202
52651
  "scriptRunner.run": [{
52203
52652
  name: "deviceId",
52204
52653
  form: "single",
@@ -52209,11 +52658,31 @@ Object.freeze({
52209
52658
  form: "single",
52210
52659
  optional: false
52211
52660
  }],
52661
+ "smoke.getStatus": [{
52662
+ name: "deviceId",
52663
+ form: "single",
52664
+ optional: false
52665
+ }],
52666
+ "snapshot.applyDeviceSettingsPatch": [{
52667
+ name: "deviceId",
52668
+ form: "single",
52669
+ optional: false
52670
+ }],
52212
52671
  "snapshot.getDebugState": [{
52213
52672
  name: "deviceId",
52214
52673
  form: "single",
52215
52674
  optional: false
52216
52675
  }],
52676
+ "snapshot.getDeviceLiveContribution": [{
52677
+ name: "deviceId",
52678
+ form: "single",
52679
+ optional: false
52680
+ }],
52681
+ "snapshot.getDeviceSettingsContribution": [{
52682
+ name: "deviceId",
52683
+ form: "single",
52684
+ optional: false
52685
+ }],
52217
52686
  "snapshot.getSnapshot": [{
52218
52687
  name: "deviceId",
52219
52688
  form: "single",
@@ -52230,6 +52699,11 @@ Object.freeze({
52230
52699
  form: "array",
52231
52700
  optional: false
52232
52701
  }],
52702
+ "snapshot.getStatus": [{
52703
+ name: "deviceId",
52704
+ form: "single",
52705
+ optional: false
52706
+ }],
52233
52707
  "snapshot.invalidateCache": [{
52234
52708
  name: "deviceId",
52235
52709
  form: "single",
@@ -52240,6 +52714,11 @@ Object.freeze({
52240
52714
  form: "single",
52241
52715
  optional: false
52242
52716
  }],
52717
+ "streamBroker.applyDeviceSettingsPatch": [{
52718
+ name: "deviceId",
52719
+ form: "single",
52720
+ optional: false
52721
+ }],
52243
52722
  "streamBroker.assignProfile": [{
52244
52723
  name: "deviceId",
52245
52724
  form: "single",
@@ -52255,6 +52734,16 @@ Object.freeze({
52255
52734
  form: "single",
52256
52735
  optional: false
52257
52736
  }],
52737
+ "streamBroker.getDeviceLiveContribution": [{
52738
+ name: "deviceId",
52739
+ form: "single",
52740
+ optional: false
52741
+ }],
52742
+ "streamBroker.getDeviceSettingsContribution": [{
52743
+ name: "deviceId",
52744
+ form: "single",
52745
+ optional: false
52746
+ }],
52258
52747
  "streamBroker.getStreamWithCodec": [{
52259
52748
  name: "deviceId",
52260
52749
  form: "single",
@@ -52315,16 +52804,46 @@ Object.freeze({
52315
52804
  form: "single",
52316
52805
  optional: false
52317
52806
  }],
52807
+ "streamParams.getStatus": [{
52808
+ name: "deviceId",
52809
+ form: "single",
52810
+ optional: false
52811
+ }],
52318
52812
  "streamParams.setProfile": [{
52319
52813
  name: "deviceId",
52320
52814
  form: "single",
52321
52815
  optional: false
52322
52816
  }],
52817
+ "switch.getStatus": [{
52818
+ name: "deviceId",
52819
+ form: "single",
52820
+ optional: false
52821
+ }],
52323
52822
  "switch.setState": [{
52324
52823
  name: "deviceId",
52325
52824
  form: "single",
52326
52825
  optional: false
52327
52826
  }],
52827
+ "tamper.getStatus": [{
52828
+ name: "deviceId",
52829
+ form: "single",
52830
+ optional: false
52831
+ }],
52832
+ "temperatureSensor.getStatus": [{
52833
+ name: "deviceId",
52834
+ form: "single",
52835
+ optional: false
52836
+ }],
52837
+ "update.getStatus": [{
52838
+ name: "deviceId",
52839
+ form: "single",
52840
+ optional: false
52841
+ }],
52842
+ "vacuumControl.getStatus": [{
52843
+ name: "deviceId",
52844
+ form: "single",
52845
+ optional: false
52846
+ }],
52328
52847
  "vacuumControl.locate": [{
52329
52848
  name: "deviceId",
52330
52849
  form: "single",
@@ -52360,6 +52879,11 @@ Object.freeze({
52360
52879
  form: "single",
52361
52880
  optional: false
52362
52881
  }],
52882
+ "valve.getStatus": [{
52883
+ name: "deviceId",
52884
+ form: "single",
52885
+ optional: false
52886
+ }],
52363
52887
  "valve.open": [{
52364
52888
  name: "deviceId",
52365
52889
  form: "single",
@@ -52375,6 +52899,11 @@ Object.freeze({
52375
52899
  form: "single",
52376
52900
  optional: false
52377
52901
  }],
52902
+ "vibration.getStatus": [{
52903
+ name: "deviceId",
52904
+ form: "single",
52905
+ optional: false
52906
+ }],
52378
52907
  "videoclips.dialClipStream": [{
52379
52908
  name: "deviceId",
52380
52909
  form: "single",
@@ -52410,6 +52939,11 @@ Object.freeze({
52410
52939
  form: "single",
52411
52940
  optional: false
52412
52941
  }],
52942
+ "waterHeater.getStatus": [{
52943
+ name: "deviceId",
52944
+ form: "single",
52945
+ optional: false
52946
+ }],
52413
52947
  "waterHeater.setAway": [{
52414
52948
  name: "deviceId",
52415
52949
  form: "single",
@@ -52425,6 +52959,11 @@ Object.freeze({
52425
52959
  form: "single",
52426
52960
  optional: false
52427
52961
  }],
52962
+ "weather.getStatus": [{
52963
+ name: "deviceId",
52964
+ form: "single",
52965
+ optional: false
52966
+ }],
52428
52967
  "webrtcSession.addIceCandidate": [{
52429
52968
  name: "deviceId",
52430
52969
  form: "single",
@@ -53162,7 +53701,7 @@ var PreviewTextField = string().max(200);
53162
53701
  * Whether the notification's preview is a STILL or a short animation.
53163
53702
  *
53164
53703
  * The operator's ask, verbatim: *"inviato come gif o video (come per le altre
53165
- * rule)"* — the other rules already offer an animated preview, and a ten-hour
53704
+ * rule)"* [sent as a gif or video (as for the other rules)] — the other rules already offer an animated preview, and a ten-hour
53166
53705
  * night reads better as three seconds of motion than as one frame of it. Both
53167
53706
  * modes get the SAME treatment (blurred frame, large centred title); `'gif'`
53168
53707
  * simply applies it to a dozen frames sampled across the render and assembles