@camstack/addon-provider-amcrest 0.2.129 → 0.2.131
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 +249 -140
- package/dist/addon.mjs +249 -140
- package/package.json +1 -1
package/dist/addon.js
CHANGED
|
@@ -10510,6 +10510,57 @@ var ClipSearchStrictnessSchema = _enum([
|
|
|
10510
10510
|
"balanced",
|
|
10511
10511
|
"strict"
|
|
10512
10512
|
]);
|
|
10513
|
+
new Set([
|
|
10514
|
+
{
|
|
10515
|
+
id: "person",
|
|
10516
|
+
name: "Person"
|
|
10517
|
+
},
|
|
10518
|
+
{
|
|
10519
|
+
id: "vehicle",
|
|
10520
|
+
name: "Vehicle"
|
|
10521
|
+
},
|
|
10522
|
+
{
|
|
10523
|
+
id: "animal",
|
|
10524
|
+
name: "Animal"
|
|
10525
|
+
},
|
|
10526
|
+
{
|
|
10527
|
+
id: "package",
|
|
10528
|
+
name: "Package"
|
|
10529
|
+
}
|
|
10530
|
+
].map((l) => l.id));
|
|
10531
|
+
var COCO_TO_MACRO = {
|
|
10532
|
+
mapping: {
|
|
10533
|
+
person: "person",
|
|
10534
|
+
bicycle: "vehicle",
|
|
10535
|
+
car: "vehicle",
|
|
10536
|
+
motorcycle: "vehicle",
|
|
10537
|
+
airplane: "vehicle",
|
|
10538
|
+
bus: "vehicle",
|
|
10539
|
+
train: "vehicle",
|
|
10540
|
+
truck: "vehicle",
|
|
10541
|
+
boat: "vehicle",
|
|
10542
|
+
bird: "animal",
|
|
10543
|
+
cat: "animal",
|
|
10544
|
+
dog: "animal",
|
|
10545
|
+
horse: "animal",
|
|
10546
|
+
sheep: "animal",
|
|
10547
|
+
cow: "animal",
|
|
10548
|
+
elephant: "animal",
|
|
10549
|
+
bear: "animal",
|
|
10550
|
+
zebra: "animal",
|
|
10551
|
+
giraffe: "animal",
|
|
10552
|
+
suitcase: "package",
|
|
10553
|
+
backpack: "package",
|
|
10554
|
+
handbag: "package"
|
|
10555
|
+
},
|
|
10556
|
+
preserveOriginal: false
|
|
10557
|
+
};
|
|
10558
|
+
/** Steps a root detector may declare it fills. */
|
|
10559
|
+
var FILLABLE_STEP_IDS = [
|
|
10560
|
+
"animal-classifier",
|
|
10561
|
+
"vehicle-classifier",
|
|
10562
|
+
"package-detection"
|
|
10563
|
+
];
|
|
10513
10564
|
var MODEL_FORMATS = [
|
|
10514
10565
|
"onnx",
|
|
10515
10566
|
"coreml",
|
|
@@ -10579,11 +10630,11 @@ var ModelVariantGroupSchema = object({
|
|
|
10579
10630
|
/** Quantization axis. Omit ⇒ the fp32 base build. */
|
|
10580
10631
|
precision: _enum(["fp32", "int8"]).optional(),
|
|
10581
10632
|
/**
|
|
10582
|
-
*
|
|
10583
|
-
*
|
|
10584
|
-
*
|
|
10633
|
+
* Training / latency-variant axis. Omit ⇒ the standard build. `test` marks
|
|
10634
|
+
* an alternate training of the same family (Scrypted `relu_test`); chip
|
|
10635
|
+
* label is "Test".
|
|
10585
10636
|
*/
|
|
10586
|
-
optimization: _enum(["standard", "
|
|
10637
|
+
optimization: _enum(["standard", "test"]).optional(),
|
|
10587
10638
|
/**
|
|
10588
10639
|
* Input-resolution axis (square input side, px). Omit ⇒ the family's native
|
|
10589
10640
|
* resolution (640 for yolo26). Reduced-input builds (320 / 256) are a big,
|
|
@@ -10606,9 +10657,10 @@ var ModelProviderIdSchema = _enum([
|
|
|
10606
10657
|
* are per upstream. A persisted custom-model row written when this field was a
|
|
10607
10658
|
* string still parses — the string is lifted into `{ weights }`.
|
|
10608
10659
|
*
|
|
10609
|
-
* Every licence surface (the
|
|
10610
|
-
*
|
|
10611
|
-
*
|
|
10660
|
+
* Every machine licence surface (`THIRD_PARTY_MODELS.md`, the Hugging Face
|
|
10661
|
+
* model table) is GENERATED from these records by
|
|
10662
|
+
* `scripts/gen-model-licenses.ts` (D661). Operator-facing docs live in
|
|
10663
|
+
* `camstack/docs` → `/docs/detection/models`.
|
|
10612
10664
|
*/
|
|
10613
10665
|
var ModelLicenseSchema = preprocess((value) => typeof value === "string" ? { weights: value } : value, object({
|
|
10614
10666
|
/** SPDX id of the WEIGHTS' terms, a `LicenseRef-*` for non-SPDX terms, or `UNKNOWN`. */
|
|
@@ -10641,6 +10693,12 @@ var ModelLicenseSchema = preprocess((value) => typeof value === "string" ? { wei
|
|
|
10641
10693
|
/** True when the weights or their data forbid commercial use. */
|
|
10642
10694
|
nonCommercial: boolean().optional()
|
|
10643
10695
|
}));
|
|
10696
|
+
/** One `fillsClassifierEffects` entry — see `ModelCatalogEntry.fillsClassifierEffects`. */
|
|
10697
|
+
var FillsClassifierEffectSchema = object({
|
|
10698
|
+
stepId: _enum(FILLABLE_STEP_IDS),
|
|
10699
|
+
labelToEffect: record(string(), string()),
|
|
10700
|
+
uncovered: array(string()).readonly()
|
|
10701
|
+
});
|
|
10644
10702
|
var ModelCatalogEntrySchema = object({
|
|
10645
10703
|
id: string(),
|
|
10646
10704
|
name: string(),
|
|
@@ -10767,6 +10825,16 @@ var ModelCatalogEntrySchema = object({
|
|
|
10767
10825
|
*/
|
|
10768
10826
|
classMap: DetectionCatalogClassMapSchema.optional(),
|
|
10769
10827
|
/**
|
|
10828
|
+
* The pipeline steps this ROOT detector already does the work of (D715):
|
|
10829
|
+
* its labels name the effect the step exists to produce (`deer` for
|
|
10830
|
+
* `animal-classifier`, `package` for `package-detection`). Derived from the
|
|
10831
|
+
* labelmap by `deriveClassifierFills`, never hand-written; a COCO model
|
|
10832
|
+
* declares none. Whether a declaration is honoured is the step's own
|
|
10833
|
+
* `labelLink` policy (`resolveLabelLink`). `labelToEffect` values are in
|
|
10834
|
+
* `FILLABLE_STEP_VOCABULARIES` (guard `check-label-link-vocabulary`).
|
|
10835
|
+
*/
|
|
10836
|
+
fillsClassifierEffects: array(FillsClassifierEffectSchema).readonly().optional(),
|
|
10837
|
+
/**
|
|
10770
10838
|
* The model's CLIP feature-space contract (text encoder, dimension, vector
|
|
10771
10839
|
* index, token window, search floor) — see `clip-model.ts`. Present ONLY on a
|
|
10772
10840
|
* CLIP image encoder; its absence is what "not a CLIP model" means to the
|
|
@@ -14239,7 +14307,7 @@ DeviceType.Camera;
|
|
|
14239
14307
|
* This matters here more than anywhere else in the repo, because every provider
|
|
14240
14308
|
* that knows a device's host knows its PASSWORD too: `{ host, port, username,
|
|
14241
14309
|
* password }` sit in one object on Hikvision, Amcrest, Reolink and ONVIF alike,
|
|
14242
|
-
* and `http://admin:hunter2@192.168.
|
|
14310
|
+
* and `http://admin:hunter2@192.168.60.139/` is a URL a browser accepts. The
|
|
14243
14311
|
* camera's own page will ask for its own login. That is correct, and pre-
|
|
14244
14312
|
* filling it is the operator's business, not ours.
|
|
14245
14313
|
*
|
|
@@ -17524,7 +17592,7 @@ method(object({
|
|
|
17524
17592
|
timeoutMs: 6e5
|
|
17525
17593
|
});
|
|
17526
17594
|
method(object({
|
|
17527
|
-
|
|
17595
|
+
targetNodeId: string(),
|
|
17528
17596
|
modelId: string(),
|
|
17529
17597
|
format: _enum(MODEL_FORMATS),
|
|
17530
17598
|
entry: ModelCatalogEntrySchema
|
|
@@ -18090,51 +18158,6 @@ method(object({}), array(TargetKindSchema)), method(object({}), array(TargetSche
|
|
|
18090
18158
|
kind: "mutation",
|
|
18091
18159
|
auth: "admin"
|
|
18092
18160
|
});
|
|
18093
|
-
new Set([
|
|
18094
|
-
{
|
|
18095
|
-
id: "person",
|
|
18096
|
-
name: "Person"
|
|
18097
|
-
},
|
|
18098
|
-
{
|
|
18099
|
-
id: "vehicle",
|
|
18100
|
-
name: "Vehicle"
|
|
18101
|
-
},
|
|
18102
|
-
{
|
|
18103
|
-
id: "animal",
|
|
18104
|
-
name: "Animal"
|
|
18105
|
-
},
|
|
18106
|
-
{
|
|
18107
|
-
id: "package",
|
|
18108
|
-
name: "Package"
|
|
18109
|
-
}
|
|
18110
|
-
].map((l) => l.id));
|
|
18111
|
-
var COCO_TO_MACRO = {
|
|
18112
|
-
mapping: {
|
|
18113
|
-
person: "person",
|
|
18114
|
-
bicycle: "vehicle",
|
|
18115
|
-
car: "vehicle",
|
|
18116
|
-
motorcycle: "vehicle",
|
|
18117
|
-
airplane: "vehicle",
|
|
18118
|
-
bus: "vehicle",
|
|
18119
|
-
train: "vehicle",
|
|
18120
|
-
truck: "vehicle",
|
|
18121
|
-
boat: "vehicle",
|
|
18122
|
-
bird: "animal",
|
|
18123
|
-
cat: "animal",
|
|
18124
|
-
dog: "animal",
|
|
18125
|
-
horse: "animal",
|
|
18126
|
-
sheep: "animal",
|
|
18127
|
-
cow: "animal",
|
|
18128
|
-
elephant: "animal",
|
|
18129
|
-
bear: "animal",
|
|
18130
|
-
zebra: "animal",
|
|
18131
|
-
giraffe: "animal",
|
|
18132
|
-
suitcase: "package",
|
|
18133
|
-
backpack: "package",
|
|
18134
|
-
handbag: "package"
|
|
18135
|
-
},
|
|
18136
|
-
preserveOriginal: false
|
|
18137
|
-
};
|
|
18138
18161
|
var AUDIO_MACRO_LABELS = [
|
|
18139
18162
|
{
|
|
18140
18163
|
id: "speech",
|
|
@@ -18930,6 +18953,8 @@ var NcSystemEventKindSchema = _enum([
|
|
|
18930
18953
|
"stream-offline",
|
|
18931
18954
|
"node-online",
|
|
18932
18955
|
"node-offline",
|
|
18956
|
+
"node-restarting",
|
|
18957
|
+
"node-updating",
|
|
18933
18958
|
"node-inference-unavailable",
|
|
18934
18959
|
"detection-blind",
|
|
18935
18960
|
"addon-crash-loop",
|
|
@@ -20028,8 +20053,9 @@ var NcRuleSchema = NcRuleInputSchema.extend({
|
|
|
20028
20053
|
disabledTargetIds: array(string()).default([])
|
|
20029
20054
|
});
|
|
20030
20055
|
/**
|
|
20031
|
-
* The state-summary SECTIONS (D647 / D698): the D637 kind groups that
|
|
20032
|
-
* still-true state. `
|
|
20056
|
+
* The state-summary SECTIONS (D647 / D698 / D708): the D637 kind groups that
|
|
20057
|
+
* report a still-true state. `addons` is the crash-looped addons only and
|
|
20058
|
+
* `addon-updates` the addons that are behind (D708 split them). `backups-exports` and `alarm` are not sections — a completed
|
|
20033
20059
|
* job is not an open state, and the alarm stays instant.
|
|
20034
20060
|
*/
|
|
20035
20061
|
var NcStateSummarySectionIdSchema = _enum([
|
|
@@ -20041,6 +20067,7 @@ var NcStateSummarySectionIdSchema = _enum([
|
|
|
20041
20067
|
"detection-blind",
|
|
20042
20068
|
"nodes",
|
|
20043
20069
|
"addons",
|
|
20070
|
+
"addon-updates",
|
|
20044
20071
|
"updates"
|
|
20045
20072
|
]);
|
|
20046
20073
|
/** One section of a previewed state summary. `unavailable` = its state could not be read. */
|
|
@@ -20521,7 +20548,19 @@ var NcAlarmModeDelaysListSchema = array(object({
|
|
|
20521
20548
|
* When this mode may be armed. Absent / null = always allowed (same as a
|
|
20522
20549
|
* rule with no `schedule`). Evaluated with {@link isScheduleActive}.
|
|
20523
20550
|
*/
|
|
20524
|
-
schedule: NcScheduleSchema.optional()
|
|
20551
|
+
schedule: NcScheduleSchema.optional(),
|
|
20552
|
+
/**
|
|
20553
|
+
* D706: while this mode's ENTRY DELAY runs, do the alarm rules' own pushes go out (as an
|
|
20554
|
+
* intrusion naming the locations)? Absent = false — the entry-delay notification is the
|
|
20555
|
+
* only one, and the matches ride the triggered notification's mosaic (D705).
|
|
20556
|
+
*/
|
|
20557
|
+
notifyDuringEntryDelay: boolean().optional(),
|
|
20558
|
+
/**
|
|
20559
|
+
* D706: notify "watched again" when a sensor this arm bypassed closes and opens again.
|
|
20560
|
+
* Absent = false (logged, not sent). Even when true it is not sent when that same sensor
|
|
20561
|
+
* is the one that starts the entry delay — the entry-delay notification already names it.
|
|
20562
|
+
*/
|
|
20563
|
+
notifySensorRewatched: boolean().optional()
|
|
20525
20564
|
})).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
|
|
20526
20565
|
var NcAlarmModeDelaysEditListSchema = array(object({
|
|
20527
20566
|
mode: AlarmArmModeSchema,
|
|
@@ -20530,7 +20569,11 @@ var NcAlarmModeDelaysEditListSchema = array(object({
|
|
|
20530
20569
|
triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional(),
|
|
20531
20570
|
postTriggeredAction: NcAlarmPostTriggeredActionSchema.nullable().optional(),
|
|
20532
20571
|
/** Set a schedule, or `null` to clear (mode always allowed again). */
|
|
20533
|
-
schedule: NcScheduleSchema.nullable().optional()
|
|
20572
|
+
schedule: NcScheduleSchema.nullable().optional(),
|
|
20573
|
+
/** D706: set the switch, or `null` to clear it (back to the default, false). */
|
|
20574
|
+
notifyDuringEntryDelay: boolean().nullable().optional(),
|
|
20575
|
+
/** D706: set the switch, or `null` to clear it (back to the default, false). */
|
|
20576
|
+
notifySensorRewatched: boolean().nullable().optional()
|
|
20534
20577
|
})).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
|
|
20535
20578
|
/** One switch of the alarm table: put ONE device on, or take it off, ONE mode's list. */
|
|
20536
20579
|
var NcAlarmNonBlockingEditSchema = object({
|
|
@@ -21491,39 +21534,19 @@ Object.freeze(Object.fromEntries([{
|
|
|
21491
21534
|
label: "Face recognition model",
|
|
21492
21535
|
defaultModelId: "auraface-r100",
|
|
21493
21536
|
indexName: "the enrolled face gallery",
|
|
21494
|
-
options: [
|
|
21495
|
-
|
|
21496
|
-
|
|
21497
|
-
|
|
21498
|
-
},
|
|
21499
|
-
{
|
|
21500
|
-
id: "arcface-r100",
|
|
21501
|
-
label: "ArcFace (ResNet34)"
|
|
21502
|
-
},
|
|
21503
|
-
{
|
|
21504
|
-
id: "inception-resnet-v1",
|
|
21505
|
-
label: "Inception ResNet V1"
|
|
21506
|
-
}
|
|
21507
|
-
]
|
|
21537
|
+
options: [{
|
|
21538
|
+
id: "auraface-r100",
|
|
21539
|
+
label: "AuraFace R100"
|
|
21540
|
+
}]
|
|
21508
21541
|
}, {
|
|
21509
21542
|
stepId: "clip-embedding",
|
|
21510
21543
|
label: "Semantic search model",
|
|
21511
|
-
defaultModelId: "
|
|
21544
|
+
defaultModelId: "siglip2-b16-224",
|
|
21512
21545
|
indexName: "the object semantic-search index",
|
|
21513
|
-
options: [
|
|
21514
|
-
|
|
21515
|
-
|
|
21516
|
-
|
|
21517
|
-
},
|
|
21518
|
-
{
|
|
21519
|
-
id: "mobileclip-s2",
|
|
21520
|
-
label: "MobileCLIP S2"
|
|
21521
|
-
},
|
|
21522
|
-
{
|
|
21523
|
-
id: "siglip2-b16-224",
|
|
21524
|
-
label: "SigLIP2 B/16 (Apache-2.0)"
|
|
21525
|
-
}
|
|
21526
|
-
]
|
|
21546
|
+
options: [{
|
|
21547
|
+
id: "siglip2-b16-224",
|
|
21548
|
+
label: "SigLIP2 B/16 (Apache-2.0)"
|
|
21549
|
+
}]
|
|
21527
21550
|
}].map((s) => [s.stepId, s.defaultModelId])));
|
|
21528
21551
|
var CLUSTER_STEP_SETTING_FIELDS = [{
|
|
21529
21552
|
stepId: "face-embedding",
|
|
@@ -23578,7 +23601,8 @@ var PipelineModelOptionSchema = object({
|
|
|
23578
23601
|
group: ModelVariantGroupSchema.optional(),
|
|
23579
23602
|
legacy: boolean().optional(),
|
|
23580
23603
|
provider: ModelProviderIdSchema.optional(),
|
|
23581
|
-
defaultConfidence: number().optional()
|
|
23604
|
+
defaultConfidence: number().optional(),
|
|
23605
|
+
fillsClassifierEffects: array(FillsClassifierEffectSchema).readonly().optional()
|
|
23582
23606
|
});
|
|
23583
23607
|
var ConfigFieldBridge = custom();
|
|
23584
23608
|
var PipelineAddonSchemaSchema = object({
|
|
@@ -24411,6 +24435,22 @@ var MotionSourceEnum = _enum([
|
|
|
24411
24435
|
"device-activity"
|
|
24412
24436
|
]);
|
|
24413
24437
|
/**
|
|
24438
|
+
* What opened an on-motion detection SESSION: the motion source that passed the
|
|
24439
|
+
* camera's `motionSources` gate, and what raised it (the camera itself, or a
|
|
24440
|
+
* sensor the operator attached — D672). `sensorName` is the attached sensor's
|
|
24441
|
+
* device name as the orchestrator's camera-sensors resolution last read it;
|
|
24442
|
+
* absent when unknown or when the camera itself triggered.
|
|
24443
|
+
*
|
|
24444
|
+
* Carried on the session attach ONLY so the runner's `DetectionPhaseTransition`
|
|
24445
|
+
* can say what started the session (D672 rule 11, amended 2026-10-06). The
|
|
24446
|
+
* runner never decides anything on it.
|
|
24447
|
+
*/
|
|
24448
|
+
var SessionTriggerSchema = object({
|
|
24449
|
+
source: MotionSourceEnum,
|
|
24450
|
+
triggeredBy: MotionTriggeredBySchema,
|
|
24451
|
+
sensorName: string().optional()
|
|
24452
|
+
});
|
|
24453
|
+
/**
|
|
24414
24454
|
* List of motion sources active on a camera. Empty array is valid:
|
|
24415
24455
|
* "no source" — happens for battery cams without firmware motion when
|
|
24416
24456
|
* the operator hasn't opted into the SW analyzer (would hold the
|
|
@@ -24662,6 +24702,14 @@ var RunnerCameraConfigSchema = object({
|
|
|
24662
24702
|
*/
|
|
24663
24703
|
motionSources: MotionSourcesSchema.default(["analyzer"]),
|
|
24664
24704
|
/**
|
|
24705
|
+
* What opened this attach, on a SESSION attach only (see
|
|
24706
|
+
* {@link SessionTriggerSchema}). OPTIONAL with no default: absent on a
|
|
24707
|
+
* standing attach, an occupancy burst, a re-dispatch with no motion event
|
|
24708
|
+
* behind it, and every attach from an orchestrator older than the field — the
|
|
24709
|
+
* runner then names no source on the phase event.
|
|
24710
|
+
*/
|
|
24711
|
+
sessionTrigger: SessionTriggerSchema.optional(),
|
|
24712
|
+
/**
|
|
24665
24713
|
* WHICH root detector runs for this camera. The detection counterpart of
|
|
24666
24714
|
* {@link motionSources}, same shape and same discipline: a per-camera list
|
|
24667
24715
|
* of sources the system understands, vendor-agnostic, owned here.
|
|
@@ -32563,7 +32611,7 @@ var LocalInterfaceSchema = object({
|
|
|
32563
32611
|
name: string(),
|
|
32564
32612
|
family: _enum(["IPv4", "IPv6"]),
|
|
32565
32613
|
address: string(),
|
|
32566
|
-
/** CIDR shorthand (e.g. `192.168.
|
|
32614
|
+
/** CIDR shorthand (e.g. `192.168.10.10/24`). Empty when OS doesn't expose. */
|
|
32567
32615
|
cidr: string(),
|
|
32568
32616
|
/** OS netmask. Stable across calls so the SDK can hash on it. */
|
|
32569
32617
|
netmask: string(),
|
|
@@ -32617,7 +32665,8 @@ var ConnectionEndpointSchema = object({
|
|
|
32617
32665
|
"lan-ipv4",
|
|
32618
32666
|
"lan-ipv6",
|
|
32619
32667
|
"public",
|
|
32620
|
-
"loopback"
|
|
32668
|
+
"loopback",
|
|
32669
|
+
"app-link"
|
|
32621
32670
|
]),
|
|
32622
32671
|
/**
|
|
32623
32672
|
* Originating-interface kind — `lan`/`wifi`/`docker`/`vpn`/`other`/
|
|
@@ -32686,15 +32735,27 @@ var GetConnectionEndpointsResultSchema = object({
|
|
|
32686
32735
|
localPort: AdvertisedLocalPortSchema
|
|
32687
32736
|
});
|
|
32688
32737
|
/**
|
|
32689
|
-
* The
|
|
32690
|
-
*
|
|
32691
|
-
*
|
|
32738
|
+
* The address flagged for notification links. `baseUrl: null` = AUTO, which
|
|
32739
|
+
* since D709 is the CamStack app link; `resolved` reports the effective value,
|
|
32740
|
+
* so the UI can show it either way.
|
|
32692
32741
|
*/
|
|
32693
32742
|
var NotificationEndpointSchema = object({
|
|
32694
32743
|
/** The operator's explicit choice, or null for AUTO. */
|
|
32695
32744
|
baseUrl: string().nullable(),
|
|
32696
|
-
/**
|
|
32697
|
-
|
|
32745
|
+
/**
|
|
32746
|
+
* The effective flagged address: the explicit choice, else (AUTO) the
|
|
32747
|
+
* CamStack app link `https://camstack.zentik.app` (D709). A pre-D709 hub
|
|
32748
|
+
* answered the public tunnel / mesh here, or null.
|
|
32749
|
+
*/
|
|
32750
|
+
resolved: string().nullable(),
|
|
32751
|
+
/**
|
|
32752
|
+
* The hub origin an app link carries as `hub=` (D709): the hub's best
|
|
32753
|
+
* public HTTPS address — the tunnel, then the mesh (Tailscale MagicDNS) —
|
|
32754
|
+
* picked from this cap's own palette by `pickAppLinkHub`. `null` when the
|
|
32755
|
+
* hub advertises neither; the app link is then minted without `hub=`.
|
|
32756
|
+
* Absent on a pre-D709 hub.
|
|
32757
|
+
*/
|
|
32758
|
+
appLinkHub: string().nullable()
|
|
32698
32759
|
});
|
|
32699
32760
|
/**
|
|
32700
32761
|
* The URLs the SDK / viewer should race for API access. `baseUrls` empty =
|
|
@@ -32748,7 +32809,11 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
|
|
|
32748
32809
|
* Pass `'https'` when the caller is itself loaded over HTTPS
|
|
32749
32810
|
* to avoid mixed-content blocks in the browser. The public
|
|
32750
32811
|
* tunnel always emits `https://` regardless. */
|
|
32751
|
-
scheme: _enum(["http", "https"]).optional()
|
|
32812
|
+
scheme: _enum(["http", "https"]).optional(),
|
|
32813
|
+
/** Append the CamStack app link entry (`kind: 'app-link'`, D709) —
|
|
32814
|
+
* an address notification links can be flagged with, not a hub
|
|
32815
|
+
* route. Default `false`: racers and rankers never see it. */
|
|
32816
|
+
includeAppLink: boolean().optional()
|
|
32752
32817
|
}), 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, {
|
|
32753
32818
|
kind: "mutation",
|
|
32754
32819
|
auth: "admin"
|
|
@@ -33077,7 +33142,7 @@ var MeshPeerSchema = object({
|
|
|
33077
33142
|
tags: array(string()).readonly(),
|
|
33078
33143
|
/** True when the peer advertises itself as an exit-node candidate. */
|
|
33079
33144
|
exitNodeOption: boolean(),
|
|
33080
|
-
/** Subnet routes the peer advertises (e.g. `["192.168.
|
|
33145
|
+
/** Subnet routes the peer advertises (e.g. `["192.168.10.0/24"]`). */
|
|
33081
33146
|
advertisedRoutes: array(string()).readonly(),
|
|
33082
33147
|
/** Owner account login (e.g. `foo@example.com`). Null for tagged peers. */
|
|
33083
33148
|
userLogin: string().nullable(),
|
|
@@ -33207,7 +33272,8 @@ var MotionStatusSchema = object({
|
|
|
33207
33272
|
* writes this slice (not even a boot seed), and neither does the runner's
|
|
33208
33273
|
* phase machine: its phase is "a session is attached" for every on-motion
|
|
33209
33274
|
* session, not motion, and it now has its own `DetectionPhaseTransition`.
|
|
33210
|
-
* A provider's `isDetected`
|
|
33275
|
+
* A provider's `isDetected` and `getStatus` answer from the hub's slice
|
|
33276
|
+
* (`hubMotionNativeProvider`).
|
|
33211
33277
|
* - **Sensors** (Home Assistant binary sensors, Homematic, Matter, Alexa
|
|
33212
33278
|
* imports) — the provider pushes both edges itself, from the upstream
|
|
33213
33279
|
* system's own state change. That is the sensor's own fact.
|
|
@@ -34405,7 +34471,13 @@ var OsdStatusSchema = object({ overlays: array(object({
|
|
|
34405
34471
|
*/
|
|
34406
34472
|
availablePositions: array(OsdPositionEnum).readonly(),
|
|
34407
34473
|
/** Firmware does not allow editing the `text` field (e.g. timestamp). */
|
|
34408
|
-
readOnly: boolean().optional()
|
|
34474
|
+
readOnly: boolean().optional(),
|
|
34475
|
+
/**
|
|
34476
|
+
* Firmware text ceiling for this overlay. Absent = no known limit.
|
|
34477
|
+
* The OSD manager truncates here on every write — never stores its own
|
|
34478
|
+
* copy on the binding.
|
|
34479
|
+
*/
|
|
34480
|
+
maxCharacters: number().int().positive().optional()
|
|
34409
34481
|
})).readonly() });
|
|
34410
34482
|
var OsdOverlayPatchSchema = object({
|
|
34411
34483
|
enabled: boolean().optional(),
|
|
@@ -34502,7 +34574,9 @@ var OsdTemplateBindingSchema = object({
|
|
|
34502
34574
|
valuePath: string().min(1).max(64),
|
|
34503
34575
|
/** Convert TO this unit at render (`tryConvertUnit`). Absent = source unit. */
|
|
34504
34576
|
displayUnit: string().max(16).optional(),
|
|
34505
|
-
maxDecimals: number().int().min(0).max(4).default(1)
|
|
34577
|
+
maxDecimals: number().int().min(0).max(4).default(1),
|
|
34578
|
+
/** Raw value → display text (same shape as slot binding). Empty string hides. */
|
|
34579
|
+
valueMap: record(string(), string()).optional()
|
|
34506
34580
|
});
|
|
34507
34581
|
/**
|
|
34508
34582
|
* A named template: bindings (alias → leaf field) + a parser that
|
|
@@ -34552,18 +34626,11 @@ var OsdSlotBindingSchema = object({
|
|
|
34552
34626
|
source: OsdSourceSchema,
|
|
34553
34627
|
/** `${value}` and `${unit}` are substituted; every occurrence. */
|
|
34554
34628
|
template: string().max(96).default("${value}"),
|
|
34555
|
-
/** Truncate with an ellipsis past this length. Absent = no limit. */
|
|
34556
|
-
maxCharacters: number().int().min(4).max(64).optional(),
|
|
34557
34629
|
/**
|
|
34558
34630
|
* Decimal places for a numeric value. `0` yields an integer — the
|
|
34559
34631
|
* documented workaround for firmwares that reject `.` in overlay text.
|
|
34560
34632
|
*/
|
|
34561
34633
|
maxDecimals: number().int().min(0).max(4).default(1),
|
|
34562
|
-
/**
|
|
34563
|
-
* Appended via `${unit}` when no unit conversion produces a label.
|
|
34564
|
-
* Prefer `source.displayUnit` for converted device-state values.
|
|
34565
|
-
*/
|
|
34566
|
-
unitLabel: string().max(8).optional(),
|
|
34567
34634
|
/** Raw value → display text, e.g. `{"true":"MOTION","false":""}`. */
|
|
34568
34635
|
valueMap: record(string(), string()).optional(),
|
|
34569
34636
|
/** Time windows in which the slot is shown. Absent = always. */
|
|
@@ -34572,9 +34639,7 @@ var OsdSlotBindingSchema = object({
|
|
|
34572
34639
|
* Display gate, in the notification centre's condition vocabulary.
|
|
34573
34640
|
* Only the keys reported by `getConditionSupport` are accepted.
|
|
34574
34641
|
*/
|
|
34575
|
-
conditions: NcConditionsSchema.optional()
|
|
34576
|
-
/** Rendered when the gate is closed or the value unreadable. Empty = hide. */
|
|
34577
|
-
fallbackText: string().max(64).default("")
|
|
34642
|
+
conditions: NcConditionsSchema.optional()
|
|
34578
34643
|
});
|
|
34579
34644
|
/** One camera slot, as the operator sees it: firmware truth + our binding. */
|
|
34580
34645
|
var OsdSlotViewSchema = object({
|
|
@@ -53346,6 +53411,8 @@ new Map(Object.entries({
|
|
|
53346
53411
|
"detection-blind": "device-events",
|
|
53347
53412
|
"node-online": "system",
|
|
53348
53413
|
"node-offline": "system",
|
|
53414
|
+
"node-restarting": "system",
|
|
53415
|
+
"node-updating": "system",
|
|
53349
53416
|
"node-inference-unavailable": "system",
|
|
53350
53417
|
"addon-crash-loop": "system",
|
|
53351
53418
|
"addon-update-available": "system",
|
|
@@ -53423,18 +53490,21 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
|
|
|
53423
53490
|
kinds: [
|
|
53424
53491
|
"node-offline",
|
|
53425
53492
|
"node-online",
|
|
53493
|
+
"node-restarting",
|
|
53426
53494
|
"node-inference-unavailable"
|
|
53427
53495
|
]
|
|
53428
53496
|
},
|
|
53429
53497
|
{
|
|
53430
53498
|
id: "addons",
|
|
53431
53499
|
family: "system",
|
|
53432
|
-
label: "Addons",
|
|
53433
|
-
kinds: [
|
|
53434
|
-
|
|
53435
|
-
|
|
53436
|
-
|
|
53437
|
-
|
|
53500
|
+
label: "Addons stopped",
|
|
53501
|
+
kinds: ["addon-crash-loop"]
|
|
53502
|
+
},
|
|
53503
|
+
{
|
|
53504
|
+
id: "addon-updates",
|
|
53505
|
+
family: "system",
|
|
53506
|
+
label: "Addon updates",
|
|
53507
|
+
kinds: ["addon-update-available", "addon-updated"]
|
|
53438
53508
|
},
|
|
53439
53509
|
{
|
|
53440
53510
|
id: "updates",
|
|
@@ -53442,6 +53512,7 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
|
|
|
53442
53512
|
label: "Server & container updates",
|
|
53443
53513
|
kinds: [
|
|
53444
53514
|
"server-update-available",
|
|
53515
|
+
"node-updating",
|
|
53445
53516
|
"server-updated",
|
|
53446
53517
|
"wrapper-update-available"
|
|
53447
53518
|
]
|
|
@@ -53589,18 +53660,21 @@ var STATE_SUMMARY_SECTION_VARS = [
|
|
|
53589
53660
|
kinds: [
|
|
53590
53661
|
"node-offline",
|
|
53591
53662
|
"node-online",
|
|
53663
|
+
"node-restarting",
|
|
53592
53664
|
"node-inference-unavailable"
|
|
53593
53665
|
]
|
|
53594
53666
|
},
|
|
53595
53667
|
{
|
|
53596
53668
|
name: "summaryAddons",
|
|
53597
|
-
label: "Summary: addons",
|
|
53598
|
-
example: "
|
|
53599
|
-
kinds: [
|
|
53600
|
-
|
|
53601
|
-
|
|
53602
|
-
|
|
53603
|
-
|
|
53669
|
+
label: "Summary: addons stopped",
|
|
53670
|
+
example: "hub — recorder stopped after repeated crashes",
|
|
53671
|
+
kinds: ["addon-crash-loop"]
|
|
53672
|
+
},
|
|
53673
|
+
{
|
|
53674
|
+
name: "summaryAddonUpdates",
|
|
53675
|
+
label: "Summary: addon updates",
|
|
53676
|
+
example: "hub:\n• @camstack/addon-recorder 1.2.3 → 1.2.4",
|
|
53677
|
+
kinds: ["addon-update-available", "addon-updated"]
|
|
53604
53678
|
},
|
|
53605
53679
|
{
|
|
53606
53680
|
name: "summaryUpdates",
|
|
@@ -53608,6 +53682,7 @@ var STATE_SUMMARY_SECTION_VARS = [
|
|
|
53608
53682
|
example: "server 1.2.377 → 1.2.378",
|
|
53609
53683
|
kinds: [
|
|
53610
53684
|
"server-update-available",
|
|
53685
|
+
"node-updating",
|
|
53611
53686
|
"server-updated",
|
|
53612
53687
|
"wrapper-update-available"
|
|
53613
53688
|
]
|
|
@@ -53684,6 +53759,7 @@ var STATE_SUMMARY_VARS = [
|
|
|
53684
53759
|
[...RULE_BODY_ONLY],
|
|
53685
53760
|
[...RULE_TEXT],
|
|
53686
53761
|
([...RULE_TEXT], [...DEVICE_EVENTS]),
|
|
53762
|
+
([...RULE_TEXT], [...COMBINED_ALARM]),
|
|
53687
53763
|
([...RULE_TEXT], [...DEVICE_EVENTS]),
|
|
53688
53764
|
([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
|
|
53689
53765
|
([...RULE_TEXT], [...CONSUMABLE]),
|
|
@@ -53724,6 +53800,8 @@ var STATE_SUMMARY_VARS = [
|
|
|
53724
53800
|
[...RULE_TEXT],
|
|
53725
53801
|
[...RULE_TEXT],
|
|
53726
53802
|
[...RULE_TEXT],
|
|
53803
|
+
[...RULE_TEXT],
|
|
53804
|
+
[...RULE_TEXT],
|
|
53727
53805
|
...STATE_SUMMARY_VARS
|
|
53728
53806
|
];
|
|
53729
53807
|
new Set([
|
|
@@ -54060,10 +54138,9 @@ TimelapseRuleInputSchema.extend({
|
|
|
54060
54138
|
createdAt: number(),
|
|
54061
54139
|
updatedAt: number()
|
|
54062
54140
|
});
|
|
54063
|
-
async function
|
|
54064
|
-
let slice;
|
|
54141
|
+
async function readSlice(deviceState, deviceId) {
|
|
54065
54142
|
try {
|
|
54066
|
-
|
|
54143
|
+
return await deviceState.getCapSlice.query({
|
|
54067
54144
|
deviceId,
|
|
54068
54145
|
capName: "motion"
|
|
54069
54146
|
});
|
|
@@ -54071,10 +54148,44 @@ async function readHubMotionDetected(deviceState, deviceId) {
|
|
|
54071
54148
|
const reason = err instanceof Error ? err.message : String(err);
|
|
54072
54149
|
throw new Error(`motion state of device ${deviceId} is unreadable: ${reason}`, { cause: err });
|
|
54073
54150
|
}
|
|
54074
|
-
|
|
54151
|
+
}
|
|
54152
|
+
/**
|
|
54153
|
+
* The hub's `motion` slice as a `MotionStatus`, or `null` when nobody has
|
|
54154
|
+
* published it since the hub started. Throws when the hub does not answer or
|
|
54155
|
+
* the slice is malformed — never a made-up "no motion".
|
|
54156
|
+
*/
|
|
54157
|
+
async function readHubMotionStatus(deviceState, deviceId) {
|
|
54158
|
+
const slice = await readSlice(deviceState, deviceId);
|
|
54159
|
+
if (slice === null) return null;
|
|
54160
|
+
const parsed = MotionStatusSchema.safeParse(slice);
|
|
54161
|
+
if (!parsed.success) throw new Error(`motion state of device ${deviceId} is malformed on the hub: ${parsed.error.message}`);
|
|
54162
|
+
return parsed.data;
|
|
54163
|
+
}
|
|
54164
|
+
async function readHubMotionDetected(deviceState, deviceId) {
|
|
54165
|
+
const detected = (await readSlice(deviceState, deviceId))?.["detected"];
|
|
54075
54166
|
if (typeof detected !== "boolean") throw new Error(`motion state of device ${deviceId} is not published yet (unknown)`);
|
|
54076
54167
|
return detected;
|
|
54077
54168
|
}
|
|
54169
|
+
/**
|
|
54170
|
+
* The native `motion` provider of a camera whose slice the orchestrator writes
|
|
54171
|
+
* (D696): `isDetected` AND `getStatus`, both from the hub. `owner` names the
|
|
54172
|
+
* provider class in the deviceId-mismatch error.
|
|
54173
|
+
*/
|
|
54174
|
+
function hubMotionNativeProvider(deviceState, deviceId, owner) {
|
|
54175
|
+
const ownDevice = (asked) => {
|
|
54176
|
+
if (asked !== deviceId) throw new Error(`${owner}: motion deviceId mismatch, expected ${deviceId}, got ${asked}`);
|
|
54177
|
+
};
|
|
54178
|
+
return {
|
|
54179
|
+
isDetected: async ({ deviceId: asked }) => {
|
|
54180
|
+
ownDevice(asked);
|
|
54181
|
+
return readHubMotionDetected(deviceState, deviceId);
|
|
54182
|
+
},
|
|
54183
|
+
getStatus: async ({ deviceId: asked }) => {
|
|
54184
|
+
ownDevice(asked);
|
|
54185
|
+
return readHubMotionStatus(deviceState, deviceId);
|
|
54186
|
+
}
|
|
54187
|
+
};
|
|
54188
|
+
}
|
|
54078
54189
|
MotionOnMotionChangedDataSchema.omit({ triggeredBy: true });
|
|
54079
54190
|
function providerMotionEvent(source, data) {
|
|
54080
54191
|
return createEvent(EventCategory.ProviderMotion, source, data);
|
|
@@ -56448,14 +56559,12 @@ var AmcrestCamera = class AmcrestCamera extends BaseDevice {
|
|
|
56448
56559
|
}
|
|
56449
56560
|
/** Register the native `motion` cap. Its mere presence (a `kind:'native'`
|
|
56450
56561
|
* `motion` binding) is what the orchestrator reads to default a
|
|
56451
|
-
* freshly-adopted camera to `motionSources:['onboard']`. `isDetected`
|
|
56452
|
-
*
|
|
56453
|
-
*
|
|
56562
|
+
* freshly-adopted camera to `motionSources:['onboard']`. `isDetected` and
|
|
56563
|
+
* `getStatus` answer from the HUB's slice (`hubMotionNativeProvider`); an
|
|
56564
|
+
* unreadable hub fails both — never `false` for unknown (D49, D393). */
|
|
56454
56565
|
registerMotionCap() {
|
|
56455
|
-
this.ctx.
|
|
56456
|
-
|
|
56457
|
-
return readHubMotionDetected(this.ctx.api.deviceState, this.id);
|
|
56458
|
-
} });
|
|
56566
|
+
const provider = hubMotionNativeProvider(this.ctx.api.deviceState, this.id, "AmcrestCamera");
|
|
56567
|
+
this.ctx.registerNativeCap(motionCapability, provider);
|
|
56459
56568
|
this.ctx.logger.info("amcrest: motion cap registered", { tags: { deviceId: this.id } });
|
|
56460
56569
|
}
|
|
56461
56570
|
/** Reusable event-source identity for every emit on this device. */
|
|
@@ -56666,7 +56775,7 @@ var AmcrestCamera = class AmcrestCamera extends BaseDevice {
|
|
|
56666
56775
|
key: "host",
|
|
56667
56776
|
label: "Camera IP",
|
|
56668
56777
|
required: true,
|
|
56669
|
-
placeholder: "192.168.
|
|
56778
|
+
placeholder: "192.168.10.100"
|
|
56670
56779
|
},
|
|
56671
56780
|
{
|
|
56672
56781
|
type: "number",
|
|
@@ -70888,13 +70997,13 @@ function enumerateHosts(cidr) {
|
|
|
70888
70997
|
for (let d = 1; d <= 254; d += 1) out.push(`${a}.${b}.${c}.${d}`);
|
|
70889
70998
|
return out;
|
|
70890
70999
|
}
|
|
70891
|
-
/** Best-effort local /24 from the first non-internal IPv4 interface (e.g. `192.168.
|
|
71000
|
+
/** Best-effort local /24 from the first non-internal IPv4 interface (e.g. `192.168.10.0/24`). */
|
|
70892
71001
|
function detectLocalCidr() {
|
|
70893
71002
|
for (const addrs of Object.values((0, node_os.networkInterfaces)())) for (const addr of addrs ?? []) if (addr.family === "IPv4" && !addr.internal) {
|
|
70894
71003
|
const [a, b, c] = addr.address.split(".");
|
|
70895
71004
|
return `${a}.${b}.${c}.0/24`;
|
|
70896
71005
|
}
|
|
70897
|
-
return "192.168.
|
|
71006
|
+
return "192.168.10.0/24";
|
|
70898
71007
|
}
|
|
70899
71008
|
/** Flatten a host into a flat row-key slug — must match `generateStableId`'s host fallback so a
|
|
70900
71009
|
* re-scan of a host-added camera is detected as already onboarded. */
|
|
@@ -70963,7 +71072,7 @@ function buildCreationFormSchema() {
|
|
|
70963
71072
|
key: "host",
|
|
70964
71073
|
label: "Camera IP",
|
|
70965
71074
|
required: true,
|
|
70966
|
-
placeholder: "192.168.
|
|
71075
|
+
placeholder: "192.168.10.100",
|
|
70967
71076
|
inputType: "text"
|
|
70968
71077
|
},
|
|
70969
71078
|
{
|
|
@@ -71014,14 +71123,14 @@ function buildDiscoveryParamsFormSchema() {
|
|
|
71014
71123
|
}, {
|
|
71015
71124
|
id: "scan",
|
|
71016
71125
|
title: "Scan options",
|
|
71017
|
-
description: "The credentialed CGI subnet scan is the reliable path (multicast WS-Discovery is not received on a macvlan/br0 hub). IMPORTANT: leaving the network blank scans only the HUB’s own subnet — if your cameras are on a DIFFERENT subnet than the hub, you MUST enter their CIDR here (e.g. 192.168.
|
|
71126
|
+
description: "The credentialed CGI subnet scan is the reliable path (multicast WS-Discovery is not received on a macvlan/br0 hub). IMPORTANT: leaving the network blank scans only the HUB’s own subnet — if your cameras are on a DIFFERENT subnet than the hub, you MUST enter their CIDR here (e.g. 192.168.60.0/24), otherwise the scan returns nothing.",
|
|
71018
71127
|
columns: 1,
|
|
71019
71128
|
fields: [{
|
|
71020
71129
|
type: "text",
|
|
71021
71130
|
key: "networkCidr",
|
|
71022
71131
|
label: "Network (CIDR) — required if cameras are on a different subnet than the hub",
|
|
71023
71132
|
required: false,
|
|
71024
|
-
placeholder: "192.168.
|
|
71133
|
+
placeholder: "192.168.60.0/24"
|
|
71025
71134
|
}, {
|
|
71026
71135
|
type: "number",
|
|
71027
71136
|
key: "timeoutMs",
|