@camstack/types 1.2.284 → 1.2.286
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/capabilities/device-provider.cap.d.ts +2 -0
- package/dist/capabilities/index.d.ts +1 -1
- package/dist/capabilities/notification-rules.cap.d.ts +230 -8
- package/dist/device/base-device-provider.d.ts +2 -0
- package/dist/generated/addon-api.d.ts +7 -0
- package/dist/generated/method-access-map.d.ts +1 -1
- package/dist/generated/method-device-selectors.d.ts +2 -2
- package/dist/generated/system-proxy.d.ts +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +312 -21
- package/dist/index.mjs +297 -22
- package/dist/notification/alarm-settings.d.ts +58 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -13327,7 +13327,17 @@ function siteZoneKey(label) {
|
|
|
13327
13327
|
var ProviderStatusSchema = zod.z.object({
|
|
13328
13328
|
connected: zod.z.boolean(),
|
|
13329
13329
|
deviceCount: zod.z.number(),
|
|
13330
|
-
error: zod.z.string().optional()
|
|
13330
|
+
error: zod.z.string().optional(),
|
|
13331
|
+
/**
|
|
13332
|
+
* `'orchestrator'`: this provider writes NO camera's `motion` runtime slice
|
|
13333
|
+
* — the orchestrator is its only writer (D696). Set by `BaseDeviceProvider`,
|
|
13334
|
+
* which every provider bundles, so only a provider BUILT from D696-amended
|
|
13335
|
+
* code says it. ABSENT means an older provider that may still write it (raw
|
|
13336
|
+
* VMD writes, a boot seed), and the orchestrator's provider gate keeps that
|
|
13337
|
+
* provider's cameras unwritten (`camera-sensors/motion-slice-provider-gate.ts`)
|
|
13338
|
+
* — the provider twin of the runner's `getLocalLoad().motionSliceWriter`.
|
|
13339
|
+
*/
|
|
13340
|
+
motionSliceWriter: zod.z.literal("orchestrator").optional()
|
|
13331
13341
|
});
|
|
13332
13342
|
var DiscoveredDeviceSchema = zod.z.object({
|
|
13333
13343
|
externalId: zod.z.string(),
|
|
@@ -21283,6 +21293,41 @@ var NcSnoozeSuppressedSchema = zod.z.object({
|
|
|
21283
21293
|
firstAt: zod.z.number(),
|
|
21284
21294
|
lastAt: zod.z.number()
|
|
21285
21295
|
});
|
|
21296
|
+
/** The bounds every alarm delay field carries — settings, per-mode overrides, both editors. */
|
|
21297
|
+
var NC_ALARM_DELAY_MAX_SEC = 600;
|
|
21298
|
+
var NC_ALARM_TRIGGERED_MAX_SEC = 3600;
|
|
21299
|
+
/** At most this many ids on one mode's non-blocking list. */
|
|
21300
|
+
var NC_ALARM_NONBLOCKING_MAX = 200;
|
|
21301
|
+
var NcAlarmDelaySecSchema = zod.z.number().int().min(0).max(600);
|
|
21302
|
+
var NcAlarmTriggeredSecSchema = zod.z.number().int().min(0).max(NC_ALARM_TRIGGERED_MAX_SEC);
|
|
21303
|
+
var uniqueModes = (entries) => new Set(entries.map((e) => e.mode)).size === entries.length;
|
|
21304
|
+
/** One mode's OVERRIDES. An absent field inherits the global value (D697). */
|
|
21305
|
+
var NcAlarmModeDelaysSchema = zod.z.object({
|
|
21306
|
+
mode: AlarmArmModeSchema,
|
|
21307
|
+
exitDelaySec: NcAlarmDelaySecSchema.optional(),
|
|
21308
|
+
entryDelaySec: NcAlarmDelaySecSchema.optional(),
|
|
21309
|
+
triggeredDurationSec: NcAlarmTriggeredSecSchema.optional()
|
|
21310
|
+
});
|
|
21311
|
+
var NcAlarmModeDelaysListSchema = zod.z.array(NcAlarmModeDelaysSchema).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
|
|
21312
|
+
/**
|
|
21313
|
+
* One mode's EDIT in a patch: a number sets the override, `null` removes it (the mode inherits
|
|
21314
|
+
* again), an absent field leaves it alone. Per field, so two editors changing two different
|
|
21315
|
+
* delays of one mode never undo each other.
|
|
21316
|
+
*/
|
|
21317
|
+
var NcAlarmModeDelaysEditSchema = zod.z.object({
|
|
21318
|
+
mode: AlarmArmModeSchema,
|
|
21319
|
+
exitDelaySec: NcAlarmDelaySecSchema.nullable().optional(),
|
|
21320
|
+
entryDelaySec: NcAlarmDelaySecSchema.nullable().optional(),
|
|
21321
|
+
triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional()
|
|
21322
|
+
});
|
|
21323
|
+
var NcAlarmModeDelaysEditListSchema = zod.z.array(NcAlarmModeDelaysEditSchema).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
|
|
21324
|
+
/** One switch of the alarm table: put ONE device on, or take it off, ONE mode's list. */
|
|
21325
|
+
var NcAlarmNonBlockingEditSchema = zod.z.object({
|
|
21326
|
+
mode: AlarmArmModeSchema,
|
|
21327
|
+
deviceId: zod.z.number().int().positive(),
|
|
21328
|
+
/** true = on the list (may be open, does not block); false = off the list (blocks). */
|
|
21329
|
+
nonBlocking: zod.z.boolean()
|
|
21330
|
+
});
|
|
21286
21331
|
/**
|
|
21287
21332
|
* One arm mode's non-blocking list: devices that may be open when that mode
|
|
21288
21333
|
* arms, without the arm being refused.
|
|
@@ -21296,10 +21341,10 @@ var NcAlarmNonBlockingSchema = zod.z.object({
|
|
|
21296
21341
|
* meaning a reader could agree on (union? the last one?), so they are refused
|
|
21297
21342
|
* at the boundary rather than interpreted.
|
|
21298
21343
|
*/
|
|
21299
|
-
var NcAlarmNonBlockingListSchema = zod.z.array(NcAlarmNonBlockingSchema).max(8).refine(
|
|
21344
|
+
var NcAlarmNonBlockingListSchema = zod.z.array(NcAlarmNonBlockingSchema).max(8).refine(uniqueModes, { message: "nonBlocking: at most one list per arm mode" });
|
|
21300
21345
|
/**
|
|
21301
|
-
* The three durations
|
|
21302
|
-
* transitions, and which openings each mode tolerates.
|
|
21346
|
+
* The three durations — global, and per mode since D697 — the panel's state
|
|
21347
|
+
* machine runs on, who hears about its transitions, and which openings each mode tolerates.
|
|
21303
21348
|
*
|
|
21304
21349
|
* They live on the NOTIFICATION-RULES cap, not on `alarm-panel`, on purpose:
|
|
21305
21350
|
* `alarm-panel` is `deviceNative` and its other provider mirrors somebody
|
|
@@ -21309,15 +21354,15 @@ var NcAlarmNonBlockingListSchema = zod.z.array(NcAlarmNonBlockingSchema).max(8).
|
|
|
21309
21354
|
*/
|
|
21310
21355
|
var NcAlarmSettingsSchema = zod.z.object({
|
|
21311
21356
|
/** Grace period between arming and the mode taking effect. 0 = immediate. */
|
|
21312
|
-
exitDelaySec:
|
|
21357
|
+
exitDelaySec: NcAlarmDelaySecSchema,
|
|
21313
21358
|
/** Grace period between a trigger and the alarm firing. 0 = immediate. */
|
|
21314
|
-
entryDelaySec:
|
|
21359
|
+
entryDelaySec: NcAlarmDelaySecSchema,
|
|
21315
21360
|
/**
|
|
21316
21361
|
* How long `triggered` lasts before the panel re-arms itself.
|
|
21317
21362
|
* **0 = until an operator disarms it** — the behaviour before this field
|
|
21318
21363
|
* existed, and therefore what an untouched install keeps doing.
|
|
21319
21364
|
*/
|
|
21320
|
-
triggeredDurationSec:
|
|
21365
|
+
triggeredDurationSec: NcAlarmTriggeredSecSchema,
|
|
21321
21366
|
/**
|
|
21322
21367
|
* Deprecated by D630 — every transition is announced. Parsed, never read;
|
|
21323
21368
|
* remove after one release. Optional so an older admin's patch (which still
|
|
@@ -21340,17 +21385,30 @@ var NcAlarmSettingsSchema = zod.z.object({
|
|
|
21340
21385
|
* per mode is meaningful. Defaulted to `[]` so a blob stored before D630
|
|
21341
21386
|
* parses as "every opening blocks" — the behaviour it was written under.
|
|
21342
21387
|
*/
|
|
21343
|
-
nonBlocking: NcAlarmNonBlockingListSchema.default([])
|
|
21388
|
+
nonBlocking: NcAlarmNonBlockingListSchema.default([]),
|
|
21389
|
+
/**
|
|
21390
|
+
* Per arm mode, the delays that mode OVERRIDES (D697). A mode with no entry, or an entry
|
|
21391
|
+
* without a field, uses the global value above — so `[]`, the default, is exactly the
|
|
21392
|
+
* behaviour of a blob stored before this field existed. Read through `resolveModeDelays`.
|
|
21393
|
+
*/
|
|
21394
|
+
modeDelays: NcAlarmModeDelaysListSchema.default([])
|
|
21344
21395
|
});
|
|
21345
21396
|
/**
|
|
21346
21397
|
* Every field optional — a tab edits one control at a time.
|
|
21347
21398
|
*
|
|
21348
|
-
* `nonBlocking`
|
|
21349
|
-
* remove an inner `.default()`, so a patch that never
|
|
21350
|
-
* parse to `
|
|
21351
|
-
* (the same trap {@link NcRulePatchSchema} documents).
|
|
21399
|
+
* `nonBlocking` and `modeDelays` are re-declared WITHOUT their defaults:
|
|
21400
|
+
* `.partial()` does not remove an inner `.default()`, so a patch that never
|
|
21401
|
+
* named the field would parse to `[]` and wipe every mode's list on an
|
|
21402
|
+
* unrelated edit (the same trap {@link NcRulePatchSchema} documents). Here
|
|
21403
|
+
* `modeDelays` means EDITS, not the stored overrides.
|
|
21352
21404
|
*/
|
|
21353
|
-
var NcAlarmSettingsPatchSchema = NcAlarmSettingsSchema.extend({
|
|
21405
|
+
var NcAlarmSettingsPatchSchema = NcAlarmSettingsSchema.extend({
|
|
21406
|
+
nonBlocking: NcAlarmNonBlockingListSchema,
|
|
21407
|
+
/** Per-mode, per-field edits — NOT the whole list (see NcAlarmModeDelaysEditSchema). */
|
|
21408
|
+
modeDelays: NcAlarmModeDelaysEditListSchema,
|
|
21409
|
+
/** ONE membership change; the panel applies it to the list it holds at its turn. */
|
|
21410
|
+
nonBlockingEdit: NcAlarmNonBlockingEditSchema
|
|
21411
|
+
}).partial().refine((p) => p.nonBlocking === void 0 || p.nonBlockingEdit === void 0, { message: "nonBlocking and nonBlockingEdit are exclusive — send the whole lists or one edit" });
|
|
21354
21412
|
/**
|
|
21355
21413
|
* What one arm mode actually arms, DERIVED from the enabled rules gated on it.
|
|
21356
21414
|
* Never authored, never stored — see `alarm-mode-coverage.ts` for why a stored
|
|
@@ -21450,6 +21508,30 @@ var NcAlarmConfigSchema = zod.z.object({
|
|
|
21450
21508
|
*/
|
|
21451
21509
|
live: NcAlarmLiveSchema.optional()
|
|
21452
21510
|
});
|
|
21511
|
+
/** At most this many ids in one `getAlarmSensors` call — a validation bound, not a target. */
|
|
21512
|
+
var NC_ALARM_SENSORS_MAX = 500;
|
|
21513
|
+
var NcAlarmSensorReadingSchema = zod.z.enum([
|
|
21514
|
+
"open",
|
|
21515
|
+
"closed",
|
|
21516
|
+
"unknown",
|
|
21517
|
+
"not-opening"
|
|
21518
|
+
]);
|
|
21519
|
+
/** One device's state as the alarm reads it — the classifier the arm check uses. */
|
|
21520
|
+
var NcAlarmSensorStateSchema = zod.z.object({
|
|
21521
|
+
deviceId: zod.z.number().int().positive(),
|
|
21522
|
+
reading: NcAlarmSensorReadingSchema,
|
|
21523
|
+
/** The word as read (`open`, `closed`, `unlocked`, `stopped`, …); null when unknown / not an opening. */
|
|
21524
|
+
state: zod.z.string().nullable(),
|
|
21525
|
+
/** Why `unknown`: the read failed, or the slice holds no word its cap defines (a placeholder included). */
|
|
21526
|
+
unknownWhy: zod.z.enum(["read-failed", "unknown-word"]).nullable(),
|
|
21527
|
+
/** The device manager's liveness as the centre mirrors it; null = not known. */
|
|
21528
|
+
online: zod.z.boolean().nullable()
|
|
21529
|
+
});
|
|
21530
|
+
var NcAlarmSensorsInputSchema = zod.z.object({ deviceIds: zod.z.array(zod.z.number().int().positive()).max(500) });
|
|
21531
|
+
var NcAlarmSensorsSchema = zod.z.object({
|
|
21532
|
+
sensors: zod.z.array(NcAlarmSensorStateSchema),
|
|
21533
|
+
readAt: zod.z.number().int().nonnegative()
|
|
21534
|
+
});
|
|
21453
21535
|
/**
|
|
21454
21536
|
* The most seconds of footage any notification rule may ask a camera to retain.
|
|
21455
21537
|
*
|
|
@@ -21709,8 +21791,9 @@ var notificationRulesCapability = {
|
|
|
21709
21791
|
*/
|
|
21710
21792
|
getAlarmConfig: require_sleep.method(zod.z.object({}), NcAlarmConfigSchema, { auth: "admin" }),
|
|
21711
21793
|
/**
|
|
21712
|
-
* Patch the settings (durations
|
|
21713
|
-
*
|
|
21794
|
+
* Patch the settings (durations — global and per mode —, recipients,
|
|
21795
|
+
* per-mode non-blocking lists or one membership edit; `announceArm` is
|
|
21796
|
+
* accepted and ignored — D630). Returns the WHOLE config,
|
|
21714
21797
|
* coverage and `live` included, so a
|
|
21715
21798
|
* client never has to guess what the server settled on — the panel clamps
|
|
21716
21799
|
* and normalises, and a form that re-rendered from its own input would
|
|
@@ -21719,7 +21802,15 @@ var notificationRulesCapability = {
|
|
|
21719
21802
|
setAlarmConfig: require_sleep.method(zod.z.object({ patch: NcAlarmSettingsPatchSchema }), NcAlarmConfigSchema, {
|
|
21720
21803
|
kind: "mutation",
|
|
21721
21804
|
auth: "admin"
|
|
21722
|
-
})
|
|
21805
|
+
}),
|
|
21806
|
+
/**
|
|
21807
|
+
* The CURRENT state of each asked device as the alarm reads it (D697) — open, closed,
|
|
21808
|
+
* unknown (why) or not an opening, plus liveness. Classified by the same table the arm
|
|
21809
|
+
* check uses (`alarm-openings.ts`), so the editor and the arm can never disagree. The
|
|
21810
|
+
* caller names the ids (the household openings it already holds); at most
|
|
21811
|
+
* `NC_ALARM_SENSORS_MAX`.
|
|
21812
|
+
*/
|
|
21813
|
+
getAlarmSensors: require_sleep.method(NcAlarmSensorsInputSchema, NcAlarmSensorsSchema, { auth: "admin" })
|
|
21723
21814
|
}
|
|
21724
21815
|
};
|
|
21725
21816
|
//#endregion
|
|
@@ -47977,13 +48068,14 @@ var BaseDeviceProvider = class extends require_sleep.BaseAddon {
|
|
|
47977
48068
|
async getStatus() {
|
|
47978
48069
|
const all = await this.ctx.kernel.devices?.getAll() ?? [];
|
|
47979
48070
|
const summary = this.restoreFailureSummary();
|
|
47980
|
-
|
|
48071
|
+
const base = {
|
|
47981
48072
|
connected: true,
|
|
47982
|
-
deviceCount: all.length
|
|
48073
|
+
deviceCount: all.length,
|
|
48074
|
+
motionSliceWriter: "orchestrator"
|
|
47983
48075
|
};
|
|
48076
|
+
if (summary === null) return base;
|
|
47984
48077
|
return {
|
|
47985
|
-
|
|
47986
|
-
deviceCount: all.length,
|
|
48078
|
+
...base,
|
|
47987
48079
|
error: summary
|
|
47988
48080
|
};
|
|
47989
48081
|
}
|
|
@@ -56424,6 +56516,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
56424
56516
|
addonId: null,
|
|
56425
56517
|
access: "view"
|
|
56426
56518
|
},
|
|
56519
|
+
"notificationRules.getAlarmSensors": {
|
|
56520
|
+
capName: "notification-rules",
|
|
56521
|
+
capScope: "system",
|
|
56522
|
+
addonId: null,
|
|
56523
|
+
access: "view"
|
|
56524
|
+
},
|
|
56427
56525
|
"notificationRules.getClipRetentionAsks": {
|
|
56428
56526
|
capName: "notification-rules",
|
|
56429
56527
|
capScope: "system",
|
|
@@ -61244,6 +61342,11 @@ var METHOD_DEVICE_SELECTORS = Object.freeze({
|
|
|
61244
61342
|
form: "single",
|
|
61245
61343
|
optional: false
|
|
61246
61344
|
}],
|
|
61345
|
+
"notificationRules.getAlarmSensors": [{
|
|
61346
|
+
name: "deviceIds",
|
|
61347
|
+
form: "array",
|
|
61348
|
+
optional: false
|
|
61349
|
+
}],
|
|
61247
61350
|
"notificationRules.setDeviceMuted": [{
|
|
61248
61351
|
name: "deviceId",
|
|
61249
61352
|
form: "single",
|
|
@@ -62482,6 +62585,7 @@ var SYSTEM_SCOPE_DEVICE_METHODS = [
|
|
|
62482
62585
|
"faceGallery.listRecentFaces",
|
|
62483
62586
|
"networkQuality.getDeviceStats",
|
|
62484
62587
|
"networkQuality.reportClientStats",
|
|
62588
|
+
"notificationRules.getAlarmSensors",
|
|
62485
62589
|
"notificationRules.setDeviceMuted",
|
|
62486
62590
|
"osdManager.clearSlotBinding",
|
|
62487
62591
|
"osdManager.copyDeviceConfiguration",
|
|
@@ -63422,7 +63526,8 @@ function createSystemProxy(api) {
|
|
|
63422
63526
|
createSnooze: (input) => dispatch("notificationRules", "createSnooze", "mutation", input),
|
|
63423
63527
|
cancelSnooze: (input) => dispatch("notificationRules", "cancelSnooze", "mutation", input),
|
|
63424
63528
|
getAlarmConfig: (input) => dispatch("notificationRules", "getAlarmConfig", "query", input),
|
|
63425
|
-
setAlarmConfig: (input) => dispatch("notificationRules", "setAlarmConfig", "mutation", input)
|
|
63529
|
+
setAlarmConfig: (input) => dispatch("notificationRules", "setAlarmConfig", "mutation", input),
|
|
63530
|
+
getAlarmSensors: (input) => dispatch("notificationRules", "getAlarmSensors", "query", input)
|
|
63426
63531
|
},
|
|
63427
63532
|
osdManager: {
|
|
63428
63533
|
getConditionSupport: (input) => dispatch("osdManager", "getConditionSupport", "query", input),
|
|
@@ -65457,6 +65562,176 @@ function sensorTransitionNeverFires(rule) {
|
|
|
65457
65562
|
/** The warning an editor shows for {@link sensorTransitionNeverFires}. */
|
|
65458
65563
|
var NC_SENSOR_TRANSITION_NEVER_FIRES_WARNING = "This rule belongs to the alarm, and an alarm rule fires only when an opening OPENS. Set to “only when it clears”, it can never fire.";
|
|
65459
65564
|
//#endregion
|
|
65565
|
+
//#region src/notification/alarm-settings.ts
|
|
65566
|
+
var NC_ALARM_DELAY_FIELDS = [
|
|
65567
|
+
"exitDelaySec",
|
|
65568
|
+
"entryDelaySec",
|
|
65569
|
+
"triggeredDurationSec"
|
|
65570
|
+
];
|
|
65571
|
+
/** The mode's value when it overrides the field, else the global one. */
|
|
65572
|
+
function pick(override, global) {
|
|
65573
|
+
return override === void 0 ? {
|
|
65574
|
+
value: global,
|
|
65575
|
+
source: "default"
|
|
65576
|
+
} : {
|
|
65577
|
+
value: override,
|
|
65578
|
+
source: "mode"
|
|
65579
|
+
};
|
|
65580
|
+
}
|
|
65581
|
+
/** What `mode` actually runs on: its own overrides, the global value for every other field. */
|
|
65582
|
+
function resolveModeDelays(settings, mode) {
|
|
65583
|
+
const entry = (settings.modeDelays ?? []).find((e) => e.mode === mode);
|
|
65584
|
+
const exit = pick(entry?.exitDelaySec, settings.exitDelaySec);
|
|
65585
|
+
const entryDelay = pick(entry?.entryDelaySec, settings.entryDelaySec);
|
|
65586
|
+
const triggered = pick(entry?.triggeredDurationSec, settings.triggeredDurationSec);
|
|
65587
|
+
return {
|
|
65588
|
+
exitDelaySec: exit.value,
|
|
65589
|
+
entryDelaySec: entryDelay.value,
|
|
65590
|
+
triggeredDurationSec: triggered.value,
|
|
65591
|
+
source: {
|
|
65592
|
+
exitDelaySec: exit.source,
|
|
65593
|
+
entryDelaySec: entryDelay.source,
|
|
65594
|
+
triggeredDurationSec: triggered.source
|
|
65595
|
+
}
|
|
65596
|
+
};
|
|
65597
|
+
}
|
|
65598
|
+
/** One field of an entry after an edit: number sets, null clears, undefined keeps. */
|
|
65599
|
+
function edited(current, edit) {
|
|
65600
|
+
if (edit === void 0) return current;
|
|
65601
|
+
return edit === null ? void 0 : edit;
|
|
65602
|
+
}
|
|
65603
|
+
/**
|
|
65604
|
+
* Apply per-field edits to the stored overrides. Returns new arrays, never mutates the input;
|
|
65605
|
+
* an entry with no field left is dropped (the mode inherits everything again).
|
|
65606
|
+
*/
|
|
65607
|
+
function applyModeDelaysEdits(current, edits) {
|
|
65608
|
+
const out = current.map((e) => ({ ...e }));
|
|
65609
|
+
for (const edit of edits) {
|
|
65610
|
+
const at = out.findIndex((e) => e.mode === edit.mode);
|
|
65611
|
+
const base = at >= 0 ? out[at] ?? { mode: edit.mode } : { mode: edit.mode };
|
|
65612
|
+
const next = { mode: edit.mode };
|
|
65613
|
+
const exit = edited(base.exitDelaySec, edit.exitDelaySec);
|
|
65614
|
+
const entry = edited(base.entryDelaySec, edit.entryDelaySec);
|
|
65615
|
+
const triggered = edited(base.triggeredDurationSec, edit.triggeredDurationSec);
|
|
65616
|
+
if (exit !== void 0) next.exitDelaySec = exit;
|
|
65617
|
+
if (entry !== void 0) next.entryDelaySec = entry;
|
|
65618
|
+
if (triggered !== void 0) next.triggeredDurationSec = triggered;
|
|
65619
|
+
if (at >= 0) out[at] = next;
|
|
65620
|
+
else out.push(next);
|
|
65621
|
+
}
|
|
65622
|
+
return out.filter((e) => e.exitDelaySec !== void 0 || e.entryDelaySec !== void 0 || e.triggeredDurationSec !== void 0);
|
|
65623
|
+
}
|
|
65624
|
+
/**
|
|
65625
|
+
* Put ONE device on, or take it off, ONE mode's list. A no-op answers `changed: false`; an add
|
|
65626
|
+
* to a full list is REFUSED by reason (never silently dropped); an emptied list drops its entry.
|
|
65627
|
+
*/
|
|
65628
|
+
function applyNonBlockingEdit(lists, edit) {
|
|
65629
|
+
const copy = lists.map((l) => ({
|
|
65630
|
+
mode: l.mode,
|
|
65631
|
+
deviceIds: [...l.deviceIds]
|
|
65632
|
+
}));
|
|
65633
|
+
const at = copy.findIndex((l) => l.mode === edit.mode);
|
|
65634
|
+
const held = at >= 0 ? copy[at]?.deviceIds ?? [] : [];
|
|
65635
|
+
const present = held.includes(edit.deviceId);
|
|
65636
|
+
if (edit.nonBlocking === present) return {
|
|
65637
|
+
kind: "applied",
|
|
65638
|
+
lists: copy,
|
|
65639
|
+
changed: false
|
|
65640
|
+
};
|
|
65641
|
+
if (edit.nonBlocking) {
|
|
65642
|
+
if (held.length >= 200) return {
|
|
65643
|
+
kind: "refused",
|
|
65644
|
+
reason: "list-full",
|
|
65645
|
+
mode: edit.mode,
|
|
65646
|
+
max: 200
|
|
65647
|
+
};
|
|
65648
|
+
const next = {
|
|
65649
|
+
mode: edit.mode,
|
|
65650
|
+
deviceIds: [...held, edit.deviceId]
|
|
65651
|
+
};
|
|
65652
|
+
if (at >= 0) copy[at] = next;
|
|
65653
|
+
else copy.push(next);
|
|
65654
|
+
} else {
|
|
65655
|
+
const next = {
|
|
65656
|
+
mode: edit.mode,
|
|
65657
|
+
deviceIds: held.filter((id) => id !== edit.deviceId)
|
|
65658
|
+
};
|
|
65659
|
+
if (at >= 0) copy[at] = next;
|
|
65660
|
+
}
|
|
65661
|
+
return {
|
|
65662
|
+
kind: "applied",
|
|
65663
|
+
lists: copy.filter((l) => l.deviceIds.length > 0),
|
|
65664
|
+
changed: true
|
|
65665
|
+
};
|
|
65666
|
+
}
|
|
65667
|
+
function sameSet(a, b) {
|
|
65668
|
+
const sa = new Set(a);
|
|
65669
|
+
const sb = new Set(b);
|
|
65670
|
+
return sa.size === sb.size && [...sa].every((x) => sb.has(x));
|
|
65671
|
+
}
|
|
65672
|
+
/** Per-mode id sets of a lists value, empty lists ignored. */
|
|
65673
|
+
function listsByMode(lists) {
|
|
65674
|
+
const out = /* @__PURE__ */ new Map();
|
|
65675
|
+
for (const l of lists) if (l.deviceIds.length > 0) out.set(l.mode, new Set(l.deviceIds));
|
|
65676
|
+
return out;
|
|
65677
|
+
}
|
|
65678
|
+
function sameLists(a, b) {
|
|
65679
|
+
const ma = listsByMode(a);
|
|
65680
|
+
const mb = listsByMode(b);
|
|
65681
|
+
if (ma.size !== mb.size) return false;
|
|
65682
|
+
for (const [mode, ids] of ma) {
|
|
65683
|
+
const other = mb.get(mode);
|
|
65684
|
+
if (other === void 0 || !sameSet([...ids], [...other])) return false;
|
|
65685
|
+
}
|
|
65686
|
+
return true;
|
|
65687
|
+
}
|
|
65688
|
+
/** The returned entry's value for one field of a mode-delays edit. */
|
|
65689
|
+
function fieldOf(entry, field) {
|
|
65690
|
+
if (entry === void 0) return void 0;
|
|
65691
|
+
switch (field) {
|
|
65692
|
+
case "exitDelaySec": return entry.exitDelaySec;
|
|
65693
|
+
case "entryDelaySec": return entry.entryDelaySec;
|
|
65694
|
+
case "triggeredDurationSec": return entry.triggeredDurationSec;
|
|
65695
|
+
}
|
|
65696
|
+
}
|
|
65697
|
+
/** The edit's value for one field. */
|
|
65698
|
+
function editFieldOf(edit, field) {
|
|
65699
|
+
switch (field) {
|
|
65700
|
+
case "exitDelaySec": return edit.exitDelaySec;
|
|
65701
|
+
case "entryDelaySec": return edit.entryDelaySec;
|
|
65702
|
+
case "triggeredDurationSec": return edit.triggeredDurationSec;
|
|
65703
|
+
}
|
|
65704
|
+
}
|
|
65705
|
+
/**
|
|
65706
|
+
* True iff every key the patch sent is reflected in what the host returned. A host older than
|
|
65707
|
+
* this build strips the keys it does not know; this is how a client tells "saved" from "parsed
|
|
65708
|
+
* and dropped". `announceArm` is ignored (parsed, never read). A `null` clear "lands" on a host
|
|
65709
|
+
* that stripped the key (it lacks the field) — harmless, because such a host stores no overrides.
|
|
65710
|
+
* A whole-list `nonBlocking` naming a mode the panel does not offer reads as "not landed" (the host
|
|
65711
|
+
* drops it); only older clients and the prune send whole lists, and they do not call this.
|
|
65712
|
+
*/
|
|
65713
|
+
function alarmPatchLanded(patch, returned) {
|
|
65714
|
+
if (patch.exitDelaySec !== void 0 && patch.exitDelaySec !== returned.exitDelaySec) return false;
|
|
65715
|
+
if (patch.entryDelaySec !== void 0 && patch.entryDelaySec !== returned.entryDelaySec) return false;
|
|
65716
|
+
if (patch.triggeredDurationSec !== void 0 && patch.triggeredDurationSec !== returned.triggeredDurationSec) return false;
|
|
65717
|
+
if (patch.announceTargets !== void 0 && !sameSet(patch.announceTargets, returned.announceTargets)) return false;
|
|
65718
|
+
if (patch.nonBlocking !== void 0 && !sameLists(patch.nonBlocking, returned.nonBlocking ?? [])) return false;
|
|
65719
|
+
for (const edit of patch.modeDelays ?? []) {
|
|
65720
|
+
const entry = (returned.modeDelays ?? []).find((e) => e.mode === edit.mode);
|
|
65721
|
+
for (const field of NC_ALARM_DELAY_FIELDS) {
|
|
65722
|
+
const want = editFieldOf(edit, field);
|
|
65723
|
+
if (want === void 0) continue;
|
|
65724
|
+
const got = fieldOf(entry, field);
|
|
65725
|
+
if (want === null ? got !== void 0 : got !== want) return false;
|
|
65726
|
+
}
|
|
65727
|
+
}
|
|
65728
|
+
if (patch.nonBlockingEdit !== void 0) {
|
|
65729
|
+
const e = patch.nonBlockingEdit;
|
|
65730
|
+
if (((returned.nonBlocking ?? []).find((l) => l.mode === e.mode)?.deviceIds.includes(e.deviceId) ?? false) !== e.nonBlocking) return false;
|
|
65731
|
+
}
|
|
65732
|
+
return true;
|
|
65733
|
+
}
|
|
65734
|
+
//#endregion
|
|
65460
65735
|
//#region src/notification/sensor-raised.ts
|
|
65461
65736
|
/**
|
|
65462
65737
|
* WHICH WAY A BOOLEAN SENSOR MOVED — read off the one slice a sensor event
|
|
@@ -70084,8 +70359,13 @@ exports.NATIVE_LEASE_TILE_BUDGET_KEY = NATIVE_LEASE_TILE_BUDGET_KEY;
|
|
|
70084
70359
|
exports.NAVIGATION_ACTION_CATALOG = NAVIGATION_ACTION_CATALOG;
|
|
70085
70360
|
exports.NAVIGATION_LIGHT_LEVEL_MAX = NAVIGATION_LIGHT_LEVEL_MAX;
|
|
70086
70361
|
exports.NAVIGATION_LIGHT_LEVEL_MIN = NAVIGATION_LIGHT_LEVEL_MIN;
|
|
70362
|
+
exports.NC_ALARM_DELAY_FIELDS = NC_ALARM_DELAY_FIELDS;
|
|
70363
|
+
exports.NC_ALARM_DELAY_MAX_SEC = NC_ALARM_DELAY_MAX_SEC;
|
|
70364
|
+
exports.NC_ALARM_NONBLOCKING_MAX = NC_ALARM_NONBLOCKING_MAX;
|
|
70087
70365
|
exports.NC_ALARM_OPENING_EVENT_KINDS = NC_ALARM_OPENING_EVENT_KINDS;
|
|
70366
|
+
exports.NC_ALARM_SENSORS_MAX = NC_ALARM_SENSORS_MAX;
|
|
70088
70367
|
exports.NC_ALARM_SYSTEM_EVENT_KINDS = NC_ALARM_SYSTEM_EVENT_KINDS;
|
|
70368
|
+
exports.NC_ALARM_TRIGGERED_MAX_SEC = NC_ALARM_TRIGGERED_MAX_SEC;
|
|
70089
70369
|
exports.NC_AUDIO_CONFIRM_HITS_DEFAULT = NC_AUDIO_CONFIRM_HITS_DEFAULT;
|
|
70090
70370
|
exports.NC_AUDIO_CONFIRM_HITS_MAX = NC_AUDIO_CONFIRM_HITS_MAX;
|
|
70091
70371
|
exports.NC_AUDIO_CONFIRM_HITS_MIN = NC_AUDIO_CONFIRM_HITS_MIN;
|
|
@@ -70173,6 +70453,13 @@ exports.NavigationRuntimeStateSchema = NavigationRuntimeStateSchema;
|
|
|
70173
70453
|
exports.NavigationStatusSchema = NavigationStatusSchema;
|
|
70174
70454
|
exports.NcAlarmConfigSchema = NcAlarmConfigSchema;
|
|
70175
70455
|
exports.NcAlarmModeCoverageSchema = NcAlarmModeCoverageSchema;
|
|
70456
|
+
exports.NcAlarmModeDelaysEditSchema = NcAlarmModeDelaysEditSchema;
|
|
70457
|
+
exports.NcAlarmModeDelaysSchema = NcAlarmModeDelaysSchema;
|
|
70458
|
+
exports.NcAlarmNonBlockingEditSchema = NcAlarmNonBlockingEditSchema;
|
|
70459
|
+
exports.NcAlarmSensorReadingSchema = NcAlarmSensorReadingSchema;
|
|
70460
|
+
exports.NcAlarmSensorStateSchema = NcAlarmSensorStateSchema;
|
|
70461
|
+
exports.NcAlarmSensorsInputSchema = NcAlarmSensorsInputSchema;
|
|
70462
|
+
exports.NcAlarmSensorsSchema = NcAlarmSensorsSchema;
|
|
70176
70463
|
exports.NcAlarmSettingsPatchSchema = NcAlarmSettingsPatchSchema;
|
|
70177
70464
|
exports.NcAlarmSettingsSchema = NcAlarmSettingsSchema;
|
|
70178
70465
|
exports.NcAlarmSkipReasonSchema = NcAlarmSkipReasonSchema;
|
|
@@ -70745,8 +71032,11 @@ exports.addonsCapability = addonsCapability;
|
|
|
70745
71032
|
exports.adminUiCapability = require_sleep.adminUiCapability;
|
|
70746
71033
|
exports.airQualitySensorCapability = airQualitySensorCapability;
|
|
70747
71034
|
exports.alarmPanelCapability = alarmPanelCapability;
|
|
71035
|
+
exports.alarmPatchLanded = alarmPatchLanded;
|
|
70748
71036
|
exports.alertsCapability = alertsCapability;
|
|
70749
71037
|
exports.ambientLightSensorCapability = ambientLightSensorCapability;
|
|
71038
|
+
exports.applyModeDelaysEdits = applyModeDelaysEdits;
|
|
71039
|
+
exports.applyNonBlockingEdit = applyNonBlockingEdit;
|
|
70750
71040
|
exports.asBoolean = require_sleep.asBoolean;
|
|
70751
71041
|
exports.asJsonArray = require_sleep.asJsonArray;
|
|
70752
71042
|
exports.asJsonObject = require_sleep.asJsonObject;
|
|
@@ -71215,6 +71505,7 @@ exports.resolveHydratedFieldValue = require_sleep.resolveHydratedFieldValue;
|
|
|
71215
71505
|
exports.resolveLocationIcon = resolveLocationIcon;
|
|
71216
71506
|
exports.resolveLocationMode = resolveLocationMode;
|
|
71217
71507
|
exports.resolveMethodAuth = resolveMethodAuth;
|
|
71508
|
+
exports.resolveModeDelays = resolveModeDelays;
|
|
71218
71509
|
exports.resolveMutate = resolveMutate;
|
|
71219
71510
|
exports.resolvePoolMemoryPolicy = resolvePoolMemoryPolicy;
|
|
71220
71511
|
exports.resolveRecordingProfiles = resolveRecordingProfiles;
|