@camstack/addon-export-ha-mqtt 1.1.22 → 1.1.23

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.
@@ -36,7 +36,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
36
36
  }) : target, mod));
37
37
  var __toCommonJS = (mod) => __hasOwnProp.call(mod, "module.exports") ? mod["module.exports"] : __copyProps(__defProp({}, "__esModule", { value: true }), mod);
38
38
  //#endregion
39
- //#region ../types/dist/event-category-CFZs3jI4.mjs
39
+ //#region ../types/dist/event-category-H4AVePnn.mjs
40
40
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
41
41
  EventCategory["SystemBoot"] = "system.boot";
42
42
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -186,6 +186,9 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
186
186
  EventCategory["RecordingSegmentWritten"] = "recording.segment.written";
187
187
  EventCategory["RecordingPolicyFallback"] = "recording.policy.fallback";
188
188
  EventCategory["RecordingRetentionCompleted"] = "recording.retention.completed";
189
+ /** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
190
+ * thumb is a scrub gap the recorder's keyframe backfill covers. */
191
+ EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
189
192
  EventCategory["DetectionEvent"] = "detection.event";
190
193
  EventCategory["SessionTrackNew"] = "session.track.new";
191
194
  EventCategory["SessionTrackExpired"] = "session.track.expired";
@@ -9864,7 +9867,7 @@ object({
9864
9867
  deviceId: number$1(),
9865
9868
  timestamp: number$1()
9866
9869
  });
