@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.mjs CHANGED
@@ -7437,7 +7437,7 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
7437
7437
  return DeviceRole;
7438
7438
  }({});
7439
7439
  //#endregion
7440
- //#region ../types/dist/composition-43aqsZQj.mjs
7440
+ //#region ../types/dist/composition-Bzr7GwgP.mjs
7441
7441
  /**
7442
7442
  * The ffmpeg build every CamStack node downloads, per platform and arch.
7443
7443
  *
@@ -7491,20 +7491,20 @@ function portable(target) {
7491
7491
  }
7492
7492
  portable("linux64"), portable("linuxarm64"), portable("macarm64"), portable("mac64");
7493
7493
  /**
7494
- * LA tabella "quale booleano di questo tipo di device conta come ALTO", e il
7495
- * valutatore puro del suo FRONTE.
7494
+ * THE table "which boolean of this device type counts as HIGH", and the
7495
+ * pure evaluator of its EDGE.
7496
7496
  *
7497
- * UNA tabella per tutti quelli che chiedono "questo device è ALTO?": il
7498
- * trigger `RecordingTriggers.sensorDeviceIds` del recorder, i marker dei
7499
- * sensori della post-analysis, il bridge camera-sensors dell'orchestratore e
7500
- * le sorgenti di un campanello composto (`doorbellFeatureSources`, D671).
7501
- * Una seconda copia divergerebbe alla prima cap aggiunta, e il sintomo — "il
7502
- * sensore fa suonare il campanello ma non registra" — è esattamente D62.
7497
+ * ONE table for everyone who asks "is this device HIGH?": the
7498
+ * recorder's `RecordingTriggers.sensorDeviceIds` trigger, the post-analysis
7499
+ * sensor markers, the orchestrator's camera-sensors bridge and
7500
+ * the sources of a composite doorbell (`doorbellFeatureSources`, D671).
7501
+ * A second copy would diverge at the first cap added, and the symptom — "the
7502
+ * sensor rings the doorbell but does not record" — is exactly D62.
7503
7503
  *
7504
- * ⚠ NON è `DEVICE_STATE_READERS` (`catalogs/device-state-vocabulary.ts`), e le
7505
- * due non vanno unificate: quella risponde a "qual è la PAROLA di stato per una
7506
- * regola" (e include `presence`, `cover`, `alarm-panel`), questa a "qual è il
7507
- * booleano il cui FRONTE conta". Vocabolari deliberatamente diversi.
7504
+ * ⚠ NOT `DEVICE_STATE_READERS` (`catalogs/device-state-vocabulary.ts`), and the
7505
+ * two must not be unified: that one answers "what is the state WORD for a
7506
+ * rule" (and includes `presence`, `cover`, `alarm-panel`), this one "which
7507
+ * boolean's EDGE counts". Deliberately different vocabularies.
7508
7508
  */
7509
7509
  /**
7510
7510
  * Known binary / switch source caps → the boolean slice field whose
@@ -7525,6 +7525,8 @@ var SOURCE_CAP_ACTIVE_FIELD = {
7525
7525
  vibration: "detected",
7526
7526
  tamper: "tampered"
7527
7527
  };
7528
+ /** Cap names whose presence in a device's bindings qualify it as a source. */
7529
+ var SOURCE_CAPS = Object.keys(SOURCE_CAP_ACTIVE_FIELD);
7528
7530
  /**
7529
7531
  * Error types for the safe expression engine. Two distinct classes so callers
7530
7532
  * can tell a compile-time (grammar) failure from a runtime (evaluation)
@@ -9131,22 +9133,22 @@ var CLASS_MAP_MACRO_TARGETS = [
9131
9133
  "package"
9132
9134
  ];
9133
9135
  /**
9134
- * Le macro classi di PRIMO LIVELLO: quelle che un object detector emette e che
9135
- * un operatore può selezionare.
9136
+ * The FIRST-LEVEL macro classes: those an object detector emits and that
9137
+ * an operator can select.
9136
9138
  *
9137
- * Sono le tre offerte dallo step `object-detection`
9139
+ * They are the three offered by the `object-detection` step
9138
9140
  * (`addon-pipeline/src/detection-pipeline/registry/step-definitions.ts`,
9139
- * `enabledMacroClasses`). `package` sta in {@link CLASS_MAP_MACRO_TARGETS} e in
9140
- * `MACRO_LABELS` — è una macro vera — ma NON qui: appartiene allo step
9141
- * `package-detection`, la cui abilitazione è guidata dalle zone, e offrire la
9142
- * stessa parola due volte ha già fatto accendere a un operatore il proxy COCO
9141
+ * `enabledMacroClasses`). `package` is in {@link CLASS_MAP_MACRO_TARGETS} and in
9142
+ * `MACRO_LABELS` — it is a true macro — but NOT here: it belongs to the step
9143
+ * `package-detection`, whose enablement is driven by zones, and offering the
9144
+ * same word twice has already made an operator turn on the COCO proxy
9143
9145
  * (suitcase/backpack/handbag) lasciando spento il detector dedicato.
9144
9146
  *
9145
- * UNA lista. Prima di oggi le stesse tre erano scritte a mano nell'offerta
9146
- * dello step e una seconda volta come union `FirstLevelMacro`
9147
- * (`types/detection.ts`); una terza copia per il trigger di registrazione
9148
- * (`RecordingTriggers.objectClasses`) avrebbe reso invisibile la divergenza
9149
- * successiva.
9147
+ * ONE list. Before today the same three were hand-written in the step's offer
9148
+ * and a second time as the union `FirstLevelMacro`
9149
+ * (`types/detection.ts`); a third copy for the recording trigger
9150
+ * (`RecordingTriggers.objectClasses`) would have made the later divergence
9151
+ * invisible.
9150
9152
  */
