@camstack/addon-provider-homeassistant 1.2.147 → 1.2.149

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.
@@ -5369,7 +5369,7 @@ var ZodIssueCode = {
5369
5369
  var ZodFirstPartyTypeKind;
5370
5370
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5371
5371
  //#endregion
5372
- //#region ../types/dist/sleep-DlrgY4Qb.mjs
5372
+ //#region ../types/dist/sleep-gU6hqv4_.mjs
5373
5373
  /**
5374
5374
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5375
5375
  * window to float samples (D455).
@@ -7471,7 +7471,59 @@ function errMsg(err) {
7471
7471
  return String(err);
7472
7472
  }
7473
7473
  //#endregion
7474
- //#region ../types/dist/composition-BK-GTFYb.mjs
7474
+ //#region ../types/dist/composition-Dq42XWp0.mjs
7475
+ /**
7476
+ * The ffmpeg build every CamStack node downloads, per platform and arch.
7477
+ *
7478
+ * ## Why a download, on every node, including the container
7479
+ *
7480
+ * The version of ffmpeg used to be CODE: baked into the image, changeable only
7481
+ * by rebuilding and rolling it. Now it is DATA — this file states the release,
7482
+ * and a node that boots with a different one downloads it. Changing ffmpeg is a
7483
+ * framework bump, not an image rebuild.
7484
+ *
7485
+ * It also settles the licence question by removing it. FFmpeg's licence is
7486
+ * chosen at compile time: the core is LGPL 2.1+, `--enable-gpl` makes it GPL
7487
+ * (for x264/x265), `--enable-version3` makes that v3, and `--enable-nonfree`
7488
+ * makes the result undistributable. These are GPL v3 builds, and we do not
7489
+ * distribute them: the user's own node fetches the archive from the project
7490
+ * that publishes it, so we convey no GPL work and inherit none of the
7491
+ * obligations that come with conveying one. That is the whole reason the image
7492
+ * no longer installs ffmpeg at all — not a technical preference.
7493
+ *
7494
+ * ## Why jellyfin-ffmpeg
7495
+ *
7496
+ * One vendor covering linux-amd64, linux-arm64, darwin-arm64 and darwin-x64
7497
+ * from one release, with the widest hardware surface of anything maintained:
7498
+ * VAAPI, QSV, NVENC/NVDEC, AMF, Vulkan, OpenCL and DRM on amd64, plus Rockchip
7499
+ * MPP on arm64. It reaches the vendor libraries through dlopen trampolines,
7500
+ * so the binary is not linked against a driver stack it may not find.
7501
+ *
7502
+ * **What it still needs from the host, measured 2026-09-19.** On the Unraid
7503
+ * HOST, which has no libva, `-vaapi_device` aborts the process outright —
7504
+ * `implib-gen: libva-drm.so.2: failed to load library ... Assertion '0 &&
7505
+ * "Assertion in generated code"' failed`. Inside our container, which installs
7506
+ * libva plus the iHD driver, the same command encodes: verified end to end with
7507
+ * `testsrc → format=nv12,hwupload → h264_vaapi`. So the image drops ffmpeg and
7508
+ * KEEPS the Intel media stack; the drivers are the part a binary cannot bring.
7509
+ *
7510
+ * ## Why each artifact carries a checksum and a claim
7511
+ *
7512
+ * The download is now the only source, so `sha256` is verified before anything
7513
+ * is extracted — jellyfin publishes no checksums on its release assets, so
7514
+ * these are ours, taken at the version bump. And `expectedHwaccels` is what the
7515
+ * build is supposed to be able to do: a binary that probes short of its own
7516
+ * claim is a source that changed under us, which is precisely what went
7517
+ * unnoticed for months when a static build turned out to carry no VAAPI at all
7518
+ * (D536).
7519
+ */
7520
+ /** The pinned jellyfin-ffmpeg release. Changing this is the version change. */
7521
+ var FFMPEG_RELEASE = "8.1.2-5";
7522
+ var BASE = `https://github.com/jellyfin/jellyfin-ffmpeg/releases/download/v${FFMPEG_RELEASE}`;
7523
+ function portable(target) {
7524
+ return `${BASE}/jellyfin-ffmpeg_${FFMPEG_RELEASE}_portable_${target}-gpl.tar.xz`;
7525
+ }
7526
+ portable("linux64"), portable("linuxarm64"), portable("macarm64"), portable("mac64");
7475
7527
  /**
7476
7528
  * LA tabella "quale booleano di questo tipo di device conta come ALTO", e il
7477
7529
  * valutatore puro del suo FRONTE.
@@ -8277,7 +8329,6 @@ var CompositionSchema = object({
8277
8329
  });
8278
8330
  new Set([
8279
8331
  "track",
8280
- "summary",
8281
8332
  "face",
8282
8333
  "identity",
8283
8334
  "plate",
@@ -9090,6 +9141,82 @@ var ArchivedDebugNoteQueryInputSchema = object({
9090
9141
  /** Max rows returned, newest-first. */
9091
9142
  limit: number().int().min(1).max(1e3).optional()
9092
9143
  });
