@camstack/addon-provider-onvif 1.1.25 → 1.1.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/addon.js +176 -12
  2. package/dist/addon.mjs +176 -12
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -2,7 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  //#region \0rolldown/runtime.js
3
3
  var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
4
4
  //#endregion
5
- //#region ../types/dist/event-category-CFZs3jI4.mjs
5
+ //#region ../types/dist/event-category-H4AVePnn.mjs
6
6
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
7
7
  EventCategory["SystemBoot"] = "system.boot";
8
8
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -152,6 +152,9 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
152
152
  EventCategory["RecordingSegmentWritten"] = "recording.segment.written";
153
153
  EventCategory["RecordingPolicyFallback"] = "recording.policy.fallback";
154
154
  EventCategory["RecordingRetentionCompleted"] = "recording.retention.completed";
155
+ /** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
156
+ * thumb is a scrub gap the recorder's keyframe backfill covers. */
157
+ EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
155
158
  EventCategory["DetectionEvent"] = "detection.event";
156
159
  EventCategory["SessionTrackNew"] = "session.track.new";
157
160
  EventCategory["SessionTrackExpired"] = "session.track.expired";
@@ -9998,7 +10001,7 @@ object({
9998
10001
  deviceId: number(),
9999
10002
  timestamp: number()
10000
10003
  });