9867
- DeviceType.Button;
9870
+ DeviceType.Button, DeviceType.Camera;
9868
9871
  /**
9869
9872
  * Enum-state sensor — a string value picked from a finite option set.
9870
9873
  * Drives HA `sensor` entries with `state_class: enum` (HVAC action
@@ -14259,6 +14262,14 @@ var ConfigEntrySchema = object({
14259
14262
  value: unknown(),
14260
14263
  description: string().optional()
14261
14264
  });
14265
+ var DeviceLinkModeSchema = _enum(["auto", "manual"]);
14266
+ /** One resolved linked device — the compact projection consumers need. */
14267
+ var LinkedDeviceSchema = object({
14268
+ deviceId: number$1(),
14269
+ name: string(),
14270
+ location: string().nullable(),
14271
+ features: array(string())
14272
+ });
14262
14273
  var SavedDeviceRowSchema = object({
14263
14274
  /** Numeric id reserved at allocateDeviceId time. */
14264
14275
  id: number$1(),
@@ -14480,7 +14491,10 @@ method(object({
14480
14491
  }), _void(), {
14481
14492
  kind: "mutation",
14482
14493
  auth: "admin"
14483
- }), method(object({ addonId: string() }), array(SavedDeviceRowSchema)), method(object({ addonId: string().optional() }), array(DeviceInfoSchema)), method(object({ deviceId: number$1() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number$1() }), array(DeviceInfoSchema)), method(object({ deviceId: number$1() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number$1() }), array(ConfigEntrySchema)), method(object({ deviceId: number$1() }), ConfigUISchemaOutput), method(object({
14494
+ }), method(object({ addonId: string() }), array(SavedDeviceRowSchema)), method(object({ addonId: string().optional() }), array(DeviceInfoSchema)), method(object({ deviceId: number$1() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number$1() }), array(DeviceInfoSchema)), method(object({ deviceId: number$1() }), object({
14495
+ mode: DeviceLinkModeSchema,
14496
+ devices: array(LinkedDeviceSchema)
14497
+ })), method(object({ deviceId: number$1() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number$1() }), array(ConfigEntrySchema)), method(object({ deviceId: number$1() }), ConfigUISchemaOutput), method(object({
14484
14498
  deviceId: number$1(),
14485
14499
  values: record(string(), unknown())
14486
14500
  }), object({ success: literal(true) }), {
@@ -15749,6 +15763,61 @@ var EventKindSchema = _enum([
15749
15763
  "object",
15750
15764
  "audio"
15751
15765
  ]);
15766
+ /**
15767
+ * Spatial filter for `listTracks` — the rect + polygon variants of the shared
15768
+ * MaskShape vocabulary (see `mask-shape.ts`). Coordinates are NORMALIZED 0..1
15769
+ * of the camera frame (top-left origin), matching the drawing-plane editor.
15770
+ */
15771
+ var TrackZoneFilterSchema = discriminatedUnion("kind", [MaskRectShapeSchema, MaskPolygonShapeSchema]);
15772
+ /** Closed icon vocabulary so clients render a known glyph per kind. */
15773
+ var EventKindIconSchema = _enum([
15774
+ "motion",
15775
+ "audio",
15776
+ "person",
15777
+ "vehicle",
15778
+ "animal",
15779
+ "door",
15780
+ "pir",
15781
+ "smoke",
15782
+ "water",
15783
+ "button",
15784
+ "generic"
15785
+ ]);
15786
+ var EventKindCategorySchema = _enum([
15787
+ "motion",
15788
+ "audio",
15789
+ "detection",
15790
+ "sensor",
15791
+ "custom"
15792
+ ]);
15793
+ var EventKindDescriptorSchema = object({
15794
+ /** Stable kind id (e.g. 'motion', 'person', 'contact'). */
15795
+ kind: string(),
15796
+ label: string(),
15797
+ /** Hex color for timeline/legend rendering. */
15798
+ color: string(),
15799
+ icon: EventKindIconSchema,
15800
+ category: EventKindCategorySchema,
15801
+ /** Which cap + device contributes this kind. For built-ins the camera
15802
+ * itself; for sensor kinds the LINKED source device. */
15803
+ source: object({
15804
+ capName: string(),
15805
+ deviceId: number$1()
15806
+ })
15807
+ });
15808
+ var SensorEventSchema = object({
15809
+ id: string(),
15810
+ /** The CAMERA the event is attributed to (a sensor linked to N cameras
15811
+ * yields N rows, one per camera). */
15812
+ deviceId: number$1(),
15813
+ /** The linked sensor device whose state changed. */
15814
+ sourceDeviceId: number$1(),
15815
+ /** Event kind id — matches an `EventKindDescriptor.kind`. */
15816
+ kind: string(),
15817
+ /** Snapshot of the sensor cap's runtime-state slice at the change. */
15818
+ value: record(string(), unknown()).nullable(),
15819
+ timestamp: number$1()
15820
+ });
15752
15821
  var TrackPositionSchema = object({
15753
15822
  x: number$1(),
15754
15823
  y: number$1(),
@@ -15762,6 +15831,30 @@ var TrackSnapshotSchema = object({
15762
15831
  mediaKey: string()
15763
15832
  });
15764
15833
  /**
15834
+ * Normalized 0..1 trajectory envelope (min/max over every position bbox,
15835
+ * divided by the track's detection-frame dims), computed at persist time.
15836
+ * Absent when the frame dims were unknown when the track was persisted
15837
+ * (legacy rows / dims-less sources) and on active (in-RAM) tracks.
15838
+ */
15839
+ var TrackEnvelopeSchema = object({
15840
+ minX: number$1(),
15841
+ minY: number$1(),
15842
+ maxX: number$1(),
15843
+ maxY: number$1()
15844
+ });
15845
+ /**
15846
+ * Row projection for track list queries. `full` (default) returns the
15847
+ * complete Track including the frame-rate `positions[]` history and the
15848
+ * `snapshots[]` references — megabytes across a page of tracks. `slim`
15849
+ * keeps every scalar the list surfaces actually render (ids, class(es),
15850
+ * label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
15851
+ * zonesVisited, bestEventId, envelope) and returns `positions` /
15852
+ * `snapshots` as EMPTY arrays — detail views re-fetch the full row via
15853
+ * `getTrack`. Mirrors the event-store `projection` convention
15854
+ * (`getObjectEvents` et al.).
15855
+ */
15856
+ var TrackProjectionSchema = _enum(["full", "slim"]);
15857
+ /**
15765
15858
  * One audio-classification label heard on the track's camera while the
15766
15859
  * track was alive, aggregated per label. An "episode" is one persisted
15767
15860
  * audio event (the confident-classification path: score ≥ the device's
@@ -15812,7 +15905,11 @@ var TrackSchema = object({
15812
15905
  /** Audio-classification labels heard on the camera during the track's
15813
15906
  * life (score ≥ device `classificationMinScore`), aggregated per label.
15814
15907
  * Absent on legacy rows / tracks with no confident audio. */
15815
- audioLabels: array(TrackAudioLabelSchema).readonly().optional()
15908
+ audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
15909
+ /** Normalized 0..1 trajectory envelope (see {@link TrackEnvelopeSchema}).
15910
+ * Populated from the persisted envelope columns on historical reads;
15911
+ * absent on legacy rows, dims-less tracks and active (in-RAM) tracks. */
15912
+ envelope: TrackEnvelopeSchema.optional()
15816
15913
  });
15817
15914
  var BaseEventFields = {
15818
15915
  id: string(),
@@ -15922,11 +16019,13 @@ var MediaFileSchema = object({
15922
16019
  sizeBytes: number$1(),
15923
16020
  timestamp: number$1()
15924
16021
  });
16022
+ var DEFAULT_EVENT_QUERY_LIMIT = 1e3;
16023
+ var MAX_EVENT_QUERY_LIMIT = 5e3;
15925
16024
  var DeviceEventQueryInput = object({
15926
16025
  deviceId: number$1(),
15927
16026
  since: number$1().optional(),
15928
16027
  until: number$1().optional(),
15929
- limit: number$1().int().min(1).max(5e3).default(1e3),
16028
+ limit: number$1().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT),
15930
16029
  /** `slim` drops heavy JSON fields (regions/bbox/zones) and carries an
15931
16030
  * optional `mediaUrl` (populated by B5). `full` (default) keeps today's
15932
16031
  * exact behaviour. Callers may omit this field — the store defaults to
@@ -15934,6 +16033,27 @@ var DeviceEventQueryInput = object({
15934
16033
  projection: _enum(["full", "slim"]).optional()
15935
16034
  });
15936
16035
  var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string().optional() });
16036
+ var RecentTracksQueryInput = object({
16037
+ /** Devices to merge. An empty array yields `{ tracks: [], nextCursor: null }`. */
16038
+ deviceIds: array(number$1()),
16039
+ /** Window lower bound on `lastSeen` (inclusive). */
16040
+ since: number$1().optional(),
16041
+ /** Window upper bound on `lastSeen` (inclusive). */
16042
+ until: number$1().optional(),
16043
+ /** Page size. Default 200, max 1000. */
16044
+ limit: number$1().int().min(1).max(1e3).default(200),
16045
+ /** Opaque continuation cursor from a previous page's `nextCursor`.
16046
+ * Encodes the (lastSeen, trackId) sort position — treat as opaque. */
16047
+ cursor: string().optional(),
16048
+ /** See {@link TrackProjectionSchema}. Default `full`. */
16049
+ projection: TrackProjectionSchema.optional()
16050
+ });
16051
+ var RecentTracksPageSchema = object({
16052
+ /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
16053
+ tracks: array(TrackSchema).readonly(),
16054
+ /** Cursor for the next page, or null when this page is the last. */
16055
+ nextCursor: string().nullable()
16056
+ });
15937
16057
  var KeyEventQueryInput = object({
15938
16058
  deviceId: number$1(),
15939
16059
  /** Window lower bound (track firstSeen ≥ since). */
@@ -16016,11 +16136,25 @@ DeviceType.Camera, method(object({ deviceId: number$1() }), array(TrackSchema).r
16016
16136
  deviceId: number$1(),
16017
16137
  since: number$1().optional(),
16018
16138
  until: number$1().optional(),
16019
- limit: number$1().optional()
16020
- }), array(TrackSchema).readonly()), method(object({ deviceId: number$1() }), _void(), {
16021
- kind: "mutation",
16022
- auth: "admin"
16023
- }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
16139
+ limit: number$1().optional(),
16140
+ /** Spatial filter only tracks whose trajectory intersects the zone
16141
+ * (normalized 0..1 rect or polygon). SQL-prefiltered on the persisted
16142
+ * envelope columns, then precisely tested per position. Tracks with
16143
+ * an unknown envelope (no frame dims at persist time) always match. */
16144
+ zone: TrackZoneFilterSchema.optional(),
16145
+ /** See {@link TrackProjectionSchema}. Default `full` (backward
16146
+ * compatible — omitting the field keeps today's exact behaviour). */
16147
+ projection: TrackProjectionSchema.optional()
16148
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number$1() }), _void(), {
16149
+ kind: "mutation",
16150
+ auth: "admin"
16151
+ }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number$1() }), array(EventKindDescriptorSchema).readonly()), method(object({
16152
+ deviceId: number$1(),
16153
+ since: number$1().optional(),
16154
+ until: number$1().optional(),
16155
+ kinds: array(string()).optional(),
16156
+ limit: number$1().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
16157
+ }), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
16024
16158
  deviceId: number$1(),
16025
16159
  since: number$1(),
16026
16160
  until: number$1(),
@@ -19221,7 +19355,12 @@ var RecordingStorageUsageSchema = object({
19221
19355
  /**
19222
19356
  * Result of locating footage at a wall-clock instant for one device/profile.
19223
19357
  * `segment` carries the covering segment's window; `gap` reports the forward
19224
- * nearest covered edge (`null` past the end of footage / when none exists).
19358
+ * nearest covered edge (`null` past the end of footage / when none exists)
19359
+ * and the backward covered edge `prevEndMs` (exclusive end of the nearest
19360
+ * footage behind the epoch; `null` when none — optional so older providers
19361
+ * that omit it stay valid). `prevEndMs` lets a backward frame-step hop the
19362
+ * small inter-segment cracks (durMs under-covers the span to the next
19363
+ * startMs by ~11-17 ms) instead of no-opping at a segment head.
19225
19364
  */
19226
19365
  var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
19227
19366
  kind: literal("segment"),
@@ -19230,7 +19369,8 @@ var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
19230
19369
  bytes: number$1()
19231
19370
  }), object({
19232
19371
  kind: literal("gap"),
19233
- nearestEdgeMs: number$1().nullable()
19372
+ nearestEdgeMs: number$1().nullable(),
19373
+ prevEndMs: number$1().nullable().optional()
19234
19374
  })]);
