@camstack/types 1.2.255 → 1.2.256
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 -1
- package/dist/addon.mjs +1 -1
- package/dist/capabilities/index.d.ts +1 -1
- package/dist/capabilities/notification-rules.cap.d.ts +149 -0
- package/dist/capabilities/osd-manager.cap.d.ts +32 -0
- package/dist/generated/addon-api.d.ts +7 -0
- package/dist/generated/method-access-map.d.ts +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +254 -1
- package/dist/index.mjs +243 -2
- package/dist/notification/alarm-membership.d.ts +43 -0
- package/dist/notification/sensor-raised.d.ts +45 -0
- package/dist/{sleep-D_4W7xuQ.mjs → sleep-DU7mu4wb.mjs} +1 -0
- package/dist/{sleep-BAgDk7I9.js → sleep-DtomDrRW.js} +1 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_sleep = require("./sleep-
|
|
2
|
+
const require_sleep = require("./sleep-DtomDrRW.js");
|
|
3
3
|
const require_event_category = require("./event-category-BVfsrBYA.js");
|
|
4
4
|
const require_canonical_hash = require("./canonical-hash-CSE4ioRi.js");
|
|
5
5
|
const require_enums = require("./enums.js");
|
|
@@ -17495,6 +17495,16 @@ var NcCrossingSchema = zod.z.enum([
|
|
|
17495
17495
|
"exit",
|
|
17496
17496
|
"any"
|
|
17497
17497
|
]);
|
|
17498
|
+
/**
|
|
17499
|
+
* Which edge of a BOOLEAN sensor fires a device-event rule (D640).
|
|
17500
|
+
* - `raised` — the sensor went high: water detected, smoke, open, tampered.
|
|
17501
|
+
* - `cleared` — it went back: dry, clear, closed.
|
|
17502
|
+
* - absent — both edges, which is what every rule authored before this did.
|
|
17503
|
+
*
|
|
17504
|
+
* There is no third member for "both": absence already says it, and a value
|
|
17505
|
+
* that means the same as absence is a second way to write one rule.
|
|
17506
|
+
*/
|
|
17507
|
+
var NcSensorTransitionSchema = zod.z.enum(["raised", "cleared"]);
|
|
17498
17508
|
/** Admin-zone membership condition (zone IDs as stamped by the ZoneEngine). */
|
|
17499
17509
|
var NcZoneConditionSchema = zod.z.object({
|
|
17500
17510
|
ids: zod.z.array(zod.z.string().min(1)).min(1),
|
|
@@ -17684,6 +17694,20 @@ var NcConditionsSchema = zod.z.object({
|
|
|
17684
17694
|
scene: NcSceneConditionSchema.optional(),
|
|
17685
17695
|
/** Device scope — absent = all devices. */
|
|
17686
17696
|
devices: zod.z.array(zod.z.number()).optional(),
|
|
17697
|
+
/**
|
|
17698
|
+
* Device EXCLUSION (D641) — "every device except these". Judged on the SAME
|
|
17699
|
+
* subject ids {@link devices} is judged on (the camera, the sensor that
|
|
17700
|
+
* fired, a linked set's sensor and row cameras), so a sensor fanned out per
|
|
17701
|
+
* linked camera is excluded exactly where an include would have tested it.
|
|
17702
|
+
* `min(1)`: an empty exclusion excludes nothing and is written as absent.
|
|
17703
|
+
*
|
|
17704
|
+
* Not for `system-event` rules — those carry their own
|
|
17705
|
+
* `systemEvent.excludeDeviceIds` (D636), and the hub refuses this key there.
|
|
17706
|
+
* Editors present the two lists as ONE field (All | Only these | All except
|
|
17707
|
+
* these); the engine evaluates each independently, so a legacy rule
|
|
17708
|
+
* carrying both still means "these, minus those".
|
|
17709
|
+
*/
|
|
17710
|
+
devicesExclude: zod.z.array(zod.z.number()).min(1).optional(),
|
|
17687
17711
|
/** Detector class names (any overlap with the record's class set). */
|
|
17688
17712
|
classes: zod.z.array(zod.z.string().min(1)).optional(),
|
|
17689
17713
|
/** Veto classes — any overlap fails the rule. */
|
|
@@ -17817,6 +17841,16 @@ var NcConditionsSchema = zod.z.object({
|
|
|
17817
17841
|
*/
|
|
17818
17842
|
sensorKinds: zod.z.array(zod.z.string().min(1)).optional(),
|
|
17819
17843
|
/**
|
|
17844
|
+
* DEVICE-EVENT only (D640). Fire on one edge of a boolean sensor —
|
|
17845
|
+
* {@link NcSensorTransitionSchema}. Which field of the slice means "raised"
|
|
17846
|
+
* is `@camstack/types` → `notification/sensor-raised.ts`. A reading the
|
|
17847
|
+
* engine cannot place (a kind with no raise, an unreadable slice) PASSES:
|
|
17848
|
+
* the condition fails open towards notifying, never towards silence. Editors
|
|
17849
|
+
* offer it only when every chosen {@link sensorKinds} member has a raise
|
|
17850
|
+
* (`sensorTransitionOffered`), and the hub refuses it on any other delivery.
|
|
17851
|
+
*/
|
|
17852
|
+
sensorTransition: NcSensorTransitionSchema.optional(),
|
|
17853
|
+
/**
|
|
17820
17854
|
* PACKAGE-EVENT only. Which package phase fires the rule — `delivered`
|
|
17821
17855
|
* (a parked parcel appeared), `picked-up` (it departed), or `both`. Fails
|
|
17822
17856
|
* when the subject's phase does not match (a subject always carries a phase
|
|
@@ -18449,6 +18483,7 @@ var NcConditionDescriptorSchema = zod.z.object({
|
|
|
18449
18483
|
/** Editor widget the UI renders — never hardcode per-condition forms. */
|
|
18450
18484
|
valueType: zod.z.enum([
|
|
18451
18485
|
"deviceIdList",
|
|
18486
|
+
"deviceIdExcludeList",
|
|
18452
18487
|
"stringList",
|
|
18453
18488
|
"number01",
|
|
18454
18489
|
"number",
|
|
@@ -18459,6 +18494,7 @@ var NcConditionDescriptorSchema = zod.z.object({
|
|
|
18459
18494
|
"plateMatcher",
|
|
18460
18495
|
"packagePhase",
|
|
18461
18496
|
"crossingSelect",
|
|
18497
|
+
"sensorTransition",
|
|
18462
18498
|
"polygonDraw",
|
|
18463
18499
|
"occupancy",
|
|
18464
18500
|
"audio",
|
|
@@ -18657,6 +18693,21 @@ var NC_CONDITION_CATALOG = [
|
|
|
18657
18693
|
phase: "P1",
|
|
18658
18694
|
description: "Restrict the rule to these devices; absent = all devices. A sensor event matches either the SENSOR that fired or the camera it is attributed to, so a rule may name either one."
|
|
18659
18695
|
},
|
|
18696
|
+
{
|
|
18697
|
+
id: "devicesExclude",
|
|
18698
|
+
group: "scope",
|
|
18699
|
+
label: "Excluded devices",
|
|
18700
|
+
valueType: "deviceIdExcludeList",
|
|
18701
|
+
operator: "notIn",
|
|
18702
|
+
appliesTo: [
|
|
18703
|
+
"immediate",
|
|
18704
|
+
"track-end",
|
|
18705
|
+
"device-event",
|
|
18706
|
+
"package-event"
|
|
18707
|
+
],
|
|
18708
|
+
phase: "P1",
|
|
18709
|
+
description: "Every device except these. Judged on the same device ids as Devices: a sensor event is excluded by the SENSOR that fired or by the camera it is attributed to."
|
|
18710
|
+
},
|
|
18660
18711
|
{
|
|
18661
18712
|
id: "classes",
|
|
18662
18713
|
group: "class",
|
|
@@ -18913,6 +18964,33 @@ var NC_CONDITION_CATALOG = [
|
|
|
18913
18964
|
phase: "P1",
|
|
18914
18965
|
description: "Raw device event-type tokens (e.g. doorbell press / press_long) from the event-emitter slice; absent on doorbell-pulse / passive sensors."
|
|
18915
18966
|
},
|
|
18967
|
+
{
|
|
18968
|
+
id: "sensorTransition",
|
|
18969
|
+
group: "device",
|
|
18970
|
+
label: "Notify when",
|
|
18971
|
+
valueType: "sensorTransition",
|
|
18972
|
+
options: [
|
|
18973
|
+
{
|
|
18974
|
+
value: "",
|
|
18975
|
+
label: "It triggers and when it clears",
|
|
18976
|
+
hint: "Every change: water detected, and back to dry."
|
|
18977
|
+
},
|
|
18978
|
+
{
|
|
18979
|
+
value: "raised",
|
|
18980
|
+
label: "Only when it triggers",
|
|
18981
|
+
hint: "Water detected, smoke, a contact opening — never the return to normal."
|
|
18982
|
+
},
|
|
18983
|
+
{
|
|
18984
|
+
value: "cleared",
|
|
18985
|
+
label: "Only when it clears",
|
|
18986
|
+
hint: "Back to dry, smoke gone, a contact closing — never the alert itself."
|
|
18987
|
+
}
|
|
18988
|
+
],
|
|
18989
|
+
operator: "in",
|
|
18990
|
+
appliesTo: ["device-event"],
|
|
18991
|
+
phase: "P2",
|
|
18992
|
+
description: "Fire on one edge of a boolean sensor. Offered only when every chosen sensor kind raises and clears; a reading that cannot be placed still notifies."
|
|
18993
|
+
},
|
|
18916
18994
|
{
|
|
18917
18995
|
id: "packagePhase",
|
|
18918
18996
|
group: "package",
|
|
@@ -19099,6 +19177,39 @@ var NcHistoryFilterSchema = zod.z.object({
|
|
|
19099
19177
|
limit: zod.z.number().int().min(1).max(500).default(100)
|
|
19100
19178
|
});
|
|
19101
19179
|
/**
|
|
19180
|
+
* The newest delivery row of ONE rule — the "Last run" of a rules table.
|
|
19181
|
+
*
|
|
19182
|
+
* A projection of the same outbox rows `getHistory` returns, so it records
|
|
19183
|
+
* DELIVERIES only: a throttled or unmatched evaluation never produced a row
|
|
19184
|
+
* and is not a run here. When one fire reached several targets (several rows
|
|
19185
|
+
* at the same `lastAt`), `status` is the least successful of them
|
|
19186
|
+
* (`dead` > `pending` > `sent`): "the last run delivered" must be true for
|
|
19187
|
+
* every target it names.
|
|
19188
|
+
*/
|
|
19189
|
+
var NcRuleLastRunSchema = zod.z.object({
|
|
19190
|
+
ruleId: zod.z.string(),
|
|
19191
|
+
/** Fire time of the newest row (`createdAt`, epoch ms). */
|
|
19192
|
+
lastAt: zod.z.number(),
|
|
19193
|
+
status: NcHistoryStatusSchema,
|
|
19194
|
+
/** The camera/device of that row (a digest row files under its first camera). */
|
|
19195
|
+
deviceId: zod.z.number()
|
|
19196
|
+
});
|
|
19197
|
+
/**
|
|
19198
|
+
* Every rule's last run, in one answer.
|
|
19199
|
+
*
|
|
19200
|
+
* A rule ABSENT from `runs` produced no delivery inside `horizonMs` — how far
|
|
19201
|
+
* back this answer looked, in ms before the hub's now. It is the outbox prune
|
|
19202
|
+
* window (7 days by default, operator-configurable), NARROWED when the read hit
|
|
19203
|
+
* its row bound: the answer never claims a window it did not read. `null` means
|
|
19204
|
+
* the operator keeps the outbox forever AND the read reached its end, so absent
|
|
19205
|
+
* means "never on record". A UI derives its "not in the last N days" from this
|
|
19206
|
+
* value, never from a constant — and only when the call ANSWERED (D315).
|
|
19207
|
+
*/
|
|
19208
|
+
var NcRuleLastRunsSchema = zod.z.object({
|
|
19209
|
+
runs: zod.z.array(NcRuleLastRunSchema),
|
|
19210
|
+
horizonMs: zod.z.number().nonnegative().nullable()
|
|
19211
|
+
});
|
|
19212
|
+
/**
|
|
19102
19213
|
* What a snooze covers. Broader scopes win when several overlap, so one window
|
|
19103
19214
|
* leaves ONE digest rather than a rule snooze and a whole-feed snooze both
|
|
19104
19215
|
* summarising the same silence.
|
|
@@ -19285,6 +19396,14 @@ var NcAlarmModeCoverageSchema = zod.z.object({
|
|
|
19285
19396
|
/** Ids named by the covering rules. A SUBSET when `allDevices` is true. */
|
|
19286
19397
|
deviceIds: zod.z.array(zod.z.number().int()),
|
|
19287
19398
|
/**
|
|
19399
|
+
* D641: the ids NOT covered although `allDevices` is true — every unscoped
|
|
19400
|
+
* covering rule EXCLUDES them (`conditions.devicesExclude`) and no named rule
|
|
19401
|
+
* covers them. Always `[]` when `allDevices` is false. Excluded by the rules,
|
|
19402
|
+
* which is not the same as skipped by a switch: never in `skippedDevices`.
|
|
19403
|
+
* Defaulted so an answer computed before this field parses as "none".
|
|
19404
|
+
*/
|
|
19405
|
+
allDevicesExcept: zod.z.array(zod.z.number().int()).default([]),
|
|
19406
|
+
/**
|
|
19288
19407
|
* Devices this mode NAMES but cannot actually arm, each with the switch that
|
|
19289
19408
|
* excludes it.
|
|
19290
19409
|
*
|
|
@@ -19526,6 +19645,15 @@ var notificationRulesCapability = {
|
|
|
19526
19645
|
*/
|
|
19527
19646
|
getHistory: require_sleep.method(zod.z.object({ filter: NcHistoryFilterSchema.default({ limit: 100 }) }), zod.z.object({ entries: zod.z.array(NcHistoryEntrySchema) }), { auth: "admin" }),
|
|
19528
19647
|
/**
|
|
19648
|
+
* The newest delivery of every rule, in ONE bounded read of the outbox —
|
|
19649
|
+
* the "Last run" column. Never a `getHistory` per rule. A rule with no
|
|
19650
|
+
* delivery inside `horizonMs` is absent from `runs`; see
|
|
19651
|
+
* {@link NcRuleLastRunsSchema} for what absent means. A store that cannot
|
|
19652
|
+
* answer FAILS the call rather than answering "nothing ran". Admin-only,
|
|
19653
|
+
* like `getHistory`, of which it is a projection.
|
|
19654
|
+
*/
|
|
19655
|
+
getRuleLastRuns: require_sleep.method(zod.z.object({}), NcRuleLastRunsSchema, { auth: "admin" }),
|
|
19656
|
+
/**
|
|
19529
19657
|
* Mint a fresh, externally-reachable URL for one artefact a history row
|
|
19530
19658
|
* named in {@link NcHistoryEntrySchema.shape.artifactIds} — the SAME
|
|
19531
19659
|
* signed-link mechanism the dispatcher uses to attach media to an
|
|
@@ -52863,6 +52991,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
52863
52991
|
addonId: null,
|
|
52864
52992
|
access: "view"
|
|
52865
52993
|
},
|
|
52994
|
+
"notificationRules.getRuleLastRuns": {
|
|
52995
|
+
capName: "notification-rules",
|
|
52996
|
+
capScope: "system",
|
|
52997
|
+
addonId: null,
|
|
52998
|
+
access: "view"
|
|
52999
|
+
},
|
|
52866
53000
|
"notificationRules.getTemplateCatalog": {
|
|
52867
53001
|
capName: "notification-rules",
|
|
52868
53002
|
capScope: "system",
|
|
@@ -61016,6 +61150,7 @@ function systemFamilyOfKind(kind) {
|
|
|
61016
61150
|
*/
|
|
61017
61151
|
var NO_SENSOR_KIND = "An occupancy edge is not a sensor event: it carries no sensor kind, so this condition can never match one.";
|
|
61018
61152
|
var NO_EVENT_TOKEN = "An occupancy edge carries no device event-type token — that comes from an event-emitter slice, which a count crossing has none of.";
|
|
61153
|
+
var NO_SENSOR_EDGE = "An occupancy edge is a count crossing, not a sensor reading: it has no raise or clear, so this choice could never narrow it.";
|
|
61019
61154
|
var OCCUPANCY_SOURCE = "An occupancy edge is always produced by the pipeline, so any other source can never match and “pipeline” narrows nothing.";
|
|
61020
61155
|
var AUDIO_SOURCE = "A confirmed sound window is always stamped as an audio subject, so any other source can never match.";
|
|
61021
61156
|
var SOUND_NOT_A_PICTURE = "A sound rule fires on what the camera HEARD. Its subject carries no detection, so this condition can never match one — name the sounds in the Sound condition instead.";
|
|
@@ -61047,6 +61182,7 @@ var NC_RULE_KIND_SPECS = [
|
|
|
61047
61182
|
excluded: {
|
|
61048
61183
|
sensorKinds: NO_SENSOR_KIND,
|
|
61049
61184
|
eventTypeTokens: NO_EVENT_TOKEN,
|
|
61185
|
+
sensorTransition: NO_SENSOR_EDGE,
|
|
61050
61186
|
source: OCCUPANCY_SOURCE
|
|
61051
61187
|
},
|
|
61052
61188
|
editable: true,
|
|
@@ -61500,6 +61636,111 @@ function isScheduleActive(schedule, atMs) {
|
|
|
61500
61636
|
return schedule.invert === true ? !inside : inside;
|
|
61501
61637
|
}
|
|
61502
61638
|
//#endregion
|
|
61639
|
+
//#region src/notification/alarm-membership.ts
|
|
61640
|
+
var ARMED_WORD_PREFIX = "armed_";
|
|
61641
|
+
var ALARM_PANEL_CAP = "alarm-panel";
|
|
61642
|
+
var ALARM_PANEL_TRIGGER_METHOD = "trigger";
|
|
61643
|
+
/**
|
|
61644
|
+
* The sensor-event kinds that are OPENINGS to the alarm — the keys of the
|
|
61645
|
+
* engine's opening table (`alarm-openings.ts`, which is checked against this
|
|
61646
|
+
* list with `satisfies`). Only these carry an opening edge the alarm refuses.
|
|
61647
|
+
*/
|
|
61648
|
+
var NC_ALARM_OPENING_EVENT_KINDS = [
|
|
61649
|
+
"contact",
|
|
61650
|
+
"cover",
|
|
61651
|
+
"lock"
|
|
61652
|
+
];
|
|
61653
|
+
/**
|
|
61654
|
+
* A rule belongs to the alarm when its `deviceState` gate names ANY device's
|
|
61655
|
+
* `armed_*` word, or an ENABLED `onTrigger` sequence pulls the alarm panel's
|
|
61656
|
+
* trigger (D630).
|
|
61657
|
+
*/
|
|
61658
|
+
function ruleBelongsToAlarm(rule) {
|
|
61659
|
+
if ((rule.conditions.deviceState?.states ?? []).some((s) => s.trim().toLowerCase().startsWith(ARMED_WORD_PREFIX))) return true;
|
|
61660
|
+
return (rule.onTrigger ?? []).some((sequence) => sequence.enabled && sequence.actions.some((step) => step.kind === "cap" && step.cap === ALARM_PANEL_CAP && step.method === ALARM_PANEL_TRIGGER_METHOD));
|
|
61661
|
+
}
|
|
61662
|
+
function isOpeningKind(kind) {
|
|
61663
|
+
const k = kind.trim().toLowerCase();
|
|
61664
|
+
return NC_ALARM_OPENING_EVENT_KINDS.some((opening) => opening === k);
|
|
61665
|
+
}
|
|
61666
|
+
/**
|
|
61667
|
+
* An alarm rule over openings only, asking for the CLEAR: the alarm edge
|
|
61668
|
+
* refuses every closing, and the chosen edge refuses every opening, so nothing
|
|
61669
|
+
* is left (D640 × D630). Not refused on save — alarm membership is derived and
|
|
61670
|
+
* can change with an action edit — but every editor must SAY it.
|
|
61671
|
+
*/
|
|
61672
|
+
function sensorTransitionNeverFires(rule) {
|
|
61673
|
+
const kinds = rule.conditions.sensorKinds ?? [];
|
|
61674
|
+
if (rule.conditions.sensorTransition !== "cleared" || kinds.length === 0) return false;
|
|
61675
|
+
if (!kinds.every(isOpeningKind)) return false;
|
|
61676
|
+
return ruleBelongsToAlarm(rule);
|
|
61677
|
+
}
|
|
61678
|
+
/** The warning an editor shows for {@link sensorTransitionNeverFires}. */
|
|
61679
|
+
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.";
|
|
61680
|
+
//#endregion
|
|
61681
|
+
//#region src/notification/sensor-raised.ts
|
|
61682
|
+
/**
|
|
61683
|
+
* WHICH WAY A BOOLEAN SENSOR MOVED — read off the one slice a sensor event
|
|
61684
|
+
* persists (D640 "a sensor rule fires on the raise, the clear, or both").
|
|
61685
|
+
*
|
|
61686
|
+
* A device-event rule over a flood sensor notified on BOTH edges: water
|
|
61687
|
+
* detected, and back to dry. `NcConditions.sensorTransition` lets the rule
|
|
61688
|
+
* name one edge; this file answers, for one `SensorEvent`, which edge it is.
|
|
61689
|
+
*
|
|
61690
|
+
* NOT A SECOND TABLE. The "which boolean of this cap counts as HIGH" question
|
|
61691
|
+
* already has one answer, `SOURCE_CAP_ACTIVE_FIELD`
|
|
61692
|
+
* (`catalogs/sensor-active-state.ts`, the doorbell's and the recorder's edge
|
|
61693
|
+
* table), and a sensor event names its kind, not its cap. So the table here is
|
|
61694
|
+
* DERIVED: event kind → cap (`EVENT_KIND_BY_CAP`) → that cap's active field.
|
|
61695
|
+
* Only kinds whose taxonomy category is `sensor` take part — a switch has an
|
|
61696
|
+
* `on` boolean too, but "it triggers / it clears" is not a sentence about a
|
|
61697
|
+
* light, and offering it there would be a knob with a misleading label.
|
|
61698
|
+
* `presence` is a WORD (`home` / `not_home` / a zone), not a boolean, and is
|
|
61699
|
+
* absent from the source table, so it is absent here.
|
|
61700
|
+
*
|
|
61701
|
+
* `undefined` = never guessed: a kind with no raise (a doorbell press, a
|
|
61702
|
+
* button, a cover), or a slice whose field is missing or not a boolean. The
|
|
61703
|
+
* engine then does NOT filter — a flood alert must not go silent because one
|
|
61704
|
+
* read came back unreadable (the same stance as the alarm's `sensorEdgeOf`).
|
|
61705
|
+
*
|
|
61706
|
+
* Pure, RN-safe: the viewer imports the support rule from here.
|
|
61707
|
+
*/
|
|
61708
|
+
/** Event kind → the boolean field of its cap slice that means "raised". */
|
|
61709
|
+
var NC_SENSOR_RAISED_FIELD_BY_KIND = Object.freeze(Object.fromEntries(Object.entries(EVENT_KIND_BY_CAP).flatMap(([capName, descriptor]) => {
|
|
61710
|
+
const field = SOURCE_CAP_ACTIVE_FIELD[capName];
|
|
61711
|
+
if (field === void 0 || descriptor.category !== "sensor") return [];
|
|
61712
|
+
return [[descriptor.kind, field]];
|
|
61713
|
+
})));
|
|
61714
|
+
/** The sensor kinds `sensorTransition` means something for. */
|
|
61715
|
+
var NC_SENSOR_TRANSITION_KINDS = Object.freeze(Object.keys(NC_SENSOR_RAISED_FIELD_BY_KIND));
|
|
61716
|
+
function normaliseKind(kind) {
|
|
61717
|
+
return kind.trim().toLowerCase();
|
|
61718
|
+
}
|
|
61719
|
+
/**
|
|
61720
|
+
* true = the sensor is raised (water, smoke, open, tampered…), false = it
|
|
61721
|
+
* cleared, undefined = this kind has no raise or the slice cannot say.
|
|
61722
|
+
*/
|
|
61723
|
+
function sensorRaisedOf(kind, value) {
|
|
61724
|
+
if (value === null) return void 0;
|
|
61725
|
+
const field = NC_SENSOR_RAISED_FIELD_BY_KIND[normaliseKind(kind)];
|
|
61726
|
+
if (field === void 0) return void 0;
|
|
61727
|
+
const raw = Object.entries(value).find(([key]) => key === field)?.[1];
|
|
61728
|
+
return typeof raw === "boolean" ? raw : void 0;
|
|
61729
|
+
}
|
|
61730
|
+
/**
|
|
61731
|
+
* THE SUPPORT RULE, shared by both editors: "Notify when" is offered only when
|
|
61732
|
+
* the rule names at least one sensor kind and EVERY kind it names has a raise.
|
|
61733
|
+
* A mixed rule (flood + doorbell) would hear "only when it clears" as "never
|
|
61734
|
+
* for the doorbell" in the operator's head while the engine lets the doorbell
|
|
61735
|
+
* through — so the choice is not offered, and an editor prunes it on save.
|
|
61736
|
+
*/
|
|
61737
|
+
function sensorTransitionOffered(sensorKinds) {
|
|
61738
|
+
if (sensorKinds === void 0 || sensorKinds.length === 0) return false;
|
|
61739
|
+
return sensorKinds.every((kind) => NC_SENSOR_TRANSITION_KINDS.includes(normaliseKind(kind)));
|
|
61740
|
+
}
|
|
61741
|
+
/** What an editor tells the operator when it is about to prune the choice. */
|
|
61742
|
+
var NC_SENSOR_TRANSITION_UNSUPPORTED_REASON = "Only a sensor that raises and clears (water, smoke, gas, CO, vibration, tamper, motion, contact) can fire on one edge. Pick only such sensor kinds, or the rule fires on every change.";
|
|
61743
|
+
//#endregion
|
|
61503
61744
|
//#region src/notification/template-vars.ts
|
|
61504
61745
|
var RULE_BODY_ONLY = ["body"];
|
|
61505
61746
|
var RULE_TEXT = ["title", "body"];
|
|
@@ -65910,6 +66151,7 @@ exports.NATIVE_LEASE_TILE_BUDGET_KEY = NATIVE_LEASE_TILE_BUDGET_KEY;
|
|
|
65910
66151
|
exports.NAVIGATION_ACTION_CATALOG = NAVIGATION_ACTION_CATALOG;
|
|
65911
66152
|
exports.NAVIGATION_LIGHT_LEVEL_MAX = NAVIGATION_LIGHT_LEVEL_MAX;
|
|
65912
66153
|
exports.NAVIGATION_LIGHT_LEVEL_MIN = NAVIGATION_LIGHT_LEVEL_MIN;
|
|
66154
|
+
exports.NC_ALARM_OPENING_EVENT_KINDS = NC_ALARM_OPENING_EVENT_KINDS;
|
|
65913
66155
|
exports.NC_ALARM_SYSTEM_EVENT_KINDS = NC_ALARM_SYSTEM_EVENT_KINDS;
|
|
65914
66156
|
exports.NC_AUDIO_CONFIRM_HITS_DEFAULT = NC_AUDIO_CONFIRM_HITS_DEFAULT;
|
|
65915
66157
|
exports.NC_AUDIO_CONFIRM_HITS_MAX = NC_AUDIO_CONFIRM_HITS_MAX;
|
|
@@ -65946,6 +66188,10 @@ exports.NC_RULE_CLEARABLE_KEYS = NC_RULE_CLEARABLE_KEYS;
|
|
|
65946
66188
|
exports.NC_RULE_EDITOR_SECTION_ORDER = NC_RULE_EDITOR_SECTION_ORDER;
|
|
65947
66189
|
exports.NC_RULE_KIND_SPECS = NC_RULE_KIND_SPECS;
|
|
65948
66190
|
exports.NC_RULE_SECTIONS = NC_RULE_SECTIONS;
|
|
66191
|
+
exports.NC_SENSOR_RAISED_FIELD_BY_KIND = NC_SENSOR_RAISED_FIELD_BY_KIND;
|
|
66192
|
+
exports.NC_SENSOR_TRANSITION_KINDS = NC_SENSOR_TRANSITION_KINDS;
|
|
66193
|
+
exports.NC_SENSOR_TRANSITION_NEVER_FIRES_WARNING = NC_SENSOR_TRANSITION_NEVER_FIRES_WARNING;
|
|
66194
|
+
exports.NC_SENSOR_TRANSITION_UNSUPPORTED_REASON = NC_SENSOR_TRANSITION_UNSUPPORTED_REASON;
|
|
65949
66195
|
exports.NC_SERVER_PACKAGE_NAME = NC_SERVER_PACKAGE_NAME;
|
|
65950
66196
|
exports.NC_SNOOZE_MAX_MINUTES = NC_SNOOZE_MAX_MINUTES;
|
|
65951
66197
|
exports.NC_SYSTEM_DELIVERY = NC_SYSTEM_DELIVERY;
|
|
@@ -66015,6 +66261,8 @@ exports.NcRuleActionsSchema = NcRuleActionsSchema;
|
|
|
66015
66261
|
exports.NcRuleClearableKeySchema = NcRuleClearableKeySchema;
|
|
66016
66262
|
exports.NcRuleInputSchema = NcRuleInputSchema;
|
|
66017
66263
|
exports.NcRuleKindSchema = NcRuleKindSchema;
|
|
66264
|
+
exports.NcRuleLastRunSchema = NcRuleLastRunSchema;
|
|
66265
|
+
exports.NcRuleLastRunsSchema = NcRuleLastRunsSchema;
|
|
66018
66266
|
exports.NcRuleNotificationButtonSchema = NcRuleNotificationButtonSchema;
|
|
66019
66267
|
exports.NcRulePatchSchema = NcRulePatchSchema;
|
|
66020
66268
|
exports.NcRuleSchema = NcRuleSchema;
|
|
@@ -66023,6 +66271,7 @@ exports.NcRuleUpdateInputSchema = NcRuleUpdateInputSchema;
|
|
|
66023
66271
|
exports.NcSceneConditionSchema = NcSceneConditionSchema;
|
|
66024
66272
|
exports.NcScheduleSchema = NcScheduleSchema;
|
|
66025
66273
|
exports.NcScheduleWindowSchema = NcScheduleWindowSchema;
|
|
66274
|
+
exports.NcSensorTransitionSchema = NcSensorTransitionSchema;
|
|
66026
66275
|
exports.NcSnoozeInputSchema = NcSnoozeInputSchema;
|
|
66027
66276
|
exports.NcSnoozeSchema = NcSnoozeSchema;
|
|
66028
66277
|
exports.NcSnoozeScopeSchema = NcSnoozeScopeSchema;
|
|
@@ -66926,6 +67175,7 @@ exports.resolveStreamMaps = require_canonical_hash.resolveStreamMaps;
|
|
|
66926
67175
|
exports.resolveVariantModelId = resolveVariantModelId;
|
|
66927
67176
|
exports.resolveViewableDeviceIds = resolveViewableDeviceIds;
|
|
66928
67177
|
exports.roleSpec = roleSpec;
|
|
67178
|
+
exports.ruleBelongsToAlarm = ruleBelongsToAlarm;
|
|
66929
67179
|
exports.ruleEditorSectionsForKind = ruleEditorSectionsForKind;
|
|
66930
67180
|
exports.ruleKindOf = ruleKindOf;
|
|
66931
67181
|
exports.ruleKindSpec = ruleKindSpec;
|
|
@@ -66946,6 +67196,9 @@ exports.scoreRuntimes = scoreRuntimes;
|
|
|
66946
67196
|
exports.scriptRunnerCapability = scriptRunnerCapability;
|
|
66947
67197
|
exports.searchDisplayIcons = searchDisplayIcons;
|
|
66948
67198
|
exports.selectAssignedProfileSlots = require_sleep.selectAssignedProfileSlots;
|
|
67199
|
+
exports.sensorRaisedOf = sensorRaisedOf;
|
|
67200
|
+
exports.sensorTransitionNeverFires = sensorTransitionNeverFires;
|
|
67201
|
+
exports.sensorTransitionOffered = sensorTransitionOffered;
|
|
66949
67202
|
exports.serverManagementCapability = serverManagementCapability;
|
|
66950
67203
|
exports.setByPath = setByPath;
|
|
66951
67204
|
exports.settingsStoreCapability = settingsStoreCapability;
|