10001
- DeviceType.Button;
10004
+ DeviceType.Button, DeviceType.Camera;
10002
10005
  /**
10003
10006
  * Enum-state sensor — a string value picked from a finite option set.
10004
10007
  * Drives HA `sensor` entries with `state_class: enum` (HVAC action
@@ -14662,6 +14665,14 @@ var ConfigEntrySchema = object({
14662
14665
  value: unknown(),
14663
14666
  description: string().optional()
14664
14667
  });
14668
+ var DeviceLinkModeSchema = _enum(["auto", "manual"]);
14669
+ /** One resolved linked device — the compact projection consumers need. */
14670
+ var LinkedDeviceSchema = object({
14671
+ deviceId: number(),
14672
+ name: string(),
14673
+ location: string().nullable(),
14674
+ features: array(string())
14675
+ });
14665
14676
  var SavedDeviceRowSchema = object({
14666
14677
  /** Numeric id reserved at allocateDeviceId time. */
14667
14678
  id: number(),
@@ -14883,7 +14894,10 @@ method(object({
14883
14894
  }), _void(), {
14884
14895
  kind: "mutation",
14885
14896
  auth: "admin"
14886
- }), method(object({ addonId: string() }), array(SavedDeviceRowSchema)), method(object({ addonId: string().optional() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
14897
+ }), method(object({ addonId: string() }), array(SavedDeviceRowSchema)), method(object({ addonId: string().optional() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), object({
14898
+ mode: DeviceLinkModeSchema,
14899
+ devices: array(LinkedDeviceSchema)
14900
+ })), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
14887
14901
  deviceId: number(),
14888
14902
  values: record(string(), unknown())
14889
14903
  }), object({ success: literal(true) }), {
@@ -16152,6 +16166,61 @@ var EventKindSchema = _enum([
16152
16166
  "object",
16153
16167
  "audio"
16154
16168
  ]);
16169
+ /**
16170
+ * Spatial filter for `listTracks` — the rect + polygon variants of the shared
16171
+ * MaskShape vocabulary (see `mask-shape.ts`). Coordinates are NORMALIZED 0..1
16172
+ * of the camera frame (top-left origin), matching the drawing-plane editor.
16173
+ */
16174
+ var TrackZoneFilterSchema = discriminatedUnion("kind", [MaskRectShapeSchema, MaskPolygonShapeSchema]);
16175
+ /** Closed icon vocabulary so clients render a known glyph per kind. */
16176
+ var EventKindIconSchema = _enum([
16177
+ "motion",
16178
+ "audio",
16179
+ "person",
16180
+ "vehicle",
16181
+ "animal",
16182
+ "door",
16183
+ "pir",
16184
+ "smoke",
16185
+ "water",
16186
+ "button",
16187
+ "generic"
16188
+ ]);
16189
+ var EventKindCategorySchema = _enum([
16190
+ "motion",
16191
+ "audio",
16192
+ "detection",
16193
+ "sensor",
16194
+ "custom"
16195
+ ]);
16196
+ var EventKindDescriptorSchema = object({
16197
+ /** Stable kind id (e.g. 'motion', 'person', 'contact'). */
16198
+ kind: string(),
16199
+ label: string(),
16200
+ /** Hex color for timeline/legend rendering. */
16201
+ color: string(),
16202
+ icon: EventKindIconSchema,
16203
+ category: EventKindCategorySchema,
16204
+ /** Which cap + device contributes this kind. For built-ins the camera
16205
+ * itself; for sensor kinds the LINKED source device. */
16206
+ source: object({
16207
+ capName: string(),
16208
+ deviceId: number()
16209
+ })
16210
+ });
16211
+ var SensorEventSchema = object({
16212
+ id: string(),
16213
+ /** The CAMERA the event is attributed to (a sensor linked to N cameras
16214
+ * yields N rows, one per camera). */
16215
+ deviceId: number(),
16216
+ /** The linked sensor device whose state changed. */
16217
+ sourceDeviceId: number(),
16218
+ /** Event kind id — matches an `EventKindDescriptor.kind`. */
16219
+ kind: string(),
16220
+ /** Snapshot of the sensor cap's runtime-state slice at the change. */
16221
+ value: record(string(), unknown()).nullable(),
16222
+ timestamp: number()
16223
+ });
16155
16224
  var TrackPositionSchema = object({
16156
16225
  x: number(),
16157
16226
  y: number(),
@@ -16165,6 +16234,30 @@ var TrackSnapshotSchema = object({
16165
16234
  mediaKey: string()
16166
16235
  });
16167
16236
  /**
16237
+ * Normalized 0..1 trajectory envelope (min/max over every position bbox,
16238
+ * divided by the track's detection-frame dims), computed at persist time.
16239
+ * Absent when the frame dims were unknown when the track was persisted
16240
+ * (legacy rows / dims-less sources) and on active (in-RAM) tracks.
16241
+ */
16242
+ var TrackEnvelopeSchema = object({
16243
+ minX: number(),
16244
+ minY: number(),
16245
+ maxX: number(),
16246
+ maxY: number()
16247
+ });
16248
+ /**
16249
+ * Row projection for track list queries. `full` (default) returns the
16250
+ * complete Track including the frame-rate `positions[]` history and the
16251
+ * `snapshots[]` references — megabytes across a page of tracks. `slim`
16252
+ * keeps every scalar the list surfaces actually render (ids, class(es),
16253
+ * label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
16254
+ * zonesVisited, bestEventId, envelope) and returns `positions` /
16255
+ * `snapshots` as EMPTY arrays — detail views re-fetch the full row via
16256
+ * `getTrack`. Mirrors the event-store `projection` convention
16257
+ * (`getObjectEvents` et al.).
16258
+ */
16259
+ var TrackProjectionSchema = _enum(["full", "slim"]);
16260
+ /**
16168
16261
  * One audio-classification label heard on the track's camera while the
16169
16262
  * track was alive, aggregated per label. An "episode" is one persisted
16170
16263
  * audio event (the confident-classification path: score ≥ the device's
@@ -16215,7 +16308,11 @@ var TrackSchema = object({
16215
16308
  /** Audio-classification labels heard on the camera during the track's
16216
16309
  * life (score ≥ device `classificationMinScore`), aggregated per label.
16217
16310
  * Absent on legacy rows / tracks with no confident audio. */
16218
- audioLabels: array(TrackAudioLabelSchema).readonly().optional()
16311
+ audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
16312
+ /** Normalized 0..1 trajectory envelope (see {@link TrackEnvelopeSchema}).
16313
+ * Populated from the persisted envelope columns on historical reads;
16314
+ * absent on legacy rows, dims-less tracks and active (in-RAM) tracks. */
16315
+ envelope: TrackEnvelopeSchema.optional()
16219
16316
  });
16220
16317
  var BaseEventFields = {
16221
16318
  id: string(),
@@ -16325,11 +16422,13 @@ var MediaFileSchema = object({
16325
16422
  sizeBytes: number(),
16326
16423
  timestamp: number()
16327
16424
  });
16425
+ var DEFAULT_EVENT_QUERY_LIMIT = 1e3;
16426
+ var MAX_EVENT_QUERY_LIMIT = 5e3;
16328
16427
  var DeviceEventQueryInput = object({
16329
16428
  deviceId: number(),
16330
16429
  since: number().optional(),
16331
16430
  until: number().optional(),
16332
- limit: number().int().min(1).max(5e3).default(1e3),
16431
+ limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT),
16333
16432
  /** `slim` drops heavy JSON fields (regions/bbox/zones) and carries an
16334
16433
  * optional `mediaUrl` (populated by B5). `full` (default) keeps today's
16335
16434
  * exact behaviour. Callers may omit this field — the store defaults to
@@ -16337,6 +16436,27 @@ var DeviceEventQueryInput = object({
16337
16436
  projection: _enum(["full", "slim"]).optional()
16338
16437
  });
16339
16438
  var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string().optional() });
16439
+ var RecentTracksQueryInput = object({
16440
+ /** Devices to merge. An empty array yields `{ tracks: [], nextCursor: null }`. */
16441
+ deviceIds: array(number()),
16442
+ /** Window lower bound on `lastSeen` (inclusive). */
16443
+ since: number().optional(),
16444
+ /** Window upper bound on `lastSeen` (inclusive). */
16445
+ until: number().optional(),
16446
+ /** Page size. Default 200, max 1000. */
16447
+ limit: number().int().min(1).max(1e3).default(200),
16448
+ /** Opaque continuation cursor from a previous page's `nextCursor`.
16449
+ * Encodes the (lastSeen, trackId) sort position — treat as opaque. */
16450
+ cursor: string().optional(),
16451
+ /** See {@link TrackProjectionSchema}. Default `full`. */
16452
+ projection: TrackProjectionSchema.optional()
16453
+ });
16454
+ var RecentTracksPageSchema = object({
16455
+ /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
16456
+ tracks: array(TrackSchema).readonly(),
16457
+ /** Cursor for the next page, or null when this page is the last. */
16458
+ nextCursor: string().nullable()
16459
+ });
16340
16460
  var KeyEventQueryInput = object({
16341
16461
  deviceId: number(),
16342
16462
  /** Window lower bound (track firstSeen ≥ since). */
@@ -16419,11 +16539,25 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
16419
16539
  deviceId: number(),
16420
16540
  since: number().optional(),
16421
16541
  until: number().optional(),
16422
- limit: number().optional()
16423
- }), array(TrackSchema).readonly()), method(object({ deviceId: number() }), _void(), {
16424
- kind: "mutation",
16425
- auth: "admin"
16426
- }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
16542
+ limit: number().optional(),
16543
+ /** Spatial filter only tracks whose trajectory intersects the zone
16544
+ * (normalized 0..1 rect or polygon). SQL-prefiltered on the persisted
16545
+ * envelope columns, then precisely tested per position. Tracks with
16546
+ * an unknown envelope (no frame dims at persist time) always match. */
16547
+ zone: TrackZoneFilterSchema.optional(),
16548
+ /** See {@link TrackProjectionSchema}. Default `full` (backward
16549
+ * compatible — omitting the field keeps today's exact behaviour). */
16550
+ projection: TrackProjectionSchema.optional()
16551
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
16552
+ kind: "mutation",
16553
+ auth: "admin"
16554
+ }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({
16555
+ deviceId: number(),
16556
+ since: number().optional(),
16557
+ until: number().optional(),
16558
+ kinds: array(string()).optional(),
16559
+ limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
16560
+ }), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
16427
16561
  deviceId: number(),
16428
16562
  since: number(),
16429
16563
  until: number(),
@@ -19717,7 +19851,12 @@ var RecordingStorageUsageSchema = object({
19717
19851
  /**
19718
19852
  * Result of locating footage at a wall-clock instant for one device/profile.
19719
19853
  * `segment` carries the covering segment's window; `gap` reports the forward
19720
- * nearest covered edge (`null` past the end of footage / when none exists).
19854
+ * nearest covered edge (`null` past the end of footage / when none exists)
19855
+ * and the backward covered edge `prevEndMs` (exclusive end of the nearest
19856
+ * footage behind the epoch; `null` when none — optional so older providers
19857
+ * that omit it stay valid). `prevEndMs` lets a backward frame-step hop the
19858
+ * small inter-segment cracks (durMs under-covers the span to the next
19859
+ * startMs by ~11-17 ms) instead of no-opping at a segment head.
19721
19860
  */
19722
19861
  var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
19723
19862
  kind: literal("segment"),
@@ -19726,7 +19865,8 @@ var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
19726
19865
  bytes: number()
19727
19866
  }), object({
19728
19867
  kind: literal("gap"),
19729
- nearestEdgeMs: number().nullable()
19868
+ nearestEdgeMs: number().nullable(),
19869
+ prevEndMs: number().nullable().optional()
19730
19870
  })]);