19235
19375
  /** Raw bytes of one finalized footage segment (read off disk on the recording node). */
19236
19376
  var ReadSegmentBytesResultSchema = object({ data: _instanceof(Uint8Array) });
@@ -20799,6 +20939,12 @@ Object.freeze({
20799
20939
  addonId: null,
20800
20940
  access: "view"
20801
20941
  },
20942
+ "deviceManager.getLinkedDevices": {
20943
+ capName: "device-manager",
20944
+ capScope: "system",
20945
+ addonId: null,
20946
+ access: "view"
20947
+ },
20802
20948
  "deviceManager.getRoleDisplayDefaults": {
20803
20949
  capName: "device-manager",
20804
20950
  capScope: "system",
@@ -22353,6 +22499,12 @@ Object.freeze({
22353
22499
  addonId: null,
22354
22500
  access: "view"
22355
22501
  },
22502
+ "pipelineAnalytics.getSensorEvents": {
22503
+ capName: "pipeline-analytics",
22504
+ capScope: "device",
22505
+ addonId: null,
22506
+ access: "view"
22507
+ },
22356
22508
  "pipelineAnalytics.getTrack": {
22357
22509
  capName: "pipeline-analytics",
22358
22510
  capScope: "device",
@@ -22365,6 +22517,18 @@ Object.freeze({
22365
22517
  addonId: null,
22366
22518
  access: "view"
22367
22519
  },
22520
+ "pipelineAnalytics.listEventKinds": {
22521
+ capName: "pipeline-analytics",
22522
+ capScope: "device",
22523
+ addonId: null,
22524
+ access: "view"
22525
+ },
22526
+ "pipelineAnalytics.listRecentTracks": {
22527
+ capName: "pipeline-analytics",
22528
+ capScope: "device",
22529
+ addonId: null,
22530
+ access: "view"
22531
+ },
22368
22532
  "pipelineAnalytics.listTracks": {
22369
22533
  capName: "pipeline-analytics",
22370
22534
  capScope: "device",
@@ -34,7 +34,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
34
34
  var __toCommonJS = (mod) => __hasOwnProp.call(mod, "module.exports") ? mod["module.exports"] : __copyProps(__defProp({}, "__esModule", { value: true }), mod);
35
35
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
36
36
  //#endregion
37
- //#region ../types/dist/event-category-CFZs3jI4.mjs
37
+ //#region ../types/dist/event-category-H4AVePnn.mjs
38
38
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
39
39
  EventCategory["SystemBoot"] = "system.boot";
40
40
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -184,6 +184,9 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
184
184
  EventCategory["RecordingSegmentWritten"] = "recording.segment.written";
185
185
  EventCategory["RecordingPolicyFallback"] = "recording.policy.fallback";
186
186
  EventCategory["RecordingRetentionCompleted"] = "recording.retention.completed";
187
+ /** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
188
+ * thumb is a scrub gap the recorder's keyframe backfill covers. */
189
+ EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
187
190
  EventCategory["DetectionEvent"] = "detection.event";
188
191
  EventCategory["SessionTrackNew"] = "session.track.new";
189
192
  EventCategory["SessionTrackExpired"] = "session.track.expired";
@@ -9862,7 +9865,7 @@ object({
9862
9865
  deviceId: number$1(),
9863
9866
  timestamp: number$1()
9864
9867
  });
9865
- DeviceType.Button;
9868
+ DeviceType.Button, DeviceType.Camera;
9866
9869
  /**
9867
9870
  * Enum-state sensor — a string value picked from a finite option set.
9868
9871
  * Drives HA `sensor` entries with `state_class: enum` (HVAC action
@@ -14257,6 +14260,14 @@ var ConfigEntrySchema = object({
14257
14260
  value: unknown(),
14258
14261
  description: string().optional()
14259
14262
  });
14263
+ var DeviceLinkModeSchema = _enum(["auto", "manual"]);
14264
+ /** One resolved linked device — the compact projection consumers need. */
14265
+ var LinkedDeviceSchema = object({
14266
+ deviceId: number$1(),
14267
+ name: string(),
14268
+ location: string().nullable(),
14269
+ features: array(string())
14270
+ });
14260
14271
  var SavedDeviceRowSchema = object({
14261
14272
  /** Numeric id reserved at allocateDeviceId time. */
14262
14273
  id: number$1(),
@@ -14478,7 +14489,10 @@ method(object({
14478
14489
  }), _void(), {
14479
14490
  kind: "mutation",
14480
14491
  auth: "admin"
14481
- }), method(object({ addonId: string() }), array(SavedDeviceRowSchema)), method(object({ addonId: string().optional() }), array(DeviceInfoSchema)), method(object({ deviceId: number$1() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number$1() }), array(DeviceInfoSchema)), method(object({ deviceId: number$1() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number$1() }), array(ConfigEntrySchema)), method(object({ deviceId: number$1() }), ConfigUISchemaOutput), method(object({
14492
+ }), method(object({ addonId: string() }), array(SavedDeviceRowSchema)), method(object({ addonId: string().optional() }), array(DeviceInfoSchema)), method(object({ deviceId: number$1() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number$1() }), array(DeviceInfoSchema)), method(object({ deviceId: number$1() }), object({
14493
+ mode: DeviceLinkModeSchema,
14494
+ devices: array(LinkedDeviceSchema)
14495
+ })), method(object({ deviceId: number$1() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number$1() }), array(ConfigEntrySchema)), method(object({ deviceId: number$1() }), ConfigUISchemaOutput), method(object({
14482
14496
  deviceId: number$1(),
14483
14497
  values: record(string(), unknown())
14484
14498
  }), object({ success: literal(true) }), {
@@ -15747,6 +15761,61 @@ var EventKindSchema = _enum([
15747
15761
  "object",
15748
15762
  "audio"
15749
15763
  ]);
15764
+ /**
15765
+ * Spatial filter for `listTracks` — the rect + polygon variants of the shared
15766
+ * MaskShape vocabulary (see `mask-shape.ts`). Coordinates are NORMALIZED 0..1
15767
+ * of the camera frame (top-left origin), matching the drawing-plane editor.
15768
+ */
15769
+ var TrackZoneFilterSchema = discriminatedUnion("kind", [MaskRectShapeSchema, MaskPolygonShapeSchema]);
15770
+ /** Closed icon vocabulary so clients render a known glyph per kind. */
15771
+ var EventKindIconSchema = _enum([
15772
+ "motion",
15773
+ "audio",
15774
+ "person",
15775
+ "vehicle",
15776
+ "animal",
15777
+ "door",
15778
+ "pir",
15779
+ "smoke",
15780
+ "water",
15781
+ "button",
15782
+ "generic"
15783
+ ]);
15784
+ var EventKindCategorySchema = _enum([
15785
+ "motion",
15786
+ "audio",
15787
+ "detection",
15788
+ "sensor",
15789
+ "custom"
15790
+ ]);
15791
+ var EventKindDescriptorSchema = object({
15792
+ /** Stable kind id (e.g. 'motion', 'person', 'contact'). */
15793
+ kind: string(),
15794
+ label: string(),
15795
+ /** Hex color for timeline/legend rendering. */
15796
+ color: string(),
15797
+ icon: EventKindIconSchema,
15798
+ category: EventKindCategorySchema,
15799
+ /** Which cap + device contributes this kind. For built-ins the camera
15800
+ * itself; for sensor kinds the LINKED source device. */
15801
+ source: object({
15802
+ capName: string(),
15803
+ deviceId: number$1()
15804
+ })
15805
+ });
15806
+ var SensorEventSchema = object({
15807
+ id: string(),
15808
+ /** The CAMERA the event is attributed to (a sensor linked to N cameras
15809
+ * yields N rows, one per camera). */
15810
+ deviceId: number$1(),
15811
+ /** The linked sensor device whose state changed. */
15812
+ sourceDeviceId: number$1(),
15813
+ /** Event kind id — matches an `EventKindDescriptor.kind`. */
15814
+ kind: string(),
15815
+ /** Snapshot of the sensor cap's runtime-state slice at the change. */
15816
+ value: record(string(), unknown()).nullable(),
15817
+ timestamp: number$1()
15818
+ });
15750
15819
  var TrackPositionSchema = object({
15751
15820
  x: number$1(),
15752
15821
  y: number$1(),
@@ -15760,6 +15829,30 @@ var TrackSnapshotSchema = object({
15760
15829
  mediaKey: string()
15761
15830
  });
15762
15831
  /**
15832
+ * Normalized 0..1 trajectory envelope (min/max over every position bbox,
15833
+ * divided by the track's detection-frame dims), computed at persist time.
15834
+ * Absent when the frame dims were unknown when the track was persisted
15835
+ * (legacy rows / dims-less sources) and on active (in-RAM) tracks.
15836
+ */
15837
+ var TrackEnvelopeSchema = object({
15838
+ minX: number$1(),
15839
+ minY: number$1(),
15840
+ maxX: number$1(),
15841
+ maxY: number$1()
15842
+ });
15843
+ /**
15844
+ * Row projection for track list queries. `full` (default) returns the
15845
+ * complete Track including the frame-rate `positions[]` history and the
15846
+ * `snapshots[]` references — megabytes across a page of tracks. `slim`
15847
+ * keeps every scalar the list surfaces actually render (ids, class(es),
15848
+ * label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
15849
+ * zonesVisited, bestEventId, envelope) and returns `positions` /
15850
+ * `snapshots` as EMPTY arrays — detail views re-fetch the full row via
15851
+ * `getTrack`. Mirrors the event-store `projection` convention
15852
+ * (`getObjectEvents` et al.).
15853
+ */
15854
+ var TrackProjectionSchema = _enum(["full", "slim"]);
15855
+ /**
15763
15856
  * One audio-classification label heard on the track's camera while the
15764
15857
  * track was alive, aggregated per label. An "episode" is one persisted
15765
15858
  * audio event (the confident-classification path: score ≥ the device's
@@ -15810,7 +15903,11 @@ var TrackSchema = object({
15810
15903
  /** Audio-classification labels heard on the camera during the track's
15811
15904
  * life (score ≥ device `classificationMinScore`), aggregated per label.
15812
15905
  * Absent on legacy rows / tracks with no confident audio. */
15813
- audioLabels: array(TrackAudioLabelSchema).readonly().optional()
15906
+ audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
15907
+ /** Normalized 0..1 trajectory envelope (see {@link TrackEnvelopeSchema}).
15908
+ * Populated from the persisted envelope columns on historical reads;
15909
+ * absent on legacy rows, dims-less tracks and active (in-RAM) tracks. */
15910
+ envelope: TrackEnvelopeSchema.optional()
15814
15911
  });
15815
15912
  var BaseEventFields = {
15816
15913
  id: string(),
@@ -15920,11 +16017,13 @@ var MediaFileSchema = object({
15920
16017
  sizeBytes: number$1(),
15921
16018
  timestamp: number$1()
15922
16019
  });
16020
+ var DEFAULT_EVENT_QUERY_LIMIT = 1e3;
16021
+ var MAX_EVENT_QUERY_LIMIT = 5e3;
15923
16022
  var DeviceEventQueryInput = object({
15924
16023
  deviceId: number$1(),
15925
16024
  since: number$1().optional(),
15926
16025
  until: number$1().optional(),
15927
- limit: number$1().int().min(1).max(5e3).default(1e3),
16026
+ limit: number$1().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT),
15928
16027
  /** `slim` drops heavy JSON fields (regions/bbox/zones) and carries an
15929
16028
  * optional `mediaUrl` (populated by B5). `full` (default) keeps today's
15930
16029
  * exact behaviour. Callers may omit this field — the store defaults to
@@ -15932,6 +16031,27 @@ var DeviceEventQueryInput = object({
15932
16031
  projection: _enum(["full", "slim"]).optional()
15933
16032
  });
15934
16033
  var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string().optional() });
16034
+ var RecentTracksQueryInput = object({
16035
+ /** Devices to merge. An empty array yields `{ tracks: [], nextCursor: null }`. */
16036
+ deviceIds: array(number$1()),
16037
+ /** Window lower bound on `lastSeen` (inclusive). */
16038
+ since: number$1().optional(),
16039
+ /** Window upper bound on `lastSeen` (inclusive). */
16040
+ until: number$1().optional(),
16041
+ /** Page size. Default 200, max 1000. */
16042
+ limit: number$1().int().min(1).max(1e3).default(200),
16043
+ /** Opaque continuation cursor from a previous page's `nextCursor`.
16044
+ * Encodes the (lastSeen, trackId) sort position — treat as opaque. */
16045
+ cursor: string().optional(),
16046
+ /** See {@link TrackProjectionSchema}. Default `full`. */
16047
+ projection: TrackProjectionSchema.optional()
16048
+ });
16049
+ var RecentTracksPageSchema = object({
16050
+ /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
16051
+ tracks: array(TrackSchema).readonly(),
16052
+ /** Cursor for the next page, or null when this page is the last. */
16053
+ nextCursor: string().nullable()
16054
+ });
15935
16055
  var KeyEventQueryInput = object({
15936
16056
  deviceId: number$1(),
15937
16057
  /** Window lower bound (track firstSeen ≥ since). */
@@ -16014,11 +16134,25 @@ DeviceType.Camera, method(object({ deviceId: number$1() }), array(TrackSchema).r
16014
16134
  deviceId: number$1(),
16015
16135
  since: number$1().optional(),
16016
16136
  until: number$1().optional(),
16017
- limit: number$1().optional()
16018
- }), array(TrackSchema).readonly()), method(object({ deviceId: number$1() }), _void(), {
16019
- kind: "mutation",
16020
- auth: "admin"
16021
- }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
16137
+ limit: number$1().optional(),
16138
+ /** Spatial filter only tracks whose trajectory intersects the zone
16139
+ * (normalized 0..1 rect or polygon). SQL-prefiltered on the persisted
16140
+ * envelope columns, then precisely tested per position. Tracks with
16141
+ * an unknown envelope (no frame dims at persist time) always match. */
16142
+ zone: TrackZoneFilterSchema.optional(),
16143
+ /** See {@link TrackProjectionSchema}. Default `full` (backward
16144
+ * compatible — omitting the field keeps today's exact behaviour). */
16145
+ projection: TrackProjectionSchema.optional()
16146
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number$1() }), _void(), {
16147
+ kind: "mutation",
16148
+ auth: "admin"
16149
+ }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number$1() }), array(EventKindDescriptorSchema).readonly()), method(object({
16150
+ deviceId: number$1(),
16151
+ since: number$1().optional(),
16152
+ until: number$1().optional(),
16153
+ kinds: array(string()).optional(),
16154
+ limit: number$1().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
16155
+ }), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
16022
16156
  deviceId: number$1(),
16023
16157
  since: number$1(),
16024
16158
  until: number$1(),
@@ -19219,7 +19353,12 @@ var RecordingStorageUsageSchema = object({
19219
19353
  /**
19220
19354
  * Result of locating footage at a wall-clock instant for one device/profile.
19221
19355
  * `segment` carries the covering segment's window; `gap` reports the forward
19222
- * nearest covered edge (`null` past the end of footage / when none exists).
19356
+ * nearest covered edge (`null` past the end of footage / when none exists)
19357
+ * and the backward covered edge `prevEndMs` (exclusive end of the nearest
19358
+ * footage behind the epoch; `null` when none — optional so older providers
19359
+ * that omit it stay valid). `prevEndMs` lets a backward frame-step hop the
19360
+ * small inter-segment cracks (durMs under-covers the span to the next
19361
+ * startMs by ~11-17 ms) instead of no-opping at a segment head.
19223
19362
  */
19224
19363
  var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
19225
19364
  kind: literal("segment"),
@@ -19228,7 +19367,8 @@ var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
19228
19367
  bytes: number$1()
19229
19368
  }), object({
19230
19369
  kind: literal("gap"),
19231
- nearestEdgeMs: number$1().nullable()
19370
+ nearestEdgeMs: number$1().nullable(),
19371
+ prevEndMs: number$1().nullable().optional()
19232
19372
  })]);
19233
19373
  /** Raw bytes of one finalized footage segment (read off disk on the recording node). */
19234
19374
  var ReadSegmentBytesResultSchema = object({ data: _instanceof(Uint8Array) });
@@ -20797,6 +20937,12 @@ Object.freeze({
20797
20937
  addonId: null,
20798
20938
  access: "view"
20799
20939
  },
20940
+ "deviceManager.getLinkedDevices": {
20941
+ capName: "device-manager",
20942
+ capScope: "system",
20943
+ addonId: null,
20944
+ access: "view"
20945
+ },
20800
20946
  "deviceManager.getRoleDisplayDefaults": {
20801
20947
  capName: "device-manager",
20802
20948
  capScope: "system",
@@ -22351,6 +22497,12 @@ Object.freeze({
22351
22497
  addonId: null,
22352
22498
  access: "view"
22353
22499
  },
22500
+ "pipelineAnalytics.getSensorEvents": {
22501
+ capName: "pipeline-analytics",
22502
+ capScope: "device",
22503
+ addonId: null,
22504
+ access: "view"
22505
+ },
22354
22506
  "pipelineAnalytics.getTrack": {
22355
22507
  capName: "pipeline-analytics",
22356
22508
  capScope: "device",
@@ -22363,6 +22515,18 @@ Object.freeze({
22363
22515
  addonId: null,
22364
22516
  access: "view"
22365
22517
  },
22518
+ "pipelineAnalytics.listEventKinds": {
22519
+ capName: "pipeline-analytics",
22520
+ capScope: "device",
22521
+ addonId: null,
22522
+ access: "view"
22523
+ },
22524
+ "pipelineAnalytics.listRecentTracks": {
22525
+ capName: "pipeline-analytics",
22526
+ capScope: "device",
22527
+ addonId: null,
22528
+ access: "view"
22529
+ },
22366
22530
  "pipelineAnalytics.listTracks": {
22367
22531
  capName: "pipeline-analytics",
22368
22532
  capScope: "device",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-export-ha-mqtt",
3
- "version": "1.1.22",
3
+ "version": "1.1.23",
4
4
  "description": "HomeAssistant MQTT discovery exporter for CamStack devices. Publishes discovery topics so HA auto-creates entities for exposed cameras/switches/intercoms/sensors.",
5
5
  "keywords": [
6
6
  "camstack",