@camstack/addon-provider-reolink 1.2.113 → 1.2.116
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 +286 -86
- package/dist/addon.mjs +286 -86
- package/package.json +1 -1
package/dist/addon.js
CHANGED
|
@@ -25,7 +25,7 @@ let fs_promises = require("fs/promises");
|
|
|
25
25
|
fs_promises = require_chunk.__toESM(fs_promises, 1);
|
|
26
26
|
let node_os = require("node:os");
|
|
27
27
|
node_os = require_chunk.__toESM(node_os);
|
|
28
|
-
//#region ../types/dist/event-category-
|
|
28
|
+
//#region ../types/dist/event-category-DAXzJeTX.mjs
|
|
29
29
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
30
30
|
EventCategory["SystemBoot"] = "system.boot";
|
|
31
31
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -617,7 +617,6 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
617
617
|
* issue. Payload `PipelineAnalyticsPlateGalleryChangedPayload`.
|
|
618
618
|
*/
|
|
619
619
|
EventCategory["PipelineAnalyticsPlateGalleryChanged"] = "pipeline-analytics.plate-gallery-changed";
|
|
620
|
-
EventCategory["FrigateLiveEvent"] = "frigate.live-event";
|
|
621
620
|
EventCategory["CameraStreamsProfileSlotsChanged"] = "camera-streams.onProfileSlotsChanged";
|
|
622
621
|
/**
|
|
623
622
|
* Stream-broker health watchdog. Per-broker (deviceId/profile) emission.
|
|
@@ -13229,7 +13228,7 @@ DeviceType.Camera;
|
|
|
13229
13228
|
var SourceInfoSchema = object({
|
|
13230
13229
|
/** Live dispatch key — mutable when the source system allows rename. */
|
|
13231
13230
|
id: string(),
|
|
13232
|
-
/** Source system tag — e.g. 'homeassistant' | 'reolink' | '
|
|
13231
|
+
/** Source system tag — e.g. 'homeassistant' | 'reolink' | 'onvif'. */
|
|
13233
13232
|
system: string(),
|
|
13234
13233
|
/** Immutable upstream identifier when available (HA `unique_id`, … ).
|
|
13235
13234
|
* Used to detect rename when `id` changes. */
|
|
@@ -13242,7 +13241,7 @@ var SourceInfoSchema = object({
|
|
|
13242
13241
|
/**
|
|
13243
13242
|
* Build the synthetic SourceInfo every existing provider falls back to
|
|
13244
13243
|
* when no upstream value has been persisted. Keeps non-migrated providers
|
|
13245
|
-
* (Reolink / Hikvision / ONVIF /
|
|
13244
|
+
* (Reolink / Hikvision / ONVIF / RTSP) functional without code
|
|
13246
13245
|
* changes — `id` reuses the CamStack stableId, `system` reuses the addon
|
|
13247
13246
|
* id. Real upstream identity replaces this once a provider migrates and
|
|
13248
13247
|
* calls `updateSourceInfo()` with concrete values.
|
|
@@ -13904,7 +13903,7 @@ var deviceProviderCapability = {
|
|
|
13904
13903
|
* - `device-management.router.ts` (deleted in Phase 2)
|
|
13905
13904
|
* - `device-ops.router.ts` (compat layer — deleted; device-provider ops absorbed here)
|
|
13906
13905
|
*
|
|
13907
|
-
* All device provider addons (rtsp, onvif,
|
|
13906
|
+
* All device provider addons (rtsp, onvif, …) are hub-local: they may
|
|
13908
13907
|
* fork into separate processes but never run on remote cluster agents. Therefore:
|
|
13909
13908
|
* - No nodeId routing needed — this is a pure hub singleton.
|
|
13910
13909
|
* - The hub's DeviceRegistry is the single source of truth for all live devices.
|
|
@@ -17992,7 +17991,7 @@ var NcRuleInputSchema = object({
|
|
|
17992
17991
|
* The measured seven-person arrival on device 590 spans 110 s with every
|
|
17993
17992
|
* internal gap under 30 s. A 12 s fixed window cuts it into three groups; an
|
|
17994
17993
|
* idle cutoff holds it as one and ends it when the arrival actually ends.
|
|
17995
|
-
* 30 is
|
|
17994
|
+
* 30 s is a widely shipped value for the same decision.
|
|
17996
17995
|
*
|
|
17997
17996
|
* ### What it replaces
|
|
17998
17997
|
*
|
|
@@ -20074,6 +20073,13 @@ var ZoneCrossingSchema = object({
|
|
|
20074
20073
|
/** Zone display name at crossing time (falls back to the id). */
|
|
20075
20074
|
zoneName: string().optional()
|
|
20076
20075
|
});
|
|
20076
|
+
/** One zone a box was stamped with, and how much of the BOX fell inside it. */
|
|
20077
|
+
var ZoneOverlapSchema = object({
|
|
20078
|
+
zoneId: string(),
|
|
20079
|
+
zoneName: string().optional(),
|
|
20080
|
+
/** Percentage of the BOX area inside the zone, 0–100. */
|
|
20081
|
+
overlapPct: number()
|
|
20082
|
+
});
|
|
20077
20083
|
var ObjectEventSchema = object({
|
|
20078
20084
|
...BaseEventFields,
|
|
20079
20085
|
kind: literal("object"),
|
|
@@ -20098,6 +20104,35 @@ var ObjectEventSchema = object({
|
|
|
20098
20104
|
bbox: BoundingBoxSchema.optional(),
|
|
20099
20105
|
/** Heavy JSON — omitted in slim projection. */
|
|
20100
20106
|
zones: array(string()).readonly().optional(),
|
|
20107
|
+
/**
|
|
20108
|
+
* How far inside each stamped zone the box actually was, as a percentage of
|
|
20109
|
+
* the BOX area.
|
|
20110
|
+
*
|
|
20111
|
+
* Membership alone cannot express "at least a third of it inside", which is
|
|
20112
|
+
* the bar an operator argues with — and the number already existed: the
|
|
20113
|
+
* engine computed it, the pipeline logged it, and then discarded it. It
|
|
20114
|
+
* matters most on the events that carry no track, where a rule has nothing
|
|
20115
|
+
* else to judge by.
|
|
20116
|
+
*/
|
|
20117
|
+
zoneOverlaps: array(ZoneOverlapSchema).readonly().optional(),
|
|
20118
|
+
/**
|
|
20119
|
+
* Present when this event describes a detection the TRACKER refused, so it
|
|
20120
|
+
* has no track and never will.
|
|
20121
|
+
*
|
|
20122
|
+
* A zone-scoped immediate rule asks "is there an animal in the flowerbed
|
|
20123
|
+
* NOW?"; tracking answers a different question ("is this the same subject as
|
|
20124
|
+
* before?") whose confirmation threshold presumes continuity. On 2026-09-09 a
|
|
20125
|
+
* dog at 0.7729, 100% inside a watched zone, was refused three times in six
|
|
20126
|
+
* seconds with three different candidate ids — seven analysed frames in the
|
|
20127
|
+
* window, the subject in a handful of them, metres apart — and produced no
|
|
20128
|
+
* event at all.
|
|
20129
|
+
*
|
|
20130
|
+
* It is NAMED rather than merely implied by a missing `trackId`: an event
|
|
20131
|
+
* with no track and no reason is indistinguishable from a track whose media
|
|
20132
|
+
* went missing, and a consumer that asks this one for a best shot or a
|
|
20133
|
+
* history is asking for something that never existed.
|
|
20134
|
+
*/
|
|
20135
|
+
spawnRefused: string().optional(),
|
|
20101
20136
|
/** Omitted in slim projection. */
|
|
20102
20137
|
state: TrackStateSchema.optional(),
|
|
20103
20138
|
/**
|
|
@@ -20524,7 +20559,17 @@ var EventDensityBucketSchema = object({
|
|
|
20524
20559
|
bucketStart: number(),
|
|
20525
20560
|
motion: number().int(),
|
|
20526
20561
|
object: number().int(),
|
|
20527
|
-
audio: number().int()
|
|
20562
|
+
audio: number().int(),
|
|
20563
|
+
/**
|
|
20564
|
+
* Energy-weighted mean dBFS of the audio events in this bucket — the LEVEL,
|
|
20565
|
+
* as opposed to `audio`, which is their COUNT (D431).
|
|
20566
|
+
*
|
|
20567
|
+
* ABSENT when the bucket holds no audio event. Absence means "nothing was
|
|
20568
|
+
* measured", which is not the same claim as silence, and a lane that cannot
|
|
20569
|
+
* tell them apart paints a quiet hour at full scale — which is exactly what
|
|
20570
|
+
* the count-on-a-level-meter did.
|
|
20571
|
+
*/
|
|
20572
|
+
audioDbfs: number().optional()
|
|
20528
20573
|
});
|
|
20529
20574
|
/**
|
|
20530
20575
|
* One camera's row in a `getEventDensityBatch` answer.
|
|
@@ -21171,6 +21216,60 @@ var NativeCropResultSchema = object({
|
|
|
21171
21216
|
*/
|
|
21172
21217
|
tier: _enum(["native", "ram-fullframe"]).optional()
|
|
21173
21218
|
});
|
|
21219
|
+
/**
|
|
21220
|
+
* What a PARKED frame is for — the `kind` half of the `(deviceId, trackId,
|
|
21221
|
+
* kind)` key ([D422](../../../docs/decisions/adr-0422-a-relevant-frame-is-parked-when-it-becomes-relevant.md)).
|
|
21222
|
+
*
|
|
21223
|
+
* - `keyFrame` — the track's clean best FULL frame at native width (capped by
|
|
21224
|
+
* the caller's `maxWidth`). What `keyFrame` + `keyFrameSmall` are written
|
|
21225
|
+
* from, and what the detail plane's full-frame rung cuts from.
|
|
21226
|
+
* - `thumbnail` — the best-shot subject slab: the caller's 16:9 central-square
|
|
21227
|
+
* window, cut by the runner at uncapped native resolution.
|
|
21228
|
+
*
|
|
21229
|
+
* The runner never interprets `trackId`; it is an opaque key the hub owns.
|
|
21230
|
+
*/
|
|
21231
|
+
var ParkedFrameKindSchema = _enum(["keyFrame", "thumbnail"]);
|
|
21232
|
+
/**
|
|
21233
|
+
* Why a park did NOT happen. Every one is logged on the runner with
|
|
21234
|
+
* `tags: { deviceId }` and the handle's measured age, because a handle already
|
|
21235
|
+
* gone at park time IS the defect the 150–500 ms window exists to prevent —
|
|
21236
|
+
* never a reason to retry in a loop.
|
|
21237
|
+
*
|
|
21238
|
+
* - `handle-gone` — the native surface no longer resolves this handle (never
|
|
21239
|
+
* registered, past the lease bound, or the worker released it). `detail`
|
|
21240
|
+
* carries the runner's own miss reason.
|
|
21241
|
+
* - `encode-failed` — pixels resolved and the JPEG encode threw.
|
|
21242
|
+
*/
|
|
21243
|
+
var ParkRefusalSchema = _enum(["handle-gone", "encode-failed"]);
|
|
21244
|
+
/** Answer to `parkTrackFrame` — a discriminated union, so "not parked" always names why. */
|
|
21245
|
+
var ParkTrackFrameResultSchema = discriminatedUnion("parked", [object({
|
|
21246
|
+
parked: literal(true),
|
|
21247
|
+
/** The node holding the parcel — what a later retrieval must be pinned to. */
|
|
21248
|
+
nodeId: string(),
|
|
21249
|
+
width: number().int().positive(),
|
|
21250
|
+
height: number().int().positive(),
|
|
21251
|
+
/** JPEG bytes the parcel costs on the node. */
|
|
21252
|
+
bytes: number().int().nonnegative(),
|
|
21253
|
+
/** Whether this park replaced a parcel already held for the key. */
|
|
21254
|
+
replaced: boolean()
|
|
21255
|
+
}), object({
|
|
21256
|
+
parked: literal(false),
|
|
21257
|
+
nodeId: string(),
|
|
21258
|
+
reason: ParkRefusalSchema,
|
|
21259
|
+
/** Age of the handle at the park, on the runner's clock; null if unknown. */
|
|
21260
|
+
handleAgeMs: number().nullable(),
|
|
21261
|
+
detail: string().optional()
|
|
21262
|
+
})]);
|
|
21263
|
+
/** A retrieved parcel — the runner's own JPEG, base64 for the wire. */
|
|
21264
|
+
var ParkedTrackFrameSchema = object({
|
|
21265
|
+
jpeg: string(),
|
|
21266
|
+
width: number().int().positive(),
|
|
21267
|
+
height: number().int().positive(),
|
|
21268
|
+
/** The frame instant the parcel shows (the caller's clock, echoed back). */
|
|
21269
|
+
timestamp: number(),
|
|
21270
|
+
/** When the node stored it (the node's clock). */
|
|
21271
|
+
parkedAt: number()
|
|
21272
|
+
});
|
|
21174
21273
|
/** Parent detection context passed to `runDetailSubtree` — the crop's
|
|
21175
21274
|
* originating detection, in FRAME-space coordinates. Reuses
|
|
21176
21275
|
* `NativeCropBboxSchema`'s `{x,y,w,h}` shape (same numeric fields; here
|
|
@@ -21560,7 +21659,7 @@ var RunnerCameraConfigSchema = object({
|
|
|
21560
21659
|
* - `analyzer`: ML/frame-diff motion detection (motion-wasm or other
|
|
21561
21660
|
* analyzer providers) running on decoded frames in this runner.
|
|
21562
21661
|
* - `onboard`: camera-native motion pushes (Reolink Baichuan, ONVIF
|
|
21563
|
-
* analytics
|
|
21662
|
+
* analytics). The provider emits ProviderMotion
|
|
21564
21663
|
* events; the orchestrator forwards to `reportMotion`.
|
|
21565
21664
|
*/
|
|
21566
21665
|
motionSources: MotionSourcesSchema.default(["analyzer"]),
|
|
@@ -21802,7 +21901,26 @@ method(RunnerCameraConfigSchema, object({ success: literal(true) }), { kind: "mu
|
|
|
21802
21901
|
className: string(),
|
|
21803
21902
|
/** Camera the pixels came from. Diagnostics + log tags ONLY — never routing. */
|
|
21804
21903
|
sourceDeviceId: number()
|
|
21805
|
-
}), RunStatelessStepResultSchema, { kind: "mutation" })
|
|
21904
|
+
}), RunStatelessStepResultSchema, { kind: "mutation" }), method(object({
|
|
21905
|
+
deviceId: number(),
|
|
21906
|
+
/** Opaque to the runner — the hub's track id. */
|
|
21907
|
+
trackId: string(),
|
|
21908
|
+
kind: ParkedFrameKindSchema,
|
|
21909
|
+
handle: FrameHandleSchema,
|
|
21910
|
+
/** Normalized [0,1] window to cut. `{0,0,1,1}` for a full frame. */
|
|
21911
|
+
bbox: NativeCropBboxSchema,
|
|
21912
|
+
/** Width cap for a full-frame park (the `keyFrame` native cap). */
|
|
21913
|
+
maxWidth: number().int().positive().optional(),
|
|
21914
|
+
/** The frame instant (caller's clock) — orders parks for one key. */
|
|
21915
|
+
timestamp: number()
|
|
21916
|
+
}), ParkTrackFrameResultSchema, { kind: "mutation" }), method(object({
|
|
21917
|
+
deviceId: number(),
|
|
21918
|
+
trackId: string(),
|
|
21919
|
+
kind: ParkedFrameKindSchema
|
|
21920
|
+
}), ParkedTrackFrameSchema.nullable()), method(object({
|
|
21921
|
+
deviceId: number(),
|
|
21922
|
+
trackId: string()
|
|
21923
|
+
}), object({ released: number().int().nonnegative() }), { kind: "mutation" });
|
|
21806
21924
|
var CameraPipelineConfigSchema = object({
|
|
21807
21925
|
engine: PipelineEngineChoiceSchema.optional(),
|
|
21808
21926
|
steps: array(PipelineStepInputSchema).readonly(),
|
|
@@ -24976,8 +25094,8 @@ onStatusChanged: { data: object({
|
|
|
24976
25094
|
/**
|
|
24977
25095
|
* Runtime-state slice — every provider that registers this cap
|
|
24978
25096
|
* stores the same shape under `device.runtimeState[battery]`.
|
|
24979
|
-
* Cross-provider uniformity: a Reolink Argus, a
|
|
24980
|
-
*
|
|
25097
|
+
* Cross-provider uniformity: a Reolink Argus, a sensor proxy,
|
|
25098
|
+
* an ONVIF battery cam all read/write the same keys.
|
|
24981
25099
|
* Consumers (BatteryBadge, snapshot wrapper sleep gate) read once
|
|
24982
25100
|
* via `device.runtimeState.getCapState('battery')` regardless of
|
|
24983
25101
|
* the underlying driver.
|
|
@@ -25110,7 +25228,7 @@ DeviceType.Button, method(object({ deviceId: number().int().nonnegative() }), _v
|
|
|
25110
25228
|
*
|
|
25111
25229
|
* Implementations:
|
|
25112
25230
|
* - Each camera-providing addon registers this cap natively per
|
|
25113
|
-
* device (Reolink, Hikvision, RTSP,
|
|
25231
|
+
* device (Reolink, Hikvision, RTSP, ONVIF self).
|
|
25114
25232
|
* - Returns a snapshot from the persisted device config blob — no
|
|
25115
25233
|
* extra round-trip to the camera, no probing.
|
|
25116
25234
|
* - The cap is admin-only (`auth: 'admin'`) — credentials must not
|
|
@@ -27202,7 +27320,7 @@ var AvailableIntegrationTypeSchema = object({
|
|
|
27202
27320
|
* Which integration-marker cap the addon declared, so the wizard can
|
|
27203
27321
|
* branch on CAP — never on addon name. `device-adoption` integrations
|
|
27204
27322
|
* (Home Assistant, …) route through the broker step (Approach A);
|
|
27205
|
-
* `device-provider` integrations (Reolink/
|
|
27323
|
+
* `device-provider` integrations (Reolink/ONVIF) keep the
|
|
27206
27324
|
* legacy config → discovery flow.
|
|
27207
27325
|
*/
|
|
27208
27326
|
kind: _enum(["device-adoption", "device-provider"]),
|
|
@@ -30677,7 +30795,23 @@ var RecordingRangeSchema = object({
|
|
|
30677
30795
|
});
|
|
30678
30796
|
var RecordingAvailabilitySchema = object({
|
|
30679
30797
|
deviceId: number(),
|
|
30680
|
-
ranges: array(RecordingRangeSchema)
|
|
30798
|
+
ranges: array(RecordingRangeSchema),
|
|
30799
|
+
/**
|
|
30800
|
+
* Every profile this camera has footage in — not only the one `ranges`
|
|
30801
|
+
* describes (D433).
|
|
30802
|
+
*
|
|
30803
|
+
* `ranges` answers for ONE profile by design: the timeline is a single bar,
|
|
30804
|
+
* and enumerating all of them triples the directory reads for a bar that
|
|
30805
|
+
* would look identical. But the answer used to say nothing about that, so a
|
|
30806
|
+
* caller asking "what can I export?" read the single preferred profile as
|
|
30807
|
+
* the only one that exists — on this deployment every camera records `high`
|
|
30808
|
+
* AND `low`, the low tree holding 14 GB for camera 615 alone, and the export
|
|
30809
|
+
* UI could not see it.
|
|
30810
|
+
*
|
|
30811
|
+
* Cheap: it is the same shallow directory read the profile CHOICE already
|
|
30812
|
+
* makes. Ask for a specific profile's ranges with the `profile` input.
|
|
30813
|
+
*/
|
|
30814
|
+
profilesWithFootage: array(string())
|
|
30681
30815
|
});
|
|
30682
30816
|
var RecordingDaysSchema = object({
|
|
30683
30817
|
deviceId: number(),
|
|
@@ -30703,7 +30837,11 @@ var RecordingDaysSchema = object({
|
|
|
30703
30837
|
var RecordingAvailabilityForDeviceSchema = object({
|
|
30704
30838
|
deviceId: number(),
|
|
30705
30839
|
read: _enum(["read", "unreadable"]),
|
|
30706
|
-
ranges: array(RecordingRangeSchema).readonly()
|
|
30840
|
+
ranges: array(RecordingRangeSchema).readonly(),
|
|
30841
|
+
/** Same field, same meaning, as the singular answer (D433). A row that
|
|
30842
|
+
* dropped it would tell a grid caller the archive holds one profile.
|
|
30843
|
+
* Empty on an `'unreadable'` row: nobody looked. */
|
|
30844
|
+
profilesWithFootage: array(string()).readonly()
|
|
30707
30845
|
});
|
|
30708
30846
|
/**
|
|
30709
30847
|
* One camera's row in a `getDaysWithRecordingsBatch` answer. Same rule as
|
|
@@ -30733,13 +30871,31 @@ var RecordingManifestSchema = object({
|
|
|
30733
30871
|
*/
|
|
30734
30872
|
playbackEndpoints: array(string())
|
|
30735
30873
|
});
|
|
30736
|
-
/**
|
|
30737
|
-
*
|
|
30874
|
+
/**
|
|
30875
|
+
* Recording storage usage for one camera — what the ARCHIVE holds for it,
|
|
30876
|
+
* across every profile and every resolvable location on this node.
|
|
30877
|
+
*
|
|
30878
|
+
* ## Archive vs residency, which is the whole point of this shape (D418)
|
|
30879
|
+
*
|
|
30880
|
+
* `usedBytes` / `oldestMs` / `segments` are the durable hour ledger's numbers:
|
|
30881
|
+
* the same quantity `RecordingLocationUsage.usedBytes` reports for the volume
|
|
30882
|
+
* this camera writes to, so the two can be added up and compared.
|
|
30883
|
+
*
|
|
30884
|
+
* They were not always. Until D418 this row came from the recorder's in-RAM
|
|
30885
|
+
* `RecordingIndex`, which since D287 holds only the live tail plus the hours
|
|
30886
|
+
* somebody hydrated — so a hub with 1.9 TB and 3.3 days of footage reported
|
|
30887
|
+
* 60.5 GB and "oldest: three hours ago" on the same page as the volume row
|
|
30888
|
+
* that said otherwise, and two people read it as retention eating recent
|
|
30889
|
+
* footage. Residency is still reported, under `residentBytes` /
|
|
30890
|
+
* `residentOldestMs`, which answer a different question and say so.
|
|
30891
|
+
*/
|
|
30738
30892
|
var RecordingDeviceUsageSchema = object({
|
|
30739
30893
|
deviceId: number(),
|
|
30894
|
+
/** Bytes the ARCHIVE holds for this camera on this node's resolvable
|
|
30895
|
+
* recordings locations. */
|
|
30740
30896
|
usedBytes: number(),
|
|
30741
30897
|
/**
|
|
30742
|
-
* Start of this camera's OLDEST
|
|
30898
|
+
* Start of this camera's OLDEST ARCHIVED segment, across every profile and
|
|
30743
30899
|
* location — the "Oldest footage" column in Recordings → Storage, and the
|
|
30744
30900
|
* only honest answer to "is retention actually holding?" per camera.
|
|
30745
30901
|
*
|
|
@@ -30749,7 +30905,24 @@ var RecordingDeviceUsageSchema = object({
|
|
|
30749
30905
|
* (types) and the addon ship on different trains, and the addon is usually
|
|
30750
30906
|
* the later of the two.
|
|
30751
30907
|
*/
|
|
30752
|
-
oldestMs: number().nullable().optional()
|
|
30908
|
+
oldestMs: number().nullable().optional(),
|
|
30909
|
+
/** Segments the archive holds for this camera — the "M" beside `usedBytes`.
|
|
30910
|
+
* OPTIONAL for the same train-skew reason as `oldestMs`. */
|
|
30911
|
+
segments: number().optional(),
|
|
30912
|
+
/**
|
|
30913
|
+
* RESIDENCY, not the archive: bytes the recorder process currently holds in
|
|
30914
|
+
* its RAM index — the live tail plus the hours a reader hydrated.
|
|
30915
|
+
*
|
|
30916
|
+
* It answers "what can be served without touching the disk", never "how much
|
|
30917
|
+
* footage this camera has". A UI that renders it must label it as such, and
|
|
30918
|
+
* must never total it as storage. OPTIONAL: a recorder predating D418 omits
|
|
30919
|
+
* it, and so does a node whose ledger could not answer.
|
|
30920
|
+
*/
|
|
30921
|
+
residentBytes: number().optional(),
|
|
30922
|
+
/** The residency counterpart of `oldestMs` — the oldest segment currently in
|
|
30923
|
+
* RAM, which on a healthy recorder is minutes ago and means nothing about
|
|
30924
|
+
* retention. `null` = nothing resident. */
|
|
30925
|
+
residentOldestMs: number().nullable().optional()
|
|
30753
30926
|
});
|
|
30754
30927
|
/** Recording storage usage + capacity for one storage location. */
|
|
30755
30928
|
var RecordingLocationUsageSchema = object({
|
|
@@ -30787,6 +30960,17 @@ var RecordingStorageUsageSchema = object({
|
|
|
30787
30960
|
totalUsedBytes: number(),
|
|
30788
30961
|
devices: array(RecordingDeviceUsageSchema),
|
|
30789
30962
|
/**
|
|
30963
|
+
* WHERE `devices[]` came from, so an empty table is never mistaken for empty
|
|
30964
|
+
* disks (D418).
|
|
30965
|
+
*
|
|
30966
|
+
* `archive` = the durable hour ledger answered. `unavailable` = this node
|
|
30967
|
+
* declared no ledger and the recorder REFUSED rather than answering the
|
|
30968
|
+
* question with the resident index (D295 rule 3) — the rows are UNKNOWN, not
|
|
30969
|
+
* zero, and a UI must say so. OPTIONAL: a recorder predating D418 omits it,
|
|
30970
|
+
* and its rows are residency.
|
|
30971
|
+
*/
|
|
30972
|
+
devicesRead: _enum(["archive", "unavailable"]).optional(),
|
|
30973
|
+
/**
|
|
30790
30974
|
* Per-physical-volume capacity. OPTIONAL, and consumers must render the rest
|
|
30791
30975
|
* of the payload without it: the hub serves this method through a BAKED
|
|
30792
30976
|
* router, so a hub whose framework train predates a change to this array
|
|
@@ -30947,7 +31131,14 @@ var ReadWindowBytesResultSchema = discriminatedUnion("kind", [object({
|
|
|
30947
31131
|
method(object({
|
|
30948
31132
|
deviceId: number(),
|
|
30949
31133
|
fromMs: number(),
|
|
30950
|
-
toMs: number()
|
|
31134
|
+
toMs: number(),
|
|
31135
|
+
/**
|
|
31136
|
+
* Answer for THIS profile instead of the preferred one (D433). Absent
|
|
31137
|
+
* keeps the timeline's behaviour — one bar, one profile, one set of
|
|
31138
|
+
* reads. `profilesWithFootage` on the answer says what may be asked
|
|
31139
|
+
* for.
|
|
31140
|
+
*/
|
|
31141
|
+
profile: string().optional()
|
|
30951
31142
|
}), RecordingAvailabilitySchema, {
|
|
30952
31143
|
kind: "query",
|
|
30953
31144
|
auth: "protected"
|
|
@@ -34879,7 +35070,7 @@ function toDeviceSummary(device, addonId) {
|
|
|
34879
35070
|
};
|
|
34880
35071
|
}
|
|
34881
35072
|
/**
|
|
34882
|
-
* Base class for device-provider addons (rtsp, onvif
|
|
35073
|
+
* Base class for device-provider addons (rtsp, onvif).
|
|
34883
35074
|
*
|
|
34884
35075
|
* Provides default implementations for the common device-provider cap
|
|
34885
35076
|
* methods (`start`, `stop`, `getStatus`, `getDevices`, `supportsDiscovery`,
|
|
@@ -39698,6 +39889,24 @@ Object.freeze({
|
|
|
39698
39889
|
addonId: null,
|
|
39699
39890
|
access: "view"
|
|
39700
39891
|
},
|
|
39892
|
+
"pipelineRunner.getParkedTrackFrame": {
|
|
39893
|
+
capName: "pipeline-runner",
|
|
39894
|
+
capScope: "system",
|
|
39895
|
+
addonId: null,
|
|
39896
|
+
access: "view"
|
|
39897
|
+
},
|
|
39898
|
+
"pipelineRunner.parkTrackFrame": {
|
|
39899
|
+
capName: "pipeline-runner",
|
|
39900
|
+
capScope: "system",
|
|
39901
|
+
addonId: null,
|
|
39902
|
+
access: "create"
|
|
39903
|
+
},
|
|
39904
|
+
"pipelineRunner.releaseParkedTrackFrames": {
|
|
39905
|
+
capName: "pipeline-runner",
|
|
39906
|
+
capScope: "system",
|
|
39907
|
+
addonId: null,
|
|
39908
|
+
access: "create"
|
|
39909
|
+
},
|
|
39701
39910
|
"pipelineRunner.reportMotion": {
|
|
39702
39911
|
capName: "pipeline-runner",
|
|
39703
39912
|
capScope: "system",
|
|
@@ -42975,6 +43184,21 @@ Object.freeze({
|
|
|
42975
43184
|
form: "single",
|
|
42976
43185
|
optional: false
|
|
42977
43186
|
}],
|
|
43187
|
+
"pipelineRunner.getParkedTrackFrame": [{
|
|
43188
|
+
name: "deviceId",
|
|
43189
|
+
form: "single",
|
|
43190
|
+
optional: false
|
|
43191
|
+
}],
|
|
43192
|
+
"pipelineRunner.parkTrackFrame": [{
|
|
43193
|
+
name: "deviceId",
|
|
43194
|
+
form: "single",
|
|
43195
|
+
optional: false
|
|
43196
|
+
}],
|
|
43197
|
+
"pipelineRunner.releaseParkedTrackFrames": [{
|
|
43198
|
+
name: "deviceId",
|
|
43199
|
+
form: "single",
|
|
43200
|
+
optional: false
|
|
43201
|
+
}],
|
|
42978
43202
|
"pipelineRunner.reportMotion": [{
|
|
42979
43203
|
name: "deviceId",
|
|
42980
43204
|
form: "single",
|
|
@@ -43666,7 +43890,7 @@ var PreviewTextField = string().max(200);
|
|
|
43666
43890
|
* Whether the notification's preview is a STILL or a short animation.
|
|
43667
43891
|
*
|
|
43668
43892
|
* The operator's ask, verbatim: *"inviato come gif o video (come per le altre
|
|
43669
|
-
* rule)"* —
|
|
43893
|
+
* rule)"* — the other rules already offer an animated preview, and a ten-hour
|
|
43670
43894
|
* night reads better as three seconds of motion than as one frame of it. Both
|
|
43671
43895
|
* modes get the SAME treatment (blurred frame, large centred title); `'gif'`
|
|
43672
43896
|
* simply applies it to a dozen frames sampled across the render and assembles
|
|
@@ -145536,12 +145760,10 @@ function mapNetworkReadout(readout, now) {
|
|
|
145536
145760
|
//#region src/error-classifier.ts
|
|
145537
145761
|
/**
|
|
145538
145762
|
* Recognise transient Baichuan/socket failures that are expected to
|
|
145539
|
-
* recover on the next reconnect cycle
|
|
145540
|
-
*
|
|
145541
|
-
* keeping parity so the same wire-level conditions are treated the
|
|
145542
|
-
* same way across plugins.
|
|
145763
|
+
* recover on the next reconnect cycle — the same wire-level conditions
|
|
145764
|
+
* are always treated the same way.
|
|
145543
145765
|
*
|
|
145544
|
-
*
|
|
145766
|
+
* Categories:
|
|
145545
145767
|
* - Baichuan-specific transport closes (`Baichuan socket closed`,
|
|
145546
145768
|
* `Baichuan UDP stream closed`, `Baichuan TCP socket is not
|
|
145547
145769
|
* connected`)
|
|
@@ -145611,9 +145833,7 @@ var resolveZoomStep = (travel, zoom) => {
|
|
|
145611
145833
|
/**
|
|
145612
145834
|
* IMA ADPCM (DVI4) encoder — Reolink Baichuan talk-back wire format.
|
|
145613
145835
|
*
|
|
145614
|
-
*
|
|
145615
|
-
* rest of the cross-cam Scrypted infra). Reolink cameras expect ADPCM
|
|
145616
|
-
* blocks of (4 + N) bytes:
|
|
145836
|
+
* Reolink cameras expect ADPCM blocks of (4 + N) bytes:
|
|
145617
145837
|
* - 2 bytes: little-endian Int16 predictor (first PCM sample of the
|
|
145618
145838
|
* block, used to seed the decoder state on the camera side)
|
|
145619
145839
|
* - 1 byte: index into the IMA step table (always 0 — we re-seed
|
|
@@ -145997,14 +146217,12 @@ var ReolinkIntercomSession = class {
|
|
|
145997
146217
|
}
|
|
145998
146218
|
}
|
|
145999
146219
|
};
|
|
146000
|
-
/** Clamp `blocksPerPayload` into the lib's accepted range.
|
|
146001
|
-
* scrypted-reolink-native's `intercom-mixin.ts:96-101` clamp. */
|
|
146220
|
+
/** Clamp `blocksPerPayload` into the lib's accepted range. */
|
|
146002
146221
|
function clampBlocks(value) {
|
|
146003
146222
|
if (value === void 0 || !Number.isFinite(value)) return DEFAULT_BLOCKS_PER_PAYLOAD;
|
|
146004
146223
|
return Math.max(1, Math.min(8, Math.floor(value)));
|
|
146005
146224
|
}
|
|
146006
|
-
/** Clamp `outputGain` into the operator-safe
|
|
146007
|
-
* band as Scrypted (`intercom-mixin.ts:104-107`). */
|
|
146225
|
+
/** Clamp `outputGain` into the operator-safe `[0.1, 10]` band. */
|
|
146008
146226
|
function clampGain(value) {
|
|
146009
146227
|
if (value === void 0 || !Number.isFinite(value)) return DEFAULT_GAIN;
|
|
146010
146228
|
return Math.max(MIN_GAIN, Math.min(MAX_GAIN, value));
|
|
@@ -146603,9 +146821,8 @@ var ReolinkUdpDiscoveryMethodSchema = _enum([
|
|
|
146603
146821
|
"map"
|
|
146604
146822
|
]);
|
|
146605
146823
|
/**
|
|
146606
|
-
* Lib-side socket debug categories
|
|
146607
|
-
*
|
|
146608
|
-
* users coming from Scrypted recognize them. Each flag is forwarded
|
|
146824
|
+
* Lib-side socket debug categories — the names and semantics the lib
|
|
146825
|
+
* itself uses, so they are recognizable. Each flag is forwarded
|
|
146609
146826
|
* verbatim into the `DebugOptions` blob `ReolinkBaichuanApi` accepts.
|
|
146610
146827
|
*/
|
|
146611
146828
|
var ReolinkSocketDebugFlagSchema = _enum([
|
|
@@ -147007,14 +147224,12 @@ var reolinkCameraSchema = object({
|
|
|
147007
147224
|
}).loose().optional(),
|
|
147008
147225
|
/**
|
|
147009
147226
|
* Generic Baichuan debug logs. Forwarded as `DebugOptions.general`
|
|
147010
|
-
* on the lib's `ReolinkBaichuanApi` constructor.
|
|
147011
|
-
* `debugLogs` boolean.
|
|
147227
|
+
* on the lib's `ReolinkBaichuanApi` constructor.
|
|
147012
147228
|
*/
|
|
147013
147229
|
debugGeneral: boolean().default(false),
|
|
147014
147230
|
/**
|
|
147015
147231
|
* Lib-side socket trace categories. Each flag flips the matching
|
|
147016
|
-
* `DebugOptions.<flag>` on the api.
|
|
147017
|
-
* `socketApiDebugLogs` multi-select.
|
|
147232
|
+
* `DebugOptions.<flag>` on the api.
|
|
147018
147233
|
*/
|
|
147019
147234
|
debugSocketLogs: array(ReolinkSocketDebugFlagSchema).default([]),
|
|
147020
147235
|
/**
|
|
@@ -147269,21 +147484,20 @@ var reolinkCameraSchema = object({
|
|
|
147269
147484
|
/**
|
|
147270
147485
|
* Intercom (browser→cam talk channel) tuning. Only consumed
|
|
147271
147486
|
* when the camera advertises two-way audio (`hasIntercom` in the
|
|
147272
|
-
* feature-probe slice).
|
|
147273
|
-
*
|
|
147274
|
-
* same defaults so the user-facing latency matches Scrypted's.
|
|
147487
|
+
* feature-probe slice). The names, ranges and defaults are the ones
|
|
147488
|
+
* the lib itself documents, so the user-facing latency is predictable.
|
|
147275
147489
|
*
|
|
147276
147490
|
* `intercomBlocksPerPayload` — number of IMA-ADPCM blocks bundled
|
|
147277
147491
|
* into each `sendAudio` call against the lib's dedicated talk
|
|
147278
147492
|
* session. Lower = smaller chunks, more sends/sec, lower latency.
|
|
147279
147493
|
* Higher = fewer sends, less per-call socket overhead. Default 1
|
|
147280
|
-
* = lowest latency
|
|
147494
|
+
* = lowest latency.
|
|
147281
147495
|
*/
|
|
147282
147496
|
intercomBlocksPerPayload: number().int().min(1).max(8).optional(),
|
|
147283
147497
|
/**
|
|
147284
147498
|
* `intercomMaxBacklogMs` — bound on the PCM backlog before the
|
|
147285
|
-
* pump drops oldest samples to cap latency. Default 120ms
|
|
147286
|
-
*
|
|
147499
|
+
* pump drops oldest samples to cap latency. Default 120ms; raise
|
|
147500
|
+
* via the Settings UI on systems where the cross-
|
|
147287
147501
|
* process Opus→PCM path is bursty enough to trigger frequent
|
|
147288
147502
|
* `intercom backlog clamped` warnings.
|
|
147289
147503
|
*/
|
|
@@ -147303,8 +147517,7 @@ var reolinkCameraSchema = object({
|
|
|
147303
147517
|
* instances; this schema only carries connection + debug + the cached
|
|
147304
147518
|
* channels summary so we can re-render the Discovery panel offline.
|
|
147305
147519
|
*
|
|
147306
|
-
*
|
|
147307
|
-
* `storageSettings` (`nvr.ts:49-178`): same scope, same fields, just
|
|
147520
|
+
* The NVR device's own settings scope and fields, just
|
|
147308
147521
|
* adapted to the Zod conventions used elsewhere in this package.
|
|
147309
147522
|
*/
|
|
147310
147523
|
var reolinkHubSchema = object({
|
|
@@ -148085,8 +148298,7 @@ var ReolinkCamera = class ReolinkCamera extends BaseDevice {
|
|
|
148085
148298
|
objectDetectionsSubscribed = false;
|
|
148086
148299
|
/**
|
|
148087
148300
|
* Plugin-level event-health interval — fallback layer over the
|
|
148088
|
-
* lib's internal 5-minute watchdog.
|
|
148089
|
-
* `startEventCheck` (`baichuan-base.ts:719-783`): every 60 s,
|
|
148301
|
+
* lib's internal 5-minute watchdog. The rule: every 60 s,
|
|
148090
148302
|
* if `eventSubscriptionActive` is false on a live socket OR no
|
|
148091
148303
|
* event has arrived in 10 min, force a full unsub/resub cycle.
|
|
148092
148304
|
*/
|
|
@@ -148201,9 +148413,7 @@ var ReolinkCamera = class ReolinkCamera extends BaseDevice {
|
|
|
148201
148413
|
/** Aux accessory references registered by spawned children
|
|
148202
148414
|
* (siren / floodlight / pir). The parent's centralised align
|
|
148203
148415
|
* method iterates these to refresh their slices on a single
|
|
148204
|
-
* cadence — replaces the old per-accessory setInterval.
|
|
148205
|
-
* scrypted-reolink-native's `motionSiren` / `floodlight` / `pir`
|
|
148206
|
-
* field refs + their `alignAuxDevicesState` method. */
|
|
148416
|
+
* cadence — replaces the old per-accessory setInterval. */
|
|
148207
148417
|
auxAccessoryRefs = /* @__PURE__ */ new Map();
|
|
148208
148418
|
/**
|
|
148209
148419
|
* Reliability watchdogs (Slice 10). Both timers are armed after a
|
|
@@ -149008,8 +149218,7 @@ var ReolinkCamera = class ReolinkCamera extends BaseDevice {
|
|
|
149008
149218
|
* Single-flight guard for snapshot fetches (Slice 10). When two
|
|
149009
149219
|
* consumers hit `getSnapshot` concurrently we issue ONE Baichuan
|
|
149010
149220
|
* request and let both await its result — saves a doubled wake on
|
|
149011
|
-
* battery cams and halves load for regular ones.
|
|
149012
|
-
* `takePictureInFlight` in scrypted-reolink-native.
|
|
149221
|
+
* battery cams and halves load for regular ones.
|
|
149013
149222
|
*/
|
|
149014
149223
|
snapshotInFlight = null;
|
|
149015
149224
|
/**
|
|
@@ -151342,9 +151551,8 @@ var ReolinkCamera = class ReolinkCamera extends BaseDevice {
|
|
|
151342
151551
|
};
|
|
151343
151552
|
}
|
|
151344
151553
|
/**
|
|
151345
|
-
* Battery-cam pre-wake hook for the intercom orchestrator
|
|
151346
|
-
*
|
|
151347
|
-
* the current sleep status (passive — no traffic), and if the cam
|
|
151554
|
+
* Battery-cam pre-wake hook for the intercom orchestrator: ask the
|
|
151555
|
+
* lib for the current sleep status (passive — no traffic), and if the cam
|
|
151348
151556
|
* is asleep issue an explicit `wakeUp(channel, {waitAfterWakeMs:2000})`
|
|
151349
151557
|
* + a 1s settle delay before letting the talk-session handshake
|
|
151350
151558
|
* fire. Without this, the handshake against a sleeping UDP/battery
|
|
@@ -151884,7 +152092,7 @@ var ReolinkCamera = class ReolinkCamera extends BaseDevice {
|
|
|
151884
152092
|
/**
|
|
151885
152093
|
* Synthesize the HTTP-FLV pull URL for a (channel, profile) pair. FLV is
|
|
151886
152094
|
* served off the Reolink Baichuan media port (default 1935, app `bcs`) as
|
|
151887
|
-
* `channel<channel>_<profile>.bcs` — the same shape
|
|
152095
|
+
* `channel<channel>_<profile>.bcs` — the same shape go2rtc uses. The
|
|
151888
152096
|
* lib does NOT surface this URL, so we build it from the SAME connection
|
|
151889
152097
|
* creds the RTSP/native paths use (`host`/`username`/`password` on the
|
|
151890
152098
|
* device config), URL-encoding the credentials.
|
|
@@ -152735,9 +152943,8 @@ var ReolinkCamera = class ReolinkCamera extends BaseDevice {
|
|
|
152735
152943
|
/**
|
|
152736
152944
|
* Shared wake-transition handler invoked by both the simpleEvent
|
|
152737
152945
|
* `awake` push (canonical fast path) and the sleep poll's
|
|
152738
|
-
* `sleeping → awake` flip (backstop).
|
|
152739
|
-
*
|
|
152740
|
-
* out the refreshes that depend on the camera being responsive:
|
|
152946
|
+
* `sleeping → awake` flip (backstop). Fan out the refreshes that
|
|
152947
|
+
* depend on the camera being responsive:
|
|
152741
152948
|
* - aux accessories (siren/floodlight/PIR) re-read their
|
|
152742
152949
|
* firmware state via `alignAuxDevicesState('wake')`
|
|
152743
152950
|
* - parent settings snapshot (image / motion / AI / enc / mask /
|
|
@@ -152886,8 +153093,6 @@ var ReolinkCamera = class ReolinkCamera extends BaseDevice {
|
|
|
152886
153093
|
* 3. Register via `onSimpleEvent(handleSimpleEventBound)`.
|
|
152887
153094
|
* Lib starts/refreshes its own subscribe + 5min watchdog.
|
|
152888
153095
|
*
|
|
152889
|
-
* Mirrors `subscribeToEventsInternal` in Scrypted's
|
|
152890
|
-
* `baichuan-base.ts:837-888` — same pattern, same rationale.
|
|
152891
153096
|
*/
|
|
152892
153097
|
async resubscribeSimpleEvents(api, reason) {
|
|
152893
153098
|
try {
|
|
@@ -153764,7 +153969,7 @@ var ReolinkCamera = class ReolinkCamera extends BaseDevice {
|
|
|
153764
153969
|
type: "slider",
|
|
153765
153970
|
key: "intercomBlocksPerPayload",
|
|
153766
153971
|
label: "Blocks per payload",
|
|
153767
|
-
description: "Lower = lower latency (more sendAudio calls/sec). Higher = fewer calls, less per-call socket overhead. Range 1..8. Default 1 (
|
|
153972
|
+
description: "Lower = lower latency (more sendAudio calls/sec). Higher = fewer calls, less per-call socket overhead. Range 1..8. Default 1 (lowest latency).",
|
|
153768
153973
|
min: 1,
|
|
153769
153974
|
max: 8,
|
|
153770
153975
|
step: 1,
|
|
@@ -153776,7 +153981,7 @@ var ReolinkCamera = class ReolinkCamera extends BaseDevice {
|
|
|
153776
153981
|
type: "slider",
|
|
153777
153982
|
key: "intercomMaxBacklogMs",
|
|
153778
153983
|
label: "Max backlog (ms)",
|
|
153779
|
-
description: "Maximum PCM backlog before dropping oldest samples to cap latency. Higher = more stable on slow systems but more latency. Range 20..5000. Default 120
|
|
153984
|
+
description: "Maximum PCM backlog before dropping oldest samples to cap latency. Higher = more stable on slow systems but more latency. Range 20..5000. Default 120.",
|
|
153780
153985
|
min: 20,
|
|
153781
153986
|
max: 5e3,
|
|
153782
153987
|
step: 20,
|
|
@@ -153911,7 +154116,7 @@ var ReolinkCamera = class ReolinkCamera extends BaseDevice {
|
|
|
153911
154116
|
id: "debug",
|
|
153912
154117
|
tab: "advanced",
|
|
153913
154118
|
title: "Debug",
|
|
153914
|
-
description: "Lib-side Baichuan tracing.
|
|
154119
|
+
description: "Lib-side Baichuan tracing. Changing these resets the control-channel client (active streams keep running) so new debug options take effect on the next dial.",
|
|
153915
154120
|
columns: 1,
|
|
153916
154121
|
fields: [{
|
|
153917
154122
|
type: "boolean",
|
|
@@ -154605,9 +154810,8 @@ var ReolinkCamera = class ReolinkCamera extends BaseDevice {
|
|
|
154605
154810
|
return this.loginPromise;
|
|
154606
154811
|
}
|
|
154607
154812
|
/**
|
|
154608
|
-
* Bridge Reolink hardware events to the camstack event bus
|
|
154609
|
-
*
|
|
154610
|
-
* (`camera.ts:1979-2033`): online and sleeping are TWO ORTHOGONAL
|
|
154813
|
+
* Bridge Reolink hardware events to the camstack event bus:
|
|
154814
|
+
* online and sleeping are TWO ORTHOGONAL
|
|
154611
154815
|
* axes, each driven exclusively by their own firmware push events.
|
|
154612
154816
|
*
|
|
154613
154817
|
* - 'motion' + AI types (people, vehicle, animal, face, package):
|
|
@@ -154636,8 +154840,7 @@ var ReolinkCamera = class ReolinkCamera extends BaseDevice {
|
|
|
154636
154840
|
}
|
|
154637
154841
|
/**
|
|
154638
154842
|
* Build the `DebugOptions` blob forwarded to `ReolinkBaichuanApi`'s
|
|
154639
|
-
* constructor.
|
|
154640
|
-
* `camera.ts:1778-1786`. Returns `undefined` when no flags are set
|
|
154843
|
+
* constructor. Returns `undefined` when no flags are set
|
|
154641
154844
|
* so the lib falls back to its own defaults instead of an empty
|
|
154642
154845
|
* object override.
|
|
154643
154846
|
*/
|
|
@@ -154896,8 +155099,7 @@ var ReolinkCamera = class ReolinkCamera extends BaseDevice {
|
|
|
154896
155099
|
* idle UDP socket on its own, the camera is asleep, and there is
|
|
154897
155100
|
* nothing to reconnect to. Aggressively reconnecting in that state
|
|
154898
155101
|
* is what was waking up the doorbell every ~60 s in production
|
|
154899
|
-
* logs.
|
|
154900
|
-
* reference, but DO NOT schedule a reconnect timer. The next
|
|
155102
|
+
* logs. Drop the api reference, but DO NOT schedule a reconnect timer. The next
|
|
154901
155103
|
* `awake` push (or a snapshot demand from the operator) will
|
|
154902
155104
|
* lazily call `ensureApi()` and re-establish the client.
|
|
154903
155105
|
*/
|
|
@@ -155010,8 +155212,8 @@ function isHubLike(d) {
|
|
|
155010
155212
|
* starts at 60s) OR the subscription is genuinely broken / nothing is
|
|
155011
155213
|
* happening in front of the cam (counter rises → backoff lengthens).
|
|
155012
155214
|
*
|
|
155013
|
-
* Schedule: 60s → 2min → 5min → 15min capped
|
|
155014
|
-
*
|
|
155215
|
+
* Schedule: 60s → 2min → 5min → 15min capped — the long-poll backoff
|
|
155216
|
+
* curve this hardware is known to tolerate.
|
|
155015
155217
|
*/
|
|
155016
155218
|
function computeHealthCheckBackoffMs(consecutive) {
|
|
155017
155219
|
if (consecutive <= 1) return 6e4;
|
|
@@ -155155,7 +155357,7 @@ var HUB_RECONNECT_MAX_MS = 3e4;
|
|
|
155155
155357
|
/**
|
|
155156
155358
|
* Reolink Hub / NVR — single Baichuan socket fronting N channels.
|
|
155157
155359
|
*
|
|
155158
|
-
*
|
|
155360
|
+
* The NVR pattern:
|
|
155159
155361
|
* - One persistent control + event socket on the parent (no
|
|
155160
155362
|
* per-channel login).
|
|
155161
155363
|
* - `device-discovery` cap exposes the channel list with status,
|
|
@@ -155308,8 +155510,7 @@ var ReolinkHub = class ReolinkHub extends BaseDevice {
|
|
|
155308
155510
|
}
|
|
155309
155511
|
}
|
|
155310
155512
|
/**
|
|
155311
|
-
* Hub-specific settings form
|
|
155312
|
-
* `ReolinkNativeNvrDevice.storageSettings` block (`nvr.ts:49-178`):
|
|
155513
|
+
* Hub-specific settings form:
|
|
155313
155514
|
* connection (host / port / credentials) on the General tab,
|
|
155314
155515
|
* Baichuan debug flags on Advanced. Per-channel settings (image,
|
|
155315
155516
|
* motion, AI sensitivity, …) live on the adopted child cameras —
|
|
@@ -155401,7 +155602,7 @@ var ReolinkHub = class ReolinkHub extends BaseDevice {
|
|
|
155401
155602
|
id: "debug",
|
|
155402
155603
|
tab: "advanced",
|
|
155403
155604
|
title: "Debug",
|
|
155404
|
-
description: "Lib-side Baichuan tracing.
|
|
155605
|
+
description: "Lib-side Baichuan tracing. Changing these resets the control-channel client (active streams keep running) so new debug options take effect on the next dial.",
|
|
155405
155606
|
columns: 1,
|
|
155406
155607
|
fields: [{
|
|
155407
155608
|
type: "boolean",
|
|
@@ -155564,8 +155765,8 @@ var ReolinkHub = class ReolinkHub extends BaseDevice {
|
|
|
155564
155765
|
}
|
|
155565
155766
|
/**
|
|
155566
155767
|
* Pull the channel list from the Hub via the lib's
|
|
155567
|
-
* `getNvrChannelsSummary({ source: 'cgi' })`. CGI
|
|
155568
|
-
*
|
|
155768
|
+
* `getNvrChannelsSummary({ source: 'cgi' })`. CGI is chosen because
|
|
155769
|
+
* `GetChannelstatus` returns the channel list
|
|
155569
155770
|
* synchronously (no race against the cmd_id 145 push cache that
|
|
155570
155771
|
* can be empty right after login).
|
|
155571
155772
|
*
|
|
@@ -155957,8 +156158,7 @@ var ReolinkHub = class ReolinkHub extends BaseDevice {
|
|
|
155957
156158
|
}
|
|
155958
156159
|
/**
|
|
155959
156160
|
* Dispatches a Hub-received simpleEvent to the matching child's
|
|
155960
|
-
* `handleSimpleEvent`.
|
|
155961
|
-
* `ReolinkNativeNvrDevice.onSimpleEvent` (`nvr.ts:288-319`).
|
|
156161
|
+
* `handleSimpleEvent`.
|
|
155962
156162
|
*/
|
|
155963
156163
|
routeSimpleEvent(ev) {
|
|
155964
156164
|
const channel = ev?.channel;
|
|
@@ -156116,7 +156316,7 @@ function computeChildNativeId(parentStableId, channel, uid) {
|
|
|
156116
156316
|
}
|
|
156117
156317
|
/**
|
|
156118
156318
|
* Map the lib's per-channel summary booleans to our `DiscoveredChildStatus`.
|
|
156119
|
-
* Order of precedence
|
|
156319
|
+
* Order of precedence:
|
|
156120
156320
|
* 1. `online === false` → offline
|
|
156121
156321
|
* 2. `sleeping === true` → sleeping
|
|
156122
156322
|
* 3. anything else with non-empty state → online
|