19731
19871
  /** Raw bytes of one finalized footage segment (read off disk on the recording node). */
19732
19872
  var ReadSegmentBytesResultSchema = object({ data: _instanceof(Uint8Array) });
@@ -21295,6 +21435,12 @@ Object.freeze({
21295
21435
  addonId: null,
21296
21436
  access: "view"
21297
21437
  },
21438
+ "deviceManager.getLinkedDevices": {
21439
+ capName: "device-manager",
21440
+ capScope: "system",
21441
+ addonId: null,
21442
+ access: "view"
21443
+ },
21298
21444
  "deviceManager.getRoleDisplayDefaults": {
21299
21445
  capName: "device-manager",
21300
21446
  capScope: "system",
@@ -22849,6 +22995,12 @@ Object.freeze({
22849
22995
  addonId: null,
22850
22996
  access: "view"
22851
22997
  },
22998
+ "pipelineAnalytics.getSensorEvents": {
22999
+ capName: "pipeline-analytics",
23000
+ capScope: "device",
23001
+ addonId: null,
23002
+ access: "view"
23003
+ },
22852
23004
  "pipelineAnalytics.getTrack": {
22853
23005
  capName: "pipeline-analytics",
22854
23006
  capScope: "device",
@@ -22861,6 +23013,18 @@ Object.freeze({
22861
23013
  addonId: null,
22862
23014
  access: "view"
22863
23015
  },
23016
+ "pipelineAnalytics.listEventKinds": {
23017
+ capName: "pipeline-analytics",
23018
+ capScope: "device",
23019
+ addonId: null,
23020
+ access: "view"
23021
+ },
23022
+ "pipelineAnalytics.listRecentTracks": {
23023
+ capName: "pipeline-analytics",
23024
+ capScope: "device",
23025
+ addonId: null,
23026
+ access: "view"
23027
+ },
22864
23028
  "pipelineAnalytics.listTracks": {
22865
23029
  capName: "pipeline-analytics",
22866
23030
  capScope: "device",
package/dist/addon.mjs CHANGED
@@ -3,7 +3,7 @@ import { createRequire } from "node:module";
3
3
  var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
4
4
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
5
5
  //#endregion
6
- //#region ../types/dist/event-category-CFZs3jI4.mjs
6
+ //#region ../types/dist/event-category-H4AVePnn.mjs
7
7
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
8
8
  EventCategory["SystemBoot"] = "system.boot";
9
9
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -153,6 +153,9 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
153
153
  EventCategory["RecordingSegmentWritten"] = "recording.segment.written";
154
154
  EventCategory["RecordingPolicyFallback"] = "recording.policy.fallback";
155
155
  EventCategory["RecordingRetentionCompleted"] = "recording.retention.completed";
156
+ /** Runner-sampled scrub thumbnail (~1/5 s/camera). Telemetry (D8): a lost
157
+ * thumb is a scrub gap the recorder's keyframe backfill covers. */
158
+ EventCategory["RecordingThumbSampled"] = "recording.thumb-sampled";
156
159
  EventCategory["DetectionEvent"] = "detection.event";
157
160
  EventCategory["SessionTrackNew"] = "session.track.new";
158
161
  EventCategory["SessionTrackExpired"] = "session.track.expired";
@@ -9999,7 +10002,7 @@ object({
9999
10002
  deviceId: number(),
10000
10003
  timestamp: number()
10001
10004
  });
10002
- DeviceType.Button;
10005
+ DeviceType.Button, DeviceType.Camera;
10003
10006
  /**
10004
10007
  * Enum-state sensor — a string value picked from a finite option set.
10005
10008
  * Drives HA `sensor` entries with `state_class: enum` (HVAC action
@@ -14663,6 +14666,14 @@ var ConfigEntrySchema = object({
14663
14666
  value: unknown(),
14664
14667
  description: string().optional()
14665
14668
  });
14669
+ var DeviceLinkModeSchema = _enum(["auto", "manual"]);
14670
+ /** One resolved linked device — the compact projection consumers need. */
14671
+ var LinkedDeviceSchema = object({
14672
+ deviceId: number(),
14673
+ name: string(),
14674
+ location: string().nullable(),
14675
+ features: array(string())
14676
+ });
14666
14677
  var SavedDeviceRowSchema = object({
14667
14678
  /** Numeric id reserved at allocateDeviceId time. */
14668
14679
  id: number(),
@@ -14884,7 +14895,10 @@ method(object({
14884
14895
  }), _void(), {
14885
14896
  kind: "mutation",
14886
14897
  auth: "admin"
14887
- }), method(object({ addonId: string() }), array(SavedDeviceRowSchema)), method(object({ addonId: string().optional() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
14898
+ }), method(object({ addonId: string() }), array(SavedDeviceRowSchema)), method(object({ addonId: string().optional() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), object({
14899
+ mode: DeviceLinkModeSchema,
14900
+ devices: array(LinkedDeviceSchema)
14901
+ })), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
14888
14902
  deviceId: number(),
14889
14903
  values: record(string(), unknown())
14890
14904
  }), object({ success: literal(true) }), {
@@ -16153,6 +16167,61 @@ var EventKindSchema = _enum([
16153
16167
  "object",
16154
16168
  "audio"
16155
16169
  ]);
16170
+ /**
16171
+ * Spatial filter for `listTracks` — the rect + polygon variants of the shared
16172
+ * MaskShape vocabulary (see `mask-shape.ts`). Coordinates are NORMALIZED 0..1
16173
+ * of the camera frame (top-left origin), matching the drawing-plane editor.
16174
+ */
16175
+ var TrackZoneFilterSchema = discriminatedUnion("kind", [MaskRectShapeSchema, MaskPolygonShapeSchema]);
16176
+ /** Closed icon vocabulary so clients render a known glyph per kind. */
16177
+ var EventKindIconSchema = _enum([
16178
+ "motion",
16179
+ "audio",
16180
+ "person",
16181
+ "vehicle",
16182
+ "animal",
16183
+ "door",
16184
+ "pir",
16185
+ "smoke",
16186
+ "water",
16187
+ "button",
16188
+ "generic"
16189
+ ]);
16190
+ var EventKindCategorySchema = _enum([
16191
+ "motion",
16192
+ "audio",
16193
+ "detection",
16194
+ "sensor",
16195
+ "custom"
16196
+ ]);
16197
+ var EventKindDescriptorSchema = object({
16198
+ /** Stable kind id (e.g. 'motion', 'person', 'contact'). */
16199
+ kind: string(),
16200
+ label: string(),
16201
+ /** Hex color for timeline/legend rendering. */
16202
+ color: string(),
16203
+ icon: EventKindIconSchema,
16204
+ category: EventKindCategorySchema,
16205
+ /** Which cap + device contributes this kind. For built-ins the camera
16206
+ * itself; for sensor kinds the LINKED source device. */
16207
+ source: object({
16208
+ capName: string(),
16209
+ deviceId: number()
16210
+ })
16211
+ });
16212
+ var SensorEventSchema = object({
16213
+ id: string(),
16214
+ /** The CAMERA the event is attributed to (a sensor linked to N cameras
16215
+ * yields N rows, one per camera). */
16216
+ deviceId: number(),
16217
+ /** The linked sensor device whose state changed. */
16218
+ sourceDeviceId: number(),
16219
+ /** Event kind id — matches an `EventKindDescriptor.kind`. */
16220
+ kind: string(),
16221
+ /** Snapshot of the sensor cap's runtime-state slice at the change. */
16222
+ value: record(string(), unknown()).nullable(),
16223
+ timestamp: number()
16224
+ });
16156
16225
  var TrackPositionSchema = object({
16157
16226
  x: number(),
16158
16227
  y: number(),
@@ -16166,6 +16235,30 @@ var TrackSnapshotSchema = object({
16166
16235
  mediaKey: string()
16167
16236
  });
16168
16237
  /**
16238
+ * Normalized 0..1 trajectory envelope (min/max over every position bbox,
16239
+ * divided by the track's detection-frame dims), computed at persist time.
16240
+ * Absent when the frame dims were unknown when the track was persisted
16241
+ * (legacy rows / dims-less sources) and on active (in-RAM) tracks.
16242
+ */
16243
+ var TrackEnvelopeSchema = object({
16244
+ minX: number(),
16245
+ minY: number(),
16246
+ maxX: number(),
16247
+ maxY: number()
16248
+ });
16249
+ /**
16250
+ * Row projection for track list queries. `full` (default) returns the
16251
+ * complete Track including the frame-rate `positions[]` history and the
16252
+ * `snapshots[]` references — megabytes across a page of tracks. `slim`
16253
+ * keeps every scalar the list surfaces actually render (ids, class(es),
16254
+ * label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
16255
+ * zonesVisited, bestEventId, envelope) and returns `positions` /
16256
+ * `snapshots` as EMPTY arrays — detail views re-fetch the full row via
16257
+ * `getTrack`. Mirrors the event-store `projection` convention
16258
+ * (`getObjectEvents` et al.).
16259
+ */
16260
+ var TrackProjectionSchema = _enum(["full", "slim"]);
16261
+ /**
16169
16262
  * One audio-classification label heard on the track's camera while the
16170
16263
  * track was alive, aggregated per label. An "episode" is one persisted
16171
16264
  * audio event (the confident-classification path: score ≥ the device's
@@ -16216,7 +16309,11 @@ var TrackSchema = object({
16216
16309
  /** Audio-classification labels heard on the camera during the track's
16217
16310
  * life (score ≥ device `classificationMinScore`), aggregated per label.
16218
16311
  * Absent on legacy rows / tracks with no confident audio. */
16219
- audioLabels: array(TrackAudioLabelSchema).readonly().optional()
16312
+ audioLabels: array(TrackAudioLabelSchema).readonly().optional(),
16313
+ /** Normalized 0..1 trajectory envelope (see {@link TrackEnvelopeSchema}).
16314
+ * Populated from the persisted envelope columns on historical reads;
16315
+ * absent on legacy rows, dims-less tracks and active (in-RAM) tracks. */
16316
+ envelope: TrackEnvelopeSchema.optional()
16220
16317
  });
16221
16318
  var BaseEventFields = {
16222
16319
  id: string(),
@@ -16326,11 +16423,13 @@ var MediaFileSchema = object({
16326
16423
  sizeBytes: number(),
16327
16424
  timestamp: number()
16328
16425
  });
16426
+ var DEFAULT_EVENT_QUERY_LIMIT = 1e3;
16427
+ var MAX_EVENT_QUERY_LIMIT = 5e3;
16329
16428
  var DeviceEventQueryInput = object({
16330
16429
  deviceId: number(),
16331
16430
  since: number().optional(),
16332
16431
  until: number().optional(),
16333
- limit: number().int().min(1).max(5e3).default(1e3),
16432
+ limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT),
16334
16433
  /** `slim` drops heavy JSON fields (regions/bbox/zones) and carries an
16335
16434
  * optional `mediaUrl` (populated by B5). `full` (default) keeps today's
16336
16435
  * exact behaviour. Callers may omit this field — the store defaults to
@@ -16338,6 +16437,27 @@ var DeviceEventQueryInput = object({
16338
16437
  projection: _enum(["full", "slim"]).optional()
16339
16438
  });
16340
16439
  var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string().optional() });
16440
+ var RecentTracksQueryInput = object({
16441
+ /** Devices to merge. An empty array yields `{ tracks: [], nextCursor: null }`. */
16442
+ deviceIds: array(number()),
16443
+ /** Window lower bound on `lastSeen` (inclusive). */
16444
+ since: number().optional(),
16445
+ /** Window upper bound on `lastSeen` (inclusive). */
16446
+ until: number().optional(),
16447
+ /** Page size. Default 200, max 1000. */
16448
+ limit: number().int().min(1).max(1e3).default(200),
16449
+ /** Opaque continuation cursor from a previous page's `nextCursor`.
16450
+ * Encodes the (lastSeen, trackId) sort position — treat as opaque. */
16451
+ cursor: string().optional(),
16452
+ /** See {@link TrackProjectionSchema}. Default `full`. */
16453
+ projection: TrackProjectionSchema.optional()
16454
+ });
16455
+ var RecentTracksPageSchema = object({
16456
+ /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
16457
+ tracks: array(TrackSchema).readonly(),
16458
+ /** Cursor for the next page, or null when this page is the last. */
16459
+ nextCursor: string().nullable()
16460
+ });
16341
16461
  var KeyEventQueryInput = object({
16342
16462
  deviceId: number(),
16343
16463
  /** Window lower bound (track firstSeen ≥ since). */
@@ -16420,11 +16540,25 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
16420
16540
  deviceId: number(),
16421
16541
  since: number().optional(),
16422
16542
  until: number().optional(),
16423
- limit: number().optional()
16424
- }), array(TrackSchema).readonly()), method(object({ deviceId: number() }), _void(), {
16425
- kind: "mutation",
16426
- auth: "admin"
16427
- }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
16543
+ limit: number().optional(),
16544
+ /** Spatial filter only tracks whose trajectory intersects the zone
16545
+ * (normalized 0..1 rect or polygon). SQL-prefiltered on the persisted
16546
+ * envelope columns, then precisely tested per position. Tracks with
16547
+ * an unknown envelope (no frame dims at persist time) always match. */
16548
+ zone: TrackZoneFilterSchema.optional(),
16549
+ /** See {@link TrackProjectionSchema}. Default `full` (backward
16550
+ * compatible — omitting the field keeps today's exact behaviour). */
16551
+ projection: TrackProjectionSchema.optional()
16552
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
16553
+ kind: "mutation",
16554
+ auth: "admin"
16555
+ }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({
16556
+ deviceId: number(),
16557
+ since: number().optional(),
16558
+ until: number().optional(),
16559
+ kinds: array(string()).optional(),
16560
+ limit: number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT)
16561
+ }), array(SensorEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
16428
16562
  deviceId: number(),
16429
16563
  since: number(),
16430
16564
  until: number(),
@@ -19718,7 +19852,12 @@ var RecordingStorageUsageSchema = object({
19718
19852
  /**
19719
19853
  * Result of locating footage at a wall-clock instant for one device/profile.
19720
19854
  * `segment` carries the covering segment's window; `gap` reports the forward
19721
- * nearest covered edge (`null` past the end of footage / when none exists).
19855
+ * nearest covered edge (`null` past the end of footage / when none exists)
19856
+ * and the backward covered edge `prevEndMs` (exclusive end of the nearest
19857
+ * footage behind the epoch; `null` when none — optional so older providers
19858
+ * that omit it stay valid). `prevEndMs` lets a backward frame-step hop the
19859
+ * small inter-segment cracks (durMs under-covers the span to the next
19860
+ * startMs by ~11-17 ms) instead of no-opping at a segment head.
19722
19861
  */
19723
19862
  var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
19724
19863
  kind: literal("segment"),
@@ -19727,7 +19866,8 @@ var LocateSegmentResultSchema = discriminatedUnion("kind", [object({
19727
19866
  bytes: number()
19728
19867
  }), object({
19729
19868
  kind: literal("gap"),
19730
- nearestEdgeMs: number().nullable()
19869
+ nearestEdgeMs: number().nullable(),
19870
+ prevEndMs: number().nullable().optional()
19731
19871
  })]);
19732
19872
  /** Raw bytes of one finalized footage segment (read off disk on the recording node). */
19733
19873
  var ReadSegmentBytesResultSchema = object({ data: _instanceof(Uint8Array) });
@@ -21296,6 +21436,12 @@ Object.freeze({
21296
21436
  addonId: null,
21297
21437
  access: "view"
21298
21438
  },
21439
+ "deviceManager.getLinkedDevices": {
21440
+ capName: "device-manager",
21441
+ capScope: "system",
21442
+ addonId: null,
21443
+ access: "view"
21444
+ },
21299
21445
  "deviceManager.getRoleDisplayDefaults": {
21300
21446
  capName: "device-manager",
21301
21447
  capScope: "system",
@@ -22850,6 +22996,12 @@ Object.freeze({
22850
22996
  addonId: null,
22851
22997
  access: "view"
22852
22998
  },
22999
+ "pipelineAnalytics.getSensorEvents": {
23000
+ capName: "pipeline-analytics",
23001
+ capScope: "device",
23002
+ addonId: null,
23003
+ access: "view"
23004
+ },
22853
23005
  "pipelineAnalytics.getTrack": {
22854
23006
  capName: "pipeline-analytics",
22855
23007
  capScope: "device",
@@ -22862,6 +23014,18 @@ Object.freeze({
22862
23014
  addonId: null,
22863
23015
  access: "view"
22864
23016
  },
23017
+ "pipelineAnalytics.listEventKinds": {
23018
+ capName: "pipeline-analytics",
23019
+ capScope: "device",
23020
+ addonId: null,
23021
+ access: "view"
23022
+ },
23023
+ "pipelineAnalytics.listRecentTracks": {
23024
+ capName: "pipeline-analytics",
23025
+ capScope: "device",
23026
+ addonId: null,
23027
+ access: "view"
23028
+ },
22865
23029
  "pipelineAnalytics.listTracks": {
22866
23030
  capName: "pipeline-analytics",
22867
23031
  capScope: "device",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-onvif",
3
- "version": "1.1.25",
3
+ "version": "1.1.26",
4
4
  "description": "ONVIF camera device provider addon for CamStack",
5
5
  "keywords": [
6
6
  "camstack",