@camstack/addon-provider-hikvision 1.2.20 → 1.2.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/addon.mjs CHANGED
@@ -7,7 +7,7 @@ import { networkInterfaces } from "node:os";
7
7
  var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
8
8
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
9
9
  //#endregion
10
- //#region ../types/dist/event-category-Cv9dO26A.mjs
10
+ //#region ../types/dist/event-category-Bxo5yJjt.mjs
11
11
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
12
12
  EventCategory["SystemBoot"] = "system.boot";
13
13
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -214,6 +214,33 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
214
214
  EventCategory["PipelineCameraAssigned"] = "pipeline.camera-assigned";
215
215
  EventCategory["PipelineCameraUnassigned"] = "pipeline.camera-unassigned";
216
216
  /**
217
+ * A node the orchestrator would otherwise place cameras on has NO usable
218
+ * inference device: the operator enabled one or more accelerators there and
219
+ * the live probe reports every one of them unavailable. Emitted once per
220
+ * TRANSITION into that state (never per dispatch), and the node is dropped
221
+ * from the placement candidate set for as long as it holds.
222
+ *
223
+ * This exists because the state was previously invisible: little-unraid
224
+ * absorbed 283k inference errors in a day while still being handed cameras,
225
+ * and nothing in the system said so.
226
+ *
227
+ * A node with no accelerators configured at all is NOT this — its devices
228
+ * are `disabled`, not `unavailable`, and the runner's default CPU pool
229
+ * serves it exactly as before.
230
+ */
231
+ EventCategory["PipelineNodeInferenceUnavailable"] = "pipeline.node-inference-unavailable";
232
+ /**
233
+ * A camera has an OPEN detection session and has produced no detection at
234
+ * all for longer than the blind threshold — the camera is being decoded and
235
+ * inferred and is returning nothing. Emitted once per transition into blind,
236
+ * per camera.
237
+ *
238
+ * The failure it reports: a 1h43 detection blackout on the entrance camera
239
+ * that nobody noticed, because "a camera that detects nothing" and "a quiet
240
+ * camera" produce byte-identical silence.
241
+ */
242
+ EventCategory["PipelineDetectionBlind"] = "pipeline.detection-blind";
243
+ /**
217
244
  * Per-camera pipeline config was mutated by the orchestrator
218
245
  * (3-level settings change via `setAgentAddonDefaults` /
219
246
  * `setCameraStepToggle` / `setCameraPipelineForAgent` or a
@@ -3005,6 +3032,9 @@ function handlePipeResult(left, next, ctx) {
3005
3032
  fallback: left.fallback
3006
3033
  }, ctx);
3007
3034
  }
3035
+ var $ZodPreprocess = /*@__PURE__*/ $constructor("$ZodPreprocess", (inst, def) => {
3036
+ $ZodPipe.init(inst, def);
3037
+ });
3008
3038
  var $ZodReadonly = /*@__PURE__*/ $constructor("$ZodReadonly", (inst, def) => {
3009
3039
  $ZodType.init(inst, def);
3010
3040
  defineLazy(inst._zod, "propValues", () => def.innerType._zod.propValues);
@@ -5190,6 +5220,10 @@ function pipe(in_, out) {
5190
5220
  out
5191
5221
  });
5192
5222
  }