9144
+ var TrackRelationKindSchema = _enum(["same-subject", "different-subjects"]);
9145
+ var TrackSideSchema = _enum(["before", "after"]);
9146
+ var TrackPurityValueSchema = _enum(["mixed", "not-a-subject"]);
9147
+ var TrackRelationSchema = object({
9148
+ id: string(),
9149
+ deviceId: number().int(),
9150
+ leftTrackId: string(),
9151
+ rightTrackId: string(),
9152
+ leftSide: TrackSideSchema.nullable(),
9153
+ rightSide: TrackSideSchema.nullable(),
9154
+ relation: TrackRelationKindSchema,
9155
+ presence: literal("continuous").nullable(),
9156
+ leftStartedAt: number().int().nullable(),
9157
+ rightStartedAt: number().int().nullable(),
9158
+ createdAt: number().int(),
9159
+ updatedAt: number().int(),
9160
+ author: string().nullable()
9161
+ });
9162
+ var TrackPuritySchema = object({
9163
+ id: string(),
9164
+ deviceId: number().int(),
9165
+ sourceTrackId: string(),
9166
+ purity: TrackPurityValueSchema,
9167
+ switchAtMs: number().int().nullable(),
9168
+ startedAt: number().int().nullable(),
9169
+ createdAt: number().int(),
9170
+ updatedAt: number().int(),
9171
+ author: string().nullable()
9172
+ });
9173
+ var SetTrackRelationInputSchema = object({
9174
+ deviceId: number().int(),
9175
+ trackId: string().min(1),
9176
+ otherTrackId: string().min(1),
9177
+ relation: TrackRelationKindSchema,
9178
+ presence: literal("continuous").optional(),
9179
+ trackSide: TrackSideSchema.optional(),
9180
+ otherSide: TrackSideSchema.optional()
9181
+ });
9182
+ var ClearTrackRelationInputSchema = object({
9183
+ deviceId: number().int(),
9184
+ trackId: string().min(1),
9185
+ otherTrackId: string().min(1)
9186
+ });
9187
+ var ClearTrackRelationResultSchema = object({ cleared: boolean() });
9188
+ var SetTrackPurityInputSchema = object({
9189
+ deviceId: number().int(),
9190
+ trackId: string().min(1),
9191
+ purity: _enum([
9192
+ "pure",
9193
+ "mixed",
9194
+ "not-a-subject"
9195
+ ]),
9196
+ switchAtMs: number().int().optional()
9197
+ });
9198
+ /** `null` when `pure` cleared the row. */
9199
+ var SetTrackPurityResultSchema = object({ purity: TrackPuritySchema.nullable() });
9200
+ var ListTrackRelationsInputSchema = object({
9201
+ deviceId: number().int(),
9202
+ trackId: string().optional(),
9203
+ since: number().int().optional(),
9204
+ until: number().int().optional(),
9205
+ limit: number().int().min(1).max(5e3).optional()
9206
+ });
9207
+ var ListTrackRelationsResultSchema = object({
9208
+ relations: array(TrackRelationSchema).readonly(),
9209
+ purities: array(TrackPuritySchema).readonly(),
9210
+ truncated: boolean()
9211
+ });
9212
+ _enum([
9213
+ "unknown-track",
9214
+ "cross-device",
9215
+ "self-relation",
9216
+ "contradiction",
9217
+ "switch-outside-track",
9218
+ "switch-needs-mixed"
9219
+ ]);
9093
9220
  /**
9094
9221
  * Ops-log — the durable, append-only operations audit shared by the
9095
9222
  * recordings and events management surfaces.
@@ -13347,6 +13474,70 @@ var CompositionBlockStateSchema = object({
13347
13474
  reason: string().optional(),
13348
13475
  fields: array(CompositionFieldStateSchema)
13349
13476
  });
13477
+ var NUMBER = {
13478
+ kind: "fixed",
13479
+ result: ["number"]
13480
+ };
13481
+ var BOOLEAN = {
13482
+ kind: "fixed",
13483
+ result: ["boolean"]
13484
+ };
13485
+ Object.freeze({
13486
+ min: NUMBER,
13487
+ max: NUMBER,
13488
+ abs: NUMBER,
13489
+ floor: NUMBER,
13490
+ ceil: NUMBER,
13491
+ sqrt: NUMBER,
13492
+ round: NUMBER,
13493
+ pow: NUMBER,
13494
+ clamp: NUMBER,
13495
+ avg: NUMBER,
13496
+ sum: NUMBER,
13497
+ age: NUMBER,
13498
+ convert: NUMBER,
13499
+ coalesce: { kind: "coalesce" },
13500
+ any: BOOLEAN,
13501
+ all: BOOLEAN,
13502
+ within: BOOLEAN,
13503
+ latest: {
13504
+ kind: "fixed",
13505
+ result: ["number", "null"]
13506
+ },
13507
+ number: {
13508
+ kind: "fixed",
13509
+ result: ["number", "null"]
13510
+ },
13511
+ rose: {
13512
+ kind: "fixed",
13513
+ result: ["number", "null"]
13514
+ },
13515
+ count: NUMBER
13516
+ });
13517
+ `${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
13518
+ /**
13519
+ * What a composition may BUILD on a device type (G2, D676): the caps a new
13520
+ * device of that type, or an existing one that lacks them, can be given. The
13521
+ * blockers are the validator's own refusal codes, and a spec compares this
13522
+ * listing with `planComposition` for every capability — the editor can never
13523
+ * offer a feature the save would refuse for the same reason.
13524
+ */
13525
+ var ComposableFieldSchema = object({
13526
+ path: string(),
13527
+ kind: CompositionFieldKindSchema,
13528
+ nullable: boolean(),
13529
+ required: boolean(),
13530
+ enumValues: array(string()).optional()
13531
+ });
13532
+ var ComposableCapabilitiesSchema = object({ caps: array(object({
13533
+ cap: string(),
13534
+ fields: array(ComposableFieldSchema),
13535
+ /** Present for an item-array cap (`consumables.items`). */
13536
+ itemArray: object({
13537
+ path: string(),
13538
+ keyField: string()
13539
+ }).optional()
13540
+ })) });
13350
13541
  /** Where a block runs. The operator chooses — a block driving a device on an
13351
13542
  * agent is the reason placement is not fixed to the hub. */
13352
13543
  var CoreBlockPlacementSchema = union([literal("hub"), string().min(1)]);
