@camstack/addon-mqtt-broker 1.2.90 → 1.2.93
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/mqtt-broker.addon.js +242 -18
- package/dist/mqtt-broker.addon.mjs +242 -18
- package/package.json +1 -1
|
@@ -44,7 +44,7 @@ let crypto$10 = __toESM(crypto$1, 1);
|
|
|
44
44
|
crypto$1 = __toESM(crypto$1);
|
|
45
45
|
let node_fs = require("node:fs");
|
|
46
46
|
let node_path = require("node:path");
|
|
47
|
-
//#region ../types/dist/event-category-
|
|
47
|
+
//#region ../types/dist/event-category-DAXzJeTX.mjs
|
|
48
48
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
49
49
|
EventCategory["SystemBoot"] = "system.boot";
|
|
50
50
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -636,7 +636,6 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
636
636
|
* issue. Payload `PipelineAnalyticsPlateGalleryChangedPayload`.
|
|
637
637
|
*/
|
|
638
638
|
EventCategory["PipelineAnalyticsPlateGalleryChanged"] = "pipeline-analytics.plate-gallery-changed";
|
|
639
|
-
EventCategory["FrigateLiveEvent"] = "frigate.live-event";
|
|
640
639
|
EventCategory["CameraStreamsProfileSlotsChanged"] = "camera-streams.onProfileSlotsChanged";
|
|
641
640
|
/**
|
|
642
641
|
* Stream-broker health watchdog. Per-broker (deviceId/profile) emission.
|
|
@@ -12601,7 +12600,7 @@ DeviceType.Camera;
|
|
|
12601
12600
|
var SourceInfoSchema = object({
|
|
12602
12601
|
/** Live dispatch key — mutable when the source system allows rename. */
|
|
12603
12602
|
id: string(),
|
|
12604
|
-
/** Source system tag — e.g. 'homeassistant' | 'reolink' | '
|
|
12603
|
+
/** Source system tag — e.g. 'homeassistant' | 'reolink' | 'onvif'. */
|
|
12605
12604
|
system: string(),
|
|
12606
12605
|
/** Immutable upstream identifier when available (HA `unique_id`, … ).
|
|
12607
12606
|
* Used to detect rename when `id` changes. */
|
|
@@ -13088,7 +13087,7 @@ method(_void(), _void(), { kind: "mutation" }), method(_void(), _void(), { kind:
|
|
|
13088
13087
|
* - `device-management.router.ts` (deleted in Phase 2)
|
|
13089
13088
|
* - `device-ops.router.ts` (compat layer — deleted; device-provider ops absorbed here)
|
|
13090
13089
|
*
|
|
13091
|
-
* All device provider addons (rtsp, onvif,
|
|
13090
|
+
* All device provider addons (rtsp, onvif, …) are hub-local: they may
|
|
13092
13091
|
* fork into separate processes but never run on remote cluster agents. Therefore:
|
|
13093
13092
|
* - No nodeId routing needed — this is a pure hub singleton.
|
|
13094
13093
|
* - The hub's DeviceRegistry is the single source of truth for all live devices.
|
|
@@ -17117,7 +17116,7 @@ var NcRuleInputSchema = object({
|
|
|
17117
17116
|
* The measured seven-person arrival on device 590 spans 110 s with every
|
|
17118
17117
|
* internal gap under 30 s. A 12 s fixed window cuts it into three groups; an
|
|
17119
17118
|
* idle cutoff holds it as one and ends it when the arrival actually ends.
|
|
17120
|
-
* 30 is
|
|
17119
|
+
* 30 s is a widely shipped value for the same decision.
|
|
17121
17120
|
*
|
|
17122
17121
|
* ### What it replaces
|
|
17123
17122
|
*
|
|
@@ -19159,6 +19158,13 @@ var ZoneCrossingSchema = object({
|
|
|
19159
19158
|
/** Zone display name at crossing time (falls back to the id). */
|
|
19160
19159
|
zoneName: string().optional()
|
|
19161
19160
|
});
|
|
19161
|
+
/** One zone a box was stamped with, and how much of the BOX fell inside it. */
|
|
19162
|
+
var ZoneOverlapSchema = object({
|
|
19163
|
+
zoneId: string(),
|
|
19164
|
+
zoneName: string().optional(),
|
|
19165
|
+
/** Percentage of the BOX area inside the zone, 0–100. */
|
|
19166
|
+
overlapPct: number()
|
|
19167
|
+
});
|
|
19162
19168
|
var ObjectEventSchema = object({
|
|
19163
19169
|
...BaseEventFields,
|
|
19164
19170
|
kind: literal("object"),
|
|
@@ -19183,6 +19189,35 @@ var ObjectEventSchema = object({
|
|
|
19183
19189
|
bbox: BoundingBoxSchema.optional(),
|
|
19184
19190
|
/** Heavy JSON — omitted in slim projection. */
|
|
19185
19191
|
zones: array(string()).readonly().optional(),
|
|
19192
|
+
/**
|
|
19193
|
+
* How far inside each stamped zone the box actually was, as a percentage of
|
|
19194
|
+
* the BOX area.
|
|
19195
|
+
*
|
|
19196
|
+
* Membership alone cannot express "at least a third of it inside", which is
|
|
19197
|
+
* the bar an operator argues with — and the number already existed: the
|
|
19198
|
+
* engine computed it, the pipeline logged it, and then discarded it. It
|
|
19199
|
+
* matters most on the events that carry no track, where a rule has nothing
|
|
19200
|
+
* else to judge by.
|
|
19201
|
+
*/
|
|
19202
|
+
zoneOverlaps: array(ZoneOverlapSchema).readonly().optional(),
|
|
19203
|
+
/**
|
|
19204
|
+
* Present when this event describes a detection the TRACKER refused, so it
|
|
19205
|
+
* has no track and never will.
|
|
19206
|
+
*
|
|
19207
|
+
* A zone-scoped immediate rule asks "is there an animal in the flowerbed
|
|
19208
|
+
* NOW?"; tracking answers a different question ("is this the same subject as
|
|
19209
|
+
* before?") whose confirmation threshold presumes continuity. On 2026-09-09 a
|
|
19210
|
+
* dog at 0.7729, 100% inside a watched zone, was refused three times in six
|
|
19211
|
+
* seconds with three different candidate ids — seven analysed frames in the
|
|
19212
|
+
* window, the subject in a handful of them, metres apart — and produced no
|
|
19213
|
+
* event at all.
|
|
19214
|
+
*
|
|
19215
|
+
* It is NAMED rather than merely implied by a missing `trackId`: an event
|
|
19216
|
+
* with no track and no reason is indistinguishable from a track whose media
|
|
19217
|
+
* went missing, and a consumer that asks this one for a best shot or a
|
|
19218
|
+
* history is asking for something that never existed.
|
|
19219
|
+
*/
|
|
19220
|
+
spawnRefused: string().optional(),
|
|
19186
19221
|
/** Omitted in slim projection. */
|
|
19187
19222
|
state: TrackStateSchema.optional(),
|
|
19188
19223
|
/**
|
|
@@ -19609,7 +19644,17 @@ var EventDensityBucketSchema = object({
|
|
|
19609
19644
|
bucketStart: number(),
|
|
19610
19645
|
motion: number().int(),
|
|
19611
19646
|
object: number().int(),
|
|
19612
|
-
audio: number().int()
|
|
19647
|
+
audio: number().int(),
|
|
19648
|
+
/**
|
|
19649
|
+
* Energy-weighted mean dBFS of the audio events in this bucket — the LEVEL,
|
|
19650
|
+
* as opposed to `audio`, which is their COUNT (D431).
|
|
19651
|
+
*
|
|
19652
|
+
* ABSENT when the bucket holds no audio event. Absence means "nothing was
|
|
19653
|
+
* measured", which is not the same claim as silence, and a lane that cannot
|
|
19654
|
+
* tell them apart paints a quiet hour at full scale — which is exactly what
|
|
19655
|
+
* the count-on-a-level-meter did.
|
|
19656
|
+
*/
|
|
19657
|
+
audioDbfs: number().optional()
|
|
19613
19658
|
});
|
|
19614
19659
|
/**
|
|
19615
19660
|
* One camera's row in a `getEventDensityBatch` answer.
|
|
@@ -20256,6 +20301,60 @@ var NativeCropResultSchema = object({
|
|
|
20256
20301
|
*/
|
|
20257
20302
|
tier: _enum(["native", "ram-fullframe"]).optional()
|
|
20258
20303
|
});
|
|
20304
|
+
/**
|
|
20305
|
+
* What a PARKED frame is for — the `kind` half of the `(deviceId, trackId,
|
|
20306
|
+
* kind)` key ([D422](../../../docs/decisions/adr-0422-a-relevant-frame-is-parked-when-it-becomes-relevant.md)).
|
|
20307
|
+
*
|
|
20308
|
+
* - `keyFrame` — the track's clean best FULL frame at native width (capped by
|
|
20309
|
+
* the caller's `maxWidth`). What `keyFrame` + `keyFrameSmall` are written
|
|
20310
|
+
* from, and what the detail plane's full-frame rung cuts from.
|
|
20311
|
+
* - `thumbnail` — the best-shot subject slab: the caller's 16:9 central-square
|
|
20312
|
+
* window, cut by the runner at uncapped native resolution.
|
|
20313
|
+
*
|
|
20314
|
+
* The runner never interprets `trackId`; it is an opaque key the hub owns.
|
|
20315
|
+
*/
|
|
20316
|
+
var ParkedFrameKindSchema = _enum(["keyFrame", "thumbnail"]);
|
|
20317
|
+
/**
|
|
20318
|
+
* Why a park did NOT happen. Every one is logged on the runner with
|
|
20319
|
+
* `tags: { deviceId }` and the handle's measured age, because a handle already
|
|
20320
|
+
* gone at park time IS the defect the 150–500 ms window exists to prevent —
|
|
20321
|
+
* never a reason to retry in a loop.
|
|
20322
|
+
*
|
|
20323
|
+
* - `handle-gone` — the native surface no longer resolves this handle (never
|
|
20324
|
+
* registered, past the lease bound, or the worker released it). `detail`
|
|
20325
|
+
* carries the runner's own miss reason.
|
|
20326
|
+
* - `encode-failed` — pixels resolved and the JPEG encode threw.
|
|
20327
|
+
*/
|
|
20328
|
+
var ParkRefusalSchema = _enum(["handle-gone", "encode-failed"]);
|
|
20329
|
+
/** Answer to `parkTrackFrame` — a discriminated union, so "not parked" always names why. */
|
|
20330
|
+
var ParkTrackFrameResultSchema = discriminatedUnion("parked", [object({
|
|
20331
|
+
parked: literal(true),
|
|
20332
|
+
/** The node holding the parcel — what a later retrieval must be pinned to. */
|
|
20333
|
+
nodeId: string(),
|
|
20334
|
+
width: number().int().positive(),
|
|
20335
|
+
height: number().int().positive(),
|
|
20336
|
+
/** JPEG bytes the parcel costs on the node. */
|
|
20337
|
+
bytes: number().int().nonnegative(),
|
|
20338
|
+
/** Whether this park replaced a parcel already held for the key. */
|
|
20339
|
+
replaced: boolean()
|
|
20340
|
+
}), object({
|
|
20341
|
+
parked: literal(false),
|
|
20342
|
+
nodeId: string(),
|
|
20343
|
+
reason: ParkRefusalSchema,
|
|
20344
|
+
/** Age of the handle at the park, on the runner's clock; null if unknown. */
|
|
20345
|
+
handleAgeMs: number().nullable(),
|
|
20346
|
+
detail: string().optional()
|
|
20347
|
+
})]);
|
|
20348
|
+
/** A retrieved parcel — the runner's own JPEG, base64 for the wire. */
|
|
20349
|
+
var ParkedTrackFrameSchema = object({
|
|
20350
|
+
jpeg: string(),
|
|
20351
|
+
width: number().int().positive(),
|
|
20352
|
+
height: number().int().positive(),
|
|
20353
|
+
/** The frame instant the parcel shows (the caller's clock, echoed back). */
|
|
20354
|
+
timestamp: number(),
|
|
20355
|
+
/** When the node stored it (the node's clock). */
|
|
20356
|
+
parkedAt: number()
|
|
20357
|
+
});
|
|
20259
20358
|
/** Parent detection context passed to `runDetailSubtree` — the crop's
|
|
20260
20359
|
* originating detection, in FRAME-space coordinates. Reuses
|
|
20261
20360
|
* `NativeCropBboxSchema`'s `{x,y,w,h}` shape (same numeric fields; here
|
|
@@ -20645,7 +20744,7 @@ var RunnerCameraConfigSchema = object({
|
|
|
20645
20744
|
* - `analyzer`: ML/frame-diff motion detection (motion-wasm or other
|
|
20646
20745
|
* analyzer providers) running on decoded frames in this runner.
|
|
20647
20746
|
* - `onboard`: camera-native motion pushes (Reolink Baichuan, ONVIF
|
|
20648
|
-
* analytics
|
|
20747
|
+
* analytics). The provider emits ProviderMotion
|
|
20649
20748
|
* events; the orchestrator forwards to `reportMotion`.
|
|
20650
20749
|
*/
|
|
20651
20750
|
motionSources: MotionSourcesSchema.default(["analyzer"]),
|
|
@@ -20887,7 +20986,26 @@ method(RunnerCameraConfigSchema, object({ success: literal(true) }), { kind: "mu
|
|
|
20887
20986
|
className: string(),
|
|
20888
20987
|
/** Camera the pixels came from. Diagnostics + log tags ONLY — never routing. */
|
|
20889
20988
|
sourceDeviceId: number()
|
|
20890
|
-
}), RunStatelessStepResultSchema, { kind: "mutation" })
|
|
20989
|
+
}), RunStatelessStepResultSchema, { kind: "mutation" }), method(object({
|
|
20990
|
+
deviceId: number(),
|
|
20991
|
+
/** Opaque to the runner — the hub's track id. */
|
|
20992
|
+
trackId: string(),
|
|
20993
|
+
kind: ParkedFrameKindSchema,
|
|
20994
|
+
handle: FrameHandleSchema,
|
|
20995
|
+
/** Normalized [0,1] window to cut. `{0,0,1,1}` for a full frame. */
|
|
20996
|
+
bbox: NativeCropBboxSchema,
|
|
20997
|
+
/** Width cap for a full-frame park (the `keyFrame` native cap). */
|
|
20998
|
+
maxWidth: number().int().positive().optional(),
|
|
20999
|
+
/** The frame instant (caller's clock) — orders parks for one key. */
|
|
21000
|
+
timestamp: number()
|
|
21001
|
+
}), ParkTrackFrameResultSchema, { kind: "mutation" }), method(object({
|
|
21002
|
+
deviceId: number(),
|
|
21003
|
+
trackId: string(),
|
|
21004
|
+
kind: ParkedFrameKindSchema
|
|
21005
|
+
}), ParkedTrackFrameSchema.nullable()), method(object({
|
|
21006
|
+
deviceId: number(),
|
|
21007
|
+
trackId: string()
|
|
21008
|
+
}), object({ released: number().int().nonnegative() }), { kind: "mutation" });
|
|
20891
21009
|
var CameraPipelineConfigSchema = object({
|
|
20892
21010
|
engine: PipelineEngineChoiceSchema.optional(),
|
|
20893
21011
|
steps: array(PipelineStepInputSchema).readonly(),
|
|
@@ -23816,7 +23934,7 @@ DeviceType.Button, method(object({ deviceId: number().int().nonnegative() }), _v
|
|
|
23816
23934
|
*
|
|
23817
23935
|
* Implementations:
|
|
23818
23936
|
* - Each camera-providing addon registers this cap natively per
|
|
23819
|
-
* device (Reolink, Hikvision, RTSP,
|
|
23937
|
+
* device (Reolink, Hikvision, RTSP, ONVIF self).
|
|
23820
23938
|
* - Returns a snapshot from the persisted device config blob — no
|
|
23821
23939
|
* extra round-trip to the camera, no probing.
|
|
23822
23940
|
* - The cap is admin-only (`auth: 'admin'`) — credentials must not
|
|
@@ -25202,7 +25320,7 @@ var AvailableIntegrationTypeSchema = object({
|
|
|
25202
25320
|
* Which integration-marker cap the addon declared, so the wizard can
|
|
25203
25321
|
* branch on CAP — never on addon name. `device-adoption` integrations
|
|
25204
25322
|
* (Home Assistant, …) route through the broker step (Approach A);
|
|
25205
|
-
* `device-provider` integrations (Reolink/
|
|
25323
|
+
* `device-provider` integrations (Reolink/ONVIF) keep the
|
|
25206
25324
|
* legacy config → discovery flow.
|
|
25207
25325
|
*/
|
|
25208
25326
|
kind: _enum(["device-adoption", "device-provider"]),
|
|
@@ -27703,7 +27821,23 @@ var RecordingRangeSchema = object({
|
|
|
27703
27821
|
});
|
|
27704
27822
|
var RecordingAvailabilitySchema = object({
|
|
27705
27823
|
deviceId: number(),
|
|
27706
|
-
ranges: array(RecordingRangeSchema)
|
|
27824
|
+
ranges: array(RecordingRangeSchema),
|
|
27825
|
+
/**
|
|
27826
|
+
* Every profile this camera has footage in — not only the one `ranges`
|
|
27827
|
+
* describes (D433).
|
|
27828
|
+
*
|
|
27829
|
+
* `ranges` answers for ONE profile by design: the timeline is a single bar,
|
|
27830
|
+
* and enumerating all of them triples the directory reads for a bar that
|
|
27831
|
+
* would look identical. But the answer used to say nothing about that, so a
|
|
27832
|
+
* caller asking "what can I export?" read the single preferred profile as
|
|
27833
|
+
* the only one that exists — on this deployment every camera records `high`
|
|
27834
|
+
* AND `low`, the low tree holding 14 GB for camera 615 alone, and the export
|
|
27835
|
+
* UI could not see it.
|
|
27836
|
+
*
|
|
27837
|
+
* Cheap: it is the same shallow directory read the profile CHOICE already
|
|
27838
|
+
* makes. Ask for a specific profile's ranges with the `profile` input.
|
|
27839
|
+
*/
|
|
27840
|
+
profilesWithFootage: array(string())
|
|
27707
27841
|
});
|
|
27708
27842
|
var RecordingDaysSchema = object({
|
|
27709
27843
|
deviceId: number(),
|
|
@@ -27729,7 +27863,11 @@ var RecordingDaysSchema = object({
|
|
|
27729
27863
|
var RecordingAvailabilityForDeviceSchema = object({
|
|
27730
27864
|
deviceId: number(),
|
|
27731
27865
|
read: _enum(["read", "unreadable"]),
|
|
27732
|
-
ranges: array(RecordingRangeSchema).readonly()
|
|
27866
|
+
ranges: array(RecordingRangeSchema).readonly(),
|
|
27867
|
+
/** Same field, same meaning, as the singular answer (D433). A row that
|
|
27868
|
+
* dropped it would tell a grid caller the archive holds one profile.
|
|
27869
|
+
* Empty on an `'unreadable'` row: nobody looked. */
|
|
27870
|
+
profilesWithFootage: array(string()).readonly()
|
|
27733
27871
|
});
|
|
27734
27872
|
/**
|
|
27735
27873
|
* One camera's row in a `getDaysWithRecordingsBatch` answer. Same rule as
|
|
@@ -27759,13 +27897,31 @@ var RecordingManifestSchema = object({
|
|
|
27759
27897
|
*/
|
|
27760
27898
|
playbackEndpoints: array(string())
|
|
27761
27899
|
});
|
|
27762
|
-
/**
|
|
27763
|
-
*
|
|
27900
|
+
/**
|
|
27901
|
+
* Recording storage usage for one camera — what the ARCHIVE holds for it,
|
|
27902
|
+
* across every profile and every resolvable location on this node.
|
|
27903
|
+
*
|
|
27904
|
+
* ## Archive vs residency, which is the whole point of this shape (D418)
|
|
27905
|
+
*
|
|
27906
|
+
* `usedBytes` / `oldestMs` / `segments` are the durable hour ledger's numbers:
|
|
27907
|
+
* the same quantity `RecordingLocationUsage.usedBytes` reports for the volume
|
|
27908
|
+
* this camera writes to, so the two can be added up and compared.
|
|
27909
|
+
*
|
|
27910
|
+
* They were not always. Until D418 this row came from the recorder's in-RAM
|
|
27911
|
+
* `RecordingIndex`, which since D287 holds only the live tail plus the hours
|
|
27912
|
+
* somebody hydrated — so a hub with 1.9 TB and 3.3 days of footage reported
|
|
27913
|
+
* 60.5 GB and "oldest: three hours ago" on the same page as the volume row
|
|
27914
|
+
* that said otherwise, and two people read it as retention eating recent
|
|
27915
|
+
* footage. Residency is still reported, under `residentBytes` /
|
|
27916
|
+
* `residentOldestMs`, which answer a different question and say so.
|
|
27917
|
+
*/
|
|
27764
27918
|
var RecordingDeviceUsageSchema = object({
|
|
27765
27919
|
deviceId: number(),
|
|
27920
|
+
/** Bytes the ARCHIVE holds for this camera on this node's resolvable
|
|
27921
|
+
* recordings locations. */
|
|
27766
27922
|
usedBytes: number(),
|
|
27767
27923
|
/**
|
|
27768
|
-
* Start of this camera's OLDEST
|
|
27924
|
+
* Start of this camera's OLDEST ARCHIVED segment, across every profile and
|
|
27769
27925
|
* location — the "Oldest footage" column in Recordings → Storage, and the
|
|
27770
27926
|
* only honest answer to "is retention actually holding?" per camera.
|
|
27771
27927
|
*
|
|
@@ -27775,7 +27931,24 @@ var RecordingDeviceUsageSchema = object({
|
|
|
27775
27931
|
* (types) and the addon ship on different trains, and the addon is usually
|
|
27776
27932
|
* the later of the two.
|
|
27777
27933
|
*/
|
|
27778
|
-
oldestMs: number().nullable().optional()
|
|
27934
|
+
oldestMs: number().nullable().optional(),
|
|
27935
|
+
/** Segments the archive holds for this camera — the "M" beside `usedBytes`.
|
|
27936
|
+
* OPTIONAL for the same train-skew reason as `oldestMs`. */
|
|
27937
|
+
segments: number().optional(),
|
|
27938
|
+
/**
|
|
27939
|
+
* RESIDENCY, not the archive: bytes the recorder process currently holds in
|
|
27940
|
+
* its RAM index — the live tail plus the hours a reader hydrated.
|
|
27941
|
+
*
|
|
27942
|
+
* It answers "what can be served without touching the disk", never "how much
|
|
27943
|
+
* footage this camera has". A UI that renders it must label it as such, and
|
|
27944
|
+
* must never total it as storage. OPTIONAL: a recorder predating D418 omits
|
|
27945
|
+
* it, and so does a node whose ledger could not answer.
|
|
27946
|
+
*/
|
|
27947
|
+
residentBytes: number().optional(),
|
|
27948
|
+
/** The residency counterpart of `oldestMs` — the oldest segment currently in
|
|
27949
|
+
* RAM, which on a healthy recorder is minutes ago and means nothing about
|
|
27950
|
+
* retention. `null` = nothing resident. */
|
|
27951
|
+
residentOldestMs: number().nullable().optional()
|
|
27779
27952
|
});
|
|
27780
27953
|
/** Recording storage usage + capacity for one storage location. */
|
|
27781
27954
|
var RecordingLocationUsageSchema = object({
|
|
@@ -27813,6 +27986,17 @@ var RecordingStorageUsageSchema = object({
|
|
|
27813
27986
|
totalUsedBytes: number(),
|
|
27814
27987
|
devices: array(RecordingDeviceUsageSchema),
|
|
27815
27988
|
/**
|
|
27989
|
+
* WHERE `devices[]` came from, so an empty table is never mistaken for empty
|
|
27990
|
+
* disks (D418).
|
|
27991
|
+
*
|
|
27992
|
+
* `archive` = the durable hour ledger answered. `unavailable` = this node
|
|
27993
|
+
* declared no ledger and the recorder REFUSED rather than answering the
|
|
27994
|
+
* question with the resident index (D295 rule 3) — the rows are UNKNOWN, not
|
|
27995
|
+
* zero, and a UI must say so. OPTIONAL: a recorder predating D418 omits it,
|
|
27996
|
+
* and its rows are residency.
|
|
27997
|
+
*/
|
|
27998
|
+
devicesRead: _enum(["archive", "unavailable"]).optional(),
|
|
27999
|
+
/**
|
|
27816
28000
|
* Per-physical-volume capacity. OPTIONAL, and consumers must render the rest
|
|
27817
28001
|
* of the payload without it: the hub serves this method through a BAKED
|
|
27818
28002
|
* router, so a hub whose framework train predates a change to this array
|
|
@@ -27973,7 +28157,14 @@ var ReadWindowBytesResultSchema = discriminatedUnion("kind", [object({
|
|
|
27973
28157
|
method(object({
|
|
27974
28158
|
deviceId: number(),
|
|
27975
28159
|
fromMs: number(),
|
|
27976
|
-
toMs: number()
|
|
28160
|
+
toMs: number(),
|
|
28161
|
+
/**
|
|
28162
|
+
* Answer for THIS profile instead of the preferred one (D433). Absent
|
|
28163
|
+
* keeps the timeline's behaviour — one bar, one profile, one set of
|
|
28164
|
+
* reads. `profilesWithFootage` on the answer says what may be asked
|
|
28165
|
+
* for.
|
|
28166
|
+
*/
|
|
28167
|
+
profile: string().optional()
|
|
27977
28168
|
}), RecordingAvailabilitySchema, {
|
|
27978
28169
|
kind: "query",
|
|
27979
28170
|
auth: "protected"
|
|
@@ -34200,6 +34391,24 @@ Object.freeze({
|
|
|
34200
34391
|
addonId: null,
|
|
34201
34392
|
access: "view"
|
|
34202
34393
|
},
|
|
34394
|
+
"pipelineRunner.getParkedTrackFrame": {
|
|
34395
|
+
capName: "pipeline-runner",
|
|
34396
|
+
capScope: "system",
|
|
34397
|
+
addonId: null,
|
|
34398
|
+
access: "view"
|
|
34399
|
+
},
|
|
34400
|
+
"pipelineRunner.parkTrackFrame": {
|
|
34401
|
+
capName: "pipeline-runner",
|
|
34402
|
+
capScope: "system",
|
|
34403
|
+
addonId: null,
|
|
34404
|
+
access: "create"
|
|
34405
|
+
},
|
|
34406
|
+
"pipelineRunner.releaseParkedTrackFrames": {
|
|
34407
|
+
capName: "pipeline-runner",
|
|
34408
|
+
capScope: "system",
|
|
34409
|
+
addonId: null,
|
|
34410
|
+
access: "create"
|
|
34411
|
+
},
|
|
34203
34412
|
"pipelineRunner.reportMotion": {
|
|
34204
34413
|
capName: "pipeline-runner",
|
|
34205
34414
|
capScope: "system",
|
|
@@ -37477,6 +37686,21 @@ Object.freeze({
|
|
|
37477
37686
|
form: "single",
|
|
37478
37687
|
optional: false
|
|
37479
37688
|
}],
|
|
37689
|
+
"pipelineRunner.getParkedTrackFrame": [{
|
|
37690
|
+
name: "deviceId",
|
|
37691
|
+
form: "single",
|
|
37692
|
+
optional: false
|
|
37693
|
+
}],
|
|
37694
|
+
"pipelineRunner.parkTrackFrame": [{
|
|
37695
|
+
name: "deviceId",
|
|
37696
|
+
form: "single",
|
|
37697
|
+
optional: false
|
|
37698
|
+
}],
|
|
37699
|
+
"pipelineRunner.releaseParkedTrackFrames": [{
|
|
37700
|
+
name: "deviceId",
|
|
37701
|
+
form: "single",
|
|
37702
|
+
optional: false
|
|
37703
|
+
}],
|
|
37480
37704
|
"pipelineRunner.reportMotion": [{
|
|
37481
37705
|
name: "deviceId",
|
|
37482
37706
|
form: "single",
|
|
@@ -38168,7 +38392,7 @@ var PreviewTextField = string().max(200);
|
|
|
38168
38392
|
* Whether the notification's preview is a STILL or a short animation.
|
|
38169
38393
|
*
|
|
38170
38394
|
* The operator's ask, verbatim: *"inviato come gif o video (come per le altre
|
|
38171
|
-
* rule)"* —
|
|
38395
|
+
* rule)"* — the other rules already offer an animated preview, and a ten-hour
|
|
38172
38396
|
* night reads better as three seconds of motion than as one frame of it. Both
|
|
38173
38397
|
* modes get the SAME treatment (blurred frame, large centred title); `'gif'`
|
|
38174
38398
|
* simply applies it to a dozen frames sampled across the render and assembles
|
|
@@ -39,7 +39,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
39
39
|
var __toCommonJS = (mod) => __hasOwnProp.call(mod, "module.exports") ? mod["module.exports"] : __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
40
40
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
41
41
|
//#endregion
|
|
42
|
-
//#region ../types/dist/event-category-
|
|
42
|
+
//#region ../types/dist/event-category-DAXzJeTX.mjs
|
|
43
43
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
44
44
|
EventCategory["SystemBoot"] = "system.boot";
|
|
45
45
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -631,7 +631,6 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
631
631
|
* issue. Payload `PipelineAnalyticsPlateGalleryChangedPayload`.
|
|
632
632
|
*/
|
|
633
633
|
EventCategory["PipelineAnalyticsPlateGalleryChanged"] = "pipeline-analytics.plate-gallery-changed";
|
|
634
|
-
EventCategory["FrigateLiveEvent"] = "frigate.live-event";
|
|
635
634
|
EventCategory["CameraStreamsProfileSlotsChanged"] = "camera-streams.onProfileSlotsChanged";
|
|
636
635
|
/**
|
|
637
636
|
* Stream-broker health watchdog. Per-broker (deviceId/profile) emission.
|
|
@@ -12596,7 +12595,7 @@ DeviceType.Camera;
|
|
|
12596
12595
|
var SourceInfoSchema = object({
|
|
12597
12596
|
/** Live dispatch key — mutable when the source system allows rename. */
|
|
12598
12597
|
id: string(),
|
|
12599
|
-
/** Source system tag — e.g. 'homeassistant' | 'reolink' | '
|
|
12598
|
+
/** Source system tag — e.g. 'homeassistant' | 'reolink' | 'onvif'. */
|
|
12600
12599
|
system: string(),
|
|
12601
12600
|
/** Immutable upstream identifier when available (HA `unique_id`, … ).
|
|
12602
12601
|
* Used to detect rename when `id` changes. */
|
|
@@ -13083,7 +13082,7 @@ method(_void(), _void(), { kind: "mutation" }), method(_void(), _void(), { kind:
|
|
|
13083
13082
|
* - `device-management.router.ts` (deleted in Phase 2)
|
|
13084
13083
|
* - `device-ops.router.ts` (compat layer — deleted; device-provider ops absorbed here)
|
|
13085
13084
|
*
|
|
13086
|
-
* All device provider addons (rtsp, onvif,
|
|
13085
|
+
* All device provider addons (rtsp, onvif, …) are hub-local: they may
|
|
13087
13086
|
* fork into separate processes but never run on remote cluster agents. Therefore:
|
|
13088
13087
|
* - No nodeId routing needed — this is a pure hub singleton.
|
|
13089
13088
|
* - The hub's DeviceRegistry is the single source of truth for all live devices.
|
|
@@ -17112,7 +17111,7 @@ var NcRuleInputSchema = object({
|
|
|
17112
17111
|
* The measured seven-person arrival on device 590 spans 110 s with every
|
|
17113
17112
|
* internal gap under 30 s. A 12 s fixed window cuts it into three groups; an
|
|
17114
17113
|
* idle cutoff holds it as one and ends it when the arrival actually ends.
|
|
17115
|
-
* 30 is
|
|
17114
|
+
* 30 s is a widely shipped value for the same decision.
|
|
17116
17115
|
*
|
|
17117
17116
|
* ### What it replaces
|
|
17118
17117
|
*
|
|
@@ -19154,6 +19153,13 @@ var ZoneCrossingSchema = object({
|
|
|
19154
19153
|
/** Zone display name at crossing time (falls back to the id). */
|
|
19155
19154
|
zoneName: string().optional()
|
|
19156
19155
|
});
|
|
19156
|
+
/** One zone a box was stamped with, and how much of the BOX fell inside it. */
|
|
19157
|
+
var ZoneOverlapSchema = object({
|
|
19158
|
+
zoneId: string(),
|
|
19159
|
+
zoneName: string().optional(),
|
|
19160
|
+
/** Percentage of the BOX area inside the zone, 0–100. */
|
|
19161
|
+
overlapPct: number()
|
|
19162
|
+
});
|
|
19157
19163
|
var ObjectEventSchema = object({
|
|
19158
19164
|
...BaseEventFields,
|
|
19159
19165
|
kind: literal("object"),
|
|
@@ -19178,6 +19184,35 @@ var ObjectEventSchema = object({
|
|
|
19178
19184
|
bbox: BoundingBoxSchema.optional(),
|
|
19179
19185
|
/** Heavy JSON — omitted in slim projection. */
|
|
19180
19186
|
zones: array(string()).readonly().optional(),
|
|
19187
|
+
/**
|
|
19188
|
+
* How far inside each stamped zone the box actually was, as a percentage of
|
|
19189
|
+
* the BOX area.
|
|
19190
|
+
*
|
|
19191
|
+
* Membership alone cannot express "at least a third of it inside", which is
|
|
19192
|
+
* the bar an operator argues with — and the number already existed: the
|
|
19193
|
+
* engine computed it, the pipeline logged it, and then discarded it. It
|
|
19194
|
+
* matters most on the events that carry no track, where a rule has nothing
|
|
19195
|
+
* else to judge by.
|
|
19196
|
+
*/
|
|
19197
|
+
zoneOverlaps: array(ZoneOverlapSchema).readonly().optional(),
|
|
19198
|
+
/**
|
|
19199
|
+
* Present when this event describes a detection the TRACKER refused, so it
|
|
19200
|
+
* has no track and never will.
|
|
19201
|
+
*
|
|
19202
|
+
* A zone-scoped immediate rule asks "is there an animal in the flowerbed
|
|
19203
|
+
* NOW?"; tracking answers a different question ("is this the same subject as
|
|
19204
|
+
* before?") whose confirmation threshold presumes continuity. On 2026-09-09 a
|
|
19205
|
+
* dog at 0.7729, 100% inside a watched zone, was refused three times in six
|
|
19206
|
+
* seconds with three different candidate ids — seven analysed frames in the
|
|
19207
|
+
* window, the subject in a handful of them, metres apart — and produced no
|
|
19208
|
+
* event at all.
|
|
19209
|
+
*
|
|
19210
|
+
* It is NAMED rather than merely implied by a missing `trackId`: an event
|
|
19211
|
+
* with no track and no reason is indistinguishable from a track whose media
|
|
19212
|
+
* went missing, and a consumer that asks this one for a best shot or a
|
|
19213
|
+
* history is asking for something that never existed.
|
|
19214
|
+
*/
|
|
19215
|
+
spawnRefused: string().optional(),
|
|
19181
19216
|
/** Omitted in slim projection. */
|
|
19182
19217
|
state: TrackStateSchema.optional(),
|
|
19183
19218
|
/**
|
|
@@ -19604,7 +19639,17 @@ var EventDensityBucketSchema = object({
|
|
|
19604
19639
|
bucketStart: number(),
|
|
19605
19640
|
motion: number().int(),
|
|
19606
19641
|
object: number().int(),
|
|
19607
|
-
audio: number().int()
|
|
19642
|
+
audio: number().int(),
|
|
19643
|
+
/**
|
|
19644
|
+
* Energy-weighted mean dBFS of the audio events in this bucket — the LEVEL,
|
|
19645
|
+
* as opposed to `audio`, which is their COUNT (D431).
|
|
19646
|
+
*
|
|
19647
|
+
* ABSENT when the bucket holds no audio event. Absence means "nothing was
|
|
19648
|
+
* measured", which is not the same claim as silence, and a lane that cannot
|
|
19649
|
+
* tell them apart paints a quiet hour at full scale — which is exactly what
|
|
19650
|
+
* the count-on-a-level-meter did.
|
|
19651
|
+
*/
|
|
19652
|
+
audioDbfs: number().optional()
|
|
19608
19653
|
});
|
|
19609
19654
|
/**
|
|
19610
19655
|
* One camera's row in a `getEventDensityBatch` answer.
|
|
@@ -20251,6 +20296,60 @@ var NativeCropResultSchema = object({
|
|
|
20251
20296
|
*/
|
|
20252
20297
|
tier: _enum(["native", "ram-fullframe"]).optional()
|
|
20253
20298
|
});
|
|
20299
|
+
/**
|
|
20300
|
+
* What a PARKED frame is for — the `kind` half of the `(deviceId, trackId,
|
|
20301
|
+
* kind)` key ([D422](../../../docs/decisions/adr-0422-a-relevant-frame-is-parked-when-it-becomes-relevant.md)).
|
|
20302
|
+
*
|
|
20303
|
+
* - `keyFrame` — the track's clean best FULL frame at native width (capped by
|
|
20304
|
+
* the caller's `maxWidth`). What `keyFrame` + `keyFrameSmall` are written
|
|
20305
|
+
* from, and what the detail plane's full-frame rung cuts from.
|
|
20306
|
+
* - `thumbnail` — the best-shot subject slab: the caller's 16:9 central-square
|
|
20307
|
+
* window, cut by the runner at uncapped native resolution.
|
|
20308
|
+
*
|
|
20309
|
+
* The runner never interprets `trackId`; it is an opaque key the hub owns.
|
|
20310
|
+
*/
|
|
20311
|
+
var ParkedFrameKindSchema = _enum(["keyFrame", "thumbnail"]);
|
|
20312
|
+
/**
|
|
20313
|
+
* Why a park did NOT happen. Every one is logged on the runner with
|
|
20314
|
+
* `tags: { deviceId }` and the handle's measured age, because a handle already
|
|
20315
|
+
* gone at park time IS the defect the 150–500 ms window exists to prevent —
|
|
20316
|
+
* never a reason to retry in a loop.
|
|
20317
|
+
*
|
|
20318
|
+
* - `handle-gone` — the native surface no longer resolves this handle (never
|
|
20319
|
+
* registered, past the lease bound, or the worker released it). `detail`
|
|
20320
|
+
* carries the runner's own miss reason.
|
|
20321
|
+
* - `encode-failed` — pixels resolved and the JPEG encode threw.
|
|
20322
|
+
*/
|
|
20323
|
+
var ParkRefusalSchema = _enum(["handle-gone", "encode-failed"]);
|
|
20324
|
+
/** Answer to `parkTrackFrame` — a discriminated union, so "not parked" always names why. */
|
|
20325
|
+
var ParkTrackFrameResultSchema = discriminatedUnion("parked", [object({
|
|
20326
|
+
parked: literal(true),
|
|
20327
|
+
/** The node holding the parcel — what a later retrieval must be pinned to. */
|
|
20328
|
+
nodeId: string(),
|
|
20329
|
+
width: number().int().positive(),
|
|
20330
|
+
height: number().int().positive(),
|
|
20331
|
+
/** JPEG bytes the parcel costs on the node. */
|
|
20332
|
+
bytes: number().int().nonnegative(),
|
|
20333
|
+
/** Whether this park replaced a parcel already held for the key. */
|
|
20334
|
+
replaced: boolean()
|
|
20335
|
+
}), object({
|
|
20336
|
+
parked: literal(false),
|
|
20337
|
+
nodeId: string(),
|
|
20338
|
+
reason: ParkRefusalSchema,
|
|
20339
|
+
/** Age of the handle at the park, on the runner's clock; null if unknown. */
|
|
20340
|
+
handleAgeMs: number().nullable(),
|
|
20341
|
+
detail: string().optional()
|
|
20342
|
+
})]);
|
|
20343
|
+
/** A retrieved parcel — the runner's own JPEG, base64 for the wire. */
|
|
20344
|
+
var ParkedTrackFrameSchema = object({
|
|
20345
|
+
jpeg: string(),
|
|
20346
|
+
width: number().int().positive(),
|
|
20347
|
+
height: number().int().positive(),
|
|
20348
|
+
/** The frame instant the parcel shows (the caller's clock, echoed back). */
|
|
20349
|
+
timestamp: number(),
|
|
20350
|
+
/** When the node stored it (the node's clock). */
|
|
20351
|
+
parkedAt: number()
|
|
20352
|
+
});
|
|
20254
20353
|
/** Parent detection context passed to `runDetailSubtree` — the crop's
|
|
20255
20354
|
* originating detection, in FRAME-space coordinates. Reuses
|
|
20256
20355
|
* `NativeCropBboxSchema`'s `{x,y,w,h}` shape (same numeric fields; here
|
|
@@ -20640,7 +20739,7 @@ var RunnerCameraConfigSchema = object({
|
|
|
20640
20739
|
* - `analyzer`: ML/frame-diff motion detection (motion-wasm or other
|
|
20641
20740
|
* analyzer providers) running on decoded frames in this runner.
|
|
20642
20741
|
* - `onboard`: camera-native motion pushes (Reolink Baichuan, ONVIF
|
|
20643
|
-
* analytics
|
|
20742
|
+
* analytics). The provider emits ProviderMotion
|
|
20644
20743
|
* events; the orchestrator forwards to `reportMotion`.
|
|
20645
20744
|
*/
|
|
20646
20745
|
motionSources: MotionSourcesSchema.default(["analyzer"]),
|
|
@@ -20882,7 +20981,26 @@ method(RunnerCameraConfigSchema, object({ success: literal(true) }), { kind: "mu
|
|
|
20882
20981
|
className: string(),
|
|
20883
20982
|
/** Camera the pixels came from. Diagnostics + log tags ONLY — never routing. */
|
|
20884
20983
|
sourceDeviceId: number()
|
|
20885
|
-
}), RunStatelessStepResultSchema, { kind: "mutation" })
|
|
20984
|
+
}), RunStatelessStepResultSchema, { kind: "mutation" }), method(object({
|
|
20985
|
+
deviceId: number(),
|
|
20986
|
+
/** Opaque to the runner — the hub's track id. */
|
|
20987
|
+
trackId: string(),
|
|
20988
|
+
kind: ParkedFrameKindSchema,
|
|
20989
|
+
handle: FrameHandleSchema,
|
|
20990
|
+
/** Normalized [0,1] window to cut. `{0,0,1,1}` for a full frame. */
|
|
20991
|
+
bbox: NativeCropBboxSchema,
|
|
20992
|
+
/** Width cap for a full-frame park (the `keyFrame` native cap). */
|
|
20993
|
+
maxWidth: number().int().positive().optional(),
|
|
20994
|
+
/** The frame instant (caller's clock) — orders parks for one key. */
|
|
20995
|
+
timestamp: number()
|
|
20996
|
+
}), ParkTrackFrameResultSchema, { kind: "mutation" }), method(object({
|
|
20997
|
+
deviceId: number(),
|
|
20998
|
+
trackId: string(),
|
|
20999
|
+
kind: ParkedFrameKindSchema
|
|
21000
|
+
}), ParkedTrackFrameSchema.nullable()), method(object({
|
|
21001
|
+
deviceId: number(),
|
|
21002
|
+
trackId: string()
|
|
21003
|
+
}), object({ released: number().int().nonnegative() }), { kind: "mutation" });
|
|
20886
21004
|
var CameraPipelineConfigSchema = object({
|
|
20887
21005
|
engine: PipelineEngineChoiceSchema.optional(),
|
|
20888
21006
|
steps: array(PipelineStepInputSchema).readonly(),
|
|
@@ -23811,7 +23929,7 @@ DeviceType.Button, method(object({ deviceId: number().int().nonnegative() }), _v
|
|
|
23811
23929
|
*
|
|
23812
23930
|
* Implementations:
|
|
23813
23931
|
* - Each camera-providing addon registers this cap natively per
|
|
23814
|
-
* device (Reolink, Hikvision, RTSP,
|
|
23932
|
+
* device (Reolink, Hikvision, RTSP, ONVIF self).
|
|
23815
23933
|
* - Returns a snapshot from the persisted device config blob — no
|
|
23816
23934
|
* extra round-trip to the camera, no probing.
|
|
23817
23935
|
* - The cap is admin-only (`auth: 'admin'`) — credentials must not
|
|
@@ -25197,7 +25315,7 @@ var AvailableIntegrationTypeSchema = object({
|
|
|
25197
25315
|
* Which integration-marker cap the addon declared, so the wizard can
|
|
25198
25316
|
* branch on CAP — never on addon name. `device-adoption` integrations
|
|
25199
25317
|
* (Home Assistant, …) route through the broker step (Approach A);
|
|
25200
|
-
* `device-provider` integrations (Reolink/
|
|
25318
|
+
* `device-provider` integrations (Reolink/ONVIF) keep the
|
|
25201
25319
|
* legacy config → discovery flow.
|
|
25202
25320
|
*/
|
|
25203
25321
|
kind: _enum(["device-adoption", "device-provider"]),
|
|
@@ -27698,7 +27816,23 @@ var RecordingRangeSchema = object({
|
|
|
27698
27816
|
});
|
|
27699
27817
|
var RecordingAvailabilitySchema = object({
|
|
27700
27818
|
deviceId: number(),
|
|
27701
|
-
ranges: array(RecordingRangeSchema)
|
|
27819
|
+
ranges: array(RecordingRangeSchema),
|
|
27820
|
+
/**
|
|
27821
|
+
* Every profile this camera has footage in — not only the one `ranges`
|
|
27822
|
+
* describes (D433).
|
|
27823
|
+
*
|
|
27824
|
+
* `ranges` answers for ONE profile by design: the timeline is a single bar,
|
|
27825
|
+
* and enumerating all of them triples the directory reads for a bar that
|
|
27826
|
+
* would look identical. But the answer used to say nothing about that, so a
|
|
27827
|
+
* caller asking "what can I export?" read the single preferred profile as
|
|
27828
|
+
* the only one that exists — on this deployment every camera records `high`
|
|
27829
|
+
* AND `low`, the low tree holding 14 GB for camera 615 alone, and the export
|
|
27830
|
+
* UI could not see it.
|
|
27831
|
+
*
|
|
27832
|
+
* Cheap: it is the same shallow directory read the profile CHOICE already
|
|
27833
|
+
* makes. Ask for a specific profile's ranges with the `profile` input.
|
|
27834
|
+
*/
|
|
27835
|
+
profilesWithFootage: array(string())
|
|
27702
27836
|
});
|
|
27703
27837
|
var RecordingDaysSchema = object({
|
|
27704
27838
|
deviceId: number(),
|
|
@@ -27724,7 +27858,11 @@ var RecordingDaysSchema = object({
|
|
|
27724
27858
|
var RecordingAvailabilityForDeviceSchema = object({
|
|
27725
27859
|
deviceId: number(),
|
|
27726
27860
|
read: _enum(["read", "unreadable"]),
|
|
27727
|
-
ranges: array(RecordingRangeSchema).readonly()
|
|
27861
|
+
ranges: array(RecordingRangeSchema).readonly(),
|
|
27862
|
+
/** Same field, same meaning, as the singular answer (D433). A row that
|
|
27863
|
+
* dropped it would tell a grid caller the archive holds one profile.
|
|
27864
|
+
* Empty on an `'unreadable'` row: nobody looked. */
|
|
27865
|
+
profilesWithFootage: array(string()).readonly()
|
|
27728
27866
|
});
|
|
27729
27867
|
/**
|
|
27730
27868
|
* One camera's row in a `getDaysWithRecordingsBatch` answer. Same rule as
|
|
@@ -27754,13 +27892,31 @@ var RecordingManifestSchema = object({
|
|
|
27754
27892
|
*/
|
|
27755
27893
|
playbackEndpoints: array(string())
|
|
27756
27894
|
});
|
|
27757
|
-
/**
|
|
27758
|
-
*
|
|
27895
|
+
/**
|
|
27896
|
+
* Recording storage usage for one camera — what the ARCHIVE holds for it,
|
|
27897
|
+
* across every profile and every resolvable location on this node.
|
|
27898
|
+
*
|
|
27899
|
+
* ## Archive vs residency, which is the whole point of this shape (D418)
|
|
27900
|
+
*
|
|
27901
|
+
* `usedBytes` / `oldestMs` / `segments` are the durable hour ledger's numbers:
|
|
27902
|
+
* the same quantity `RecordingLocationUsage.usedBytes` reports for the volume
|
|
27903
|
+
* this camera writes to, so the two can be added up and compared.
|
|
27904
|
+
*
|
|
27905
|
+
* They were not always. Until D418 this row came from the recorder's in-RAM
|
|
27906
|
+
* `RecordingIndex`, which since D287 holds only the live tail plus the hours
|
|
27907
|
+
* somebody hydrated — so a hub with 1.9 TB and 3.3 days of footage reported
|
|
27908
|
+
* 60.5 GB and "oldest: three hours ago" on the same page as the volume row
|
|
27909
|
+
* that said otherwise, and two people read it as retention eating recent
|
|
27910
|
+
* footage. Residency is still reported, under `residentBytes` /
|
|
27911
|
+
* `residentOldestMs`, which answer a different question and say so.
|
|
27912
|
+
*/
|
|
27759
27913
|
var RecordingDeviceUsageSchema = object({
|
|
27760
27914
|
deviceId: number(),
|
|
27915
|
+
/** Bytes the ARCHIVE holds for this camera on this node's resolvable
|
|
27916
|
+
* recordings locations. */
|
|
27761
27917
|
usedBytes: number(),
|
|
27762
27918
|
/**
|
|
27763
|
-
* Start of this camera's OLDEST
|
|
27919
|
+
* Start of this camera's OLDEST ARCHIVED segment, across every profile and
|
|
27764
27920
|
* location — the "Oldest footage" column in Recordings → Storage, and the
|
|
27765
27921
|
* only honest answer to "is retention actually holding?" per camera.
|
|
27766
27922
|
*
|
|
@@ -27770,7 +27926,24 @@ var RecordingDeviceUsageSchema = object({
|
|
|
27770
27926
|
* (types) and the addon ship on different trains, and the addon is usually
|
|
27771
27927
|
* the later of the two.
|
|
27772
27928
|
*/
|
|
27773
|
-
oldestMs: number().nullable().optional()
|
|
27929
|
+
oldestMs: number().nullable().optional(),
|
|
27930
|
+
/** Segments the archive holds for this camera — the "M" beside `usedBytes`.
|
|
27931
|
+
* OPTIONAL for the same train-skew reason as `oldestMs`. */
|
|
27932
|
+
segments: number().optional(),
|
|
27933
|
+
/**
|
|
27934
|
+
* RESIDENCY, not the archive: bytes the recorder process currently holds in
|
|
27935
|
+
* its RAM index — the live tail plus the hours a reader hydrated.
|
|
27936
|
+
*
|
|
27937
|
+
* It answers "what can be served without touching the disk", never "how much
|
|
27938
|
+
* footage this camera has". A UI that renders it must label it as such, and
|
|
27939
|
+
* must never total it as storage. OPTIONAL: a recorder predating D418 omits
|
|
27940
|
+
* it, and so does a node whose ledger could not answer.
|
|
27941
|
+
*/
|
|
27942
|
+
residentBytes: number().optional(),
|
|
27943
|
+
/** The residency counterpart of `oldestMs` — the oldest segment currently in
|
|
27944
|
+
* RAM, which on a healthy recorder is minutes ago and means nothing about
|
|
27945
|
+
* retention. `null` = nothing resident. */
|
|
27946
|
+
residentOldestMs: number().nullable().optional()
|
|
27774
27947
|
});
|
|
27775
27948
|
/** Recording storage usage + capacity for one storage location. */
|
|
27776
27949
|
var RecordingLocationUsageSchema = object({
|
|
@@ -27808,6 +27981,17 @@ var RecordingStorageUsageSchema = object({
|
|
|
27808
27981
|
totalUsedBytes: number(),
|
|
27809
27982
|
devices: array(RecordingDeviceUsageSchema),
|
|
27810
27983
|
/**
|
|
27984
|
+
* WHERE `devices[]` came from, so an empty table is never mistaken for empty
|
|
27985
|
+
* disks (D418).
|
|
27986
|
+
*
|
|
27987
|
+
* `archive` = the durable hour ledger answered. `unavailable` = this node
|
|
27988
|
+
* declared no ledger and the recorder REFUSED rather than answering the
|
|
27989
|
+
* question with the resident index (D295 rule 3) — the rows are UNKNOWN, not
|
|
27990
|
+
* zero, and a UI must say so. OPTIONAL: a recorder predating D418 omits it,
|
|
27991
|
+
* and its rows are residency.
|
|
27992
|
+
*/
|
|
27993
|
+
devicesRead: _enum(["archive", "unavailable"]).optional(),
|
|
27994
|
+
/**
|
|
27811
27995
|
* Per-physical-volume capacity. OPTIONAL, and consumers must render the rest
|
|
27812
27996
|
* of the payload without it: the hub serves this method through a BAKED
|
|
27813
27997
|
* router, so a hub whose framework train predates a change to this array
|
|
@@ -27968,7 +28152,14 @@ var ReadWindowBytesResultSchema = discriminatedUnion("kind", [object({
|
|
|
27968
28152
|
method(object({
|
|
27969
28153
|
deviceId: number(),
|
|
27970
28154
|
fromMs: number(),
|
|
27971
|
-
toMs: number()
|
|
28155
|
+
toMs: number(),
|
|
28156
|
+
/**
|
|
28157
|
+
* Answer for THIS profile instead of the preferred one (D433). Absent
|
|
28158
|
+
* keeps the timeline's behaviour — one bar, one profile, one set of
|
|
28159
|
+
* reads. `profilesWithFootage` on the answer says what may be asked
|
|
28160
|
+
* for.
|
|
28161
|
+
*/
|
|
28162
|
+
profile: string().optional()
|
|
27972
28163
|
}), RecordingAvailabilitySchema, {
|
|
27973
28164
|
kind: "query",
|
|
27974
28165
|
auth: "protected"
|
|
@@ -34195,6 +34386,24 @@ Object.freeze({
|
|
|
34195
34386
|
addonId: null,
|
|
34196
34387
|
access: "view"
|
|
34197
34388
|
},
|
|
34389
|
+
"pipelineRunner.getParkedTrackFrame": {
|
|
34390
|
+
capName: "pipeline-runner",
|
|
34391
|
+
capScope: "system",
|
|
34392
|
+
addonId: null,
|
|
34393
|
+
access: "view"
|
|
34394
|
+
},
|
|
34395
|
+
"pipelineRunner.parkTrackFrame": {
|
|
34396
|
+
capName: "pipeline-runner",
|
|
34397
|
+
capScope: "system",
|
|
34398
|
+
addonId: null,
|
|
34399
|
+
access: "create"
|
|
34400
|
+
},
|
|
34401
|
+
"pipelineRunner.releaseParkedTrackFrames": {
|
|
34402
|
+
capName: "pipeline-runner",
|
|
34403
|
+
capScope: "system",
|
|
34404
|
+
addonId: null,
|
|
34405
|
+
access: "create"
|
|
34406
|
+
},
|
|
34198
34407
|
"pipelineRunner.reportMotion": {
|
|
34199
34408
|
capName: "pipeline-runner",
|
|
34200
34409
|
capScope: "system",
|
|
@@ -37472,6 +37681,21 @@ Object.freeze({
|
|
|
37472
37681
|
form: "single",
|
|
37473
37682
|
optional: false
|
|
37474
37683
|
}],
|
|
37684
|
+
"pipelineRunner.getParkedTrackFrame": [{
|
|
37685
|
+
name: "deviceId",
|
|
37686
|
+
form: "single",
|
|
37687
|
+
optional: false
|
|
37688
|
+
}],
|
|
37689
|
+
"pipelineRunner.parkTrackFrame": [{
|
|
37690
|
+
name: "deviceId",
|
|
37691
|
+
form: "single",
|
|
37692
|
+
optional: false
|
|
37693
|
+
}],
|
|
37694
|
+
"pipelineRunner.releaseParkedTrackFrames": [{
|
|
37695
|
+
name: "deviceId",
|
|
37696
|
+
form: "single",
|
|
37697
|
+
optional: false
|
|
37698
|
+
}],
|
|
37475
37699
|
"pipelineRunner.reportMotion": [{
|
|
37476
37700
|
name: "deviceId",
|
|
37477
37701
|
form: "single",
|
|
@@ -38163,7 +38387,7 @@ var PreviewTextField = string().max(200);
|
|
|
38163
38387
|
* Whether the notification's preview is a STILL or a short animation.
|
|
38164
38388
|
*
|
|
38165
38389
|
* The operator's ask, verbatim: *"inviato come gif o video (come per le altre
|
|
38166
|
-
* rule)"* —
|
|
38390
|
+
* rule)"* — the other rules already offer an animated preview, and a ten-hour
|
|
38167
38391
|
* night reads better as three seconds of motion than as one frame of it. Both
|
|
38168
38392
|
* modes get the SAME treatment (blurred frame, large centred title); `'gif'`
|
|
38169
38393
|
* simply applies it to a dozen frames sampled across the render and assembles
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-mqtt-broker",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.93",
|
|
4
4
|
"description": "MQTT broker registry addon for CamStack — manages external broker entries + an optional embedded aedes broker. Consumers spin up their own `mqtt.js` clients via the `mqtt-broker` cap.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|