5223
+ var ZodPreprocess = /*@__PURE__*/ $constructor("ZodPreprocess", (inst, def) => {
5224
+ ZodPipe.init(inst, def);
5225
+ $ZodPreprocess.init(inst, def);
5226
+ });
5193
5227
  var ZodReadonly = /*@__PURE__*/ $constructor("ZodReadonly", (inst, def) => {
5194
5228
  $ZodReadonly.init(inst, def);
5195
5229
  ZodType.init(inst, def);
@@ -5248,6 +5282,13 @@ function _instanceof(cls, params = {}) {
5248
5282
  };
5249
5283
  return inst;
5250
5284
  }
5285
+ function preprocess(fn, schema) {
5286
+ return new ZodPreprocess({
5287
+ type: "pipe",
5288
+ in: transform(fn),
5289
+ out: schema
5290
+ });
5291
+ }
5251
5292
  //#endregion
5252
5293
  //#region ../../node_modules/zod/v4/classic/compat.js
5253
5294
  /** @deprecated Use the raw string literal codes instead, e.g. "invalid_type". */
@@ -5364,6 +5405,12 @@ Object.fromEntries([
5364
5405
  icon: "shapes",
5365
5406
  order: 38
5366
5407
  },
5408
+ {
5409
+ id: "scenes",
5410
+ label: "Scenes",
5411
+ icon: "scan-eye",
5412
+ order: 36
5413
+ },
5367
5414
  {
5368
5415
  id: "analytics",
5369
5416
  label: "Analytics",
@@ -14472,6 +14519,8 @@ var NcSystemEventKindSchema = _enum([
14472
14519
  "stream-offline",
14473
14520
  "node-online",
14474
14521
  "node-offline",
14522
+ "node-inference-unavailable",
14523
+ "detection-blind",
14475
14524
  "addon-update-available",
14476
14525
  "server-update-available",
14477
14526
  "alarm-triggered",
@@ -14533,7 +14582,16 @@ var NcScheduleSchema = object({
14533
14582
  });
14534
14583
  /** Fuzzy plate matcher — OCR noise makes exact match useless (spec row 12/13). */
14535
14584
  var NcPlateMatcherSchema = object({
14536
- values: array(string().min(1)).min(1),
14585
+ /**
14586
+ * Plate texts (or gallery vehicle names) to match. EMPTY = **any plate the
14587
+ * pipeline could read** — the plate half of "no selection = no narrowing",
14588
+ * and the switch that says this rule is about vehicles that were IDENTIFIED
14589
+ * rather than merely seen. A subject carrying no plate still fails.
14590
+ *
14591
+ * The `.min(1)` this used to carry made that state unauthorable; nothing has
14592
+ * ever persisted an empty list, so widening it cannot change an existing rule.
14593
+ */
14594
+ values: array(string().min(1)),
14537
14595
  /** Max Levenshtein distance after normalization (uppercase alphanumeric). */
14538
14596
  maxDistance: number().int().min(0).max(3).default(1)
14539
14597
  });
@@ -14772,18 +14830,47 @@ var NcConditionsSchema = object({
14772
14830
  */
14773
14831
  labelEquals: array(string().min(1)).optional(),
14774
14832
  /**
14775
- * Identity matcher. P1 boundary: matched against the record's collapsed
14776
- * `label` (the identity display name propagated by the face pipeline) —
14777
- * identity-ID matching rides in P2 when identity ids reach the record.
14833
+ * KNOWN FACES the rule's identity scope, and the switch that says the rule
14834
+ * is about recognised people at all.
14835
+ *
14836
+ * Three states, and the empty one is the point:
14837
+ *
14838
+ * | value | meaning |
14839
+ * | --- | --- |
14840
+ * | absent | the rule does not care who it is; an unrecognised person matches |
14841
+ * | `[]` | **only known faces** — any identity in the gallery, nobody in particular |
14842
+ * | a list | only these identities |
14843
+ *
14844
+ * `[]` is the repo-wide "no selection = no narrowing" reading (an absent
14845
+ * `devices` list is every device), applied one level down: the operator has
14846
+ * turned the face scope ON and narrowed it to nothing, which is every known
14847
+ * face. No second field states the same thing — a switch that can disagree
14848
+ * with the list under it is worse than no switch (D62).
14849
+ *
14850
+ * MEMBERS ARE FACE-GALLERY `Identity.id`s (uuid), not display names. A name is
14851
+ * renameable, and a rule authored on "Gianluca" went silently dark the moment
14852
+ * the operator fixed the spelling. The id reaches the record on
14853
+ * `LabelAttribution.identityId`; the name is what the editor shows and what
14854
+ * `{{label}}` renders.
14855
+ *
14856
+ * Rules written before this carry NAMES, and are resolved to ids lazily at
14857
+ * load (`NcRuleStore.load`) against the live gallery — a name nothing answers
14858
+ * for is left as it stands and reported, never dropped. The engine also
14859
+ * accepts a display-name hit as a compatibility leg, so a rule whose
14860
+ * migration could not resolve keeps matching exactly what it matched before.
14778
14861
  */
14779
14862
  identities: array(string().min(1)).optional(),
14780
- /** Fuzzy plate matcher against the record's `label` (plate text). */
14863
+ /**
14864
+ * KNOWN PLATES / VEHICLES — the plate mirror of {@link identities}, including
14865
+ * the empty-list reading: `values: []` is "any plate the OCR could read",
14866
+ * a non-empty list is those plates (fuzzily). See {@link NcPlateMatcherSchema}.
14867
+ */
14781
14868
  plates: NcPlateMatcherSchema.optional(),
14782
14869
  /**
14783
- * Identity EXCLUDE — mirror of {@link identities} with `notIn` semantics.
14784
- * Same P1 boundary: matched against the record's collapsed `label` (the
14785
- * identity display name). A record with NO label passes (nothing to
14786
- * exclude), unlike the include variant which fails on an absent label.
14870
+ * Identity EXCLUDE — mirror of {@link identities} with `notIn` semantics, and
14871
+ * the same id members and the same lazy name→id migration. A record with NO
14872
+ * identity passes (nothing to exclude), unlike the include variant which
14873
+ * fails on an unrecognised subject. An EMPTY list excludes nobody.
14787
14874
  */
14788
14875
  identitiesExclude: array(string().min(1)).optional(),
14789
14876
  /**
@@ -15175,7 +15262,80 @@ var NcRuleInputSchema = object({
15175
15262
  * a rule that predates the gate must keep delivering byte-for-byte as it
15176
15263
  * did, and absent is the only way to say that without a migration.
15177
15264
  */
15178
- confirm: NcConfirmSchema.optional()
15265
+ confirm: NcConfirmSchema.optional(),
15266
+ /**
15267
+ * WAIT for face/plate recognition before saying anything.
15268
+ *
15269
+ * A notification's TEXT is frozen at enqueue and its media is re-resolved at
15270
+ * send; the identity is neither. A face is confirmed after `confirmFrames`
15271
+ * agreeing observations — p50 **11.4 s** after the track was first seen,
15272
+ * measured on this hub — and an `immediate` rule enqueues on the first object
15273
+ * event, seconds before that. So "Gianluca è arrivato" is unsayable on the
15274
+ * immediate path, and no amount of media re-resolution fixes a sentence.
15275
+ *
15276
+ * Only two honest answers exist, and this flag picks between them. It has
15277
+ * effect ONLY on a rule that declares a recognition scope
15278
+ * ({@link NcConditions.identities} or {@link NcConditions.plates}) — on any
15279
+ * other rule there is nothing to wait for and the flag is inert.
15280
+ *
15281
+ * | value | what happens |
15282
+ * | --- | --- |
15283
+ * | `true` | the rule stops firing on the object event and fires at TRACK CLOSE instead, once, with the name — later, and complete |
15284
+ * | 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) |
15285
+ *
15286
+ * `.optional()` and deliberately NOT `.default()`: a Zod default does not run
15287
+ * on the addon cap path, and absent has to keep meaning exactly what every
15288
+ * rule authored before this field meant.
15289
+ *
15290
+ * The cost of `true` is stated here because the editor states it too: a rule
15291
+ * that waits also inherits track-close SEMANTICS — its `zones` condition
15292
+ * tests every zone the track visited and a `crossing` condition can no longer
15293
+ * be satisfied, because a closed track carries no crossing.
15294
+ */
15295
+ waitForEnhancement: boolean().optional(),
15296
+ /**
15297
+ * GROUP a burst of subjects into ONE notification that grows.
15298
+ *
15299
+ * Seconds of quiet after the last matching subject before the burst is
15300
+ * considered over. While it is open, the first subject enqueues immediately —
15301
+ * **exactly as today, with no added latency** — and every real growth (a new
15302
+ * subject, or a name confirmed on one already in it) REPLACES that
15303
+ * notification with an updated one naming everybody. The push carries the
15304
+ * group's own coalescing tag, so the phone replaces rather than stacks.
15305
+ *
15306
+ * `0` / absent = off, and off is today's behaviour byte for byte.
15307
+ *
15308
+ * ### Why an idle cutoff and not a window
15309
+ *
15310
+ * The measured seven-person arrival on device 590 spans 110 s with every
15311
+ * internal gap under 30 s. A 12 s fixed window cuts it into three groups; an
15312
+ * idle cutoff holds it as one and ends it when the arrival actually ends.
15313
+ * 30 is Frigate's shipped value for the same decision.
15314
+ *
15315
+ * ### What it replaces
15316
+ *
15317
+ * The blind cooldown, which collapses a burst by DISCARDING it. Measured on
15318
+ * device 615 / *Persona su Uscio* over six days: 116 qualifying tracks → 74
15319
+ * notifications, **44 (37.9%) suppressed outright**, 23 of them overlapping a
15320
+ * track that did fire and 7 carrying a confirmed identity nobody heard about.
15321
+ * A group collapses the same volume by MERGING, so the cooldown becomes a
15322
+ * budget over GROUPS — which is what it always meant — and a growth is never
15323
+ * throttled by the window its own first member spent.
15324
+ *
15325
+ * ### Interaction with {@link waitForEnhancement}
15326
+ *
15327
+ * They compose, and the order matters. `waitForEnhancement` defers the rule to
15328
+ * TRACK CLOSE, so with both set the group is opened by the first member to
15329
+ * CLOSE — already carrying its name — and grows as later members close. That
15330
+ * is later, and complete. With grouping alone the group opens on the first
15331
+ * object event and picks up names as they are confirmed, through the growth
15332
+ * path. Neither combination fires twice for one subject.
15333
+ *
15334
+ * `.optional()` and deliberately NOT `.default()`: a Zod default does not run
15335
+ * on the addon cap path, so absent must keep meaning what it meant before this
15336
+ * field existed.
15337
+ */
15338
+ groupIdleSec: number().int().min(0).max(600).optional()
15179
15339
  });
15180
15340
  /**
15181
15341
  * Partial patch for `updateRule` — any subset of the input fields, plus the
@@ -15687,7 +15847,87 @@ var MethodAccessSchema = _enum([
15687
15847
  var AllowedProviderSchema = union([literal("*"), array(string())]);
15688
15848
  var AllowedDevicesSchema = record(string(), union([literal("*"), array(string())]));
15689
15849
  var CapScopeSchema = _enum(["device", "system"]);
15690
- var TokenScopeSchema = discriminatedUnion("type", [
15850
+ /**
15851
+ * DeviceSelector (scope model v3 — 2026-08-12).
15852
+ *
15853
+ * A `device` grant no longer carries a frozen list of deviceIds. It carries
15854
+ * a SELECTOR the matcher resolves against the live fleet, so the grant can be
15855
+ * DYNAMIC: a `types:['camera']` selector automatically covers a camera added
15856
+ * AFTER the grant was minted — no re-grant, no re-login.
15857
+ *
15858
+ * - `all` — every device in the deployment. The broad viewer/operator
15859
+ * lever without a `category` grant (a `category` grant also covers device
15860
+ * caps that carry no deviceId; `all` is specifically the device set).
15861
+ * - `ids` — an explicit deviceId list. This is what a v2 `device:[…]`
15862
+ * grant migrates to (see {@link TokenScopeSchema}); STATIC — a new camera
15863
+ * is NOT covered until the grant is edited.
15864
+ * - `types` — every device of a `DeviceType` (e.g. every `camera`).
15865
+ * DYNAMIC. A device that changes type, or a new device of the type,
15866
+ * re-resolves on the next request.
15867
+ * - `locations` — every device whose operator-assigned `location` label is
15868
+ * in the set (e.g. "Garden", "Front door"). DYNAMIC. A device with a
15869
+ * null/unset location matches NO `locations` selector.
15870
+ */
15871
+ var DeviceSelectorSchema = discriminatedUnion("kind", [
15872
+ object({ kind: literal("all") }),
15873
+ object({
15874
+ kind: literal("ids"),
15875
+ ids: array(number().int()).min(1)
15876
+ }),
15877
+ object({
15878
+ kind: literal("types"),
15879
+ types: array(_enum(DeviceType)).min(1)
15880
+ }),
15881
+ object({
15882
+ kind: literal("locations"),
15883
+ locations: array(string().min(1)).min(1)
15884
+ })
15885
+ ]);
15886
+ var DeviceTokenScopeSchema = object({
15887
+ type: literal("device"),
15888
+ /** The device SET this grant covers — resolved against the live fleet. */
15889
+ selector: DeviceSelectorSchema,
15890
+ access: array(MethodAccessSchema).min(1),
15891
+ /**
15892
+ * Whether a grant on a PARENT device transparently covers its accessory
15893
+ * CHILDREN (siren / floodlight / PIR) via the persisted-parentage walk.
15894
+ * Direction is parent → children ONLY.
15895
+ *
15896
+ * Absent → the matcher DERIVES it from the access flavour: `view`
15897
+ * inherits (a camera viewer sees the camera's accessories), `create` /
15898
+ * `delete` do NOT (actuating/removing a child is an explicit act the
15899
+ * operator must grant on the child, not inherit from the parent). Set it
15900
+ * explicitly to override that default per grant.
15901
+ */
15902
+ includeLinked: boolean().optional()
15903
+ });
15904
+ /**
15905
+ * v2 → v3 lazy migration. A pre-v3 `device` grant carried
15906
+ * `targets: string[]` (stringified deviceIds); it rewrites to the equivalent
15907
+ * `selector: {kind:'ids', ids}`. Applied as a `preprocess` so it runs on
15908
+ * EVERY parse path — stored records AND the JWT-carried scope arrays
15909
+ * normalised at the request boundary ({@link normalizeTokenScopes} in
15910
+ * `device-selector.ts`). Chosen over a one-time DB migration because a
15911
+ * migration cannot reach a JWT already in a client's hands; parse-time
15912
+ * migration covers both without a flag day. No cast — the raw object is read
15913
+ * through `Reflect.get` (its static type is `unknown`).
15914
+ */
15915
+ function migrateLegacyTokenScope(raw) {
15916
+ if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return raw;
15917
+ if (Reflect.get(raw, "type") !== "device") return raw;
15918
+ if (Reflect.get(raw, "selector") !== void 0) return raw;
15919
+ const targets = Reflect.get(raw, "targets");
15920
+ if (!Array.isArray(targets)) return raw;
15921
+ return {
15922
+ type: "device",
15923
+ selector: {
15924
+ kind: "ids",
15925
+ ids: targets.map((t) => typeof t === "string" ? Number(t) : t).filter((n) => typeof n === "number" && Number.isInteger(n))
15926
+ },
15927
+ access: Reflect.get(raw, "access")
15928
+ };
15929
+ }
15930
+ var TokenScopeSchema = preprocess(migrateLegacyTokenScope, discriminatedUnion("type", [
15691
15931
  object({
15692
15932
  type: literal("category"),
15693
15933
  target: CapScopeSchema,
@@ -15703,18 +15943,8 @@ var TokenScopeSchema = discriminatedUnion("type", [
15703
15943
  target: string(),
15704
15944
  access: array(MethodAccessSchema).min(1)
15705
15945
  }),
15706
- object({
15707
- type: literal("device"),
15708
- /**
15709
- * One or more deviceIds (serialised as strings for wire-format
15710
- * consistency with the rest of the union). Matcher accepts if
15711
- * `input.deviceId` ∈ `targets`. Array shape avoids the row-explosion
15712
- * of one scope-per-device when granting access to a set of cameras.
15713
- */
15714
- targets: array(string()).min(1),
15715
- access: array(MethodAccessSchema).min(1)
15716
- })
15717
- ]);
15946
+ DeviceTokenScopeSchema
15947
+ ]));
15718
15948
  object({
15719
15949
  id: string(),
15720
15950
  username: string(),
@@ -16031,7 +16261,7 @@ var TrackEnvelopeSchema = object({
16031
16261
  * `snapshots[]` references — megabytes across a page of tracks. `slim`
16032
16262
  * keeps every scalar the list surfaces actually render (ids, class(es),
16033
16263
  * label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
16034
- * zonesVisited, bestEventId, envelope, hasFace) and returns `positions` /
16264
+ * zonesVisited, bestEventId, envelope, hasFace, hasRider) and returns `positions` /
16035
16265
  * `snapshots` as EMPTY arrays — detail views re-fetch the full row via
16036
16266
  * `getTrack`. Mirrors the event-store `projection` convention
16037
16267
  * (`getObjectEvents` et al.).
@@ -16167,7 +16397,21 @@ union([literal(1), literal(2)]);
16167
16397
  var LabelAttributionSchema = object({
16168
16398
  stepId: string(),
16169
16399
  modelId: string().optional(),
16170
- decidedAt: number()
16400
+ decidedAt: number(),
16401
+ /**
16402
+ * The GALLERY id behind a recognised tier-2 label — a face-gallery
16403
+ * `Identity.id` or a plate-gallery `Vehicle.id` (both `randomUUID`).
16404
+ *
16405
+ * The text alone is a DISPLAY NAME, and a display name is renameable: a
16406
+ * notification rule authored on "Gianluca" stopped matching the moment the
16407
+ * operator fixed the spelling in the gallery, and nothing said so. The id is
16408
+ * the thing that does not move, so it is what a rule matches on
16409
+ * (`NcConditions.identities`) and the text is what a human is shown.
16410
+ *
16411
+ * Absent when the label names no gallery row — a plate the OCR read but no
16412
+ * vehicle claims, a sub-class, a species, any tier-1 value.
16413
+ */
16414
+ identityId: string().optional()
16171
16415
  });
16172
16416
  /**
16173
16417
  * The TIERED label model (roadmap 4g), spread into `TrackSchema` and
@@ -16304,6 +16548,28 @@ var TrackSchema = object({
16304
16548
  * `=== true` and render nothing otherwise, never infer "no face".
16305
16549
  */
16306
16550
  hasFace: boolean().optional(),
16551
+ /**
16552
+ * This subject CONTAINS a folded rider — a person the rider-pairing step
16553
+ * ([D34](../decisions/adr-0034.md)) removed from the frame BEFORE the tracker,
16554
+ * so the passage is tracked once and as a VEHICLE.
16555
+ *
16556
+ * It exists because the fold's record was dishonest. D34 and the code both
16557
+ * said "the person is not lost — it is reported so both entities stay on the
16558
+ * record"; in fact the pair went into a per-processor RAM field behind an
16559
+ * accessor nobody called, and every durable surface said `vehicle`, full
16560
+ * stop. This is the composition note that makes the row true.
16561
+ *
16562
+ * A COMPOSITION, never a class and never a label. "This vehicle contains a
16563
+ * person" is not an answer to "what is this" — both label tiers would refuse
16564
+ * a macro token anyway (D89), and correctly. Nothing here changes what the
16565
+ * subject IS: a cyclist stays one vehicle track, occupancy still counts one,
16566
+ * and a `person` rule still does not fire for someone cycling past.
16567
+ *
16568
+ * **Absent ≠ false**, exactly like {@link hasFace}: every row written before
16569
+ * the column, and every hub that predates the field, omits it. Test
16570
+ * `=== true` and render nothing otherwise — never infer "no rider".
16571
+ */
16572
+ hasRider: boolean().optional(),
16307
16573
  ...TrackFlagFields,
16308
16574
  ...TrackRetrainFields
16309
16575
  });
@@ -17770,7 +18036,7 @@ var detectionFpsField = {
17770
18036
  var occupancyRecheckSecField = {
17771
18037
  min: 0,
17772
18038
  max: 300,
17773
- default: 30,
18039
+ default: 300,
17774
18040
  step: 5
17775
18041
  };
17776
18042
  var occupancyRecheckFramesField = {
@@ -23136,7 +23402,41 @@ var intercomCapability = {
23136
23402
  status: {
23137
23403
  schema: IntercomStatusSchema,
23138
23404
  kind: "command-driven"
23139
- }
23405
+ },
23406
+ /**
23407
+ * Runtime-state slice — mirrored by the kernel.
23408
+ *
23409
+ * The cap declared `status` and nothing else, so the only two sources an
23410
+ * exporter has for a value — the `device.state-changed` slice event and the
23411
+ * `deviceState.getAllSnapshots` snapshot, both built from runtime state —
23412
+ * carried nothing for `intercom`. A talk-back entity in Home Assistant would
23413
+ * have been published and never received a value, which is the defect the
23414
+ * export's two classification tables exist to prevent (177 of them, once), so
23415
+ * `intercom` was excluded rather than exported.
23416
+ *
23417
+ * The shape is the status shape: there is exactly one truth about talk-back
23418
+ * and duplicating it into a second schema is how two halves of one capability
23419
+ * come to disagree. Providers write it through
23420
+ * `this.runtimeState.setCapState('intercom', …)` at the four points that open
23421
+ * and close a session, and seed it at registration so the slice exists before
23422
+ * the first session rather than after it.
23423
+ *
23424
+ * **Bound, named rather than hidden:** `talking` mirrors the provider's own
23425
+ * session handle, so a session torn down by a transport death that never
23426
+ * reaches `stopSession` / `endTalkSession` leaves it latched until the next
23427
+ * session or the next restart. That is why the slice is `session` and not
23428
+ * `restored` — a restart must never restore "talking".
23429
+ */
23430
+ runtimeState: IntercomStatusSchema,
23431
+ /**
23432
+ * Runtime-state durability: **session** — `talking` describes a live audio
23433
+ * session, which by definition does not survive the process that held it.
23434
+ * Restoring it would publish a camera as talking to nobody.
23435
+ *
23436
+ * See `RuntimeStateDurability`. Enforced by
23437
+ * `scripts/check-runtime-state-durability.ts`.
23438
+ */
23439
+ durability: "session"
23140
23440
  };
23141
23441
  /**
23142
23442
  * Robotic lawn-mower cap. Models HA `lawn_mower.*` entities — anything
@@ -25967,7 +26267,7 @@ method(object({
25967
26267
  toMs: number()
25968
26268
  }), RecordingAvailabilitySchema, {
25969
26269
  kind: "query",
25970
- auth: "admin"
26270
+ auth: "protected"
25971
26271
  }), method(object({
25972
26272
  deviceId: number(),
25973
26273
  fromMs: number(),
@@ -25975,14 +26275,14 @@ method(object({
25975
26275
  tzOffsetMinutes: number()
25976
26276
  }), RecordingDaysSchema, {
25977
26277
  kind: "query",
25978
- auth: "admin"
26278
+ auth: "protected"
25979
26279
  }), method(object({
25980
26280
  deviceId: number(),
25981
26281
  fromMs: number(),
25982
26282
  toMs: number()
25983
26283
  }), RecordingManifestSchema, {
25984
26284
  kind: "query",
25985
- auth: "admin"
26285
+ auth: "protected"
25986
26286
  }), method(object({}), RecordingStorageUsageSchema, {
25987
26287
  kind: "query",
25988
26288
  auth: "admin"
@@ -26277,9 +26577,33 @@ method(object({
26277
26577
  * settings-contribution methods. `status.kind:'push'` — the engine pushes on
26278
26578
  * every hysteresis flip / availability change; consumers never poll.
26279
26579
  */
26280
- /** Extensible condition tag. Seeded 'day' | 'night'; open by design so more can
26281
- * be added without a wire break (matching falls back to any-condition refs). */
26580
+ /** Extensible condition tag. Seeded 'day' | 'ir' (the two variants the operator
26581
+ * captures) plus 'night' | 'dawn' | 'dusk' from the resolver's sun-times band.
26582
+ * Open by design so more can be added without a wire break.
26583
+ *
26584
+ * Matching does NOT fall back across conditions: cross-condition cosines are
26585
+ * not comparable, so "I have never seen this scene in this light" is reported
26586
+ * as `unknown`, never guessed. A day reference scored against an IR frame
26587
+ * collapses the cosine and would latch a false alarm every single night. */
26282
26588
  var SceneConditionSchema = string();
26589
+ /** `matched` = the baseline is what we see; `diverged` = it demonstrably is not;
26590
+ * `unknown` = we cannot judge (no reference for this condition, encoder model
26591
+ * changed, view shifted, no snapshot). `unknown` is a real value, not a null,
26592
+ * and never counts toward hysteresis in either direction. */
26593
+ var SceneVerdictSchema = _enum([
26594
+ "matched",
26595
+ "diverged",
26596
+ "unknown"
26597
+ ]);
26598
+ /** Why a scene cannot judge. Named, because this feature's failure mode is
26599
+ * silence that reads as "nothing has happened". */
26600
+ var SceneUnavailableSchema = _enum([
26601
+ "no-reference-for-condition",
26602
+ "view-shifted",
26603
+ "no-vision-profile",
26604
+ "encoder-model-changed",
26605
+ "no-snapshot"
26606
+ ]);
26283
26607
  /** One captured reference — condition-tagged, model-version-gated. `embedding`
26284
26608
  * is `number[]` (Float32Array does NOT survive MsgPack/UDS). */
26285
26609
  var SceneReferenceSchema = object({
@@ -26287,7 +26611,14 @@ var SceneReferenceSchema = object({
26287
26611
  modelId: string(),
26288
26612
  condition: SceneConditionSchema,
26289
26613
  capturedAt: number(),
26290
- thumbnailMediaId: string().optional()
26614
+ thumbnailMediaId: string().optional(),
26615
+ /** Whole-frame (downscaled) embedding captured alongside the ROI crop. The
26616
+ * anti-view-shift anchor: a bumped camera, a PTZ preset or a re-aim makes the
26617
+ * normalized rect frame a different piece of world, and the scene would
26618
+ * diverge forever with a perfectly plausible cosine. Checked LAZILY, only
26619
+ * when hysteresis is about to flip — one extra encode per candidate
26620
+ * transition, not per poll. */
26621
+ anchorEmbedding: array(number()).optional()
26291
26622
  });
26292
26623
  var SceneMonitorStateSchema = object({
26293
26624
  id: string(),
@@ -26309,6 +26640,25 @@ var SceneCheckSchema = discriminatedUnion("mode", [object({
26309
26640
  profileId: string().optional(),
26310
26641
  hysteresisCount: number().int().positive()
26311
26642
  })]);
26643
+ var SCENE_DEFAULT_ANCHOR_THRESHOLD = .85;
26644
+ /**
26645
+ * Vision-model adjudication of a candidate flip. Field names deliberately
26646
+ * mirror `NcConfirmSchema` so an operator meets one vocabulary, not two.
26647
+ *
26648
+ * `onTimeout` defaults to **'hold'**, the OPPOSITE of `NcConfirmGate`'s
26649
+ * fail-open: a notification suppressed is the worse error there, but a vision
26650
+ * model that timed out has not told us the bin is gone, and a latch is a
26651
+ * stateful claim that costs the operator a trip to reset.
26652
+ */
26653
+ var SceneConfirmSchema = object({
26654
+ enabled: boolean().default(false),
26655
+ prompt: string().min(1).max(1e3),
26656
+ profileId: string().optional(),
26657
+ timeoutMs: number().int().min(1e3).max(2e4).default(8e3),
26658
+ maxImagePx: number().int().min(64).max(2048).default(448),
26659
+ /** What a timeout / unavailable model means for the PENDING flip. */
26660
+ onTimeout: _enum(["flip", "hold"]).default("hold")
26661
+ });
26312
26662
  var SceneMonitorSchema = object({
26313
26663
  id: string(),
26314
26664
  label: string(),
@@ -26327,7 +26677,41 @@ var SceneMonitorSchema = object({
26327
26677
  lastConfidence: number().nullable(),
26328
26678
  currentCondition: SceneConditionSchema.nullable(),
26329
26679
  availability: _enum(["ok", "unavailable"]),
26330
- unavailableReason: string().nullable()
26680
+ unavailableReason: string().nullable(),
26681
+ /** Which state is "the initial screen". `null` until the first capture. */
26682
+ baselineStateId: string().nullable(),
26683
+ /** Which boolean drives notification rules and any export. */
26684
+ emit: _enum(["latched", "live"]).default("latched"),
26685
+ /** Live: does the region match the baseline RIGHT NOW. */
26686
+ verdict: SceneVerdictSchema,
26687
+ /** Has it been `diverged` at least once since `armedAt` — the operator's boolean. */
26688
+ latched: boolean(),
26689
+ /** Last reset (or creation). */
26690
+ armedAt: number(),
26691
+ divergedAt: number().nullable(),
26692
+ restoredAt: number().nullable(),
26693
+ /** A check is only COUNTED when the device has been quiet this long. Motion
26694
+ * during the window DISCARDS the observation — a car pulling up in front of
26695
+ * the bin must not be able to spend hysteresis credit. */
26696
+ quietSeconds: number().int().min(0).max(3600).default(60),
26697
+ /** An observation only advances the pending count when it is at least this
26698
+ * far from the previously counted one, so N agreeing checks span real time
26699
+ * rather than N adjacent polls inside one occlusion. */
26700
+ minObservationSpacingSec: number().int().min(0).max(3600).default(120),
26701
+ /** Vision-model adjudication of a candidate flip. Similarity primary only. */
26702
+ confirm: SceneConfirmSchema.optional(),
26703
+ /** Whole-frame anchor cosine below which a flip is REFUSED as `view-shifted`. */
26704
+ anchorThreshold: number().min(0).max(1).default(SCENE_DEFAULT_ANCHOR_THRESHOLD),
26705
+ /** Clear the latch on its own when the scene matches again? Default false —
26706
+ * `restoredAt` and the `scene-restored` edge are recorded regardless, so an
26707
+ * automation can react to the bin coming back without the operator's own
26708
+ * alarm silently clearing itself. */
26709
+ autoRestore: boolean().default(false),
26710
+ /** Named cause when `verdict === 'unknown'`. */
26711
+ unavailable: SceneUnavailableSchema.nullable(),
26712
+ /** Conditions that have at least one comparable reference — the coverage line
26713
+ * ("day ✓ · ir ✓ · dusk ✗") that turns a silent fallback into a visible fact. */
26714
+ coveredConditions: array(SceneConditionSchema)
26331
26715
  });
26332
26716
  var SceneMonitorStatusSchema = object({
26333
26717
  monitors: array(SceneMonitorSchema),
@@ -26376,7 +26760,14 @@ var sceneMonitorCapability = {
26376
26760
  "both"
26377
26761
  ]).optional(),
26378
26762
  checkIntervalSec: number().optional(),
26379
- check: SceneCheckSchema.optional()
26763
+ check: SceneCheckSchema.optional(),
26764
+ emit: _enum(["latched", "live"]).optional(),
26765
+ quietSeconds: number().int().min(0).max(3600).optional(),
26766
+ minObservationSpacingSec: number().int().min(0).max(3600).optional(),
26767
+ anchorThreshold: number().min(0).max(1).optional(),
26768
+ autoRestore: boolean().optional(),
26769
+ /** `null` clears the vision-model adjudicator. */
26770
+ confirm: SceneConfirmSchema.nullable().optional()
26380
26771
  })
26381
26772
  }), _void(), {
26382
26773
  kind: "mutation",
@@ -26417,6 +26808,26 @@ var sceneMonitorCapability = {
26417
26808
  }), _void(), {
26418
26809
  kind: "mutation",
26419
26810
  auth: "admin"
26811
+ }),
26812
+ /**
26813
+ * Clear the latch, re-arm, and — by default — RE-CAPTURE the baseline for
26814
+ * the CURRENT condition. The bin never goes back in exactly the same spot;
26815
+ * "reset" in the operator's head means *this is the new normal*, and
26816
+ * re-capture is what makes the feature self-healing against slow drift
26817
+ * instead of failing silently weeks later.
26818
+ *
26819
+ * Reachable from three surfaces on this one mutation: the scene card, a
26820
+ * notification button (an `onTrigger` sequence with a `kind:'cap'` step —
26821
+ * no new Notification-Center code at all), and tRPC for scripts.
26822
+ */
26823
+ resetScene: method(object({
26824
+ deviceId: number(),
26825
+ monitorId: string(),
26826
+ /** Defaults to TRUE at the provider seam — see `SCENE_RESET_RECAPTURES`. */
26827
+ recapture: boolean().optional()
26828
+ }), _void(), {
26829
+ kind: "mutation",
26830
+ auth: "admin"
26420
26831
  })
26421
26832
  },
26422
26833
  status: {
@@ -28458,6 +28869,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
28458
28869
  humiditySensor: humiditySensorCapability,
28459
28870
  image: imageCapability,
28460
28871
  imageSettings: imageSettingsCapability,
28872
+ intercom: intercomCapability,
28461
28873
  lawnMowerControl: lawnMowerControlCapability,
28462
28874
  lockControl: lockControlCapability,
28463
28875
  mediaPlayer: mediaPlayerCapability,
@@ -33654,6 +34066,12 @@ Object.freeze({
33654
34066
  addonId: null,
33655
34067
  access: "create"
33656
34068
  },
34069
+ "sceneMonitor.resetScene": {
34070
+ capName: "scene-monitor",
34071
+ capScope: "device",
34072
+ addonId: null,
34073
+ access: "delete"
34074
+ },
33657
34075
  "sceneMonitor.updateScene": {
33658
34076
  capName: "scene-monitor",
33659
34077
  capScope: "device",
@@ -34945,6 +35363,1683 @@ Object.freeze({
34945
35363
  access: "create"
34946
35364
  }
34947
35365
  });
35366
+ Object.freeze({
35367
+ "accessories.setChildHidden": [{
35368
+ name: "childDeviceId",
35369
+ form: "single",
35370
+ optional: false
35371
+ }, {
35372
+ name: "deviceId",
35373
+ form: "single",
35374
+ optional: false
35375
+ }],
35376
+ "addonSettings.getDeviceSettings": [{
35377
+ name: "deviceId",
35378
+ form: "single",
35379
+ optional: false
35380
+ }],
35381
+ "addonSettings.updateDeviceSettings": [{
35382
+ name: "deviceId",
35383
+ form: "single",
35384
+ optional: false
35385
+ }],
35386
+ "alarmPanel.arm": [{
35387
+ name: "deviceId",
35388
+ form: "single",
35389
+ optional: false
35390
+ }],
35391
+ "alarmPanel.disarm": [{
35392
+ name: "deviceId",
35393
+ form: "single",
35394
+ optional: false
35395
+ }],
35396
+ "alarmPanel.trigger": [{
35397
+ name: "deviceId",
35398
+ form: "single",
35399
+ optional: false
35400
+ }],
35401
+ "audioAnalysis.resolveDeviceSettings": [{
35402
+ name: "deviceId",
35403
+ form: "single",
35404
+ optional: false
35405
+ }],
35406
+ "audioAnalyzer.classify": [{
35407
+ name: "deviceId",
35408
+ form: "single",
35409
+ optional: true
35410
+ }],
35411
+ "audioMetrics.getCurrentSnapshot": [{
35412
+ name: "deviceId",
35413
+ form: "single",
35414
+ optional: false
35415
+ }],
35416
+ "audioMetrics.getHistory": [{
35417
+ name: "deviceId",
35418
+ form: "single",
35419
+ optional: false
35420
+ }],
35421
+ "automationControl.disable": [{
35422
+ name: "deviceId",
35423
+ form: "single",
35424
+ optional: false
35425
+ }],
35426
+ "automationControl.enable": [{
35427
+ name: "deviceId",
35428
+ form: "single",
35429
+ optional: false
35430
+ }],
35431
+ "automationControl.trigger": [{
35432
+ name: "deviceId",
35433
+ form: "single",
35434
+ optional: false
35435
+ }],
35436
+ "battery.wakeForStream": [{
35437
+ name: "deviceId",
35438
+ form: "single",
35439
+ optional: false
35440
+ }],
35441
+ "brightness.setBrightness": [{
35442
+ name: "deviceId",
35443
+ form: "single",
35444
+ optional: false
35445
+ }],
35446
+ "button.press": [{
35447
+ name: "deviceId",
35448
+ form: "single",
35449
+ optional: false
35450
+ }],
35451
+ "cameraCredentials.getCredentials": [{
35452
+ name: "deviceId",
35453
+ form: "single",
35454
+ optional: false
35455
+ }],
35456
+ "cameraStreams.getBrokerStreams": [{
35457
+ name: "deviceId",
35458
+ form: "single",
35459
+ optional: false
35460
+ }],
35461
+ "cameraStreams.getCameraStreams": [{
35462
+ name: "deviceId",
35463
+ form: "single",
35464
+ optional: false
35465
+ }],
35466
+ "cameraStreams.getProfileRtspEntries": [{
35467
+ name: "deviceId",
35468
+ form: "single",
35469
+ optional: false
35470
+ }],
35471
+ "cameraStreams.getRtspEntries": [{
35472
+ name: "deviceId",
35473
+ form: "single",
35474
+ optional: false
35475
+ }],
35476
+ "cameraStreams.pickStream": [{
35477
+ name: "deviceId",
35478
+ form: "single",
35479
+ optional: false
35480
+ }],
35481
+ "climateControl.setFanMode": [{
35482
+ name: "deviceId",
35483
+ form: "single",
35484
+ optional: false
35485
+ }],
35486
+ "climateControl.setMode": [{
35487
+ name: "deviceId",
35488
+ form: "single",
35489
+ optional: false
35490
+ }],
35491
+ "climateControl.setPreset": [{
35492
+ name: "deviceId",
35493
+ form: "single",
35494
+ optional: false
35495
+ }],
35496
+ "climateControl.setSwingHorizontal": [{
35497
+ name: "deviceId",
35498
+ form: "single",
35499
+ optional: false
35500
+ }],
35501
+ "climateControl.setSwingVertical": [{
35502
+ name: "deviceId",
35503
+ form: "single",
35504
+ optional: false
35505
+ }],
35506
+ "climateControl.setTarget": [{
35507
+ name: "deviceId",
35508
+ form: "single",
35509
+ optional: false
35510
+ }],
35511
+ "climateControl.setTargetHumidity": [{
35512
+ name: "deviceId",
35513
+ form: "single",
35514
+ optional: false
35515
+ }],
35516
+ "climateControl.setTargetRange": [{
35517
+ name: "deviceId",
35518
+ form: "single",
35519
+ optional: false
35520
+ }],
35521
+ "color.setColor": [{
35522
+ name: "deviceId",
35523
+ form: "single",
35524
+ optional: false
35525
+ }],
35526
+ "consumables.reset": [{
35527
+ name: "deviceId",
35528
+ form: "single",
35529
+ optional: false
35530
+ }],
35531
+ "control.setValue": [{
35532
+ name: "deviceId",
35533
+ form: "single",
35534
+ optional: false
35535
+ }],
35536
+ "cover.close": [{
35537
+ name: "deviceId",
35538
+ form: "single",
35539
+ optional: false
35540
+ }],
35541
+ "cover.open": [{
35542
+ name: "deviceId",
35543
+ form: "single",
35544
+ optional: false
35545
+ }],
35546
+ "cover.setPosition": [{
35547
+ name: "deviceId",
35548
+ form: "single",
35549
+ optional: false
35550
+ }],
35551
+ "cover.setTiltPosition": [{
35552
+ name: "deviceId",
35553
+ form: "single",
35554
+ optional: false
35555
+ }],
35556
+ "cover.stop": [{
35557
+ name: "deviceId",
35558
+ form: "single",
35559
+ optional: false
35560
+ }],
35561
+ "dayNight.getOptions": [{
35562
+ name: "deviceId",
35563
+ form: "single",
35564
+ optional: false
35565
+ }],
35566
+ "dayNight.setSettings": [{
35567
+ name: "deviceId",
35568
+ form: "single",
35569
+ optional: false
35570
+ }],
35571
+ "decoder.createSession": [{
35572
+ name: "deviceId",
35573
+ form: "single",
35574
+ optional: true
35575
+ }],
35576
+ "deviceAdoption.release": [{
35577
+ name: "camDeviceId",
35578
+ form: "single",
35579
+ optional: false
35580
+ }],
35581
+ "deviceAdoption.resync": [{
35582
+ name: "camDeviceId",
35583
+ form: "single",
35584
+ optional: false
35585
+ }],
35586
+ "deviceDiscovery.adoptDevice": [{
35587
+ name: "deviceId",
35588
+ form: "single",
35589
+ optional: false
35590
+ }],
35591
+ "deviceDiscovery.listDiscovered": [{
35592
+ name: "deviceId",
35593
+ form: "single",
35594
+ optional: false
35595
+ }],
35596
+ "deviceDiscovery.refreshDiscovery": [{
35597
+ name: "deviceId",
35598
+ form: "single",
35599
+ optional: false
35600
+ }],
35601
+ "deviceDiscovery.releaseDevice": [{
35602
+ name: "childDeviceId",
35603
+ form: "single",
35604
+ optional: false
35605
+ }, {
35606
+ name: "deviceId",
35607
+ form: "single",
35608
+ optional: false
35609
+ }],
35610
+ "deviceManager.adoptionRelease": [{
35611
+ name: "camDeviceId",
35612
+ form: "single",
35613
+ optional: false
35614
+ }],
35615
+ "deviceManager.adoptionResync": [{
35616
+ name: "camDeviceId",
35617
+ form: "single",
35618
+ optional: false
35619
+ }],
35620
+ "deviceManager.applyInitialMeta": [{
35621
+ name: "deviceId",
35622
+ form: "single",
35623
+ optional: false
35624
+ }, {
35625
+ name: "linkDeviceId",
35626
+ form: "single",
35627
+ optional: true
35628
+ }],
35629
+ "deviceManager.disable": [{
35630
+ name: "deviceId",
35631
+ form: "single",
35632
+ optional: false
35633
+ }],
35634
+ "deviceManager.enable": [{
35635
+ name: "deviceId",
35636
+ form: "single",
35637
+ optional: false
35638
+ }],
35639
+ "deviceManager.getBindings": [{
35640
+ name: "deviceId",
35641
+ form: "single",
35642
+ optional: false
35643
+ }],
35644
+ "deviceManager.getChildren": [{
35645
+ name: "parentDeviceId",
35646
+ form: "single",
35647
+ optional: false
35648
+ }],
35649
+ "deviceManager.getConfigSchema": [{
35650
+ name: "deviceId",
35651
+ form: "single",
35652
+ optional: false
35653
+ }],
35654
+ "deviceManager.getDevice": [{
35655
+ name: "deviceId",
35656
+ form: "single",
35657
+ optional: false
35658
+ }],
35659
+ "deviceManager.getDeviceAggregate": [{
35660
+ name: "deviceId",
35661
+ form: "single",
35662
+ optional: false
35663
+ }],
35664
+ "deviceManager.getDeviceLiveInfoAggregate": [{
35665
+ name: "deviceId",
35666
+ form: "single",
35667
+ optional: false
35668
+ }],
35669
+ "deviceManager.getDeviceSettingsAggregate": [{
35670
+ name: "deviceId",
35671
+ form: "single",
35672
+ optional: false
35673
+ }],
35674
+ "deviceManager.getDeviceStatusAggregate": [{
35675
+ name: "deviceId",
35676
+ form: "single",
35677
+ optional: false
35678
+ }],
35679
+ "deviceManager.getDeviceStatusAggregateBatch": [{
35680
+ name: "deviceIds",
35681
+ form: "array",
35682
+ optional: false
35683
+ }],
35684
+ "deviceManager.getLinkedDevices": [{
35685
+ name: "deviceId",
35686
+ form: "single",
35687
+ optional: false
35688
+ }],
35689
+ "deviceManager.getSettingsSchema": [{
35690
+ name: "deviceId",
35691
+ form: "single",
35692
+ optional: false
35693
+ }],
35694
+ "deviceManager.getStreamProfileMap": [{
35695
+ name: "deviceId",
35696
+ form: "single",
35697
+ optional: false
35698
+ }],
35699
+ "deviceManager.getStreamSources": [{
35700
+ name: "deviceId",
35701
+ form: "single",
35702
+ optional: false
35703
+ }],
35704
+ "deviceManager.getWireableFields": [{
35705
+ name: "deviceId",
35706
+ form: "single",
35707
+ optional: false
35708
+ }],
35709
+ "deviceManager.loadConfig": [{
35710
+ name: "deviceId",
35711
+ form: "single",
35712
+ optional: false
35713
+ }],
35714
+ "deviceManager.loadMeta": [{
35715
+ name: "deviceId",
35716
+ form: "single",
35717
+ optional: false
35718
+ }],
35719
+ "deviceManager.loadRuntimeState": [{
35720
+ name: "deviceId",
35721
+ form: "single",
35722
+ optional: false
35723
+ }],
35724
+ "deviceManager.persistConfig": [{
35725
+ name: "deviceId",
35726
+ form: "single",
35727
+ optional: false
35728
+ }],
35729
+ "deviceManager.probeStreams": [{
35730
+ name: "deviceId",
35731
+ form: "single",
35732
+ optional: false
35733
+ }],
35734
+ "deviceManager.registerDevice": [{
35735
+ name: "parentDeviceId",
35736
+ form: "single",
35737
+ optional: true
35738
+ }],
35739
+ "deviceManager.remove": [{
35740
+ name: "deviceId",
35741
+ form: "single",
35742
+ optional: false
35743
+ }],
35744
+ "deviceManager.removeDevice": [{
35745
+ name: "deviceId",
35746
+ form: "single",
35747
+ optional: false
35748
+ }],
35749
+ "deviceManager.runDeviceAction": [{
35750
+ name: "deviceId",
35751
+ form: "single",
35752
+ optional: false
35753
+ }],
35754
+ "deviceManager.setChildLayout": [{
35755
+ name: "deviceId",
35756
+ form: "single",
35757
+ optional: false
35758
+ }],
35759
+ "deviceManager.setDisabled": [{
35760
+ name: "deviceId",
35761
+ form: "single",
35762
+ optional: false
35763
+ }],
35764
+ "deviceManager.setDisplay": [{
35765
+ name: "deviceId",
35766
+ form: "single",
35767
+ optional: false
35768
+ }],
35769
+ "deviceManager.setIntegrationId": [{
35770
+ name: "deviceId",
35771
+ form: "single",
35772
+ optional: false
35773
+ }],
35774
+ "deviceManager.setLinkDeviceId": [{
35775
+ name: "deviceId",
35776
+ form: "single",
35777
+ optional: false
35778
+ }, {
35779
+ name: "linkDeviceId",
35780
+ form: "single",
35781
+ optional: true
35782
+ }],
35783
+ "deviceManager.setLocation": [{
35784
+ name: "deviceId",
35785
+ form: "single",
35786
+ optional: false
35787
+ }],
35788
+ "deviceManager.setMetadata": [{
35789
+ name: "deviceId",
35790
+ form: "single",
35791
+ optional: false
35792
+ }],
35793
+ "deviceManager.setName": [{
35794
+ name: "deviceId",
35795
+ form: "single",
35796
+ optional: false
35797
+ }],
35798
+ "deviceManager.setPrimaryChildEntityId": [{
35799
+ name: "deviceId",
35800
+ form: "single",
35801
+ optional: false
35802
+ }],
35803
+ "deviceManager.setRole": [{
35804
+ name: "deviceId",
35805
+ form: "single",
35806
+ optional: false
35807
+ }],
35808
+ "deviceManager.setStreamProfileMap": [{
35809
+ name: "deviceId",
35810
+ form: "single",
35811
+ optional: false
35812
+ }],
35813
+ "deviceManager.setType": [{
35814
+ name: "deviceId",
35815
+ form: "single",
35816
+ optional: false
35817
+ }],
35818
+ "deviceManager.setWrapperActive": [{
35819
+ name: "deviceId",
35820
+ form: "single",
35821
+ optional: false
35822
+ }],
35823
+ "deviceManager.testField": [{
35824
+ name: "deviceId",
35825
+ form: "single",
35826
+ optional: false
35827
+ }],
35828
+ "deviceManager.updateConfig": [{
35829
+ name: "deviceId",
35830
+ form: "single",
35831
+ optional: false
35832
+ }],
35833
+ "deviceManager.updateDeviceField": [{
35834
+ name: "deviceId",
35835
+ form: "single",
35836
+ optional: false
35837
+ }],
35838
+ "deviceManager.updateDeviceFieldsBatch": [{
35839
+ name: "deviceId",
35840
+ form: "single",
35841
+ optional: false
35842
+ }],
35843
+ "deviceOps.getConfigEntries": [{
35844
+ name: "deviceId",
35845
+ form: "single",
35846
+ optional: false
35847
+ }],
35848
+ "deviceOps.getRawState": [{
35849
+ name: "deviceId",
35850
+ form: "single",
35851
+ optional: false
35852
+ }],
35853
+ "deviceOps.getSettingsSchema": [{
35854
+ name: "deviceId",
35855
+ form: "single",
35856
+ optional: false
35857
+ }],
35858
+ "deviceOps.getStreamSources": [{
35859
+ name: "deviceId",
35860
+ form: "single",
35861
+ optional: false
35862
+ }],
35863
+ "deviceOps.removeDevice": [{
35864
+ name: "deviceId",
35865
+ form: "single",
35866
+ optional: false
35867
+ }],
35868
+ "deviceOps.runAction": [{
35869
+ name: "deviceId",
35870
+ form: "single",
35871
+ optional: false
35872
+ }],
35873
+ "deviceOps.setConfig": [{
35874
+ name: "deviceId",
35875
+ form: "single",
35876
+ optional: false
35877
+ }],
35878
+ "deviceState.getCapSlice": [{
35879
+ name: "deviceId",
35880
+ form: "single",
35881
+ optional: false
35882
+ }],
35883
+ "deviceState.getSnapshot": [{
35884
+ name: "deviceId",
35885
+ form: "single",
35886
+ optional: false
35887
+ }],
35888
+ "deviceState.setCapSlice": [{
35889
+ name: "deviceId",
35890
+ form: "single",
35891
+ optional: false
35892
+ }],
35893
+ "events.getEventClipUrl": [{
35894
+ name: "deviceId",
35895
+ form: "single",
35896
+ optional: false
35897
+ }],
35898
+ "events.getEvents": [{
35899
+ name: "deviceId",
35900
+ form: "single",
35901
+ optional: false
35902
+ }],
35903
+ "events.getEventThumbnail": [{
35904
+ name: "deviceId",
35905
+ form: "single",
35906
+ optional: false
35907
+ }],
35908
+ "faceGallery.getFaceByTrack": [{
35909
+ name: "deviceId",
35910
+ form: "single",
35911
+ optional: false
35912
+ }],
35913
+ "faceGallery.listRecentFaces": [{
35914
+ name: "deviceId",
35915
+ form: "single",
35916
+ optional: true
35917
+ }],
35918
+ "fanControl.setDirection": [{
35919
+ name: "deviceId",
35920
+ form: "single",
35921
+ optional: false
35922
+ }],
35923
+ "fanControl.setOscillating": [{
35924
+ name: "deviceId",
35925
+ form: "single",
35926
+ optional: false
35927
+ }],
35928
+ "fanControl.setPercentage": [{
35929
+ name: "deviceId",
35930
+ form: "single",
35931
+ optional: false
35932
+ }],
35933
+ "fanControl.setPreset": [{
35934
+ name: "deviceId",
35935
+ form: "single",
35936
+ optional: false
35937
+ }],
35938
+ "humidifier.setMode": [{
35939
+ name: "deviceId",
35940
+ form: "single",
35941
+ optional: false
35942
+ }],
35943
+ "humidifier.setOn": [{
35944
+ name: "deviceId",
35945
+ form: "single",
35946
+ optional: false
35947
+ }],
35948
+ "humidifier.setTargetHumidity": [{
35949
+ name: "deviceId",
35950
+ form: "single",
35951
+ optional: false
35952
+ }],
35953
+ "imageSettings.getOptions": [{
35954
+ name: "deviceId",
35955
+ form: "single",
35956
+ optional: false
35957
+ }],
35958
+ "imageSettings.setSettings": [{
35959
+ name: "deviceId",
35960
+ form: "single",
35961
+ optional: false
35962
+ }],
35963
+ "intercom.endTalkSession": [{
35964
+ name: "deviceId",
35965
+ form: "single",
35966
+ optional: false
35967
+ }],
35968
+ "intercom.handleAnswer": [{
35969
+ name: "deviceId",
35970
+ form: "single",
35971
+ optional: false
35972
+ }],
35973
+ "intercom.pushTalkAudio": [{
35974
+ name: "deviceId",
35975
+ form: "single",
35976
+ optional: false
35977
+ }],
35978
+ "intercom.startSession": [{
35979
+ name: "deviceId",
35980
+ form: "single",
35981
+ optional: false
35982
+ }],
35983
+ "intercom.startTalkSession": [{
35984
+ name: "deviceId",
35985
+ form: "single",
35986
+ optional: false
35987
+ }],
35988
+ "intercom.stopSession": [{
35989
+ name: "deviceId",
35990
+ form: "single",
35991
+ optional: false
35992
+ }],
35993
+ "lawnMowerControl.dock": [{
35994
+ name: "deviceId",
35995
+ form: "single",
35996
+ optional: false
35997
+ }],
35998
+ "lawnMowerControl.pause": [{
35999
+ name: "deviceId",
36000
+ form: "single",
36001
+ optional: false
36002
+ }],
36003
+ "lawnMowerControl.startMowing": [{
36004
+ name: "deviceId",
36005
+ form: "single",
36006
+ optional: false
36007
+ }],
36008
+ "lockControl.lock": [{
36009
+ name: "deviceId",
36010
+ form: "single",
36011
+ optional: false
36012
+ }],
36013
+ "lockControl.open": [{
36014
+ name: "deviceId",
36015
+ form: "single",
36016
+ optional: false
36017
+ }],
36018
+ "lockControl.unlock": [{
36019
+ name: "deviceId",
36020
+ form: "single",
36021
+ optional: false
36022
+ }],
36023
+ "mediaPlayer.next": [{
36024
+ name: "deviceId",
36025
+ form: "single",
36026
+ optional: false
36027
+ }],
36028
+ "mediaPlayer.pause": [{
36029
+ name: "deviceId",
36030
+ form: "single",
36031
+ optional: false
36032
+ }],
36033
+ "mediaPlayer.play": [{
36034
+ name: "deviceId",
36035
+ form: "single",
36036
+ optional: false
36037
+ }],
36038
+ "mediaPlayer.playMedia": [{
36039
+ name: "deviceId",
36040
+ form: "single",
36041
+ optional: false
36042
+ }],
36043
+ "mediaPlayer.previous": [{
36044
+ name: "deviceId",
36045
+ form: "single",
36046
+ optional: false
36047
+ }],
36048
+ "mediaPlayer.seek": [{
36049
+ name: "deviceId",
36050
+ form: "single",
36051
+ optional: false
36052
+ }],
36053
+ "mediaPlayer.selectSource": [{
36054
+ name: "deviceId",
36055
+ form: "single",
36056
+ optional: false
36057
+ }],
36058
+ "mediaPlayer.setMute": [{
36059
+ name: "deviceId",
36060
+ form: "single",
36061
+ optional: false
36062
+ }],
36063
+ "mediaPlayer.setRepeat": [{
36064
+ name: "deviceId",
36065
+ form: "single",
36066
+ optional: false
36067
+ }],
36068
+ "mediaPlayer.setShuffle": [{
36069
+ name: "deviceId",
36070
+ form: "single",
36071
+ optional: false
36072
+ }],
36073
+ "mediaPlayer.setVolume": [{
36074
+ name: "deviceId",
36075
+ form: "single",
36076
+ optional: false
36077
+ }],
36078
+ "mediaPlayer.stop": [{
36079
+ name: "deviceId",
36080
+ form: "single",
36081
+ optional: false
36082
+ }],
36083
+ "motion.isDetected": [{
36084
+ name: "deviceId",
36085
+ form: "single",
36086
+ optional: false
36087
+ }],
36088
+ "motionDetection.analyze": [{
36089
+ name: "deviceId",
36090
+ form: "single",
36091
+ optional: false
36092
+ }],
36093
+ "motionDetection.removeCamera": [{
36094
+ name: "deviceId",
36095
+ form: "single",
36096
+ optional: false
36097
+ }],
36098
+ "motionTrigger.setMotionTrigger": [{
36099
+ name: "deviceId",
36100
+ form: "single",
36101
+ optional: false
36102
+ }],
36103
+ "motionZones.getOptions": [{
36104
+ name: "deviceId",
36105
+ form: "single",
36106
+ optional: false
36107
+ }],
36108
+ "motionZones.setZone": [{
36109
+ name: "deviceId",
36110
+ form: "single",
36111
+ optional: false
36112
+ }],
36113
+ "nativeObjectDetection.setEnabled": [{
36114
+ name: "deviceId",
36115
+ form: "single",
36116
+ optional: false
36117
+ }],
36118
+ "networkQuality.getDeviceStats": [{
36119
+ name: "deviceId",
36120
+ form: "single",
36121
+ optional: false
36122
+ }],
36123
+ "networkQuality.reportClientStats": [{
36124
+ name: "deviceId",
36125
+ form: "single",
36126
+ optional: false
36127
+ }],
36128
+ "notificationRules.setDeviceMuted": [{
36129
+ name: "deviceId",
36130
+ form: "single",
36131
+ optional: false
36132
+ }],
36133
+ "notifier.cancel": [{
36134
+ name: "deviceId",
36135
+ form: "single",
36136
+ optional: false
36137
+ }],
36138
+ "notifier.send": [{
36139
+ name: "deviceId",
36140
+ form: "single",
36141
+ optional: false
36142
+ }],
36143
+ "osd.setOverlay": [{
36144
+ name: "deviceId",
36145
+ form: "single",
36146
+ optional: false
36147
+ }],
36148
+ "osdManager.clearSlotBinding": [{
36149
+ name: "deviceId",
36150
+ form: "single",
36151
+ optional: false
36152
+ }],
36153
+ "osdManager.copyDeviceConfiguration": [{
36154
+ name: "sourceDeviceId",
36155
+ form: "single",
36156
+ optional: false
36157
+ }, {
36158
+ name: "targetDeviceId",
36159
+ form: "single",
36160
+ optional: false
36161
+ }],
36162
+ "osdManager.getDeviceOsd": [{
36163
+ name: "deviceId",
36164
+ form: "single",
36165
+ optional: false
36166
+ }],
36167
+ "osdManager.getSourceCatalog": [{
36168
+ name: "deviceId",
36169
+ form: "single",
36170
+ optional: false
36171
+ }],
36172
+ "osdManager.previewSlot": [{
36173
+ name: "deviceId",
36174
+ form: "single",
36175
+ optional: false
36176
+ }],
36177
+ "osdManager.renderDevice": [{
36178
+ name: "deviceId",
36179
+ form: "single",
36180
+ optional: false
36181
+ }],
36182
+ "osdManager.setSlotBinding": [{
36183
+ name: "deviceId",
36184
+ form: "single",
36185
+ optional: false
36186
+ }],
36187
+ "petFeeder.callPet": [{
36188
+ name: "deviceId",
36189
+ form: "single",
36190
+ optional: false
36191
+ }],
36192
+ "petFeeder.cancelFeed": [{
36193
+ name: "deviceId",
36194
+ form: "single",
36195
+ optional: false
36196
+ }],
36197
+ "petFeeder.feed": [{
36198
+ name: "deviceId",
36199
+ form: "single",
36200
+ optional: false
36201
+ }],
36202
+ "petFeeder.markFoodReplenished": [{
36203
+ name: "deviceId",
36204
+ form: "single",
36205
+ optional: false
36206
+ }],
36207
+ "petFeeder.playSound": [{
36208
+ name: "deviceId",
36209
+ form: "single",
36210
+ optional: false
36211
+ }],
36212
+ "petFeeder.resetDesiccant": [{
36213
+ name: "deviceId",
36214
+ form: "single",
36215
+ optional: false
36216
+ }],
36217
+ "petFeeder.setChildLock": [{
36218
+ name: "deviceId",
36219
+ form: "single",
36220
+ optional: false
36221
+ }],
36222
+ "petFeeder.setFeedSound": [{
36223
+ name: "deviceId",
36224
+ form: "single",
36225
+ optional: false
36226
+ }],
36227
+ "petFeeder.setIndicatorLight": [{
36228
+ name: "deviceId",
36229
+ form: "single",
36230
+ optional: false
36231
+ }],
36232
+ "petFeeder.setVolume": [{
36233
+ name: "deviceId",
36234
+ form: "single",
36235
+ optional: false
36236
+ }],
36237
+ "pipelineAnalytics.clearTracks": [{
36238
+ name: "deviceId",
36239
+ form: "single",
36240
+ optional: false
36241
+ }],
36242
+ "pipelineAnalytics.completeRetrainTrack": [{
36243
+ name: "deviceId",
36244
+ form: "single",
36245
+ optional: false
36246
+ }],
36247
+ "pipelineAnalytics.deleteDeviceEvents": [{
36248
+ name: "deviceId",
36249
+ form: "single",
36250
+ optional: false
36251
+ }],
36252
+ "pipelineAnalytics.deleteTracks": [{
36253
+ name: "deviceId",
36254
+ form: "single",
36255
+ optional: false
36256
+ }],
36257
+ "pipelineAnalytics.deselectRetrainFrame": [{
36258
+ name: "deviceId",
36259
+ form: "single",
36260
+ optional: false
36261
+ }],
36262
+ "pipelineAnalytics.getActiveTracks": [{
36263
+ name: "deviceId",
36264
+ form: "single",
36265
+ optional: false
36266
+ }],
36267
+ "pipelineAnalytics.getAudioEvents": [{
36268
+ name: "deviceId",
36269
+ form: "single",
36270
+ optional: false
36271
+ }],
36272
+ "pipelineAnalytics.getEventDensity": [{
36273
+ name: "deviceId",
36274
+ form: "single",
36275
+ optional: false
36276
+ }],
36277
+ "pipelineAnalytics.getKeyEvents": [{
36278
+ name: "deviceId",
36279
+ form: "single",
36280
+ optional: false
36281
+ }],
36282
+ "pipelineAnalytics.getMotionEvents": [{
36283
+ name: "deviceId",
36284
+ form: "single",
36285
+ optional: false
36286
+ }],
36287
+ "pipelineAnalytics.getObjectEvents": [{
36288
+ name: "deviceId",
36289
+ form: "single",
36290
+ optional: false
36291
+ }],
36292
+ "pipelineAnalytics.getRetrainExportUrl": [{
36293
+ name: "deviceIds",
36294
+ form: "array",
36295
+ optional: true
36296
+ }],
36297
+ "pipelineAnalytics.getSensorEvents": [{
36298
+ name: "deviceId",
36299
+ form: "single",
36300
+ optional: false
36301
+ }],
36302
+ "pipelineAnalytics.getTrack": [{
36303
+ name: "deviceId",
36304
+ form: "single",
36305
+ optional: false
36306
+ }],
36307
+ "pipelineAnalytics.getTrainingExportSummary": [{
36308
+ name: "deviceIds",
36309
+ form: "array",
36310
+ optional: true
36311
+ }],
36312
+ "pipelineAnalytics.getTrainingExportUrl": [{
36313
+ name: "deviceIds",
36314
+ form: "array",
36315
+ optional: true
36316
+ }],
36317
+ "pipelineAnalytics.listEventKinds": [{
36318
+ name: "deviceId",
36319
+ form: "single",
36320
+ optional: false
36321
+ }],
36322
+ "pipelineAnalytics.listEventKindsBatch": [{
36323
+ name: "deviceIds",
36324
+ form: "array",
36325
+ optional: false
36326
+ }],
36327
+ "pipelineAnalytics.listOpsLog": [{
36328
+ name: "deviceId",
36329
+ form: "single",
36330
+ optional: true
36331
+ }],
36332
+ "pipelineAnalytics.listRecentTracks": [{
36333
+ name: "deviceIds",
36334
+ form: "array",
36335
+ optional: false
36336
+ }],
36337
+ "pipelineAnalytics.listRetrainStaging": [{
36338
+ name: "deviceIds",
36339
+ form: "array",
36340
+ optional: true
36341
+ }],
36342
+ "pipelineAnalytics.listTracks": [{
36343
+ name: "deviceId",
36344
+ form: "single",
36345
+ optional: false
36346
+ }],
36347
+ "pipelineAnalytics.proposeRetrainAnnotations": [{
36348
+ name: "deviceId",
36349
+ form: "single",
36350
+ optional: false
36351
+ }],
36352
+ "pipelineAnalytics.pruneEventsBefore": [{
36353
+ name: "deviceId",
36354
+ form: "single",
36355
+ optional: false
36356
+ }],
36357
+ "pipelineAnalytics.pruneTracksBefore": [{
36358
+ name: "deviceId",
36359
+ form: "single",
36360
+ optional: false
36361
+ }],
36362
+ "pipelineAnalytics.rebuildObjectEmbeddings": [{
36363
+ name: "deviceId",
36364
+ form: "single",
36365
+ optional: true
36366
+ }],
36367
+ "pipelineAnalytics.restageRetrainTrack": [{
36368
+ name: "deviceId",
36369
+ form: "single",
36370
+ optional: false
36371
+ }],
36372
+ "pipelineAnalytics.saveRetrainAnnotations": [{
36373
+ name: "deviceId",
36374
+ form: "single",
36375
+ optional: false
36376
+ }],
36377
+ "pipelineAnalytics.searchObjectEvents": [{
36378
+ name: "deviceId",
36379
+ form: "single",
36380
+ optional: true
36381
+ }],
36382
+ "pipelineAnalytics.selectRetrainFrames": [{
36383
+ name: "deviceId",
36384
+ form: "single",
36385
+ optional: false
36386
+ }],
36387
+ "pipelineAnalytics.setTrackFlags": [{
36388
+ name: "deviceId",
36389
+ form: "single",
36390
+ optional: false
36391
+ }],
36392
+ "pipelineAnalytics.wipeAllAnalytics": [{
36393
+ name: "deviceId",
36394
+ form: "single",
36395
+ optional: false
36396
+ }],
36397
+ "pipelineExecutor.runPipeline": [{
36398
+ name: "deviceId",
36399
+ form: "single",
36400
+ optional: true
36401
+ }],
36402
+ "pipelineExecutor.runPipelineBatch": [{
36403
+ name: "deviceId",
36404
+ form: "single",
36405
+ optional: true
36406
+ }],
36407
+ "pipelineOrchestrator.assignAudio": [{
36408
+ name: "deviceId",
36409
+ form: "single",
36410
+ optional: false
36411
+ }],
36412
+ "pipelineOrchestrator.assignPipeline": [{
36413
+ name: "deviceId",
36414
+ form: "single",
36415
+ optional: false
36416
+ }],
36417
+ "pipelineOrchestrator.getAudioAssignment": [{
36418
+ name: "deviceId",
36419
+ form: "single",
36420
+ optional: false
36421
+ }],
36422
+ "pipelineOrchestrator.getCameraMetrics": [{
36423
+ name: "deviceId",
36424
+ form: "single",
36425
+ optional: false
36426
+ }],
36427
+ "pipelineOrchestrator.getCameraSettings": [{
36428
+ name: "deviceId",
36429
+ form: "single",
36430
+ optional: false
36431
+ }],
36432
+ "pipelineOrchestrator.getCameraStatus": [{
36433
+ name: "deviceId",
36434
+ form: "single",
36435
+ optional: false
36436
+ }],
36437
+ "pipelineOrchestrator.getCameraStatuses": [{
36438
+ name: "deviceIds",
36439
+ form: "array",
36440
+ optional: true
36441
+ }],
36442
+ "pipelineOrchestrator.getCameraStepOverrides": [{
36443
+ name: "deviceId",
36444
+ form: "single",
36445
+ optional: false
36446
+ }],
36447
+ "pipelineOrchestrator.getCameraSwitches": [{
36448
+ name: "deviceId",
36449
+ form: "single",
36450
+ optional: false
36451
+ }],
36452
+ "pipelineOrchestrator.getPipelineAssignment": [{
36453
+ name: "deviceId",
36454
+ form: "single",
36455
+ optional: false
36456
+ }],
36457
+ "pipelineOrchestrator.getPipelineDevicePin": [{
36458
+ name: "deviceId",
36459
+ form: "single",
36460
+ optional: false
36461
+ }],
36462
+ "pipelineOrchestrator.resolvePipeline": [{
36463
+ name: "deviceId",
36464
+ form: "single",
36465
+ optional: false
36466
+ }],
36467
+ "pipelineOrchestrator.setCameraPipelineForAgent": [{
36468
+ name: "deviceId",
36469
+ form: "single",
36470
+ optional: false
36471
+ }],
36472
+ "pipelineOrchestrator.setCameraStepOverride": [{
36473
+ name: "deviceId",
36474
+ form: "single",
36475
+ optional: false
36476
+ }],
36477
+ "pipelineOrchestrator.setCameraStepToggle": [{
36478
+ name: "deviceId",
36479
+ form: "single",
36480
+ optional: false
36481
+ }],
36482
+ "pipelineOrchestrator.setCameraSwitch": [{
36483
+ name: "deviceId",
36484
+ form: "single",
36485
+ optional: false
36486
+ }],
36487
+ "pipelineOrchestrator.setPipelineDevicePin": [{
36488
+ name: "deviceId",
36489
+ form: "single",
36490
+ optional: false
36491
+ }],
36492
+ "pipelineOrchestrator.unassignAudio": [{
36493
+ name: "deviceId",
36494
+ form: "single",
36495
+ optional: false
36496
+ }],
36497
+ "pipelineOrchestrator.unassignPipeline": [{
36498
+ name: "deviceId",
36499
+ form: "single",
36500
+ optional: false
36501
+ }],
36502
+ "pipelineRunner.attachCamera": [{
36503
+ name: "deviceId",
36504
+ form: "single",
36505
+ optional: false
36506
+ }],
36507
+ "pipelineRunner.detachCamera": [{
36508
+ name: "deviceId",
36509
+ form: "single",
36510
+ optional: false
36511
+ }],
36512
+ "pipelineRunner.getCameraMetrics": [{
36513
+ name: "deviceId",
36514
+ form: "single",
36515
+ optional: false
36516
+ }],
36517
+ "pipelineRunner.reportMotion": [{
36518
+ name: "deviceId",
36519
+ form: "single",
36520
+ optional: false
36521
+ }],
36522
+ "pipelineRunner.runDetailSubtree": [{
36523
+ name: "deviceId",
36524
+ form: "single",
36525
+ optional: false
36526
+ }],
36527
+ "pipelineRunner.runStatelessStep": [{
36528
+ name: "sourceDeviceId",
36529
+ form: "single",
36530
+ optional: false
36531
+ }],
36532
+ "plateGallery.getPlateByTrack": [{
36533
+ name: "deviceId",
36534
+ form: "single",
36535
+ optional: false
36536
+ }],
36537
+ "plateGallery.listPlates": [{
36538
+ name: "deviceId",
36539
+ form: "single",
36540
+ optional: true
36541
+ }],
36542
+ "privacyMask.getOptions": [{
36543
+ name: "deviceId",
36544
+ form: "single",
36545
+ optional: false
36546
+ }],
36547
+ "privacyMask.setAudioEnabled": [{
36548
+ name: "deviceId",
36549
+ form: "single",
36550
+ optional: false
36551
+ }],
36552
+ "privacyMask.setMask": [{
36553
+ name: "deviceId",
36554
+ form: "single",
36555
+ optional: false
36556
+ }],
36557
+ "ptz.continuousMove": [{
36558
+ name: "deviceId",
36559
+ form: "single",
36560
+ optional: false
36561
+ }],
36562
+ "ptz.deletePreset": [{
36563
+ name: "deviceId",
36564
+ form: "single",
36565
+ optional: false
36566
+ }],
36567
+ "ptz.getOptions": [{
36568
+ name: "deviceId",
36569
+ form: "single",
36570
+ optional: false
36571
+ }],
36572
+ "ptz.getPosition": [{
36573
+ name: "deviceId",
36574
+ form: "single",
36575
+ optional: false
36576
+ }],
36577
+ "ptz.getPresets": [{
36578
+ name: "deviceId",
36579
+ form: "single",
36580
+ optional: false
36581
+ }],
36582
+ "ptz.goHome": [{
36583
+ name: "deviceId",
36584
+ form: "single",
36585
+ optional: false
36586
+ }],
36587
+ "ptz.goToPreset": [{
36588
+ name: "deviceId",
36589
+ form: "single",
36590
+ optional: false
36591
+ }],
36592
+ "ptz.move": [{
36593
+ name: "deviceId",
36594
+ form: "single",
36595
+ optional: false
36596
+ }],
36597
+ "ptz.savePreset": [{
36598
+ name: "deviceId",
36599
+ form: "single",
36600
+ optional: false
36601
+ }],
36602
+ "ptz.setAutofocus": [{
36603
+ name: "deviceId",
36604
+ form: "single",
36605
+ optional: false
36606
+ }],
36607
+ "ptz.stop": [{
36608
+ name: "deviceId",
36609
+ form: "single",
36610
+ optional: false
36611
+ }],
36612
+ "ptzAutotrack.getSettings": [{
36613
+ name: "deviceId",
36614
+ form: "single",
36615
+ optional: false
36616
+ }],
36617
+ "ptzAutotrack.getStatus": [{
36618
+ name: "deviceId",
36619
+ form: "single",
36620
+ optional: false
36621
+ }],
36622
+ "ptzAutotrack.setEnabled": [{
36623
+ name: "deviceId",
36624
+ form: "single",
36625
+ optional: false
36626
+ }],
36627
+ "ptzAutotrack.setSettings": [{
36628
+ name: "deviceId",
36629
+ form: "single",
36630
+ optional: false
36631
+ }],
36632
+ "reboot.reboot": [{
36633
+ name: "deviceId",
36634
+ form: "single",
36635
+ optional: false
36636
+ }],
36637
+ "recording.deleteFootprint": [{
36638
+ name: "deviceId",
36639
+ form: "single",
36640
+ optional: false
36641
+ }],
36642
+ "recording.getAvailability": [{
36643
+ name: "deviceId",
36644
+ form: "single",
36645
+ optional: false
36646
+ }],
36647
+ "recording.getDaysWithRecordings": [{
36648
+ name: "deviceId",
36649
+ form: "single",
36650
+ optional: false
36651
+ }],
36652
+ "recording.getDeviceConfig": [{
36653
+ name: "deviceId",
36654
+ form: "single",
36655
+ optional: false
36656
+ }],
36657
+ "recording.getPlaybackManifest": [{
36658
+ name: "deviceId",
36659
+ form: "single",
36660
+ optional: false
36661
+ }],
36662
+ "recording.listOpsLog": [{
36663
+ name: "deviceId",
36664
+ form: "single",
36665
+ optional: true
36666
+ }],
36667
+ "recording.locateSegment": [{
36668
+ name: "deviceId",
36669
+ form: "single",
36670
+ optional: false
36671
+ }],
36672
+ "recording.pruneFootage": [{
36673
+ name: "deviceId",
36674
+ form: "single",
36675
+ optional: false
36676
+ }],
36677
+ "recording.readGopBytes": [{
36678
+ name: "deviceId",
36679
+ form: "single",
36680
+ optional: false
36681
+ }],
36682
+ "recording.readSegmentBytes": [{
36683
+ name: "deviceId",
36684
+ form: "single",
36685
+ optional: false
36686
+ }],
36687
+ "recording.relocateFootage": [{
36688
+ name: "deviceId",
36689
+ form: "single",
36690
+ optional: true
36691
+ }],
36692
+ "recording.renderClip": [{
36693
+ name: "deviceId",
36694
+ form: "single",
36695
+ optional: false
36696
+ }],
36697
+ "recording.renderGif": [{
36698
+ name: "deviceId",
36699
+ form: "single",
36700
+ optional: false
36701
+ }],
36702
+ "recording.rescanStorage": [{
36703
+ name: "deviceId",
36704
+ form: "single",
36705
+ optional: false
36706
+ }],
36707
+ "recording.setDeviceConfig": [{
36708
+ name: "deviceId",
36709
+ form: "single",
36710
+ optional: false
36711
+ }],
36712
+ "recording.startStorageMigrationMove": [{
36713
+ name: "deviceId",
36714
+ form: "single",
36715
+ optional: true
36716
+ }],
36717
+ "recordingExport.createExport": [{
36718
+ name: "deviceId",
36719
+ form: "single",
36720
+ optional: false
36721
+ }],
36722
+ "recordingExport.listExports": [{
36723
+ name: "deviceId",
36724
+ form: "single",
36725
+ optional: true
36726
+ }],
36727
+ "sceneMonitor.captureReference": [{
36728
+ name: "deviceId",
36729
+ form: "single",
36730
+ optional: false
36731
+ }],
36732
+ "sceneMonitor.createScene": [{
36733
+ name: "deviceId",
36734
+ form: "single",
36735
+ optional: false
36736
+ }],
36737
+ "sceneMonitor.deleteReference": [{
36738
+ name: "deviceId",
36739
+ form: "single",
36740
+ optional: false
36741
+ }],
36742
+ "sceneMonitor.deleteScene": [{
36743
+ name: "deviceId",
36744
+ form: "single",
36745
+ optional: false
36746
+ }],
36747
+ "sceneMonitor.listScenes": [{
36748
+ name: "deviceId",
36749
+ form: "single",
36750
+ optional: false
36751
+ }],
36752
+ "sceneMonitor.recheckNow": [{
36753
+ name: "deviceId",
36754
+ form: "single",
36755
+ optional: false
36756
+ }],
36757
+ "sceneMonitor.resetScene": [{
36758
+ name: "deviceId",
36759
+ form: "single",
36760
+ optional: false
36761
+ }],
36762
+ "sceneMonitor.updateScene": [{
36763
+ name: "deviceId",
36764
+ form: "single",
36765
+ optional: false
36766
+ }],
36767
+ "scriptRunner.run": [{
36768
+ name: "deviceId",
36769
+ form: "single",
36770
+ optional: false
36771
+ }],
36772
+ "scriptRunner.stop": [{
36773
+ name: "deviceId",
36774
+ form: "single",
36775
+ optional: false
36776
+ }],
36777
+ "snapshot.getSnapshot": [{
36778
+ name: "deviceId",
36779
+ form: "single",
36780
+ optional: false
36781
+ }],
36782
+ "snapshot.getSnapshotOverview": [{
36783
+ name: "deviceIds",
36784
+ form: "array",
36785
+ optional: false
36786
+ }],
36787
+ "snapshot.invalidateCache": [{
36788
+ name: "deviceId",
36789
+ form: "single",
36790
+ optional: false
36791
+ }],
36792
+ "streamBroker.acquireEgressTranscode": [{
36793
+ name: "deviceId",
36794
+ form: "single",
36795
+ optional: false
36796
+ }],
36797
+ "streamBroker.assignProfile": [{
36798
+ name: "deviceId",
36799
+ form: "single",
36800
+ optional: false
36801
+ }],
36802
+ "streamBroker.getDeviceAudioMute": [{
36803
+ name: "deviceId",
36804
+ form: "single",
36805
+ optional: false
36806
+ }],
36807
+ "streamBroker.getStreamWithCodec": [{
36808
+ name: "deviceId",
36809
+ form: "single",
36810
+ optional: false
36811
+ }],
36812
+ "streamBroker.produceEventMedia": [{
36813
+ name: "deviceId",
36814
+ form: "single",
36815
+ optional: false
36816
+ }],
36817
+ "streamBroker.publishCameraStream": [{
36818
+ name: "deviceId",
36819
+ form: "single",
36820
+ optional: false
36821
+ }],
36822
+ "streamBroker.renderPreBufferClip": [{
36823
+ name: "deviceId",
36824
+ form: "single",
36825
+ optional: false
36826
+ }],
36827
+ "streamBroker.restartProfile": [{
36828
+ name: "deviceId",
36829
+ form: "single",
36830
+ optional: false
36831
+ }],
36832
+ "streamBroker.retractCameraStream": [{
36833
+ name: "deviceId",
36834
+ form: "single",
36835
+ optional: false
36836
+ }],
36837
+ "streamBroker.setDeviceAudioMute": [{
36838
+ name: "deviceId",
36839
+ form: "single",
36840
+ optional: false
36841
+ }],
36842
+ "streamBroker.unassignProfile": [{
36843
+ name: "deviceId",
36844
+ form: "single",
36845
+ optional: false
36846
+ }],
36847
+ "streamCatalog.getCatalog": [{
36848
+ name: "deviceId",
36849
+ form: "single",
36850
+ optional: false
36851
+ }],
36852
+ "streamParams.getConfigSchema": [{
36853
+ name: "deviceId",
36854
+ form: "single",
36855
+ optional: false
36856
+ }],
36857
+ "streamParams.getOptions": [{
36858
+ name: "deviceId",
36859
+ form: "single",
36860
+ optional: false
36861
+ }],
36862
+ "streamParams.setProfile": [{
36863
+ name: "deviceId",
36864
+ form: "single",
36865
+ optional: false
36866
+ }],
36867
+ "switch.setState": [{
36868
+ name: "deviceId",
36869
+ form: "single",
36870
+ optional: false
36871
+ }],
36872
+ "vacuumControl.locate": [{
36873
+ name: "deviceId",
36874
+ form: "single",
36875
+ optional: false
36876
+ }],
36877
+ "vacuumControl.pause": [{
36878
+ name: "deviceId",
36879
+ form: "single",
36880
+ optional: false
36881
+ }],
36882
+ "vacuumControl.returnToBase": [{
36883
+ name: "deviceId",
36884
+ form: "single",
36885
+ optional: false
36886
+ }],
36887
+ "vacuumControl.setFanSpeed": [{
36888
+ name: "deviceId",
36889
+ form: "single",
36890
+ optional: false
36891
+ }],
36892
+ "vacuumControl.start": [{
36893
+ name: "deviceId",
36894
+ form: "single",
36895
+ optional: false
36896
+ }],
36897
+ "vacuumControl.stop": [{
36898
+ name: "deviceId",
36899
+ form: "single",
36900
+ optional: false
36901
+ }],
36902
+ "valve.close": [{
36903
+ name: "deviceId",
36904
+ form: "single",
36905
+ optional: false
36906
+ }],
36907
+ "valve.open": [{
36908
+ name: "deviceId",
36909
+ form: "single",
36910
+ optional: false
36911
+ }],
36912
+ "valve.setPosition": [{
36913
+ name: "deviceId",
36914
+ form: "single",
36915
+ optional: false
36916
+ }],
36917
+ "valve.stop": [{
36918
+ name: "deviceId",
36919
+ form: "single",
36920
+ optional: false
36921
+ }],
36922
+ "videoclips.getClipPlayback": [{
36923
+ name: "deviceId",
36924
+ form: "single",
36925
+ optional: false
36926
+ }],
36927
+ "videoclips.listClips": [{
36928
+ name: "deviceId",
36929
+ form: "single",
36930
+ optional: false
36931
+ }],
36932
+ "waterHeater.setAway": [{
36933
+ name: "deviceId",
36934
+ form: "single",
36935
+ optional: false
36936
+ }],
36937
+ "waterHeater.setOperationMode": [{
36938
+ name: "deviceId",
36939
+ form: "single",
36940
+ optional: false
36941
+ }],
36942
+ "waterHeater.setTargetTemp": [{
36943
+ name: "deviceId",
36944
+ form: "single",
36945
+ optional: false
36946
+ }],
36947
+ "webrtcSession.addIceCandidate": [{
36948
+ name: "deviceId",
36949
+ form: "single",
36950
+ optional: false
36951
+ }],
36952
+ "webrtcSession.closeSession": [{
36953
+ name: "deviceId",
36954
+ form: "single",
36955
+ optional: false
36956
+ }],
36957
+ "webrtcSession.createSession": [{
36958
+ name: "deviceId",
36959
+ form: "single",
36960
+ optional: false
36961
+ }],
36962
+ "webrtcSession.getIceCandidates": [{
36963
+ name: "deviceId",
36964
+ form: "single",
36965
+ optional: false
36966
+ }],
36967
+ "webrtcSession.getSessionState": [{
36968
+ name: "deviceId",
36969
+ form: "single",
36970
+ optional: false
36971
+ }],
36972
+ "webrtcSession.handleAnswer": [{
36973
+ name: "deviceId",
36974
+ form: "single",
36975
+ optional: false
36976
+ }],
36977
+ "webrtcSession.handleOffer": [{
36978
+ name: "deviceId",
36979
+ form: "single",
36980
+ optional: false
36981
+ }],
36982
+ "webrtcSession.hasAdaptiveBitrate": [{
36983
+ name: "deviceId",
36984
+ form: "single",
36985
+ optional: false
36986
+ }],
36987
+ "webrtcSession.listStreams": [{
36988
+ name: "deviceId",
36989
+ form: "single",
36990
+ optional: false
36991
+ }],
36992
+ "zoneAnalytics.getCameraHistory": [{
36993
+ name: "deviceId",
36994
+ form: "single",
36995
+ optional: false
36996
+ }],
36997
+ "zoneAnalytics.getCurrentSnapshot": [{
36998
+ name: "deviceId",
36999
+ form: "single",
37000
+ optional: false
37001
+ }],
37002
+ "zoneAnalytics.getUnzonedHistory": [{
37003
+ name: "deviceId",
37004
+ form: "single",
37005
+ optional: false
37006
+ }],
37007
+ "zoneAnalytics.getZoneHistory": [{
37008
+ name: "deviceId",
37009
+ form: "single",
37010
+ optional: false
37011
+ }],
37012
+ "zoneRules.listRules": [{
37013
+ name: "deviceId",
37014
+ form: "single",
37015
+ optional: false
37016
+ }],
37017
+ "zoneRules.setRules": [{
37018
+ name: "deviceId",
37019
+ form: "single",
37020
+ optional: false
37021
+ }],
37022
+ "zones.addZone": [{
37023
+ name: "deviceId",
37024
+ form: "single",
37025
+ optional: false
37026
+ }],
37027
+ "zones.listZones": [{
37028
+ name: "deviceId",
37029
+ form: "single",
37030
+ optional: false
37031
+ }],
37032
+ "zones.removeZone": [{
37033
+ name: "deviceId",
37034
+ form: "single",
37035
+ optional: false
37036
+ }],
37037
+ "zones.updateZone": [{
37038
+ name: "deviceId",
37039
+ form: "single",
37040
+ optional: false
37041
+ }]
37042
+ });
34948
37043
  Object.freeze({
34949
37044
  "broker": "broker",
34950
37045
  "device-export": "device-export",
@@ -39739,6 +41834,29 @@ var HikvisionCamera = class HikvisionCamera extends BaseDevice {
39739
41834
  * operator flips `twoWayAudioMode`) noop once the cap is already
39740
41835
  * registered.
39741
41836
  */
41837
+ /**
41838
+ * Mirror talk-back into the `intercom` runtime-state slice.
41839
+ *
41840
+ * The cap's `status` is command-driven and nothing reads it: every consumer
41841
+ * outside this process — the admin UI, the Home Assistant export — sees a
41842
+ * capability only through the runtime-state slice, via the
41843
+ * `device.state-changed` event or the `deviceState.getAllSnapshots`
41844
+ * snapshot. Without this write the `intercom` entity Home Assistant
41845
+ * publishes would exist and never receive a value, which is exactly the
41846
+ * defect that kept the capability out of the export.
41847
+ *
41848
+ * Called at the four points that open or close a session — and seeded at
41849
+ * registration, so the slice says `talking: false` from boot rather than
41850
+ * only after the first session.
41851
+ */
41852
+ publishIntercomState(talking) {
41853
+ const previous = this.getCapSlice(intercomCapability);
41854
+ this.setCapSlice(intercomCapability, {
41855
+ talking,
41856
+ lastSessionAt: talking ? Date.now() : previous?.lastSessionAt ?? null,
41857
+ ability: previous?.ability ?? null
41858
+ });
41859
+ }
39742
41860
  registerIntercomIfSupported() {
39743
41861
  if (this.intercomRegistered) return;
39744
41862
  if (!this.intercomEnabled()) return;
@@ -39763,7 +41881,14 @@ var HikvisionCamera = class HikvisionCamera extends BaseDevice {
39763
41881
  deviceTag: `camera-${this.id}`
39764
41882
  })
39765
41883
  });
39766
- return this.intercomOrchestrator.start();
41884
+ try {
41885
+ const opened = await this.intercomOrchestrator.start();
41886
+ this.publishIntercomState(true);
41887
+ return opened;
41888
+ } catch (err) {
41889
+ this.publishIntercomState(false);
41890
+ throw err;
41891
+ }
39767
41892
  },
39768
41893
  handleAnswer: async ({ deviceId, sessionId, sdpAnswer }) => {
39769
41894
  if (deviceId !== this.id) return;
@@ -39774,6 +41899,7 @@ var HikvisionCamera = class HikvisionCamera extends BaseDevice {
39774
41899
  if (deviceId !== this.id) return;
39775
41900
  if (!this.intercomOrchestrator) return;
39776
41901
  await this.intercomOrchestrator.stop(sessionId);
41902
+ this.publishIntercomState(false);
39777
41903
  },
39778
41904
  startTalkSession: async ({ deviceId }) => {
39779
41905
  if (deviceId !== this.id) throw new Error(`HikvisionCamera: intercom deviceId mismatch, expected ${this.id}, got ${deviceId}`);
@@ -39798,6 +41924,7 @@ var HikvisionCamera = class HikvisionCamera extends BaseDevice {
39798
41924
  lastSequenceNumber: -1,
39799
41925
  opusDecode: null
39800
41926
  };
41927
+ this.publishIntercomState(true);
39801
41928
  this.ctx.logger.info("intercom talk session opened", {
39802
41929
  tags: { deviceId: this.id },
39803
41930
  meta: {
@@ -39934,6 +42061,7 @@ var HikvisionCamera = class HikvisionCamera extends BaseDevice {
39934
42061
  }
39935
42062
  });
39936
42063
  });
42064
+ this.publishIntercomState(false);
39937
42065
  this.ctx.logger.info("intercom talk session closed", {
39938
42066
  tags: { deviceId: this.id },
39939
42067
  meta: {
@@ -39943,6 +42071,7 @@ var HikvisionCamera = class HikvisionCamera extends BaseDevice {
39943
42071
  });
39944
42072
  }
39945
42073
  });
42074
+ this.publishIntercomState(false);
39946
42075
  this.ctx.logger.info("intercom cap registered (ISAPI two-way audio)", { tags: { deviceId: this.id } });
39947
42076
  }
39948
42077
  /**