@camstack/addon-provider-reolink 1.2.174 → 1.2.176
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 +232 -81
- package/dist/addon.mjs +232 -81
- package/package.json +1 -1
package/dist/addon.js
CHANGED
|
@@ -11101,6 +11101,57 @@ var ClipSearchStrictnessSchema = _enum([
|
|
|
11101
11101
|
"balanced",
|
|
11102
11102
|
"strict"
|
|
11103
11103
|
]);
|
|
11104
|
+
new Set([
|
|
11105
|
+
{
|
|
11106
|
+
id: "person",
|
|
11107
|
+
name: "Person"
|
|
11108
|
+
},
|
|
11109
|
+
{
|
|
11110
|
+
id: "vehicle",
|
|
11111
|
+
name: "Vehicle"
|
|
11112
|
+
},
|
|
11113
|
+
{
|
|
11114
|
+
id: "animal",
|
|
11115
|
+
name: "Animal"
|
|
11116
|
+
},
|
|
11117
|
+
{
|
|
11118
|
+
id: "package",
|
|
11119
|
+
name: "Package"
|
|
11120
|
+
}
|
|
11121
|
+
].map((l) => l.id));
|
|
11122
|
+
var COCO_TO_MACRO = {
|
|
11123
|
+
mapping: {
|
|
11124
|
+
person: "person",
|
|
11125
|
+
bicycle: "vehicle",
|
|
11126
|
+
car: "vehicle",
|
|
11127
|
+
motorcycle: "vehicle",
|
|
11128
|
+
airplane: "vehicle",
|
|
11129
|
+
bus: "vehicle",
|
|
11130
|
+
train: "vehicle",
|
|
11131
|
+
truck: "vehicle",
|
|
11132
|
+
boat: "vehicle",
|
|
11133
|
+
bird: "animal",
|
|
11134
|
+
cat: "animal",
|
|
11135
|
+
dog: "animal",
|
|
11136
|
+
horse: "animal",
|
|
11137
|
+
sheep: "animal",
|
|
11138
|
+
cow: "animal",
|
|
11139
|
+
elephant: "animal",
|
|
11140
|
+
bear: "animal",
|
|
11141
|
+
zebra: "animal",
|
|
11142
|
+
giraffe: "animal",
|
|
11143
|
+
suitcase: "package",
|
|
11144
|
+
backpack: "package",
|
|
11145
|
+
handbag: "package"
|
|
11146
|
+
},
|
|
11147
|
+
preserveOriginal: false
|
|
11148
|
+
};
|
|
11149
|
+
/** Steps a root detector may declare it fills. */
|
|
11150
|
+
var FILLABLE_STEP_IDS = [
|
|
11151
|
+
"animal-classifier",
|
|
11152
|
+
"vehicle-classifier",
|
|
11153
|
+
"package-detection"
|
|
11154
|
+
];
|
|
11104
11155
|
var MODEL_FORMATS = [
|
|
11105
11156
|
"onnx",
|
|
11106
11157
|
"coreml",
|
|
@@ -11233,6 +11284,12 @@ var ModelLicenseSchema = preprocess((value) => typeof value === "string" ? { wei
|
|
|
11233
11284
|
/** True when the weights or their data forbid commercial use. */
|
|
11234
11285
|
nonCommercial: boolean().optional()
|
|
11235
11286
|
}));
|
|
11287
|
+
/** One `fillsClassifierEffects` entry — see `ModelCatalogEntry.fillsClassifierEffects`. */
|
|
11288
|
+
var FillsClassifierEffectSchema = object({
|
|
11289
|
+
stepId: _enum(FILLABLE_STEP_IDS),
|
|
11290
|
+
labelToEffect: record(string(), string()),
|
|
11291
|
+
uncovered: array(string()).readonly()
|
|
11292
|
+
});
|
|
11236
11293
|
var ModelCatalogEntrySchema = object({
|
|
11237
11294
|
id: string(),
|
|
11238
11295
|
name: string(),
|
|
@@ -11359,6 +11416,16 @@ var ModelCatalogEntrySchema = object({
|
|
|
11359
11416
|
*/
|
|
11360
11417
|
classMap: DetectionCatalogClassMapSchema.optional(),
|
|
11361
11418
|
/**
|
|
11419
|
+
* The pipeline steps this ROOT detector already does the work of (D715):
|
|
11420
|
+
* its labels name the effect the step exists to produce (`deer` for
|
|
11421
|
+
* `animal-classifier`, `package` for `package-detection`). Derived from the
|
|
11422
|
+
* labelmap by `deriveClassifierFills`, never hand-written; a COCO model
|
|
11423
|
+
* declares none. Whether a declaration is honoured is the step's own
|
|
11424
|
+
* `labelLink` policy (`resolveLabelLink`). `labelToEffect` values are in
|
|
11425
|
+
* `FILLABLE_STEP_VOCABULARIES` (guard `check-label-link-vocabulary`).
|
|
11426
|
+
*/
|
|
11427
|
+
fillsClassifierEffects: array(FillsClassifierEffectSchema).readonly().optional(),
|
|
11428
|
+
/**
|
|
11362
11429
|
* The model's CLIP feature-space contract (text encoder, dimension, vector
|
|
11363
11430
|
* index, token window, search floor) — see `clip-model.ts`. Present ONLY on a
|
|
11364
11431
|
* CLIP image encoder; its absence is what "not a CLIP model" means to the
|
|
@@ -14831,7 +14898,7 @@ DeviceType.Camera;
|
|
|
14831
14898
|
* This matters here more than anywhere else in the repo, because every provider
|
|
14832
14899
|
* that knows a device's host knows its PASSWORD too: `{ host, port, username,
|
|
14833
14900
|
* password }` sit in one object on Hikvision, Amcrest, Reolink and ONVIF alike,
|
|
14834
|
-
* and `http://admin:hunter2@192.168.
|
|
14901
|
+
* and `http://admin:hunter2@192.168.60.139/` is a URL a browser accepts. The
|
|
14835
14902
|
* camera's own page will ask for its own login. That is correct, and pre-
|
|
14836
14903
|
* filling it is the operator's business, not ours.
|
|
14837
14904
|
*
|
|
@@ -18722,51 +18789,6 @@ method(object({}), array(TargetKindSchema)), method(object({}), array(TargetSche
|
|
|
18722
18789
|
kind: "mutation",
|
|
18723
18790
|
auth: "admin"
|
|
18724
18791
|
});
|
|
18725
|
-
new Set([
|
|
18726
|
-
{
|
|
18727
|
-
id: "person",
|
|
18728
|
-
name: "Person"
|
|
18729
|
-
},
|
|
18730
|
-
{
|
|
18731
|
-
id: "vehicle",
|
|
18732
|
-
name: "Vehicle"
|
|
18733
|
-
},
|
|
18734
|
-
{
|
|
18735
|
-
id: "animal",
|
|
18736
|
-
name: "Animal"
|
|
18737
|
-
},
|
|
18738
|
-
{
|
|
18739
|
-
id: "package",
|
|
18740
|
-
name: "Package"
|
|
18741
|
-
}
|
|
18742
|
-
].map((l) => l.id));
|
|
18743
|
-
var COCO_TO_MACRO = {
|
|
18744
|
-
mapping: {
|
|
18745
|
-
person: "person",
|
|
18746
|
-
bicycle: "vehicle",
|
|
18747
|
-
car: "vehicle",
|
|
18748
|
-
motorcycle: "vehicle",
|
|
18749
|
-
airplane: "vehicle",
|
|
18750
|
-
bus: "vehicle",
|
|
18751
|
-
train: "vehicle",
|
|
18752
|
-
truck: "vehicle",
|
|
18753
|
-
boat: "vehicle",
|
|
18754
|
-
bird: "animal",
|
|
18755
|
-
cat: "animal",
|
|
18756
|
-
dog: "animal",
|
|
18757
|
-
horse: "animal",
|
|
18758
|
-
sheep: "animal",
|
|
18759
|
-
cow: "animal",
|
|
18760
|
-
elephant: "animal",
|
|
18761
|
-
bear: "animal",
|
|
18762
|
-
zebra: "animal",
|
|
18763
|
-
giraffe: "animal",
|
|
18764
|
-
suitcase: "package",
|
|
18765
|
-
backpack: "package",
|
|
18766
|
-
handbag: "package"
|
|
18767
|
-
},
|
|
18768
|
-
preserveOriginal: false
|
|
18769
|
-
};
|
|
18770
18792
|
var AUDIO_MACRO_LABELS = [
|
|
18771
18793
|
{
|
|
18772
18794
|
id: "speech",
|
|
@@ -20660,8 +20682,9 @@ var NcRuleSchema = NcRuleInputSchema.extend({
|
|
|
20660
20682
|
disabledTargetIds: array(string()).default([])
|
|
20661
20683
|
});
|
|
20662
20684
|
/**
|
|
20663
|
-
* The state-summary SECTIONS (D647 / D698): the D637 kind groups that
|
|
20664
|
-
* still-true state. `
|
|
20685
|
+
* The state-summary SECTIONS (D647 / D698 / D708): the D637 kind groups that
|
|
20686
|
+
* report a still-true state. `addons` is the crash-looped addons only and
|
|
20687
|
+
* `addon-updates` the addons that are behind (D708 split them). `backups-exports` and `alarm` are not sections — a completed
|
|
20665
20688
|
* job is not an open state, and the alarm stays instant.
|
|
20666
20689
|
*/
|
|
20667
20690
|
var NcStateSummarySectionIdSchema = _enum([
|
|
@@ -20673,6 +20696,7 @@ var NcStateSummarySectionIdSchema = _enum([
|
|
|
20673
20696
|
"detection-blind",
|
|
20674
20697
|
"nodes",
|
|
20675
20698
|
"addons",
|
|
20699
|
+
"addon-updates",
|
|
20676
20700
|
"updates"
|
|
20677
20701
|
]);
|
|
20678
20702
|
/** One section of a previewed state summary. `unavailable` = its state could not be read. */
|
|
@@ -21153,7 +21177,19 @@ var NcAlarmModeDelaysListSchema = array(object({
|
|
|
21153
21177
|
* When this mode may be armed. Absent / null = always allowed (same as a
|
|
21154
21178
|
* rule with no `schedule`). Evaluated with {@link isScheduleActive}.
|
|
21155
21179
|
*/
|
|
21156
|
-
schedule: NcScheduleSchema.optional()
|
|
21180
|
+
schedule: NcScheduleSchema.optional(),
|
|
21181
|
+
/**
|
|
21182
|
+
* D706: while this mode's ENTRY DELAY runs, do the alarm rules' own pushes go out (as an
|
|
21183
|
+
* intrusion naming the locations)? Absent = false — the entry-delay notification is the
|
|
21184
|
+
* only one, and the matches ride the triggered notification's mosaic (D705).
|
|
21185
|
+
*/
|
|
21186
|
+
notifyDuringEntryDelay: boolean().optional(),
|
|
21187
|
+
/**
|
|
21188
|
+
* D706: notify "watched again" when a sensor this arm bypassed closes and opens again.
|
|
21189
|
+
* Absent = false (logged, not sent). Even when true it is not sent when that same sensor
|
|
21190
|
+
* is the one that starts the entry delay — the entry-delay notification already names it.
|
|
21191
|
+
*/
|
|
21192
|
+
notifySensorRewatched: boolean().optional()
|
|
21157
21193
|
})).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
|
|
21158
21194
|
var NcAlarmModeDelaysEditListSchema = array(object({
|
|
21159
21195
|
mode: AlarmArmModeSchema,
|
|
@@ -21162,7 +21198,11 @@ var NcAlarmModeDelaysEditListSchema = array(object({
|
|
|
21162
21198
|
triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional(),
|
|
21163
21199
|
postTriggeredAction: NcAlarmPostTriggeredActionSchema.nullable().optional(),
|
|
21164
21200
|
/** Set a schedule, or `null` to clear (mode always allowed again). */
|
|
21165
|
-
schedule: NcScheduleSchema.nullable().optional()
|
|
21201
|
+
schedule: NcScheduleSchema.nullable().optional(),
|
|
21202
|
+
/** D706: set the switch, or `null` to clear it (back to the default, false). */
|
|
21203
|
+
notifyDuringEntryDelay: boolean().nullable().optional(),
|
|
21204
|
+
/** D706: set the switch, or `null` to clear it (back to the default, false). */
|
|
21205
|
+
notifySensorRewatched: boolean().nullable().optional()
|
|
21166
21206
|
})).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
|
|
21167
21207
|
/** One switch of the alarm table: put ONE device on, or take it off, ONE mode's list. */
|
|
21168
21208
|
var NcAlarmNonBlockingEditSchema = object({
|
|
@@ -24190,7 +24230,8 @@ var PipelineModelOptionSchema = object({
|
|
|
24190
24230
|
group: ModelVariantGroupSchema.optional(),
|
|
24191
24231
|
legacy: boolean().optional(),
|
|
24192
24232
|
provider: ModelProviderIdSchema.optional(),
|
|
24193
|
-
defaultConfidence: number().optional()
|
|
24233
|
+
defaultConfidence: number().optional(),
|
|
24234
|
+
fillsClassifierEffects: array(FillsClassifierEffectSchema).readonly().optional()
|
|
24194
24235
|
});
|
|
24195
24236
|
var ConfigFieldBridge = custom();
|
|
24196
24237
|
var PipelineAddonSchemaSchema = object({
|
|
@@ -25023,6 +25064,22 @@ var MotionSourceEnum = _enum([
|
|
|
25023
25064
|
"device-activity"
|
|
25024
25065
|
]);
|
|
25025
25066
|
/**
|
|
25067
|
+
* What opened an on-motion detection SESSION: the motion source that passed the
|
|
25068
|
+
* camera's `motionSources` gate, and what raised it (the camera itself, or a
|
|
25069
|
+
* sensor the operator attached — D672). `sensorName` is the attached sensor's
|
|
25070
|
+
* device name as the orchestrator's camera-sensors resolution last read it;
|
|
25071
|
+
* absent when unknown or when the camera itself triggered.
|
|
25072
|
+
*
|
|
25073
|
+
* Carried on the session attach ONLY so the runner's `DetectionPhaseTransition`
|
|
25074
|
+
* can say what started the session (D672 rule 11, amended 2026-10-06). The
|
|
25075
|
+
* runner never decides anything on it.
|
|
25076
|
+
*/
|
|
25077
|
+
var SessionTriggerSchema = object({
|
|
25078
|
+
source: MotionSourceEnum,
|
|
25079
|
+
triggeredBy: MotionTriggeredBySchema,
|
|
25080
|
+
sensorName: string().optional()
|
|
25081
|
+
});
|
|
25082
|
+
/**
|
|
25026
25083
|
* List of motion sources active on a camera. Empty array is valid:
|
|
25027
25084
|
* "no source" — happens for battery cams without firmware motion when
|
|
25028
25085
|
* the operator hasn't opted into the SW analyzer (would hold the
|
|
@@ -25274,6 +25331,14 @@ var RunnerCameraConfigSchema = object({
|
|
|
25274
25331
|
*/
|
|
25275
25332
|
motionSources: MotionSourcesSchema.default(["analyzer"]),
|
|
25276
25333
|
/**
|
|
25334
|
+
* What opened this attach, on a SESSION attach only (see
|
|
25335
|
+
* {@link SessionTriggerSchema}). OPTIONAL with no default: absent on a
|
|
25336
|
+
* standing attach, an occupancy burst, a re-dispatch with no motion event
|
|
25337
|
+
* behind it, and every attach from an orchestrator older than the field — the
|
|
25338
|
+
* runner then names no source on the phase event.
|
|
25339
|
+
*/
|
|
25340
|
+
sessionTrigger: SessionTriggerSchema.optional(),
|
|
25341
|
+
/**
|
|
25277
25342
|
* WHICH root detector runs for this camera. The detection counterpart of
|
|
25278
25343
|
* {@link motionSources}, same shape and same discipline: a per-camera list
|
|
25279
25344
|
* of sources the system understands, vendor-agnostic, owned here.
|
|
@@ -33184,7 +33249,7 @@ var LocalInterfaceSchema = object({
|
|
|
33184
33249
|
name: string(),
|
|
33185
33250
|
family: _enum(["IPv4", "IPv6"]),
|
|
33186
33251
|
address: string(),
|
|
33187
|
-
/** CIDR shorthand (e.g. `192.168.
|
|
33252
|
+
/** CIDR shorthand (e.g. `192.168.10.10/24`). Empty when OS doesn't expose. */
|
|
33188
33253
|
cidr: string(),
|
|
33189
33254
|
/** OS netmask. Stable across calls so the SDK can hash on it. */
|
|
33190
33255
|
netmask: string(),
|
|
@@ -33238,7 +33303,8 @@ var ConnectionEndpointSchema = object({
|
|
|
33238
33303
|
"lan-ipv4",
|
|
33239
33304
|
"lan-ipv6",
|
|
33240
33305
|
"public",
|
|
33241
|
-
"loopback"
|
|
33306
|
+
"loopback",
|
|
33307
|
+
"app-link"
|
|
33242
33308
|
]),
|
|
33243
33309
|
/**
|
|
33244
33310
|
* Originating-interface kind — `lan`/`wifi`/`docker`/`vpn`/`other`/
|
|
@@ -33307,15 +33373,27 @@ var GetConnectionEndpointsResultSchema = object({
|
|
|
33307
33373
|
localPort: AdvertisedLocalPortSchema
|
|
33308
33374
|
});
|
|
33309
33375
|
/**
|
|
33310
|
-
* The
|
|
33311
|
-
*
|
|
33312
|
-
*
|
|
33376
|
+
* The address flagged for notification links. `baseUrl: null` = AUTO, which
|
|
33377
|
+
* since D709 is the CamStack app link; `resolved` reports the effective value,
|
|
33378
|
+
* so the UI can show it either way.
|
|
33313
33379
|
*/
|
|
33314
33380
|
var NotificationEndpointSchema = object({
|
|
33315
33381
|
/** The operator's explicit choice, or null for AUTO. */
|
|
33316
33382
|
baseUrl: string().nullable(),
|
|
33317
|
-
/**
|
|
33318
|
-
|
|
33383
|
+
/**
|
|
33384
|
+
* The effective flagged address: the explicit choice, else (AUTO) the
|
|
33385
|
+
* CamStack app link `https://camstack.zentik.app` (D709). A pre-D709 hub
|
|
33386
|
+
* answered the public tunnel / mesh here, or null.
|
|
33387
|
+
*/
|
|
33388
|
+
resolved: string().nullable(),
|
|
33389
|
+
/**
|
|
33390
|
+
* The hub origin an app link carries as `hub=` (D709): the hub's best
|
|
33391
|
+
* public HTTPS address — the tunnel, then the mesh (Tailscale MagicDNS) —
|
|
33392
|
+
* picked from this cap's own palette by `pickAppLinkHub`. `null` when the
|
|
33393
|
+
* hub advertises neither; the app link is then minted without `hub=`.
|
|
33394
|
+
* Absent on a pre-D709 hub.
|
|
33395
|
+
*/
|
|
33396
|
+
appLinkHub: string().nullable()
|
|
33319
33397
|
});
|
|
33320
33398
|
/**
|
|
33321
33399
|
* The URLs the SDK / viewer should race for API access. `baseUrls` empty =
|
|
@@ -33369,7 +33447,11 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
|
|
|
33369
33447
|
* Pass `'https'` when the caller is itself loaded over HTTPS
|
|
33370
33448
|
* to avoid mixed-content blocks in the browser. The public
|
|
33371
33449
|
* tunnel always emits `https://` regardless. */
|
|
33372
|
-
scheme: _enum(["http", "https"]).optional()
|
|
33450
|
+
scheme: _enum(["http", "https"]).optional(),
|
|
33451
|
+
/** Append the CamStack app link entry (`kind: 'app-link'`, D709) —
|
|
33452
|
+
* an address notification links can be flagged with, not a hub
|
|
33453
|
+
* route. Default `false`: racers and rankers never see it. */
|
|
33454
|
+
includeAppLink: boolean().optional()
|
|
33373
33455
|
}), GetConnectionEndpointsResultSchema), method(_void(), NotificationEndpointSchema), method(object({ baseUrl: string().nullable() }), NotificationEndpointSchema, { kind: "mutation" }), method(_void(), ViewerEndpointsSchema), method(object({ baseUrls: array(string()).readonly() }), ViewerEndpointsSchema, { kind: "mutation" }), method(_void(), AllowedAddressesSchema), method(AllowedAddressesSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), AllowedAddressesSchema, { kind: "mutation" }), method(_void(), TlsStatusSchema), method(object({ reason: string().optional() }), TlsStatusSchema, {
|
|
33374
33456
|
kind: "mutation",
|
|
33375
33457
|
auth: "admin"
|
|
@@ -33698,7 +33780,7 @@ var MeshPeerSchema = object({
|
|
|
33698
33780
|
tags: array(string()).readonly(),
|
|
33699
33781
|
/** True when the peer advertises itself as an exit-node candidate. */
|
|
33700
33782
|
exitNodeOption: boolean(),
|
|
33701
|
-
/** Subnet routes the peer advertises (e.g. `["192.168.
|
|
33783
|
+
/** Subnet routes the peer advertises (e.g. `["192.168.10.0/24"]`). */
|
|
33702
33784
|
advertisedRoutes: array(string()).readonly(),
|
|
33703
33785
|
/** Owner account login (e.g. `foo@example.com`). Null for tagged peers. */
|
|
33704
33786
|
userLogin: string().nullable(),
|
|
@@ -54129,12 +54211,14 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
|
|
|
54129
54211
|
{
|
|
54130
54212
|
id: "addons",
|
|
54131
54213
|
family: "system",
|
|
54132
|
-
label: "Addons",
|
|
54133
|
-
kinds: [
|
|
54134
|
-
|
|
54135
|
-
|
|
54136
|
-
|
|
54137
|
-
|
|
54214
|
+
label: "Addons stopped",
|
|
54215
|
+
kinds: ["addon-crash-loop"]
|
|
54216
|
+
},
|
|
54217
|
+
{
|
|
54218
|
+
id: "addon-updates",
|
|
54219
|
+
family: "system",
|
|
54220
|
+
label: "Addon updates",
|
|
54221
|
+
kinds: ["addon-update-available", "addon-updated"]
|
|
54138
54222
|
},
|
|
54139
54223
|
{
|
|
54140
54224
|
id: "updates",
|
|
@@ -54294,13 +54378,15 @@ var STATE_SUMMARY_SECTION_VARS = [
|
|
|
54294
54378
|
},
|
|
54295
54379
|
{
|
|
54296
54380
|
name: "summaryAddons",
|
|
54297
|
-
label: "Summary: addons",
|
|
54298
|
-
example: "
|
|
54299
|
-
kinds: [
|
|
54300
|
-
|
|
54301
|
-
|
|
54302
|
-
|
|
54303
|
-
|
|
54381
|
+
label: "Summary: addons stopped",
|
|
54382
|
+
example: "hub — recorder stopped after repeated crashes",
|
|
54383
|
+
kinds: ["addon-crash-loop"]
|
|
54384
|
+
},
|
|
54385
|
+
{
|
|
54386
|
+
name: "summaryAddonUpdates",
|
|
54387
|
+
label: "Summary: addon updates",
|
|
54388
|
+
example: "hub:\n• @camstack/addon-recorder 1.2.3 → 1.2.4",
|
|
54389
|
+
kinds: ["addon-update-available", "addon-updated"]
|
|
54304
54390
|
},
|
|
54305
54391
|
{
|
|
54306
54392
|
name: "summaryUpdates",
|
|
@@ -54384,6 +54470,7 @@ var STATE_SUMMARY_VARS = [
|
|
|
54384
54470
|
[...RULE_BODY_ONLY],
|
|
54385
54471
|
[...RULE_TEXT],
|
|
54386
54472
|
([...RULE_TEXT], [...DEVICE_EVENTS]),
|
|
54473
|
+
([...RULE_TEXT], [...COMBINED_ALARM]),
|
|
54387
54474
|
([...RULE_TEXT], [...DEVICE_EVENTS]),
|
|
54388
54475
|
([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
|
|
54389
54476
|
([...RULE_TEXT], [...CONSUMABLE]),
|
|
@@ -166246,6 +166333,37 @@ function buildSyntheticRfc4571Sdp(input) {
|
|
|
166246
166333
|
function buildLazyRfc4571Url(camStreamId) {
|
|
166247
166334
|
return `lazy:rfc4571:${encodeURIComponent(camStreamId)}`;
|
|
166248
166335
|
}
|
|
166336
|
+
function createMotionSensorTracker(now = Date.now) {
|
|
166337
|
+
const latest = /* @__PURE__ */ new Map();
|
|
166338
|
+
return {
|
|
166339
|
+
observe(event) {
|
|
166340
|
+
if (event.type !== "motion") return;
|
|
166341
|
+
const sensor = event.motion.source;
|
|
166342
|
+
if (sensor === void 0) return;
|
|
166343
|
+
latest.set(event.channel, {
|
|
166344
|
+
sensor,
|
|
166345
|
+
at: now()
|
|
166346
|
+
});
|
|
166347
|
+
},
|
|
166348
|
+
take(channel) {
|
|
166349
|
+
const entry = latest.get(channel);
|
|
166350
|
+
if (!entry) return null;
|
|
166351
|
+
latest.delete(channel);
|
|
166352
|
+
return now() - entry.at <= 2e3 ? entry.sensor : null;
|
|
166353
|
+
}
|
|
166354
|
+
};
|
|
166355
|
+
}
|
|
166356
|
+
var isMotionSensor = (value) => value === "md" || value === "pir" || value === "unknown";
|
|
166357
|
+
/**
|
|
166358
|
+
* The sensor a simple event states itself, for a library version that forwards
|
|
166359
|
+
* `motion.source` on the simple event; `null` for the versions that do not.
|
|
166360
|
+
*/
|
|
166361
|
+
function motionSensorOnSimpleEvent(event) {
|
|
166362
|
+
if (!("motion" in event)) return null;
|
|
166363
|
+
const motion = event.motion;
|
|
166364
|
+
if (typeof motion !== "object" || motion === null || !("source" in motion)) return null;
|
|
166365
|
+
return isMotionSensor(motion.source) ? motion.source : null;
|
|
166366
|
+
}
|
|
166249
166367
|
//#endregion
|
|
166250
166368
|
//#region src/reolink-camera.ts
|
|
166251
166369
|
/**
|
|
@@ -166552,6 +166670,16 @@ var ReolinkCamera = class ReolinkCamera extends BaseDevice {
|
|
|
166552
166670
|
this.handleSimpleEvent(event);
|
|
166553
166671
|
};
|
|
166554
166672
|
/**
|
|
166673
|
+
* MD vs PIR of this camera's own motion pushes. The lib's simple event drops
|
|
166674
|
+
* it, so the raw client `event` is observed — PREPENDED, so the sensor is
|
|
166675
|
+
* recorded before the API maps the same emit into the simple event
|
|
166676
|
+
* (`motion-sensor-source.ts`). Hub children get theirs from the hub.
|
|
166677
|
+
*/
|
|
166678
|
+
motionSensors = createMotionSensorTracker();
|
|
166679
|
+
observeRawEventBound = (event) => {
|
|
166680
|
+
this.motionSensors.observe(event);
|
|
166681
|
+
};
|
|
166682
|
+
/**
|
|
166555
166683
|
* Stable bound handler for `api.onObjectDetections` — created ONCE so
|
|
166556
166684
|
* every `onObjectDetections` / `offObjectDetections` call uses the
|
|
166557
166685
|
* SAME function reference (same listener-Set dedup rationale as
|
|
@@ -171953,6 +172081,11 @@ var ReolinkCamera = class ReolinkCamera extends BaseDevice {
|
|
|
171953
172081
|
this.ctx.logger.debug("Reolink event watchdog re-subscribe failed", { meta: { error: err instanceof Error ? err.message : String(err) } });
|
|
171954
172082
|
}
|
|
171955
172083
|
}
|
|
172084
|
+
/** Off-then-prepend, so a re-attached api never carries two observers. */
|
|
172085
|
+
observeMotionSensors(api) {
|
|
172086
|
+
api.client.off("event", this.observeRawEventBound);
|
|
172087
|
+
api.client.prependListener("event", this.observeRawEventBound);
|
|
172088
|
+
}
|
|
171956
172089
|
/**
|
|
171957
172090
|
* Subscribe (or re-subscribe) `handleSimpleEventBound` against
|
|
171958
172091
|
* the Baichuan API. Single-source-of-truth for the listener
|
|
@@ -172288,7 +172421,7 @@ var ReolinkCamera = class ReolinkCamera extends BaseDevice {
|
|
|
172288
172421
|
key: "host",
|
|
172289
172422
|
label: "Camera IP",
|
|
172290
172423
|
required: true,
|
|
172291
|
-
placeholder: "192.168.
|
|
172424
|
+
placeholder: "192.168.10.100"
|
|
172292
172425
|
},
|
|
172293
172426
|
{
|
|
172294
172427
|
type: "number",
|
|
@@ -173547,6 +173680,7 @@ var ReolinkCamera = class ReolinkCamera extends BaseDevice {
|
|
|
173547
173680
|
adoptApi(api) {
|
|
173548
173681
|
this.api = api;
|
|
173549
173682
|
this.reconnectAttempts = 0;
|
|
173683
|
+
this.observeMotionSensors(api);
|
|
173550
173684
|
api.client.on("close", () => this.scheduleReconnect("close"));
|
|
173551
173685
|
api.client.on("error", (err) => {
|
|
173552
173686
|
this.ctx.logger.warn("Baichuan client error — scheduling reconnect", {
|
|
@@ -173694,6 +173828,7 @@ var ReolinkCamera = class ReolinkCamera extends BaseDevice {
|
|
|
173694
173828
|
meta: { error: err instanceof Error ? err.message : String(err) }
|
|
173695
173829
|
});
|
|
173696
173830
|
});
|
|
173831
|
+
this.observeMotionSensors(api);
|
|
173697
173832
|
api.client.on("close", () => this.scheduleReconnect("close"));
|
|
173698
173833
|
api.client.on("error", (err) => {
|
|
173699
173834
|
this.ctx.logger.warn("Baichuan client error — scheduling reconnect", {
|
|
@@ -173763,8 +173898,9 @@ var ReolinkCamera = class ReolinkCamera extends BaseDevice {
|
|
|
173763
173898
|
* when the camera lives under a Hub and inherits the parent's
|
|
173764
173899
|
* single subscription.
|
|
173765
173900
|
*/
|
|
173766
|
-
handleSimpleEvent(event) {
|
|
173901
|
+
handleSimpleEvent(event, routedMotionSensor = null) {
|
|
173767
173902
|
this.lastEventAt = Date.now();
|
|
173903
|
+
const motionSensor = event.type === "motion" ? motionSensorOnSimpleEvent(event) ?? routedMotionSensor ?? this.motionSensors.take(event.channel) : null;
|
|
173768
173904
|
this.consecutiveStaleHealthChecks = 0;
|
|
173769
173905
|
this.nextEventHealthCheckAt = 0;
|
|
173770
173906
|
this.markPassiveContact();
|
|
@@ -173783,7 +173919,8 @@ var ReolinkCamera = class ReolinkCamera extends BaseDevice {
|
|
|
173783
173919
|
type: event.type,
|
|
173784
173920
|
channel: event.channel,
|
|
173785
173921
|
timestamp: event.timestamp,
|
|
173786
|
-
source: event.source
|
|
173922
|
+
source: event.source,
|
|
173923
|
+
...event.type === "motion" ? { motionSensor } : {}
|
|
173787
173924
|
} });
|
|
173788
173925
|
if (event.type === "motion") {
|
|
173789
173926
|
const now = Date.now();
|
|
@@ -174342,6 +174479,17 @@ var ReolinkHub = class ReolinkHub extends BaseDevice {
|
|
|
174342
174479
|
handleSimpleEventBound = (ev) => {
|
|
174343
174480
|
this.routeSimpleEvent(ev);
|
|
174344
174481
|
};
|
|
174482
|
+
/** MD vs PIR per channel, read off the raw client event the lib's simple
|
|
174483
|
+
* event drops (`motion-sensor-source.ts`) and handed to the child. */
|
|
174484
|
+
motionSensors = createMotionSensorTracker();
|
|
174485
|
+
observeRawEventBound = (ev) => {
|
|
174486
|
+
this.motionSensors.observe(ev);
|
|
174487
|
+
};
|
|
174488
|
+
/** Off-then-prepend: recorded before the API maps the same emit. */
|
|
174489
|
+
observeMotionSensors(api) {
|
|
174490
|
+
api.client.off("event", this.observeRawEventBound);
|
|
174491
|
+
api.client.prependListener("event", this.observeRawEventBound);
|
|
174492
|
+
}
|
|
174345
174493
|
constructor(ctx) {
|
|
174346
174494
|
super(ctx, reolinkHubSchema, { type: DeviceType.Hub });
|
|
174347
174495
|
this.registerDeviceDiscovery();
|
|
@@ -174494,7 +174642,7 @@ var ReolinkHub = class ReolinkHub extends BaseDevice {
|
|
|
174494
174642
|
key: "host",
|
|
174495
174643
|
label: "Hub IP",
|
|
174496
174644
|
required: true,
|
|
174497
|
-
placeholder: "192.168.
|
|
174645
|
+
placeholder: "192.168.10.100"
|
|
174498
174646
|
},
|
|
174499
174647
|
{
|
|
174500
174648
|
type: "number",
|
|
@@ -175105,6 +175253,7 @@ var ReolinkHub = class ReolinkHub extends BaseDevice {
|
|
|
175105
175253
|
routeSimpleEvent(ev) {
|
|
175106
175254
|
const channel = ev?.channel;
|
|
175107
175255
|
if (typeof channel !== "number") return;
|
|
175256
|
+
const motionSensor = ev.type === "motion" ? this.motionSensors.take(channel) : null;
|
|
175108
175257
|
const deviceId = this.channelToDeviceId.get(channel);
|
|
175109
175258
|
if (deviceId === void 0) {
|
|
175110
175259
|
const last = this.unroutedChannelLoggedAt.get(channel) ?? 0;
|
|
@@ -175134,7 +175283,7 @@ var ReolinkHub = class ReolinkHub extends BaseDevice {
|
|
|
175134
175283
|
deviceId: child.id,
|
|
175135
175284
|
name: child.name
|
|
175136
175285
|
} });
|
|
175137
|
-
child.handleSimpleEvent(ev);
|
|
175286
|
+
child.handleSimpleEvent(ev, motionSensor);
|
|
175138
175287
|
}).catch((err) => {
|
|
175139
175288
|
this.ctx.logger.debug("Hub simpleEvent dispatch failed", { meta: {
|
|
175140
175289
|
channel,
|
|
@@ -175178,6 +175327,7 @@ var ReolinkHub = class ReolinkHub extends BaseDevice {
|
|
|
175178
175327
|
try {
|
|
175179
175328
|
await api.offSimpleEvent(this.handleSimpleEventBound);
|
|
175180
175329
|
} catch {}
|
|
175330
|
+
this.observeMotionSensors(api);
|
|
175181
175331
|
await api.onSimpleEvent(this.handleSimpleEventBound);
|
|
175182
175332
|
api.client.on("close", () => this.scheduleReconnect("socket-close"));
|
|
175183
175333
|
api.client.on("error", (err) => {
|
|
@@ -175236,6 +175386,7 @@ var ReolinkHub = class ReolinkHub extends BaseDevice {
|
|
|
175236
175386
|
this.api = api;
|
|
175237
175387
|
this.reconnectAttempts = 0;
|
|
175238
175388
|
this.markOnline(true);
|
|
175389
|
+
this.observeMotionSensors(api);
|
|
175239
175390
|
api.client.on("close", () => this.scheduleReconnect("socket-close"));
|
|
175240
175391
|
api.client.on("error", (err) => {
|
|
175241
175392
|
this.ctx.logger.warn("Reolink Hub adopted socket error", { meta: { error: err instanceof Error ? err.message : String(err) } });
|
|
@@ -175328,7 +175479,7 @@ function buildDiscoveryParamsFormSchema() {
|
|
|
175328
175479
|
}, {
|
|
175329
175480
|
id: "scan",
|
|
175330
175481
|
title: "Scan options",
|
|
175331
|
-
description: "Leave the network blank to scan the local subnet. To find cameras on a different subnet, enter its CIDR (e.g. 192.168.
|
|
175482
|
+
description: "Leave the network blank to scan the local subnet. To find cameras on a different subnet, enter its CIDR (e.g. 192.168.20.0/24).",
|
|
175332
175483
|
columns: 1,
|
|
175333
175484
|
fields: [
|
|
175334
175485
|
{
|
|
@@ -175336,7 +175487,7 @@ function buildDiscoveryParamsFormSchema() {
|
|
|
175336
175487
|
key: "networkCidr",
|
|
175337
175488
|
label: "Network (CIDR)",
|
|
175338
175489
|
required: false,
|
|
175339
|
-
placeholder: "192.168.
|
|
175490
|
+
placeholder: "192.168.20.0/24"
|
|
175340
175491
|
},
|
|
175341
175492
|
{
|
|
175342
175493
|
type: "boolean",
|
|
@@ -175420,7 +175571,7 @@ function buildCreationFormSchema() {
|
|
|
175420
175571
|
key: "host",
|
|
175421
175572
|
label: "Host (IP / hostname / UID)",
|
|
175422
175573
|
required: true,
|
|
175423
|
-
placeholder: "192.168.
|
|
175574
|
+
placeholder: "192.168.10.100",
|
|
175424
175575
|
description: "For UDP-only mode you can leave the host blank and supply the camera UID below — the library will discover it on the network.",
|
|
175425
175576
|
inputType: "text"
|
|
175426
175577
|
},
|
package/dist/addon.mjs
CHANGED
|
@@ -11093,6 +11093,57 @@ var ClipSearchStrictnessSchema = _enum([
|
|
|
11093
11093
|
"balanced",
|
|
11094
11094
|
"strict"
|
|
11095
11095
|
]);
|
|
11096
|
+
new Set([
|
|
11097
|
+
{
|
|
11098
|
+
id: "person",
|
|
11099
|
+
name: "Person"
|
|
11100
|
+
},
|
|
11101
|
+
{
|
|
11102
|
+
id: "vehicle",
|
|
11103
|
+
name: "Vehicle"
|
|
11104
|
+
},
|
|
11105
|
+
{
|
|
11106
|
+
id: "animal",
|
|
11107
|
+
name: "Animal"
|
|
11108
|
+
},
|
|
11109
|
+
{
|
|
11110
|
+
id: "package",
|
|
11111
|
+
name: "Package"
|
|
11112
|
+
}
|
|
11113
|
+
].map((l) => l.id));
|
|
11114
|
+
var COCO_TO_MACRO = {
|
|
11115
|
+
mapping: {
|
|
11116
|
+
person: "person",
|
|
11117
|
+
bicycle: "vehicle",
|
|
11118
|
+
car: "vehicle",
|
|
11119
|
+
motorcycle: "vehicle",
|
|
11120
|
+
airplane: "vehicle",
|
|
11121
|
+
bus: "vehicle",
|
|
11122
|
+
train: "vehicle",
|
|
11123
|
+
truck: "vehicle",
|
|
11124
|
+
boat: "vehicle",
|
|
11125
|
+
bird: "animal",
|
|
11126
|
+
cat: "animal",
|
|
11127
|
+
dog: "animal",
|
|
11128
|
+
horse: "animal",
|
|
11129
|
+
sheep: "animal",
|
|
11130
|
+
cow: "animal",
|
|
11131
|
+
elephant: "animal",
|
|
11132
|
+
bear: "animal",
|
|
11133
|
+
zebra: "animal",
|
|
11134
|
+
giraffe: "animal",
|
|
11135
|
+
suitcase: "package",
|
|
11136
|
+
backpack: "package",
|
|
11137
|
+
handbag: "package"
|
|
11138
|
+
},
|
|
11139
|
+
preserveOriginal: false
|
|
11140
|
+
};
|
|
11141
|
+
/** Steps a root detector may declare it fills. */
|
|
11142
|
+
var FILLABLE_STEP_IDS = [
|
|
11143
|
+
"animal-classifier",
|
|
11144
|
+
"vehicle-classifier",
|
|
11145
|
+
"package-detection"
|
|
11146
|
+
];
|
|
11096
11147
|
var MODEL_FORMATS = [
|
|
11097
11148
|
"onnx",
|
|
11098
11149
|
"coreml",
|
|
@@ -11225,6 +11276,12 @@ var ModelLicenseSchema = preprocess((value) => typeof value === "string" ? { wei
|
|
|
11225
11276
|
/** True when the weights or their data forbid commercial use. */
|
|
11226
11277
|
nonCommercial: boolean().optional()
|
|
11227
11278
|
}));
|
|
11279
|
+
/** One `fillsClassifierEffects` entry — see `ModelCatalogEntry.fillsClassifierEffects`. */
|
|
11280
|
+
var FillsClassifierEffectSchema = object({
|
|
11281
|
+
stepId: _enum(FILLABLE_STEP_IDS),
|
|
11282
|
+
labelToEffect: record(string(), string()),
|
|
11283
|
+
uncovered: array(string()).readonly()
|
|
11284
|
+
});
|
|
11228
11285
|
var ModelCatalogEntrySchema = object({
|
|
11229
11286
|
id: string(),
|
|
11230
11287
|
name: string(),
|
|
@@ -11351,6 +11408,16 @@ var ModelCatalogEntrySchema = object({
|
|
|
11351
11408
|
*/
|
|
11352
11409
|
classMap: DetectionCatalogClassMapSchema.optional(),
|
|
11353
11410
|
/**
|
|
11411
|
+
* The pipeline steps this ROOT detector already does the work of (D715):
|
|
11412
|
+
* its labels name the effect the step exists to produce (`deer` for
|
|
11413
|
+
* `animal-classifier`, `package` for `package-detection`). Derived from the
|
|
11414
|
+
* labelmap by `deriveClassifierFills`, never hand-written; a COCO model
|
|
11415
|
+
* declares none. Whether a declaration is honoured is the step's own
|
|
11416
|
+
* `labelLink` policy (`resolveLabelLink`). `labelToEffect` values are in
|
|
11417
|
+
* `FILLABLE_STEP_VOCABULARIES` (guard `check-label-link-vocabulary`).
|
|
11418
|
+
*/
|
|
11419
|
+
fillsClassifierEffects: array(FillsClassifierEffectSchema).readonly().optional(),
|
|
11420
|
+
/**
|
|
11354
11421
|
* The model's CLIP feature-space contract (text encoder, dimension, vector
|
|
11355
11422
|
* index, token window, search floor) — see `clip-model.ts`. Present ONLY on a
|
|
11356
11423
|
* CLIP image encoder; its absence is what "not a CLIP model" means to the
|
|
@@ -14823,7 +14890,7 @@ DeviceType.Camera;
|
|
|
14823
14890
|
* This matters here more than anywhere else in the repo, because every provider
|
|
14824
14891
|
* that knows a device's host knows its PASSWORD too: `{ host, port, username,
|
|
14825
14892
|
* password }` sit in one object on Hikvision, Amcrest, Reolink and ONVIF alike,
|
|
14826
|
-
* and `http://admin:hunter2@192.168.
|
|
14893
|
+
* and `http://admin:hunter2@192.168.60.139/` is a URL a browser accepts. The
|
|
14827
14894
|
* camera's own page will ask for its own login. That is correct, and pre-
|
|
14828
14895
|
* filling it is the operator's business, not ours.
|
|
14829
14896
|
*
|
|
@@ -18714,51 +18781,6 @@ method(object({}), array(TargetKindSchema)), method(object({}), array(TargetSche
|
|
|
18714
18781
|
kind: "mutation",
|
|
18715
18782
|
auth: "admin"
|
|
18716
18783
|
});
|
|
18717
|
-
new Set([
|
|
18718
|
-
{
|
|
18719
|
-
id: "person",
|
|
18720
|
-
name: "Person"
|
|
18721
|
-
},
|
|
18722
|
-
{
|
|
18723
|
-
id: "vehicle",
|
|
18724
|
-
name: "Vehicle"
|
|
18725
|
-
},
|
|
18726
|
-
{
|
|
18727
|
-
id: "animal",
|
|
18728
|
-
name: "Animal"
|
|
18729
|
-
},
|
|
18730
|
-
{
|
|
18731
|
-
id: "package",
|
|
18732
|
-
name: "Package"
|
|
18733
|
-
}
|
|
18734
|
-
].map((l) => l.id));
|
|
18735
|
-
var COCO_TO_MACRO = {
|
|
18736
|
-
mapping: {
|
|
18737
|
-
person: "person",
|
|
18738
|
-
bicycle: "vehicle",
|
|
18739
|
-
car: "vehicle",
|
|
18740
|
-
motorcycle: "vehicle",
|
|
18741
|
-
airplane: "vehicle",
|
|
18742
|
-
bus: "vehicle",
|
|
18743
|
-
train: "vehicle",
|
|
18744
|
-
truck: "vehicle",
|
|
18745
|
-
boat: "vehicle",
|
|
18746
|
-
bird: "animal",
|
|
18747
|
-
cat: "animal",
|
|
18748
|
-
dog: "animal",
|
|
18749
|
-
horse: "animal",
|
|
18750
|
-
sheep: "animal",
|
|
18751
|
-
cow: "animal",
|
|
18752
|
-
elephant: "animal",
|
|
18753
|
-
bear: "animal",
|
|
18754
|
-
zebra: "animal",
|
|
18755
|
-
giraffe: "animal",
|
|
18756
|
-
suitcase: "package",
|
|
18757
|
-
backpack: "package",
|
|
18758
|
-
handbag: "package"
|
|
18759
|
-
},
|
|
18760
|
-
preserveOriginal: false
|
|
18761
|
-
};
|
|
18762
18784
|
var AUDIO_MACRO_LABELS = [
|
|
18763
18785
|
{
|
|
18764
18786
|
id: "speech",
|
|
@@ -20652,8 +20674,9 @@ var NcRuleSchema = NcRuleInputSchema.extend({
|
|
|
20652
20674
|
disabledTargetIds: array(string()).default([])
|
|
20653
20675
|
});
|
|
20654
20676
|
/**
|
|
20655
|
-
* The state-summary SECTIONS (D647 / D698): the D637 kind groups that
|
|
20656
|
-
* still-true state. `
|
|
20677
|
+
* The state-summary SECTIONS (D647 / D698 / D708): the D637 kind groups that
|
|
20678
|
+
* report a still-true state. `addons` is the crash-looped addons only and
|
|
20679
|
+
* `addon-updates` the addons that are behind (D708 split them). `backups-exports` and `alarm` are not sections — a completed
|
|
20657
20680
|
* job is not an open state, and the alarm stays instant.
|
|
20658
20681
|
*/
|
|
20659
20682
|
var NcStateSummarySectionIdSchema = _enum([
|
|
@@ -20665,6 +20688,7 @@ var NcStateSummarySectionIdSchema = _enum([
|
|
|
20665
20688
|
"detection-blind",
|
|
20666
20689
|
"nodes",
|
|
20667
20690
|
"addons",
|
|
20691
|
+
"addon-updates",
|
|
20668
20692
|
"updates"
|
|
20669
20693
|
]);
|
|
20670
20694
|
/** One section of a previewed state summary. `unavailable` = its state could not be read. */
|
|
@@ -21145,7 +21169,19 @@ var NcAlarmModeDelaysListSchema = array(object({
|
|
|
21145
21169
|
* When this mode may be armed. Absent / null = always allowed (same as a
|
|
21146
21170
|
* rule with no `schedule`). Evaluated with {@link isScheduleActive}.
|
|
21147
21171
|
*/
|
|
21148
|
-
schedule: NcScheduleSchema.optional()
|
|
21172
|
+
schedule: NcScheduleSchema.optional(),
|
|
21173
|
+
/**
|
|
21174
|
+
* D706: while this mode's ENTRY DELAY runs, do the alarm rules' own pushes go out (as an
|
|
21175
|
+
* intrusion naming the locations)? Absent = false — the entry-delay notification is the
|
|
21176
|
+
* only one, and the matches ride the triggered notification's mosaic (D705).
|
|
21177
|
+
*/
|
|
21178
|
+
notifyDuringEntryDelay: boolean().optional(),
|
|
21179
|
+
/**
|
|
21180
|
+
* D706: notify "watched again" when a sensor this arm bypassed closes and opens again.
|
|
21181
|
+
* Absent = false (logged, not sent). Even when true it is not sent when that same sensor
|
|
21182
|
+
* is the one that starts the entry delay — the entry-delay notification already names it.
|
|
21183
|
+
*/
|
|
21184
|
+
notifySensorRewatched: boolean().optional()
|
|
21149
21185
|
})).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
|
|
21150
21186
|
var NcAlarmModeDelaysEditListSchema = array(object({
|
|
21151
21187
|
mode: AlarmArmModeSchema,
|
|
@@ -21154,7 +21190,11 @@ var NcAlarmModeDelaysEditListSchema = array(object({
|
|
|
21154
21190
|
triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional(),
|
|
21155
21191
|
postTriggeredAction: NcAlarmPostTriggeredActionSchema.nullable().optional(),
|
|
21156
21192
|
/** Set a schedule, or `null` to clear (mode always allowed again). */
|
|
21157
|
-
schedule: NcScheduleSchema.nullable().optional()
|
|
21193
|
+
schedule: NcScheduleSchema.nullable().optional(),
|
|
21194
|
+
/** D706: set the switch, or `null` to clear it (back to the default, false). */
|
|
21195
|
+
notifyDuringEntryDelay: boolean().nullable().optional(),
|
|
21196
|
+
/** D706: set the switch, or `null` to clear it (back to the default, false). */
|
|
21197
|
+
notifySensorRewatched: boolean().nullable().optional()
|
|
21158
21198
|
})).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
|
|
21159
21199
|
/** One switch of the alarm table: put ONE device on, or take it off, ONE mode's list. */
|
|
21160
21200
|
var NcAlarmNonBlockingEditSchema = object({
|
|
@@ -24182,7 +24222,8 @@ var PipelineModelOptionSchema = object({
|
|
|
24182
24222
|
group: ModelVariantGroupSchema.optional(),
|
|
24183
24223
|
legacy: boolean().optional(),
|
|
24184
24224
|
provider: ModelProviderIdSchema.optional(),
|
|
24185
|
-
defaultConfidence: number().optional()
|
|
24225
|
+
defaultConfidence: number().optional(),
|
|
24226
|
+
fillsClassifierEffects: array(FillsClassifierEffectSchema).readonly().optional()
|
|
24186
24227
|
});
|
|
24187
24228
|
var ConfigFieldBridge = custom();
|
|
24188
24229
|
var PipelineAddonSchemaSchema = object({
|
|
@@ -25015,6 +25056,22 @@ var MotionSourceEnum = _enum([
|
|
|
25015
25056
|
"device-activity"
|
|
25016
25057
|
]);
|
|
25017
25058
|
/**
|
|
25059
|
+
* What opened an on-motion detection SESSION: the motion source that passed the
|
|
25060
|
+
* camera's `motionSources` gate, and what raised it (the camera itself, or a
|
|
25061
|
+
* sensor the operator attached — D672). `sensorName` is the attached sensor's
|
|
25062
|
+
* device name as the orchestrator's camera-sensors resolution last read it;
|
|
25063
|
+
* absent when unknown or when the camera itself triggered.
|
|
25064
|
+
*
|
|
25065
|
+
* Carried on the session attach ONLY so the runner's `DetectionPhaseTransition`
|
|
25066
|
+
* can say what started the session (D672 rule 11, amended 2026-10-06). The
|
|
25067
|
+
* runner never decides anything on it.
|
|
25068
|
+
*/
|
|
25069
|
+
var SessionTriggerSchema = object({
|
|
25070
|
+
source: MotionSourceEnum,
|
|
25071
|
+
triggeredBy: MotionTriggeredBySchema,
|
|
25072
|
+
sensorName: string().optional()
|
|
25073
|
+
});
|
|
25074
|
+
/**
|
|
25018
25075
|
* List of motion sources active on a camera. Empty array is valid:
|
|
25019
25076
|
* "no source" — happens for battery cams without firmware motion when
|
|
25020
25077
|
* the operator hasn't opted into the SW analyzer (would hold the
|
|
@@ -25266,6 +25323,14 @@ var RunnerCameraConfigSchema = object({
|
|
|
25266
25323
|
*/
|
|
25267
25324
|
motionSources: MotionSourcesSchema.default(["analyzer"]),
|
|
25268
25325
|
/**
|
|
25326
|
+
* What opened this attach, on a SESSION attach only (see
|
|
25327
|
+
* {@link SessionTriggerSchema}). OPTIONAL with no default: absent on a
|
|
25328
|
+
* standing attach, an occupancy burst, a re-dispatch with no motion event
|
|
25329
|
+
* behind it, and every attach from an orchestrator older than the field — the
|
|
25330
|
+
* runner then names no source on the phase event.
|
|
25331
|
+
*/
|
|
25332
|
+
sessionTrigger: SessionTriggerSchema.optional(),
|
|
25333
|
+
/**
|
|
25269
25334
|
* WHICH root detector runs for this camera. The detection counterpart of
|
|
25270
25335
|
* {@link motionSources}, same shape and same discipline: a per-camera list
|
|
25271
25336
|
* of sources the system understands, vendor-agnostic, owned here.
|
|
@@ -33176,7 +33241,7 @@ var LocalInterfaceSchema = object({
|
|
|
33176
33241
|
name: string(),
|
|
33177
33242
|
family: _enum(["IPv4", "IPv6"]),
|
|
33178
33243
|
address: string(),
|
|
33179
|
-
/** CIDR shorthand (e.g. `192.168.
|
|
33244
|
+
/** CIDR shorthand (e.g. `192.168.10.10/24`). Empty when OS doesn't expose. */
|
|
33180
33245
|
cidr: string(),
|
|
33181
33246
|
/** OS netmask. Stable across calls so the SDK can hash on it. */
|
|
33182
33247
|
netmask: string(),
|
|
@@ -33230,7 +33295,8 @@ var ConnectionEndpointSchema = object({
|
|
|
33230
33295
|
"lan-ipv4",
|
|
33231
33296
|
"lan-ipv6",
|
|
33232
33297
|
"public",
|
|
33233
|
-
"loopback"
|
|
33298
|
+
"loopback",
|
|
33299
|
+
"app-link"
|
|
33234
33300
|
]),
|
|
33235
33301
|
/**
|
|
33236
33302
|
* Originating-interface kind — `lan`/`wifi`/`docker`/`vpn`/`other`/
|
|
@@ -33299,15 +33365,27 @@ var GetConnectionEndpointsResultSchema = object({
|
|
|
33299
33365
|
localPort: AdvertisedLocalPortSchema
|
|
33300
33366
|
});
|
|
33301
33367
|
/**
|
|
33302
|
-
* The
|
|
33303
|
-
*
|
|
33304
|
-
*
|
|
33368
|
+
* The address flagged for notification links. `baseUrl: null` = AUTO, which
|
|
33369
|
+
* since D709 is the CamStack app link; `resolved` reports the effective value,
|
|
33370
|
+
* so the UI can show it either way.
|
|
33305
33371
|
*/
|
|
33306
33372
|
var NotificationEndpointSchema = object({
|
|
33307
33373
|
/** The operator's explicit choice, or null for AUTO. */
|
|
33308
33374
|
baseUrl: string().nullable(),
|
|
33309
|
-
/**
|
|
33310
|
-
|
|
33375
|
+
/**
|
|
33376
|
+
* The effective flagged address: the explicit choice, else (AUTO) the
|
|
33377
|
+
* CamStack app link `https://camstack.zentik.app` (D709). A pre-D709 hub
|
|
33378
|
+
* answered the public tunnel / mesh here, or null.
|
|
33379
|
+
*/
|
|
33380
|
+
resolved: string().nullable(),
|
|
33381
|
+
/**
|
|
33382
|
+
* The hub origin an app link carries as `hub=` (D709): the hub's best
|
|
33383
|
+
* public HTTPS address — the tunnel, then the mesh (Tailscale MagicDNS) —
|
|
33384
|
+
* picked from this cap's own palette by `pickAppLinkHub`. `null` when the
|
|
33385
|
+
* hub advertises neither; the app link is then minted without `hub=`.
|
|
33386
|
+
* Absent on a pre-D709 hub.
|
|
33387
|
+
*/
|
|
33388
|
+
appLinkHub: string().nullable()
|
|
33311
33389
|
});
|
|
33312
33390
|
/**
|
|
33313
33391
|
* The URLs the SDK / viewer should race for API access. `baseUrls` empty =
|
|
@@ -33361,7 +33439,11 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
|
|
|
33361
33439
|
* Pass `'https'` when the caller is itself loaded over HTTPS
|
|
33362
33440
|
* to avoid mixed-content blocks in the browser. The public
|
|
33363
33441
|
* tunnel always emits `https://` regardless. */
|
|
33364
|
-
scheme: _enum(["http", "https"]).optional()
|
|
33442
|
+
scheme: _enum(["http", "https"]).optional(),
|
|
33443
|
+
/** Append the CamStack app link entry (`kind: 'app-link'`, D709) —
|
|
33444
|
+
* an address notification links can be flagged with, not a hub
|
|
33445
|
+
* route. Default `false`: racers and rankers never see it. */
|
|
33446
|
+
includeAppLink: boolean().optional()
|
|
33365
33447
|
}), GetConnectionEndpointsResultSchema), method(_void(), NotificationEndpointSchema), method(object({ baseUrl: string().nullable() }), NotificationEndpointSchema, { kind: "mutation" }), method(_void(), ViewerEndpointsSchema), method(object({ baseUrls: array(string()).readonly() }), ViewerEndpointsSchema, { kind: "mutation" }), method(_void(), AllowedAddressesSchema), method(AllowedAddressesSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), AllowedAddressesSchema, { kind: "mutation" }), method(_void(), TlsStatusSchema), method(object({ reason: string().optional() }), TlsStatusSchema, {
|
|
33366
33448
|
kind: "mutation",
|
|
33367
33449
|
auth: "admin"
|
|
@@ -33690,7 +33772,7 @@ var MeshPeerSchema = object({
|
|
|
33690
33772
|
tags: array(string()).readonly(),
|
|
33691
33773
|
/** True when the peer advertises itself as an exit-node candidate. */
|
|
33692
33774
|
exitNodeOption: boolean(),
|
|
33693
|
-
/** Subnet routes the peer advertises (e.g. `["192.168.
|
|
33775
|
+
/** Subnet routes the peer advertises (e.g. `["192.168.10.0/24"]`). */
|
|
33694
33776
|
advertisedRoutes: array(string()).readonly(),
|
|
33695
33777
|
/** Owner account login (e.g. `foo@example.com`). Null for tagged peers. */
|
|
33696
33778
|
userLogin: string().nullable(),
|
|
@@ -54121,12 +54203,14 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
|
|
|
54121
54203
|
{
|
|
54122
54204
|
id: "addons",
|
|
54123
54205
|
family: "system",
|
|
54124
|
-
label: "Addons",
|
|
54125
|
-
kinds: [
|
|
54126
|
-
|
|
54127
|
-
|
|
54128
|
-
|
|
54129
|
-
|
|
54206
|
+
label: "Addons stopped",
|
|
54207
|
+
kinds: ["addon-crash-loop"]
|
|
54208
|
+
},
|
|
54209
|
+
{
|
|
54210
|
+
id: "addon-updates",
|
|
54211
|
+
family: "system",
|
|
54212
|
+
label: "Addon updates",
|
|
54213
|
+
kinds: ["addon-update-available", "addon-updated"]
|
|
54130
54214
|
},
|
|
54131
54215
|
{
|
|
54132
54216
|
id: "updates",
|
|
@@ -54286,13 +54370,15 @@ var STATE_SUMMARY_SECTION_VARS = [
|
|
|
54286
54370
|
},
|
|
54287
54371
|
{
|
|
54288
54372
|
name: "summaryAddons",
|
|
54289
|
-
label: "Summary: addons",
|
|
54290
|
-
example: "
|
|
54291
|
-
kinds: [
|
|
54292
|
-
|
|
54293
|
-
|
|
54294
|
-
|
|
54295
|
-
|
|
54373
|
+
label: "Summary: addons stopped",
|
|
54374
|
+
example: "hub — recorder stopped after repeated crashes",
|
|
54375
|
+
kinds: ["addon-crash-loop"]
|
|
54376
|
+
},
|
|
54377
|
+
{
|
|
54378
|
+
name: "summaryAddonUpdates",
|
|
54379
|
+
label: "Summary: addon updates",
|
|
54380
|
+
example: "hub:\n• @camstack/addon-recorder 1.2.3 → 1.2.4",
|
|
54381
|
+
kinds: ["addon-update-available", "addon-updated"]
|
|
54296
54382
|
},
|
|
54297
54383
|
{
|
|
54298
54384
|
name: "summaryUpdates",
|
|
@@ -54376,6 +54462,7 @@ var STATE_SUMMARY_VARS = [
|
|
|
54376
54462
|
[...RULE_BODY_ONLY],
|
|
54377
54463
|
[...RULE_TEXT],
|
|
54378
54464
|
([...RULE_TEXT], [...DEVICE_EVENTS]),
|
|
54465
|
+
([...RULE_TEXT], [...COMBINED_ALARM]),
|
|
54379
54466
|
([...RULE_TEXT], [...DEVICE_EVENTS]),
|
|
54380
54467
|
([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
|
|
54381
54468
|
([...RULE_TEXT], [...CONSUMABLE]),
|
|
@@ -166238,6 +166325,37 @@ function buildSyntheticRfc4571Sdp(input) {
|
|
|
166238
166325
|
function buildLazyRfc4571Url(camStreamId) {
|
|
166239
166326
|
return `lazy:rfc4571:${encodeURIComponent(camStreamId)}`;
|
|
166240
166327
|
}
|
|
166328
|
+
function createMotionSensorTracker(now = Date.now) {
|
|
166329
|
+
const latest = /* @__PURE__ */ new Map();
|
|
166330
|
+
return {
|
|
166331
|
+
observe(event) {
|
|
166332
|
+
if (event.type !== "motion") return;
|
|
166333
|
+
const sensor = event.motion.source;
|
|
166334
|
+
if (sensor === void 0) return;
|
|
166335
|
+
latest.set(event.channel, {
|
|
166336
|
+
sensor,
|
|
166337
|
+
at: now()
|
|
166338
|
+
});
|
|
166339
|
+
},
|
|
166340
|
+
take(channel) {
|
|
166341
|
+
const entry = latest.get(channel);
|
|
166342
|
+
if (!entry) return null;
|
|
166343
|
+
latest.delete(channel);
|
|
166344
|
+
return now() - entry.at <= 2e3 ? entry.sensor : null;
|
|
166345
|
+
}
|
|
166346
|
+
};
|
|
166347
|
+
}
|
|
166348
|
+
var isMotionSensor = (value) => value === "md" || value === "pir" || value === "unknown";
|
|
166349
|
+
/**
|
|
166350
|
+
* The sensor a simple event states itself, for a library version that forwards
|
|
166351
|
+
* `motion.source` on the simple event; `null` for the versions that do not.
|
|
166352
|
+
*/
|
|
166353
|
+
function motionSensorOnSimpleEvent(event) {
|
|
166354
|
+
if (!("motion" in event)) return null;
|
|
166355
|
+
const motion = event.motion;
|
|
166356
|
+
if (typeof motion !== "object" || motion === null || !("source" in motion)) return null;
|
|
166357
|
+
return isMotionSensor(motion.source) ? motion.source : null;
|
|
166358
|
+
}
|
|
166241
166359
|
//#endregion
|
|
166242
166360
|
//#region src/reolink-camera.ts
|
|
166243
166361
|
/**
|
|
@@ -166544,6 +166662,16 @@ var ReolinkCamera = class ReolinkCamera extends BaseDevice {
|
|
|
166544
166662
|
this.handleSimpleEvent(event);
|
|
166545
166663
|
};
|
|
166546
166664
|
/**
|
|
166665
|
+
* MD vs PIR of this camera's own motion pushes. The lib's simple event drops
|
|
166666
|
+
* it, so the raw client `event` is observed — PREPENDED, so the sensor is
|
|
166667
|
+
* recorded before the API maps the same emit into the simple event
|
|
166668
|
+
* (`motion-sensor-source.ts`). Hub children get theirs from the hub.
|
|
166669
|
+
*/
|
|
166670
|
+
motionSensors = createMotionSensorTracker();
|
|
166671
|
+
observeRawEventBound = (event) => {
|
|
166672
|
+
this.motionSensors.observe(event);
|
|
166673
|
+
};
|
|
166674
|
+
/**
|
|
166547
166675
|
* Stable bound handler for `api.onObjectDetections` — created ONCE so
|
|
166548
166676
|
* every `onObjectDetections` / `offObjectDetections` call uses the
|
|
166549
166677
|
* SAME function reference (same listener-Set dedup rationale as
|
|
@@ -171945,6 +172073,11 @@ var ReolinkCamera = class ReolinkCamera extends BaseDevice {
|
|
|
171945
172073
|
this.ctx.logger.debug("Reolink event watchdog re-subscribe failed", { meta: { error: err instanceof Error ? err.message : String(err) } });
|
|
171946
172074
|
}
|
|
171947
172075
|
}
|
|
172076
|
+
/** Off-then-prepend, so a re-attached api never carries two observers. */
|
|
172077
|
+
observeMotionSensors(api) {
|
|
172078
|
+
api.client.off("event", this.observeRawEventBound);
|
|
172079
|
+
api.client.prependListener("event", this.observeRawEventBound);
|
|
172080
|
+
}
|
|
171948
172081
|
/**
|
|
171949
172082
|
* Subscribe (or re-subscribe) `handleSimpleEventBound` against
|
|
171950
172083
|
* the Baichuan API. Single-source-of-truth for the listener
|
|
@@ -172280,7 +172413,7 @@ var ReolinkCamera = class ReolinkCamera extends BaseDevice {
|
|
|
172280
172413
|
key: "host",
|
|
172281
172414
|
label: "Camera IP",
|
|
172282
172415
|
required: true,
|
|
172283
|
-
placeholder: "192.168.
|
|
172416
|
+
placeholder: "192.168.10.100"
|
|
172284
172417
|
},
|
|
172285
172418
|
{
|
|
172286
172419
|
type: "number",
|
|
@@ -173539,6 +173672,7 @@ var ReolinkCamera = class ReolinkCamera extends BaseDevice {
|
|
|
173539
173672
|
adoptApi(api) {
|
|
173540
173673
|
this.api = api;
|
|
173541
173674
|
this.reconnectAttempts = 0;
|
|
173675
|
+
this.observeMotionSensors(api);
|
|
173542
173676
|
api.client.on("close", () => this.scheduleReconnect("close"));
|
|
173543
173677
|
api.client.on("error", (err) => {
|
|
173544
173678
|
this.ctx.logger.warn("Baichuan client error — scheduling reconnect", {
|
|
@@ -173686,6 +173820,7 @@ var ReolinkCamera = class ReolinkCamera extends BaseDevice {
|
|
|
173686
173820
|
meta: { error: err instanceof Error ? err.message : String(err) }
|
|
173687
173821
|
});
|
|
173688
173822
|
});
|
|
173823
|
+
this.observeMotionSensors(api);
|
|
173689
173824
|
api.client.on("close", () => this.scheduleReconnect("close"));
|
|
173690
173825
|
api.client.on("error", (err) => {
|
|
173691
173826
|
this.ctx.logger.warn("Baichuan client error — scheduling reconnect", {
|
|
@@ -173755,8 +173890,9 @@ var ReolinkCamera = class ReolinkCamera extends BaseDevice {
|
|
|
173755
173890
|
* when the camera lives under a Hub and inherits the parent's
|
|
173756
173891
|
* single subscription.
|
|
173757
173892
|
*/
|
|
173758
|
-
handleSimpleEvent(event) {
|
|
173893
|
+
handleSimpleEvent(event, routedMotionSensor = null) {
|
|
173759
173894
|
this.lastEventAt = Date.now();
|
|
173895
|
+
const motionSensor = event.type === "motion" ? motionSensorOnSimpleEvent(event) ?? routedMotionSensor ?? this.motionSensors.take(event.channel) : null;
|
|
173760
173896
|
this.consecutiveStaleHealthChecks = 0;
|
|
173761
173897
|
this.nextEventHealthCheckAt = 0;
|
|
173762
173898
|
this.markPassiveContact();
|
|
@@ -173775,7 +173911,8 @@ var ReolinkCamera = class ReolinkCamera extends BaseDevice {
|
|
|
173775
173911
|
type: event.type,
|
|
173776
173912
|
channel: event.channel,
|
|
173777
173913
|
timestamp: event.timestamp,
|
|
173778
|
-
source: event.source
|
|
173914
|
+
source: event.source,
|
|
173915
|
+
...event.type === "motion" ? { motionSensor } : {}
|
|
173779
173916
|
} });
|
|
173780
173917
|
if (event.type === "motion") {
|
|
173781
173918
|
const now = Date.now();
|
|
@@ -174334,6 +174471,17 @@ var ReolinkHub = class ReolinkHub extends BaseDevice {
|
|
|
174334
174471
|
handleSimpleEventBound = (ev) => {
|
|
174335
174472
|
this.routeSimpleEvent(ev);
|
|
174336
174473
|
};
|
|
174474
|
+
/** MD vs PIR per channel, read off the raw client event the lib's simple
|
|
174475
|
+
* event drops (`motion-sensor-source.ts`) and handed to the child. */
|
|
174476
|
+
motionSensors = createMotionSensorTracker();
|
|
174477
|
+
observeRawEventBound = (ev) => {
|
|
174478
|
+
this.motionSensors.observe(ev);
|
|
174479
|
+
};
|
|
174480
|
+
/** Off-then-prepend: recorded before the API maps the same emit. */
|
|
174481
|
+
observeMotionSensors(api) {
|
|
174482
|
+
api.client.off("event", this.observeRawEventBound);
|
|
174483
|
+
api.client.prependListener("event", this.observeRawEventBound);
|
|
174484
|
+
}
|
|
174337
174485
|
constructor(ctx) {
|
|
174338
174486
|
super(ctx, reolinkHubSchema, { type: DeviceType.Hub });
|
|
174339
174487
|
this.registerDeviceDiscovery();
|
|
@@ -174486,7 +174634,7 @@ var ReolinkHub = class ReolinkHub extends BaseDevice {
|
|
|
174486
174634
|
key: "host",
|
|
174487
174635
|
label: "Hub IP",
|
|
174488
174636
|
required: true,
|
|
174489
|
-
placeholder: "192.168.
|
|
174637
|
+
placeholder: "192.168.10.100"
|
|
174490
174638
|
},
|
|
174491
174639
|
{
|
|
174492
174640
|
type: "number",
|
|
@@ -175097,6 +175245,7 @@ var ReolinkHub = class ReolinkHub extends BaseDevice {
|
|
|
175097
175245
|
routeSimpleEvent(ev) {
|
|
175098
175246
|
const channel = ev?.channel;
|
|
175099
175247
|
if (typeof channel !== "number") return;
|
|
175248
|
+
const motionSensor = ev.type === "motion" ? this.motionSensors.take(channel) : null;
|
|
175100
175249
|
const deviceId = this.channelToDeviceId.get(channel);
|
|
175101
175250
|
if (deviceId === void 0) {
|
|
175102
175251
|
const last = this.unroutedChannelLoggedAt.get(channel) ?? 0;
|
|
@@ -175126,7 +175275,7 @@ var ReolinkHub = class ReolinkHub extends BaseDevice {
|
|
|
175126
175275
|
deviceId: child.id,
|
|
175127
175276
|
name: child.name
|
|
175128
175277
|
} });
|
|
175129
|
-
child.handleSimpleEvent(ev);
|
|
175278
|
+
child.handleSimpleEvent(ev, motionSensor);
|
|
175130
175279
|
}).catch((err) => {
|
|
175131
175280
|
this.ctx.logger.debug("Hub simpleEvent dispatch failed", { meta: {
|
|
175132
175281
|
channel,
|
|
@@ -175170,6 +175319,7 @@ var ReolinkHub = class ReolinkHub extends BaseDevice {
|
|
|
175170
175319
|
try {
|
|
175171
175320
|
await api.offSimpleEvent(this.handleSimpleEventBound);
|
|
175172
175321
|
} catch {}
|
|
175322
|
+
this.observeMotionSensors(api);
|
|
175173
175323
|
await api.onSimpleEvent(this.handleSimpleEventBound);
|
|
175174
175324
|
api.client.on("close", () => this.scheduleReconnect("socket-close"));
|
|
175175
175325
|
api.client.on("error", (err) => {
|
|
@@ -175228,6 +175378,7 @@ var ReolinkHub = class ReolinkHub extends BaseDevice {
|
|
|
175228
175378
|
this.api = api;
|
|
175229
175379
|
this.reconnectAttempts = 0;
|
|
175230
175380
|
this.markOnline(true);
|
|
175381
|
+
this.observeMotionSensors(api);
|
|
175231
175382
|
api.client.on("close", () => this.scheduleReconnect("socket-close"));
|
|
175232
175383
|
api.client.on("error", (err) => {
|
|
175233
175384
|
this.ctx.logger.warn("Reolink Hub adopted socket error", { meta: { error: err instanceof Error ? err.message : String(err) } });
|
|
@@ -175320,7 +175471,7 @@ function buildDiscoveryParamsFormSchema() {
|
|
|
175320
175471
|
}, {
|
|
175321
175472
|
id: "scan",
|
|
175322
175473
|
title: "Scan options",
|
|
175323
|
-
description: "Leave the network blank to scan the local subnet. To find cameras on a different subnet, enter its CIDR (e.g. 192.168.
|
|
175474
|
+
description: "Leave the network blank to scan the local subnet. To find cameras on a different subnet, enter its CIDR (e.g. 192.168.20.0/24).",
|
|
175324
175475
|
columns: 1,
|
|
175325
175476
|
fields: [
|
|
175326
175477
|
{
|
|
@@ -175328,7 +175479,7 @@ function buildDiscoveryParamsFormSchema() {
|
|
|
175328
175479
|
key: "networkCidr",
|
|
175329
175480
|
label: "Network (CIDR)",
|
|
175330
175481
|
required: false,
|
|
175331
|
-
placeholder: "192.168.
|
|
175482
|
+
placeholder: "192.168.20.0/24"
|
|
175332
175483
|
},
|
|
175333
175484
|
{
|
|
175334
175485
|
type: "boolean",
|
|
@@ -175412,7 +175563,7 @@ function buildCreationFormSchema() {
|
|
|
175412
175563
|
key: "host",
|
|
175413
175564
|
label: "Host (IP / hostname / UID)",
|
|
175414
175565
|
required: true,
|
|
175415
|
-
placeholder: "192.168.
|
|
175566
|
+
placeholder: "192.168.10.100",
|
|
175416
175567
|
description: "For UDP-only mode you can leave the host blank and supply the camera UID below — the library will discover it on the network.",
|
|
175417
175568
|
inputType: "text"
|
|
175418
175569
|
},
|