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