9151
9153
  var FIRST_LEVEL_MACRO_CLASSES = [
9152
9154
  "person",
@@ -9211,17 +9213,17 @@ var RecordingStorageModeSchema = _enum([
9211
9213
  "on-device-decision"
9212
9214
  ]);
9213
9215
  /**
9214
- * Le macro classi che possono aprire una finestra di registrazione — le stesse
9215
- * tre offerte dallo step `object-detection`, da UNA lista
9216
+ * The macro classes that can open a recording window — the same
9217
+ * three offered by the `object-detection` step, from ONE list
9216
9218
  * ({@link FIRST_LEVEL_MACRO_CLASSES}).
9217
9219
  */
9218
9220
  var RecordingObjectTriggerClassSchema = _enum(FIRST_LEVEL_MACRO_CLASSES);
9219
9221
  /**
9220
- * True quando `values` non ripete un elemento.
9222
+ * True when `values` does not repeat an element.
9221
9223
  *
9222
- * Un duplicato non è innocuo: ogni voce di `objectClasses` / `sensorDeviceIds`
9223
- * diventa una SORGENTE in `bandTriggerSources`, e la stessa sorgente due volte
9224
- * conterebbe due volte le sue finestre in `segmentMissedByMs`.
9224
+ * A duplicate is not harmless: every entry of `objectClasses` / `sensorDeviceIds`
9225
+ * becomes a SOURCE in `bandTriggerSources`, and the same source twice
9226
+ * would count its windows twice in `segmentMissedByMs`.
9225
9227
  */
9226
9228
  var noDuplicates = (values) => new Set(values).size === values.length;
9227
9229
  /** Which detectors trigger an `events`-mode band. */
@@ -9229,34 +9231,34 @@ var RecordingTriggersSchema = object({
9229
9231
  motion: boolean().optional(),
9230
9232
  audioThresholdDbfs: number().optional(),
9231
9233
  /**
9232
- * Le macro classi la cui detection apre una finestra. ASSENTE = la sorgente
9233
- * non è ascoltata; un array VUOTO è rifiutato, perché "banda events, trigger
9234
- * object acceso, nessuna classe" è la stessa forma "abilitata e non registra
9235
- * nulla, per sempre" contro cui è scritto `eventsBandCanEverDemand`.
9234
+ * The macro classes whose detection opens a window. ABSENT = the source
9235
+ * is not listened to; an EMPTY array is rejected, because "events band, object
9236
+ * trigger on, no class" is the same shape "enabled and records
9237
+ * nothing, forever" that `eventsBandCanEverDemand` is written against.
9236
9238
  *
9237
- * Il segnale letto è GIÀ FILTRATO: solo detection `source: 'pipeline'`, cioè
9238
- * quelle che hanno attraversato `enabledMacroClasses`, i
9239
- * `minConfidence<Macro>` e il full-frame guard. L'AI a bordo camera
9240
- * (`source: 'onboard'`) non attraversa nessuno di quei gate e NON apre
9241
- * finestre — vedi `recorder/object-trigger.ts`.
9239
+ * The signal read is ALREADY FILTERED: only `source: 'pipeline'` detections, i.e.
9240
+ * those that went through `enabledMacroClasses`, the
9241
+ * `minConfidence<Macro>` and the full-frame guard. The camera's onboard AI
9242
+ * (`source: 'onboard'`) goes through none of those gates and does NOT open
9243
+ * windows — see `recorder/object-trigger.ts`.
9242
9244
  */
9243
9245
  objectClasses: array(RecordingObjectTriggerClassSchema).min(1).refine(noDuplicates, { message: "objectClasses must not repeat a class" }).optional(),
9244
9246
  /**
9245
- * I device LINKED il cui FRONTE ALTO apre una finestra. Assente = la sorgente
9246
- * non è ascoltata; un array vuoto è rifiutato per la stessa ragione di
9247
+ * The LINKED devices whose RISING EDGE opens a window. Absent = the source
9248
+ * is not listened to; an empty array is rejected for the same reason as
9247
9249
  * `objectClasses`.
9248
9250
  *
9249
- * Sono id di device SORGENTE, non camere: la banda li nomina, quindi il
9250
- * percorso caldo (`DeviceStateChanged`, a ritmo di bus su tutta la flotta)
9251
- * non fa RPC. L'OFFERTA da cui l'operatore li sceglie è un'altra domanda, e
9252
- * si risolve con `deviceManager.getLinkedDevices` + `getBindingsBatch` per
9253
- * device (D12) — mai un elenco globale di cap.
9251
+ * These are SOURCE device ids, not cameras: the band names them, so the
9252
+ * hot path (`DeviceStateChanged`, at bus rate across the whole fleet)
9253
+ * does no RPC. The OFFER from which the operator picks them is another question, and
9254
+ * is resolved with `deviceManager.getLinkedDevices` + `getBindingsBatch` per
9255
+ * device (D12) — never a global list of caps.
9254
9256
  *
9255
- * Cosa vuol dire "alto" dipende dal TIPO di device e non è deciso qui:
9256
- * `SOURCE_CAP_ACTIVE_FIELD` (`catalogs/sensor-active-state.ts`) è LA tabella,
9257
- * la stessa del campanello composto (D671). Ed è il FRONTE, non
9258
- * il livello: un contatto trovato già aperto al riavvio del runner non fa
9259
- * registrare.
9257
+ * What "high" means depends on the device TYPE and is not decided here:
9258
+ * `SOURCE_CAP_ACTIVE_FIELD` (`catalogs/sensor-active-state.ts`) is THE table,
9259
+ * the same one as the composite doorbell (D671). And it is the EDGE, not
9260
+ * the level: a contact found already open at runner restart does not
9261
+ * record.
9260
9262
  */
9261
9263
  sensorDeviceIds: array(number().int().positive()).min(1).max(16).refine(noDuplicates, { message: "sensorDeviceIds must not repeat a device" }).optional()
9262
9264
  });
@@ -10508,7 +10510,7 @@ function findTimezone(id) {
10508
10510
  * - **VALUE** — at which level, for which scope, until when. That stays ONE
10509
10511
  * thing: the logging settings document on the `system` cap. Two authorities
10510
10512
  * over the values is the exact defect
10511
- * `docs/design/plans/2026-08-26-logging-per-componente.md` was written to
10513
+ * `docs/design/plans/2026-08-26-per-component-logging.md` was written to
10512
10514
  * remove; re-introducing it from the cure side would be grotesque.
10513
10515
  *
10514
10516
  * Nothing in this file reads a clock, an env var or a store. The registry is
@@ -12325,7 +12327,7 @@ var BrokerStatusEnum = _enum([
12325
12327
  "unreachable",
12326
12328
  "error"
12327
12329
  ]);
12328
- var BrokerInfoSchema$1 = object({
12330
+ var BrokerInfoSchema = object({
12329
12331
  /** Stable broker id. Persisted; survives addon restarts. */
12330
12332
  id: string(),
12331
12333
  /** Addon id of the provider that OWNS this broker.
@@ -12458,7 +12460,7 @@ var GetStateInputSchema = object({
12458
12460
  * HA: entity_id (returns the cached entity state). */
12459
12461
  key: string()
12460
12462
  });
12461
- method(ListInputSchema, array(BrokerInfoSchema$1)), method(GetInputSchema, BrokerInfoSchema$1.nullable()), method(_void(), array(BrokerProviderInfoSchema), { auth: "admin" }), method(AddInputSchema, AddResultSchema, {
12463
+ method(ListInputSchema, array(BrokerInfoSchema)), method(GetInputSchema, BrokerInfoSchema.nullable()), method(_void(), array(BrokerProviderInfoSchema), { auth: "admin" }), method(AddInputSchema, AddResultSchema, {
12462
12464
  kind: "mutation",
12463
12465
  auth: "admin"
12464
12466
  }), method(RemoveInputSchema, _void(), {
@@ -14169,7 +14171,7 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
14169
14171
  *
14170
14172
  * ⚠ An earlier version of this comment blamed Zod stripping, and that
14171
14173
  * was wrong — corrected 2026-08-26 after the hop map
14172
- * (`docs/design/2026-08-26-mappa-hop-argomenti.md`) traced the path.
14174
+ * (`docs/design/2026-08-26-topic-hop-map.md`) traced the path.
14173
14175
  * There is **no Zod parse at all** between the door and the engine: the
14174
14176
  * dispatcher forwards the payload verbatim and UDS carries it whole. A
14175
14177
  * field declared here reaches `SqliteSettingsBackend` either way.
@@ -15145,7 +15147,17 @@ var SiteZoneSchema = object({
15145
15147
  var ProviderStatusSchema = object({
15146
15148
  connected: boolean(),
15147
15149
  deviceCount: number(),
15148
- error: string().optional()
15150
+ error: string().optional(),
15151
+ /**
15152
+ * `'orchestrator'`: this provider writes NO camera's `motion` runtime slice
15153
+ * — the orchestrator is its only writer (D696). Set by `BaseDeviceProvider`,
15154
+ * which every provider bundles, so only a provider BUILT from D696-amended
15155
+ * code says it. ABSENT means an older provider that may still write it (raw
15156
+ * VMD writes, a boot seed), and the orchestrator's provider gate keeps that
15157
+ * provider's cameras unwritten (`camera-sensors/motion-slice-provider-gate.ts`)
15158
+ * — the provider twin of the runner's `getLocalLoad().motionSliceWriter`.
15159
+ */
15160
+ motionSliceWriter: literal("orchestrator").optional()
15149
15161
  });
15150
15162
  object({
15151
15163
  externalId: string(),
@@ -16362,7 +16374,7 @@ method(object({
16362
16374
  * per-device window, `KeyFrameCaptureLog`, `bumpCropMetric`. Every one of them
16363
16375
  * ends in a log line, and a log line is the thing the operator asked to stop
16364
16376
  * needing: *"possiamo armare questi errori intanto? Così al prossimo giro
16365
- * ricontrolliamo tutti questi punti"*. Reading them meant grepping Loki and
16377
+ * 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
16366
16378
  * hand-correlating timestamps, which is how a 22% thumbnail gap and a 3-hour
16367
16379
  * media blackout were both diagnosed. The counters stay; this is where they can
16368
16380
  * be READ.
@@ -17757,7 +17769,7 @@ var BrokerStatusSchema$1 = _enum([
17757
17769
  "unreachable",
17758
17770
  "tls-error"
17759
17771
  ]);
17760
- var BrokerInfoSchema = object({
17772
+ var BrokerInfoSchema$1 = object({
17761
17773
  id: string(),
17762
17774
  name: string(),
17763
17775
  url: string(),
@@ -17820,7 +17832,7 @@ var StatusSchema = object({
17820
17832
  brokerCount: number(),
17821
17833
  embeddedRunning: boolean()
17822
17834
  });
17823
- method(_void(), array(BrokerInfoSchema)), method(IdInputSchema, BrokerConnectionDetailsSchema, { auth: "admin" }), method(AddBrokerInputSchema, AddBrokerResultSchema, {
17835
+ method(_void(), array(BrokerInfoSchema$1)), method(IdInputSchema, BrokerConnectionDetailsSchema, { auth: "admin" }), method(AddBrokerInputSchema, AddBrokerResultSchema, {
17824
17836
  kind: "mutation",
17825
17837
  auth: "admin"
17826
17838
  }), method(IdInputSchema, _void(), {
@@ -20034,78 +20046,16 @@ var NcRuleInputSchema = object({
20034
20046
  */
20035
20047
  confirm: NcConfirmSchema.optional(),
20036
20048
  /**
20037
- * WAIT for face/plate recognition before saying anything.
20038
- *
20039
- * A notification's TEXT is frozen at enqueue and its media is re-resolved at
20040
- * send; the identity is neither. A face is confirmed after `confirmFrames`
20041
- * agreeing observations — p50 **11.4 s** after the track was first seen,
20042
- * measured on this hub — and an `immediate` rule enqueues on the first object
20043
- * event, seconds before that. So "Gianluca è arrivato" is unsayable on the
20044
- * immediate path, and no amount of media re-resolution fixes a sentence.
20045
- *
20046
- * Only two honest answers exist, and this flag picks between them. It has
20047
- * effect ONLY on a rule that declares a recognition scope
20048
- * ({@link NcConditions.identities} or {@link NcConditions.plates}) — on any
20049
- * other rule there is nothing to wait for and the flag is inert.
20050
- *
20051
- * | value | what happens |
20052
- * | --- | --- |
20053
- * | `true` | the rule stops firing on the object event and fires at TRACK CLOSE instead, once, with the name — later, and complete |
20054
- * | 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) |
20055
- *
20056
- * `.optional()` and deliberately NOT `.default()`: a Zod default does not run
20057
- * on the addon cap path, and absent has to keep meaning exactly what every
20058
- * rule authored before this field meant.
20059
- *
20060
- * The cost of `true` is stated here because the editor states it too: a rule
20061
- * that waits also inherits track-close SEMANTICS — its `zones` condition
20062
- * tests every zone the track visited and a `crossing` condition can no longer
20063
- * be satisfied, because a closed track carries no crossing.
20064
- */
20065
- waitForEnhancement: boolean().optional(),
20066
- /**
20067
- * GROUP a burst of subjects into ONE notification that grows.
20068
- *
20069
- * Seconds of quiet after the last matching subject before the burst is
20070
- * considered over. While it is open, the first subject enqueues immediately —
20071
- * **exactly as today, with no added latency** — and every real growth (a new
20072
- * subject, or a name confirmed on one already in it) REPLACES that
20073
- * notification with an updated one naming everybody. The push carries the
20074
- * group's own coalescing tag, so the phone replaces rather than stacks.
20075
- *
20076
- * `0` / absent = off, and off is today's behaviour byte for byte.
20077
- *
20078
- * ### Why an idle cutoff and not a window
20079
- *
20080
- * The measured seven-person arrival on device 590 spans 110 s with every
20081
- * internal gap under 30 s. A 12 s fixed window cuts it into three groups; an
20082
- * idle cutoff holds it as one and ends it when the arrival actually ends.
20083
- * 30 s is a widely shipped value for the same decision.
20084
- *
20085
- * ### What it replaces
20086
- *
20087
- * The blind cooldown, which collapses a burst by DISCARDING it. Measured on
20088
- * device 615 / *Persona su Uscio* over six days: 116 qualifying tracks → 74
20089
- * notifications, **44 (37.9%) suppressed outright**, 23 of them overlapping a
20090
- * track that did fire and 7 carrying a confirmed identity nobody heard about.
20091
- * A group collapses the same volume by MERGING, so the cooldown becomes a
20092
- * budget over GROUPS — which is what it always meant — and a growth is never
20093
- * throttled by the window its own first member spent.
20094
- *
20095
- * ### Interaction with {@link waitForEnhancement}
20096
- *
20097
- * They compose, and the order matters. `waitForEnhancement` defers the rule to
20098
- * TRACK CLOSE, so with both set the group is opened by the first member to
20099
- * CLOSE — already carrying its name — and grows as later members close. That
20100
- * is later, and complete. With grouping alone the group opens on the first
20101
- * object event and picks up names as they are confirmed, through the growth
20102
- * path. Neither combination fires twice for one subject.
20103
- *
20104
- * `.optional()` and deliberately NOT `.default()`: a Zod default does not run
20105
- * on the addon cap path, so absent must keep meaning what it meant before this
20106
- * field existed.
20049
+ * IMMEDIATE GROUPED (D692): the first matching subject opens a window of this many
20050
+ * seconds; the rule sends ONE message when the window closes — early, once every
20051
+ * subject in it is final, never before {@link NC_GROUPING_MIN_SEC} — naming everybody
20052
+ * the rule matched, with one mosaic tile per subject.
20053
+ * Absent = plain immediate (one message per track, at the first match).
20054
+ * Only an `immediate` DETECTION rule may carry it (`ruleGroupingApplies`, enforced on
20055
+ * save by the hub's grouping guard). `.optional()`, never `.default()`: the addon cap
20056
+ * path does not run Zod defaults.
20107
20057
  */
20108
- groupIdleSec: number().int().min(0).max(600).optional()
20058
+ groupingSec: number().int().min(5).max(60).optional()
20109
20059
  });
20110
20060
  /**
20111
20061
  * Partial patch for `updateRule` — any subset of the input fields, plus the
@@ -20153,9 +20103,10 @@ var NcRuleClearableKeySchema = _enum([
20153
20103
  "targetUsers",
20154
20104
  "snoozeOptions",
20155
20105
  "snoozeAllowGlobal",
20156
- "waitForEnhancement",
20157
20106
  "actions",
20158
20107
  "confirm",
20108
+ "groupingSec",
20109
+ "waitForEnhancement",
20159
20110
  "groupIdleSec"
20160
20111
  ]);
20161
20112
  var NcRuleUpdateInputSchema = object({
@@ -20177,9 +20128,25 @@ var NcRuleSchema = NcRuleInputSchema.extend({
20177
20128
  */
20178
20129
  disabledTargetIds: array(string()).default([])
20179
20130
  });
20131
+ /**
20132
+ * The state-summary SECTIONS (D647 / D698): the D637 kind groups that report a
20133
+ * still-true state. `backups-exports` and `alarm` are not sections — a completed
20134
+ * job is not an open state, and the alarm stays instant.
20135
+ */
20136
+ var NcStateSummarySectionIdSchema = _enum([
20137
+ "device-state",
20138
+ "streams",
20139
+ "battery",
20140
+ "consumables",
20141
+ "tanks",
20142
+ "detection-blind",
20143
+ "nodes",
20144
+ "addons",
20145
+ "updates"
20146
+ ]);
20180
20147
  /** One section of a previewed state summary. `unavailable` = its state could not be read. */
20181
20148
  var NcStateSummaryPreviewSectionSchema = object({
20182
- id: string(),
20149
+ id: NcStateSummarySectionIdSchema,
20183
20150
  status: _enum(["read", "unavailable"]),
20184
20151
  items: number().int().nonnegative(),
20185
20152
  reason: string().optional()
@@ -20189,7 +20156,7 @@ var NcStateSummaryPreviewSectionSchema = object({
20189
20156
  * a `rule` split (no `section`), one section's on a `section` split.
20190
20157
  */
20191
20158
  var NcStateSummaryPreviewRowSchema = object({
20192
- section: string().optional(),
20159
+ section: NcStateSummarySectionIdSchema.optional(),
20193
20160
  /** The section's name on a per-section row; every reported section's, joined, on a combined one. */
20194
20161
  title: string(),
20195
20162
  text: string(),
@@ -20626,6 +20593,29 @@ object({
20626
20593
  firstAt: number(),
20627
20594
  lastAt: number()
20628
20595
  });
20596
+ var NC_ALARM_TRIGGERED_MAX_SEC = 3600;
20597
+ var NcAlarmDelaySecSchema = number().int().min(0).max(600);
20598
+ var NcAlarmTriggeredSecSchema = number().int().min(0).max(NC_ALARM_TRIGGERED_MAX_SEC);
20599
+ var uniqueModes = (entries) => new Set(entries.map((e) => e.mode)).size === entries.length;
20600
+ var NcAlarmModeDelaysListSchema = array(object({
20601
+ mode: AlarmArmModeSchema,
20602
+ exitDelaySec: NcAlarmDelaySecSchema.optional(),
20603
+ entryDelaySec: NcAlarmDelaySecSchema.optional(),
20604
+ triggeredDurationSec: NcAlarmTriggeredSecSchema.optional()
20605
+ })).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
20606
+ var NcAlarmModeDelaysEditListSchema = array(object({
20607
+ mode: AlarmArmModeSchema,
20608
+ exitDelaySec: NcAlarmDelaySecSchema.nullable().optional(),
20609
+ entryDelaySec: NcAlarmDelaySecSchema.nullable().optional(),
20610
+ triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional()
20611
+ })).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
20612
+ /** One switch of the alarm table: put ONE device on, or take it off, ONE mode's list. */
20613
+ var NcAlarmNonBlockingEditSchema = object({
20614
+ mode: AlarmArmModeSchema,
20615
+ deviceId: number().int().positive(),
20616
+ /** true = on the list (may be open, does not block); false = off the list (blocks). */
20617
+ nonBlocking: boolean()
20618
+ });
20629
20619
  /**
20630
20620
  * The per-mode lists, at most one per mode. Two lists for one mode have no
20631
20621
  * meaning a reader could agree on (union? the last one?), so they are refused
@@ -20634,10 +20624,10 @@ object({
20634
20624
  var NcAlarmNonBlockingListSchema = array(object({
20635
20625
  mode: AlarmArmModeSchema,
20636
20626
  deviceIds: array(number().int()).max(200)
20637
- })).max(8).refine((lists) => new Set(lists.map((l) => l.mode)).size === lists.length, { message: "nonBlocking: at most one list per arm mode" });
20627
+ })).max(8).refine(uniqueModes, { message: "nonBlocking: at most one list per arm mode" });
20638
20628
  /**
20639
- * The three durations the panel's state machine runs on, who hears about its
20640
- * transitions, and which openings each mode tolerates.
20629
+ * The three durations — global, and per mode since D697 — the panel's state
20630
+ * machine runs on, who hears about its transitions, and which openings each mode tolerates.
20641
20631
  *
20642
20632
  * They live on the NOTIFICATION-RULES cap, not on `alarm-panel`, on purpose:
20643
20633
  * `alarm-panel` is `deviceNative` and its other provider mirrors somebody
@@ -20647,15 +20637,15 @@ var NcAlarmNonBlockingListSchema = array(object({
20647
20637
  */
20648
20638
  var NcAlarmSettingsSchema = object({
20649
20639
  /** Grace period between arming and the mode taking effect. 0 = immediate. */
20650
- exitDelaySec: number().int().min(0).max(600),
20640
+ exitDelaySec: NcAlarmDelaySecSchema,
20651
20641
  /** Grace period between a trigger and the alarm firing. 0 = immediate. */
20652
- entryDelaySec: number().int().min(0).max(600),
20642
+ entryDelaySec: NcAlarmDelaySecSchema,
20653
20643
  /**
20654
20644
  * How long `triggered` lasts before the panel re-arms itself.
20655
20645
  * **0 = until an operator disarms it** — the behaviour before this field
20656
20646
  * existed, and therefore what an untouched install keeps doing.
20657
20647
  */
20658
- triggeredDurationSec: number().int().min(0).max(3600),
20648
+ triggeredDurationSec: NcAlarmTriggeredSecSchema,
20659
20649
  /**
20660
20650
  * Deprecated by D630 — every transition is announced. Parsed, never read;
20661
20651
  * remove after one release. Optional so an older admin's patch (which still
@@ -20678,17 +20668,30 @@ var NcAlarmSettingsSchema = object({
20678
20668
  * per mode is meaningful. Defaulted to `[]` so a blob stored before D630
20679
20669
  * parses as "every opening blocks" — the behaviour it was written under.
20680
20670
  */
20681
- nonBlocking: NcAlarmNonBlockingListSchema.default([])
20671
+ nonBlocking: NcAlarmNonBlockingListSchema.default([]),
20672
+ /**
20673
+ * Per arm mode, the delays that mode OVERRIDES (D697). A mode with no entry, or an entry
20674
+ * without a field, uses the global value above — so `[]`, the default, is exactly the
20675
+ * behaviour of a blob stored before this field existed. Read through `resolveModeDelays`.
20676
+ */
20677
+ modeDelays: NcAlarmModeDelaysListSchema.default([])
20682
20678
  });
20683
20679
  /**
20684
20680
  * Every field optional — a tab edits one control at a time.
20685
20681
  *
20686
- * `nonBlocking` is re-declared WITHOUT its default: `.partial()` does not
20687
- * remove an inner `.default()`, so a patch that never named the field would
20688
- * parse to `nonBlocking: []` and wipe every mode's list on an unrelated edit
20689
- * (the same trap {@link NcRulePatchSchema} documents).
20682
+ * `nonBlocking` and `modeDelays` are re-declared WITHOUT their defaults:
20683
+ * `.partial()` does not remove an inner `.default()`, so a patch that never
20684
+ * named the field would parse to `[]` and wipe every mode's list on an
20685
+ * unrelated edit (the same trap {@link NcRulePatchSchema} documents). Here
20686
+ * `modeDelays` means EDITS, not the stored overrides.
20690
20687
  */
20691
- var NcAlarmSettingsPatchSchema = NcAlarmSettingsSchema.extend({ nonBlocking: NcAlarmNonBlockingListSchema }).partial();
20688
+ var NcAlarmSettingsPatchSchema = NcAlarmSettingsSchema.extend({
20689
+ nonBlocking: NcAlarmNonBlockingListSchema,
20690
+ /** Per-mode, per-field edits — NOT the whole list (see NcAlarmModeDelaysEditSchema). */
20691
+ modeDelays: NcAlarmModeDelaysEditListSchema,
20692
+ /** ONE membership change; the panel applies it to the list it holds at its turn. */
20693
+ nonBlockingEdit: NcAlarmNonBlockingEditSchema
20694
+ }).partial().refine((p) => p.nonBlocking === void 0 || p.nonBlockingEdit === void 0, { message: "nonBlocking and nonBlockingEdit are exclusive — send the whole lists or one edit" });
20692
20695
  /**
20693
20696
  * What one arm mode actually arms, DERIVED from the enabled rules gated on it.
20694
20697
  * Never authored, never stored — see `alarm-mode-coverage.ts` for why a stored
@@ -20788,6 +20791,28 @@ var NcAlarmConfigSchema = object({
20788
20791
  */
20789
20792
  live: NcAlarmLiveSchema.optional()
20790
20793
  });
20794
+ var NcAlarmSensorReadingSchema = _enum([
20795
+ "open",
20796
+ "closed",
20797
+ "unknown",
20798
+ "not-opening"
20799
+ ]);
20800
+ /** One device's state as the alarm reads it — the classifier the arm check uses. */
20801
+ var NcAlarmSensorStateSchema = object({
20802
+ deviceId: number().int().positive(),
20803
+ reading: NcAlarmSensorReadingSchema,
20804
+ /** The word as read (`open`, `closed`, `unlocked`, `stopped`, …); null when unknown / not an opening. */
20805
+ state: string().nullable(),
20806
+ /** Why `unknown`: the read failed, or the slice holds no word its cap defines (a placeholder included). */
20807
+ unknownWhy: _enum(["read-failed", "unknown-word"]).nullable(),
20808
+ /** The device manager's liveness as the centre mirrors it; null = not known. */
20809
+ online: boolean().nullable()
20810
+ });
20811
+ var NcAlarmSensorsInputSchema = object({ deviceIds: array(number().int().positive()).max(500) });
20812
+ var NcAlarmSensorsSchema = object({
20813
+ sensors: array(NcAlarmSensorStateSchema),
20814
+ readAt: number().int().nonnegative()
20815
+ });
20791
20816
  /**
20792
20817
  * ONE rule's demand on ONE camera's clip ring.
20793
20818
  *
@@ -20878,7 +20903,7 @@ method(object({}), object({ rules: array(NcRuleSchema) }), { auth: "admin" }), m
20878
20903
  }), method(object({}), NcAlarmConfigSchema, { auth: "admin" }), method(object({ patch: NcAlarmSettingsPatchSchema }), NcAlarmConfigSchema, {
20879
20904
  kind: "mutation",
20880
20905
  auth: "admin"
20881
- });
20906
+ }), method(NcAlarmSensorsInputSchema, NcAlarmSensorsSchema, { auth: "admin" });
20882
20907
  /**
20883
20908
  * Zod schemas for persisted record types.
20884
20909
  *
@@ -22030,14 +22055,14 @@ var TrackSchema = object({
22030
22055
  * `derive-returned-null tile=standin`,
22031
22056
  * `native-tile tile=native no-key-frame-at-close`, …) written at close and
22032
22057
  * CLEARED by the late-keyFrame upgrade when a native tile lands after all.
22033
- * The operator-facing answer to "perché manca l'immagine?" on a track whose
22058
+ * The operator-facing answer to "perché manca l'immagine?" [why is the image missing?] on a track whose
22034
22059
  * tile is a face/plate stand-in, a raster crop, or an icon.
22035
22060
  *
22036
22061
  * **`no-key-frame-at-close` (D400).** The line used to be written ONLY when
22037
22062
  * the TILE ranked below native, so a track whose thumbnail landed natively
22038
22063
  * while its key frame missed carried no reason at all — three of the four
22039
22064
  * `MISSING_KEYFRAME` tracks in the 2026-09-07 operator audit were exactly
22040
- * that shape, and their "niente ultimo" had no cause anywhere on the row.
22065
+ * that shape, and their "niente ultimo" [no last frame] had no cause anywhere on the row.
22041
22066
  * The key frame is the head of a cascade (`keyFrame ⇒ keyFrameSmall ⇒ the
22042
22067
  * lastFrame copy source`), so its absence is now on this line whatever the
22043
22068
  * tile ended up being.
@@ -22124,7 +22149,7 @@ var MotionEventSchema = object({
22124
22149
  /**
22125
22150
  * Ms offsets from `timestamp` (the episode's own first rising edge, so the
22126
22151
  * first entry is always `0`) of every genuine off→on transition the
22127
- * episode saw — "ogni evento on si deve salvare" (D475). NOT one entry per
22152
+ * episode saw — "ogni evento on si deve salvare" [every ON event must be saved] (D475). NOT one entry per
22128
22153
  * push: a firmware source that keepalives at ~1 Hz for the whole burst
22129
22154
  * (Reolink, Hikvision) produces exactly one edge; a source that reports an
22130
22155
  * explicit `false` mid-episode and then resumes before the quiet window
@@ -22648,6 +22673,7 @@ var KeyEventSchema = object({
22648
22673
  bestEventId: string(),
22649
22674
  /** Track lifetime in ms (lastSeen - firstSeen). */
22650
22675
  windowMs: number().optional(),
22676
+ audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
22651
22677
  ...TrackFlagFields,
22652
22678
  ...TrackRetrainFields
22653
22679
  });
@@ -27581,7 +27607,7 @@ var ClipPlaybackSchema = object({
27581
27607
  * **One authorised yes is one wake.** `next-natural` — take the clip the next
27582
27608
  * time the camera is awake for its own reasons — is deliberately not a member:
27583
27609
  * it was proposed, it is free on the battery, and the operator declined it on
27584
- * 2026-09-20 (*"Quando un export viene richiesto si sveglia la camera."*,
27610
+ * 2026-09-20 (*"Quando un export viene richiesto si sveglia la camera."* [When an export is requested the camera wakes up],
27585
27611
  * D558 "Considered and not taken").
27586
27612
  */
27587
27613
  var ClipWakeSchema = _enum(["authorised"]);
@@ -27977,7 +28003,7 @@ var videoclipsCapability = {
27977
28003
  * **It is a SECTION of the Recording tab, at the end of it — not a tab of
27978
28004
  * its own.** It shipped as a `clips` top-tab and the operator rejected the
27979
28005
  * placement: *"utilizzerei la stessa tab recordings, lì abbiamo già tutto il
27980
- * necessario, una nuova sezione alla fine per le clips"*. The Recording tab
28006
+ * 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
27981
28007
  * already holds the recorder's panel, the schedule bands and the unified
27982
28008
  * retention policy; footage the camera itself holds is the same question,
27983
28009
  * asked of a different store. `order: 100` puts it after all of them with
@@ -28038,7 +28064,7 @@ var videoclipsCapability = {
28038
28064
  * It replaced `sources?: string[]`, a VIEW filter over source ids that
28039
28065
  * assumed the answer was a fan-out over everything a camera has. The
28040
28066
  * operator settled otherwise on 2026-09-20 — *"l'utilizzatore è uno
28041
- * solo"* — so the list is asked of one provider at a time and there is
28067
+ * solo"* [there is only one user] — so the list is asked of one provider at a time and there is
28042
28068
  * nothing to filter out of it.
28043
28069
  */
28044
28070
  provider: string().min(1)
@@ -36385,7 +36411,7 @@ var ReadGopBytesResultSchema = object({
36385
36411
  /**
36386
36412
  * A time WINDOW of one finalized segment, cut by byte range — the multi-GOP
36387
36413
  * twin of {@link ReadGopBytesResultSchema}'s single instant. Built for the
36388
- * replay clip's `recording` source (`docs/design/plans/2026-08-26-replay-clip-su-pipeline.md`):
36414
+ * replay clip's `recording` source (`docs/design/plans/2026-08-26-clip-replay-on-pipeline.md`):
36389
36415
  * a replay needs several seconds of native pixels, not one frame.
36390
36416
  *
36391
36417
  * `ok.data` is standalone-demuxable, same as a GOP read. `ok.reachesRequestedEnd`
@@ -40127,6 +40153,7 @@ var zoneRulesCapability = {
40127
40153
  */
40128
40154
  durability: "restored"
40129
40155
  };
40156
+ SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
40130
40157
  /**
40131
40158
  * Accessory device helpers — shared across drivers.
40132
40159
  *
@@ -41201,13 +41228,14 @@ var BaseDeviceProvider = class extends BaseAddon {
41201
41228
  async getStatus() {
41202
41229
  const all = await this.ctx.kernel.devices?.getAll() ?? [];
41203
41230
  const summary = this.restoreFailureSummary();
41204
- if (summary === null) return {
41231
+ const base = {
41205
41232
  connected: true,
41206
- deviceCount: all.length
41233
+ deviceCount: all.length,
41234
+ motionSliceWriter: "orchestrator"
41207
41235
  };
41236
+ if (summary === null) return base;
41208
41237
  return {
41209
- connected: true,
41210
- deviceCount: all.length,
41238
+ ...base,
41211
41239
  error: summary
41212
41240
  };
41213
41241
  }
@@ -46861,6 +46889,12 @@ Object.freeze({
46861
46889
  addonId: null,
46862
46890
  access: "view"
46863
46891
  },
46892
+ "notificationRules.getAlarmSensors": {
46893
+ capName: "notification-rules",
46894
+ capScope: "system",
46895
+ addonId: null,
46896
+ access: "view"
46897
+ },
46864
46898
  "notificationRules.getClipRetentionAsks": {
46865
46899
  capName: "notification-rules",
46866
46900
  capScope: "system",
@@ -50439,6 +50473,11 @@ Object.freeze({
50439
50473
  }
50440
50474
  });
50441
50475
  Object.freeze({
50476
+ "accessories.getStatus": [{
50477
+ name: "deviceId",
50478
+ form: "single",
50479
+ optional: false
50480
+ }],
50442
50481
  "accessories.setChildHidden": [{
50443
50482
  name: "childDeviceId",
50444
50483
  form: "single",
@@ -50458,6 +50497,11 @@ Object.freeze({
50458
50497
  form: "single",
50459
50498
  optional: false
50460
50499
  }],
50500
+ "airQualitySensor.getStatus": [{
50501
+ name: "deviceId",
50502
+ form: "single",
50503
+ optional: false
50504
+ }],
50461
50505
  "alarmPanel.arm": [{
50462
50506
  name: "deviceId",
50463
50507
  form: "single",
@@ -50468,11 +50512,36 @@ Object.freeze({
50468
50512
  form: "single",
50469
50513
  optional: false
50470
50514
  }],
50515
+ "alarmPanel.getStatus": [{
50516
+ name: "deviceId",
50517
+ form: "single",
50518
+ optional: false
50519
+ }],
50471
50520
  "alarmPanel.trigger": [{
50472
50521
  name: "deviceId",
50473
50522
  form: "single",
50474
50523
  optional: false
50475
50524
  }],
50525
+ "ambientLightSensor.getStatus": [{
50526
+ name: "deviceId",
50527
+ form: "single",
50528
+ optional: false
50529
+ }],
50530
+ "audioAnalysis.applyDeviceSettingsPatch": [{
50531
+ name: "deviceId",
50532
+ form: "single",
50533
+ optional: false
50534
+ }],
50535
+ "audioAnalysis.getDeviceLiveContribution": [{
50536
+ name: "deviceId",
50537
+ form: "single",
50538
+ optional: false
50539
+ }],
50540
+ "audioAnalysis.getDeviceSettingsContribution": [{
50541
+ name: "deviceId",
50542
+ form: "single",
50543
+ optional: false
50544
+ }],
50476
50545
  "audioAnalysis.resolveDeviceSettings": [{
50477
50546
  name: "deviceId",
50478
50547
  form: "single",
@@ -50513,16 +50582,36 @@ Object.freeze({
50513
50582
  form: "single",
50514
50583
  optional: false
50515
50584
  }],
50585
+ "automationControl.getStatus": [{
50586
+ name: "deviceId",
50587
+ form: "single",
50588
+ optional: false
50589
+ }],
50516
50590
  "automationControl.trigger": [{
50517
50591
  name: "deviceId",
50518
50592
  form: "single",
50519
50593
  optional: false
50520
50594
  }],
50595
+ "battery.getStatus": [{
50596
+ name: "deviceId",
50597
+ form: "single",
50598
+ optional: false
50599
+ }],
50521
50600
  "battery.wakeForStream": [{
50522
50601
  name: "deviceId",
50523
50602
  form: "single",
50524
50603
  optional: false
50525
50604
  }],
50605
+ "binary.getStatus": [{
50606
+ name: "deviceId",
50607
+ form: "single",
50608
+ optional: false
50609
+ }],
50610
+ "brightness.getStatus": [{
50611
+ name: "deviceId",
50612
+ form: "single",
50613
+ optional: false
50614
+ }],
50526
50615
  "brightness.setBrightness": [{
50527
50616
  name: "deviceId",
50528
50617
  form: "single",
@@ -50538,6 +50627,26 @@ Object.freeze({
50538
50627
  form: "single",
50539
50628
  optional: false
50540
50629
  }],
50630
+ "cameraCredentials.getStatus": [{
50631
+ name: "deviceId",
50632
+ form: "single",
50633
+ optional: false
50634
+ }],
50635
+ "cameraGridLayout.applyDeviceSettingsPatch": [{
50636
+ name: "deviceId",
50637
+ form: "single",
50638
+ optional: false
50639
+ }],
50640
+ "cameraGridLayout.getDeviceLiveContribution": [{
50641
+ name: "deviceId",
50642
+ form: "single",
50643
+ optional: false
50644
+ }],
50645
+ "cameraGridLayout.getDeviceSettingsContribution": [{
50646
+ name: "deviceId",
50647
+ form: "single",
50648
+ optional: false
50649
+ }],
50541
50650
  "cameraGridLayout.getLayout": [{
50542
50651
  name: "deviceId",
50543
50652
  form: "single",
@@ -50553,6 +50662,21 @@ Object.freeze({
50553
50662
  form: "single",
50554
50663
  optional: false
50555
50664
  }],
50665
+ "cameraPipelineConfig.applyDeviceSettingsPatch": [{
50666
+ name: "deviceId",
50667
+ form: "single",
50668
+ optional: false
50669
+ }],
50670
+ "cameraPipelineConfig.getDeviceLiveContribution": [{
50671
+ name: "deviceId",
50672
+ form: "single",
50673
+ optional: false
50674
+ }],
50675
+ "cameraPipelineConfig.getDeviceSettingsContribution": [{
50676
+ name: "deviceId",
50677
+ form: "single",
50678
+ optional: false
50679
+ }],
50556
50680
  "cameraStreams.getBrokerStreams": [{
50557
50681
  name: "deviceId",
50558
50682
  form: "single",
@@ -50578,6 +50702,16 @@ Object.freeze({
50578
50702
  form: "single",
50579
50703
  optional: false
50580
50704
  }],
50705
+ "carbonMonoxide.getStatus": [{
50706
+ name: "deviceId",
50707
+ form: "single",
50708
+ optional: false
50709
+ }],
50710
+ "climateControl.getStatus": [{
50711
+ name: "deviceId",
50712
+ form: "single",
50713
+ optional: false
50714
+ }],
50581
50715
  "climateControl.setFanMode": [{
50582
50716
  name: "deviceId",
50583
50717
  form: "single",
@@ -50618,16 +50752,41 @@ Object.freeze({
50618
50752
  form: "single",
50619
50753
  optional: false
50620
50754
  }],
50755
+ "color.getStatus": [{
50756
+ name: "deviceId",
50757
+ form: "single",
50758
+ optional: false
50759
+ }],
50621
50760
  "color.setColor": [{
50622
50761
  name: "deviceId",
50623
50762
  form: "single",
50624
50763
  optional: false
50625
50764
  }],
50765
+ "connectivity.getStatus": [{
50766
+ name: "deviceId",
50767
+ form: "single",
50768
+ optional: false
50769
+ }],
50770
+ "consumables.getStatus": [{
50771
+ name: "deviceId",
50772
+ form: "single",
50773
+ optional: false
50774
+ }],
50626
50775
  "consumables.reset": [{
50627
50776
  name: "deviceId",
50628
50777
  form: "single",
50629
50778
  optional: false
50630
50779
  }],
50780
+ "contact.getStatus": [{
50781
+ name: "deviceId",
50782
+ form: "single",
50783
+ optional: false
50784
+ }],
50785
+ "control.getStatus": [{
50786
+ name: "deviceId",
50787
+ form: "single",
50788
+ optional: false
50789
+ }],
50631
50790
  "control.setValue": [{
50632
50791
  name: "deviceId",
50633
50792
  form: "single",
@@ -50638,6 +50797,11 @@ Object.freeze({
50638
50797
  form: "single",
50639
50798
  optional: false
50640
50799
  }],
50800
+ "cover.getStatus": [{
50801
+ name: "deviceId",
50802
+ form: "single",
50803
+ optional: false
50804
+ }],
50641
50805
  "cover.open": [{
50642
50806
  name: "deviceId",
50643
50807
  form: "single",
@@ -50663,6 +50827,11 @@ Object.freeze({
50663
50827
  form: "single",
50664
50828
  optional: false
50665
50829
  }],
50830
+ "dayNight.getStatus": [{
50831
+ name: "deviceId",
50832
+ form: "single",
50833
+ optional: false
50834
+ }],
50666
50835
  "dayNight.setSettings": [{
50667
50836
  name: "deviceId",
50668
50837
  form: "single",
@@ -50673,11 +50842,31 @@ Object.freeze({
50673
50842
  form: "single",
50674
50843
  optional: true
50675
50844
  }],
50845
+ "detectionPipeline.applyDeviceSettingsPatch": [{
50846
+ name: "deviceId",
50847
+ form: "single",
50848
+ optional: false
50849
+ }],
50850
+ "detectionPipeline.getDeviceLiveContribution": [{
50851
+ name: "deviceId",
50852
+ form: "single",
50853
+ optional: false
50854
+ }],
50855
+ "detectionPipeline.getDeviceSettingsContribution": [{
50856
+ name: "deviceId",
50857
+ form: "single",
50858
+ optional: false
50859
+ }],
50676
50860
  "deviceAdminLink.getAdminLink": [{
50677
50861
  name: "deviceId",
50678
50862
  form: "single",
50679
50863
  optional: false
50680
50864
  }],
50865
+ "deviceAdoption.getStatus": [{
50866
+ name: "deviceId",
50867
+ form: "single",
50868
+ optional: false
50869
+ }],
50681
50870
  "deviceAdoption.release": [{
50682
50871
  name: "camDeviceId",
50683
50872
  form: "single",
@@ -50693,6 +50882,11 @@ Object.freeze({
50693
50882
  form: "single",
50694
50883
  optional: false
50695
50884
  }],
50885
+ "deviceDiscovery.getStatus": [{
50886
+ name: "deviceId",
50887
+ form: "single",
50888
+ optional: false
50889
+ }],
50696
50890
  "deviceDiscovery.listDiscovered": [{
50697
50891
  name: "deviceId",
50698
50892
  form: "single",
@@ -50712,6 +50906,21 @@ Object.freeze({
50712
50906
  form: "single",
50713
50907
  optional: false
50714
50908
  }],
50909
+ "deviceExport.applyDeviceSettingsPatch": [{
50910
+ name: "deviceId",
50911
+ form: "single",
50912
+ optional: false
50913
+ }],
50914
+ "deviceExport.getDeviceLiveContribution": [{
50915
+ name: "deviceId",
50916
+ form: "single",
50917
+ optional: false
50918
+ }],
50919
+ "deviceExport.getDeviceSettingsContribution": [{
50920
+ name: "deviceId",
50921
+ form: "single",
50922
+ optional: false
50923
+ }],
50715
50924
  "deviceExtension.listCandidates": [{
50716
50925
  name: "deviceId",
50717
50926
  form: "single",
@@ -51060,6 +51269,26 @@ Object.freeze({
51060
51269
  form: "single",
51061
51270
  optional: false
51062
51271
  }],
51272
+ "deviceStatus.getStatus": [{
51273
+ name: "deviceId",
51274
+ form: "single",
51275
+ optional: false
51276
+ }],
51277
+ "doorbell.getStatus": [{
51278
+ name: "deviceId",
51279
+ form: "single",
51280
+ optional: false
51281
+ }],
51282
+ "enumSensor.getStatus": [{
51283
+ name: "deviceId",
51284
+ form: "single",
51285
+ optional: false
51286
+ }],
51287
+ "eventEmitter.getStatus": [{
51288
+ name: "deviceId",
51289
+ form: "single",
51290
+ optional: false
51291
+ }],
51063
51292
  "faceGallery.getFaceByTrack": [{
51064
51293
  name: "deviceId",
51065
51294
  form: "single",
@@ -51074,6 +51303,11 @@ Object.freeze({
51074
51303
  form: "array",
51075
51304
  optional: true
51076
51305
  }],
51306
+ "fanControl.getStatus": [{
51307
+ name: "deviceId",
51308
+ form: "single",
51309
+ optional: false
51310
+ }],
51077
51311
  "fanControl.setDirection": [{
51078
51312
  name: "deviceId",
51079
51313
  form: "single",
@@ -51094,6 +51328,26 @@ Object.freeze({
51094
51328
  form: "single",
51095
51329
  optional: false
51096
51330
  }],
51331
+ "featureProbe.getStatus": [{
51332
+ name: "deviceId",
51333
+ form: "single",
51334
+ optional: false
51335
+ }],
51336
+ "flood.getStatus": [{
51337
+ name: "deviceId",
51338
+ form: "single",
51339
+ optional: false
51340
+ }],
51341
+ "gas.getStatus": [{
51342
+ name: "deviceId",
51343
+ form: "single",
51344
+ optional: false
51345
+ }],
51346
+ "humidifier.getStatus": [{
51347
+ name: "deviceId",
51348
+ form: "single",
51349
+ optional: false
51350
+ }],
51097
51351
  "humidifier.setMode": [{
51098
51352
  name: "deviceId",
51099
51353
  form: "single",
@@ -51109,11 +51363,26 @@ Object.freeze({
51109
51363
  form: "single",
51110
51364
  optional: false
51111
51365
  }],
51366
+ "humiditySensor.getStatus": [{
51367
+ name: "deviceId",
51368
+ form: "single",
51369
+ optional: false
51370
+ }],
51371
+ "image.getStatus": [{
51372
+ name: "deviceId",
51373
+ form: "single",
51374
+ optional: false
51375
+ }],
51112
51376
  "imageSettings.getOptions": [{
51113
51377
  name: "deviceId",
51114
51378
  form: "single",
51115
51379
  optional: false
51116
51380
  }],
51381
+ "imageSettings.getStatus": [{
51382
+ name: "deviceId",
51383
+ form: "single",
51384
+ optional: false
51385
+ }],
51117
51386
  "imageSettings.setSettings": [{
51118
51387
  name: "deviceId",
51119
51388
  form: "single",
@@ -51124,6 +51393,11 @@ Object.freeze({
51124
51393
  form: "single",
51125
51394
  optional: false
51126
51395
  }],
51396
+ "intercom.getStatus": [{
51397
+ name: "deviceId",
51398
+ form: "single",
51399
+ optional: false
51400
+ }],
51127
51401
  "intercom.handleAnswer": [{
51128
51402
  name: "deviceId",
51129
51403
  form: "single",
@@ -51154,6 +51428,11 @@ Object.freeze({
51154
51428
  form: "single",
51155
51429
  optional: false
51156
51430
  }],
51431
+ "lawnMowerControl.getStatus": [{
51432
+ name: "deviceId",
51433
+ form: "single",
51434
+ optional: false
51435
+ }],
51157
51436
  "lawnMowerControl.pause": [{
51158
51437
  name: "deviceId",
51159
51438
  form: "single",
@@ -51164,6 +51443,11 @@ Object.freeze({
51164
51443
  form: "single",
51165
51444
  optional: false
51166
51445
  }],
51446
+ "lockControl.getStatus": [{
51447
+ name: "deviceId",
51448
+ form: "single",
51449
+ optional: false
51450
+ }],
51167
51451
  "lockControl.lock": [{
51168
51452
  name: "deviceId",
51169
51453
  form: "single",
@@ -51179,6 +51463,11 @@ Object.freeze({
51179
51463
  form: "single",
51180
51464
  optional: false
51181
51465
  }],
51466
+ "mediaPlayer.getStatus": [{
51467
+ name: "deviceId",
51468
+ form: "single",
51469
+ optional: false
51470
+ }],
51182
51471
  "mediaPlayer.next": [{
51183
51472
  name: "deviceId",
51184
51473
  form: "single",
@@ -51239,6 +51528,11 @@ Object.freeze({
51239
51528
  form: "single",
51240
51529
  optional: false
51241
51530
  }],
51531
+ "motion.getStatus": [{
51532
+ name: "deviceId",
51533
+ form: "single",
51534
+ optional: false
51535
+ }],
51242
51536
  "motion.isDetected": [{
51243
51537
  name: "deviceId",
51244
51538
  form: "single",
@@ -51249,11 +51543,31 @@ Object.freeze({
51249
51543
  form: "single",
51250
51544
  optional: false
51251
51545
  }],
51546
+ "motionDetection.applyDeviceSettingsPatch": [{
51547
+ name: "deviceId",
51548
+ form: "single",
51549
+ optional: false
51550
+ }],
51551
+ "motionDetection.getDeviceLiveContribution": [{
51552
+ name: "deviceId",
51553
+ form: "single",
51554
+ optional: false
51555
+ }],
51556
+ "motionDetection.getDeviceSettingsContribution": [{
51557
+ name: "deviceId",
51558
+ form: "single",
51559
+ optional: false
51560
+ }],
51252
51561
  "motionDetection.removeCamera": [{
51253
51562
  name: "deviceId",
51254
51563
  form: "single",
51255
51564
  optional: false
51256
51565
  }],
51566
+ "motionTrigger.getStatus": [{
51567
+ name: "deviceId",
51568
+ form: "single",
51569
+ optional: false
51570
+ }],
51257
51571
  "motionTrigger.setMotionTrigger": [{
51258
51572
  name: "deviceId",
51259
51573
  form: "single",
@@ -51264,6 +51578,11 @@ Object.freeze({
51264
51578
  form: "single",
51265
51579
  optional: false
51266
51580
  }],
51581
+ "motionZones.getStatus": [{
51582
+ name: "deviceId",
51583
+ form: "single",
51584
+ optional: false
51585
+ }],
51267
51586
  "motionZones.setZone": [{
51268
51587
  name: "deviceId",
51269
51588
  form: "single",
@@ -51274,6 +51593,11 @@ Object.freeze({
51274
51593
  form: "single",
51275
51594
  optional: false
51276
51595
  }],
51596
+ "nativeObjectDetection.getStatus": [{
51597
+ name: "deviceId",
51598
+ form: "single",
51599
+ optional: false
51600
+ }],
51277
51601
  "nativeObjectDetection.setEnabled": [{
51278
51602
  name: "deviceId",
51279
51603
  form: "single",
@@ -51289,6 +51613,11 @@ Object.freeze({
51289
51613
  form: "single",
51290
51614
  optional: false
51291
51615
  }],
51616
+ "navigation.getStatus": [{
51617
+ name: "deviceId",
51618
+ form: "single",
51619
+ optional: false
51620
+ }],
51292
51621
  "navigation.goToPoint": [{
51293
51622
  name: "deviceId",
51294
51623
  form: "single",
@@ -51334,6 +51663,11 @@ Object.freeze({
51334
51663
  form: "single",
51335
51664
  optional: false
51336
51665
  }],
51666
+ "networkLink.getStatus": [{
51667
+ name: "deviceId",
51668
+ form: "single",
51669
+ optional: false
51670
+ }],
51337
51671
  "networkQuality.getDeviceStats": [{
51338
51672
  name: "deviceId",
51339
51673
  form: "single",
@@ -51344,6 +51678,11 @@ Object.freeze({
51344
51678
  form: "single",
51345
51679
  optional: false
51346
51680
  }],
51681
+ "notificationRules.getAlarmSensors": [{
51682
+ name: "deviceIds",
51683
+ form: "array",
51684
+ optional: false
51685
+ }],
51347
51686
  "notificationRules.setDeviceMuted": [{
51348
51687
  name: "deviceId",
51349
51688
  form: "single",
@@ -51354,11 +51693,26 @@ Object.freeze({
51354
51693
  form: "single",
51355
51694
  optional: false
51356
51695
  }],
51696
+ "notifier.getStatus": [{
51697
+ name: "deviceId",
51698
+ form: "single",
51699
+ optional: false
51700
+ }],
51357
51701
  "notifier.send": [{
51358
51702
  name: "deviceId",
51359
51703
  form: "single",
51360
51704
  optional: false
51361
51705
  }],
51706
+ "numericSensor.getStatus": [{
51707
+ name: "deviceId",
51708
+ form: "single",
51709
+ optional: false
51710
+ }],
51711
+ "osd.getStatus": [{
51712
+ name: "deviceId",
51713
+ form: "single",
51714
+ optional: false
51715
+ }],
51362
51716
  "osd.setOverlay": [{
51363
51717
  name: "deviceId",
51364
51718
  form: "single",
@@ -51418,6 +51772,11 @@ Object.freeze({
51418
51772
  form: "single",
51419
51773
  optional: false
51420
51774
  }],
51775
+ "petFeeder.getStatus": [{
51776
+ name: "deviceId",
51777
+ form: "single",
51778
+ optional: false
51779
+ }],
51421
51780
  "petFeeder.markFoodReplenished": [{
51422
51781
  name: "deviceId",
51423
51782
  form: "single",
@@ -51453,6 +51812,11 @@ Object.freeze({
51453
51812
  form: "single",
51454
51813
  optional: false
51455
51814
  }],
51815
+ "pipelineAnalytics.applyDeviceSettingsPatch": [{
51816
+ name: "deviceId",
51817
+ form: "single",
51818
+ optional: false
51819
+ }],
51456
51820
  "pipelineAnalytics.clearTrackRelation": [{
51457
51821
  name: "deviceId",
51458
51822
  form: "single",
@@ -51493,6 +51857,16 @@ Object.freeze({
51493
51857
  form: "single",
51494
51858
  optional: false
51495
51859
  }],
51860
+ "pipelineAnalytics.getDeviceLiveContribution": [{
51861
+ name: "deviceId",
51862
+ form: "single",
51863
+ optional: false
51864
+ }],
51865
+ "pipelineAnalytics.getDeviceSettingsContribution": [{
51866
+ name: "deviceId",
51867
+ form: "single",
51868
+ optional: false
51869
+ }],
51496
51870
  "pipelineAnalytics.getEventDensity": [{
51497
51871
  name: "deviceId",
51498
51872
  form: "single",
@@ -51708,6 +52082,11 @@ Object.freeze({
51708
52082
  form: "single",
51709
52083
  optional: true
51710
52084
  }],
52085
+ "pipelineOrchestrator.applyDeviceSettingsPatch": [{
52086
+ name: "deviceId",
52087
+ form: "single",
52088
+ optional: false
52089
+ }],
51711
52090
  "pipelineOrchestrator.assignAudio": [{
51712
52091
  name: "deviceId",
51713
52092
  form: "single",
@@ -51753,6 +52132,16 @@ Object.freeze({
51753
52132
  form: "single",
51754
52133
  optional: false
51755
52134
  }],
52135
+ "pipelineOrchestrator.getDeviceLiveContribution": [{
52136
+ name: "deviceId",
52137
+ form: "single",
52138
+ optional: false
52139
+ }],
52140
+ "pipelineOrchestrator.getDeviceSettingsContribution": [{
52141
+ name: "deviceId",
52142
+ form: "single",
52143
+ optional: false
52144
+ }],
51756
52145
  "pipelineOrchestrator.getPipelineAssignment": [{
51757
52146
  name: "deviceId",
51758
52147
  form: "single",
@@ -51873,11 +52262,31 @@ Object.freeze({
51873
52262
  form: "single",
51874
52263
  optional: true
51875
52264
  }],
52265
+ "powerMeter.getStatus": [{
52266
+ name: "deviceId",
52267
+ form: "single",
52268
+ optional: false
52269
+ }],
52270
+ "presence.getStatus": [{
52271
+ name: "deviceId",
52272
+ form: "single",
52273
+ optional: false
52274
+ }],
52275
+ "pressureSensor.getStatus": [{
52276
+ name: "deviceId",
52277
+ form: "single",
52278
+ optional: false
52279
+ }],
51876
52280
  "privacyMask.getOptions": [{
51877
52281
  name: "deviceId",
51878
52282
  form: "single",
51879
52283
  optional: false
51880
52284
  }],
52285
+ "privacyMask.getStatus": [{
52286
+ name: "deviceId",
52287
+ form: "single",
52288
+ optional: false
52289
+ }],
51881
52290
  "privacyMask.setAudioEnabled": [{
51882
52291
  name: "deviceId",
51883
52292
  form: "single",
@@ -51928,6 +52337,11 @@ Object.freeze({
51928
52337
  form: "single",
51929
52338
  optional: false
51930
52339
  }],
52340
+ "ptz.getStatus": [{
52341
+ name: "deviceId",
52342
+ form: "single",
52343
+ optional: false
52344
+ }],
51931
52345
  "ptz.goHome": [{
51932
52346
  name: "deviceId",
51933
52347
  form: "single",
@@ -52018,6 +52432,11 @@ Object.freeze({
52018
52432
  form: "single",
52019
52433
  optional: false
52020
52434
  }],
52435
+ "recordingArchive.applyDeviceSettingsPatch": [{
52436
+ name: "deviceId",
52437
+ form: "single",
52438
+ optional: false
52439
+ }],
52021
52440
  "recordingArchive.deleteFootprint": [{
52022
52441
  name: "deviceId",
52023
52442
  form: "single",
@@ -52038,6 +52457,21 @@ Object.freeze({
52038
52457
  form: "single",
52039
52458
  optional: false
52040
52459
  }],
52460
+ "recordingArchive.getDeviceLiveContribution": [{
52461
+ name: "deviceId",
52462
+ form: "single",
52463
+ optional: false
52464
+ }],
52465
+ "recordingArchive.getDeviceSettingsContribution": [{
52466
+ name: "deviceId",
52467
+ form: "single",
52468
+ optional: false
52469
+ }],
52470
+ "recordingArchive.getStatus": [{
52471
+ name: "deviceId",
52472
+ form: "single",
52473
+ optional: false
52474
+ }],
52041
52475
  "recordingArchive.listOpsLog": [{
52042
52476
  name: "deviceId",
52043
52477
  form: "single",
@@ -52123,6 +52557,11 @@ Object.freeze({
52123
52557
  form: "single",
52124
52558
  optional: false
52125
52559
  }],
52560
+ "recordingOnboard.getStatus": [{
52561
+ name: "deviceId",
52562
+ form: "single",
52563
+ optional: false
52564
+ }],
52126
52565
  "recordingOnboard.setSettings": [{
52127
52566
  name: "deviceId",
52128
52567
  form: "single",
@@ -52153,6 +52592,11 @@ Object.freeze({
52153
52592
  form: "single",
52154
52593
  optional: false
52155
52594
  }],
52595
+ "sceneMonitor.getStatus": [{
52596
+ name: "deviceId",
52597
+ form: "single",
52598
+ optional: false
52599
+ }],
52156
52600
  "sceneMonitor.listScenes": [{
52157
52601
  name: "deviceId",
52158
52602
  form: "single",
@@ -52178,6 +52622,11 @@ Object.freeze({
52178
52622
  form: "single",
52179
52623
  optional: false
52180
52624
  }],
52625
+ "scriptRunner.getStatus": [{
52626
+ name: "deviceId",
52627
+ form: "single",
52628
+ optional: false
52629
+ }],
52181
52630
  "scriptRunner.run": [{
52182
52631
  name: "deviceId",
52183
52632
  form: "single",
@@ -52188,11 +52637,31 @@ Object.freeze({
52188
52637
  form: "single",
52189
52638
  optional: false
52190
52639
  }],
52640
+ "smoke.getStatus": [{
52641
+ name: "deviceId",
52642
+ form: "single",
52643
+ optional: false
52644
+ }],
52645
+ "snapshot.applyDeviceSettingsPatch": [{
52646
+ name: "deviceId",
52647
+ form: "single",
52648
+ optional: false
52649
+ }],
52191
52650
  "snapshot.getDebugState": [{
52192
52651
  name: "deviceId",
52193
52652
  form: "single",
52194
52653
  optional: false
52195
52654
  }],
52655
+ "snapshot.getDeviceLiveContribution": [{
52656
+ name: "deviceId",
52657
+ form: "single",
52658
+ optional: false
52659
+ }],
52660
+ "snapshot.getDeviceSettingsContribution": [{
52661
+ name: "deviceId",
52662
+ form: "single",
52663
+ optional: false
52664
+ }],
52196
52665
  "snapshot.getSnapshot": [{
52197
52666
  name: "deviceId",
52198
52667
  form: "single",
@@ -52209,6 +52678,11 @@ Object.freeze({
52209
52678
  form: "array",
52210
52679
  optional: false
52211
52680
  }],
52681
+ "snapshot.getStatus": [{
52682
+ name: "deviceId",
52683
+ form: "single",
52684
+ optional: false
52685
+ }],
52212
52686
  "snapshot.invalidateCache": [{
52213
52687
  name: "deviceId",
52214
52688
  form: "single",
@@ -52219,6 +52693,11 @@ Object.freeze({
52219
52693
  form: "single",
52220
52694
  optional: false
52221
52695
  }],
52696
+ "streamBroker.applyDeviceSettingsPatch": [{
52697
+ name: "deviceId",
52698
+ form: "single",
52699
+ optional: false
52700
+ }],
52222
52701
  "streamBroker.assignProfile": [{
52223
52702
  name: "deviceId",
52224
52703
  form: "single",
@@ -52234,6 +52713,16 @@ Object.freeze({
52234
52713
  form: "single",
52235
52714
  optional: false
52236
52715
  }],
52716
+ "streamBroker.getDeviceLiveContribution": [{
52717
+ name: "deviceId",
52718
+ form: "single",
52719
+ optional: false
52720
+ }],
52721
+ "streamBroker.getDeviceSettingsContribution": [{
52722
+ name: "deviceId",
52723
+ form: "single",
52724
+ optional: false
52725
+ }],
52237
52726
  "streamBroker.getStreamWithCodec": [{
52238
52727
  name: "deviceId",
52239
52728
  form: "single",
@@ -52294,16 +52783,46 @@ Object.freeze({
52294
52783
  form: "single",
52295
52784
  optional: false
52296
52785
  }],
52786
+ "streamParams.getStatus": [{
52787
+ name: "deviceId",
52788
+ form: "single",
52789
+ optional: false
52790
+ }],
52297
52791
  "streamParams.setProfile": [{
52298
52792
  name: "deviceId",
52299
52793
  form: "single",
52300
52794
  optional: false
52301
52795
  }],
52796
+ "switch.getStatus": [{
52797
+ name: "deviceId",
52798
+ form: "single",
52799
+ optional: false
52800
+ }],
52302
52801
  "switch.setState": [{
52303
52802
  name: "deviceId",
52304
52803
  form: "single",
52305
52804
  optional: false
52306
52805
  }],
52806
+ "tamper.getStatus": [{
52807
+ name: "deviceId",
52808
+ form: "single",
52809
+ optional: false
52810
+ }],
52811
+ "temperatureSensor.getStatus": [{
52812
+ name: "deviceId",
52813
+ form: "single",
52814
+ optional: false
52815
+ }],
52816
+ "update.getStatus": [{
52817
+ name: "deviceId",
52818
+ form: "single",
52819
+ optional: false
52820
+ }],
52821
+ "vacuumControl.getStatus": [{
52822
+ name: "deviceId",
52823
+ form: "single",
52824
+ optional: false
52825
+ }],
52307
52826
  "vacuumControl.locate": [{
52308
52827
  name: "deviceId",
52309
52828
  form: "single",
@@ -52339,6 +52858,11 @@ Object.freeze({
52339
52858
  form: "single",
52340
52859
  optional: false
52341
52860
  }],
52861
+ "valve.getStatus": [{
52862
+ name: "deviceId",
52863
+ form: "single",
52864
+ optional: false
52865
+ }],
52342
52866
  "valve.open": [{
52343
52867
  name: "deviceId",
52344
52868
  form: "single",
@@ -52354,6 +52878,11 @@ Object.freeze({
52354
52878
  form: "single",
52355
52879
  optional: false
52356
52880
  }],
52881
+ "vibration.getStatus": [{
52882
+ name: "deviceId",
52883
+ form: "single",
52884
+ optional: false
52885
+ }],
52357
52886
  "videoclips.dialClipStream": [{
52358
52887
  name: "deviceId",
52359
52888
  form: "single",
@@ -52389,6 +52918,11 @@ Object.freeze({
52389
52918
  form: "single",
52390
52919
  optional: false
52391
52920
  }],
52921
+ "waterHeater.getStatus": [{
52922
+ name: "deviceId",
52923
+ form: "single",
52924
+ optional: false
52925
+ }],
52392
52926
  "waterHeater.setAway": [{
52393
52927
  name: "deviceId",
52394
52928
  form: "single",
@@ -52404,6 +52938,11 @@ Object.freeze({
52404
52938
  form: "single",
52405
52939
  optional: false
52406
52940
  }],
52941
+ "weather.getStatus": [{
52942
+ name: "deviceId",
52943
+ form: "single",
52944
+ optional: false
52945
+ }],
52407
52946
  "webrtcSession.addIceCandidate": [{
52408
52947
  name: "deviceId",
52409
52948
  form: "single",
@@ -53141,7 +53680,7 @@ var PreviewTextField = string().max(200);
53141
53680
  * Whether the notification's preview is a STILL or a short animation.
53142
53681
  *
53143
53682
  * The operator's ask, verbatim: *"inviato come gif o video (come per le altre
53144
- * rule)"* — the other rules already offer an animated preview, and a ten-hour
53683
+ * rule)"* [sent as a gif or video (as for the other rules)] — the other rules already offer an animated preview, and a ten-hour
53145
53684
  * night reads better as three seconds of motion than as one frame of it. Both
53146
53685
  * modes get the SAME treatment (blurred frame, large centred title); `'gif'`
53147
53686
  * simply applies it to a dozen frames sampled across the render and assembles