@camstack/addon-export-ha-mqtt 1.1.25 → 1.1.27
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/export-ha-mqtt.addon.js +511 -2
- package/dist/export-ha-mqtt.addon.mjs +511 -2
- package/package.json +1 -1
|
@@ -7379,6 +7379,62 @@ var RecordingConfigSchema = object({
|
|
|
7379
7379
|
scrubThumbnails: ScrubThumbnailPresetSchema.optional()
|
|
7380
7380
|
});
|
|
7381
7381
|
/**
|
|
7382
|
+
* Ops-log — the durable, append-only operations audit shared by the
|
|
7383
|
+
* recordings and events management surfaces.
|
|
7384
|
+
*
|
|
7385
|
+
* ONE row shape is reused for both domains so a single "Activity" view can
|
|
7386
|
+
* merge the recorder's DurableState ring (recordings ops-log) and the
|
|
7387
|
+
* pipeline-analytics SQLite collection (events ops-log). Each row records a
|
|
7388
|
+
* management operation, WHY it ran (reason), and its measurable effect
|
|
7389
|
+
* (itemsAffected + bytesReclaimed). Writes are best-effort — a failed log must
|
|
7390
|
+
* never fail the operation it records.
|
|
7391
|
+
*/
|
|
7392
|
+
/** Which management domain the operation belongs to. */
|
|
7393
|
+
var OpsLogDomainSchema = _enum(["recording", "events"]);
|
|
7394
|
+
/** The kind of management operation performed. */
|
|
7395
|
+
var OpsLogOpSchema = _enum([
|
|
7396
|
+
"prune",
|
|
7397
|
+
"manual-delete",
|
|
7398
|
+
"rescan",
|
|
7399
|
+
"retention-run"
|
|
7400
|
+
]);
|
|
7401
|
+
/** Why the operation ran. */
|
|
7402
|
+
var OpsLogReasonSchema = _enum([
|
|
7403
|
+
"retention",
|
|
7404
|
+
"quota",
|
|
7405
|
+
"manual",
|
|
7406
|
+
"operator"
|
|
7407
|
+
]);
|
|
7408
|
+
/** One audit row, shared verbatim by both domains. */
|
|
7409
|
+
var OpsLogEntrySchema = object({
|
|
7410
|
+
/** Unique row id. */
|
|
7411
|
+
id: string(),
|
|
7412
|
+
/** Epoch ms the operation completed. */
|
|
7413
|
+
at: number$1(),
|
|
7414
|
+
domain: OpsLogDomainSchema,
|
|
7415
|
+
op: OpsLogOpSchema,
|
|
7416
|
+
reason: OpsLogReasonSchema,
|
|
7417
|
+
/** The camera the op targeted; null for a cluster/global op. */
|
|
7418
|
+
deviceId: number$1().nullable(),
|
|
7419
|
+
/** Node that performed the op (the log carries nodeId — no cross-node aggregation). */
|
|
7420
|
+
nodeId: string(),
|
|
7421
|
+
/** Buckets / rows deleted (op-specific unit). */
|
|
7422
|
+
itemsAffected: number$1(),
|
|
7423
|
+
/** Bytes reclaimed by the op (0 when not measurable). */
|
|
7424
|
+
bytesReclaimed: number$1(),
|
|
7425
|
+
/** Free-text detail (e.g. "floor moved to <ts>"); null when none. */
|
|
7426
|
+
detail: string().nullable(),
|
|
7427
|
+
/** Who/what triggered the op. */
|
|
7428
|
+
actor: string()
|
|
7429
|
+
});
|
|
7430
|
+
/** Shared query input for the per-domain `listOpsLog` cap methods. */
|
|
7431
|
+
var OpsLogQueryInputSchema = object({
|
|
7432
|
+
/** Restrict to a single camera; omit for every row. */
|
|
7433
|
+
deviceId: number$1().optional(),
|
|
7434
|
+
/** Max rows returned, newest-first. */
|
|
7435
|
+
limit: number$1().int().min(1).max(1e3).optional()
|
|
7436
|
+
});
|
|
7437
|
+
/**
|
|
7382
7438
|
* `StorageLocationType` — an addon-declared id that identifies the *kind* of
|
|
7383
7439
|
* storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
|
|
7384
7440
|
* so the persisted record schema and the consumer-facing cap can both consume it
|
|
@@ -7622,6 +7678,160 @@ var EncodeProfileSchema = object({
|
|
|
7622
7678
|
*/
|
|
7623
7679
|
outputArgs: array(string()).optional()
|
|
7624
7680
|
});
|
|
7681
|
+
var COCO_TO_MACRO = {
|
|
7682
|
+
mapping: {
|
|
7683
|
+
person: "person",
|
|
7684
|
+
bicycle: "vehicle",
|
|
7685
|
+
car: "vehicle",
|
|
7686
|
+
motorcycle: "vehicle",
|
|
7687
|
+
airplane: "vehicle",
|
|
7688
|
+
bus: "vehicle",
|
|
7689
|
+
train: "vehicle",
|
|
7690
|
+
truck: "vehicle",
|
|
7691
|
+
boat: "vehicle",
|
|
7692
|
+
bird: "animal",
|
|
7693
|
+
cat: "animal",
|
|
7694
|
+
dog: "animal",
|
|
7695
|
+
horse: "animal",
|
|
7696
|
+
sheep: "animal",
|
|
7697
|
+
cow: "animal",
|
|
7698
|
+
elephant: "animal",
|
|
7699
|
+
bear: "animal",
|
|
7700
|
+
zebra: "animal",
|
|
7701
|
+
giraffe: "animal",
|
|
7702
|
+
suitcase: "package",
|
|
7703
|
+
backpack: "package",
|
|
7704
|
+
handbag: "package"
|
|
7705
|
+
},
|
|
7706
|
+
preserveOriginal: false
|
|
7707
|
+
};
|
|
7708
|
+
var AUDIO_MACRO_LABELS = [
|
|
7709
|
+
{
|
|
7710
|
+
id: "speech",
|
|
7711
|
+
name: "Speech",
|
|
7712
|
+
icon: "🗣️"
|
|
7713
|
+
},
|
|
7714
|
+
{
|
|
7715
|
+
id: "scream",
|
|
7716
|
+
name: "Scream / Shout",
|
|
7717
|
+
icon: "😱"
|
|
7718
|
+
},
|
|
7719
|
+
{
|
|
7720
|
+
id: "crying",
|
|
7721
|
+
name: "Crying / Baby",
|
|
7722
|
+
icon: "😢"
|
|
7723
|
+
},
|
|
7724
|
+
{
|
|
7725
|
+
id: "laughter",
|
|
7726
|
+
name: "Laughter",
|
|
7727
|
+
icon: "😂"
|
|
7728
|
+
},
|
|
7729
|
+
{
|
|
7730
|
+
id: "music",
|
|
7731
|
+
name: "Music",
|
|
7732
|
+
icon: "🎵"
|
|
7733
|
+
},
|
|
7734
|
+
{
|
|
7735
|
+
id: "dog",
|
|
7736
|
+
name: "Dog",
|
|
7737
|
+
icon: "🐕"
|
|
7738
|
+
},
|
|
7739
|
+
{
|
|
7740
|
+
id: "cat",
|
|
7741
|
+
name: "Cat",
|
|
7742
|
+
icon: "🐈"
|
|
7743
|
+
},
|
|
7744
|
+
{
|
|
7745
|
+
id: "bird",
|
|
7746
|
+
name: "Bird",
|
|
7747
|
+
icon: "🐦"
|
|
7748
|
+
},
|
|
7749
|
+
{
|
|
7750
|
+
id: "animal",
|
|
7751
|
+
name: "Animal (other)",
|
|
7752
|
+
icon: "🐾"
|
|
7753
|
+
},
|
|
7754
|
+
{
|
|
7755
|
+
id: "alarm",
|
|
7756
|
+
name: "Alarm / Siren",
|
|
7757
|
+
icon: "🚨"
|
|
7758
|
+
},
|
|
7759
|
+
{
|
|
7760
|
+
id: "doorbell",
|
|
7761
|
+
name: "Doorbell / Knock",
|
|
7762
|
+
icon: "🔔"
|
|
7763
|
+
},
|
|
7764
|
+
{
|
|
7765
|
+
id: "glass_breaking",
|
|
7766
|
+
name: "Glass Breaking",
|
|
7767
|
+
icon: "💥"
|
|
7768
|
+
},
|
|
7769
|
+
{
|
|
7770
|
+
id: "gunshot",
|
|
7771
|
+
name: "Gunshot / Explosion",
|
|
7772
|
+
icon: "💣"
|
|
7773
|
+
},
|
|
7774
|
+
{
|
|
7775
|
+
id: "vehicle",
|
|
7776
|
+
name: "Vehicle",
|
|
7777
|
+
icon: "🚗"
|
|
7778
|
+
},
|
|
7779
|
+
{
|
|
7780
|
+
id: "siren",
|
|
7781
|
+
name: "Emergency Siren",
|
|
7782
|
+
icon: "🚑"
|
|
7783
|
+
},
|
|
7784
|
+
{
|
|
7785
|
+
id: "fire",
|
|
7786
|
+
name: "Fire / Smoke",
|
|
7787
|
+
icon: "🔥"
|
|
7788
|
+
},
|
|
7789
|
+
{
|
|
7790
|
+
id: "water",
|
|
7791
|
+
name: "Water",
|
|
7792
|
+
icon: "💧"
|
|
7793
|
+
},
|
|
7794
|
+
{
|
|
7795
|
+
id: "wind",
|
|
7796
|
+
name: "Wind / Weather",
|
|
7797
|
+
icon: "🌬️"
|
|
7798
|
+
},
|
|
7799
|
+
{
|
|
7800
|
+
id: "door",
|
|
7801
|
+
name: "Door",
|
|
7802
|
+
icon: "🚪"
|
|
7803
|
+
},
|
|
7804
|
+
{
|
|
7805
|
+
id: "footsteps",
|
|
7806
|
+
name: "Footsteps",
|
|
7807
|
+
icon: "👣"
|
|
7808
|
+
},
|
|
7809
|
+
{
|
|
7810
|
+
id: "crowd",
|
|
7811
|
+
name: "Crowd / Chatter",
|
|
7812
|
+
icon: "👥"
|
|
7813
|
+
},
|
|
7814
|
+
{
|
|
7815
|
+
id: "telephone",
|
|
7816
|
+
name: "Telephone",
|
|
7817
|
+
icon: "📞"
|
|
7818
|
+
},
|
|
7819
|
+
{
|
|
7820
|
+
id: "engine",
|
|
7821
|
+
name: "Engine / Motor",
|
|
7822
|
+
icon: "⚙️"
|
|
7823
|
+
},
|
|
7824
|
+
{
|
|
7825
|
+
id: "tools",
|
|
7826
|
+
name: "Tools / Construction",
|
|
7827
|
+
icon: "🔨"
|
|
7828
|
+
},
|
|
7829
|
+
{
|
|
7830
|
+
id: "silence",
|
|
7831
|
+
name: "Silence",
|
|
7832
|
+
icon: "🤫"
|
|
7833
|
+
}
|
|
7834
|
+
];
|
|
7625
7835
|
var YAMNET_TO_MACRO = {
|
|
7626
7836
|
mapping: {
|
|
7627
7837
|
Speech: "speech",
|
|
@@ -7888,6 +8098,125 @@ var _macroLookup = /* @__PURE__ */ new Map();
|
|
|
7888
8098
|
for (const [k, v] of Object.entries(YAMNET_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
|
|
7889
8099
|
for (const [k, v] of Object.entries(APPLE_SA_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
|
|
7890
8100
|
/**
|
|
8101
|
+
* Unified event-kind taxonomy — THE single source of truth for
|
|
8102
|
+
* `kind → { parentKind, category, level, color, iconId, labelKey, label,
|
|
8103
|
+
* icon }`.
|
|
8104
|
+
*
|
|
8105
|
+
* This dictionary folds together what used to be scattered across four
|
|
8106
|
+
* copies:
|
|
8107
|
+
* - `capabilities/sensor-event-kinds.ts` (sensor cap colors)
|
|
8108
|
+
* - `addon-post-analysis/.../services/event-kinds.ts`
|
|
8109
|
+
* (MOTION/PERSON/VEHICLE… _COLOR constants)
|
|
8110
|
+
* - `ui-library/composites/detection-colors.ts` (CLASS_COLORS)
|
|
8111
|
+
* - `addon-post-analysis/shared/frame/box-drawer.ts` (DEFAULT_COLOR)
|
|
8112
|
+
* - the COCO / audio class maps (macro ↔ sub relationships)
|
|
8113
|
+
*
|
|
8114
|
+
* The DATA (serializable — color/iconId/labelKey/parentKind) lives here in
|
|
8115
|
+
* `@camstack/types`. The UI-side mapping `iconId → lucide component` and
|
|
8116
|
+
* `labelKey → t()` lives in `@camstack/ui-library`. UIs never hardcode a
|
|
8117
|
+
* color or an icon: they read this dictionary (server descriptors carry the
|
|
8118
|
+
* fields inline; the client resolves color/icon/label from `iconId`/`kind`).
|
|
8119
|
+
*
|
|
8120
|
+
* Two levels only (v1 YAGNI): macro → sub. `person` is a leaf macro.
|
|
8121
|
+
*/
|
|
8122
|
+
var TAXONOMY_COLORS = {
|
|
8123
|
+
motion: "#f59e0b",
|
|
8124
|
+
audio: "#06b6d4",
|
|
8125
|
+
person: "#22c55e",
|
|
8126
|
+
vehicle: "#3b82f6",
|
|
8127
|
+
animal: "#f97316",
|
|
8128
|
+
package: "#a855f7",
|
|
8129
|
+
sensor: "#8b5cf6",
|
|
8130
|
+
control: "#10b981",
|
|
8131
|
+
genericDetection: "#64748b"
|
|
8132
|
+
};
|
|
8133
|
+
var DETECTION_SUB_COLORS = {
|
|
8134
|
+
car: "#f59e0b",
|
|
8135
|
+
truck: "#d97706",
|
|
8136
|
+
bus: "#b45309",
|
|
8137
|
+
motorcycle: "#eab308",
|
|
8138
|
+
bicycle: "#ca8a04",
|
|
8139
|
+
airplane: "#60a5fa",
|
|
8140
|
+
boat: "#2563eb",
|
|
8141
|
+
train: "#1d4ed8",
|
|
8142
|
+
bird: "#14b8a6",
|
|
8143
|
+
dog: "#84cc16",
|
|
8144
|
+
cat: "#f97316",
|
|
8145
|
+
horse: "#a16207",
|
|
8146
|
+
sheep: "#a3a3a3",
|
|
8147
|
+
cow: "#78716c",
|
|
8148
|
+
elephant: "#6b7280",
|
|
8149
|
+
bear: "#7c2d12",
|
|
8150
|
+
zebra: "#404040",
|
|
8151
|
+
giraffe: "#d4a373"
|
|
8152
|
+
};
|
|
8153
|
+
function titleCase(id) {
|
|
8154
|
+
return id.split(/[-_ ]/).filter((p) => p.length > 0).map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join(" ");
|
|
8155
|
+
}
|
|
8156
|
+
var entries = /* @__PURE__ */ new Map();
|
|
8157
|
+
function macro(kind, category, color, iconId, label) {
|
|
8158
|
+
entries.set(kind, {
|
|
8159
|
+
kind,
|
|
8160
|
+
parentKind: null,
|
|
8161
|
+
level: "macro",
|
|
8162
|
+
category,
|
|
8163
|
+
color,
|
|
8164
|
+
iconId,
|
|
8165
|
+
labelKey: `eventKind.${kind}`,
|
|
8166
|
+
label
|
|
8167
|
+
});
|
|
8168
|
+
}
|
|
8169
|
+
function sub(kind, parentKind, category, color, iconId, label) {
|
|
8170
|
+
entries.set(kind, {
|
|
8171
|
+
kind,
|
|
8172
|
+
parentKind,
|
|
8173
|
+
level: "sub",
|
|
8174
|
+
category,
|
|
8175
|
+
color,
|
|
8176
|
+
iconId,
|
|
8177
|
+
labelKey: `eventKind.${kind}`,
|
|
8178
|
+
label
|
|
8179
|
+
});
|
|
8180
|
+
}
|
|
8181
|
+
macro("motion", "motion", TAXONOMY_COLORS.motion, "motion", "Motion");
|
|
8182
|
+
macro("audio", "audio", TAXONOMY_COLORS.audio, "audio", "Audio");
|
|
8183
|
+
macro("person", "detection", TAXONOMY_COLORS.person, "person", "Person");
|
|
8184
|
+
macro("vehicle", "detection", TAXONOMY_COLORS.vehicle, "vehicle", "Vehicle");
|
|
8185
|
+
macro("animal", "detection", TAXONOMY_COLORS.animal, "animal", "Animal");
|
|
8186
|
+
macro("package", "package", TAXONOMY_COLORS.package, "package", "Package");
|
|
8187
|
+
macro("sensor", "sensor", TAXONOMY_COLORS.sensor, "sensor", "Sensor");
|
|
8188
|
+
macro("control", "control", TAXONOMY_COLORS.control, "control", "Control");
|
|
8189
|
+
for (const [cocoClass, macroClass] of Object.entries(COCO_TO_MACRO.mapping)) {
|
|
8190
|
+
if (macroClass !== "vehicle" && macroClass !== "animal") continue;
|
|
8191
|
+
if (entries.has(cocoClass)) continue;
|
|
8192
|
+
sub(cocoClass, macroClass, "detection", DETECTION_SUB_COLORS[cocoClass] ?? TAXONOMY_COLORS.genericDetection, cocoClass, titleCase(cocoClass));
|
|
8193
|
+
}
|
|
8194
|
+
sub("package-delivered", "package", "package", TAXONOMY_COLORS.package, "package", "Package delivered");
|
|
8195
|
+
sub("package-picked-up", "package", "package", TAXONOMY_COLORS.package, "package", "Package picked up");
|
|
8196
|
+
sub("contact", "sensor", "sensor", "#f59e0b", "door", "Contact");
|
|
8197
|
+
sub("motion-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "pir", "Motion sensor");
|
|
8198
|
+
sub("smoke", "sensor", "sensor", "#ef4444", "smoke", "Smoke");
|
|
8199
|
+
sub("flood", "sensor", "sensor", "#3b82f6", "water", "Water leak");
|
|
8200
|
+
sub("gas", "sensor", "sensor", "#ef4444", "gas", "Gas");
|
|
8201
|
+
sub("carbon-monoxide", "sensor", "sensor", "#dc2626", "smoke", "Carbon monoxide");
|
|
8202
|
+
sub("vibration", "sensor", "sensor", "#eab308", "vibration", "Vibration");
|
|
8203
|
+
sub("tamper", "sensor", "sensor", "#f97316", "tamper", "Tamper");
|
|
8204
|
+
sub("presence", "sensor", "sensor", "#22c55e", "presence", "Presence");
|
|
8205
|
+
sub("enum-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "generic", "Sensor state");
|
|
8206
|
+
sub("device-event", "sensor", "sensor", "#10b981", "button", "Device event");
|
|
8207
|
+
sub("lock", "control", "control", "#0ea5e9", "lock", "Lock");
|
|
8208
|
+
sub("switch", "control", "control", TAXONOMY_COLORS.control, "switch", "Switch");
|
|
8209
|
+
sub("siren", "control", "control", "#dc2626", "siren", "Siren");
|
|
8210
|
+
sub("button", "control", "control", "#10b981", "button", "Button");
|
|
8211
|
+
sub("doorbell", "control", "control", "#a855f7", "doorbell", "Doorbell");
|
|
8212
|
+
for (const l of AUDIO_MACRO_LABELS) {
|
|
8213
|
+
const kind = `audio-${l.id}`;
|
|
8214
|
+
if (entries.has(kind)) continue;
|
|
8215
|
+
sub(kind, "audio", "audio", TAXONOMY_COLORS.audio, kind, l.name);
|
|
8216
|
+
}
|
|
8217
|
+
/** The complete taxonomy dictionary, keyed by kind. */
|
|
8218
|
+
var EVENT_TAXONOMY = Object.freeze(Object.fromEntries(entries));
|
|
8219
|
+
/**
|
|
7891
8220
|
* Error types for the safe expression engine. Two distinct classes so callers
|
|
7892
8221
|
* can tell a compile-time (grammar) failure from a runtime (evaluation)
|
|
7893
8222
|
* failure — both are non-fatal to the host: read paths degrade to "skip link".
|
|
@@ -15862,17 +16191,30 @@ var EventKindCategorySchema = _enum([
|
|
|
15862
16191
|
"audio",
|
|
15863
16192
|
"detection",
|
|
15864
16193
|
"sensor",
|
|
16194
|
+
"control",
|
|
15865
16195
|
"custom",
|
|
15866
16196
|
"package"
|
|
15867
16197
|
]);
|
|
16198
|
+
/** Taxonomy level — macro (timeline lane) vs sub (events-page leaf). */
|
|
16199
|
+
var EventKindLevelSchema = _enum(["macro", "sub"]);
|
|
15868
16200
|
var EventKindDescriptorSchema = object({
|
|
15869
|
-
/** Stable kind id (e.g. 'motion', '
|
|
16201
|
+
/** Stable kind id (e.g. 'motion', 'vehicle', 'car', 'lock'). */
|
|
15870
16202
|
kind: string(),
|
|
16203
|
+
/** i18n key resolved on the UI side; `label` is the English fallback. */
|
|
16204
|
+
labelKey: string(),
|
|
16205
|
+
/** English fallback label (kept for clients that don't translate). */
|
|
15871
16206
|
label: string(),
|
|
15872
16207
|
/** Hex color for timeline/legend rendering. */
|
|
15873
16208
|
color: string(),
|
|
16209
|
+
/** Dictionary id → lucide component on the UI side. */
|
|
16210
|
+
iconId: string(),
|
|
16211
|
+
/** Legacy closed-vocab glyph — fallback for `iconId`. */
|
|
15874
16212
|
icon: EventKindIconSchema,
|
|
15875
16213
|
category: EventKindCategorySchema,
|
|
16214
|
+
/** Macro parent for this kind ('car' → 'vehicle'); null for a macro. */
|
|
16215
|
+
parentKind: string().nullable(),
|
|
16216
|
+
/** Derived from `parentKind`, explicit for the client tree. */
|
|
16217
|
+
level: EventKindLevelSchema,
|
|
15876
16218
|
/** Which cap + device contributes this kind. For built-ins the camera
|
|
15877
16219
|
* itself; for sensor kinds the LINKED source device. */
|
|
15878
16220
|
source: object({
|
|
@@ -15945,11 +16287,21 @@ var TrackAudioLabelSchema = object({
|
|
|
15945
16287
|
firstAt: number$1(),
|
|
15946
16288
|
lastAt: number$1()
|
|
15947
16289
|
});
|
|
16290
|
+
/**
|
|
16291
|
+
* How a track was produced. `pipeline` (default / absent) = the spatial
|
|
16292
|
+
* detection+tracking pipeline. `sensor` = a SYNTHETIC track projected from a
|
|
16293
|
+
* linked sensor/control state change (no positions; carries a snapshot). The
|
|
16294
|
+
* spatial subsystems (tracker association, occupancy count, re-id/embedding,
|
|
16295
|
+
* resurrection) MUST skip `sensor` tracks — they have no bbox trajectory.
|
|
16296
|
+
*/
|
|
16297
|
+
var TrackSourceSchema = _enum(["pipeline", "sensor"]);
|
|
15948
16298
|
var TrackSchema = object({
|
|
15949
16299
|
trackId: string(),
|
|
15950
16300
|
deviceId: number$1(),
|
|
15951
16301
|
className: string(),
|
|
15952
16302
|
label: string().optional(),
|
|
16303
|
+
/** Track provenance. Absent ⇒ `pipeline` (legacy rows). */
|
|
16304
|
+
source: TrackSourceSchema.optional(),
|
|
15953
16305
|
firstSeen: number$1(),
|
|
15954
16306
|
lastSeen: number$1(),
|
|
15955
16307
|
/** Frame-rate position history (subject to maxPositionHistory cap). */
|
|
@@ -16204,6 +16556,26 @@ var TrackCascadeCountsSchema = object({
|
|
|
16204
16556
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
16205
16557
|
embeddings: number$1().int()
|
|
16206
16558
|
});
|
|
16559
|
+
/** Event-store footprint for one camera. */
|
|
16560
|
+
var EventStoreDeviceFootprintSchema = object({
|
|
16561
|
+
deviceId: number$1(),
|
|
16562
|
+
/** Persisted event rows (motion + object + audio) for the camera. */
|
|
16563
|
+
rows: number$1().int(),
|
|
16564
|
+
/** Event-owned media bytes on disk for the camera. */
|
|
16565
|
+
bytes: number$1().int()
|
|
16566
|
+
});
|
|
16567
|
+
/** Aggregate event-store footprint: global totals + per-camera breakdown. */
|
|
16568
|
+
var EventStoreFootprintSchema = object({
|
|
16569
|
+
totalRows: number$1().int(),
|
|
16570
|
+
totalBytes: number$1().int(),
|
|
16571
|
+
devices: array(EventStoreDeviceFootprintSchema).readonly()
|
|
16572
|
+
});
|
|
16573
|
+
/** Per-kind counts returned by the event-prune / device-delete mutations. */
|
|
16574
|
+
var EventPruneCountsSchema = object({
|
|
16575
|
+
motion: number$1().int(),
|
|
16576
|
+
object: number$1().int(),
|
|
16577
|
+
audio: number$1().int()
|
|
16578
|
+
});
|
|
16207
16579
|
DeviceType.Camera, method(object({ deviceId: number$1() }), array(TrackSchema).readonly()), method(object({
|
|
16208
16580
|
deviceId: number$1(),
|
|
16209
16581
|
trackId: string()
|
|
@@ -16267,6 +16639,21 @@ DeviceType.Camera, method(object({ deviceId: number$1() }), array(TrackSchema).r
|
|
|
16267
16639
|
}), {
|
|
16268
16640
|
kind: "mutation",
|
|
16269
16641
|
auth: "admin"
|
|
16642
|
+
}), method(object({}), EventStoreFootprintSchema, {
|
|
16643
|
+
kind: "query",
|
|
16644
|
+
auth: "admin"
|
|
16645
|
+
}), method(object({
|
|
16646
|
+
olderThanMs: number$1(),
|
|
16647
|
+
reason: OpsLogReasonSchema.optional()
|
|
16648
|
+
}), EventPruneCountsSchema, {
|
|
16649
|
+
kind: "mutation",
|
|
16650
|
+
auth: "admin"
|
|
16651
|
+
}), method(object({ deviceId: number$1() }), EventPruneCountsSchema, {
|
|
16652
|
+
kind: "mutation",
|
|
16653
|
+
auth: "admin"
|
|
16654
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
16655
|
+
kind: "query",
|
|
16656
|
+
auth: "admin"
|
|
16270
16657
|
}), method(object({
|
|
16271
16658
|
eventId: string(),
|
|
16272
16659
|
kind: MediaFileKindEnum.optional()
|
|
@@ -16291,6 +16678,76 @@ DeviceType.Camera, method(object({ deviceId: number$1() }), array(TrackSchema).r
|
|
|
16291
16678
|
eventId: string(),
|
|
16292
16679
|
timestamp: number$1()
|
|
16293
16680
|
});
|
|
16681
|
+
/**
|
|
16682
|
+
* Cap → event-kind mapping for the SENSOR / CONTROL cap families — the table
|
|
16683
|
+
* `pipeline-analytics.listEventKinds` uses to turn a linked device's bound
|
|
16684
|
+
* caps into per-camera event-kind descriptors.
|
|
16685
|
+
*
|
|
16686
|
+
* The descriptor DATA (color / iconId / labelKey / parentKind / category)
|
|
16687
|
+
* is NOT duplicated here — every entry is derived from the single
|
|
16688
|
+
* `EVENT_TAXONOMY` dictionary (`catalogs/event-taxonomy.ts`). This file owns
|
|
16689
|
+
* ONLY the cap-name → taxonomy-kind mapping. Adding a new eventful sensor /
|
|
16690
|
+
* control cap means adding one line here (and a taxonomy entry); the anti-
|
|
16691
|
+
* drift guard `scripts/check-event-kind-coverage.ts` fails the build if an
|
|
16692
|
+
* eventful cap is missing.
|
|
16693
|
+
*/
|
|
16694
|
+
/** Map a taxonomy `iconId` onto the legacy closed `EventKindIcon` enum. */
|
|
16695
|
+
var LEGACY_ICON = {
|
|
16696
|
+
motion: "motion",
|
|
16697
|
+
audio: "audio",
|
|
16698
|
+
person: "person",
|
|
16699
|
+
vehicle: "vehicle",
|
|
16700
|
+
animal: "animal",
|
|
16701
|
+
package: "package",
|
|
16702
|
+
door: "door",
|
|
16703
|
+
pir: "pir",
|
|
16704
|
+
smoke: "smoke",
|
|
16705
|
+
water: "water",
|
|
16706
|
+
button: "button",
|
|
16707
|
+
generic: "generic",
|
|
16708
|
+
gas: "smoke",
|
|
16709
|
+
vibration: "generic",
|
|
16710
|
+
tamper: "generic",
|
|
16711
|
+
presence: "person",
|
|
16712
|
+
lock: "generic",
|
|
16713
|
+
siren: "generic",
|
|
16714
|
+
switch: "generic",
|
|
16715
|
+
doorbell: "button"
|
|
16716
|
+
};
|
|
16717
|
+
function legacyIcon(iconId) {
|
|
16718
|
+
return LEGACY_ICON[iconId] ?? "generic";
|
|
16719
|
+
}
|
|
16720
|
+
/**
|
|
16721
|
+
* Cap name → taxonomy kind id. Covers EVERY eventful sensor / control cap.
|
|
16722
|
+
* The anti-drift guard cross-checks this against the eventful caps declared
|
|
16723
|
+
* in `packages/types/src/capabilities/*.cap.ts`.
|
|
16724
|
+
*/
|
|
16725
|
+
var CAP_TO_KIND = {
|
|
16726
|
+
contact: "contact",
|
|
16727
|
+
motion: "motion-sensor",
|
|
16728
|
+
smoke: "smoke",
|
|
16729
|
+
flood: "flood",
|
|
16730
|
+
gas: "gas",
|
|
16731
|
+
"carbon-monoxide": "carbon-monoxide",
|
|
16732
|
+
vibration: "vibration",
|
|
16733
|
+
tamper: "tamper",
|
|
16734
|
+
presence: "presence",
|
|
16735
|
+
"enum-sensor": "enum-sensor",
|
|
16736
|
+
"event-emitter": "device-event",
|
|
16737
|
+
"lock-control": "lock",
|
|
16738
|
+
switch: "switch",
|
|
16739
|
+
button: "button",
|
|
16740
|
+
doorbell: "doorbell"
|
|
16741
|
+
};
|
|
16742
|
+
function buildDescriptor(capName, kind) {
|
|
16743
|
+
const t = EVENT_TAXONOMY[kind];
|
|
16744
|
+
if (t === void 0) throw new Error(`EVENT_KIND_BY_CAP: cap '${capName}' maps to unknown taxonomy kind '${kind}'`);
|
|
16745
|
+
return {
|
|
16746
|
+
...t,
|
|
16747
|
+
icon: legacyIcon(t.iconId)
|
|
16748
|
+
};
|
|
16749
|
+
}
|
|
16750
|
+
Object.freeze(Object.fromEntries(Object.entries(CAP_TO_KIND).map(([capName, kind]) => [capName, buildDescriptor(capName, kind)])));
|
|
16294
16751
|
var CameraPipelineConfigSchema = object({
|
|
16295
16752
|
engine: PipelineEngineChoiceSchema.optional(),
|
|
16296
16753
|
steps: array(PipelineStepInputSchema).readonly(),
|
|
@@ -19500,13 +19957,29 @@ method(object({
|
|
|
19500
19957
|
}), method(object({ deviceId: number$1() }), RecordingStatusSchema, {
|
|
19501
19958
|
kind: "mutation",
|
|
19502
19959
|
auth: "admin"
|
|
19503
|
-
}), method(object({
|
|
19960
|
+
}), method(object({
|
|
19961
|
+
deviceId: number$1(),
|
|
19962
|
+
reason: OpsLogReasonSchema.optional()
|
|
19963
|
+
}), object({
|
|
19504
19964
|
floorMs: number$1().nullable(),
|
|
19505
19965
|
deletedBuckets: number$1().int(),
|
|
19506
19966
|
reclaimedBytes: number$1().int()
|
|
19507
19967
|
}), {
|
|
19508
19968
|
kind: "mutation",
|
|
19509
19969
|
auth: "admin"
|
|
19970
|
+
}), method(object({
|
|
19971
|
+
deviceId: number$1(),
|
|
19972
|
+
fromMs: number$1().optional(),
|
|
19973
|
+
toMs: number$1().optional()
|
|
19974
|
+
}), object({
|
|
19975
|
+
deletedBuckets: number$1().int(),
|
|
19976
|
+
reclaimedBytes: number$1().int()
|
|
19977
|
+
}), {
|
|
19978
|
+
kind: "mutation",
|
|
19979
|
+
auth: "admin"
|
|
19980
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
19981
|
+
kind: "query",
|
|
19982
|
+
auth: "admin"
|
|
19510
19983
|
});
|
|
19511
19984
|
/**
|
|
19512
19985
|
* `recordingExport` cap — render a footage time range into a single downloadable
|
|
@@ -22628,6 +23101,12 @@ Object.freeze({
|
|
|
22628
23101
|
addonId: null,
|
|
22629
23102
|
access: "delete"
|
|
22630
23103
|
},
|
|
23104
|
+
"pipelineAnalytics.deleteDeviceEvents": {
|
|
23105
|
+
capName: "pipeline-analytics",
|
|
23106
|
+
capScope: "device",
|
|
23107
|
+
addonId: null,
|
|
23108
|
+
access: "delete"
|
|
23109
|
+
},
|
|
22631
23110
|
"pipelineAnalytics.deleteTracks": {
|
|
22632
23111
|
capName: "pipeline-analytics",
|
|
22633
23112
|
capScope: "device",
|
|
@@ -22658,6 +23137,12 @@ Object.freeze({
|
|
|
22658
23137
|
addonId: null,
|
|
22659
23138
|
access: "view"
|
|
22660
23139
|
},
|
|
23140
|
+
"pipelineAnalytics.getEventStoreFootprint": {
|
|
23141
|
+
capName: "pipeline-analytics",
|
|
23142
|
+
capScope: "device",
|
|
23143
|
+
addonId: null,
|
|
23144
|
+
access: "view"
|
|
23145
|
+
},
|
|
22661
23146
|
"pipelineAnalytics.getKeyEvents": {
|
|
22662
23147
|
capName: "pipeline-analytics",
|
|
22663
23148
|
capScope: "device",
|
|
@@ -22700,6 +23185,12 @@ Object.freeze({
|
|
|
22700
23185
|
addonId: null,
|
|
22701
23186
|
access: "view"
|
|
22702
23187
|
},
|
|
23188
|
+
"pipelineAnalytics.listOpsLog": {
|
|
23189
|
+
capName: "pipeline-analytics",
|
|
23190
|
+
capScope: "device",
|
|
23191
|
+
addonId: null,
|
|
23192
|
+
access: "view"
|
|
23193
|
+
},
|
|
22703
23194
|
"pipelineAnalytics.listRecentTracks": {
|
|
22704
23195
|
capName: "pipeline-analytics",
|
|
22705
23196
|
capScope: "device",
|
|
@@ -22712,6 +23203,12 @@ Object.freeze({
|
|
|
22712
23203
|
addonId: null,
|
|
22713
23204
|
access: "view"
|
|
22714
23205
|
},
|
|
23206
|
+
"pipelineAnalytics.pruneEvents": {
|
|
23207
|
+
capName: "pipeline-analytics",
|
|
23208
|
+
capScope: "device",
|
|
23209
|
+
addonId: null,
|
|
23210
|
+
access: "create"
|
|
23211
|
+
},
|
|
22715
23212
|
"pipelineAnalytics.pruneEventsBefore": {
|
|
22716
23213
|
capName: "pipeline-analytics",
|
|
22717
23214
|
capScope: "device",
|
|
@@ -23474,6 +23971,12 @@ Object.freeze({
|
|
|
23474
23971
|
addonId: null,
|
|
23475
23972
|
access: "create"
|
|
23476
23973
|
},
|
|
23974
|
+
"recording.deleteFootprint": {
|
|
23975
|
+
capName: "recording",
|
|
23976
|
+
capScope: "system",
|
|
23977
|
+
addonId: null,
|
|
23978
|
+
access: "delete"
|
|
23979
|
+
},
|
|
23477
23980
|
"recording.getAvailability": {
|
|
23478
23981
|
capName: "recording",
|
|
23479
23982
|
capScope: "system",
|
|
@@ -23504,6 +24007,12 @@ Object.freeze({
|
|
|
23504
24007
|
addonId: null,
|
|
23505
24008
|
access: "view"
|
|
23506
24009
|
},
|
|
24010
|
+
"recording.listOpsLog": {
|
|
24011
|
+
capName: "recording",
|
|
24012
|
+
capScope: "system",
|
|
24013
|
+
addonId: null,
|
|
24014
|
+
access: "view"
|
|
24015
|
+
},
|
|
23507
24016
|
"recording.locateSegment": {
|
|
23508
24017
|
capName: "recording",
|
|
23509
24018
|
capScope: "system",
|
|
@@ -7377,6 +7377,62 @@ var RecordingConfigSchema = object({
|
|
|
7377
7377
|
scrubThumbnails: ScrubThumbnailPresetSchema.optional()
|
|
7378
7378
|
});
|
|
7379
7379
|
/**
|
|
7380
|
+
* Ops-log — the durable, append-only operations audit shared by the
|
|
7381
|
+
* recordings and events management surfaces.
|
|
7382
|
+
*
|
|
7383
|
+
* ONE row shape is reused for both domains so a single "Activity" view can
|
|
7384
|
+
* merge the recorder's DurableState ring (recordings ops-log) and the
|
|
7385
|
+
* pipeline-analytics SQLite collection (events ops-log). Each row records a
|
|
7386
|
+
* management operation, WHY it ran (reason), and its measurable effect
|
|
7387
|
+
* (itemsAffected + bytesReclaimed). Writes are best-effort — a failed log must
|
|
7388
|
+
* never fail the operation it records.
|
|
7389
|
+
*/
|
|
7390
|
+
/** Which management domain the operation belongs to. */
|
|
7391
|
+
var OpsLogDomainSchema = _enum(["recording", "events"]);
|
|
7392
|
+
/** The kind of management operation performed. */
|
|
7393
|
+
var OpsLogOpSchema = _enum([
|
|
7394
|
+
"prune",
|
|
7395
|
+
"manual-delete",
|
|
7396
|
+
"rescan",
|
|
7397
|
+
"retention-run"
|
|
7398
|
+
]);
|
|
7399
|
+
/** Why the operation ran. */
|
|
7400
|
+
var OpsLogReasonSchema = _enum([
|
|
7401
|
+
"retention",
|
|
7402
|
+
"quota",
|
|
7403
|
+
"manual",
|
|
7404
|
+
"operator"
|
|
7405
|
+
]);
|
|
7406
|
+
/** One audit row, shared verbatim by both domains. */
|
|
7407
|
+
var OpsLogEntrySchema = object({
|
|
7408
|
+
/** Unique row id. */
|
|
7409
|
+
id: string(),
|
|
7410
|
+
/** Epoch ms the operation completed. */
|
|
7411
|
+
at: number$1(),
|
|
7412
|
+
domain: OpsLogDomainSchema,
|
|
7413
|
+
op: OpsLogOpSchema,
|
|
7414
|
+
reason: OpsLogReasonSchema,
|
|
7415
|
+
/** The camera the op targeted; null for a cluster/global op. */
|
|
7416
|
+
deviceId: number$1().nullable(),
|
|
7417
|
+
/** Node that performed the op (the log carries nodeId — no cross-node aggregation). */
|
|
7418
|
+
nodeId: string(),
|
|
7419
|
+
/** Buckets / rows deleted (op-specific unit). */
|
|
7420
|
+
itemsAffected: number$1(),
|
|
7421
|
+
/** Bytes reclaimed by the op (0 when not measurable). */
|
|
7422
|
+
bytesReclaimed: number$1(),
|
|
7423
|
+
/** Free-text detail (e.g. "floor moved to <ts>"); null when none. */
|
|
7424
|
+
detail: string().nullable(),
|
|
7425
|
+
/** Who/what triggered the op. */
|
|
7426
|
+
actor: string()
|
|
7427
|
+
});
|
|
7428
|
+
/** Shared query input for the per-domain `listOpsLog` cap methods. */
|
|
7429
|
+
var OpsLogQueryInputSchema = object({
|
|
7430
|
+
/** Restrict to a single camera; omit for every row. */
|
|
7431
|
+
deviceId: number$1().optional(),
|
|
7432
|
+
/** Max rows returned, newest-first. */
|
|
7433
|
+
limit: number$1().int().min(1).max(1e3).optional()
|
|
7434
|
+
});
|
|
7435
|
+
/**
|
|
7380
7436
|
* `StorageLocationType` — an addon-declared id that identifies the *kind* of
|
|
7381
7437
|
* storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
|
|
7382
7438
|
* so the persisted record schema and the consumer-facing cap can both consume it
|
|
@@ -7620,6 +7676,160 @@ var EncodeProfileSchema = object({
|
|
|
7620
7676
|
*/
|
|
7621
7677
|
outputArgs: array(string()).optional()
|
|
7622
7678
|
});
|
|
7679
|
+
var COCO_TO_MACRO = {
|
|
7680
|
+
mapping: {
|
|
7681
|
+
person: "person",
|
|
7682
|
+
bicycle: "vehicle",
|
|
7683
|
+
car: "vehicle",
|
|
7684
|
+
motorcycle: "vehicle",
|
|
7685
|
+
airplane: "vehicle",
|
|
7686
|
+
bus: "vehicle",
|
|
7687
|
+
train: "vehicle",
|
|
7688
|
+
truck: "vehicle",
|
|
7689
|
+
boat: "vehicle",
|
|
7690
|
+
bird: "animal",
|
|
7691
|
+
cat: "animal",
|
|
7692
|
+
dog: "animal",
|
|
7693
|
+
horse: "animal",
|
|
7694
|
+
sheep: "animal",
|
|
7695
|
+
cow: "animal",
|
|
7696
|
+
elephant: "animal",
|
|
7697
|
+
bear: "animal",
|
|
7698
|
+
zebra: "animal",
|
|
7699
|
+
giraffe: "animal",
|
|
7700
|
+
suitcase: "package",
|
|
7701
|
+
backpack: "package",
|
|
7702
|
+
handbag: "package"
|
|
7703
|
+
},
|
|
7704
|
+
preserveOriginal: false
|
|
7705
|
+
};
|
|
7706
|
+
var AUDIO_MACRO_LABELS = [
|
|
7707
|
+
{
|
|
7708
|
+
id: "speech",
|
|
7709
|
+
name: "Speech",
|
|
7710
|
+
icon: "🗣️"
|
|
7711
|
+
},
|
|
7712
|
+
{
|
|
7713
|
+
id: "scream",
|
|
7714
|
+
name: "Scream / Shout",
|
|
7715
|
+
icon: "😱"
|
|
7716
|
+
},
|
|
7717
|
+
{
|
|
7718
|
+
id: "crying",
|
|
7719
|
+
name: "Crying / Baby",
|
|
7720
|
+
icon: "😢"
|
|
7721
|
+
},
|
|
7722
|
+
{
|
|
7723
|
+
id: "laughter",
|
|
7724
|
+
name: "Laughter",
|
|
7725
|
+
icon: "😂"
|
|
7726
|
+
},
|
|
7727
|
+
{
|
|
7728
|
+
id: "music",
|
|
7729
|
+
name: "Music",
|
|
7730
|
+
icon: "🎵"
|
|
7731
|
+
},
|
|
7732
|
+
{
|
|
7733
|
+
id: "dog",
|
|
7734
|
+
name: "Dog",
|
|
7735
|
+
icon: "🐕"
|
|
7736
|
+
},
|
|
7737
|
+
{
|
|
7738
|
+
id: "cat",
|
|
7739
|
+
name: "Cat",
|
|
7740
|
+
icon: "🐈"
|
|
7741
|
+
},
|
|
7742
|
+
{
|
|
7743
|
+
id: "bird",
|
|
7744
|
+
name: "Bird",
|
|
7745
|
+
icon: "🐦"
|
|
7746
|
+
},
|
|
7747
|
+
{
|
|
7748
|
+
id: "animal",
|
|
7749
|
+
name: "Animal (other)",
|
|
7750
|
+
icon: "🐾"
|
|
7751
|
+
},
|
|
7752
|
+
{
|
|
7753
|
+
id: "alarm",
|
|
7754
|
+
name: "Alarm / Siren",
|
|
7755
|
+
icon: "🚨"
|
|
7756
|
+
},
|
|
7757
|
+
{
|
|
7758
|
+
id: "doorbell",
|
|
7759
|
+
name: "Doorbell / Knock",
|
|
7760
|
+
icon: "🔔"
|
|
7761
|
+
},
|
|
7762
|
+
{
|
|
7763
|
+
id: "glass_breaking",
|
|
7764
|
+
name: "Glass Breaking",
|
|
7765
|
+
icon: "💥"
|
|
7766
|
+
},
|
|
7767
|
+
{
|
|
7768
|
+
id: "gunshot",
|
|
7769
|
+
name: "Gunshot / Explosion",
|
|
7770
|
+
icon: "💣"
|
|
7771
|
+
},
|
|
7772
|
+
{
|
|
7773
|
+
id: "vehicle",
|
|
7774
|
+
name: "Vehicle",
|
|
7775
|
+
icon: "🚗"
|
|
7776
|
+
},
|
|
7777
|
+
{
|
|
7778
|
+
id: "siren",
|
|
7779
|
+
name: "Emergency Siren",
|
|
7780
|
+
icon: "🚑"
|
|
7781
|
+
},
|
|
7782
|
+
{
|
|
7783
|
+
id: "fire",
|
|
7784
|
+
name: "Fire / Smoke",
|
|
7785
|
+
icon: "🔥"
|
|
7786
|
+
},
|
|
7787
|
+
{
|
|
7788
|
+
id: "water",
|
|
7789
|
+
name: "Water",
|
|
7790
|
+
icon: "💧"
|
|
7791
|
+
},
|
|
7792
|
+
{
|
|
7793
|
+
id: "wind",
|
|
7794
|
+
name: "Wind / Weather",
|
|
7795
|
+
icon: "🌬️"
|
|
7796
|
+
},
|
|
7797
|
+
{
|
|
7798
|
+
id: "door",
|
|
7799
|
+
name: "Door",
|
|
7800
|
+
icon: "🚪"
|
|
7801
|
+
},
|
|
7802
|
+
{
|
|
7803
|
+
id: "footsteps",
|
|
7804
|
+
name: "Footsteps",
|
|
7805
|
+
icon: "👣"
|
|
7806
|
+
},
|
|
7807
|
+
{
|
|
7808
|
+
id: "crowd",
|
|
7809
|
+
name: "Crowd / Chatter",
|
|
7810
|
+
icon: "👥"
|
|
7811
|
+
},
|
|
7812
|
+
{
|
|
7813
|
+
id: "telephone",
|
|
7814
|
+
name: "Telephone",
|
|
7815
|
+
icon: "📞"
|
|
7816
|
+
},
|
|
7817
|
+
{
|
|
7818
|
+
id: "engine",
|
|
7819
|
+
name: "Engine / Motor",
|
|
7820
|
+
icon: "⚙️"
|
|
7821
|
+
},
|
|
7822
|
+
{
|
|
7823
|
+
id: "tools",
|
|
7824
|
+
name: "Tools / Construction",
|
|
7825
|
+
icon: "🔨"
|
|
7826
|
+
},
|
|
7827
|
+
{
|
|
7828
|
+
id: "silence",
|
|
7829
|
+
name: "Silence",
|
|
7830
|
+
icon: "🤫"
|
|
7831
|
+
}
|
|
7832
|
+
];
|
|
7623
7833
|
var YAMNET_TO_MACRO = {
|
|
7624
7834
|
mapping: {
|
|
7625
7835
|
Speech: "speech",
|
|
@@ -7886,6 +8096,125 @@ var _macroLookup = /* @__PURE__ */ new Map();
|
|
|
7886
8096
|
for (const [k, v] of Object.entries(YAMNET_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
|
|
7887
8097
|
for (const [k, v] of Object.entries(APPLE_SA_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
|
|
7888
8098
|
/**
|
|
8099
|
+
* Unified event-kind taxonomy — THE single source of truth for
|
|
8100
|
+
* `kind → { parentKind, category, level, color, iconId, labelKey, label,
|
|
8101
|
+
* icon }`.
|
|
8102
|
+
*
|
|
8103
|
+
* This dictionary folds together what used to be scattered across four
|
|
8104
|
+
* copies:
|
|
8105
|
+
* - `capabilities/sensor-event-kinds.ts` (sensor cap colors)
|
|
8106
|
+
* - `addon-post-analysis/.../services/event-kinds.ts`
|
|
8107
|
+
* (MOTION/PERSON/VEHICLE… _COLOR constants)
|
|
8108
|
+
* - `ui-library/composites/detection-colors.ts` (CLASS_COLORS)
|
|
8109
|
+
* - `addon-post-analysis/shared/frame/box-drawer.ts` (DEFAULT_COLOR)
|
|
8110
|
+
* - the COCO / audio class maps (macro ↔ sub relationships)
|
|
8111
|
+
*
|
|
8112
|
+
* The DATA (serializable — color/iconId/labelKey/parentKind) lives here in
|
|
8113
|
+
* `@camstack/types`. The UI-side mapping `iconId → lucide component` and
|
|
8114
|
+
* `labelKey → t()` lives in `@camstack/ui-library`. UIs never hardcode a
|
|
8115
|
+
* color or an icon: they read this dictionary (server descriptors carry the
|
|
8116
|
+
* fields inline; the client resolves color/icon/label from `iconId`/`kind`).
|
|
8117
|
+
*
|
|
8118
|
+
* Two levels only (v1 YAGNI): macro → sub. `person` is a leaf macro.
|
|
8119
|
+
*/
|
|
8120
|
+
var TAXONOMY_COLORS = {
|
|
8121
|
+
motion: "#f59e0b",
|
|
8122
|
+
audio: "#06b6d4",
|
|
8123
|
+
person: "#22c55e",
|
|
8124
|
+
vehicle: "#3b82f6",
|
|
8125
|
+
animal: "#f97316",
|
|
8126
|
+
package: "#a855f7",
|
|
8127
|
+
sensor: "#8b5cf6",
|
|
8128
|
+
control: "#10b981",
|
|
8129
|
+
genericDetection: "#64748b"
|
|
8130
|
+
};
|
|
8131
|
+
var DETECTION_SUB_COLORS = {
|
|
8132
|
+
car: "#f59e0b",
|
|
8133
|
+
truck: "#d97706",
|
|
8134
|
+
bus: "#b45309",
|
|
8135
|
+
motorcycle: "#eab308",
|
|
8136
|
+
bicycle: "#ca8a04",
|
|
8137
|
+
airplane: "#60a5fa",
|
|
8138
|
+
boat: "#2563eb",
|
|
8139
|
+
train: "#1d4ed8",
|
|
8140
|
+
bird: "#14b8a6",
|
|
8141
|
+
dog: "#84cc16",
|
|
8142
|
+
cat: "#f97316",
|
|
8143
|
+
horse: "#a16207",
|
|
8144
|
+
sheep: "#a3a3a3",
|
|
8145
|
+
cow: "#78716c",
|
|
8146
|
+
elephant: "#6b7280",
|
|
8147
|
+
bear: "#7c2d12",
|
|
8148
|
+
zebra: "#404040",
|
|
8149
|
+
giraffe: "#d4a373"
|
|
8150
|
+
};
|
|
8151
|
+
function titleCase(id) {
|
|
8152
|
+
return id.split(/[-_ ]/).filter((p) => p.length > 0).map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join(" ");
|
|
8153
|
+
}
|
|
8154
|
+
var entries = /* @__PURE__ */ new Map();
|
|
8155
|
+
function macro(kind, category, color, iconId, label) {
|
|
8156
|
+
entries.set(kind, {
|
|
8157
|
+
kind,
|
|
8158
|
+
parentKind: null,
|
|
8159
|
+
level: "macro",
|
|
8160
|
+
category,
|
|
8161
|
+
color,
|
|
8162
|
+
iconId,
|
|
8163
|
+
labelKey: `eventKind.${kind}`,
|
|
8164
|
+
label
|
|
8165
|
+
});
|
|
8166
|
+
}
|
|
8167
|
+
function sub(kind, parentKind, category, color, iconId, label) {
|
|
8168
|
+
entries.set(kind, {
|
|
8169
|
+
kind,
|
|
8170
|
+
parentKind,
|
|
8171
|
+
level: "sub",
|
|
8172
|
+
category,
|
|
8173
|
+
color,
|
|
8174
|
+
iconId,
|
|
8175
|
+
labelKey: `eventKind.${kind}`,
|
|
8176
|
+
label
|
|
8177
|
+
});
|
|
8178
|
+
}
|
|
8179
|
+
macro("motion", "motion", TAXONOMY_COLORS.motion, "motion", "Motion");
|
|
8180
|
+
macro("audio", "audio", TAXONOMY_COLORS.audio, "audio", "Audio");
|
|
8181
|
+
macro("person", "detection", TAXONOMY_COLORS.person, "person", "Person");
|
|
8182
|
+
macro("vehicle", "detection", TAXONOMY_COLORS.vehicle, "vehicle", "Vehicle");
|
|
8183
|
+
macro("animal", "detection", TAXONOMY_COLORS.animal, "animal", "Animal");
|
|
8184
|
+
macro("package", "package", TAXONOMY_COLORS.package, "package", "Package");
|
|
8185
|
+
macro("sensor", "sensor", TAXONOMY_COLORS.sensor, "sensor", "Sensor");
|
|
8186
|
+
macro("control", "control", TAXONOMY_COLORS.control, "control", "Control");
|
|
8187
|
+
for (const [cocoClass, macroClass] of Object.entries(COCO_TO_MACRO.mapping)) {
|
|
8188
|
+
if (macroClass !== "vehicle" && macroClass !== "animal") continue;
|
|
8189
|
+
if (entries.has(cocoClass)) continue;
|
|
8190
|
+
sub(cocoClass, macroClass, "detection", DETECTION_SUB_COLORS[cocoClass] ?? TAXONOMY_COLORS.genericDetection, cocoClass, titleCase(cocoClass));
|
|
8191
|
+
}
|
|
8192
|
+
sub("package-delivered", "package", "package", TAXONOMY_COLORS.package, "package", "Package delivered");
|
|
8193
|
+
sub("package-picked-up", "package", "package", TAXONOMY_COLORS.package, "package", "Package picked up");
|
|
8194
|
+
sub("contact", "sensor", "sensor", "#f59e0b", "door", "Contact");
|
|
8195
|
+
sub("motion-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "pir", "Motion sensor");
|
|
8196
|
+
sub("smoke", "sensor", "sensor", "#ef4444", "smoke", "Smoke");
|
|
8197
|
+
sub("flood", "sensor", "sensor", "#3b82f6", "water", "Water leak");
|
|
8198
|
+
sub("gas", "sensor", "sensor", "#ef4444", "gas", "Gas");
|
|
8199
|
+
sub("carbon-monoxide", "sensor", "sensor", "#dc2626", "smoke", "Carbon monoxide");
|
|
8200
|
+
sub("vibration", "sensor", "sensor", "#eab308", "vibration", "Vibration");
|
|
8201
|
+
sub("tamper", "sensor", "sensor", "#f97316", "tamper", "Tamper");
|
|
8202
|
+
sub("presence", "sensor", "sensor", "#22c55e", "presence", "Presence");
|
|
8203
|
+
sub("enum-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "generic", "Sensor state");
|
|
8204
|
+
sub("device-event", "sensor", "sensor", "#10b981", "button", "Device event");
|
|
8205
|
+
sub("lock", "control", "control", "#0ea5e9", "lock", "Lock");
|
|
8206
|
+
sub("switch", "control", "control", TAXONOMY_COLORS.control, "switch", "Switch");
|
|
8207
|
+
sub("siren", "control", "control", "#dc2626", "siren", "Siren");
|
|
8208
|
+
sub("button", "control", "control", "#10b981", "button", "Button");
|
|
8209
|
+
sub("doorbell", "control", "control", "#a855f7", "doorbell", "Doorbell");
|
|
8210
|
+
for (const l of AUDIO_MACRO_LABELS) {
|
|
8211
|
+
const kind = `audio-${l.id}`;
|
|
8212
|
+
if (entries.has(kind)) continue;
|
|
8213
|
+
sub(kind, "audio", "audio", TAXONOMY_COLORS.audio, kind, l.name);
|
|
8214
|
+
}
|
|
8215
|
+
/** The complete taxonomy dictionary, keyed by kind. */
|
|
8216
|
+
var EVENT_TAXONOMY = Object.freeze(Object.fromEntries(entries));
|
|
8217
|
+
/**
|
|
7889
8218
|
* Error types for the safe expression engine. Two distinct classes so callers
|
|
7890
8219
|
* can tell a compile-time (grammar) failure from a runtime (evaluation)
|
|
7891
8220
|
* failure — both are non-fatal to the host: read paths degrade to "skip link".
|
|
@@ -15860,17 +16189,30 @@ var EventKindCategorySchema = _enum([
|
|
|
15860
16189
|
"audio",
|
|
15861
16190
|
"detection",
|
|
15862
16191
|
"sensor",
|
|
16192
|
+
"control",
|
|
15863
16193
|
"custom",
|
|
15864
16194
|
"package"
|
|
15865
16195
|
]);
|
|
16196
|
+
/** Taxonomy level — macro (timeline lane) vs sub (events-page leaf). */
|
|
16197
|
+
var EventKindLevelSchema = _enum(["macro", "sub"]);
|
|
15866
16198
|
var EventKindDescriptorSchema = object({
|
|
15867
|
-
/** Stable kind id (e.g. 'motion', '
|
|
16199
|
+
/** Stable kind id (e.g. 'motion', 'vehicle', 'car', 'lock'). */
|
|
15868
16200
|
kind: string(),
|
|
16201
|
+
/** i18n key resolved on the UI side; `label` is the English fallback. */
|
|
16202
|
+
labelKey: string(),
|
|
16203
|
+
/** English fallback label (kept for clients that don't translate). */
|
|
15869
16204
|
label: string(),
|
|
15870
16205
|
/** Hex color for timeline/legend rendering. */
|
|
15871
16206
|
color: string(),
|
|
16207
|
+
/** Dictionary id → lucide component on the UI side. */
|
|
16208
|
+
iconId: string(),
|
|
16209
|
+
/** Legacy closed-vocab glyph — fallback for `iconId`. */
|
|
15872
16210
|
icon: EventKindIconSchema,
|
|
15873
16211
|
category: EventKindCategorySchema,
|
|
16212
|
+
/** Macro parent for this kind ('car' → 'vehicle'); null for a macro. */
|
|
16213
|
+
parentKind: string().nullable(),
|
|
16214
|
+
/** Derived from `parentKind`, explicit for the client tree. */
|
|
16215
|
+
level: EventKindLevelSchema,
|
|
15874
16216
|
/** Which cap + device contributes this kind. For built-ins the camera
|
|
15875
16217
|
* itself; for sensor kinds the LINKED source device. */
|
|
15876
16218
|
source: object({
|
|
@@ -15943,11 +16285,21 @@ var TrackAudioLabelSchema = object({
|
|
|
15943
16285
|
firstAt: number$1(),
|
|
15944
16286
|
lastAt: number$1()
|
|
15945
16287
|
});
|
|
16288
|
+
/**
|
|
16289
|
+
* How a track was produced. `pipeline` (default / absent) = the spatial
|
|
16290
|
+
* detection+tracking pipeline. `sensor` = a SYNTHETIC track projected from a
|
|
16291
|
+
* linked sensor/control state change (no positions; carries a snapshot). The
|
|
16292
|
+
* spatial subsystems (tracker association, occupancy count, re-id/embedding,
|
|
16293
|
+
* resurrection) MUST skip `sensor` tracks — they have no bbox trajectory.
|
|
16294
|
+
*/
|
|
16295
|
+
var TrackSourceSchema = _enum(["pipeline", "sensor"]);
|
|
15946
16296
|
var TrackSchema = object({
|
|
15947
16297
|
trackId: string(),
|
|
15948
16298
|
deviceId: number$1(),
|
|
15949
16299
|
className: string(),
|
|
15950
16300
|
label: string().optional(),
|
|
16301
|
+
/** Track provenance. Absent ⇒ `pipeline` (legacy rows). */
|
|
16302
|
+
source: TrackSourceSchema.optional(),
|
|
15951
16303
|
firstSeen: number$1(),
|
|
15952
16304
|
lastSeen: number$1(),
|
|
15953
16305
|
/** Frame-rate position history (subject to maxPositionHistory cap). */
|
|
@@ -16202,6 +16554,26 @@ var TrackCascadeCountsSchema = object({
|
|
|
16202
16554
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
16203
16555
|
embeddings: number$1().int()
|
|
16204
16556
|
});
|
|
16557
|
+
/** Event-store footprint for one camera. */
|
|
16558
|
+
var EventStoreDeviceFootprintSchema = object({
|
|
16559
|
+
deviceId: number$1(),
|
|
16560
|
+
/** Persisted event rows (motion + object + audio) for the camera. */
|
|
16561
|
+
rows: number$1().int(),
|
|
16562
|
+
/** Event-owned media bytes on disk for the camera. */
|
|
16563
|
+
bytes: number$1().int()
|
|
16564
|
+
});
|
|
16565
|
+
/** Aggregate event-store footprint: global totals + per-camera breakdown. */
|
|
16566
|
+
var EventStoreFootprintSchema = object({
|
|
16567
|
+
totalRows: number$1().int(),
|
|
16568
|
+
totalBytes: number$1().int(),
|
|
16569
|
+
devices: array(EventStoreDeviceFootprintSchema).readonly()
|
|
16570
|
+
});
|
|
16571
|
+
/** Per-kind counts returned by the event-prune / device-delete mutations. */
|
|
16572
|
+
var EventPruneCountsSchema = object({
|
|
16573
|
+
motion: number$1().int(),
|
|
16574
|
+
object: number$1().int(),
|
|
16575
|
+
audio: number$1().int()
|
|
16576
|
+
});
|
|
16205
16577
|
DeviceType.Camera, method(object({ deviceId: number$1() }), array(TrackSchema).readonly()), method(object({
|
|
16206
16578
|
deviceId: number$1(),
|
|
16207
16579
|
trackId: string()
|
|
@@ -16265,6 +16637,21 @@ DeviceType.Camera, method(object({ deviceId: number$1() }), array(TrackSchema).r
|
|
|
16265
16637
|
}), {
|
|
16266
16638
|
kind: "mutation",
|
|
16267
16639
|
auth: "admin"
|
|
16640
|
+
}), method(object({}), EventStoreFootprintSchema, {
|
|
16641
|
+
kind: "query",
|
|
16642
|
+
auth: "admin"
|
|
16643
|
+
}), method(object({
|
|
16644
|
+
olderThanMs: number$1(),
|
|
16645
|
+
reason: OpsLogReasonSchema.optional()
|
|
16646
|
+
}), EventPruneCountsSchema, {
|
|
16647
|
+
kind: "mutation",
|
|
16648
|
+
auth: "admin"
|
|
16649
|
+
}), method(object({ deviceId: number$1() }), EventPruneCountsSchema, {
|
|
16650
|
+
kind: "mutation",
|
|
16651
|
+
auth: "admin"
|
|
16652
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
16653
|
+
kind: "query",
|
|
16654
|
+
auth: "admin"
|
|
16268
16655
|
}), method(object({
|
|
16269
16656
|
eventId: string(),
|
|
16270
16657
|
kind: MediaFileKindEnum.optional()
|
|
@@ -16289,6 +16676,76 @@ DeviceType.Camera, method(object({ deviceId: number$1() }), array(TrackSchema).r
|
|
|
16289
16676
|
eventId: string(),
|
|
16290
16677
|
timestamp: number$1()
|
|
16291
16678
|
});
|
|
16679
|
+
/**
|
|
16680
|
+
* Cap → event-kind mapping for the SENSOR / CONTROL cap families — the table
|
|
16681
|
+
* `pipeline-analytics.listEventKinds` uses to turn a linked device's bound
|
|
16682
|
+
* caps into per-camera event-kind descriptors.
|
|
16683
|
+
*
|
|
16684
|
+
* The descriptor DATA (color / iconId / labelKey / parentKind / category)
|
|
16685
|
+
* is NOT duplicated here — every entry is derived from the single
|
|
16686
|
+
* `EVENT_TAXONOMY` dictionary (`catalogs/event-taxonomy.ts`). This file owns
|
|
16687
|
+
* ONLY the cap-name → taxonomy-kind mapping. Adding a new eventful sensor /
|
|
16688
|
+
* control cap means adding one line here (and a taxonomy entry); the anti-
|
|
16689
|
+
* drift guard `scripts/check-event-kind-coverage.ts` fails the build if an
|
|
16690
|
+
* eventful cap is missing.
|
|
16691
|
+
*/
|
|
16692
|
+
/** Map a taxonomy `iconId` onto the legacy closed `EventKindIcon` enum. */
|
|
16693
|
+
var LEGACY_ICON = {
|
|
16694
|
+
motion: "motion",
|
|
16695
|
+
audio: "audio",
|
|
16696
|
+
person: "person",
|
|
16697
|
+
vehicle: "vehicle",
|
|
16698
|
+
animal: "animal",
|
|
16699
|
+
package: "package",
|
|
16700
|
+
door: "door",
|
|
16701
|
+
pir: "pir",
|
|
16702
|
+
smoke: "smoke",
|
|
16703
|
+
water: "water",
|
|
16704
|
+
button: "button",
|
|
16705
|
+
generic: "generic",
|
|
16706
|
+
gas: "smoke",
|
|
16707
|
+
vibration: "generic",
|
|
16708
|
+
tamper: "generic",
|
|
16709
|
+
presence: "person",
|
|
16710
|
+
lock: "generic",
|
|
16711
|
+
siren: "generic",
|
|
16712
|
+
switch: "generic",
|
|
16713
|
+
doorbell: "button"
|
|
16714
|
+
};
|
|
16715
|
+
function legacyIcon(iconId) {
|
|
16716
|
+
return LEGACY_ICON[iconId] ?? "generic";
|
|
16717
|
+
}
|
|
16718
|
+
/**
|
|
16719
|
+
* Cap name → taxonomy kind id. Covers EVERY eventful sensor / control cap.
|
|
16720
|
+
* The anti-drift guard cross-checks this against the eventful caps declared
|
|
16721
|
+
* in `packages/types/src/capabilities/*.cap.ts`.
|
|
16722
|
+
*/
|
|
16723
|
+
var CAP_TO_KIND = {
|
|
16724
|
+
contact: "contact",
|
|
16725
|
+
motion: "motion-sensor",
|
|
16726
|
+
smoke: "smoke",
|
|
16727
|
+
flood: "flood",
|
|
16728
|
+
gas: "gas",
|
|
16729
|
+
"carbon-monoxide": "carbon-monoxide",
|
|
16730
|
+
vibration: "vibration",
|
|
16731
|
+
tamper: "tamper",
|
|
16732
|
+
presence: "presence",
|
|
16733
|
+
"enum-sensor": "enum-sensor",
|
|
16734
|
+
"event-emitter": "device-event",
|
|
16735
|
+
"lock-control": "lock",
|
|
16736
|
+
switch: "switch",
|
|
16737
|
+
button: "button",
|
|
16738
|
+
doorbell: "doorbell"
|
|
16739
|
+
};
|
|
16740
|
+
function buildDescriptor(capName, kind) {
|
|
16741
|
+
const t = EVENT_TAXONOMY[kind];
|
|
16742
|
+
if (t === void 0) throw new Error(`EVENT_KIND_BY_CAP: cap '${capName}' maps to unknown taxonomy kind '${kind}'`);
|
|
16743
|
+
return {
|
|
16744
|
+
...t,
|
|
16745
|
+
icon: legacyIcon(t.iconId)
|
|
16746
|
+
};
|
|
16747
|
+
}
|
|
16748
|
+
Object.freeze(Object.fromEntries(Object.entries(CAP_TO_KIND).map(([capName, kind]) => [capName, buildDescriptor(capName, kind)])));
|
|
16292
16749
|
var CameraPipelineConfigSchema = object({
|
|
16293
16750
|
engine: PipelineEngineChoiceSchema.optional(),
|
|
16294
16751
|
steps: array(PipelineStepInputSchema).readonly(),
|
|
@@ -19498,13 +19955,29 @@ method(object({
|
|
|
19498
19955
|
}), method(object({ deviceId: number$1() }), RecordingStatusSchema, {
|
|
19499
19956
|
kind: "mutation",
|
|
19500
19957
|
auth: "admin"
|
|
19501
|
-
}), method(object({
|
|
19958
|
+
}), method(object({
|
|
19959
|
+
deviceId: number$1(),
|
|
19960
|
+
reason: OpsLogReasonSchema.optional()
|
|
19961
|
+
}), object({
|
|
19502
19962
|
floorMs: number$1().nullable(),
|
|
19503
19963
|
deletedBuckets: number$1().int(),
|
|
19504
19964
|
reclaimedBytes: number$1().int()
|
|
19505
19965
|
}), {
|
|
19506
19966
|
kind: "mutation",
|
|
19507
19967
|
auth: "admin"
|
|
19968
|
+
}), method(object({
|
|
19969
|
+
deviceId: number$1(),
|
|
19970
|
+
fromMs: number$1().optional(),
|
|
19971
|
+
toMs: number$1().optional()
|
|
19972
|
+
}), object({
|
|
19973
|
+
deletedBuckets: number$1().int(),
|
|
19974
|
+
reclaimedBytes: number$1().int()
|
|
19975
|
+
}), {
|
|
19976
|
+
kind: "mutation",
|
|
19977
|
+
auth: "admin"
|
|
19978
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
19979
|
+
kind: "query",
|
|
19980
|
+
auth: "admin"
|
|
19508
19981
|
});
|
|
19509
19982
|
/**
|
|
19510
19983
|
* `recordingExport` cap — render a footage time range into a single downloadable
|
|
@@ -22626,6 +23099,12 @@ Object.freeze({
|
|
|
22626
23099
|
addonId: null,
|
|
22627
23100
|
access: "delete"
|
|
22628
23101
|
},
|
|
23102
|
+
"pipelineAnalytics.deleteDeviceEvents": {
|
|
23103
|
+
capName: "pipeline-analytics",
|
|
23104
|
+
capScope: "device",
|
|
23105
|
+
addonId: null,
|
|
23106
|
+
access: "delete"
|
|
23107
|
+
},
|
|
22629
23108
|
"pipelineAnalytics.deleteTracks": {
|
|
22630
23109
|
capName: "pipeline-analytics",
|
|
22631
23110
|
capScope: "device",
|
|
@@ -22656,6 +23135,12 @@ Object.freeze({
|
|
|
22656
23135
|
addonId: null,
|
|
22657
23136
|
access: "view"
|
|
22658
23137
|
},
|
|
23138
|
+
"pipelineAnalytics.getEventStoreFootprint": {
|
|
23139
|
+
capName: "pipeline-analytics",
|
|
23140
|
+
capScope: "device",
|
|
23141
|
+
addonId: null,
|
|
23142
|
+
access: "view"
|
|
23143
|
+
},
|
|
22659
23144
|
"pipelineAnalytics.getKeyEvents": {
|
|
22660
23145
|
capName: "pipeline-analytics",
|
|
22661
23146
|
capScope: "device",
|
|
@@ -22698,6 +23183,12 @@ Object.freeze({
|
|
|
22698
23183
|
addonId: null,
|
|
22699
23184
|
access: "view"
|
|
22700
23185
|
},
|
|
23186
|
+
"pipelineAnalytics.listOpsLog": {
|
|
23187
|
+
capName: "pipeline-analytics",
|
|
23188
|
+
capScope: "device",
|
|
23189
|
+
addonId: null,
|
|
23190
|
+
access: "view"
|
|
23191
|
+
},
|
|
22701
23192
|
"pipelineAnalytics.listRecentTracks": {
|
|
22702
23193
|
capName: "pipeline-analytics",
|
|
22703
23194
|
capScope: "device",
|
|
@@ -22710,6 +23201,12 @@ Object.freeze({
|
|
|
22710
23201
|
addonId: null,
|
|
22711
23202
|
access: "view"
|
|
22712
23203
|
},
|
|
23204
|
+
"pipelineAnalytics.pruneEvents": {
|
|
23205
|
+
capName: "pipeline-analytics",
|
|
23206
|
+
capScope: "device",
|
|
23207
|
+
addonId: null,
|
|
23208
|
+
access: "create"
|
|
23209
|
+
},
|
|
22713
23210
|
"pipelineAnalytics.pruneEventsBefore": {
|
|
22714
23211
|
capName: "pipeline-analytics",
|
|
22715
23212
|
capScope: "device",
|
|
@@ -23472,6 +23969,12 @@ Object.freeze({
|
|
|
23472
23969
|
addonId: null,
|
|
23473
23970
|
access: "create"
|
|
23474
23971
|
},
|
|
23972
|
+
"recording.deleteFootprint": {
|
|
23973
|
+
capName: "recording",
|
|
23974
|
+
capScope: "system",
|
|
23975
|
+
addonId: null,
|
|
23976
|
+
access: "delete"
|
|
23977
|
+
},
|
|
23475
23978
|
"recording.getAvailability": {
|
|
23476
23979
|
capName: "recording",
|
|
23477
23980
|
capScope: "system",
|
|
@@ -23502,6 +24005,12 @@ Object.freeze({
|
|
|
23502
24005
|
addonId: null,
|
|
23503
24006
|
access: "view"
|
|
23504
24007
|
},
|
|
24008
|
+
"recording.listOpsLog": {
|
|
24009
|
+
capName: "recording",
|
|
24010
|
+
capScope: "system",
|
|
24011
|
+
addonId: null,
|
|
24012
|
+
access: "view"
|
|
24013
|
+
},
|
|
23505
24014
|
"recording.locateSegment": {
|
|
23506
24015
|
capName: "recording",
|
|
23507
24016
|
capScope: "system",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-export-ha-mqtt",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.27",
|
|
4
4
|
"description": "HomeAssistant MQTT discovery exporter for CamStack devices. Publishes discovery topics so HA auto-creates entities for exposed cameras/switches/intercoms/sensors.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|