@camstack/addon-osd-manager 0.1.170 → 0.1.172
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/{MotionZonesSettings-CTFqdJfp.mjs → MotionZonesSettings-3SEt9bVC.mjs} +2 -2
- package/dist/{PrivacyMaskSettings-M3LLrSyZ.mjs → PrivacyMaskSettings-6XhCc_10.mjs} +4 -4
- package/dist/{SceneMonitorEditor-BWTOg6t0.mjs → SceneMonitorEditor-BOaJdiHv.mjs} +3 -3
- package/dist/_stub.js +4430 -4730
- package/dist/{_virtual_mf-localSharedImportMap___mfe_internal__addon_osd_manager_page-CGnGPNWo.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_osd_manager_page-BWC_vxZ4.mjs} +4 -4
- package/dist/_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-DMeEVWZy.mjs +26 -0
- package/dist/addon-osd-manager.css +1 -1
- package/dist/{hostInit-CXC2ehtI.mjs → hostInit-CSG1YJE4.mjs} +3 -3
- package/dist/index.js +156 -94
- package/dist/index.mjs +156 -94
- package/dist/{player-overlays-DBi0aH1E.mjs → player-overlays-7D6iloq4.mjs} +1 -1
- package/dist/remoteEntry.js +1 -1
- package/dist/{responsive-BoQdxzOM.mjs → responsive-DFTpb0I2.mjs} +1 -1
- package/dist/{scene-monitor-copy-CwfDunLo.mjs → scene-monitor-copy-D6Ypp3Cr.mjs} +1 -1
- package/dist/{square-C-adTToZ.mjs → square-CyIowYkn.mjs} +1 -1
- package/dist/{trash-2-DJjBuL5Q.mjs → trash-2-B5AYx8ut.mjs} +1 -1
- package/dist/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_osd_manager_page__remoteEntry_js-CtQlS867.mjs → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_osd_manager_page__remoteEntry_js-CzgrkKsK.mjs} +1 -1
- package/package.json +1 -1
- package/dist/_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-B4GSezZ1.mjs +0 -26
package/dist/index.js
CHANGED
|
@@ -10635,11 +10635,11 @@ var ModelVariantGroupSchema = object({
|
|
|
10635
10635
|
/** Quantization axis. Omit ⇒ the fp32 base build. */
|
|
10636
10636
|
precision: _enum(["fp32", "int8"]).optional(),
|
|
10637
10637
|
/**
|
|
10638
|
-
*
|
|
10639
|
-
*
|
|
10640
|
-
*
|
|
10638
|
+
* Training / latency-variant axis. Omit ⇒ the standard build. `test` marks
|
|
10639
|
+
* an alternate training of the same family (Scrypted `relu_test`); chip
|
|
10640
|
+
* label is "Test".
|
|
10641
10641
|
*/
|
|
10642
|
-
optimization: _enum(["standard", "
|
|
10642
|
+
optimization: _enum(["standard", "test"]).optional(),
|
|
10643
10643
|
/**
|
|
10644
10644
|
* Input-resolution axis (square input side, px). Omit ⇒ the family's native
|
|
10645
10645
|
* resolution (640 for yolo26). Reduced-input builds (320 / 256) are a big,
|
|
@@ -10662,9 +10662,10 @@ var ModelProviderIdSchema = _enum([
|
|
|
10662
10662
|
* are per upstream. A persisted custom-model row written when this field was a
|
|
10663
10663
|
* string still parses — the string is lifted into `{ weights }`.
|
|
10664
10664
|
*
|
|
10665
|
-
* Every licence surface (the
|
|
10666
|
-
*
|
|
10667
|
-
*
|
|
10665
|
+
* Every machine licence surface (`THIRD_PARTY_MODELS.md`, the Hugging Face
|
|
10666
|
+
* model table) is GENERATED from these records by
|
|
10667
|
+
* `scripts/gen-model-licenses.ts` (D661). Operator-facing docs live in
|
|
10668
|
+
* `camstack/docs` → `/docs/detection/models`.
|
|
10668
10669
|
*/
|
|
10669
10670
|
var ModelLicenseSchema = preprocess((value) => typeof value === "string" ? { weights: value } : value, object({
|
|
10670
10671
|
/** SPDX id of the WEIGHTS' terms, a `LicenseRef-*` for non-SPDX terms, or `UNKNOWN`. */
|
|
@@ -15481,7 +15482,7 @@ var detectionPipelineCapability = {
|
|
|
15481
15482
|
* This matters here more than anywhere else in the repo, because every provider
|
|
15482
15483
|
* that knows a device's host knows its PASSWORD too: `{ host, port, username,
|
|
15483
15484
|
* password }` sit in one object on Hikvision, Amcrest, Reolink and ONVIF alike,
|
|
15484
|
-
* and `http://admin:hunter2@192.168.
|
|
15485
|
+
* and `http://admin:hunter2@192.168.60.139/` is a URL a browser accepts. The
|
|
15485
15486
|
* camera's own page will ask for its own login. That is correct, and pre-
|
|
15486
15487
|
* filling it is the operator's business, not ours.
|
|
15487
15488
|
*
|
|
@@ -19767,7 +19768,7 @@ var modelDistributorCapability = {
|
|
|
19767
19768
|
mode: "singleton",
|
|
19768
19769
|
internal: true,
|
|
19769
19770
|
methods: { distributeModel: method(object({
|
|
19770
|
-
|
|
19771
|
+
targetNodeId: string(),
|
|
19771
19772
|
modelId: string(),
|
|
19772
19773
|
format: _enum(MODEL_FORMATS),
|
|
19773
19774
|
entry: ModelCatalogEntrySchema
|
|
@@ -22347,8 +22348,9 @@ var NcRuleSchema = NcRuleInputSchema.extend({
|
|
|
22347
22348
|
disabledTargetIds: array(string()).default([])
|
|
22348
22349
|
});
|
|
22349
22350
|
/**
|
|
22350
|
-
* The state-summary SECTIONS (D647 / D698): the D637 kind groups that
|
|
22351
|
-
* still-true state. `
|
|
22351
|
+
* The state-summary SECTIONS (D647 / D698 / D708): the D637 kind groups that
|
|
22352
|
+
* report a still-true state. `addons` is the crash-looped addons only and
|
|
22353
|
+
* `addon-updates` the addons that are behind (D708 split them). `backups-exports` and `alarm` are not sections — a completed
|
|
22352
22354
|
* job is not an open state, and the alarm stays instant.
|
|
22353
22355
|
*/
|
|
22354
22356
|
var NcStateSummarySectionIdSchema = _enum([
|
|
@@ -22360,6 +22362,7 @@ var NcStateSummarySectionIdSchema = _enum([
|
|
|
22360
22362
|
"detection-blind",
|
|
22361
22363
|
"nodes",
|
|
22362
22364
|
"addons",
|
|
22365
|
+
"addon-updates",
|
|
22363
22366
|
"updates"
|
|
22364
22367
|
]);
|
|
22365
22368
|
/** One section of a previewed state summary. `unavailable` = its state could not be read. */
|
|
@@ -23376,7 +23379,19 @@ var NcAlarmModeDelaysListSchema = array(object({
|
|
|
23376
23379
|
* When this mode may be armed. Absent / null = always allowed (same as a
|
|
23377
23380
|
* rule with no `schedule`). Evaluated with {@link isScheduleActive}.
|
|
23378
23381
|
*/
|
|
23379
|
-
schedule: NcScheduleSchema.optional()
|
|
23382
|
+
schedule: NcScheduleSchema.optional(),
|
|
23383
|
+
/**
|
|
23384
|
+
* D706: while this mode's ENTRY DELAY runs, do the alarm rules' own pushes go out (as an
|
|
23385
|
+
* intrusion naming the locations)? Absent = false — the entry-delay notification is the
|
|
23386
|
+
* only one, and the matches ride the triggered notification's mosaic (D705).
|
|
23387
|
+
*/
|
|
23388
|
+
notifyDuringEntryDelay: boolean().optional(),
|
|
23389
|
+
/**
|
|
23390
|
+
* D706: notify "watched again" when a sensor this arm bypassed closes and opens again.
|
|
23391
|
+
* Absent = false (logged, not sent). Even when true it is not sent when that same sensor
|
|
23392
|
+
* is the one that starts the entry delay — the entry-delay notification already names it.
|
|
23393
|
+
*/
|
|
23394
|
+
notifySensorRewatched: boolean().optional()
|
|
23380
23395
|
})).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
|
|
23381
23396
|
var NcAlarmModeDelaysEditListSchema = array(object({
|
|
23382
23397
|
mode: AlarmArmModeSchema,
|
|
@@ -23385,7 +23400,11 @@ var NcAlarmModeDelaysEditListSchema = array(object({
|
|
|
23385
23400
|
triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional(),
|
|
23386
23401
|
postTriggeredAction: NcAlarmPostTriggeredActionSchema.nullable().optional(),
|
|
23387
23402
|
/** Set a schedule, or `null` to clear (mode always allowed again). */
|
|
23388
|
-
schedule: NcScheduleSchema.nullable().optional()
|
|
23403
|
+
schedule: NcScheduleSchema.nullable().optional(),
|
|
23404
|
+
/** D706: set the switch, or `null` to clear it (back to the default, false). */
|
|
23405
|
+
notifyDuringEntryDelay: boolean().nullable().optional(),
|
|
23406
|
+
/** D706: set the switch, or `null` to clear it (back to the default, false). */
|
|
23407
|
+
notifySensorRewatched: boolean().nullable().optional()
|
|
23389
23408
|
})).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
|
|
23390
23409
|
/** One switch of the alarm table: put ONE device on, or take it off, ONE mode's list. */
|
|
23391
23410
|
var NcAlarmNonBlockingEditSchema = object({
|
|
@@ -24562,39 +24581,19 @@ Object.freeze(Object.fromEntries([{
|
|
|
24562
24581
|
label: "Face recognition model",
|
|
24563
24582
|
defaultModelId: "auraface-r100",
|
|
24564
24583
|
indexName: "the enrolled face gallery",
|
|
24565
|
-
options: [
|
|
24566
|
-
|
|
24567
|
-
|
|
24568
|
-
|
|
24569
|
-
},
|
|
24570
|
-
{
|
|
24571
|
-
id: "arcface-r100",
|
|
24572
|
-
label: "ArcFace (ResNet34)"
|
|
24573
|
-
},
|
|
24574
|
-
{
|
|
24575
|
-
id: "inception-resnet-v1",
|
|
24576
|
-
label: "Inception ResNet V1"
|
|
24577
|
-
}
|
|
24578
|
-
]
|
|
24584
|
+
options: [{
|
|
24585
|
+
id: "auraface-r100",
|
|
24586
|
+
label: "AuraFace R100"
|
|
24587
|
+
}]
|
|
24579
24588
|
}, {
|
|
24580
24589
|
stepId: "clip-embedding",
|
|
24581
24590
|
label: "Semantic search model",
|
|
24582
|
-
defaultModelId: "
|
|
24591
|
+
defaultModelId: "siglip2-b16-224",
|
|
24583
24592
|
indexName: "the object semantic-search index",
|
|
24584
|
-
options: [
|
|
24585
|
-
|
|
24586
|
-
|
|
24587
|
-
|
|
24588
|
-
},
|
|
24589
|
-
{
|
|
24590
|
-
id: "mobileclip-s2",
|
|
24591
|
-
label: "MobileCLIP S2"
|
|
24592
|
-
},
|
|
24593
|
-
{
|
|
24594
|
-
id: "siglip2-b16-224",
|
|
24595
|
-
label: "SigLIP2 B/16 (Apache-2.0)"
|
|
24596
|
-
}
|
|
24597
|
-
]
|
|
24593
|
+
options: [{
|
|
24594
|
+
id: "siglip2-b16-224",
|
|
24595
|
+
label: "SigLIP2 B/16 (Apache-2.0)"
|
|
24596
|
+
}]
|
|
24598
24597
|
}].map((s) => [s.stepId, s.defaultModelId])));
|
|
24599
24598
|
var CLUSTER_STEP_SETTING_FIELDS = [{
|
|
24600
24599
|
stepId: "face-embedding",
|
|
@@ -28338,6 +28337,22 @@ var MotionSourceEnum = _enum([
|
|
|
28338
28337
|
"device-activity"
|
|
28339
28338
|
]);
|
|
28340
28339
|
/**
|
|
28340
|
+
* What opened an on-motion detection SESSION: the motion source that passed the
|
|
28341
|
+
* camera's `motionSources` gate, and what raised it (the camera itself, or a
|
|
28342
|
+
* sensor the operator attached — D672). `sensorName` is the attached sensor's
|
|
28343
|
+
* device name as the orchestrator's camera-sensors resolution last read it;
|
|
28344
|
+
* absent when unknown or when the camera itself triggered.
|
|
28345
|
+
*
|
|
28346
|
+
* Carried on the session attach ONLY so the runner's `DetectionPhaseTransition`
|
|
28347
|
+
* can say what started the session (D672 rule 11, amended 2026-10-06). The
|
|
28348
|
+
* runner never decides anything on it.
|
|
28349
|
+
*/
|
|
28350
|
+
var SessionTriggerSchema = object({
|
|
28351
|
+
source: MotionSourceEnum,
|
|
28352
|
+
triggeredBy: MotionTriggeredBySchema,
|
|
28353
|
+
sensorName: string().optional()
|
|
28354
|
+
});
|
|
28355
|
+
/**
|
|
28341
28356
|
* List of motion sources active on a camera. Empty array is valid:
|
|
28342
28357
|
* "no source" — happens for battery cams without firmware motion when
|
|
28343
28358
|
* the operator hasn't opted into the SW analyzer (would hold the
|
|
@@ -28589,6 +28604,14 @@ var RunnerCameraConfigSchema = object({
|
|
|
28589
28604
|
*/
|
|
28590
28605
|
motionSources: MotionSourcesSchema.default(["analyzer"]),
|
|
28591
28606
|
/**
|
|
28607
|
+
* What opened this attach, on a SESSION attach only (see
|
|
28608
|
+
* {@link SessionTriggerSchema}). OPTIONAL with no default: absent on a
|
|
28609
|
+
* standing attach, an occupancy burst, a re-dispatch with no motion event
|
|
28610
|
+
* behind it, and every attach from an orchestrator older than the field — the
|
|
28611
|
+
* runner then names no source on the phase event.
|
|
28612
|
+
*/
|
|
28613
|
+
sessionTrigger: SessionTriggerSchema.optional(),
|
|
28614
|
+
/**
|
|
28592
28615
|
* WHICH root detector runs for this camera. The detection counterpart of
|
|
28593
28616
|
* {@link motionSources}, same shape and same discipline: a per-camera list
|
|
28594
28617
|
* of sources the system understands, vendor-agnostic, owned here.
|
|
@@ -37689,7 +37712,7 @@ var LocalInterfaceSchema = object({
|
|
|
37689
37712
|
name: string(),
|
|
37690
37713
|
family: _enum(["IPv4", "IPv6"]),
|
|
37691
37714
|
address: string(),
|
|
37692
|
-
/** CIDR shorthand (e.g. `192.168.
|
|
37715
|
+
/** CIDR shorthand (e.g. `192.168.10.10/24`). Empty when OS doesn't expose. */
|
|
37693
37716
|
cidr: string(),
|
|
37694
37717
|
/** OS netmask. Stable across calls so the SDK can hash on it. */
|
|
37695
37718
|
netmask: string(),
|
|
@@ -37743,7 +37766,8 @@ var ConnectionEndpointSchema = object({
|
|
|
37743
37766
|
"lan-ipv4",
|
|
37744
37767
|
"lan-ipv6",
|
|
37745
37768
|
"public",
|
|
37746
|
-
"loopback"
|
|
37769
|
+
"loopback",
|
|
37770
|
+
"app-link"
|
|
37747
37771
|
]),
|
|
37748
37772
|
/**
|
|
37749
37773
|
* Originating-interface kind — `lan`/`wifi`/`docker`/`vpn`/`other`/
|
|
@@ -37812,15 +37836,27 @@ var GetConnectionEndpointsResultSchema = object({
|
|
|
37812
37836
|
localPort: AdvertisedLocalPortSchema
|
|
37813
37837
|
});
|
|
37814
37838
|
/**
|
|
37815
|
-
* The
|
|
37816
|
-
*
|
|
37817
|
-
*
|
|
37839
|
+
* The address flagged for notification links. `baseUrl: null` = AUTO, which
|
|
37840
|
+
* since D709 is the CamStack app link; `resolved` reports the effective value,
|
|
37841
|
+
* so the UI can show it either way.
|
|
37818
37842
|
*/
|
|
37819
37843
|
var NotificationEndpointSchema = object({
|
|
37820
37844
|
/** The operator's explicit choice, or null for AUTO. */
|
|
37821
37845
|
baseUrl: string().nullable(),
|
|
37822
|
-
/**
|
|
37823
|
-
|
|
37846
|
+
/**
|
|
37847
|
+
* The effective flagged address: the explicit choice, else (AUTO) the
|
|
37848
|
+
* CamStack app link `https://camstack.zentik.app` (D709). A pre-D709 hub
|
|
37849
|
+
* answered the public tunnel / mesh here, or null.
|
|
37850
|
+
*/
|
|
37851
|
+
resolved: string().nullable(),
|
|
37852
|
+
/**
|
|
37853
|
+
* The hub origin an app link carries as `hub=` (D709): the hub's best
|
|
37854
|
+
* public HTTPS address — the tunnel, then the mesh (Tailscale MagicDNS) —
|
|
37855
|
+
* picked from this cap's own palette by `pickAppLinkHub`. `null` when the
|
|
37856
|
+
* hub advertises neither; the app link is then minted without `hub=`.
|
|
37857
|
+
* Absent on a pre-D709 hub.
|
|
37858
|
+
*/
|
|
37859
|
+
appLinkHub: string().nullable()
|
|
37824
37860
|
});
|
|
37825
37861
|
/**
|
|
37826
37862
|
* The URLs the SDK / viewer should race for API access. `baseUrls` empty =
|
|
@@ -37888,7 +37924,7 @@ var localNetworkCapability = {
|
|
|
37888
37924
|
* every client a second authority on a socket only the hub binds. A viewer
|
|
37889
37925
|
* configured with a port-less public URL (`https://camstack.example.top`)
|
|
37890
37926
|
* infers 443 from the scheme, asks with 443, and was handed
|
|
37891
|
-
* `https://192.168.
|
|
37927
|
+
* `https://192.168.10.9:443` for a hub listening on 4443. That candidate
|
|
37892
37928
|
* cannot ever answer, and losing its race reads in the log exactly like
|
|
37893
37929
|
* "the LAN was tried and it was slower" — so an operator sitting on his own
|
|
37894
37930
|
* WiFi stayed on the public tunnel for weeks, with the LAN candidate born
|
|
@@ -37921,13 +37957,21 @@ var localNetworkCapability = {
|
|
|
37921
37957
|
* Pass `'https'` when the caller is itself loaded over HTTPS
|
|
37922
37958
|
* to avoid mixed-content blocks in the browser. The public
|
|
37923
37959
|
* tunnel always emits `https://` regardless. */
|
|
37924
|
-
scheme: _enum(["http", "https"]).optional()
|
|
37960
|
+
scheme: _enum(["http", "https"]).optional(),
|
|
37961
|
+
/** Append the CamStack app link entry (`kind: 'app-link'`, D709) —
|
|
37962
|
+
* an address notification links can be flagged with, not a hub
|
|
37963
|
+
* route. Default `false`: racers and rankers never see it. */
|
|
37964
|
+
includeAppLink: boolean().optional()
|
|
37925
37965
|
}), GetConnectionEndpointsResultSchema),
|
|
37926
37966
|
/**
|
|
37927
|
-
* The
|
|
37928
|
-
*
|
|
37929
|
-
*
|
|
37930
|
-
*
|
|
37967
|
+
* The address notification links are flagged with. `baseUrl: null` means
|
|
37968
|
+
* AUTO, which is the CamStack app link (D709): viewer taps go through
|
|
37969
|
+
* `https://camstack.zentik.app/…?hub=<appLinkHub>` and open the app. Any
|
|
37970
|
+
* hub address the palette lists can be flagged instead; then viewer taps,
|
|
37971
|
+
* attachment links and action buttons all use it. Signed media and
|
|
37972
|
+
* buttons never use the app link — with it flagged (or AUTO) they keep
|
|
37973
|
+
* the ranked hub ladder (a configured origin, a connected tunnel, then
|
|
37974
|
+
* the LAN), never loopback.
|
|
37931
37975
|
*
|
|
37932
37976
|
* Why an explicit marker: the automatic ranking cannot know which of
|
|
37933
37977
|
* several reachable addresses the RECIPIENT can actually open. A link is
|
|
@@ -38320,7 +38364,7 @@ var MeshPeerSchema = object({
|
|
|
38320
38364
|
tags: array(string()).readonly(),
|
|
38321
38365
|
/** True when the peer advertises itself as an exit-node candidate. */
|
|
38322
38366
|
exitNodeOption: boolean(),
|
|
38323
|
-
/** Subnet routes the peer advertises (e.g. `["192.168.
|
|
38367
|
+
/** Subnet routes the peer advertises (e.g. `["192.168.10.0/24"]`). */
|
|
38324
38368
|
advertisedRoutes: array(string()).readonly(),
|
|
38325
38369
|
/** Owner account login (e.g. `foo@example.com`). Null for tagged peers. */
|
|
38326
38370
|
userLogin: string().nullable(),
|
|
@@ -39768,7 +39812,13 @@ var OsdStatusSchema = object({ overlays: array(object({
|
|
|
39768
39812
|
*/
|
|
39769
39813
|
availablePositions: array(OsdPositionEnum).readonly(),
|
|
39770
39814
|
/** Firmware does not allow editing the `text` field (e.g. timestamp). */
|
|
39771
|
-
readOnly: boolean().optional()
|
|
39815
|
+
readOnly: boolean().optional(),
|
|
39816
|
+
/**
|
|
39817
|
+
* Firmware text ceiling for this overlay. Absent = no known limit.
|
|
39818
|
+
* The OSD manager truncates here on every write — never stores its own
|
|
39819
|
+
* copy on the binding.
|
|
39820
|
+
*/
|
|
39821
|
+
maxCharacters: number().int().positive().optional()
|
|
39772
39822
|
})).readonly() });
|
|
39773
39823
|
var OsdOverlayPatchSchema = object({
|
|
39774
39824
|
enabled: boolean().optional(),
|
|
@@ -39865,7 +39915,9 @@ var OsdTemplateBindingSchema = object({
|
|
|
39865
39915
|
valuePath: string().min(1).max(64),
|
|
39866
39916
|
/** Convert TO this unit at render (`tryConvertUnit`). Absent = source unit. */
|
|
39867
39917
|
displayUnit: string().max(16).optional(),
|
|
39868
|
-
maxDecimals: number().int().min(0).max(4).default(1)
|
|
39918
|
+
maxDecimals: number().int().min(0).max(4).default(1),
|
|
39919
|
+
/** Raw value → display text (same shape as slot binding). Empty string hides. */
|
|
39920
|
+
valueMap: record(string(), string()).optional()
|
|
39869
39921
|
});
|
|
39870
39922
|
/**
|
|
39871
39923
|
* A named template: bindings (alias → leaf field) + a parser that
|
|
@@ -39915,18 +39967,11 @@ var OsdSlotBindingSchema = object({
|
|
|
39915
39967
|
source: OsdSourceSchema,
|
|
39916
39968
|
/** `${value}` and `${unit}` are substituted; every occurrence. */
|
|
39917
39969
|
template: string().max(96).default("${value}"),
|
|
39918
|
-
/** Truncate with an ellipsis past this length. Absent = no limit. */
|
|
39919
|
-
maxCharacters: number().int().min(4).max(64).optional(),
|
|
39920
39970
|
/**
|
|
39921
39971
|
* Decimal places for a numeric value. `0` yields an integer — the
|
|
39922
39972
|
* documented workaround for firmwares that reject `.` in overlay text.
|
|
39923
39973
|
*/
|
|
39924
39974
|
maxDecimals: number().int().min(0).max(4).default(1),
|
|
39925
|
-
/**
|
|
39926
|
-
* Appended via `${unit}` when no unit conversion produces a label.
|
|
39927
|
-
* Prefer `source.displayUnit` for converted device-state values.
|
|
39928
|
-
*/
|
|
39929
|
-
unitLabel: string().max(8).optional(),
|
|
39930
39975
|
/** Raw value → display text, e.g. `{"true":"MOTION","false":""}`. */
|
|
39931
39976
|
valueMap: record(string(), string()).optional(),
|
|
39932
39977
|
/** Time windows in which the slot is shown. Absent = always. */
|
|
@@ -39935,9 +39980,7 @@ var OsdSlotBindingSchema = object({
|
|
|
39935
39980
|
* Display gate, in the notification centre's condition vocabulary.
|
|
39936
39981
|
* Only the keys reported by `getConditionSupport` are accepted.
|
|
39937
39982
|
*/
|
|
39938
|
-
conditions: NcConditionsSchema.optional()
|
|
39939
|
-
/** Rendered when the gate is closed or the value unreadable. Empty = hide. */
|
|
39940
|
-
fallbackText: string().max(64).default("")
|
|
39983
|
+
conditions: NcConditionsSchema.optional()
|
|
39941
39984
|
});
|
|
39942
39985
|
/** One camera slot, as the operator sees it: firmware truth + our binding. */
|
|
39943
39986
|
var OsdSlotViewSchema = object({
|
|
@@ -57819,12 +57862,14 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
|
|
|
57819
57862
|
{
|
|
57820
57863
|
id: "addons",
|
|
57821
57864
|
family: "system",
|
|
57822
|
-
label: "Addons",
|
|
57823
|
-
kinds: [
|
|
57824
|
-
|
|
57825
|
-
|
|
57826
|
-
|
|
57827
|
-
|
|
57865
|
+
label: "Addons stopped",
|
|
57866
|
+
kinds: ["addon-crash-loop"]
|
|
57867
|
+
},
|
|
57868
|
+
{
|
|
57869
|
+
id: "addon-updates",
|
|
57870
|
+
family: "system",
|
|
57871
|
+
label: "Addon updates",
|
|
57872
|
+
kinds: ["addon-update-available", "addon-updated"]
|
|
57828
57873
|
},
|
|
57829
57874
|
{
|
|
57830
57875
|
id: "updates",
|
|
@@ -58064,13 +58109,15 @@ var STATE_SUMMARY_SECTION_VARS = [
|
|
|
58064
58109
|
},
|
|
58065
58110
|
{
|
|
58066
58111
|
name: "summaryAddons",
|
|
58067
|
-
label: "Summary: addons",
|
|
58068
|
-
example: "
|
|
58069
|
-
kinds: [
|
|
58070
|
-
|
|
58071
|
-
|
|
58072
|
-
|
|
58073
|
-
|
|
58112
|
+
label: "Summary: addons stopped",
|
|
58113
|
+
example: "hub — recorder stopped after repeated crashes",
|
|
58114
|
+
kinds: ["addon-crash-loop"]
|
|
58115
|
+
},
|
|
58116
|
+
{
|
|
58117
|
+
name: "summaryAddonUpdates",
|
|
58118
|
+
label: "Summary: addon updates",
|
|
58119
|
+
example: "hub:\n• @camstack/addon-recorder 1.2.3 → 1.2.4",
|
|
58120
|
+
kinds: ["addon-update-available", "addon-updated"]
|
|
58074
58121
|
},
|
|
58075
58122
|
{
|
|
58076
58123
|
name: "summaryUpdates",
|
|
@@ -58154,6 +58201,7 @@ var STATE_SUMMARY_VARS = [
|
|
|
58154
58201
|
[...RULE_BODY_ONLY],
|
|
58155
58202
|
[...RULE_TEXT],
|
|
58156
58203
|
([...RULE_TEXT], [...DEVICE_EVENTS]),
|
|
58204
|
+
([...RULE_TEXT], [...COMBINED_ALARM]),
|
|
58157
58205
|
([...RULE_TEXT], [...DEVICE_EVENTS]),
|
|
58158
58206
|
([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
|
|
58159
58207
|
([...RULE_TEXT], [...CONSUMABLE]),
|
|
@@ -58194,6 +58242,8 @@ var STATE_SUMMARY_VARS = [
|
|
|
58194
58242
|
[...RULE_TEXT],
|
|
58195
58243
|
[...RULE_TEXT],
|
|
58196
58244
|
[...RULE_TEXT],
|
|
58245
|
+
[...RULE_TEXT],
|
|
58246
|
+
[...RULE_TEXT],
|
|
58197
58247
|
...STATE_SUMMARY_VARS
|
|
58198
58248
|
];
|
|
58199
58249
|
new Set([
|
|
@@ -58986,8 +59036,8 @@ function applyTemplate(template, value, unit) {
|
|
|
58986
59036
|
/** The whole formatting chain: raw value → the text to burn into the slot. */
|
|
58987
59037
|
function formatSlotText(raw, binding, options = {}) {
|
|
58988
59038
|
const value = displayValue(options.displayRaw ?? raw, binding);
|
|
58989
|
-
const unit = options.unit ??
|
|
58990
|
-
return limitText(applyTemplate(binding.template, value, unit).trim(),
|
|
59039
|
+
const unit = options.unit ?? "";
|
|
59040
|
+
return limitText(applyTemplate(binding.template, value, unit).trim(), options.maxCharacters);
|
|
58991
59041
|
}
|
|
58992
59042
|
//#endregion
|
|
58993
59043
|
//#region src/state-leaves.ts
|
|
@@ -59252,6 +59302,12 @@ function resolveBindingLive(binding, facts) {
|
|
|
59252
59302
|
if (slice === void 0) return { reason: `device ${deviceId} publishes no "${binding.capName}" state` };
|
|
59253
59303
|
const raw = readStatePath(slice, binding.valuePath);
|
|
59254
59304
|
if (raw === void 0) return { reason: `"${binding.capName}.${binding.valuePath}" is absent on device ${deviceId}` };
|
|
59305
|
+
const mapped = binding.valueMap?.[String(raw)];
|
|
59306
|
+
if (mapped !== void 0) return {
|
|
59307
|
+
value: mapped,
|
|
59308
|
+
unit: "",
|
|
59309
|
+
formatted: applyTemplateTokenKind(mapped, "", "full")
|
|
59310
|
+
};
|
|
59255
59311
|
let value;
|
|
59256
59312
|
let unit = "";
|
|
59257
59313
|
if (typeof raw === "number") {
|
|
@@ -59324,7 +59380,7 @@ function resolveSource(binding, cameraDeviceId, facts) {
|
|
|
59324
59380
|
return { value: {
|
|
59325
59381
|
raw,
|
|
59326
59382
|
displayRaw: converted.value,
|
|
59327
|
-
unit: converted.unit
|
|
59383
|
+
...converted.unit !== void 0 && converted.unit !== "" ? { unit: converted.unit } : {}
|
|
59328
59384
|
} };
|
|
59329
59385
|
}
|
|
59330
59386
|
return { value: { raw } };
|
|
@@ -59335,7 +59391,7 @@ function resolveSource(binding, cameraDeviceId, facts) {
|
|
|
59335
59391
|
* write — a slot rewritten every tick is one firmware round-trip per tick
|
|
59336
59392
|
* per slot, for a string that did not move.
|
|
59337
59393
|
*/
|
|
59338
|
-
function renderSlot(slotId, binding, cameraDeviceId, facts, previousText) {
|
|
59394
|
+
function renderSlot(slotId, binding, cameraDeviceId, facts, previousText, maxCharacters) {
|
|
59339
59395
|
if (binding === null) return {
|
|
59340
59396
|
slotId,
|
|
59341
59397
|
outcome: "unbound",
|
|
@@ -59348,7 +59404,6 @@ function renderSlot(slotId, binding, cameraDeviceId, facts, previousText) {
|
|
|
59348
59404
|
text: "",
|
|
59349
59405
|
reason: "binding is switched off"
|
|
59350
59406
|
};
|
|
59351
|
-
const fallback = limitText(binding.fallbackText, binding.maxCharacters);
|
|
59352
59407
|
const gate = evaluateGate({
|
|
59353
59408
|
cameraDeviceId,
|
|
59354
59409
|
atMs: facts.atMs,
|
|
@@ -59356,14 +59411,14 @@ function renderSlot(slotId, binding, cameraDeviceId, facts, previousText) {
|
|
|
59356
59411
|
conditions: binding.conditions,
|
|
59357
59412
|
deviceState: facts.deviceState
|
|
59358
59413
|
});
|
|
59359
|
-
if (!gate.open) return settle(slotId,
|
|
59414
|
+
if (!gate.open) return settle(slotId, "", previousText, "gated", `condition "${gate.failedCondition}"`);
|
|
59360
59415
|
const resolved = resolveSource(binding, cameraDeviceId, facts);
|
|
59361
|
-
if ("reason" in resolved) return settle(slotId,
|
|
59362
|
-
if (resolved.value.preformatted !== void 0 && binding.source.kind === "template") return settle(slotId, limitText(resolved.value.preformatted.trim(),
|
|
59363
|
-
const unit = resolved.value.unit ?? binding.unitLabel;
|
|
59416
|
+
if ("reason" in resolved) return settle(slotId, "", previousText, "unreadable", resolved.reason);
|
|
59417
|
+
if (resolved.value.preformatted !== void 0 && binding.source.kind === "template") return settle(slotId, limitText(resolved.value.preformatted.trim(), maxCharacters), previousText, "written");
|
|
59364
59418
|
return settle(slotId, formatSlotText(resolved.value.raw, binding, {
|
|
59365
59419
|
...resolved.value.displayRaw !== void 0 ? { displayRaw: resolved.value.displayRaw } : {},
|
|
59366
|
-
...unit !== void 0 ? { unit } : {}
|
|
59420
|
+
...resolved.value.unit !== void 0 ? { unit: resolved.value.unit } : {},
|
|
59421
|
+
...maxCharacters !== void 0 ? { maxCharacters } : {}
|
|
59367
59422
|
}), previousText, "written");
|
|
59368
59423
|
}
|
|
59369
59424
|
function settle(slotId, text, previousText, outcome, reason) {
|
|
@@ -59882,7 +59937,7 @@ var OsdManager = class {
|
|
|
59882
59937
|
previewSlot = async ({ deviceId, slotId, binding }) => {
|
|
59883
59938
|
if (binding !== void 0) assertSupportedConditions(binding.conditions);
|
|
59884
59939
|
const effective = binding ?? (await this.readBindings(deviceId))[slotId] ?? null;
|
|
59885
|
-
return renderSlot(slotId, effective, deviceId, await this.collectFacts(deviceId, effective === null ? {} : { [slotId]: effective }), void 0);
|
|
59940
|
+
return renderSlot(slotId, effective, deviceId, await this.collectFacts(deviceId, effective === null ? {} : { [slotId]: effective }), void 0, await this.maxCharactersForSlot(deviceId, slotId));
|
|
59886
59941
|
};
|
|
59887
59942
|
renderDevice = async ({ deviceId }) => {
|
|
59888
59943
|
return { results: [...await this.renderDeviceInternal(deviceId, null)] };
|
|
@@ -59917,17 +59972,24 @@ var OsdManager = class {
|
|
|
59917
59972
|
});
|
|
59918
59973
|
}
|
|
59919
59974
|
}
|
|
59975
|
+
/** Firmware text ceiling for one overlay, from the live `osd` status. */
|
|
59976
|
+
async maxCharactersForSlot(deviceId, slotId) {
|
|
59977
|
+
return (await this.deps.readOsdStatus(deviceId))?.overlays.find((o) => o.id === slotId)?.maxCharacters;
|
|
59978
|
+
}
|
|
59920
59979
|
/** Render (and write) `onlySlots`, or every bound slot when `null`. */
|
|
59921
59980
|
async renderDeviceInternal(deviceId, onlySlots) {
|
|
59922
59981
|
const bindings = await this.readBindings(deviceId);
|
|
59923
59982
|
const slotIds = onlySlots ?? Object.keys(bindings);
|
|
59924
59983
|
if (slotIds.length === 0) return [];
|
|
59925
59984
|
const facts = await this.collectFacts(deviceId, bindings);
|
|
59985
|
+
const status = await this.deps.readOsdStatus(deviceId);
|
|
59986
|
+
const maxBySlot = /* @__PURE__ */ new Map();
|
|
59987
|
+
for (const overlay of status?.overlays ?? []) if (overlay.maxCharacters !== void 0) maxBySlot.set(overlay.id, overlay.maxCharacters);
|
|
59926
59988
|
const results = [];
|
|
59927
59989
|
for (const slotId of slotIds) {
|
|
59928
59990
|
const binding = bindings[slotId] ?? null;
|
|
59929
59991
|
const key = cacheKey(deviceId, slotId);
|
|
59930
|
-
const result = renderSlot(slotId, binding, deviceId, facts, this.lastWritten.get(key));
|
|
59992
|
+
const result = renderSlot(slotId, binding, deviceId, facts, this.lastWritten.get(key), maxBySlot.get(slotId));
|
|
59931
59993
|
results.push(result);
|
|
59932
59994
|
if (result.outcome === "unchanged") continue;
|
|
59933
59995
|
if (result.outcome === "unbound" || result.outcome === "disabled") continue;
|
|
@@ -60295,7 +60357,7 @@ function toOsdPickerDevices(devices) {
|
|
|
60295
60357
|
return devices.map((d) => ({
|
|
60296
60358
|
id: d.id,
|
|
60297
60359
|
name: d.name,
|
|
60298
|
-
type: d.type
|
|
60360
|
+
...typeof d.type === "string" ? { type: d.type } : {},
|
|
60299
60361
|
location: d.location ?? null,
|
|
60300
60362
|
parentDeviceId: d.parentDeviceId ?? null
|
|
60301
60363
|
}));
|