@camstack/types 1.2.302 → 1.2.304
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 +1 -2
- package/dist/addon.mjs +1 -2
- package/dist/automation/recipe.d.ts +2 -2
- package/dist/capabilities/core-blocks.cap.d.ts +17 -17
- package/dist/capabilities/custom-model-registry.cap.d.ts +2 -2
- package/dist/capabilities/device-admin-link-url.d.ts +2 -2
- package/dist/capabilities/device-admin-link.cap.d.ts +1 -1
- package/dist/capabilities/index.d.ts +1 -1
- package/dist/capabilities/local-network.cap.d.ts +1 -1
- package/dist/capabilities/model-convert.cap.d.ts +1 -1
- package/dist/capabilities/model-distributor.cap.d.ts +10 -4
- package/dist/capabilities/notification-rules.cap.d.ts +230 -0
- package/dist/capabilities/osd-manager.cap.d.ts +5 -18
- package/dist/capabilities/osd.cap.d.ts +4 -0
- package/dist/capabilities/pipeline-executor.cap.d.ts +5 -5
- package/dist/capabilities/stream-broker.cap.d.ts +4 -4
- package/dist/device/device-do-actions.d.ts +57 -0
- package/dist/encode-profile.d.ts +2 -2
- package/dist/index.d.ts +3 -3
- package/dist/index.js +520 -76
- package/dist/index.mjs +510 -77
- package/dist/notification/alarm-membership.d.ts +9 -0
- package/dist/notification/alarm-profiles.d.ts +5 -4
- package/dist/notification/alarm-settings.d.ts +9 -3
- package/dist/types/model-variant-groups.d.ts +2 -2
- package/dist/types/models.d.ts +7 -6
- package/dist/types/pipeline-step.d.ts +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5148,7 +5148,7 @@ function tierLabel(family, baseName) {
|
|
|
5148
5148
|
}
|
|
5149
5149
|
function variantLabel(precision, optimization) {
|
|
5150
5150
|
const parts = [];
|
|
5151
|
-
if (optimization === "
|
|
5151
|
+
if (optimization === "test") parts.push("Test");
|
|
5152
5152
|
parts.push(precision === "int8" ? "Int8" : "Standard");
|
|
5153
5153
|
return parts.join(" · ");
|
|
5154
5154
|
}
|
|
@@ -5172,7 +5172,7 @@ var PRECISION_ORDER = ["fp32", "int8"];
|
|
|
5172
5172
|
/**
|
|
5173
5173
|
* Fold a flat catalog into the `family → tier → variant` tree. Deterministic
|
|
5174
5174
|
* ordering: tiers by the canonical size ladder (unknown tiers appended
|
|
5175
|
-
* alphabetically), variants standard-before-int8 and
|
|
5175
|
+
* alphabetically), variants standard-before-int8 and test last.
|
|
5176
5176
|
*/
|
|
5177
5177
|
function buildModelVariantGroups(models) {
|
|
5178
5178
|
const byFamily = /* @__PURE__ */ new Map();
|
|
@@ -5203,7 +5203,7 @@ function buildModelVariantGroups(models) {
|
|
|
5203
5203
|
};
|
|
5204
5204
|
}).toSorted((a, b) => {
|
|
5205
5205
|
if (a.resolution !== b.resolution) return (b.resolution ?? Infinity) - (a.resolution ?? Infinity);
|
|
5206
|
-
if (a.optimization !== b.optimization) return a.optimization === "
|
|
5206
|
+
if (a.optimization !== b.optimization) return a.optimization === "test" ? 1 : -1;
|
|
5207
5207
|
return PRECISION_ORDER.indexOf(a.precision) - PRECISION_ORDER.indexOf(b.precision);
|
|
5208
5208
|
});
|
|
5209
5209
|
const base = options.find((o) => o.precision === "fp32" && o.optimization === "standard") ?? options[0];
|
|
@@ -5416,11 +5416,11 @@ var ModelVariantGroupSchema = zod.z.object({
|
|
|
5416
5416
|
/** Quantization axis. Omit ⇒ the fp32 base build. */
|
|
5417
5417
|
precision: zod.z.enum(["fp32", "int8"]).optional(),
|
|
5418
5418
|
/**
|
|
5419
|
-
*
|
|
5420
|
-
*
|
|
5421
|
-
*
|
|
5419
|
+
* Training / latency-variant axis. Omit ⇒ the standard build. `test` marks
|
|
5420
|
+
* an alternate training of the same family (Scrypted `relu_test`); chip
|
|
5421
|
+
* label is "Test".
|
|
5422
5422
|
*/
|
|
5423
|
-
optimization: zod.z.enum(["standard", "
|
|
5423
|
+
optimization: zod.z.enum(["standard", "test"]).optional(),
|
|
5424
5424
|
/**
|
|
5425
5425
|
* Input-resolution axis (square input side, px). Omit ⇒ the family's native
|
|
5426
5426
|
* resolution (640 for yolo26). Reduced-input builds (320 / 256) are a big,
|
|
@@ -5495,9 +5495,10 @@ var ModelLicenseRecordSchema = zod.z.object({
|
|
|
5495
5495
|
* are per upstream. A persisted custom-model row written when this field was a
|
|
5496
5496
|
* string still parses — the string is lifted into `{ weights }`.
|
|
5497
5497
|
*
|
|
5498
|
-
* Every licence surface (the
|
|
5499
|
-
*
|
|
5500
|
-
*
|
|
5498
|
+
* Every machine licence surface (`THIRD_PARTY_MODELS.md`, the Hugging Face
|
|
5499
|
+
* model table) is GENERATED from these records by
|
|
5500
|
+
* `scripts/gen-model-licenses.ts` (D661). Operator-facing docs live in
|
|
5501
|
+
* `camstack/docs` → `/docs/detection/models`.
|
|
5501
5502
|
*/
|
|
5502
5503
|
var ModelLicenseSchema = zod.z.preprocess((value) => typeof value === "string" ? { weights: value } : value, ModelLicenseRecordSchema);
|
|
5503
5504
|
var ModelCatalogEntrySchema = zod.z.object({
|
|
@@ -6008,7 +6009,16 @@ var AutomationActionSchema = zod.z.discriminatedUnion("kind", [
|
|
|
6008
6009
|
}),
|
|
6009
6010
|
zod.z.object({
|
|
6010
6011
|
kind: zod.z.literal("cap"),
|
|
6011
|
-
|
|
6012
|
+
/**
|
|
6013
|
+
* One device, several same-family devices (locks / climate family / …),
|
|
6014
|
+
* or `{ $var }` for the device that triggered the run. An array is
|
|
6015
|
+
* fan-out at codegen — each id gets the same cap.method call.
|
|
6016
|
+
*/
|
|
6017
|
+
deviceId: zod.z.union([
|
|
6018
|
+
zod.z.number().int(),
|
|
6019
|
+
zod.z.array(zod.z.number().int()).min(1),
|
|
6020
|
+
zod.z.object({ $var: zod.z.string().min(1) })
|
|
6021
|
+
]),
|
|
6012
6022
|
cap: zod.z.string().min(1),
|
|
6013
6023
|
method: zod.z.string().min(1),
|
|
6014
6024
|
/** Values may carry `{{vars.x}}` slots, which SUBSTITUTE and do not
|
|
@@ -6171,7 +6181,14 @@ function emitTrigger(trigger, index) {
|
|
|
6171
6181
|
function emitAction(action, index) {
|
|
6172
6182
|
switch (action.kind) {
|
|
6173
6183
|
case "wait": return ` case ${index}: await sleep(${j(action.seconds * 1e3)}); break`;
|
|
6174
|
-
case "cap":
|
|
6184
|
+
case "cap":
|
|
6185
|
+
if (Array.isArray(action.deviceId)) return ` case ${index}: {
|
|
6186
|
+
for (const deviceId of ${j(action.deviceId)}) {
|
|
6187
|
+
await actuate(deviceId, ${j(action.cap)}, ${j(action.method)}, ${j(action.args ?? {})}, vars)
|
|
6188
|
+
}
|
|
6189
|
+
break
|
|
6190
|
+
}`;
|
|
6191
|
+
return ` case ${index}: {
|
|
6175
6192
|
const deviceId = ${typeof action.deviceId === "number" ? j(action.deviceId) : `resolveTarget(vars, ${j(action.deviceId.$var)})`}
|
|
6176
6193
|
await actuate(deviceId, ${j(action.cap)}, ${j(action.method)}, ${j(action.args ?? {})}, vars)
|
|
6177
6194
|
break
|
|
@@ -6405,11 +6422,13 @@ export default function block(ctx: AddonContext) {
|
|
|
6405
6422
|
): Promise<void> {
|
|
6406
6423
|
const resolved: Record<string, unknown> = {}
|
|
6407
6424
|
for (const [k, v] of Object.entries(args)) resolved[k] = substitute(v, vars)
|
|
6425
|
+
// Forked-addon ctx.api namespaces are tRPC Proxies over a noop function
|
|
6426
|
+
// (typeof === 'function'), not plain objects — reject only null/undefined.
|
|
6408
6427
|
const client: unknown = Reflect.get(ctx.api, capToRouterKey(cap))
|
|
6409
6428
|
const proc: unknown =
|
|
6410
|
-
|
|
6429
|
+
client !== null && client !== undefined ? Reflect.get(client as object, method) : undefined
|
|
6411
6430
|
const mutate: unknown =
|
|
6412
|
-
|
|
6431
|
+
proc !== null && proc !== undefined ? Reflect.get(proc as object, 'mutate') : undefined
|
|
6413
6432
|
if (typeof mutate !== 'function') {
|
|
6414
6433
|
throw new Error('no such device method: ' + cap + '.' + method)
|
|
6415
6434
|
}
|
|
@@ -12441,7 +12460,7 @@ var detectionPipelineCapability = {
|
|
|
12441
12460
|
* This matters here more than anywhere else in the repo, because every provider
|
|
12442
12461
|
* that knows a device's host knows its PASSWORD too: `{ host, port, username,
|
|
12443
12462
|
* password }` sit in one object on Hikvision, Amcrest, Reolink and ONVIF alike,
|
|
12444
|
-
* and `http://admin:hunter2@192.168.
|
|
12463
|
+
* and `http://admin:hunter2@192.168.x.x/` is a URL a browser accepts. The
|
|
12445
12464
|
* camera's own page will ask for its own login. That is correct, and pre-
|
|
12446
12465
|
* filling it is the operator's business, not ours.
|
|
12447
12466
|
*
|
|
@@ -17327,9 +17346,15 @@ var modelConvertCapability = {
|
|
|
17327
17346
|
* needs the Moleculer broker + the deploy-stage registry, which a forked addon
|
|
17328
17347
|
* can't reach. `addon-model-studio` drives it via `ctx.api` and owns the
|
|
17329
17348
|
* per-node availability map.
|
|
17349
|
+
*
|
|
17350
|
+
* The destination is `targetNodeId`, NOT `nodeId`. Cap routers and the
|
|
17351
|
+
* Moleculer tRPC link strip an input field named `nodeId` and use it as a
|
|
17352
|
+
* route pin (resolve the provider ON that node). Naming the destination
|
|
17353
|
+
* `nodeId` routed the call to the agent — which does not host this
|
|
17354
|
+
* singleton — and handed the provider an input with the destination missing.
|
|
17330
17355
|
*/
|
|
17331
17356
|
var ModelDistributeInputSchema = zod.z.object({
|
|
17332
|
-
|
|
17357
|
+
targetNodeId: zod.z.string(),
|
|
17333
17358
|
modelId: zod.z.string(),
|
|
17334
17359
|
format: zod.z.enum(MODEL_FORMATS),
|
|
17335
17360
|
entry: ModelCatalogEntrySchema
|
|
@@ -21504,12 +21529,33 @@ var NC_ALARM_NONBLOCKING_MAX = 200;
|
|
|
21504
21529
|
var NcAlarmDelaySecSchema = zod.z.number().int().min(0).max(600);
|
|
21505
21530
|
var NcAlarmTriggeredSecSchema = zod.z.number().int().min(0).max(NC_ALARM_TRIGGERED_MAX_SEC);
|
|
21506
21531
|
var uniqueModes = (entries) => new Set(entries.map((e) => e.mode)).size === entries.length;
|
|
21532
|
+
/**
|
|
21533
|
+
* What the panel does when a bounded triggered window ends.
|
|
21534
|
+
* - `rearmAfter` — return to the armed mode
|
|
21535
|
+
* - `disableAfter` — auto-disarm
|
|
21536
|
+
* - `doNothing` — stay triggered until a human disarms
|
|
21537
|
+
*/
|
|
21538
|
+
var NcAlarmPostTriggeredActionSchema = zod.z.enum([
|
|
21539
|
+
"rearmAfter",
|
|
21540
|
+
"disableAfter",
|
|
21541
|
+
"doNothing"
|
|
21542
|
+
]);
|
|
21507
21543
|
/** One mode's OVERRIDES. An absent field inherits the global value (D697). */
|
|
21508
21544
|
var NcAlarmModeDelaysSchema = zod.z.object({
|
|
21509
21545
|
mode: AlarmArmModeSchema,
|
|
21510
21546
|
exitDelaySec: NcAlarmDelaySecSchema.optional(),
|
|
21511
21547
|
entryDelaySec: NcAlarmDelaySecSchema.optional(),
|
|
21512
|
-
|
|
21548
|
+
/**
|
|
21549
|
+
* Duration of `triggered` before {@link postTriggeredAction}. Kept as the
|
|
21550
|
+
* historical field name so older clients still read/write a number.
|
|
21551
|
+
*/
|
|
21552
|
+
triggeredDurationSec: NcAlarmTriggeredSecSchema.optional(),
|
|
21553
|
+
postTriggeredAction: NcAlarmPostTriggeredActionSchema.optional(),
|
|
21554
|
+
/**
|
|
21555
|
+
* When this mode may be armed. Absent / null = always allowed (same as a
|
|
21556
|
+
* rule with no `schedule`). Evaluated with {@link isScheduleActive}.
|
|
21557
|
+
*/
|
|
21558
|
+
schedule: NcScheduleSchema.optional()
|
|
21513
21559
|
});
|
|
21514
21560
|
var NcAlarmModeDelaysListSchema = zod.z.array(NcAlarmModeDelaysSchema).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
|
|
21515
21561
|
/**
|
|
@@ -21521,7 +21567,10 @@ var NcAlarmModeDelaysEditSchema = zod.z.object({
|
|
|
21521
21567
|
mode: AlarmArmModeSchema,
|
|
21522
21568
|
exitDelaySec: NcAlarmDelaySecSchema.nullable().optional(),
|
|
21523
21569
|
entryDelaySec: NcAlarmDelaySecSchema.nullable().optional(),
|
|
21524
|
-
triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional()
|
|
21570
|
+
triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional(),
|
|
21571
|
+
postTriggeredAction: NcAlarmPostTriggeredActionSchema.nullable().optional(),
|
|
21572
|
+
/** Set a schedule, or `null` to clear (mode always allowed again). */
|
|
21573
|
+
schedule: NcScheduleSchema.nullable().optional()
|
|
21525
21574
|
});
|
|
21526
21575
|
var NcAlarmModeDelaysEditListSchema = zod.z.array(NcAlarmModeDelaysEditSchema).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
|
|
21527
21576
|
/** One switch of the alarm table: put ONE device on, or take it off, ONE mode's list. */
|
|
@@ -21594,12 +21643,18 @@ var NcAlarmSettingsSchema = zod.z.object({
|
|
|
21594
21643
|
/** Grace period between a trigger and the alarm firing. 0 = immediate. */
|
|
21595
21644
|
entryDelaySec: NcAlarmDelaySecSchema,
|
|
21596
21645
|
/**
|
|
21597
|
-
* How long `triggered` lasts before
|
|
21598
|
-
*
|
|
21599
|
-
*
|
|
21646
|
+
* How long `triggered` lasts before {@link postTriggeredAction} runs.
|
|
21647
|
+
* Ignored when the action is `doNothing`. Historical name kept so older
|
|
21648
|
+
* clients still round-trip a number.
|
|
21600
21649
|
*/
|
|
21601
21650
|
triggeredDurationSec: NcAlarmTriggeredSecSchema,
|
|
21602
21651
|
/**
|
|
21652
|
+
* What happens when the triggered window ends. Absent on a blob older than
|
|
21653
|
+
* this field → derived from {@link triggeredDurationSec} (`>0` ⇒ rearmAfter,
|
|
21654
|
+
* else doNothing).
|
|
21655
|
+
*/
|
|
21656
|
+
postTriggeredAction: NcAlarmPostTriggeredActionSchema.optional(),
|
|
21657
|
+
/**
|
|
21603
21658
|
* Deprecated by D630 — every transition is announced. Parsed, never read;
|
|
21604
21659
|
* remove after one release. Optional so an older admin's patch (which still
|
|
21605
21660
|
* sends it) parses rather than failing the whole save.
|
|
@@ -22745,39 +22800,19 @@ var CLUSTER_MODEL_SCOPED_STEPS = [{
|
|
|
22745
22800
|
label: "Face recognition model",
|
|
22746
22801
|
defaultModelId: "auraface-r100",
|
|
22747
22802
|
indexName: "the enrolled face gallery",
|
|
22748
|
-
options: [
|
|
22749
|
-
|
|
22750
|
-
|
|
22751
|
-
|
|
22752
|
-
},
|
|
22753
|
-
{
|
|
22754
|
-
id: "arcface-r100",
|
|
22755
|
-
label: "ArcFace (ResNet34)"
|
|
22756
|
-
},
|
|
22757
|
-
{
|
|
22758
|
-
id: "inception-resnet-v1",
|
|
22759
|
-
label: "Inception ResNet V1"
|
|
22760
|
-
}
|
|
22761
|
-
]
|
|
22803
|
+
options: [{
|
|
22804
|
+
id: "auraface-r100",
|
|
22805
|
+
label: "AuraFace R100"
|
|
22806
|
+
}]
|
|
22762
22807
|
}, {
|
|
22763
22808
|
stepId: "clip-embedding",
|
|
22764
22809
|
label: "Semantic search model",
|
|
22765
|
-
defaultModelId: "
|
|
22810
|
+
defaultModelId: "siglip2-b16-224",
|
|
22766
22811
|
indexName: "the object semantic-search index",
|
|
22767
|
-
options: [
|
|
22768
|
-
|
|
22769
|
-
|
|
22770
|
-
|
|
22771
|
-
},
|
|
22772
|
-
{
|
|
22773
|
-
id: "mobileclip-s2",
|
|
22774
|
-
label: "MobileCLIP S2"
|
|
22775
|
-
},
|
|
22776
|
-
{
|
|
22777
|
-
id: "siglip2-b16-224",
|
|
22778
|
-
label: "SigLIP2 B/16 (Apache-2.0)"
|
|
22779
|
-
}
|
|
22780
|
-
]
|
|
22812
|
+
options: [{
|
|
22813
|
+
id: "siglip2-b16-224",
|
|
22814
|
+
label: "SigLIP2 B/16 (Apache-2.0)"
|
|
22815
|
+
}]
|
|
22781
22816
|
}];
|
|
22782
22817
|
/**
|
|
22783
22818
|
* Store identity of the cluster row inside `pipeline-orchestrator`'s GLOBAL
|
|
@@ -37050,7 +37085,7 @@ var LocalInterfaceSchema = zod.z.object({
|
|
|
37050
37085
|
name: zod.z.string(),
|
|
37051
37086
|
family: zod.z.enum(["IPv4", "IPv6"]),
|
|
37052
37087
|
address: zod.z.string(),
|
|
37053
|
-
/** CIDR shorthand (e.g. `192.168.
|
|
37088
|
+
/** CIDR shorthand (e.g. `192.168.x.x/24`). Empty when OS doesn't expose. */
|
|
37054
37089
|
cidr: zod.z.string(),
|
|
37055
37090
|
/** OS netmask. Stable across calls so the SDK can hash on it. */
|
|
37056
37091
|
netmask: zod.z.string(),
|
|
@@ -37249,7 +37284,7 @@ var localNetworkCapability = {
|
|
|
37249
37284
|
* every client a second authority on a socket only the hub binds. A viewer
|
|
37250
37285
|
* configured with a port-less public URL (`https://camstack.example.top`)
|
|
37251
37286
|
* infers 443 from the scheme, asks with 443, and was handed
|
|
37252
|
-
* `https://192.168.
|
|
37287
|
+
* `https://192.168.x.x:443` for a hub listening on 4443. That candidate
|
|
37253
37288
|
* cannot ever answer, and losing its race reads in the log exactly like
|
|
37254
37289
|
* "the LAN was tried and it was slower" — so an operator sitting on his own
|
|
37255
37290
|
* WiFi stayed on the public tunnel for weeks, with the LAN candidate born
|
|
@@ -37708,7 +37743,7 @@ var MeshPeerSchema = zod.z.object({
|
|
|
37708
37743
|
tags: zod.z.array(zod.z.string()).readonly(),
|
|
37709
37744
|
/** True when the peer advertises itself as an exit-node candidate. */
|
|
37710
37745
|
exitNodeOption: zod.z.boolean(),
|
|
37711
|
-
/** Subnet routes the peer advertises (e.g. `["192.168.
|
|
37746
|
+
/** Subnet routes the peer advertises (e.g. `["192.168.x.x/24"]`). */
|
|
37712
37747
|
advertisedRoutes: zod.z.array(zod.z.string()).readonly(),
|
|
37713
37748
|
/** Owner account login (e.g. `foo@example.com`). Null for tagged peers. */
|
|
37714
37749
|
userLogin: zod.z.string().nullable(),
|
|
@@ -39386,7 +39421,13 @@ var OsdOverlaySchema = zod.z.object({
|
|
|
39386
39421
|
*/
|
|
39387
39422
|
availablePositions: zod.z.array(OsdPositionEnum).readonly(),
|
|
39388
39423
|
/** Firmware does not allow editing the `text` field (e.g. timestamp). */
|
|
39389
|
-
readOnly: zod.z.boolean().optional()
|
|
39424
|
+
readOnly: zod.z.boolean().optional(),
|
|
39425
|
+
/**
|
|
39426
|
+
* Firmware text ceiling for this overlay. Absent = no known limit.
|
|
39427
|
+
* The OSD manager truncates here on every write — never stores its own
|
|
39428
|
+
* copy on the binding.
|
|
39429
|
+
*/
|
|
39430
|
+
maxCharacters: zod.z.number().int().positive().optional()
|
|
39390
39431
|
});
|
|
39391
39432
|
var OsdStatusSchema = zod.z.object({ overlays: zod.z.array(OsdOverlaySchema).readonly() });
|
|
39392
39433
|
var OsdOverlayPatchSchema = zod.z.object({
|
|
@@ -39504,7 +39545,9 @@ var OsdTemplateBindingSchema = zod.z.object({
|
|
|
39504
39545
|
valuePath: zod.z.string().min(1).max(64),
|
|
39505
39546
|
/** Convert TO this unit at render (`tryConvertUnit`). Absent = source unit. */
|
|
39506
39547
|
displayUnit: zod.z.string().max(16).optional(),
|
|
39507
|
-
maxDecimals: zod.z.number().int().min(0).max(4).default(1)
|
|
39548
|
+
maxDecimals: zod.z.number().int().min(0).max(4).default(1),
|
|
39549
|
+
/** Raw value → display text (same shape as slot binding). Empty string hides. */
|
|
39550
|
+
valueMap: zod.z.record(zod.z.string(), zod.z.string()).optional()
|
|
39508
39551
|
});
|
|
39509
39552
|
/**
|
|
39510
39553
|
* A named template: bindings (alias → leaf field) + a parser that
|
|
@@ -39554,18 +39597,11 @@ var OsdSlotBindingSchema = zod.z.object({
|
|
|
39554
39597
|
source: OsdSourceSchema,
|
|
39555
39598
|
/** `${value}` and `${unit}` are substituted; every occurrence. */
|
|
39556
39599
|
template: zod.z.string().max(96).default("${value}"),
|
|
39557
|
-
/** Truncate with an ellipsis past this length. Absent = no limit. */
|
|
39558
|
-
maxCharacters: zod.z.number().int().min(4).max(64).optional(),
|
|
39559
39600
|
/**
|
|
39560
39601
|
* Decimal places for a numeric value. `0` yields an integer — the
|
|
39561
39602
|
* documented workaround for firmwares that reject `.` in overlay text.
|
|
39562
39603
|
*/
|
|
39563
39604
|
maxDecimals: zod.z.number().int().min(0).max(4).default(1),
|
|
39564
|
-
/**
|
|
39565
|
-
* Appended via `${unit}` when no unit conversion produces a label.
|
|
39566
|
-
* Prefer `source.displayUnit` for converted device-state values.
|
|
39567
|
-
*/
|
|
39568
|
-
unitLabel: zod.z.string().max(8).optional(),
|
|
39569
39605
|
/** Raw value → display text, e.g. `{"true":"MOTION","false":""}`. */
|
|
39570
39606
|
valueMap: zod.z.record(zod.z.string(), zod.z.string()).optional(),
|
|
39571
39607
|
/** Time windows in which the slot is shown. Absent = always. */
|
|
@@ -39574,9 +39610,7 @@ var OsdSlotBindingSchema = zod.z.object({
|
|
|
39574
39610
|
* Display gate, in the notification centre's condition vocabulary.
|
|
39575
39611
|
* Only the keys reported by `getConditionSupport` are accepted.
|
|
39576
39612
|
*/
|
|
39577
|
-
conditions: NcConditionsSchema.optional()
|
|
39578
|
-
/** Rendered when the gate is closed or the value unreadable. Empty = hide. */
|
|
39579
|
-
fallbackText: zod.z.string().max(64).default("")
|
|
39613
|
+
conditions: NcConditionsSchema.optional()
|
|
39580
39614
|
});
|
|
39581
39615
|
/** One camera slot, as the operator sees it: firmware truth + our binding. */
|
|
39582
39616
|
var OsdSlotViewSchema = zod.z.object({
|
|
@@ -57700,6 +57734,62 @@ var DEVICE_DO_ACTIONS = [
|
|
|
57700
57734
|
method: "stop",
|
|
57701
57735
|
args: {}
|
|
57702
57736
|
},
|
|
57737
|
+
{
|
|
57738
|
+
id: "valve.open",
|
|
57739
|
+
label: "Open valve",
|
|
57740
|
+
cap: "valve",
|
|
57741
|
+
method: "open",
|
|
57742
|
+
args: {}
|
|
57743
|
+
},
|
|
57744
|
+
{
|
|
57745
|
+
id: "valve.close",
|
|
57746
|
+
label: "Close valve",
|
|
57747
|
+
cap: "valve",
|
|
57748
|
+
method: "close",
|
|
57749
|
+
args: {}
|
|
57750
|
+
},
|
|
57751
|
+
{
|
|
57752
|
+
id: "valve.stop",
|
|
57753
|
+
label: "Stop valve",
|
|
57754
|
+
cap: "valve",
|
|
57755
|
+
method: "stop",
|
|
57756
|
+
args: {}
|
|
57757
|
+
},
|
|
57758
|
+
{
|
|
57759
|
+
id: "humidifier.on",
|
|
57760
|
+
label: "Humidifier on",
|
|
57761
|
+
cap: "humidifier",
|
|
57762
|
+
method: "setOn",
|
|
57763
|
+
args: { on: true }
|
|
57764
|
+
},
|
|
57765
|
+
{
|
|
57766
|
+
id: "humidifier.off",
|
|
57767
|
+
label: "Humidifier off",
|
|
57768
|
+
cap: "humidifier",
|
|
57769
|
+
method: "setOn",
|
|
57770
|
+
args: { on: false }
|
|
57771
|
+
},
|
|
57772
|
+
{
|
|
57773
|
+
id: "waterHeater.off",
|
|
57774
|
+
label: "Water heater off",
|
|
57775
|
+
cap: "water-heater",
|
|
57776
|
+
method: "setOperationMode",
|
|
57777
|
+
args: { mode: "off" }
|
|
57778
|
+
},
|
|
57779
|
+
{
|
|
57780
|
+
id: "waterHeater.awayOn",
|
|
57781
|
+
label: "Water heater away on",
|
|
57782
|
+
cap: "water-heater",
|
|
57783
|
+
method: "setAway",
|
|
57784
|
+
args: { on: true }
|
|
57785
|
+
},
|
|
57786
|
+
{
|
|
57787
|
+
id: "waterHeater.awayOff",
|
|
57788
|
+
label: "Water heater away off",
|
|
57789
|
+
cap: "water-heater",
|
|
57790
|
+
method: "setAway",
|
|
57791
|
+
args: { on: false }
|
|
57792
|
+
},
|
|
57703
57793
|
{
|
|
57704
57794
|
id: "climate.off",
|
|
57705
57795
|
label: "Climate off",
|
|
@@ -57770,6 +57860,115 @@ var DEVICE_DO_ACTIONS = [
|
|
|
57770
57860
|
method: "returnToBase",
|
|
57771
57861
|
args: {}
|
|
57772
57862
|
},
|
|
57863
|
+
{
|
|
57864
|
+
id: "lawnMower.start",
|
|
57865
|
+
label: "Start mowing",
|
|
57866
|
+
cap: "lawn-mower-control",
|
|
57867
|
+
method: "startMowing",
|
|
57868
|
+
args: {}
|
|
57869
|
+
},
|
|
57870
|
+
{
|
|
57871
|
+
id: "lawnMower.pause",
|
|
57872
|
+
label: "Pause mower",
|
|
57873
|
+
cap: "lawn-mower-control",
|
|
57874
|
+
method: "pause",
|
|
57875
|
+
args: {}
|
|
57876
|
+
},
|
|
57877
|
+
{
|
|
57878
|
+
id: "lawnMower.dock",
|
|
57879
|
+
label: "Dock mower",
|
|
57880
|
+
cap: "lawn-mower-control",
|
|
57881
|
+
method: "dock",
|
|
57882
|
+
args: {}
|
|
57883
|
+
},
|
|
57884
|
+
{
|
|
57885
|
+
id: "media.play",
|
|
57886
|
+
label: "Play",
|
|
57887
|
+
cap: "media-player",
|
|
57888
|
+
method: "play",
|
|
57889
|
+
args: {}
|
|
57890
|
+
},
|
|
57891
|
+
{
|
|
57892
|
+
id: "media.pause",
|
|
57893
|
+
label: "Pause media",
|
|
57894
|
+
cap: "media-player",
|
|
57895
|
+
method: "pause",
|
|
57896
|
+
args: {}
|
|
57897
|
+
},
|
|
57898
|
+
{
|
|
57899
|
+
id: "media.stop",
|
|
57900
|
+
label: "Stop media",
|
|
57901
|
+
cap: "media-player",
|
|
57902
|
+
method: "stop",
|
|
57903
|
+
args: {}
|
|
57904
|
+
},
|
|
57905
|
+
{
|
|
57906
|
+
id: "media.next",
|
|
57907
|
+
label: "Next track",
|
|
57908
|
+
cap: "media-player",
|
|
57909
|
+
method: "next",
|
|
57910
|
+
args: {}
|
|
57911
|
+
},
|
|
57912
|
+
{
|
|
57913
|
+
id: "media.previous",
|
|
57914
|
+
label: "Previous track",
|
|
57915
|
+
cap: "media-player",
|
|
57916
|
+
method: "previous",
|
|
57917
|
+
args: {}
|
|
57918
|
+
},
|
|
57919
|
+
{
|
|
57920
|
+
id: "script.run",
|
|
57921
|
+
label: "Run script",
|
|
57922
|
+
cap: "script-runner",
|
|
57923
|
+
method: "run",
|
|
57924
|
+
args: {}
|
|
57925
|
+
},
|
|
57926
|
+
{
|
|
57927
|
+
id: "script.stop",
|
|
57928
|
+
label: "Stop script",
|
|
57929
|
+
cap: "script-runner",
|
|
57930
|
+
method: "stop",
|
|
57931
|
+
args: {}
|
|
57932
|
+
},
|
|
57933
|
+
{
|
|
57934
|
+
id: "haAutomation.enable",
|
|
57935
|
+
label: "Enable automation",
|
|
57936
|
+
cap: "automation-control",
|
|
57937
|
+
method: "enable",
|
|
57938
|
+
args: {}
|
|
57939
|
+
},
|
|
57940
|
+
{
|
|
57941
|
+
id: "haAutomation.disable",
|
|
57942
|
+
label: "Disable automation",
|
|
57943
|
+
cap: "automation-control",
|
|
57944
|
+
method: "disable",
|
|
57945
|
+
args: {}
|
|
57946
|
+
},
|
|
57947
|
+
{
|
|
57948
|
+
id: "haAutomation.trigger",
|
|
57949
|
+
label: "Trigger automation",
|
|
57950
|
+
cap: "automation-control",
|
|
57951
|
+
method: "trigger",
|
|
57952
|
+
args: {}
|
|
57953
|
+
},
|
|
57954
|
+
{
|
|
57955
|
+
id: "petFeeder.feed",
|
|
57956
|
+
label: "Feed",
|
|
57957
|
+
cap: "pet-feeder",
|
|
57958
|
+
method: "feed",
|
|
57959
|
+
openArgs: [{
|
|
57960
|
+
key: "grams",
|
|
57961
|
+
label: "Grams",
|
|
57962
|
+
kind: "number"
|
|
57963
|
+
}]
|
|
57964
|
+
},
|
|
57965
|
+
{
|
|
57966
|
+
id: "petFeeder.callPet",
|
|
57967
|
+
label: "Call pet",
|
|
57968
|
+
cap: "pet-feeder",
|
|
57969
|
+
method: "callPet",
|
|
57970
|
+
args: {}
|
|
57971
|
+
},
|
|
57773
57972
|
{
|
|
57774
57973
|
id: "ptz.goHome",
|
|
57775
57974
|
label: "PTZ go home",
|
|
@@ -57997,6 +58196,94 @@ function bakedArgsEqual(action, args) {
|
|
|
57997
58196
|
return argsEqual(action.args, args);
|
|
57998
58197
|
}
|
|
57999
58198
|
/**
|
|
58199
|
+
* Catalogue caps a `DeviceType` is expected to offer in the Do picker.
|
|
58200
|
+
*
|
|
58201
|
+
* Exhaustive over {@link DeviceType}: adding a new enum member without an
|
|
58202
|
+
* entry fails the TypeScript build here (same pattern as
|
|
58203
|
+
* {@link DEVICE_TYPE_CONTROL_KIND}). An empty list is a deliberate choice
|
|
58204
|
+
* for read-only / non-actuatable types — never "forgotten".
|
|
58205
|
+
*
|
|
58206
|
+
* Camera accessories (ptz, privacy-mask, …) are listed on Camera even though
|
|
58207
|
+
* a given camera may bind only a subset; {@link actionsForBoundCaps} still
|
|
58208
|
+
* filters to what the device actually binds.
|
|
58209
|
+
*/
|
|
58210
|
+
var DEVICE_TYPE_DO_CAPS = {
|
|
58211
|
+
[require_err_msg.DeviceType.Camera]: [
|
|
58212
|
+
"ptz",
|
|
58213
|
+
"ptz-autotrack",
|
|
58214
|
+
"privacy-mask",
|
|
58215
|
+
"day-night",
|
|
58216
|
+
"reboot",
|
|
58217
|
+
"motion-trigger"
|
|
58218
|
+
],
|
|
58219
|
+
[require_err_msg.DeviceType.Hub]: [],
|
|
58220
|
+
[require_err_msg.DeviceType.Light]: ["switch", "brightness"],
|
|
58221
|
+
[require_err_msg.DeviceType.Siren]: ["switch", "motion-trigger"],
|
|
58222
|
+
[require_err_msg.DeviceType.Switch]: ["switch", "motion-trigger"],
|
|
58223
|
+
[require_err_msg.DeviceType.Sensor]: [],
|
|
58224
|
+
[require_err_msg.DeviceType.Thermostat]: ["climate-control"],
|
|
58225
|
+
[require_err_msg.DeviceType.Climate]: ["climate-control"],
|
|
58226
|
+
[require_err_msg.DeviceType.Button]: ["button"],
|
|
58227
|
+
[require_err_msg.DeviceType.EventEmitter]: [],
|
|
58228
|
+
[require_err_msg.DeviceType.Update]: [],
|
|
58229
|
+
[require_err_msg.DeviceType.Generic]: [],
|
|
58230
|
+
[require_err_msg.DeviceType.Notifier]: [],
|
|
58231
|
+
[require_err_msg.DeviceType.Script]: ["script-runner"],
|
|
58232
|
+
[require_err_msg.DeviceType.Automation]: ["automation-control"],
|
|
58233
|
+
[require_err_msg.DeviceType.Lock]: ["lock-control"],
|
|
58234
|
+
[require_err_msg.DeviceType.Cover]: ["cover"],
|
|
58235
|
+
[require_err_msg.DeviceType.Valve]: ["valve"],
|
|
58236
|
+
[require_err_msg.DeviceType.Humidifier]: ["humidifier"],
|
|
58237
|
+
[require_err_msg.DeviceType.WaterHeater]: ["water-heater"],
|
|
58238
|
+
[require_err_msg.DeviceType.Fan]: ["fan-control", "switch"],
|
|
58239
|
+
[require_err_msg.DeviceType.MediaPlayer]: ["media-player"],
|
|
58240
|
+
[require_err_msg.DeviceType.AlarmPanel]: ["alarm-panel"],
|
|
58241
|
+
[require_err_msg.DeviceType.Control]: [],
|
|
58242
|
+
[require_err_msg.DeviceType.Presence]: [],
|
|
58243
|
+
[require_err_msg.DeviceType.Weather]: [],
|
|
58244
|
+
[require_err_msg.DeviceType.Vacuum]: ["vacuum-control"],
|
|
58245
|
+
[require_err_msg.DeviceType.LawnMower]: ["lawn-mower-control"],
|
|
58246
|
+
[require_err_msg.DeviceType.Container]: [],
|
|
58247
|
+
[require_err_msg.DeviceType.Image]: [],
|
|
58248
|
+
[require_err_msg.DeviceType.PetFeeder]: ["pet-feeder"]
|
|
58249
|
+
};
|
|
58250
|
+
/**
|
|
58251
|
+
* Whether a device type belongs in a Do / automation action device picker.
|
|
58252
|
+
*
|
|
58253
|
+
* Containers stay in {@link DEVICE_TYPE_DO_CAPS} (empty, for exhaustiveness)
|
|
58254
|
+
* but must never appear as selectable targets — actuate the children instead.
|
|
58255
|
+
*/
|
|
58256
|
+
function isDoPickerDeviceType(type) {
|
|
58257
|
+
return type !== require_err_msg.DeviceType.Container;
|
|
58258
|
+
}
|
|
58259
|
+
/**
|
|
58260
|
+
* Do-picker family id — devices that share one may be multi-selected for
|
|
58261
|
+
* the same action (several locks, the climate family, cover+valve, …).
|
|
58262
|
+
*
|
|
58263
|
+
* Distinct from {@link DeviceControlKind}: humidifier / water-heater keep
|
|
58264
|
+
* their own control widgets but author with climate siblings.
|
|
58265
|
+
*/
|
|
58266
|
+
function deviceDoFamily(type) {
|
|
58267
|
+
switch (type) {
|
|
58268
|
+
case require_err_msg.DeviceType.Climate:
|
|
58269
|
+
case require_err_msg.DeviceType.Thermostat:
|
|
58270
|
+
case require_err_msg.DeviceType.Humidifier:
|
|
58271
|
+
case require_err_msg.DeviceType.WaterHeater: return "climate-family";
|
|
58272
|
+
case require_err_msg.DeviceType.Cover:
|
|
58273
|
+
case require_err_msg.DeviceType.Valve: return "cover-family";
|
|
58274
|
+
case require_err_msg.DeviceType.Switch:
|
|
58275
|
+
case require_err_msg.DeviceType.Siren:
|
|
58276
|
+
case require_err_msg.DeviceType.Light: return "switch-family";
|
|
58277
|
+
case require_err_msg.DeviceType.Vacuum:
|
|
58278
|
+
case require_err_msg.DeviceType.LawnMower: return "robot-family";
|
|
58279
|
+
default: return type;
|
|
58280
|
+
}
|
|
58281
|
+
}
|
|
58282
|
+
/** True when two device types may share one multi-target Do step. */
|
|
58283
|
+
function sameDoFamily(leftType, rightType) {
|
|
58284
|
+
return deviceDoFamily(leftType) === deviceDoFamily(rightType);
|
|
58285
|
+
}
|
|
58286
|
+
/**
|
|
58000
58287
|
* Actions offered for a device that binds the given caps.
|
|
58001
58288
|
*
|
|
58002
58289
|
* Only catalogue entries whose cap is bound AND still actuatable in
|
|
@@ -58007,6 +58294,50 @@ function actionsForBoundCaps(boundCaps) {
|
|
|
58007
58294
|
const set = new Set(boundCaps);
|
|
58008
58295
|
return DEVICE_DO_ACTIONS.filter((action) => set.has(action.cap) && isDoActionActuatable(action));
|
|
58009
58296
|
}
|
|
58297
|
+
/**
|
|
58298
|
+
* Catalogue actions for a wire `DeviceType` string — the fallback when
|
|
58299
|
+
* bindings have not answered yet (or answered empty for a typed actuator).
|
|
58300
|
+
* Unknown type strings → empty.
|
|
58301
|
+
*/
|
|
58302
|
+
function actionsForDeviceType(type) {
|
|
58303
|
+
if (!Object.values(require_err_msg.DeviceType).includes(type)) return [];
|
|
58304
|
+
return actionsForBoundCaps(DEVICE_TYPE_DO_CAPS[type]);
|
|
58305
|
+
}
|
|
58306
|
+
/**
|
|
58307
|
+
* Union of bound-cap actions with the type's expected catalogue caps.
|
|
58308
|
+
*
|
|
58309
|
+
* Bindings win for filtering (a lock without `lock-control` bound still
|
|
58310
|
+
* offers nothing from bindings alone); the type map fills gaps when the
|
|
58311
|
+
* binding read is empty so a Lock / Valve / Climate never shows
|
|
58312
|
+
* "No actions for this device" solely because getBindings lagged.
|
|
58313
|
+
*/
|
|
58314
|
+
function actionsForDevice(input) {
|
|
58315
|
+
const fromBound = input.boundCaps !== void 0 && input.boundCaps.length > 0 ? actionsForBoundCaps(input.boundCaps) : [];
|
|
58316
|
+
if (fromBound.length > 0) return fromBound;
|
|
58317
|
+
if (input.deviceType !== void 0 && input.deviceType.length > 0) return actionsForDeviceType(input.deviceType);
|
|
58318
|
+
return [];
|
|
58319
|
+
}
|
|
58320
|
+
/**
|
|
58321
|
+
* Intersection of {@link actionsForDevice} across several targets — what a
|
|
58322
|
+
* multi-select same-family Do step may offer.
|
|
58323
|
+
*/
|
|
58324
|
+
function actionsForDevices(targets) {
|
|
58325
|
+
if (targets.length === 0) return [];
|
|
58326
|
+
let common = null;
|
|
58327
|
+
for (const target of targets) {
|
|
58328
|
+
const offered = actionsForDevice({
|
|
58329
|
+
boundCaps: target.boundCaps,
|
|
58330
|
+
deviceType: target.deviceType
|
|
58331
|
+
});
|
|
58332
|
+
if (common === null) {
|
|
58333
|
+
common = offered;
|
|
58334
|
+
continue;
|
|
58335
|
+
}
|
|
58336
|
+
const ids = new Set(offered.map((a) => a.id));
|
|
58337
|
+
common = common.filter((a) => ids.has(a.id));
|
|
58338
|
+
}
|
|
58339
|
+
return common ?? [];
|
|
58340
|
+
}
|
|
58010
58341
|
/** The whole catalogue (still actuatable) — for a `{$var}` automation target. */
|
|
58011
58342
|
function allDoActions() {
|
|
58012
58343
|
return DEVICE_DO_ACTIONS.filter(isDoActionActuatable);
|
|
@@ -67333,6 +67664,10 @@ function bindingPullsAlarmTrigger(binding, sequenceActionsOf) {
|
|
|
67333
67664
|
if (steps === void 0) return false;
|
|
67334
67665
|
return steps.some((step) => step.kind === "cap" && step.cap === ALARM_PANEL_CAP && step.method === ALARM_PANEL_TRIGGER_METHOD);
|
|
67335
67666
|
}
|
|
67667
|
+
/** True when the rule's deviceState gate names any `armed_*` word. */
|
|
67668
|
+
function ruleGatedOnArmedState(rule) {
|
|
67669
|
+
return (rule.conditions.deviceState?.states ?? []).some((s) => s.trim().toLowerCase().startsWith(ARMED_WORD_PREFIX));
|
|
67670
|
+
}
|
|
67336
67671
|
/**
|
|
67337
67672
|
* A rule belongs to the alarm when its `deviceState` gate names ANY device's
|
|
67338
67673
|
* `armed_*` word, or an on-match binding pulls the alarm panel's trigger
|
|
@@ -67340,10 +67675,19 @@ function bindingPullsAlarmTrigger(binding, sequenceActionsOf) {
|
|
|
67340
67675
|
* escalation.
|
|
67341
67676
|
*/
|
|
67342
67677
|
function ruleBelongsToAlarm(rule) {
|
|
67343
|
-
if ((rule
|
|
67678
|
+
if (ruleGatedOnArmedState(rule)) return true;
|
|
67344
67679
|
for (const binding of rule.actions?.onTrigger ?? []) if (bindingPullsAlarmTrigger(binding, rule.sequenceActionsOf)) return true;
|
|
67345
67680
|
return false;
|
|
67346
67681
|
}
|
|
67682
|
+
/**
|
|
67683
|
+
* A rule gated on `armed_*` auto-triggers the CamStack `alarm-panel` on match
|
|
67684
|
+
* — no `onTrigger` sequence required. Sirens are never part of this path.
|
|
67685
|
+
* An explicit `alarm-panel.trigger` binding without an armed gate stays
|
|
67686
|
+
* explicit actuation only ({@link ruleBelongsToAlarm}).
|
|
67687
|
+
*/
|
|
67688
|
+
function ruleAutoTriggersAlarm(rule) {
|
|
67689
|
+
return ruleGatedOnArmedState(rule);
|
|
67690
|
+
}
|
|
67347
67691
|
function isOpeningKind(kind) {
|
|
67348
67692
|
const k = kind.trim().toLowerCase();
|
|
67349
67693
|
return NC_ALARM_OPENING_EVENT_KINDS.some((opening) => opening === k);
|
|
@@ -67409,6 +67753,14 @@ var NC_ALARM_DELAY_FIELDS = [
|
|
|
67409
67753
|
"entryDelaySec",
|
|
67410
67754
|
"triggeredDurationSec"
|
|
67411
67755
|
];
|
|
67756
|
+
/**
|
|
67757
|
+
* Derive the post-triggered action from a stored blob that may predate the field:
|
|
67758
|
+
* a positive duration meant re-arm; zero/absent meant stay triggered.
|
|
67759
|
+
*/
|
|
67760
|
+
function derivePostTriggeredAction(action, triggeredDurationSec) {
|
|
67761
|
+
if (action !== void 0) return action;
|
|
67762
|
+
return triggeredDurationSec > 0 ? "rearmAfter" : "doNothing";
|
|
67763
|
+
}
|
|
67412
67764
|
/** The mode's value when it overrides the field, else the global one. */
|
|
67413
67765
|
function pick(override, global) {
|
|
67414
67766
|
return override === void 0 ? {
|
|
@@ -67425,14 +67777,19 @@ function resolveModeDelays(settings, mode) {
|
|
|
67425
67777
|
const exit = pick(entry?.exitDelaySec, settings.exitDelaySec);
|
|
67426
67778
|
const entryDelay = pick(entry?.entryDelaySec, settings.entryDelaySec);
|
|
67427
67779
|
const triggered = pick(entry?.triggeredDurationSec, settings.triggeredDurationSec);
|
|
67780
|
+
const actionOverride = entry?.postTriggeredAction;
|
|
67781
|
+
const actionSource = actionOverride !== void 0 ? "mode" : "default";
|
|
67782
|
+
const postTriggeredAction = derivePostTriggeredAction(actionOverride ?? settings.postTriggeredAction, triggered.value);
|
|
67428
67783
|
return {
|
|
67429
67784
|
exitDelaySec: exit.value,
|
|
67430
67785
|
entryDelaySec: entryDelay.value,
|
|
67431
67786
|
triggeredDurationSec: triggered.value,
|
|
67787
|
+
postTriggeredAction,
|
|
67432
67788
|
source: {
|
|
67433
67789
|
exitDelaySec: exit.source,
|
|
67434
67790
|
entryDelaySec: entryDelay.source,
|
|
67435
|
-
triggeredDurationSec: triggered.source
|
|
67791
|
+
triggeredDurationSec: triggered.source,
|
|
67792
|
+
postTriggeredAction: actionSource
|
|
67436
67793
|
}
|
|
67437
67794
|
};
|
|
67438
67795
|
}
|
|
@@ -67441,6 +67798,29 @@ function edited(current, edit) {
|
|
|
67441
67798
|
if (edit === void 0) return current;
|
|
67442
67799
|
return edit === null ? void 0 : edit;
|
|
67443
67800
|
}
|
|
67801
|
+
function editedAction(current, edit) {
|
|
67802
|
+
if (edit === void 0) return current;
|
|
67803
|
+
return edit === null ? void 0 : edit;
|
|
67804
|
+
}
|
|
67805
|
+
function editedSchedule(current, edit) {
|
|
67806
|
+
if (edit === void 0) return current;
|
|
67807
|
+
return edit === null ? void 0 : edit;
|
|
67808
|
+
}
|
|
67809
|
+
function sameSchedule(a, b) {
|
|
67810
|
+
if (a === void 0 && b === void 0) return true;
|
|
67811
|
+
if (a === void 0 || b === void 0) return false;
|
|
67812
|
+
if (a.invert !== b.invert || a.timezone !== b.timezone) return false;
|
|
67813
|
+
if (a.windows.length !== b.windows.length) return false;
|
|
67814
|
+
for (let i = 0; i < a.windows.length; i++) {
|
|
67815
|
+
const wa = a.windows[i];
|
|
67816
|
+
const wb = b.windows[i];
|
|
67817
|
+
if (wa === void 0 || wb === void 0) return false;
|
|
67818
|
+
if (wa.startMinute !== wb.startMinute || wa.endMinute !== wb.endMinute) return false;
|
|
67819
|
+
if (wa.days.length !== wb.days.length) return false;
|
|
67820
|
+
for (let d = 0; d < wa.days.length; d++) if (wa.days[d] !== wb.days[d]) return false;
|
|
67821
|
+
}
|
|
67822
|
+
return true;
|
|
67823
|
+
}
|
|
67444
67824
|
/**
|
|
67445
67825
|
* Apply per-field edits to the stored overrides. Returns new arrays, never mutates the input;
|
|
67446
67826
|
* an entry with no field left is dropped (the mode inherits everything again).
|
|
@@ -67454,13 +67834,17 @@ function applyModeDelaysEdits(current, edits) {
|
|
|
67454
67834
|
const exit = edited(base.exitDelaySec, edit.exitDelaySec);
|
|
67455
67835
|
const entry = edited(base.entryDelaySec, edit.entryDelaySec);
|
|
67456
67836
|
const triggered = edited(base.triggeredDurationSec, edit.triggeredDurationSec);
|
|
67837
|
+
const action = editedAction(base.postTriggeredAction, edit.postTriggeredAction);
|
|
67838
|
+
const schedule = editedSchedule(base.schedule, edit.schedule);
|
|
67457
67839
|
if (exit !== void 0) next.exitDelaySec = exit;
|
|
67458
67840
|
if (entry !== void 0) next.entryDelaySec = entry;
|
|
67459
67841
|
if (triggered !== void 0) next.triggeredDurationSec = triggered;
|
|
67842
|
+
if (action !== void 0) next.postTriggeredAction = action;
|
|
67843
|
+
if (schedule !== void 0) next.schedule = schedule;
|
|
67460
67844
|
if (at >= 0) out[at] = next;
|
|
67461
67845
|
else out.push(next);
|
|
67462
67846
|
}
|
|
67463
|
-
return out.filter((e) => e.exitDelaySec !== void 0 || e.entryDelaySec !== void 0 || e.triggeredDurationSec !== void 0);
|
|
67847
|
+
return out.filter((e) => e.exitDelaySec !== void 0 || e.entryDelaySec !== void 0 || e.triggeredDurationSec !== void 0 || e.postTriggeredAction !== void 0 || e.schedule !== void 0);
|
|
67464
67848
|
}
|
|
67465
67849
|
/**
|
|
67466
67850
|
* Put ONE device on, or take it off, ONE mode's device-id list. A no-op answers
|
|
@@ -67588,6 +67972,7 @@ function alarmPatchLanded(patch, returned) {
|
|
|
67588
67972
|
if (patch.exitDelaySec !== void 0 && patch.exitDelaySec !== returned.exitDelaySec) return false;
|
|
67589
67973
|
if (patch.entryDelaySec !== void 0 && patch.entryDelaySec !== returned.entryDelaySec) return false;
|
|
67590
67974
|
if (patch.triggeredDurationSec !== void 0 && patch.triggeredDurationSec !== returned.triggeredDurationSec) return false;
|
|
67975
|
+
if (patch.postTriggeredAction !== void 0 && patch.postTriggeredAction !== derivePostTriggeredAction(returned.postTriggeredAction, returned.triggeredDurationSec)) return false;
|
|
67591
67976
|
if (patch.announceTargets !== void 0 && !sameSet(patch.announceTargets, returned.announceTargets)) return false;
|
|
67592
67977
|
if (patch.nonBlocking !== void 0 && !sameLists(patch.nonBlocking, returned.nonBlocking ?? [])) return false;
|
|
67593
67978
|
if (patch.blocking !== void 0 && !sameLists(patch.blocking, returned.blocking ?? [])) return false;
|
|
@@ -67600,6 +67985,14 @@ function alarmPatchLanded(patch, returned) {
|
|
|
67600
67985
|
const got = fieldOf(entry, field);
|
|
67601
67986
|
if (want === null ? got !== void 0 : got !== want) return false;
|
|
67602
67987
|
}
|
|
67988
|
+
if (edit.postTriggeredAction !== void 0) {
|
|
67989
|
+
const got = entry?.postTriggeredAction;
|
|
67990
|
+
if (edit.postTriggeredAction === null ? got !== void 0 : got !== edit.postTriggeredAction) return false;
|
|
67991
|
+
}
|
|
67992
|
+
if (edit.schedule !== void 0) {
|
|
67993
|
+
const got = entry?.schedule;
|
|
67994
|
+
if (edit.schedule === null ? got !== void 0 : !sameSchedule(got, edit.schedule)) return false;
|
|
67995
|
+
}
|
|
67603
67996
|
}
|
|
67604
67997
|
if (patch.nonBlockingEdit !== void 0) {
|
|
67605
67998
|
const e = patch.nonBlockingEdit;
|
|
@@ -67620,11 +68013,12 @@ function alarmPatchLanded(patch, returned) {
|
|
|
67620
68013
|
/** Stable id of the always-present Default profile (migrated from flat settings). */
|
|
67621
68014
|
var NC_ALARM_DEFAULT_PROFILE_ID = "default";
|
|
67622
68015
|
var NC_ALARM_DEFAULT_PROFILE_NAME = "Default";
|
|
67623
|
-
/** Stock delays —
|
|
68016
|
+
/** Stock delays — re-arm 10 s after trigger (inherited by every mode). */
|
|
67624
68017
|
var NC_ALARM_SYSTEM_DEFAULT_DELAYS = {
|
|
67625
68018
|
exitDelaySec: 30,
|
|
67626
68019
|
entryDelaySec: 20,
|
|
67627
|
-
triggeredDurationSec:
|
|
68020
|
+
triggeredDurationSec: 10,
|
|
68021
|
+
postTriggeredAction: "rearmAfter"
|
|
67628
68022
|
};
|
|
67629
68023
|
/** Empty memberships + stock delays + no announce targets. */
|
|
67630
68024
|
function ncAlarmSystemDefaultSettings() {
|
|
@@ -67646,6 +68040,7 @@ function cloneAlarmSettings(settings) {
|
|
|
67646
68040
|
exitDelaySec: settings.exitDelaySec,
|
|
67647
68041
|
entryDelaySec: settings.entryDelaySec,
|
|
67648
68042
|
triggeredDurationSec: settings.triggeredDurationSec,
|
|
68043
|
+
...settings.postTriggeredAction !== void 0 ? { postTriggeredAction: settings.postTriggeredAction } : {},
|
|
67649
68044
|
...settings.announceArm !== void 0 ? { announceArm: settings.announceArm } : {},
|
|
67650
68045
|
announceTargets: [...settings.announceTargets],
|
|
67651
68046
|
nonBlocking: settings.nonBlocking.map((l) => ({
|
|
@@ -67660,7 +68055,22 @@ function cloneAlarmSettings(settings) {
|
|
|
67660
68055
|
mode: l.mode,
|
|
67661
68056
|
deviceIds: [...l.deviceIds]
|
|
67662
68057
|
})),
|
|
67663
|
-
modeDelays: settings.modeDelays.map((e) => ({
|
|
68058
|
+
modeDelays: settings.modeDelays.map((e) => ({
|
|
68059
|
+
mode: e.mode,
|
|
68060
|
+
...e.exitDelaySec !== void 0 ? { exitDelaySec: e.exitDelaySec } : {},
|
|
68061
|
+
...e.entryDelaySec !== void 0 ? { entryDelaySec: e.entryDelaySec } : {},
|
|
68062
|
+
...e.triggeredDurationSec !== void 0 ? { triggeredDurationSec: e.triggeredDurationSec } : {},
|
|
68063
|
+
...e.postTriggeredAction !== void 0 ? { postTriggeredAction: e.postTriggeredAction } : {},
|
|
68064
|
+
...e.schedule !== void 0 ? { schedule: {
|
|
68065
|
+
windows: e.schedule.windows.map((w) => ({
|
|
68066
|
+
days: [...w.days],
|
|
68067
|
+
startMinute: w.startMinute,
|
|
68068
|
+
endMinute: w.endMinute
|
|
68069
|
+
})),
|
|
68070
|
+
...e.schedule.timezone !== void 0 ? { timezone: e.schedule.timezone } : {},
|
|
68071
|
+
...e.schedule.invert === true ? { invert: true } : {}
|
|
68072
|
+
} } : {}
|
|
68073
|
+
}))
|
|
67664
68074
|
};
|
|
67665
68075
|
}
|
|
67666
68076
|
/**
|
|
@@ -68411,7 +68821,7 @@ var NC_TEMPLATE_VARS = [
|
|
|
68411
68821
|
{
|
|
68412
68822
|
name: "devices",
|
|
68413
68823
|
label: "Devices",
|
|
68414
|
-
description: "node-inference-unavailable: the affected cameras, comma-joined. Alarm arm / refusal: HOW MANY devices are armed (or open).",
|
|
68824
|
+
description: "node-inference-unavailable: the affected cameras, comma-joined. Alarm arm / arming / refusal: HOW MANY devices are armed (or open).",
|
|
68415
68825
|
example: "Ingresso, Garage",
|
|
68416
68826
|
group: "system",
|
|
68417
68827
|
families: ["rule"],
|
|
@@ -68420,6 +68830,7 @@ var NC_TEMPLATE_VARS = [
|
|
|
68420
68830
|
systemEventKinds: [
|
|
68421
68831
|
"node-inference-unavailable",
|
|
68422
68832
|
"alarm-armed",
|
|
68833
|
+
"alarm-arming",
|
|
68423
68834
|
"alarm-arm-refused"
|
|
68424
68835
|
]
|
|
68425
68836
|
},
|
|
@@ -68640,18 +69051,18 @@ var NC_TEMPLATE_VARS = [
|
|
|
68640
69051
|
{
|
|
68641
69052
|
name: "rules",
|
|
68642
69053
|
label: "Covering rules",
|
|
68643
|
-
description: "How many enabled rules the armed mode gates.",
|
|
69054
|
+
description: "How many enabled rules the armed / arming mode gates.",
|
|
68644
69055
|
example: "2",
|
|
68645
69056
|
group: "system",
|
|
68646
69057
|
families: ["rule"],
|
|
68647
69058
|
fields: [...RULE_TEXT],
|
|
68648
69059
|
kinds: ["system"],
|
|
68649
|
-
systemEventKinds: ["alarm-armed"]
|
|
69060
|
+
systemEventKinds: ["alarm-armed", "alarm-arming"]
|
|
68650
69061
|
},
|
|
68651
69062
|
{
|
|
68652
69063
|
name: "names",
|
|
68653
69064
|
label: "Device names",
|
|
68654
|
-
description: "Armed: the devices
|
|
69065
|
+
description: "Armed / arming: the Active devices (or every skipped name when none are Active). Refusal: the open sensors.",
|
|
68655
69066
|
example: "Ingresso, Garage",
|
|
68656
69067
|
group: "system",
|
|
68657
69068
|
families: ["rule"],
|
|
@@ -68672,7 +69083,29 @@ var NC_TEMPLATE_VARS = [
|
|
|
68672
69083
|
families: ["rule"],
|
|
68673
69084
|
fields: [...RULE_TEXT],
|
|
68674
69085
|
kinds: ["system"],
|
|
68675
|
-
systemEventKinds: ["alarm-armed"]
|
|
69086
|
+
systemEventKinds: ["alarm-armed", "alarm-arming"]
|
|
69087
|
+
},
|
|
69088
|
+
{
|
|
69089
|
+
name: "active",
|
|
69090
|
+
label: "Active count",
|
|
69091
|
+
description: "How many named devices the armed / arming mode is watching (title: n attivi / n active).",
|
|
69092
|
+
example: "3",
|
|
69093
|
+
group: "system",
|
|
69094
|
+
families: ["rule"],
|
|
69095
|
+
fields: [...RULE_TEXT],
|
|
69096
|
+
kinds: ["system"],
|
|
69097
|
+
systemEventKinds: ["alarm-armed", "alarm-arming"]
|
|
69098
|
+
},
|
|
69099
|
+
{
|
|
69100
|
+
name: "skipped",
|
|
69101
|
+
label: "Skipped count",
|
|
69102
|
+
description: "How many named devices the mode cannot arm — muted, detection off, offline (title: m saltati).",
|
|
69103
|
+
example: "1",
|
|
69104
|
+
group: "system",
|
|
69105
|
+
families: ["rule"],
|
|
69106
|
+
fields: [...RULE_TEXT],
|
|
69107
|
+
kinds: ["system"],
|
|
69108
|
+
systemEventKinds: ["alarm-armed", "alarm-arming"]
|
|
68676
69109
|
},
|
|
68677
69110
|
{
|
|
68678
69111
|
name: "bypassedNames",
|
|
@@ -72485,6 +72918,7 @@ exports.DEVICE_SETTINGS_CONTRIBUTION_METHODS = require_sleep.DEVICE_SETTINGS_CON
|
|
|
72485
72918
|
exports.DEVICE_STATE_READERS = DEVICE_STATE_READERS;
|
|
72486
72919
|
exports.DEVICE_STATUS_METHOD = require_sleep.DEVICE_STATUS_METHOD;
|
|
72487
72920
|
exports.DEVICE_TYPE_CONTROL_KIND = DEVICE_TYPE_CONTROL_KIND;
|
|
72921
|
+
exports.DEVICE_TYPE_DO_CAPS = DEVICE_TYPE_DO_CAPS;
|
|
72488
72922
|
exports.DEVICE_TYPE_INFO = DEVICE_TYPE_INFO;
|
|
72489
72923
|
exports.DISPLAY_ICON_GROUPS = DISPLAY_ICON_GROUPS;
|
|
72490
72924
|
exports.DISPLAY_ICON_KEYS = DISPLAY_ICON_KEYS;
|
|
@@ -72989,6 +73423,7 @@ exports.NcAlarmModeDelaysSchema = NcAlarmModeDelaysSchema;
|
|
|
72989
73423
|
exports.NcAlarmModeDeviceListSchema = NcAlarmModeDeviceListSchema;
|
|
72990
73424
|
exports.NcAlarmNonBlockingEditSchema = NcAlarmNonBlockingEditSchema;
|
|
72991
73425
|
exports.NcAlarmNonBlockingSchema = NcAlarmNonBlockingSchema;
|
|
73426
|
+
exports.NcAlarmPostTriggeredActionSchema = NcAlarmPostTriggeredActionSchema;
|
|
72992
73427
|
exports.NcAlarmProfileIdInputSchema = NcAlarmProfileIdInputSchema;
|
|
72993
73428
|
exports.NcAlarmProfileMetaSchema = NcAlarmProfileMetaSchema;
|
|
72994
73429
|
exports.NcAlarmProfilesViewSchema = NcAlarmProfilesViewSchema;
|
|
@@ -73573,6 +74008,9 @@ exports.__resetLogChannelRegistryForTests = __resetLogChannelRegistryForTests;
|
|
|
73573
74008
|
exports.accessoriesCapability = accessoriesCapability;
|
|
73574
74009
|
exports.accessoryStableId = accessoryStableId;
|
|
73575
74010
|
exports.actionsForBoundCaps = actionsForBoundCaps;
|
|
74011
|
+
exports.actionsForDevice = actionsForDevice;
|
|
74012
|
+
exports.actionsForDeviceType = actionsForDeviceType;
|
|
74013
|
+
exports.actionsForDevices = actionsForDevices;
|
|
73576
74014
|
exports.activateAlarmProfile = activateAlarmProfile;
|
|
73577
74015
|
exports.addonPagesCapability = addonPagesCapability;
|
|
73578
74016
|
exports.addonPagesSourceCapability = addonPagesSourceCapability;
|
|
@@ -73738,6 +74176,7 @@ exports.deleteAlarmProfile = deleteAlarmProfile;
|
|
|
73738
74176
|
exports.deriveBatteryPresence = deriveBatteryPresence;
|
|
73739
74177
|
exports.deriveCameraSwitches = deriveCameraSwitches;
|
|
73740
74178
|
exports.deriveDetailCropRect = deriveDetailCropRect;
|
|
74179
|
+
exports.derivePostTriggeredAction = derivePostTriggeredAction;
|
|
73741
74180
|
exports.deriveRecordingMode = deriveRecordingMode;
|
|
73742
74181
|
exports.describeComposableCaps = describeComposableCaps;
|
|
73743
74182
|
exports.describeCustomActions = require_sleep.describeCustomActions;
|
|
@@ -73755,6 +74194,7 @@ exports.deviceAdoptionCapability = deviceAdoptionCapability;
|
|
|
73755
74194
|
exports.deviceBackendToFormat = deviceBackendToFormat;
|
|
73756
74195
|
exports.deviceCustomAction = require_sleep.deviceCustomAction;
|
|
73757
74196
|
exports.deviceDiscoveryCapability = deviceDiscoveryCapability;
|
|
74197
|
+
exports.deviceDoFamily = deviceDoFamily;
|
|
73758
74198
|
exports.deviceExportCapability = deviceExportCapability;
|
|
73759
74199
|
exports.deviceExtensionCapability = deviceExtensionCapability;
|
|
73760
74200
|
exports.deviceManagerCapability = deviceManagerCapability;
|
|
@@ -73881,6 +74321,7 @@ exports.isDeviceConfigCap = require_sleep.isDeviceConfigCap;
|
|
|
73881
74321
|
exports.isDeviceScopedCap = require_sleep.isDeviceScopedCap;
|
|
73882
74322
|
exports.isDisplayIconKey = isDisplayIconKey;
|
|
73883
74323
|
exports.isDoActionActuatable = isDoActionActuatable;
|
|
74324
|
+
exports.isDoPickerDeviceType = isDoPickerDeviceType;
|
|
73884
74325
|
exports.isEmbeddingModelFailed = isEmbeddingModelFailed;
|
|
73885
74326
|
exports.isEvent = require_sleep.isEvent;
|
|
73886
74327
|
exports.isEventKindLabelKey = isEventKindLabelKey;
|
|
@@ -74098,10 +74539,12 @@ exports.resolveVariantModelId = resolveVariantModelId;
|
|
|
74098
74539
|
exports.resolveViewableDeviceIds = resolveViewableDeviceIds;
|
|
74099
74540
|
exports.roleSpec = roleSpec;
|
|
74100
74541
|
exports.roomCompositionExample = roomCompositionExample;
|
|
74542
|
+
exports.ruleAutoTriggersAlarm = ruleAutoTriggersAlarm;
|
|
74101
74543
|
exports.ruleBelongsToAlarm = ruleBelongsToAlarm;
|
|
74102
74544
|
exports.ruleDeviceCompatCapNames = ruleDeviceCompatCapNames;
|
|
74103
74545
|
exports.ruleDeviceCompatCapQueries = ruleDeviceCompatCapQueries;
|
|
74104
74546
|
exports.ruleEditorSectionsForKind = ruleEditorSectionsForKind;
|
|
74547
|
+
exports.ruleGatedOnArmedState = ruleGatedOnArmedState;
|
|
74105
74548
|
exports.ruleGroupingApplies = ruleGroupingApplies;
|
|
74106
74549
|
exports.ruleKindOf = ruleKindOf;
|
|
74107
74550
|
exports.ruleKindSpec = ruleKindSpec;
|
|
@@ -74112,6 +74555,7 @@ exports.ruleSeedForSection = ruleSeedForSection;
|
|
|
74112
74555
|
exports.runInferenceStep = runInferenceStep;
|
|
74113
74556
|
exports.runtimeDevices = runtimeDevices;
|
|
74114
74557
|
exports.runtimeStatePolicyFor = runtimeStatePolicyFor;
|
|
74558
|
+
exports.sameDoFamily = sameDoFamily;
|
|
74115
74559
|
exports.sceneMonitorCapability = sceneMonitorCapability;
|
|
74116
74560
|
exports.scheduleForSendTimes = scheduleForSendTimes;
|
|
74117
74561
|
exports.schemaDeclaresAnyField = schemaDeclaresAnyField;
|