@camstack/addon-provider-rtsp 1.2.57 → 1.2.59

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/addon.js CHANGED
@@ -10583,6 +10583,89 @@ var LocationStatSchema = object({
10583
10583
  fileCount: number(),
10584
10584
  present: boolean()
10585
10585
  });
10586
+ /** Lifecycle of a backup run. Terminal states: succeeded / failed / cancelled. */
10587
+ var BackupRunStateSchema = _enum([
10588
+ "queued",
10589
+ "running",
10590
+ "succeeded",
10591
+ "failed",
10592
+ "cancelled"
10593
+ ]);
10594
+ /**
10595
+ * Where a running backup currently is. `queued` before it starts,
10596
+ * `building` while the tar.gz is being staged, `uploading` during the
10597
+ * per-destination fan-out, `done` once terminal.
10598
+ */
10599
+ var BackupRunPhaseSchema = _enum([
10600
+ "queued",
10601
+ "building",
10602
+ "uploading",
10603
+ "done"
10604
+ ]);
10605
+ /**
10606
+ * Observable state of one backup run — readable WHILE it runs via
10607
+ * `backup.listRuns`. This is what makes the execution queue and
10608
+ * `backup.cancel` usable: the 2026-09-04 incident (two concurrent
10609
+ * multi-GB builds, staging 5.1 GB → 18 GB, load 62) was only
10610
+ * diagnosable with `du` because nothing reported that runs existed or
10611
+ * how large the staged archive had grown.
10612
+ */
10613
+ var BackupRunSchema = object({
10614
+ /** Stable run id — the handle `backup.cancel` takes. */
10615
+ id: string(),
10616
+ state: BackupRunStateSchema,
10617
+ phase: BackupRunPhaseSchema,
10618
+ /**
10619
+ * Resolved destination location ids. Empty while queued (targets are
10620
+ * resolved when the run starts, against the then-current policies).
10621
+ */
10622
+ destinationIds: array(string()).readonly(),
10623
+ label: string().optional(),
10624
+ /** ms-epoch when the run was submitted (trigger call / schedule fire). */
10625
+ requestedAt: number(),
10626
+ /** ms-epoch when the run left the queue and started building. */
10627
+ startedAt: number().optional(),
10628
+ /** ms-epoch when the run reached a terminal state. */
10629
+ finishedAt: number().optional(),
10630
+ /** Compressed bytes of the staging archive written so far. */
10631
+ stagedBytes: number(),
10632
+ /** Final staged archive size, once the build phase completes. */
10633
+ archiveSizeBytes: number().optional(),
10634
+ /** Bytes pushed to the destination currently uploading. */
10635
+ uploadedBytes: number(),
10636
+ /** Destinations where the archive fully landed (uploaded + indexed). */
10637
+ completedDestinationIds: array(string()).readonly(),
10638
+ /** Destinations that failed during the fan-out. */
10639
+ failedDestinationIds: array(string()).readonly(),
10640
+ /** Failure message when `state === 'failed'`. */
10641
+ error: string().optional(),
10642
+ /**
10643
+ * 1-based place in the execution queue — 1 = runs next. Present only
10644
+ * while `state === 'queued'`. Stamped by the orchestrator from the
10645
+ * queue's OWN pending order, never derived from timestamps, so the
10646
+ * UI cannot show an order the executor will not honour.
10647
+ */
10648
+ queuePosition: number().int().min(1).optional()
10649
+ });
10650
+ /**
10651
+ * Result of `backup.trigger`. The call still resolves when the run
10652
+ * terminates (compat with schedule-driven runs and the admin UI), but
10653
+ * it now names the run and says whether it had to WAIT: a trigger that
10654
+ * arrives while another run is in flight is enqueued (or joined onto
10655
+ * an identical already-queued run), never started concurrently.
10656
+ */
10657
+ var BackupTriggerResultSchema = object({
10658
+ /** The run this trigger mapped to — poll it via `listRuns`, stop it via `cancel`. */
10659
+ runId: string(),
10660
+ /** True when the run waited behind an in-flight run instead of starting immediately. */
10661
+ queued: boolean(),
10662
+ /** True when this trigger was coalesced onto an identical already-queued run. */
10663
+ joined: boolean(),
10664
+ /** True when the run was cancelled before completing every destination. */
10665
+ cancelled: boolean(),
10666
+ /** One entry per destination the archive landed at (partial on cancel). */
10667
+ entries: array(BackupEntrySchema).readonly()
10668
+ });
10586
10669
  /**
10587
10670
  * A backup schedule — the N:M "entry" that binds one cron cadence to a
10588
10671
  * SET of destination locations. Supersedes the per-location cron on
@@ -10630,7 +10713,10 @@ method(_void(), array(BackupDestinationInfoSchema).readonly(), { auth: "admin" }
10630
10713
  * retention (manual runs).
10631
10714
  */
