@camstack/addon-post-analysis 1.2.310 → 1.2.312
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/{clip-model-registry-xYrJkXdS.js → clip-model-registry-CRkjjUyj.js} +257 -18
- package/dist/{clip-model-registry-BROqj9pS.mjs → clip-model-registry-ivwvxxex.mjs} +210 -19
- package/dist/embedding-encoder/index.js +1 -1
- package/dist/embedding-encoder/index.mjs +1 -1
- package/dist/pipeline-analytics/_stub.js +2 -2
- package/dist/pipeline-analytics/{_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-KF5Fk8sD.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-BocOElW2.mjs} +2 -2
- package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-Ds6vT2FJ.mjs +26 -0
- package/dist/pipeline-analytics/{_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-B8qeS8Da.mjs → _virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-B_KS96RA.mjs} +1 -1
- package/dist/pipeline-analytics/{hostInit-B3xcTHUM.mjs → hostInit-CRloCh1h.mjs} +2 -2
- package/dist/pipeline-analytics/index.js +413 -31
- package/dist/pipeline-analytics/index.mjs +413 -31
- package/dist/pipeline-analytics/remoteEntry.js +1 -1
- package/package.json +1 -1
- package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-DytyGNZ-.mjs +0 -26
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as
|
|
1
|
+
import { $ as NC_ALARM_SYSTEM_EVENT_KINDS, $n as readDeviceStateFrom, $r as union, $t as SetTrackPurityInputSchema, A as EMBEDDING_REQUIREMENTS_FAILED, An as encodeVectorBase64, Ar as CamProfileSchema, At as NcSnoozeSuppressedSchema, B as ListTrackRelationsInputSchema, Bn as isMediaOwnerType, Br as _enum, Bt as RECORDING_SOURCE_CAMSTACK_ADDON, C as DEFAULT_EVENT_COLOR, Cn as describeSystemEventDeliveryProblem, Cr as DEFAULT_FIRST_SIGHTING_FRESHNESS_MS, Ct as NcRulePatchSchema, D as DeclaredDevices, Dn as embeddingRefusalOf, Dr as DeviceType, Dt as NcScheduleSchema, E as DETECTION_PIPELINE_CAP_NAME, Er as isSourceCap, Et as NcRuleUpdateInputSchema, F as EXPORT_DENSE_MAX_RANGES, Fn as gifFromMp4Args, Fr as isDeviceScopedCap, Ft as NcTemplateVarDescriptorSchema, G as MAX_BIRTH_LATENCY_PROXY_MS, Gn as kebabToCamel, Gr as looseObject, Gt as SCENE_DEFAULT_ANCHOR_THRESHOLD, H as LockStateSchema, Hn as isSystemDelivery, Hr as boolean, Ht as RetrainStatusSchema, I as FIRST_LEVEL_MACRO_CLASSES, In as isAudioClassName, Ir as nodePin, It as OPS_LOG_DEFAULT_LIMIT, J as MOTION_CLOSE_AFTER_MS, Jn as notificationRulesCapability, Jr as partialRecord, Jt as SCENE_DEFAULT_QUIET_SECONDS, K as MAX_TRACK_PURITIES, Kn as mayWriteToLocation, Kr as number, Kt as SCENE_DEFAULT_CHECK_INTERVAL_SEC, L as FULL_IMAGE_BBOX, Ln as isDetectionMacroClass, Lt as OpsLogEntrySchema, M as EVENT_DENSITY_BATCH_MAX, Mn as faceGalleryCapability, Mr as customAction, Mt as NcTaxonomySchema, N as EVENT_KIND_BY_CAP, Nn as failureContributionCapability, Nr as defineCustomActions, Nt as NcTemplatePreviewInputSchema, O as DetectionSourceSchema, Or as errMsg, Ot as NcSnoozeInputSchema, P as EVENT_OWNER_TYPES, Pn as gifDeriveSpeed, Pr as hydrateSchema, Pt as NcTemplatePreviewSchema, Q as NC_ALARM_DELAY_MAX_SEC, Qn as plateGalleryCapability, Qr as tuple, Qt as SceneMonitorSchema, R as FailureCounters, Rn as isEventOwnerType, Rr as sleep$1, S as CoverStateSchema, Sn as deriveRecordingMode, Sr as zoneAnalyticsCapability, St as NcRuleInputSchema, T as DETECTION_MACRO_CLASSES, Tr as evaluateSensorEdge, Tt as NcRuleTargetSchema, U as MAX_ARCHIVED_DEBUG_NOTES, Un as isSystemEventSummaryRule, Ur as discriminatedUnion, Ut as SCENE_CONFIRM_DEFAULT_MAX_IMAGE_PX, V as ListTrackRelationsResultSchema, Vn as isScheduleActive, Vr as array, Vt as RebuildObjectEmbeddingsRefusalSchema, W as MAX_BIRTH_DECISION_RECORDS, Wn as isVectorIndexDimConflict, Wr as literal, Wt as SCENE_CONFIRM_DEFAULT_TIMEOUT_MS, X as MotionTriggeredBySchema, Xr as strictObject, Xt as SCENE_DIVERGED, Y as MediaFileKindEnum, Yn as occupancyScope, Yr as record, Yt as SCENE_DEFAULT_UNCOVERED_POLICY, Z as NC_ALARM_DELAY_FIELDS, Zn as pipelineAnalyticsCapability, Zr as string, Zt as SCENE_RESET_RECAPTURES, _ as BaseDevice, _n as audioMetricsCapability, _r as systemEventSummaryScheduleOf, _t as NcAlarmSensorsInputSchema, a as CLIP_EMBEDDING_STEP_ID, an as TimelapseRulePatchSchema, at as NC_CLIP_RETENTION_MAX_SEC, b as ClearTrackRelationInputSchema, bn as consumableLowPercentOf, br as templateVarsFor, bt as NcConditionDescriptorSchema, c as resolveClusterModelPin, cn as TrackRelationKindSchema, cr as ruleKindOf, ct as NC_CONSUMABLE_SYSTEM_EVENT_KINDS, d as APPEARANCE_RESOLVES_AMBIGUITY_DEFAULT, dn as TrackSourceSchema, dr as servedTemplateVars, dt as NC_SNOOZE_MAX_MINUTES, ei as unknown, en as SetTrackPurityResultSchema, er as readMotionTriggeredBy, et as NC_ALARM_TRIGGERED_MAX_SEC, f as ARCHIVED_DEBUG_NOTES_DEFAULT_LIMIT, fn as addonWidgetsSourceCapability, fr as storageOccupancyCapability, ft as NC_SYSTEM_EVENT_KIND_GROUP_SPECS, g as BIRTH_DECISION_DEFAULT_LIMIT, gn as assertTimelapseCadences, gr as systemEventFilterApplies, gt as NcAlarmConfigSchema, h as ArchivedDebugNoteSchema, hn as applyNonBlockingEdit, hr as systemEventFamilyProblems, ht as NC_TEMPLATE_VARS, in as TimelapseRuleInputSchema, ir as resolveModeDelays, it as NC_CLIP_PRE_ROLL_DEFAULT_SEC, j as EMBEDDING_REQUIREMENTS_UNAVAILABLE, jn as evictionPolicyOfLocation, jr as createEvent, jt as NcSystemEventKindSchema, k as EMBEDDING_MODEL_FAILED, kr as BaseAddon, kt as NcSnoozeSchema, l as APPEARANCE_BIN_COUNT, ln as TrackRelationSchema, lr as sceneMonitorCapability, lt as NC_DEFAULT_SNOOZE_MINUTES, m as AlarmArmModeSchema, mn as applyModeDelaysEdits, mr as systemEventDeliveryProblems, mt as NC_TAXONOMY, nn as TIMELAPSE_DENSE_FLOOR_SEC, nr as resolveClipSearchMinScore, nt as NC_AUDIO_CONFIRM_WINDOW_SEC_DEFAULT, o as FACE_EMBEDDING_STEP_ID, on as TimelapseRuleSchema, or as ruleBelongsToAlarm$1, ot as NC_CONDITION_CATALOG, p as AUDIO_MACRO_LABELS, pn as alarmPanelCapability, pr as subKindsOf, pt as NC_TANK_SYSTEM_EVENT_KINDS, q as MAX_TRACK_RELATIONS, qn as memoizePinnedFfmpeg, qr as object, qt as SCENE_DEFAULT_OBSERVATION_SPACING_SEC, rn as TRACK_RELATIONS_DEFAULT_LIMIT, rr as resolveLocationMode, rt as NC_CLIP_POST_ROLL_DEFAULT_SEC, s as readClusterModelPinStrict, sn as TrackPuritySchema, sr as ruleDeviceCompatCapQueries, st as NC_CONSUMABLE_LOW_PERCENT_DEFAULT, t as BUILTIN_CLIP_MODELS, ti as EventCategory, tn as SetTrackRelationInputSchema, tr as readTimelapseGeneratedAt, tt as NC_AUDIO_CONFIRM_HITS_DEFAULT, u as APPEARANCE_BLOCKS, un as TrackSideSchema, ur as sensorRaisedOf, ut as NC_SENSOR_TRANSITION_KINDS, v as BirthDecisionRecordSchema, vn as audioModeOf, vr as systemEventSummarySplitOf, vt as NcAlarmSensorsSchema, w as DEFAULT_TIMELAPSE_PREVIEW_TEXT, wn as describeSystemEventFamilyProblem, wr as canonicalHash, wt as NcRuleSchema, x as ClearTrackRelationResultSchema, xn as cosineSimilarity$1, xr as vectorDimFromBase64, xt as NcConditionsSchema, y as COCO_TO_MACRO, yn as buildEventKindDescriptor, yr as templateCarriesSummary, yt as NcAlarmSettingsPatchSchema, z as LabelAttributionSchema, zn as isKnownTemplateVar, zr as ZodObject, zt as RECORDING_EXPORT_MAX_READ_BYTES } from "../clip-model-registry-ivwvxxex.mjs";
|
|
2
2
|
import { t as __exportAll } from "../embedding-encoder/index.mjs";
|
|
3
3
|
import * as fs$1 from "node:fs";
|
|
4
4
|
import { createWriteStream, promises } from "node:fs";
|
|
@@ -1389,11 +1389,85 @@ var NcAlarmExclusions = class {
|
|
|
1389
1389
|
}
|
|
1390
1390
|
};
|
|
1391
1391
|
//#endregion
|
|
1392
|
+
//#region src/notification-center/alarm/alarm-mode-delays.ts
|
|
1393
|
+
/**
|
|
1394
|
+
* The persisted per-mode delay overrides, read through a guard (D697).
|
|
1395
|
+
*
|
|
1396
|
+
* The panel's config schema keeps `mode` a plain string so a blob written by a later release
|
|
1397
|
+
* with a mode this one does not know cannot fail the whole config. This is where that string is
|
|
1398
|
+
* narrowed: an entry that cannot be trusted is dropped and REPORTED, never repaired. An entry of an unknown
|
|
1399
|
+
* mode is also handed back raw (`foreign`) so a write can keep it.
|
|
1400
|
+
*/
|
|
1401
|
+
function inBounds(value, max) {
|
|
1402
|
+
return Number.isInteger(value) && value >= 0 && value <= max;
|
|
1403
|
+
}
|
|
1404
|
+
/** Read the persisted overrides through a guard, never a cast (like `nonBlockingFromPersisted`). */
|
|
1405
|
+
function modeDelaysFromPersisted(raw) {
|
|
1406
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1407
|
+
const entries = [];
|
|
1408
|
+
const dropped = [];
|
|
1409
|
+
const foreign = [];
|
|
1410
|
+
for (const item of raw) {
|
|
1411
|
+
const mode = AlarmArmModeSchema.safeParse(item.mode);
|
|
1412
|
+
if (!mode.success) {
|
|
1413
|
+
dropped.push({
|
|
1414
|
+
mode: item.mode,
|
|
1415
|
+
why: "unknown-mode"
|
|
1416
|
+
});
|
|
1417
|
+
foreign.push(item);
|
|
1418
|
+
continue;
|
|
1419
|
+
}
|
|
1420
|
+
if (seen.has(mode.data)) {
|
|
1421
|
+
dropped.push({
|
|
1422
|
+
mode: item.mode,
|
|
1423
|
+
why: "duplicate-mode"
|
|
1424
|
+
});
|
|
1425
|
+
continue;
|
|
1426
|
+
}
|
|
1427
|
+
seen.add(mode.data);
|
|
1428
|
+
const kept = { mode: mode.data };
|
|
1429
|
+
const fields = [
|
|
1430
|
+
{
|
|
1431
|
+
field: "exitDelaySec",
|
|
1432
|
+
max: NC_ALARM_DELAY_MAX_SEC
|
|
1433
|
+
},
|
|
1434
|
+
{
|
|
1435
|
+
field: "entryDelaySec",
|
|
1436
|
+
max: NC_ALARM_DELAY_MAX_SEC
|
|
1437
|
+
},
|
|
1438
|
+
{
|
|
1439
|
+
field: "triggeredDurationSec",
|
|
1440
|
+
max: NC_ALARM_TRIGGERED_MAX_SEC
|
|
1441
|
+
}
|
|
1442
|
+
];
|
|
1443
|
+
for (const { field, max } of fields) {
|
|
1444
|
+
const value = item[field];
|
|
1445
|
+
if (value === void 0) continue;
|
|
1446
|
+
if (!inBounds(value, max)) {
|
|
1447
|
+
dropped.push({
|
|
1448
|
+
mode: item.mode,
|
|
1449
|
+
why: "out-of-bounds",
|
|
1450
|
+
field
|
|
1451
|
+
});
|
|
1452
|
+
continue;
|
|
1453
|
+
}
|
|
1454
|
+
kept[field] = value;
|
|
1455
|
+
}
|
|
1456
|
+
if (kept.exitDelaySec !== void 0 || kept.entryDelaySec !== void 0 || kept.triggeredDurationSec !== void 0) entries.push(kept);
|
|
1457
|
+
}
|
|
1458
|
+
return {
|
|
1459
|
+
entries,
|
|
1460
|
+
dropped,
|
|
1461
|
+
foreign
|
|
1462
|
+
};
|
|
1463
|
+
}
|
|
1464
|
+
//#endregion
|
|
1392
1465
|
//#region src/notification-center/alarm/alarm-state-machine.ts
|
|
1393
1466
|
/**
|
|
1394
|
-
*
|
|
1395
|
-
*
|
|
1396
|
-
*
|
|
1467
|
+
* The GLOBAL defaults an operator can change per panel — what a mode inherits
|
|
1468
|
+
* when it overrides nothing. A mode can override each of the three since D697
|
|
1469
|
+
* (`resolveModeDelays`): `home` has no exit delay on purpose — nobody is
|
|
1470
|
+
* leaving — and says so with its own entry, not by this shared value.
|
|
1397
1471
|
*
|
|
1398
1472
|
* `triggeredDurationSec: 0` = "sound until somebody disarms it". That is what
|
|
1399
1473
|
* the panel did before the field existed, so an install that never opens the
|
|
@@ -1808,6 +1882,19 @@ var ncAlarmPanelSchema = object({
|
|
|
1808
1882
|
nonBlocking: array(object({
|
|
1809
1883
|
mode: string(),
|
|
1810
1884
|
deviceIds: array(number().int())
|
|
1885
|
+
})).default([]),
|
|
1886
|
+
/**
|
|
1887
|
+
* Per arm mode, the delays that override the global ones (D697). Loose on purpose — `mode` is
|
|
1888
|
+
* a string and the numbers are unbounded here — and read back through
|
|
1889
|
+
* {@link modeDelaysFromPersisted}, never a cast: an entry this release cannot trust is dropped
|
|
1890
|
+
* and logged at boot, never the whole config. A blob written before D697 has no key and
|
|
1891
|
+
* parses to no overrides.
|
|
1892
|
+
*/
|
|
1893
|
+
modeDelays: array(object({
|
|
1894
|
+
mode: string(),
|
|
1895
|
+
exitDelaySec: number().optional(),
|
|
1896
|
+
entryDelaySec: number().optional(),
|
|
1897
|
+
triggeredDurationSec: number().optional()
|
|
1811
1898
|
})).default([])
|
|
1812
1899
|
});
|
|
1813
1900
|
/**
|
|
@@ -1878,7 +1965,6 @@ function machineFromPersisted(raw) {
|
|
|
1878
1965
|
var NcAlarmPanelDevice = class extends BaseDevice {
|
|
1879
1966
|
features = [];
|
|
1880
1967
|
machine = DISARMED;
|
|
1881
|
-
delays = DEFAULT_DELAYS;
|
|
1882
1968
|
ticker = null;
|
|
1883
1969
|
onPublish = null;
|
|
1884
1970
|
/**
|
|
@@ -1909,7 +1995,7 @@ var NcAlarmPanelDevice = class extends BaseDevice {
|
|
|
1909
1995
|
refusalSeq = 0;
|
|
1910
1996
|
constructor(ctx) {
|
|
1911
1997
|
super(ctx, ncAlarmPanelSchema, { type: DeviceType.AlarmPanel });
|
|
1912
|
-
this.
|
|
1998
|
+
this.logDroppedModeDelays();
|
|
1913
1999
|
this.restore();
|
|
1914
2000
|
this.registerAlarmCap();
|
|
1915
2001
|
this.publish();
|
|
@@ -1921,30 +2007,148 @@ var NcAlarmPanelDevice = class extends BaseDevice {
|
|
|
1921
2007
|
...this.readDelays(),
|
|
1922
2008
|
announceArm: this.config.get("announceArm"),
|
|
1923
2009
|
announceTargets: [...this.config.get("announceTargets")],
|
|
1924
|
-
nonBlocking: nonBlockingFromPersisted(this.config.get("nonBlocking"))
|
|
2010
|
+
nonBlocking: nonBlockingFromPersisted(this.config.get("nonBlocking")),
|
|
2011
|
+
modeDelays: modeDelaysFromPersisted(this.config.get("modeDelays")).entries
|
|
1925
2012
|
};
|
|
1926
2013
|
}
|
|
1927
2014
|
/**
|
|
1928
2015
|
* Apply an editor's patch and return what the panel settled on.
|
|
1929
2016
|
*
|
|
1930
2017
|
* The new delays take effect on the NEXT transition, never retroactively: a
|
|
1931
|
-
* machine already counting down keeps the instants it was given
|
|
1932
|
-
*
|
|
1933
|
-
*
|
|
2018
|
+
* machine already counting down keeps the instants it was given (the exit
|
|
2019
|
+
* delay is read at arm, the entry delay and siren duration at trigger, and
|
|
2020
|
+
* the machine stores the instants, not the durations). Re-deriving `armedAt`
|
|
2021
|
+
* from a delay the operator changed mid-exit would move the arm instant under
|
|
2022
|
+
* somebody who is walking out of the door.
|
|
2023
|
+
*
|
|
2024
|
+
* Two phases, so a refused patch writes NOTHING:
|
|
2025
|
+
* 1. every refusal is checked first (a mode this panel does not offer, an
|
|
2026
|
+
* add to a full non-blocking list) — it logs why and throws;
|
|
2027
|
+
* 2. every LIST write is CALLED before the first `await`. `DeviceConfig.set`
|
|
2028
|
+
* replaces its in-memory value synchronously, so a list computed after an
|
|
2029
|
+
* await could be based on a list another call has since replaced — and a
|
|
2030
|
+
* whole-list write (the deleted-device prune sends one, computed
|
|
2031
|
+
* synchronously before calling: `device-prune-runner.ts` `applyAlarm`)
|
|
2032
|
+
* would erase the membership edit that landed in between.
|
|
1934
2033
|
*/
|
|
1935
2034
|
async applySettings(patch) {
|
|
2035
|
+
const edits = patch.modeDelays ?? [];
|
|
2036
|
+
const membership = patch.nonBlockingEdit;
|
|
2037
|
+
for (const edit of edits) this.refuseUnofferedMode(edit.mode);
|
|
2038
|
+
if (membership !== void 0) {
|
|
2039
|
+
this.refuseUnofferedMode(membership.mode, membership.deviceId);
|
|
2040
|
+
const verdict = applyNonBlockingEdit(patch.nonBlocking !== void 0 ? patch.nonBlocking : nonBlockingFromPersisted(this.config.get("nonBlocking")), membership);
|
|
2041
|
+
if (verdict.kind === "refused") {
|
|
2042
|
+
this.ctx.logger.info("alarm settings refused", {
|
|
2043
|
+
tags: { deviceId: membership.deviceId },
|
|
2044
|
+
meta: {
|
|
2045
|
+
panelId: this.id,
|
|
2046
|
+
reason: "list-full",
|
|
2047
|
+
mode: verdict.mode
|
|
2048
|
+
}
|
|
2049
|
+
});
|
|
2050
|
+
throw new Error(`the ${verdict.mode} non-blocking list already holds ${verdict.max} devices — remove one first`);
|
|
2051
|
+
}
|
|
2052
|
+
}
|
|
2053
|
+
const listWrites = [];
|
|
2054
|
+
if (patch.nonBlocking !== void 0) listWrites.push(this.config.set("nonBlocking", patch.nonBlocking.map((l) => ({
|
|
2055
|
+
mode: l.mode,
|
|
2056
|
+
deviceIds: [...l.deviceIds]
|
|
2057
|
+
}))));
|
|
2058
|
+
let membershipChanged = null;
|
|
2059
|
+
if (membership !== void 0) {
|
|
2060
|
+
const result = applyNonBlockingEdit(nonBlockingFromPersisted(this.config.get("nonBlocking")), membership);
|
|
2061
|
+
if (result.kind === "applied") {
|
|
2062
|
+
membershipChanged = result.changed;
|
|
2063
|
+
if (result.changed) listWrites.push(this.config.set("nonBlocking", result.lists.map((l) => ({
|
|
2064
|
+
mode: l.mode,
|
|
2065
|
+
deviceIds: [...l.deviceIds]
|
|
2066
|
+
}))));
|
|
2067
|
+
}
|
|
2068
|
+
}
|
|
2069
|
+
const persistedDelays = modeDelaysFromPersisted(this.config.get("modeDelays"));
|
|
2070
|
+
const beforeDelays = persistedDelays.entries;
|
|
2071
|
+
const afterDelays = edits.length > 0 ? applyModeDelaysEdits(beforeDelays, edits) : beforeDelays;
|
|
2072
|
+
if (edits.length > 0) {
|
|
2073
|
+
for (const drop of persistedDelays.dropped) {
|
|
2074
|
+
if (drop.why === "unknown-mode") continue;
|
|
2075
|
+
this.ctx.logger.info("alarm per-mode delay discarded on write", {
|
|
2076
|
+
tags: { deviceId: this.id },
|
|
2077
|
+
meta: {
|
|
2078
|
+
mode: drop.mode,
|
|
2079
|
+
why: drop.why,
|
|
2080
|
+
field: drop.field
|
|
2081
|
+
}
|
|
2082
|
+
});
|
|
2083
|
+
}
|
|
2084
|
+
listWrites.push(this.config.set("modeDelays", [...afterDelays, ...persistedDelays.foreign]));
|
|
2085
|
+
}
|
|
2086
|
+
await Promise.all(listWrites);
|
|
2087
|
+
this.logModeDelayChanges(beforeDelays, afterDelays, edits);
|
|
1936
2088
|
if (patch.exitDelaySec !== void 0) await this.config.set("exitDelaySec", patch.exitDelaySec);
|
|
1937
2089
|
if (patch.entryDelaySec !== void 0) await this.config.set("entryDelaySec", patch.entryDelaySec);
|
|
1938
2090
|
if (patch.triggeredDurationSec !== void 0) await this.config.set("triggeredDurationSec", patch.triggeredDurationSec);
|
|
1939
2091
|
if (patch.announceArm !== void 0) await this.config.set("announceArm", patch.announceArm);
|
|
1940
2092
|
if (patch.announceTargets !== void 0) await this.config.set("announceTargets", [...patch.announceTargets]);
|
|
1941
|
-
if (
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
2093
|
+
if (membership !== void 0 && membershipChanged !== null) this.ctx.logger.info("alarm non-blocking list changed", {
|
|
2094
|
+
tags: { deviceId: membership.deviceId },
|
|
2095
|
+
meta: {
|
|
2096
|
+
panelId: this.id,
|
|
2097
|
+
mode: membership.mode,
|
|
2098
|
+
nonBlocking: membership.nonBlocking,
|
|
2099
|
+
changed: membershipChanged
|
|
2100
|
+
}
|
|
2101
|
+
});
|
|
1946
2102
|
return this.settings();
|
|
1947
2103
|
}
|
|
2104
|
+
/**
|
|
2105
|
+
* Refuse a mode this panel does not offer — logged by reason, then thrown. A membership edit
|
|
2106
|
+
* passes its SENSOR as `deviceId` (the tag); a per-mode delay edit defaults to the panel.
|
|
2107
|
+
*/
|
|
2108
|
+
refuseUnofferedMode(mode, deviceId = this.id) {
|
|
2109
|
+
if (NC_ALARM_MODES.includes(mode)) return;
|
|
2110
|
+
this.ctx.logger.info("alarm settings refused", {
|
|
2111
|
+
tags: { deviceId },
|
|
2112
|
+
meta: {
|
|
2113
|
+
panelId: this.id,
|
|
2114
|
+
reason: "mode-not-offered",
|
|
2115
|
+
mode
|
|
2116
|
+
}
|
|
2117
|
+
});
|
|
2118
|
+
throw new Error(`alarm mode '${mode}' is not offered by this panel`);
|
|
2119
|
+
}
|
|
2120
|
+
/** One INFO line per mode-delay field an edit really changed (`null` = inherit). */
|
|
2121
|
+
logModeDelayChanges(before, after, edits) {
|
|
2122
|
+
for (const edit of edits) {
|
|
2123
|
+
const was = before.find((e) => e.mode === edit.mode);
|
|
2124
|
+
const now = after.find((e) => e.mode === edit.mode);
|
|
2125
|
+
for (const field of NC_ALARM_DELAY_FIELDS) {
|
|
2126
|
+
const from = was?.[field] ?? null;
|
|
2127
|
+
const to = now?.[field] ?? null;
|
|
2128
|
+
if (from === to) continue;
|
|
2129
|
+
this.ctx.logger.info("alarm mode delays changed", {
|
|
2130
|
+
tags: { deviceId: this.id },
|
|
2131
|
+
meta: {
|
|
2132
|
+
mode: edit.mode,
|
|
2133
|
+
field,
|
|
2134
|
+
from,
|
|
2135
|
+
to
|
|
2136
|
+
}
|
|
2137
|
+
});
|
|
2138
|
+
}
|
|
2139
|
+
}
|
|
2140
|
+
}
|
|
2141
|
+
/** One INFO line per persisted per-mode delay entry the guard refused to trust. */
|
|
2142
|
+
logDroppedModeDelays() {
|
|
2143
|
+
for (const drop of modeDelaysFromPersisted(this.config.get("modeDelays")).dropped) this.ctx.logger.info("alarm per-mode delay dropped at boot", {
|
|
2144
|
+
tags: { deviceId: this.id },
|
|
2145
|
+
meta: {
|
|
2146
|
+
mode: drop.mode,
|
|
2147
|
+
why: drop.why,
|
|
2148
|
+
field: drop.field
|
|
2149
|
+
}
|
|
2150
|
+
});
|
|
2151
|
+
}
|
|
1948
2152
|
/** Wire the state mirror and the transition notifications. See
|
|
1949
2153
|
* {@link NcAlarmPublishHook}. */
|
|
1950
2154
|
setPublishHook(hook) {
|
|
@@ -2227,7 +2431,17 @@ var NcAlarmPanelDevice = class extends BaseDevice {
|
|
|
2227
2431
|
else this.exclusions.clear();
|
|
2228
2432
|
this.persist();
|
|
2229
2433
|
}
|
|
2230
|
-
|
|
2434
|
+
const resolved = this.delaysFor(mode);
|
|
2435
|
+
this.machine = arm(mode, resolved, now);
|
|
2436
|
+
this.ctx.logger.info("alarm delays applied", {
|
|
2437
|
+
tags: { deviceId: this.id },
|
|
2438
|
+
meta: {
|
|
2439
|
+
mode,
|
|
2440
|
+
phase: "arm",
|
|
2441
|
+
exitDelaySec: resolved.exitDelaySec,
|
|
2442
|
+
source: resolved.source.exitDelaySec
|
|
2443
|
+
}
|
|
2444
|
+
});
|
|
2231
2445
|
this.attribution.clear();
|
|
2232
2446
|
this.publish(now);
|
|
2233
2447
|
for (const { device, why } of exclusions ?? []) this.ctx.logger.info("alarm armed with an open device excluded", {
|
|
@@ -2327,7 +2541,9 @@ var NcAlarmPanelDevice = class extends BaseDevice {
|
|
|
2327
2541
|
this.announceIgnoredTrigger(source, now);
|
|
2328
2542
|
return;
|
|
2329
2543
|
}
|
|
2330
|
-
const
|
|
2544
|
+
const armed = armModeOf(this.machine.target, NC_ALARM_MODES);
|
|
2545
|
+
const resolved = this.delaysFor(armed);
|
|
2546
|
+
const next = trigger(this.machine, resolved, now);
|
|
2331
2547
|
if (next === this.machine) {
|
|
2332
2548
|
const state = stateAt(this.machine, now);
|
|
2333
2549
|
this.ctx.logger.info(ignoredTriggerMessage(state), {
|
|
@@ -2345,6 +2561,19 @@ var NcAlarmPanelDevice = class extends BaseDevice {
|
|
|
2345
2561
|
}
|
|
2346
2562
|
});
|
|
2347
2563
|
this.machine = next;
|
|
2564
|
+
this.ctx.logger.info("alarm delays applied", {
|
|
2565
|
+
tags: { deviceId: this.id },
|
|
2566
|
+
meta: {
|
|
2567
|
+
mode: armed,
|
|
2568
|
+
phase: "trigger",
|
|
2569
|
+
entryDelaySec: resolved.entryDelaySec,
|
|
2570
|
+
triggeredDurationSec: resolved.triggeredDurationSec,
|
|
2571
|
+
source: {
|
|
2572
|
+
entry: resolved.source.entryDelaySec,
|
|
2573
|
+
siren: resolved.source.triggeredDurationSec
|
|
2574
|
+
}
|
|
2575
|
+
}
|
|
2576
|
+
});
|
|
2348
2577
|
this.publish(now);
|
|
2349
2578
|
}
|
|
2350
2579
|
});
|
|
@@ -2480,7 +2709,32 @@ var NcAlarmPanelDevice = class extends BaseDevice {
|
|
|
2480
2709
|
});
|
|
2481
2710
|
}
|
|
2482
2711
|
}
|
|
2483
|
-
/** The
|
|
2712
|
+
/** The global durations plus the per-mode overrides, read from the persisted config NOW. */
|
|
2713
|
+
delaySettings() {
|
|
2714
|
+
return {
|
|
2715
|
+
...this.readDelays(),
|
|
2716
|
+
modeDelays: modeDelaysFromPersisted(this.config.get("modeDelays")).entries
|
|
2717
|
+
};
|
|
2718
|
+
}
|
|
2719
|
+
/**
|
|
2720
|
+
* What `mode` runs on, read at the transition that uses it — never cached. `null` (no armed
|
|
2721
|
+
* mode to look at) is the global values, every field `default`.
|
|
2722
|
+
*/
|
|
2723
|
+
delaysFor(mode) {
|
|
2724
|
+
const settings = this.delaySettings();
|
|
2725
|
+
if (mode === null) return {
|
|
2726
|
+
exitDelaySec: settings.exitDelaySec,
|
|
2727
|
+
entryDelaySec: settings.entryDelaySec,
|
|
2728
|
+
triggeredDurationSec: settings.triggeredDurationSec,
|
|
2729
|
+
source: {
|
|
2730
|
+
exitDelaySec: "default",
|
|
2731
|
+
entryDelaySec: "default",
|
|
2732
|
+
triggeredDurationSec: "default"
|
|
2733
|
+
}
|
|
2734
|
+
};
|
|
2735
|
+
return resolveModeDelays(settings, mode);
|
|
2736
|
+
}
|
|
2737
|
+
/** The three global durations, read from the persisted config. */
|
|
2484
2738
|
readDelays() {
|
|
2485
2739
|
return {
|
|
2486
2740
|
exitDelaySec: this.config.get("exitDelaySec"),
|
|
@@ -8345,6 +8599,79 @@ function sameWord(a, b) {
|
|
|
8345
8599
|
return a !== void 0 && a.trim().toLowerCase() === b.trim().toLowerCase();
|
|
8346
8600
|
}
|
|
8347
8601
|
//#endregion
|
|
8602
|
+
//#region src/notification-center/alarm/alarm-sensors.ts
|
|
8603
|
+
/**
|
|
8604
|
+
* One id's state as the table shows it — spec §3.4's hub table, nothing else.
|
|
8605
|
+
*
|
|
8606
|
+
* Built ON `classifyCoveredOpening`, the arm check's classifier: what is
|
|
8607
|
+
* unknown, open or skipped is decided there, and this only splits a skip into
|
|
8608
|
+
* `closed` / `not-opening` for the table. A later change to the classifier
|
|
8609
|
+
* therefore moves the table with the arm.
|
|
8610
|
+
*/
|
|
8611
|
+
function alarmSensorStateOf(deviceId, opening, online) {
|
|
8612
|
+
const verdict = classifyCoveredOpening(opening);
|
|
8613
|
+
switch (verdict.kind) {
|
|
8614
|
+
case "unknown": return {
|
|
8615
|
+
deviceId,
|
|
8616
|
+
reading: "unknown",
|
|
8617
|
+
state: null,
|
|
8618
|
+
unknownWhy: verdict.why,
|
|
8619
|
+
online
|
|
8620
|
+
};
|
|
8621
|
+
case "open": return {
|
|
8622
|
+
deviceId,
|
|
8623
|
+
reading: "open",
|
|
8624
|
+
state: verdict.state,
|
|
8625
|
+
unknownWhy: null,
|
|
8626
|
+
online
|
|
8627
|
+
};
|
|
8628
|
+
case "skip": return opening?.kind === "reading" ? {
|
|
8629
|
+
deviceId,
|
|
8630
|
+
reading: "closed",
|
|
8631
|
+
state: opening.state,
|
|
8632
|
+
unknownWhy: null,
|
|
8633
|
+
online
|
|
8634
|
+
} : {
|
|
8635
|
+
deviceId,
|
|
8636
|
+
reading: "not-opening",
|
|
8637
|
+
state: null,
|
|
8638
|
+
unknownWhy: null,
|
|
8639
|
+
online
|
|
8640
|
+
};
|
|
8641
|
+
}
|
|
8642
|
+
}
|
|
8643
|
+
/** The asked ids, de-duplicated and ascending. */
|
|
8644
|
+
function alarmSensorReadIds(ids) {
|
|
8645
|
+
return [...new Set(ids)].toSorted((a, b) => a - b);
|
|
8646
|
+
}
|
|
8647
|
+
/**
|
|
8648
|
+
* The sensors read's health, logged on CHANGE only (the call is polled every
|
|
8649
|
+
* 5-15 s by every open tab). "Wholesale failure" = ids were asked and not one
|
|
8650
|
+
* was answered (the device manager is unreachable): WARN once when it starts,
|
|
8651
|
+
* ONE INFO when answers return. A partial answer is not a health change — those
|
|
8652
|
+
* ids already leave their own debug line and show as `unknown`.
|
|
8653
|
+
*/
|
|
8654
|
+
var NcAlarmSensorsReadLog = class {
|
|
8655
|
+
failing = false;
|
|
8656
|
+
next(asked, answered) {
|
|
8657
|
+
const wholesale = asked > 0 && answered === 0;
|
|
8658
|
+
if (wholesale === this.failing) return null;
|
|
8659
|
+
this.failing = wholesale;
|
|
8660
|
+
return wholesale ? {
|
|
8661
|
+
level: "warn",
|
|
8662
|
+
message: "alarm sensors read: no asked device answered — every row is unknown",
|
|
8663
|
+
meta: { asked }
|
|
8664
|
+
} : {
|
|
8665
|
+
level: "info",
|
|
8666
|
+
message: "alarm sensors read: devices answer again",
|
|
8667
|
+
meta: {
|
|
8668
|
+
asked,
|
|
8669
|
+
answered
|
|
8670
|
+
}
|
|
8671
|
+
};
|
|
8672
|
+
}
|
|
8673
|
+
};
|
|
8674
|
+
//#endregion
|
|
8348
8675
|
//#region src/notification-center/alarm/alarm-live.ts
|
|
8349
8676
|
/** Every covered id across all modes, ascending, once — what the one read asks for. */
|
|
8350
8677
|
function alarmLiveReadIds(covered) {
|
|
@@ -11329,6 +11656,18 @@ function streamHealthAccepted(category, reason) {
|
|
|
11329
11656
|
function discardedSystemEvent(event, lookup) {
|
|
11330
11657
|
const accessory = discardedAccessoryLiveness(event, lookup);
|
|
11331
11658
|
if (accessory !== null) return accessory;
|
|
11659
|
+
if (event.category === "worker.online" || event.category === "worker.offline") {
|
|
11660
|
+
const workerId = stringField(event.data, "workerId");
|
|
11661
|
+
return {
|
|
11662
|
+
category: event.category,
|
|
11663
|
+
reason: "a runner is not a node",
|
|
11664
|
+
tags: {},
|
|
11665
|
+
meta: {
|
|
11666
|
+
reason: "a runner is not a node",
|
|
11667
|
+
...workerId !== void 0 ? { workerId } : {}
|
|
11668
|
+
}
|
|
11669
|
+
};
|
|
11670
|
+
}
|
|
11332
11671
|
if (event.category !== "stream.online" && event.category !== "stream.offline") return null;
|
|
11333
11672
|
const data = event.data;
|
|
11334
11673
|
const reason = stringField(data, "reason");
|
|
@@ -11655,12 +11994,11 @@ function incomingFromSystemEvent(event, lookup) {
|
|
|
11655
11994
|
deviceId
|
|
11656
11995
|
});
|
|
11657
11996
|
}
|
|
11658
|
-
case "agent.online":
|
|
11659
|
-
case "agent.offline":
|
|
11660
11997
|
case "worker.online":
|
|
11661
|
-
case "worker.offline":
|
|
11662
|
-
|
|
11663
|
-
|
|
11998
|
+
case "worker.offline": return null;
|
|
11999
|
+
case "agent.online":
|
|
12000
|
+
case "agent.offline": {
|
|
12001
|
+
const nodeId = stringField(data, "agentId");
|
|
11664
12002
|
if (nodeId === void 0) return null;
|
|
11665
12003
|
const kind = event.category.endsWith(".online") ? "node-online" : "node-offline";
|
|
11666
12004
|
return systemSubject({
|
|
@@ -11668,7 +12006,7 @@ function incomingFromSystemEvent(event, lookup) {
|
|
|
11668
12006
|
kind,
|
|
11669
12007
|
subject: `node:${nodeId}`,
|
|
11670
12008
|
titleKey: `system.${kind}.title`,
|
|
11671
|
-
bodyKey:
|
|
12009
|
+
bodyKey: `system.${kind}.body.agent`,
|
|
11672
12010
|
textParams: { nodeId },
|
|
11673
12011
|
nodeId
|
|
11674
12012
|
});
|
|
@@ -13285,10 +13623,8 @@ var en_default = {
|
|
|
13285
13623
|
"system.stream-offline.body.profiled": "{{profile}} stream for camera {{deviceName}} is offline",
|
|
13286
13624
|
"system.node-online.title": "Node online",
|
|
13287
13625
|
"system.node-online.body.agent": "Agent {{nodeId}} is online",
|
|
13288
|
-
"system.node-online.body.worker": "Worker {{nodeId}} is online",
|
|
13289
13626
|
"system.node-offline.title": "Node offline",
|
|
13290
13627
|
"system.node-offline.body.agent": "Agent {{nodeId}} is offline",
|
|
13291
|
-
"system.node-offline.body.worker": "Worker {{nodeId}} is offline",
|
|
13292
13628
|
"system.node-inference-unavailable.title": "Node has no usable inference device",
|
|
13293
13629
|
"system.node-inference-unavailable.body": "Node {{nodeId}} can no longer run inference — every enabled device is unavailable ({{devices}}). It will not receive cameras until one returns.",
|
|
13294
13630
|
"system.addon-crash-loop.title": "Addon stopped after repeated crashes",
|
|
@@ -13615,10 +13951,8 @@ var it_default = {
|
|
|
13615
13951
|
"system.stream-offline.body.profiled": "Lo stream {{profile}} della camera {{deviceName}} è offline",
|
|
13616
13952
|
"system.node-online.title": "Nodo online",
|
|
13617
13953
|
"system.node-online.body.agent": "L'agent {{nodeId}} è online",
|
|
13618
|
-
"system.node-online.body.worker": "Il worker {{nodeId}} è online",
|
|
13619
13954
|
"system.node-offline.title": "Nodo offline",
|
|
13620
13955
|
"system.node-offline.body.agent": "L'agent {{nodeId}} è offline",
|
|
13621
|
-
"system.node-offline.body.worker": "Il worker {{nodeId}} è offline",
|
|
13622
13956
|
"system.node-inference-unavailable.title": "Nodo senza dispositivi di inferenza utilizzabili",
|
|
13623
13957
|
"system.node-inference-unavailable.body": "Il nodo {{nodeId}} non può più eseguire inferenza — tutti i dispositivi abilitati non sono disponibili ({{devices}}). Non riceverà camere finché uno non torna disponibile.",
|
|
13624
13958
|
"system.addon-crash-loop.title": "Addon fermato dopo ripetuti crash",
|
|
@@ -17004,7 +17338,8 @@ var ncActions = defineCustomActions({
|
|
|
17004
17338
|
* `getStatus`; this one opens up once it filters to the caller's grants.
|
|
17005
17339
|
* The config pair is the admin's, as `getAlarmConfig` / `setAlarmConfig` are
|
|
17006
17340
|
* on the cap: it carries the delays, the recipients and the non-blocking
|
|
17007
|
-
* lists.
|
|
17341
|
+
* lists. `getAlarmSensors` is the admin's too: it names which of the asked
|
|
17342
|
+
* devices are open.
|
|
17008
17343
|
*/
|
|
17009
17344
|
"nc.getAlarmStatus": customAction(object({}), NcAlarmStatusSchema, {
|
|
17010
17345
|
auth: "admin",
|
|
@@ -17045,6 +17380,10 @@ var ncActions = defineCustomActions({
|
|
|
17045
17380
|
auth: "admin",
|
|
17046
17381
|
caller: "required"
|
|
17047
17382
|
}),
|
|
17383
|
+
"nc.getAlarmSensors": customAction(NcAlarmSensorsInputSchema, NcAlarmSensorsSchema, {
|
|
17384
|
+
auth: "admin",
|
|
17385
|
+
caller: "required"
|
|
17386
|
+
}),
|
|
17048
17387
|
"nc.setAlarmConfig": customAction(object({ patch: NcAlarmSettingsPatchSchema }), NcAlarmConfigSchema, {
|
|
17049
17388
|
kind: "mutation",
|
|
17050
17389
|
auth: "admin",
|
|
@@ -17837,6 +18176,10 @@ function makeNcActionHandlers(deps) {
|
|
|
17837
18176
|
requireAdmin(caller);
|
|
17838
18177
|
return requireAlarm("nc.getAlarmConfig").getConfig();
|
|
17839
18178
|
},
|
|
18179
|
+
"nc.getAlarmSensors": async (input, caller) => {
|
|
18180
|
+
requireAdmin(caller);
|
|
18181
|
+
return requireAlarm("nc.getAlarmSensors").getSensors(input);
|
|
18182
|
+
},
|
|
17840
18183
|
"nc.setAlarmConfig": async (input, caller) => {
|
|
17841
18184
|
requireAdmin(caller);
|
|
17842
18185
|
return requireAlarm("nc.setAlarmConfig").setConfig(input.patch);
|
|
@@ -32671,7 +33014,8 @@ function consumablesSliceOf(event) {
|
|
|
32671
33014
|
var NC_ALARM_SETTINGS_FALLBACK = {
|
|
32672
33015
|
...DEFAULT_DELAYS,
|
|
32673
33016
|
announceTargets: [],
|
|
32674
|
-
nonBlocking: []
|
|
33017
|
+
nonBlocking: [],
|
|
33018
|
+
modeDelays: []
|
|
32675
33019
|
};
|
|
32676
33020
|
/**
|
|
32677
33021
|
* How often the "matched NO rule" report may fire per device. Long enough that
|
|
@@ -33053,6 +33397,7 @@ var NotificationCenter = class NotificationCenter {
|
|
|
33053
33397
|
alarmPanel = null;
|
|
33054
33398
|
/** The live view's read, logged on change only — see `alarm-live-read-log.ts`. */
|
|
33055
33399
|
alarmLiveReadLog = new NcAlarmLiveReadLog();
|
|
33400
|
+
alarmSensorsReadLog = new NcAlarmSensorsReadLog();
|
|
33056
33401
|
/**
|
|
33057
33402
|
* The words the panel answers the `deviceState` gate with — its state, plus
|
|
33058
33403
|
* the armed mode a `pending`/`triggered` belongs to (D630). Refreshed on
|
|
@@ -35371,6 +35716,7 @@ var NotificationCenter = class NotificationCenter {
|
|
|
35371
35716
|
return { success: true };
|
|
35372
35717
|
},
|
|
35373
35718
|
getAlarmConfig: async () => this.alarmConfig(),
|
|
35719
|
+
getAlarmSensors: async (input) => this.alarmSensors(input),
|
|
35374
35720
|
setAlarmConfig: async ({ patch }) => this.setAlarmConfig(patch)
|
|
35375
35721
|
};
|
|
35376
35722
|
}
|
|
@@ -35598,6 +35944,7 @@ var NotificationCenter = class NotificationCenter {
|
|
|
35598
35944
|
});
|
|
35599
35945
|
},
|
|
35600
35946
|
getConfig: () => this.alarmConfig(),
|
|
35947
|
+
getSensors: (input) => this.alarmSensors(input),
|
|
35601
35948
|
setConfig: (patch) => this.setAlarmConfig(patch)
|
|
35602
35949
|
};
|
|
35603
35950
|
}
|
|
@@ -35611,7 +35958,8 @@ var NotificationCenter = class NotificationCenter {
|
|
|
35611
35958
|
exitDelaySec: settings.exitDelaySec,
|
|
35612
35959
|
entryDelaySec: settings.entryDelaySec,
|
|
35613
35960
|
triggeredDurationSec: settings.triggeredDurationSec,
|
|
35614
|
-
announceTargets: settings.announceTargets.length
|
|
35961
|
+
announceTargets: settings.announceTargets.length,
|
|
35962
|
+
modeDelays: settings.modeDelays.length
|
|
35615
35963
|
}
|
|
35616
35964
|
});
|
|
35617
35965
|
return this.alarmConfig();
|
|
@@ -35667,6 +36015,40 @@ var NotificationCenter = class NotificationCenter {
|
|
|
35667
36015
|
name: this.deviceNameFromDirectory()
|
|
35668
36016
|
});
|
|
35669
36017
|
}
|
|
36018
|
+
/**
|
|
36019
|
+
* The opening states of the asked ids, for the alarm editors' sensor table.
|
|
36020
|
+
*
|
|
36021
|
+
* A separate read from `getAlarmConfig` on purpose: that one is polled every
|
|
36022
|
+
* 2–15 s and the household set needs a whole-fleet bindings pass, while the
|
|
36023
|
+
* client already holds the ids. Cost: one `loadRuntimeState` RPC per id, 8 in
|
|
36024
|
+
* flight (`readAlarmOpenings`); the client sends at most `NC_ALARM_SENSORS_MAX`
|
|
36025
|
+
* ids per call and polls every 15 s, every 5 s only while a countdown or the
|
|
36026
|
+
* siren runs. No log line per call (it is polled): one WARN/INFO per change of
|
|
36027
|
+
* wholesale read health (`NcAlarmSensorsReadLog`); a per-id read failure keeps
|
|
36028
|
+
* `readAlarmOpenings`' own debug line, and shows as `unknown` (D49).
|
|
36029
|
+
*
|
|
36030
|
+
* An id with no persisted device (removed) or whose provider never wrote an
|
|
36031
|
+
* opening slice reads `not-opening`, exactly as the arm check sees it — NOT
|
|
36032
|
+
* "verified not an opening". The client shows "Removed" from its fleet read.
|
|
36033
|
+
*/
|
|
36034
|
+
async alarmSensors(input) {
|
|
36035
|
+
const read = this.deps.readDeviceOpenings;
|
|
36036
|
+
if (read === void 0) throw new Error("the opening reader is not wired on this node");
|
|
36037
|
+
const ids = alarmSensorReadIds(input.deviceIds);
|
|
36038
|
+
const openings = await read(ids);
|
|
36039
|
+
const line = this.alarmSensorsReadLog.next(ids.length, openings.size);
|
|
36040
|
+
if (line !== null) {
|
|
36041
|
+
const panelId = this.alarmPanel?.deviceId;
|
|
36042
|
+
this.logger[line.level](line.message, {
|
|
36043
|
+
...panelId === void 0 ? {} : { tags: { deviceId: panelId } },
|
|
36044
|
+
meta: line.meta
|
|
36045
|
+
});
|
|
36046
|
+
}
|
|
36047
|
+
return {
|
|
36048
|
+
sensors: ids.map((id) => alarmSensorStateOf(id, openings.get(id), this.deviceDirectory.get(id)?.online ?? null)),
|
|
36049
|
+
readAt: Date.now()
|
|
36050
|
+
};
|
|
36051
|
+
}
|
|
35670
36052
|
/** Settings + the DERIVED coverage + the live panel. Read together — see the cap doc. */
|
|
35671
36053
|
async alarmConfig() {
|
|
35672
36054
|
const panel = this.alarmPanel;
|
|
@@ -30,7 +30,7 @@ async function d(e) {
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
async function f() {
|
|
33
|
-
return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-
|
|
33
|
+
return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-BocOElW2.mjs")).catch((e) => {
|
|
34
34
|
throw l = void 0, e;
|
|
35
35
|
}), l;
|
|
36
36
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-post-analysis",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.312",
|
|
4
4
|
"description": "Post-Analysis bundle — enrichment, embedding-encoder, pipeline-analytics. Multi-entry npm package shipping addons that consume pipeline output.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|