@@ -13511,7 +13702,7 @@ method(object({}), object({ blocks: array(CoreBlockSchema) }), { auth: "admin" }
13511
13702
  }), method(object({ blockId: string() }), CompositionGetReadSchema, { auth: "admin" }), method(object({}), CompositionListReadSchema, { auth: "admin" }), method(object({
13512
13703
  addonId: string().min(1),
13513
13704
  stableId: string().min(1)
13514
- }), CompositionCustomizationReadSchema, { auth: "admin" }), method(object({
13705
+ }), CompositionCustomizationReadSchema, { auth: "admin" }), method(object({ deviceType: _enum(DeviceType) }), ComposableCapabilitiesSchema, { auth: "admin" }), method(object({
13515
13706
  composition: CompositionSchema,
13516
13707
  blockId: string().optional()
13517
13708
  }), CompositionValidationSchema, {
@@ -19009,8 +19200,14 @@ var NcSensorTransitionSchema = _enum(["raised", "cleared"]);
19009
19200
  /** Admin-zone membership condition (zone IDs as stamped by the ZoneEngine). */
19010
19201
  var NcZoneConditionSchema = object({
19011
19202
  ids: array(string().min(1)).min(1),
19012
- /** Quantifier over `ids` — at least one / every one visited. */
19013
- match: _enum(["any", "all"]).default("any")
19203
+ /**
19204
+ * LEGACY quantifier over `ids`. Absent = `any` (at least one visited), which
19205
+ * is what both editors mean and all they write since D690: "all of" was
19206
+ * removed from the editors because on an immediate rule it asked one
19207
+ * detection to stand in every zone at once. Still ACCEPTED, and `all` still
19208
+ * evaluated, so a stored rule keeps parsing and meaning what it meant.
19209
+ */
19210
+ match: _enum(["any", "all"]).optional()
19014
19211
  });
19015
19212
  /**
19016
19213
  * The P1 condition set — a flat AND of groups; absent group = pass;
@@ -20883,6 +21080,102 @@ var oauthIntegrationCapability = {
20883
21080
  getDescriptor: method(_void(), OauthIntegrationDescriptorSchema, { auth: "admin" }) }
20884
21081
  };
20885
21082
  /**
21083
+ * What started a camera's onboard motion (D672). `camera` is the camera's own
21084
+ * firmware; `sensor` is a device the operator ATTACHED to it. Absent on the
21085
+ * wire means the camera: only the camera-sensors bridge ever says `sensor`.
21086
+ */
21087
+ var MotionTriggeredBySchema = discriminatedUnion("kind", [object({ kind: literal("camera") }), object({
21088
+ kind: literal("sensor"),
21089
+ deviceId: number().int().positive()
21090
+ })]);
21091
+ Object.freeze({ kind: "camera" });
21092
+ var CameraSensorRefSchema = object({
21093
+ addonId: string().min(1),
21094
+ stableId: string().min(1)
21095
+ });
21096
+ function cameraSensorRefKey(ref) {
21097
+ return `${ref.addonId}/${ref.stableId}`;
21098
+ }
21099
+ /** CS-1 accepts exactly one mode; CS-2 (D673) widens it to confirm / replace. */
21100
+ var CameraSensorsModeSchema = _enum(["in-addition"]);
21101
+ var CameraSensorsConfigSchema = object({
21102
+ mode: CameraSensorsModeSchema,
21103
+ sensors: array(CameraSensorRefSchema).min(1).max(8)
21104
+ }).superRefine((value, ctx) => {
21105
+ const seen = /* @__PURE__ */ new Set();
21106
+ value.sensors.forEach((ref, index) => {
21107
+ const key = cameraSensorRefKey(ref);
21108
+ if (seen.has(key)) ctx.addIssue({
21109
+ code: "custom",
21110
+ path: ["sensors", index],
21111
+ message: `duplicate camera sensor ${key}`
21112
+ });
21113
+ seen.add(key);
21114
+ });
21115
+ });
21116
+ var RefFields = {
21117
+ addonId: string(),
21118
+ stableId: string()
21119
+ };
21120
+ var CameraSensorAttachmentSchema = discriminatedUnion("state", [
21121
+ object({
21122
+ ...RefFields,
21123
+ state: literal("ready"),
21124
+ deviceId: number(),
21125
+ name: string(),
21126
+ caps: array(string()).readonly()
21127
+ }),
21128
+ object({
21129
+ ...RefFields,
21130
+ state: literal("offline"),
21131
+ deviceId: number(),
21132
+ name: string(),
21133
+ reason: _enum(["offline", "disabled"])
21134
+ }),
21135
+ object({
21136
+ ...RefFields,
21137
+ state: literal("missing"),
21138
+ reason: string()
21139
+ }),
21140
+ object({
21141
+ ...RefFields,
21142
+ state: literal("unsupported"),
21143
+ deviceId: number(),
21144
+ name: string(),
21145
+ reason: string()
21146
+ }),
21147
+ object({
21148
+ ...RefFields,
21149
+ state: literal("unreadable"),
21150
+ reason: string()
21151
+ })
21152
+ ]);
21153
+ /**
21154
+ * Why a configured camera forwards NOTHING from its sensors, however ready they
21155
+ * are (D672): it does not list `onboard` in `motionSources` (attaching a sensor
21156
+ * does not add it), or it has no active detection config at all (the bridge
21157
+ * reads the active config). Absent = forwarded, or an older node that does not
21158
+ * say.
21159
+ */
21160
+ var CameraSensorsNotForwardedSchema = _enum(["onboard-not-listed", "no-active-detection"]);
21161
+ var CameraSensorsStatusSchema = discriminatedUnion("state", [
21162
+ object({ state: literal("not-configured") }),
21163
+ object({
21164
+ state: literal("unreadable"),
21165
+ reason: string()
21166
+ }),
21167
+ object({
21168
+ state: literal("configured"),
21169
+ mode: CameraSensorsModeSchema,
21170
+ sensors: array(CameraSensorAttachmentSchema).readonly(),
21171
+ notForwarded: CameraSensorsNotForwardedSchema.optional()
21172
+ })
21173
+ ]);
21174
+ Object.freeze({
21175
+ state: "unreadable",
21176
+ reason: "camera sensor mappings not loaded"
21177
+ });
21178
+ /**
20886
21179
  * A model choice has a SCOPE, and a scope change has a workflow.
20887
21180
  *
20888
21181
  * ## The two scopes
@@ -21631,6 +21924,12 @@ var MotionEventSchema = object({
21631
21924
  /** Populated by B5 (recording playback URL for this event). */
21632
21925
  mediaUrl: string().optional(),
21633
21926
  /**
21927
+ * The FIRST trigger of an `onboard` episode, written once at open (D672).
21928
+ * Absent = not recorded (a row written before D672, or an analyzer /
21929
+ * device-activity episode) — never read as "the camera" (D393).
21930
+ */
21931
+ triggeredBy: MotionTriggeredBySchema.optional(),
21932
+ /**
21634
21933
  * One row per motion EPISODE, not one per push (D475). `null` while the
21635
21934
  * episode is still open — a further rising edge extends it in place rather
21636
21935
  * than inserting a new row. Set once, at close, to `lastOnAt - startedAt`
@@ -21789,6 +22088,21 @@ var ObjectEventSchema = object({
21789
22088
  keyFrameMediaId: number().int().optional(),
21790
22089
  /** Populated by B5 (recording playback URL for this event). */
21791
22090
  mediaUrl: string().optional(),
22091
+ /**
22092
+ * When the change this row records HAPPENED, epoch ms, when that is earlier
22093
+ * than {@link timestamp} and the producer could date it (D684).
22094
+ *
22095
+ * Set on a package PICK-UP row only: its `timestamp` is when the departure
22096
+ * was CONCLUDED — five minutes of unseen observed time after the parcel went
22097
+ * — and a notification's footage has to be cut around the pick-up, not the
22098
+ * empty doormat after it (D682). Stored so every path that rebuilds a
22099
+ * notification subject from the row (the boot reconcile, a dry-run) anchors
22100
+ * on the same instant the live hook did.
22101
+ *
22102
+ * `timestamp` keeps its meaning. Absent on every other row and on every
22103
+ * pick-up written before D684 — UNKNOWN, never 0 and never `timestamp`.
22104
+ */
22105
+ observedAt: number().optional(),
21792
22106
  /** The parent track's key-event importance [0,1], propagated to every object
21793
22107
  * event of the track (so an event row can be sorted by importance without a
21794
22108
  * track join). Absent on legacy rows / before the track was scored. */
@@ -22124,131 +22438,6 @@ var RecentTracksQueryInput = object({
22124
22438
  /** See {@link ExcludeSourcesDoc}. */
22125
22439
  excludeSources: array(TrackSourceSchema).optional()
22126
22440
  });
22127
- /**
22128
- * A Summary (D359): the per-camera session envelope that references tracks.
22129
- * `groupShotMediaId` is the media ROW id of its group shot (`ownerKind:
22130
- * 'summary'`, served by the event-media plane at `/m/<id>`), null until the
22131
- * first frame with a member visible has been materialised (D482 — it was the
22132
- * row's composite key, which embedded the owner and could name another table's
22133
- * row once event ids became per-table rowids).
22134
- */
22135
- var SummarySchema = object({
22136
- id: string(),
22137
- deviceId: number(),
22138
- openedAt: number(),
22139
- lastActiveAt: number(),
22140
- sealedAt: number().nullable(),
22141
- memberCount: number().int().nonnegative(),
22142
- groupShotMediaId: number().int().nullable()
22143
- });
22144
- var SummariesQueryInput = object({
22145
- deviceIds: array(number()).min(1),
22146
- since: number().optional(),
22147
- until: number().optional(),
22148
- limit: number().int().min(1).max(200).default(50),
22149
- /** The same member-wise filter {@link listRecentSummaries} takes — one
22150
- * meaning of "dog" on every summary surface. */
22151
- classes: array(string().min(1).max(60)).max(40).optional()
22152
- });
22153
- var SummaryDetailSchema = object({
22154
- summary: SummarySchema,
22155
- /** Members in absorption order, oldest join first. */
22156
- members: array(object({
22157
- trackId: string(),
22158
- /**
22159
- * The track's class at the time it JOINED, or `null` when it was unresolved
22160
- * and the track no longer exists to fill it.
22161
- *
22162
- * The join, not the latest opinion: class voting can re-decide a track's
22163
- * class afterwards, and a group's composition is the history of who came
22164
- * together. A consumer counts these to badge a thumbnail — "two people and a
22165
- * dog" — rather than being handed a second, denormalised tally that would
22166
- * drift from the members it claims to describe.
22167
- */
22168
- className: string().nullable(),
22169
- /** `primary` is the one member that carries the group's identity. */
22170
- role: _enum([
22171
- "primary",
22172
- "sibling",
22173
- "child"
22174
- ]).nullable(),
22175
- joinedAt: number(),
22176
- /** Tier 1 — the sub-class (`dog`, `van`), resolved from the member's track
22177
- * at read time. Absent when nothing resolved, never an empty string. */
22178
- label: string().optional(),
22179
- /** Tier 2 — the instance: a person's name, a plate. Absent when the pipeline
22180
- * recognised nobody, and absent for a member whose track has been pruned —
22181
- * a thumbnail that names the wrong person is worse than one naming nobody. */
22182
- subLabel: string().optional()
22183
- })).readonly()
22184
- });
22185
- /**
22186
- * What a LIST of groups carries: the envelope plus what it is MADE OF.
22187
- *
22188
- * Coarse on purpose — the operator's rule is "only the rough data on the list,
22189
- * we extend when we notice we need more". Enough to draw the card ("two people
22190
- * and a dog") and no more. The MEMBERS, their names and the per-member links
22191
- * are on {@link getSummary}: shipping every member of every group so a client
22192
- * can count them turns a page of two hundred groups into a thousand records to
22193
- * draw two hundred badges.
22194
- */
22195
- var SummaryListItemSchema = object({
22196
- summary: SummarySchema,
22197
- /** Class counts, most numerous first; `className: null` is a member whose
22198
- * class never resolved, counted so the counts add up to `memberCount`. */
22199
- classes: array(object({
22200
- className: string().nullable(),
22201
- count: number().int().positive()
22202
- })).readonly()
22203
- });
22204
- var SummariesPageSchema = object({ summaries: array(SummaryListItemSchema).readonly() });
22205
- /**
22206
- * The paged feed, deliberately the SAME shape as {@link RecentTracksQueryInput}.
22207
- *
22208
- * The reel on the cameras page and the Events gallery both ride a cursor, so a
22209
- * summaries feed that could only answer "the last N for these cameras"
22210
- * (`listSummaries`) would make groups available in the timeline and nowhere
22211
- * else. Two feeds with different ordering contracts would be two ideas of what
22212
- * "newest" means, on one screen.
22213
- */
22214
- var RecentSummariesQueryInput = object({
22215
- /** Devices to merge. An empty array yields an empty page. */
22216
- deviceIds: array(number()),
22217
- /** Window lower bound on `lastActiveAt` (inclusive). */
22218
- since: number().optional(),
22219
- /** Window upper bound on `lastActiveAt` (inclusive). */
22220
- until: number().optional(),
22221
- limit: number().int().min(1).max(500).default(100),
22222
- /** Opaque continuation cursor from a previous page's `nextCursor`. */
22223
- cursor: string().optional(),
22224
- /**
22225
- * Restrict to these classes — THE SAME FIELD `listRecentTracks` takes, and
22226
- * deliberately the same name: the events filter tree emits one list of ticked
22227
- * taxonomy nodes, and a summaries feed that called it something else would
22228
- * make the operator's one filter component produce two shapes.
22229
- *
22230
- * A question about the MEMBERS: a group matches when ANY of them does. "Show
22231
- * me the arrivals with a dog" has to return the group of four people who had
22232
- * one with them; a filter on the group's own fields could only ever answer
22233
- * about its primary.
22234
- *
22235
- * Matched against all THREE tiers of a member — the class (`animal`), the
22236
- * sub-class (`dog`) and the instance (a name, a plate) — because which tier a
22237
- * ticked node lives on is the taxonomy's business, not the caller's. `dog` is
22238
- * an event kind in the tree and a tier-1 label on an `animal` track; a filter
22239
- * that read only the class would answer "animal" and never "dog".
22240
- *
22241
- * ABSENT or EMPTY means no filter — absent is not a selection of none.
22242
- */
22243
- classes: array(string().min(1).max(60)).max(40).optional()
22244
- });
22245
- var RecentSummariesPageSchema = object({
22246
- /** Ordered by (`lastActiveAt` DESC, id DESC). Same light item as
22247
- * {@link listSummaries} — one list shape, so a card renders the same
22248
- * whichever feed drew it. */
22249
- summaries: array(SummaryListItemSchema).readonly(),
22250
- nextCursor: string().nullable()
22251
- });
22252
22441
  var RecentTracksPageSchema = object({
22253
22442
  /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
22254
22443
  tracks: array(TrackSchema).readonly(),
@@ -22760,7 +22949,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
22760
22949
  classes: array(string()).optional(),
22761
22950
  /** See {@link ExcludeSourcesDoc}. */
22762
22951
  excludeSources: array(TrackSourceSchema).optional()
22763
- }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(RecentSummariesQueryInput, RecentSummariesPageSchema), method(object({ id: string() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
22952
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
22764
22953
  kind: "mutation",
22765
22954
  auth: "admin"
22766
22955
  }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({ deviceIds: array(number()).min(1).max(200) }), array(EventKindsForDeviceSchema).readonly()), method(object({
@@ -22814,7 +23003,8 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
22814
23003
  trackIds: array(string()).min(1)
22815
23004
  }), object({
22816
23005
  deleted: number().int(),
22817
- failed: array(string()).readonly()
23006
+ failed: array(string()).readonly(),
23007
+ sparedMediaIds: array(number().int()).readonly().optional()
22818
23008
  }), {
22819
23009
  kind: "mutation",
22820
23010
  auth: "admin"
@@ -22823,7 +23013,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
22823
23013
  deviceId: number(),
22824
23014
  trackId: string(),
22825
23015
  flags: TrackFlagsPatchSchema
22826
- }), TrackFlagsSchema, { kind: "mutation" }), method(ArchivedDebugNoteQueryInputSchema, array(ArchivedDebugNoteSchema).readonly(), { kind: "query" }), method(BirthDecisionQueryInputSchema, array(BirthDecisionRecordSchema).readonly(), { kind: "query" }), method(object({}), EventStoreFootprintSchema, {
23016
+ }), TrackFlagsSchema, { kind: "mutation" }), method(ArchivedDebugNoteQueryInputSchema, array(ArchivedDebugNoteSchema).readonly(), { kind: "query" }), method(SetTrackRelationInputSchema, TrackRelationSchema, { kind: "mutation" }), method(ClearTrackRelationInputSchema, ClearTrackRelationResultSchema, { kind: "mutation" }), method(SetTrackPurityInputSchema, SetTrackPurityResultSchema, { kind: "mutation" }), method(ListTrackRelationsInputSchema, ListTrackRelationsResultSchema, { kind: "query" }), method(BirthDecisionQueryInputSchema, array(BirthDecisionRecordSchema).readonly(), { kind: "query" }), method(object({}), EventStoreFootprintSchema, {
22827
23017
  kind: "query",
22828
23018
  auth: "admin"
22829
23019
  }), method(object({ deviceId: number().int().optional() }), EventMediaKindBreakdownSchema, {
@@ -23980,6 +24170,23 @@ var MotionSourceEnum = _enum([
23980
24170
  */
23981
24171
  var MotionSourcesSchema = array(MotionSourceEnum);
23982
24172
  /**
24173
+ * The operator-facing name of each MOTION source (D672: `onboard` = the
24174
+ * camera's sensors — its own motion plus any sensor attached to it). The wire
24175
+ * value stays `onboard`; only the label changed. `detectionSources: 'onboard'`
24176
+ * ("Camera onboard AI") and the notification source filter keep their labels.
24177
+ */
24178
+ var MOTION_SOURCE_LABELS = {
24179
+ analyzer: "Frame-diff Analyzer (motion addon)",
24180
+ onboard: "Camera sensors",
24181
+ "device-activity": "Device activity (the device says it is working)"
24182
+ };
24183
+ /** The order the motion-source picker offers them in (not the enum's order). */
24184
+ var MOTION_SOURCE_PICKER_ORDER = [
24185
+ "analyzer",
24186
+ "onboard",
24187
+ "device-activity"
24188
+ ];
24189
+ /**
23983
24190
  * Which root detector a camera runs — EXACTLY ONE.
23984
24191
  *
23985
24192
  * Deliberately the SAME vocabulary post-analysis already tags every detection
@@ -24326,7 +24533,14 @@ var RunnerCameraConfigSchema = object({
24326
24533
  */
24327
24534
  inferenceDevices: array(RunnerInferenceDeviceSchema).readonly().optional()
24328
24535
  });
24329
- motionFpsField.min, motionFpsField.max, motionFpsField.step, motionFpsField.default, detectionFpsField.min, detectionFpsField.max, detectionFpsField.step, detectionFpsField.default, motionCooldownMsField.min, motionCooldownMsField.max, motionCooldownMsField.step, motionCooldownMsField.default, maxSessionHoldMsField.min, maxSessionHoldMsField.max, maxSessionHoldMsField.step, maxSessionHoldMsField.default, audioMotionWindowMsField.min, audioMotionWindowMsField.max, audioMotionWindowMsField.step, audioMotionWindowMsField.default, preRollInferenceFramesField.min, preRollInferenceFramesField.max, preRollInferenceFramesField.step, preRollInferenceFramesField.default, occupancyRecheckSecField.min, occupancyRecheckSecField.max, occupancyRecheckSecField.step, occupancyRecheckSecField.default, occupancyRecheckFramesField.min, occupancyRecheckFramesField.max, occupancyRecheckFramesField.step, occupancyRecheckFramesField.default;
24536
+ MOTION_SOURCE_PICKER_ORDER.map((value) => value === "onboard" ? {
24537
+ value,
24538
+ label: MOTION_SOURCE_LABELS[value],
24539
+ description: "The camera's own motion, plus any sensor attached to it"
24540
+ } : {
24541
+ value,
24542
+ label: MOTION_SOURCE_LABELS[value]
24543
+ }), motionFpsField.min, motionFpsField.max, motionFpsField.step, motionFpsField.default, detectionFpsField.min, detectionFpsField.max, detectionFpsField.step, detectionFpsField.default, motionCooldownMsField.min, motionCooldownMsField.max, motionCooldownMsField.step, motionCooldownMsField.default, maxSessionHoldMsField.min, maxSessionHoldMsField.max, maxSessionHoldMsField.step, maxSessionHoldMsField.default, audioMotionWindowMsField.min, audioMotionWindowMsField.max, audioMotionWindowMsField.step, audioMotionWindowMsField.default, preRollInferenceFramesField.min, preRollInferenceFramesField.max, preRollInferenceFramesField.step, preRollInferenceFramesField.default, occupancyRecheckSecField.min, occupancyRecheckSecField.max, occupancyRecheckSecField.step, occupancyRecheckSecField.default, occupancyRecheckFramesField.min, occupancyRecheckFramesField.max, occupancyRecheckFramesField.step, occupancyRecheckFramesField.default;
24330
24544
  /**
24331
24545
  * Runtime load summary returned by `getLocalLoad`. Used by the orchestrator's
24332
24546
  * load-balancing levels (L2 capacity-based, L3 hardware-aware) to decide
@@ -24900,6 +25114,11 @@ var CameraStatusSchema = object({
24900
25114
  */
24901
25115
  switchedOff: array(CameraSwitchIdSchema).readonly(),
24902
25116
  /**
25117
+ * The camera's attached sensors (D672). Optional only for a status composed
25118
+ * by an orchestrator older than D672; this orchestrator always sets it.
25119
+ */
25120
+ cameraSensors: CameraSensorsStatusSchema.optional(),
25121
+ /**
24903
25122
  * Stages of the bounded fan-out that were CUT SHORT — a timeout or a
24904
25123
  * rejection — and whose block is therefore `null` because we could not
24905
25124
  * READ it, not because there is nothing there.
@@ -24992,7 +25211,64 @@ var NodeInferenceDevicesSchema = object({
24992
25211
  reachable: boolean(),
24993
25212
  devices: array(NodeInferenceDeviceSchema).readonly()
24994
25213
  });
24995
- method(StorageMigrationLeaseInputSchema, object({ paused: literal(true) }), {
25214
+ /**
25215
+ * Pipeline Orchestrator capability — global load balancer + camera dispatcher.
25216
+ *
25217
+ * Lives on the hub. Tracks the camera-to-agent assignment map, listens to
25218
+ * device lifecycle events, queries each runner's capacity + hardware
25219
+ * profile, and dispatches `attachCamera` / `detachCamera` cap calls to the
25220
+ * appropriate runner instances. Persists assignments via the multi-level
25221
+ * settings store so they survive hub restarts.
25222
+ *
25223
+ * Strictly the control plane: never sees a frame, never calls inference,
25224
+ * never drains queues. The runner does that work locally on each agent.
25225
+ */
25226
+ /**
25227
+ * The input of `setCameraSensors` (G5, D676): the ONE typed write path of a
25228
+ * camera's attached sensors (D672). `config: null` removes the attachment —
25229
+ * the camera reads `not-configured` again, never `unreadable`.
25230
+ */
25231
+ var SetCameraSensorsInputSchema = object({
25232
+ deviceId: number().int().nonnegative(),
25233
+ /** `null` removes the attachment: the camera goes back to `not-configured`. */
25234
+ config: CameraSensorsConfigSchema.nullable()
25235
+ });
25236
+ /**
25237
+ * Why an early occupancy look (D691) was not scheduled.
25238
+ *
25239
+ * - `unknown-camera` — no session was ever dispatched for it, so there is no
25240
+ * node and no config to attach a burst with.
25241
+ * - `out-of-range` — the ask is negative or further out than the orchestrator
25242
+ * will hold a timer for; the parked-object cadence is the answer there.
25243
+ * - `no-burst-producer` — this build has no burst producer at all.
25244
+ * - `already-looked` — this camera's ONE early look since its last session has
25245
+ * been spent. A look's own burst can re-arm a flickering flip, and a look
25246
+ * per arm would chain a burst every ~30 s forever (review H2); the next
25247
+ * real session re-arms the budget.
25248
+ */
25249
+ var OccupancyLookRefusalSchema = _enum([
25250
+ "unknown-camera",
25251
+ "out-of-range",
25252
+ "no-burst-producer",
25253
+ "already-looked"
25254
+ ]);
25255
+ method(object({
25256
+ deviceId: number().int().nonnegative(),
25257
+ /** How long from NOW until the pending flip's sustain window ends. RELATIVE,
25258
+ * so the caller's clock and the orchestrator's never have to agree. */
25259
+ afterMs: number().finite(),
25260
+ /** Why, for the log. */
25261
+ reason: string()
25262
+ }), object({
25263
+ scheduled: boolean(),
25264
+ /** When `scheduled`: how long until the burst is dialled. */
25265
+ dueInMs: number().optional(),
25266
+ /** When not `scheduled`: why. */
25267
+ refusedBecause: OccupancyLookRefusalSchema.optional()
25268
+ }), {
25269
+ kind: "mutation",
25270
+ auth: "admin"
25271
+ }), method(StorageMigrationLeaseInputSchema, object({ paused: literal(true) }), {
24996
25272
  kind: "mutation",
24997
25273
  auth: "admin"
24998
25274
  }), method(StorageMigrationLeaseInputSchema, object({ resumed: literal(true) }), {
@@ -25146,7 +25422,10 @@ method(StorageMigrationLeaseInputSchema, object({ paused: literal(true) }), {
25146
25422
  }), CameraSwitchGroupSchema, {
25147
25423
  kind: "mutation",
25148
25424
  auth: "admin"
25149
- }), method(object({ deviceId: number() }), CameraStatusSchema), method(object({ deviceIds: array(number()).optional() }), array(CameraStatusSchema).readonly()), method(_void(), DiskReconcileJobSchema, {
25425
+ }), method(object({ deviceId: number() }), CameraStatusSchema), method(object({ deviceIds: array(number()).optional() }), array(CameraStatusSchema).readonly()), method(SetCameraSensorsInputSchema, object({ success: literal(true) }), {
25426
+ kind: "mutation",
25427
+ auth: "admin"
25428
+ }), method(_void(), DiskReconcileJobSchema, {
25150
25429
  kind: "mutation",
25151
25430
  auth: "admin"
25152
25431
  }), method(_void(), DiskReconcileJobSchema, { auth: "admin" }), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
@@ -32327,7 +32606,9 @@ var MotionOnMotionChangedDataSchema = object({
32327
32606
  detected: boolean(),
32328
32607
  timestamp: number(),
32329
32608
  source: MotionSourceEnum,
32330
- regions: array(MotionRegionSchema).readonly().optional()
32609
+ regions: array(MotionRegionSchema).readonly().optional(),
32610
+ /** Who started it (D672). Absent = the camera itself. Only `onboard` carries `sensor`. */
32611
+ triggeredBy: MotionTriggeredBySchema.optional()
32331
32612
  });
32332
32613
  var motionCapability = {
32333
32614
  name: "motion",
@@ -38817,47 +39098,6 @@ var zoneRulesCapability = {
38817
39098
  */
38818
39099
  durability: "restored"
38819
39100
  };
38820
- var NUMBER = {
38821
- kind: "fixed",
38822
- result: ["number"]
38823
- };
38824
- var BOOLEAN = {
38825
- kind: "fixed",
38826
- result: ["boolean"]
38827
- };
38828
- Object.freeze({
38829
- min: NUMBER,
38830
- max: NUMBER,
38831
- abs: NUMBER,
38832
- floor: NUMBER,
38833
- ceil: NUMBER,
38834
- sqrt: NUMBER,
38835
- round: NUMBER,
38836
- pow: NUMBER,
38837
- clamp: NUMBER,
38838
- avg: NUMBER,
38839
- sum: NUMBER,
38840
- age: NUMBER,
38841
- convert: NUMBER,
38842
- coalesce: { kind: "coalesce" },
38843
- any: BOOLEAN,
38844
- all: BOOLEAN,
38845
- within: BOOLEAN,
38846
- latest: {
38847
- kind: "fixed",
38848
- result: ["number", "null"]
38849
- },
38850
- number: {
38851
- kind: "fixed",
38852
- result: ["number", "null"]
38853
- },
38854
- rose: {
38855
- kind: "fixed",
38856
- result: ["number", "null"]
38857
- },
38858
- count: NUMBER
38859
- });
38860
- `${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
38861
39101
  /**
38862
39102
  * Accessory device helpers — shared across drivers.
38863
39103
  *
@@ -42803,6 +43043,12 @@ Object.freeze({
42803
43043
  addonId: null,
42804
43044
  access: "view"
42805
43045
  },
43046
+ "coreBlocks.listComposableCaps": {
43047
+ capName: "core-blocks",
43048
+ capScope: "system",
43049
+ addonId: null,
43050
+ access: "view"
43051
+ },
42806
43052
  "coreBlocks.listCompositions": {
42807
43053
  capName: "core-blocks",
42808
43054
  capScope: "system",
@@ -45617,6 +45863,12 @@ Object.freeze({
45617
45863
  addonId: null,
45618
45864
  access: "create"
45619
45865
  },
45866
+ "pipelineAnalytics.clearTrackRelation": {
45867
+ capName: "pipeline-analytics",
45868
+ capScope: "device",
45869
+ addonId: null,
45870
+ access: "delete"
45871
+ },
45620
45872
  "pipelineAnalytics.clearTracks": {
45621
45873
  capName: "pipeline-analytics",
45622
45874
  capScope: "device",
@@ -45773,12 +46025,6 @@ Object.freeze({
45773
46025
  addonId: null,
45774
46026
  access: "view"
45775
46027
  },
45776
- "pipelineAnalytics.getSummary": {
45777
- capName: "pipeline-analytics",
45778
- capScope: "device",
45779
- addonId: null,
45780
- access: "view"
45781
- },
45782
46028
  "pipelineAnalytics.getTrack": {
45783
46029
  capName: "pipeline-analytics",
45784
46030
  capScope: "device",
@@ -45839,12 +46085,6 @@ Object.freeze({
45839
46085
  addonId: null,
45840
46086
  access: "view"
45841
46087
  },
45842
- "pipelineAnalytics.listRecentSummaries": {
45843
- capName: "pipeline-analytics",
45844
- capScope: "device",
45845
- addonId: null,
45846
- access: "view"
45847
- },
45848
46088
  "pipelineAnalytics.listRecentTracks": {
45849
46089
  capName: "pipeline-analytics",
45850
46090
  capScope: "device",
@@ -45875,13 +46115,13 @@ Object.freeze({
45875
46115
  addonId: null,
45876
46116
  access: "view"
45877
46117
  },
45878
- "pipelineAnalytics.listSummaries": {
46118
+ "pipelineAnalytics.listTrackMedia": {
45879
46119
  capName: "pipeline-analytics",
45880
46120
  capScope: "device",
45881
46121
  addonId: null,
45882
46122
  access: "view"
45883
46123
  },
45884
- "pipelineAnalytics.listTrackMedia": {
46124
+ "pipelineAnalytics.listTrackRelations": {
45885
46125
  capName: "pipeline-analytics",
45886
46126
  capScope: "device",
45887
46127
  addonId: null,
@@ -46001,6 +46241,18 @@ Object.freeze({
46001
46241
  addonId: null,
46002
46242
  access: "create"
46003
46243
  },
46244
+ "pipelineAnalytics.setTrackPurity": {
46245
+ capName: "pipeline-analytics",
46246
+ capScope: "device",
46247
+ addonId: null,
46248
+ access: "create"
46249
+ },
46250
+ "pipelineAnalytics.setTrackRelation": {
46251
+ capName: "pipeline-analytics",
46252
+ capScope: "device",
46253
+ addonId: null,
46254
+ access: "create"
46255
+ },
46004
46256
  "pipelineAnalytics.startStorageMigrationMove": {
46005
46257
  capName: "pipeline-analytics",
46006
46258
  capScope: "device",
@@ -46439,6 +46691,12 @@ Object.freeze({
46439
46691
  addonId: null,
46440
46692
  access: "delete"
46441
46693
  },
46694
+ "pipelineOrchestrator.requestOccupancyLook": {
46695
+ capName: "pipeline-orchestrator",
46696
+ capScope: "system",
46697
+ addonId: null,
46698
+ access: "create"
46699
+ },
46442
46700
  "pipelineOrchestrator.resetNodePipelineDefaults": {
46443
46701
  capName: "pipeline-orchestrator",
46444
46702
  capScope: "system",
@@ -46505,6 +46763,12 @@ Object.freeze({
46505
46763
  addonId: null,
46506
46764
  access: "create"
46507
46765
  },
46766
+ "pipelineOrchestrator.setCameraSensors": {
46767
+ capName: "pipeline-orchestrator",
46768
+ capScope: "system",
46769
+ addonId: null,
46770
+ access: "create"
46771
+ },
46508
46772
  "pipelineOrchestrator.setCameraStepOverride": {
46509
46773
  capName: "pipeline-orchestrator",
46510
46774
  capScope: "system",
@@ -49915,6 +50179,11 @@ Object.freeze({
49915
50179
  form: "single",
49916
50180
  optional: false
49917
50181
  }],
50182
+ "pipelineAnalytics.clearTrackRelation": [{
50183
+ name: "deviceId",
50184
+ form: "single",
50185
+ optional: false
50186
+ }],
49918
50187
  "pipelineAnalytics.clearTracks": [{
49919
50188
  name: "deviceId",
49920
50189
  form: "single",
@@ -50050,11 +50319,6 @@ Object.freeze({
50050
50319
  form: "single",
50051
50320
  optional: true
50052
50321
  }],
50053
- "pipelineAnalytics.listRecentSummaries": [{
50054
- name: "deviceIds",
50055
- form: "array",
50056
- optional: false
50057
- }],
50058
50322
  "pipelineAnalytics.listRecentTracks": [{
50059
50323
  name: "deviceIds",
50060
50324
  form: "array",
@@ -50065,12 +50329,12 @@ Object.freeze({
50065
50329
  form: "array",
50066
50330
  optional: true
50067
50331
  }],
50068
- "pipelineAnalytics.listSummaries": [{
50069
- name: "deviceIds",
50070
- form: "array",
50332
+ "pipelineAnalytics.listTrackMedia": [{
50333
+ name: "deviceId",
50334
+ form: "single",
50071
50335
  optional: false
50072
50336
  }],
50073
- "pipelineAnalytics.listTrackMedia": [{
50337
+ "pipelineAnalytics.listTrackRelations": [{
50074
50338
  name: "deviceId",
50075
50339
  form: "single",
50076
50340
  optional: false
@@ -50145,6 +50409,16 @@ Object.freeze({
50145
50409
  form: "single",
50146
50410
  optional: false
50147
50411
  }],
50412
+ "pipelineAnalytics.setTrackPurity": [{
50413
+ name: "deviceId",
50414
+ form: "single",
50415
+ optional: false
50416
+ }],
50417
+ "pipelineAnalytics.setTrackRelation": [{
50418
+ name: "deviceId",
50419
+ form: "single",
50420
+ optional: false
50421
+ }],
50148
50422
  "pipelineAnalytics.wipeAllAnalytics": [{
50149
50423
  name: "deviceId",
50150
50424
  form: "single",
@@ -50215,6 +50489,11 @@ Object.freeze({
50215
50489
  form: "single",
50216
50490
  optional: false
50217
50491
  }],
50492
+ "pipelineOrchestrator.requestOccupancyLook": [{
50493
+ name: "deviceId",
50494
+ form: "single",
50495
+ optional: false
50496
+ }],
50218
50497
  "pipelineOrchestrator.resolvePipeline": [{
50219
50498
  name: "deviceId",
50220
50499
  form: "single",
@@ -50225,6 +50504,11 @@ Object.freeze({
50225
50504
  form: "single",
50226
50505
  optional: false
50227
50506
  }],
50507
+ "pipelineOrchestrator.setCameraSensors": [{
50508
+ name: "deviceId",
50509
+ form: "single",
50510
+ optional: false
50511
+ }],
50228
50512
  "pipelineOrchestrator.setCameraStepOverride": [{
50229
50513
  name: "deviceId",
50230
50514
  form: "single",
@@ -51654,6 +51938,37 @@ var STATE_SUMMARY_VARS = [
51654
51938
  [...RULE_TEXT],
51655
51939
  ...STATE_SUMMARY_VARS
51656
51940
  ];
51941
+ new Set([
51942
+ "disarmed",
51943
+ "armed_home",
51944
+ "armed_away",
51945
+ "armed_night",
51946
+ "armed_vacation",
51947
+ "armed_custom_bypass",
51948
+ "arming",
51949
+ "disarming",
51950
+ "pending",
51951
+ "triggered",
51952
+ "open",
51953
+ "opening",
51954
+ "closing",
51955
+ "closed",
51956
+ "stopped",
51957
+ "locked",
51958
+ "unlocked",
51959
+ "locking",
51960
+ "unlocking",
51961
+ "jammed",
51962
+ "on",
51963
+ "off",
51964
+ "home",
51965
+ "not_home",
51966
+ "matched",
51967
+ "diverged",
51968
+ "unknown",
51969
+ "latched",
51970
+ "live"
51971
+ ]);
51657
51972
  /**
51658
51973
  * TimelapseRule — the STANDALONE scheduled timelapse producer's rule model.
51659
51974
  *