10632
10715
  retentionCount: number().int().min(1).max(1e3).optional()
10633
- }).optional(), array(BackupEntrySchema).readonly(), {
10716
+ }).optional(), BackupTriggerResultSchema, {
10717
+ kind: "mutation",
10718
+ auth: "admin"
10719
+ }), method(_void(), array(BackupRunSchema).readonly(), { auth: "admin" }), method(object({ runId: string() }), object({ cancelled: boolean() }), {
10634
10720
  kind: "mutation",
10635
10721
  auth: "admin"
10636
10722
  }), method(_void(), array(BackupEntrySchema).readonly(), { auth: "admin" }), method(_void(), array(LocationStatSchema).readonly(), { auth: "admin" }), method(object({
@@ -11347,6 +11433,14 @@ method(object({
11347
11433
  }), object({ success: literal(true) }), {
11348
11434
  kind: "mutation",
11349
11435
  auth: "admin"
11436
+ }), method(object({ deviceId: number().int().nonnegative() }), object({
11437
+ derivedStreamsDeleted: array(string()).readonly(),
11438
+ assignmentsPurged: boolean(),
11439
+ probeSnapshotsDropped: number().int().nonnegative(),
11440
+ rtspTokenRowsDeleted: number().int().nonnegative()
11441
+ }), {
11442
+ kind: "mutation",
11443
+ auth: "admin"
11350
11444
  }), method(object({
11351
11445
  deviceId: number(),
11352
11446
  /** Absent = the LOWEST assigned profile — a notification attachment is
@@ -19239,7 +19333,20 @@ var RecentTracksQueryInput = object({
19239
19333
  projection: TrackProjectionSchema.optional(),
19240
19334
  /** Include stationary-promoted rows (parked objects). Default false: the
19241
19335
  * feed lists passages; parking records live on the stationary registry. */
19242
- includeStationary: boolean().optional()
19336
+ includeStationary: boolean().optional(),
19337
+ /**
19338
+ * Restrict to these track classes. ABSENT or EMPTY means no filter.
19339
+ *
19340
+ * The same filter `listTracks` takes, because the timeline's class chips must
19341
+ * mean the same thing whether the scope is one camera or twelve. Until this
19342
+ * existed the scoped feed downloaded a page and narrowed it on the phone
19343
+ * while the single-camera path narrowed the read — one filter, two costs.
19344
+ *
19345
+ * A SUPERSET prefilter on `classes[]`, like its single-camera twin: rows
19346
+ * whose class list is unreadable are kept, and the client's rule stays the
19347
+ * exact one.
19348
+ */
19349
+ classes: array(string()).optional()
19243
19350
  });
19244
19351
  var RecentTracksPageSchema = object({
19245
19352
  /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
@@ -23513,8 +23620,22 @@ var automationControlCapability = {
23513
23620
  * threshold.
23514
23621
  */
23515
23622
  var BatteryStatusSchema = object({
23516
- /** 0..100 inclusive. Firmware-reported. */
23517
- percentage: number().min(0).max(100),
23623
+ /**
23624
+ * 0..100 inclusive, firmware-reported. **`null` means NOT YET KNOWN** — the
23625
+ * provider has registered the capability but no reading has landed.
23626
+ *
23627
+ * It is nullable because it was not, and the only value a provider could
23628
+ * seed with was `0`. A battery camera behind an NVR therefore announced
23629
+ * itself at 0% on every start and corrected itself a moment later, which is
23630
+ * indistinguishable from a real flat battery: it fires the low-battery alert
23631
+ * every time the hub restarts. Unknown is not empty (D315), and on a battery
23632
+ * reading the difference is an alarm.
23633
+ *
23634
+ * `vacuum-control` and `lawn-mower-control` already model it this way.
23635
+ * Consumers must SKIP a null rather than coerce it — `battery-band` already
23636
+ * declines to band a non-finite reading, which is the correct shape.
23637
+ */
23638
+ percentage: number().min(0).max(100).nullable(),
23518
23639
  /**
23519
23640
  * Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
23520
23641
  * Reolink-specific for the Solar Panel 2 accessory (will become
@@ -33349,6 +33470,12 @@ Object.freeze({
33349
33470
  addonId: null,
33350
33471
  access: "create"
33351
33472
  },
33473
+ "backup.cancel": {
33474
+ capName: "backup",
33475
+ capScope: "system",
33476
+ addonId: null,
33477
+ access: "create"
33478
+ },
33352
33479
  "backup.delete": {
33353
33480
  capName: "backup",
33354
33481
  capScope: "system",
@@ -33391,6 +33518,12 @@ Object.freeze({
33391
33518
  addonId: null,
33392
33519
  access: "view"
33393
33520
  },
33521
+ "backup.listRuns": {
33522
+ capName: "backup",
33523
+ capScope: "system",
33524
+ addonId: null,
33525
+ access: "view"
33526
+ },
33394
33527
  "backup.listSchedules": {
33395
33528
  capName: "backup",
33396
33529
  capScope: "system",
@@ -37957,6 +38090,12 @@ Object.freeze({
37957
38090
  addonId: null,
37958
38091
  access: "create"
37959
38092
  },
38093
+ "streamBroker.forgetDeviceHardware": {
38094
+ capName: "stream-broker",
38095
+ capScope: "system",
38096
+ addonId: null,
38097
+ access: "delete"
38098
+ },
37960
38099
  "streamBroker.getAllRtspEntries": {
37961
38100
  capName: "stream-broker",
37962
38101
  capScope: "system",
@@ -40415,6 +40554,11 @@ Object.freeze({
40415
40554
  form: "single",
40416
40555
  optional: false
40417
40556
  }],
40557
+ "streamBroker.forgetDeviceHardware": [{
40558
+ name: "deviceId",
40559
+ form: "single",
40560
+ optional: false
40561
+ }],
40418
40562
  "streamBroker.getDeviceAudioMute": [{
40419
40563
  name: "deviceId",
40420
40564
  form: "single",
package/dist/addon.mjs CHANGED
@@ -10559,6 +10559,89 @@ var LocationStatSchema = object({
10559
10559
  fileCount: number(),
10560
10560
  present: boolean()
10561
10561
  });
10562
+ /** Lifecycle of a backup run. Terminal states: succeeded / failed / cancelled. */
10563
+ var BackupRunStateSchema = _enum([
10564
+ "queued",
10565
+ "running",
10566
+ "succeeded",
10567
+ "failed",
10568
+ "cancelled"
10569
+ ]);
10570
+ /**
10571
+ * Where a running backup currently is. `queued` before it starts,
10572
+ * `building` while the tar.gz is being staged, `uploading` during the
10573
+ * per-destination fan-out, `done` once terminal.
10574
+ */
10575
+ var BackupRunPhaseSchema = _enum([
10576
+ "queued",
10577
+ "building",
10578
+ "uploading",
10579
+ "done"
10580
+ ]);
10581
+ /**
10582
+ * Observable state of one backup run — readable WHILE it runs via
10583
+ * `backup.listRuns`. This is what makes the execution queue and
10584
+ * `backup.cancel` usable: the 2026-09-04 incident (two concurrent
10585
+ * multi-GB builds, staging 5.1 GB → 18 GB, load 62) was only
10586
+ * diagnosable with `du` because nothing reported that runs existed or
10587
+ * how large the staged archive had grown.
10588
+ */
10589
+ var BackupRunSchema = object({
10590
+ /** Stable run id — the handle `backup.cancel` takes. */
10591
+ id: string(),
10592
+ state: BackupRunStateSchema,
10593
+ phase: BackupRunPhaseSchema,
10594
+ /**
10595
+ * Resolved destination location ids. Empty while queued (targets are
10596
+ * resolved when the run starts, against the then-current policies).
10597
+ */
10598
+ destinationIds: array(string()).readonly(),
10599
+ label: string().optional(),
10600
+ /** ms-epoch when the run was submitted (trigger call / schedule fire). */
10601
+ requestedAt: number(),
10602
+ /** ms-epoch when the run left the queue and started building. */
10603
+ startedAt: number().optional(),
10604
+ /** ms-epoch when the run reached a terminal state. */
10605
+ finishedAt: number().optional(),
10606
+ /** Compressed bytes of the staging archive written so far. */
10607
+ stagedBytes: number(),
10608
+ /** Final staged archive size, once the build phase completes. */
10609
+ archiveSizeBytes: number().optional(),
10610
+ /** Bytes pushed to the destination currently uploading. */
10611
+ uploadedBytes: number(),
10612
+ /** Destinations where the archive fully landed (uploaded + indexed). */
10613
+ completedDestinationIds: array(string()).readonly(),
10614
+ /** Destinations that failed during the fan-out. */
10615
+ failedDestinationIds: array(string()).readonly(),
10616
+ /** Failure message when `state === 'failed'`. */
10617
+ error: string().optional(),
10618
+ /**
10619
+ * 1-based place in the execution queue — 1 = runs next. Present only
10620
+ * while `state === 'queued'`. Stamped by the orchestrator from the
10621
+ * queue's OWN pending order, never derived from timestamps, so the
10622
+ * UI cannot show an order the executor will not honour.
10623
+ */
10624
+ queuePosition: number().int().min(1).optional()
10625
+ });
10626
+ /**
10627
+ * Result of `backup.trigger`. The call still resolves when the run
10628
+ * terminates (compat with schedule-driven runs and the admin UI), but
10629
+ * it now names the run and says whether it had to WAIT: a trigger that
10630
+ * arrives while another run is in flight is enqueued (or joined onto
10631
+ * an identical already-queued run), never started concurrently.
10632
+ */
10633
+ var BackupTriggerResultSchema = object({
10634
+ /** The run this trigger mapped to — poll it via `listRuns`, stop it via `cancel`. */
10635
+ runId: string(),
10636
+ /** True when the run waited behind an in-flight run instead of starting immediately. */
10637
+ queued: boolean(),
10638
+ /** True when this trigger was coalesced onto an identical already-queued run. */
10639
+ joined: boolean(),
10640
+ /** True when the run was cancelled before completing every destination. */
10641
+ cancelled: boolean(),
10642
+ /** One entry per destination the archive landed at (partial on cancel). */
10643
+ entries: array(BackupEntrySchema).readonly()
10644
+ });
10562
10645
  /**
10563
10646
  * A backup schedule — the N:M "entry" that binds one cron cadence to a
10564
10647
  * SET of destination locations. Supersedes the per-location cron on
@@ -10606,7 +10689,10 @@ method(_void(), array(BackupDestinationInfoSchema).readonly(), { auth: "admin" }
10606
10689
  * retention (manual runs).
10607
10690
  */
10608
10691
  retentionCount: number().int().min(1).max(1e3).optional()
10609
- }).optional(), array(BackupEntrySchema).readonly(), {
10692
+ }).optional(), BackupTriggerResultSchema, {
10693
+ kind: "mutation",
10694
+ auth: "admin"
10695
+ }), method(_void(), array(BackupRunSchema).readonly(), { auth: "admin" }), method(object({ runId: string() }), object({ cancelled: boolean() }), {
10610
10696
  kind: "mutation",
10611
10697
  auth: "admin"
10612
10698
  }), method(_void(), array(BackupEntrySchema).readonly(), { auth: "admin" }), method(_void(), array(LocationStatSchema).readonly(), { auth: "admin" }), method(object({
@@ -11323,6 +11409,14 @@ method(object({
11323
11409
  }), object({ success: literal(true) }), {
11324
11410
  kind: "mutation",
11325
11411
  auth: "admin"
11412
+ }), method(object({ deviceId: number().int().nonnegative() }), object({
11413
+ derivedStreamsDeleted: array(string()).readonly(),
11414
+ assignmentsPurged: boolean(),
11415
+ probeSnapshotsDropped: number().int().nonnegative(),
11416
+ rtspTokenRowsDeleted: number().int().nonnegative()
11417
+ }), {
11418
+ kind: "mutation",
11419
+ auth: "admin"
11326
11420
  }), method(object({
11327
11421
  deviceId: number(),
11328
11422
  /** Absent = the LOWEST assigned profile — a notification attachment is
@@ -19215,7 +19309,20 @@ var RecentTracksQueryInput = object({
19215
19309
  projection: TrackProjectionSchema.optional(),
19216
19310
  /** Include stationary-promoted rows (parked objects). Default false: the
19217
19311
  * feed lists passages; parking records live on the stationary registry. */
19218
- includeStationary: boolean().optional()
19312
+ includeStationary: boolean().optional(),
19313
+ /**
19314
+ * Restrict to these track classes. ABSENT or EMPTY means no filter.
19315
+ *
19316
+ * The same filter `listTracks` takes, because the timeline's class chips must
19317
+ * mean the same thing whether the scope is one camera or twelve. Until this
19318
+ * existed the scoped feed downloaded a page and narrowed it on the phone
19319
+ * while the single-camera path narrowed the read — one filter, two costs.
19320
+ *
19321
+ * A SUPERSET prefilter on `classes[]`, like its single-camera twin: rows
19322
+ * whose class list is unreadable are kept, and the client's rule stays the
19323
+ * exact one.
19324
+ */
19325
+ classes: array(string()).optional()
19219
19326
  });
19220
19327
  var RecentTracksPageSchema = object({
19221
19328
  /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
@@ -23489,8 +23596,22 @@ var automationControlCapability = {
23489
23596
  * threshold.
23490
23597
  */
23491
23598
  var BatteryStatusSchema = object({
23492
- /** 0..100 inclusive. Firmware-reported. */
23493
- percentage: number().min(0).max(100),
23599
+ /**
23600
+ * 0..100 inclusive, firmware-reported. **`null` means NOT YET KNOWN** — the
23601
+ * provider has registered the capability but no reading has landed.
23602
+ *
23603
+ * It is nullable because it was not, and the only value a provider could
23604
+ * seed with was `0`. A battery camera behind an NVR therefore announced
23605
+ * itself at 0% on every start and corrected itself a moment later, which is
23606
+ * indistinguishable from a real flat battery: it fires the low-battery alert
23607
+ * every time the hub restarts. Unknown is not empty (D315), and on a battery
23608
+ * reading the difference is an alarm.
23609
+ *
23610
+ * `vacuum-control` and `lawn-mower-control` already model it this way.
23611
+ * Consumers must SKIP a null rather than coerce it — `battery-band` already
23612
+ * declines to band a non-finite reading, which is the correct shape.
23613
+ */
23614
+ percentage: number().min(0).max(100).nullable(),
23494
23615
  /**
23495
23616
  * Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
23496
23617
  * Reolink-specific for the Solar Panel 2 accessory (will become
@@ -33325,6 +33446,12 @@ Object.freeze({
33325
33446
  addonId: null,
33326
33447
  access: "create"
33327
33448
  },
33449
+ "backup.cancel": {
33450
+ capName: "backup",
33451
+ capScope: "system",
33452
+ addonId: null,
33453
+ access: "create"
33454
+ },
33328
33455
  "backup.delete": {
33329
33456
  capName: "backup",
33330
33457
  capScope: "system",
@@ -33367,6 +33494,12 @@ Object.freeze({
33367
33494
  addonId: null,
33368
33495
  access: "view"
33369
33496
  },
33497
+ "backup.listRuns": {
33498
+ capName: "backup",
33499
+ capScope: "system",
33500
+ addonId: null,
33501
+ access: "view"
33502
+ },
33370
33503
  "backup.listSchedules": {
33371
33504
  capName: "backup",
33372
33505
  capScope: "system",
@@ -37933,6 +38066,12 @@ Object.freeze({
37933
38066
  addonId: null,
37934
38067
  access: "create"
37935
38068
  },
38069
+ "streamBroker.forgetDeviceHardware": {
38070
+ capName: "stream-broker",
38071
+ capScope: "system",
38072
+ addonId: null,
38073
+ access: "delete"
38074
+ },
37936
38075
  "streamBroker.getAllRtspEntries": {
37937
38076
  capName: "stream-broker",
37938
38077
  capScope: "system",
@@ -40391,6 +40530,11 @@ Object.freeze({
40391
40530
  form: "single",
40392
40531
  optional: false
40393
40532
  }],
40533
+ "streamBroker.forgetDeviceHardware": [{
40534
+ name: "deviceId",
40535
+ form: "single",
40536
+ optional: false
40537
+ }],
40394
40538
  "streamBroker.getDeviceAudioMute": [{
40395
40539
  name: "deviceId",
40396
40540
  form: "single",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-rtsp",
3
- "version": "1.2.57",
3
+ "version": "1.2.59",
4
4
  "description": "Generic RTSP camera device provider addon for CamStack",
5
5
  "keywords": [
6
6
  "camstack",