@camstack/addon-provider-homematic 1.2.23 → 1.2.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/addon.js +167 -59
- package/dist/addon.mjs +167 -59
- package/package.json +1 -1
package/dist/addon.js
CHANGED
|
@@ -7575,7 +7575,7 @@ var RecordingBandSchema = object({
|
|
|
7575
7575
|
postBufferSec: number().min(0).optional()
|
|
7576
7576
|
});
|
|
7577
7577
|
({
|
|
7578
|
-
preBufferSec:
|
|
7578
|
+
preBufferSec: 15,
|
|
7579
7579
|
postBufferSec: 30
|
|
7580
7580
|
}).postBufferSec * 1e3;
|
|
7581
7581
|
/**
|
|
@@ -13844,128 +13844,103 @@ var COCO_TO_MACRO = {
|
|
|
13844
13844
|
var AUDIO_MACRO_LABELS = [
|
|
13845
13845
|
{
|
|
13846
13846
|
id: "speech",
|
|
13847
|
-
name: "Speech"
|
|
13848
|
-
icon: "🗣️"
|
|
13847
|
+
name: "Speech"
|
|
13849
13848
|
},
|
|
13850
13849
|
{
|
|
13851
13850
|
id: "scream",
|
|
13852
|
-
name: "Scream / Shout"
|
|
13853
|
-
icon: "😱"
|
|
13851
|
+
name: "Scream / Shout"
|
|
13854
13852
|
},
|
|
13855
13853
|
{
|
|
13856
13854
|
id: "crying",
|
|
13857
|
-
name: "Crying / Baby"
|
|
13858
|
-
icon: "😢"
|
|
13855
|
+
name: "Crying / Baby"
|
|
13859
13856
|
},
|
|
13860
13857
|
{
|
|
13861
13858
|
id: "laughter",
|
|
13862
|
-
name: "Laughter"
|
|
13863
|
-
icon: "😂"
|
|
13859
|
+
name: "Laughter"
|
|
13864
13860
|
},
|
|
13865
13861
|
{
|
|
13866
13862
|
id: "music",
|
|
13867
|
-
name: "Music"
|
|
13868
|
-
icon: "🎵"
|
|
13863
|
+
name: "Music"
|
|
13869
13864
|
},
|
|
13870
13865
|
{
|
|
13871
13866
|
id: "dog",
|
|
13872
|
-
name: "Dog"
|
|
13873
|
-
icon: "🐕"
|
|
13867
|
+
name: "Dog"
|
|
13874
13868
|
},
|
|
13875
13869
|
{
|
|
13876
13870
|
id: "cat",
|
|
13877
|
-
name: "Cat"
|
|
13878
|
-
icon: "🐈"
|
|
13871
|
+
name: "Cat"
|
|
13879
13872
|
},
|
|
13880
13873
|
{
|
|
13881
13874
|
id: "bird",
|
|
13882
|
-
name: "Bird"
|
|
13883
|
-
icon: "🐦"
|
|
13875
|
+
name: "Bird"
|
|
13884
13876
|
},
|
|
13885
13877
|
{
|
|
13886
13878
|
id: "animal",
|
|
13887
|
-
name: "Animal (other)"
|
|
13888
|
-
icon: "🐾"
|
|
13879
|
+
name: "Animal (other)"
|
|
13889
13880
|
},
|
|
13890
13881
|
{
|
|
13891
13882
|
id: "alarm",
|
|
13892
|
-
name: "Alarm / Siren"
|
|
13893
|
-
icon: "🚨"
|
|
13883
|
+
name: "Alarm / Siren"
|
|
13894
13884
|
},
|
|
13895
13885
|
{
|
|
13896
13886
|
id: "doorbell",
|
|
13897
|
-
name: "Doorbell / Knock"
|
|
13898
|
-
icon: "🔔"
|
|
13887
|
+
name: "Doorbell / Knock"
|
|
13899
13888
|
},
|
|
13900
13889
|
{
|
|
13901
13890
|
id: "glass_breaking",
|
|
13902
|
-
name: "Glass Breaking"
|
|
13903
|
-
icon: "💥"
|
|
13891
|
+
name: "Glass Breaking"
|
|
13904
13892
|
},
|
|
13905
13893
|
{
|
|
13906
13894
|
id: "gunshot",
|
|
13907
|
-
name: "Gunshot / Explosion"
|
|
13908
|
-
icon: "💣"
|
|
13895
|
+
name: "Gunshot / Explosion"
|
|
13909
13896
|
},
|
|
13910
13897
|
{
|
|
13911
13898
|
id: "vehicle",
|
|
13912
|
-
name: "Vehicle"
|
|
13913
|
-
icon: "🚗"
|
|
13899
|
+
name: "Vehicle"
|
|
13914
13900
|
},
|
|
13915
13901
|
{
|
|
13916
13902
|
id: "siren",
|
|
13917
|
-
name: "Emergency Siren"
|
|
13918
|
-
icon: "🚑"
|
|
13903
|
+
name: "Emergency Siren"
|
|
13919
13904
|
},
|
|
13920
13905
|
{
|
|
13921
13906
|
id: "fire",
|
|
13922
|
-
name: "Fire / Smoke"
|
|
13923
|
-
icon: "🔥"
|
|
13907
|
+
name: "Fire / Smoke"
|
|
13924
13908
|
},
|
|
13925
13909
|
{
|
|
13926
13910
|
id: "water",
|
|
13927
|
-
name: "Water"
|
|
13928
|
-
icon: "💧"
|
|
13911
|
+
name: "Water"
|
|
13929
13912
|
},
|
|
13930
13913
|
{
|
|
13931
13914
|
id: "wind",
|
|
13932
|
-
name: "Wind / Weather"
|
|
13933
|
-
icon: "🌬️"
|
|
13915
|
+
name: "Wind / Weather"
|
|
13934
13916
|
},
|
|
13935
13917
|
{
|
|
13936
13918
|
id: "door",
|
|
13937
|
-
name: "Door"
|
|
13938
|
-
icon: "🚪"
|
|
13919
|
+
name: "Door"
|
|
13939
13920
|
},
|
|
13940
13921
|
{
|
|
13941
13922
|
id: "footsteps",
|
|
13942
|
-
name: "Footsteps"
|
|
13943
|
-
icon: "👣"
|
|
13923
|
+
name: "Footsteps"
|
|
13944
13924
|
},
|
|
13945
13925
|
{
|
|
13946
13926
|
id: "crowd",
|
|
13947
|
-
name: "Crowd / Chatter"
|
|
13948
|
-
icon: "👥"
|
|
13927
|
+
name: "Crowd / Chatter"
|
|
13949
13928
|
},
|
|
13950
13929
|
{
|
|
13951
13930
|
id: "telephone",
|
|
13952
|
-
name: "Telephone"
|
|
13953
|
-
icon: "📞"
|
|
13931
|
+
name: "Telephone"
|
|
13954
13932
|
},
|
|
13955
13933
|
{
|
|
13956
13934
|
id: "engine",
|
|
13957
|
-
name: "Engine / Motor"
|
|
13958
|
-
icon: "⚙️"
|
|
13935
|
+
name: "Engine / Motor"
|
|
13959
13936
|
},
|
|
13960
13937
|
{
|
|
13961
13938
|
id: "tools",
|
|
13962
|
-
name: "Tools / Construction"
|
|
13963
|
-
icon: "🔨"
|
|
13939
|
+
name: "Tools / Construction"
|
|
13964
13940
|
},
|
|
13965
13941
|
{
|
|
13966
13942
|
id: "silence",
|
|
13967
|
-
name: "Silence"
|
|
13968
|
-
icon: "🤫"
|
|
13943
|
+
name: "Silence"
|
|
13969
13944
|
}
|
|
13970
13945
|
];
|
|
13971
13946
|
var YAMNET_TO_MACRO = {
|
|
@@ -16467,7 +16442,7 @@ var TrackEnvelopeSchema = object({
|
|
|
16467
16442
|
* `snapshots[]` references — megabytes across a page of tracks. `slim`
|
|
16468
16443
|
* keeps every scalar the list surfaces actually render (ids, class(es),
|
|
16469
16444
|
* label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
|
|
16470
|
-
* zonesVisited, bestEventId, envelope, hasFace, hasRider) and returns `positions` /
|
|
16445
|
+
* zonesVisited, bestEventId, envelope, hasFace, hasEmbeddedFace, hasRider) and returns `positions` /
|
|
16471
16446
|
* `snapshots` as EMPTY arrays — detail views re-fetch the full row via
|
|
16472
16447
|
* `getTrack`. Mirrors the event-store `projection` convention
|
|
16473
16448
|
* (`getObjectEvents` et al.).
|
|
@@ -16762,6 +16737,35 @@ var TrackSchema = object({
|
|
|
16762
16737
|
*/
|
|
16763
16738
|
hasFace: boolean().optional(),
|
|
16764
16739
|
/**
|
|
16740
|
+
* This track has a face row IN THE GALLERY: a crop **and** an embedding — a
|
|
16741
|
+
* face an operator could ASSIGN to an identity.
|
|
16742
|
+
*
|
|
16743
|
+
* The STRICT twin of {@link hasFace}, and the pair only earns its keep
|
|
16744
|
+
* because the two disagree. `hasFace` is stamped at the TOP of the face
|
|
16745
|
+
* branch, before every gate, and means no more than "a face detector produced
|
|
16746
|
+
* a face detail". This one is stamped at the single moment the gallery row
|
|
16747
|
+
* LANDS — after `FaceRecognizer.onTrackEnd` successfully persists it, i.e.
|
|
16748
|
+
* past the embedding-magnitude verdict, the `minFacePx` detection gate, the
|
|
16749
|
+
* candidate gate, the imageless-track drop (no crop was ever captured) and
|
|
16750
|
+
* the crop-store drop. Everything between the detector and that insert can
|
|
16751
|
+
* legitimately refuse the face, so a flag written any earlier promises the
|
|
16752
|
+
* operator something to assign and delivers nothing.
|
|
16753
|
+
*
|
|
16754
|
+
* **Independent of recognition.** A face collected but never auto-matched is
|
|
16755
|
+
* still assignable — it is in fact the face an operator most wants to reach —
|
|
16756
|
+
* so this is NOT gated on `recognizedIdentityId`. Recognition lands in
|
|
16757
|
+
* `subLabel`; this says only that the raw material exists.
|
|
16758
|
+
*
|
|
16759
|
+
* **Set once, never cleared.** A track that produced a gallery row produced
|
|
16760
|
+
* one; deleting the row later is the gallery's business, not this flag's.
|
|
16761
|
+
*
|
|
16762
|
+
* **Absent ≠ false**, the same rule as {@link hasFace}: every row written
|
|
16763
|
+
* before the column omits it, and so does every server that predates the
|
|
16764
|
+
* field. A consumer must test `=== true` and render nothing otherwise —
|
|
16765
|
+
* never infer "no assignable face".
|
|
16766
|
+
*/
|
|
16767
|
+
hasEmbeddedFace: boolean().optional(),
|
|
16768
|
+
/**
|
|
16765
16769
|
* This subject CONTAINS a folded rider — a person the rider-pairing step
|
|
16766
16770
|
* ([D34](../decisions/adr-0034.md)) removed from the frame BEFORE the tracker,
|
|
16767
16771
|
* so the passage is tracked once and as a VEHICLE.
|
|
@@ -18151,6 +18155,32 @@ var DetailResultSchema = object({
|
|
|
18151
18155
|
/** FRAME-space bbox (already mapped back from crop space). */
|
|
18152
18156
|
bbox: NativeCropBboxSchema.optional(),
|
|
18153
18157
|
embedding: string().optional(),
|
|
18158
|
+
/**
|
|
18159
|
+
* L2 magnitude of the RAW pre-normalization embedding. Additive and optional
|
|
18160
|
+
* so an older runner that does not send it degrades to "unmeasurable", which
|
|
18161
|
+
* the consuming gate treats as accept — never as reject.
|
|
18162
|
+
*/
|
|
18163
|
+
embeddingMagnitude: number().optional(),
|
|
18164
|
+
/**
|
|
18165
|
+
* Model that produced `embedding` — the SAME contract `labelModelId` has for
|
|
18166
|
+
* `label`, and for the same reason: the producing node is the only side that
|
|
18167
|
+
* knows which model actually ran, and re-deriving it downstream is exactly
|
|
18168
|
+
* the inference this model exists to forbid.
|
|
18169
|
+
*
|
|
18170
|
+
* Additive and optional, so a runner that predates it degrades to
|
|
18171
|
+
* "unmeasurable" rather than to a wrong answer — the consumer falls back to
|
|
18172
|
+
* its previous assumption instead of refusing.
|
|
18173
|
+
*
|
|
18174
|
+
* Its absence was not cosmetic. `FaceRecognizer` needs the probe's model id
|
|
18175
|
+
* to use `face-matcher`'s same-model gate (`sample.modelId !== probe.modelId`);
|
|
18176
|
+
* with nothing on the wire it took the id from the GALLERY, so the gate
|
|
18177
|
+
* compared the gallery against itself and could never fire. That turned the
|
|
18178
|
+
* one guard protecting the face feature space into a tautology, and it is
|
|
18179
|
+
* why swapping `face-embedding`'s model would NOT have stranded the enrolled
|
|
18180
|
+
* gallery as the catalog comment predicts — it would have scored the new
|
|
18181
|
+
* model's vectors against the old model's samples in one cosine space.
|
|
18182
|
+
*/
|
|
18183
|
+
embeddingModelId: string().optional(),
|
|
18154
18184
|
label: string().optional(),
|
|
18155
18185
|
/**
|
|
18156
18186
|
* The tier `label` occupies, copied VERBATIM from the producing step's
|
|
@@ -19561,6 +19591,7 @@ DeviceType.Camera, method(object({
|
|
|
19561
19591
|
isBattery: boolean(),
|
|
19562
19592
|
reason: _enum([
|
|
19563
19593
|
"disabled",
|
|
19594
|
+
"offline",
|
|
19564
19595
|
"sleeping",
|
|
19565
19596
|
"unreachable",
|
|
19566
19597
|
"waking"
|
|
@@ -19606,9 +19637,17 @@ targets: array(object({
|
|
|
19606
19637
|
sleeping: boolean(),
|
|
19607
19638
|
/** Current device state rendered over the cached frame. State images
|
|
19608
19639
|
* remain authoritative even when their photographic background is
|
|
19609
|
-
* old; null means the link must carry a current camera frame.
|
|
19640
|
+
* old; null means the link must carry a current camera frame.
|
|
19641
|
+
*
|
|
19642
|
+
* **This is the ONLY source a surface may derive an inactive tile
|
|
19643
|
+
* from.** A client that reads a device's `online`/`disabled` flags and
|
|
19644
|
+
* draws its own verdict will disagree with the pixels it is painting
|
|
19645
|
+
* — the frame comes from here, and so must the sentence over it
|
|
19646
|
+
* (D190). Pair with `ageMs` for the age of the photograph behind the
|
|
19647
|
+
* state. */
|
|
19610
19648
|
stateReason: _enum([
|
|
19611
19649
|
"disabled",
|
|
19650
|
+
"offline",
|
|
19612
19651
|
"sleeping",
|
|
19613
19652
|
"unreachable",
|
|
19614
19653
|
"waking"
|
|
@@ -26327,9 +26366,21 @@ var RecordingLocationUsageSchema = object({
|
|
|
26327
26366
|
* previously rendered as two identical "disks" with a nonsensical used
|
|
26328
26367
|
* split — hydrate attribution across aliases is arbitrary by nature. */
|
|
26329
26368
|
locationIds: array(string()).optional(),
|
|
26330
|
-
/**
|
|
26369
|
+
/**
|
|
26370
|
+
* Filesystem root of the physical volume this row accounts — the only
|
|
26371
|
+
* operator-legible identity when a location has no `displayName` yet, and
|
|
26372
|
+
* what a "which disk is full" alert has to name. OPTIONAL for the same
|
|
26373
|
+
* train-skew reason as `oldestMs`: a recorder that predates the field omits
|
|
26374
|
+
* it, and this schema must keep validating that older provider's payload.
|
|
26375
|
+
*/
|
|
26376
|
+
root: string().optional(),
|
|
26377
|
+
/** Bytes of recordings stored on this PHYSICAL volume (all aliases). This is
|
|
26378
|
+
* the footage's SHARE of the volume, not how full the volume is — the disk
|
|
26379
|
+
* also holds everything that is not recordings. Volume fill is
|
|
26380
|
+
* `(totalBytes - availableBytes) / totalBytes`. */
|
|
26331
26381
|
usedBytes: number(),
|
|
26332
|
-
/** Free bytes on the location's volume; null when capacity is unknown
|
|
26382
|
+
/** Free bytes on the location's volume; null when capacity is unknown
|
|
26383
|
+
* (remote/unstattable — the recorder logs the statfs failure with the root). */
|
|
26333
26384
|
availableBytes: number().nullable(),
|
|
26334
26385
|
/** Total bytes of the location's volume; null when unknown. */
|
|
26335
26386
|
totalBytes: number().nullable()
|
|
@@ -26341,7 +26392,15 @@ var RecordingStorageUsageSchema = object({
|
|
|
26341
26392
|
nodeId: string(),
|
|
26342
26393
|
totalUsedBytes: number(),
|
|
26343
26394
|
devices: array(RecordingDeviceUsageSchema),
|
|
26344
|
-
|
|
26395
|
+
/**
|
|
26396
|
+
* Per-physical-volume capacity. OPTIONAL, and consumers must render the rest
|
|
26397
|
+
* of the payload without it: the hub serves this method through a BAKED
|
|
26398
|
+
* router, so a hub whose framework train predates a change to this array
|
|
26399
|
+
* strips it out of an answer a newer recorder happily produced. A UI that
|
|
26400
|
+
* dereferences it unconditionally crashes the whole Storage page over a
|
|
26401
|
+
* missing disk bar.
|
|
26402
|
+
*/
|
|
26403
|
+
locations: array(RecordingLocationUsageSchema).optional()
|
|
26345
26404
|
});
|
|
26346
26405
|
/**
|
|
26347
26406
|
* The OPERATOR-ARMED half of multi-location recordings (D116).
|
|
@@ -37126,8 +37185,13 @@ Object.freeze({
|
|
|
37126
37185
|
"network-access": "ingress",
|
|
37127
37186
|
"smtp-provider": "email"
|
|
37128
37187
|
});
|
|
37129
|
-
|
|
37188
|
+
/** Schema defaults — an untouched sub-field must author exactly these. */
|
|
37189
|
+
var NC_AUDIO_DEFAULTS = {
|
|
37190
|
+
hitPercent: 60,
|
|
37191
|
+
samplingSeconds: 10
|
|
37192
|
+
};
|
|
37130
37193
|
new Set(["devices", "classes"]);
|
|
37194
|
+
NC_AUDIO_DEFAULTS.hitPercent, NC_AUDIO_DEFAULTS.samplingSeconds;
|
|
37131
37195
|
/**
|
|
37132
37196
|
* TimelapseRule — the STANDALONE scheduled timelapse producer's rule model.
|
|
37133
37197
|
*
|
|
@@ -37359,6 +37423,39 @@ TimelapseRuleInputSchema.extend({
|
|
|
37359
37423
|
createdAt: number(),
|
|
37360
37424
|
updatedAt: number()
|
|
37361
37425
|
});
|
|
37426
|
+
Object.freeze(Object.fromEntries([{
|
|
37427
|
+
stepId: "face-embedding",
|
|
37428
|
+
label: "Face recognition model",
|
|
37429
|
+
defaultModelId: "arcface-r100",
|
|
37430
|
+
indexName: "the enrolled face gallery",
|
|
37431
|
+
options: [
|
|
37432
|
+
{
|
|
37433
|
+
id: "arcface-r100",
|
|
37434
|
+
label: "ArcFace (ResNet34)"
|
|
37435
|
+
},
|
|
37436
|
+
{
|
|
37437
|
+
id: "auraface-r100",
|
|
37438
|
+
label: "AuraFace R100"
|
|
37439
|
+
},
|
|
37440
|
+
{
|
|
37441
|
+
id: "inception-resnet-v1",
|
|
37442
|
+
label: "Inception ResNet V1"
|
|
37443
|
+
}
|
|
37444
|
+
]
|
|
37445
|
+
}, {
|
|
37446
|
+
stepId: "clip-embedding",
|
|
37447
|
+
label: "Semantic search model",
|
|
37448
|
+
defaultModelId: "mobileclip-s1",
|
|
37449
|
+
indexName: "the object semantic-search index",
|
|
37450
|
+
options: [{
|
|
37451
|
+
id: "mobileclip-s1",
|
|
37452
|
+
label: "MobileCLIP S1"
|
|
37453
|
+
}, {
|
|
37454
|
+
id: "mobileclip-s2",
|
|
37455
|
+
label: "MobileCLIP S2"
|
|
37456
|
+
}]
|
|
37457
|
+
}].map((s) => [s.stepId, s.defaultModelId])));
|
|
37458
|
+
string().min(1);
|
|
37362
37459
|
object({
|
|
37363
37460
|
/**
|
|
37364
37461
|
* Fraction of the box's own size added on EACH side before cutting.
|
|
@@ -37379,10 +37476,21 @@ object({
|
|
|
37379
37476
|
*/
|
|
37380
37477
|
square: boolean()
|
|
37381
37478
|
});
|
|
37382
|
-
|
|
37479
|
+
/**
|
|
37480
|
+
* The convention in force when nobody has configured one — byte-for-byte the
|
|
37481
|
+
* behaviour of the pre-unification LIVE path (`DETAIL_CROP_PADDING_RATIO`).
|
|
37482
|
+
*/
|
|
37483
|
+
var DEFAULT_DETAIL_CROP_CONVENTION = {
|
|
37383
37484
|
paddingRatio: .15,
|
|
37384
37485
|
square: false
|
|
37385
|
-
}
|
|
37486
|
+
};
|
|
37487
|
+
Object.freeze({
|
|
37488
|
+
x: 0,
|
|
37489
|
+
y: 0,
|
|
37490
|
+
w: 1,
|
|
37491
|
+
h: 1
|
|
37492
|
+
});
|
|
37493
|
+
DEFAULT_DETAIL_CROP_CONVENTION.paddingRatio;
|
|
37386
37494
|
/**
|
|
37387
37495
|
* WHICH delivered frames the decode worker retains a native copy of.
|
|
37388
37496
|
*
|
package/dist/addon.mjs
CHANGED
|
@@ -7576,7 +7576,7 @@ var RecordingBandSchema = object({
|
|
|
7576
7576
|
postBufferSec: number().min(0).optional()
|
|
7577
7577
|
});
|
|
7578
7578
|
({
|
|
7579
|
-
preBufferSec:
|
|
7579
|
+
preBufferSec: 15,
|
|
7580
7580
|
postBufferSec: 30
|
|
7581
7581
|
}).postBufferSec * 1e3;
|
|
7582
7582
|
/**
|
|
@@ -13845,128 +13845,103 @@ var COCO_TO_MACRO = {
|
|
|
13845
13845
|
var AUDIO_MACRO_LABELS = [
|
|
13846
13846
|
{
|
|
13847
13847
|
id: "speech",
|
|
13848
|
-
name: "Speech"
|
|
13849
|
-
icon: "🗣️"
|
|
13848
|
+
name: "Speech"
|
|
13850
13849
|
},
|
|
13851
13850
|
{
|
|
13852
13851
|
id: "scream",
|
|
13853
|
-
name: "Scream / Shout"
|
|
13854
|
-
icon: "😱"
|
|
13852
|
+
name: "Scream / Shout"
|
|
13855
13853
|
},
|
|
13856
13854
|
{
|
|
13857
13855
|
id: "crying",
|
|
13858
|
-
name: "Crying / Baby"
|
|
13859
|
-
icon: "😢"
|
|
13856
|
+
name: "Crying / Baby"
|
|
13860
13857
|
},
|
|
13861
13858
|
{
|
|
13862
13859
|
id: "laughter",
|
|
13863
|
-
name: "Laughter"
|
|
13864
|
-
icon: "😂"
|
|
13860
|
+
name: "Laughter"
|
|
13865
13861
|
},
|
|
13866
13862
|
{
|
|
13867
13863
|
id: "music",
|
|
13868
|
-
name: "Music"
|
|
13869
|
-
icon: "🎵"
|
|
13864
|
+
name: "Music"
|
|
13870
13865
|
},
|
|
13871
13866
|
{
|
|
13872
13867
|
id: "dog",
|
|
13873
|
-
name: "Dog"
|
|
13874
|
-
icon: "🐕"
|
|
13868
|
+
name: "Dog"
|
|
13875
13869
|
},
|
|
13876
13870
|
{
|
|
13877
13871
|
id: "cat",
|
|
13878
|
-
name: "Cat"
|
|
13879
|
-
icon: "🐈"
|
|
13872
|
+
name: "Cat"
|
|
13880
13873
|
},
|
|
13881
13874
|
{
|
|
13882
13875
|
id: "bird",
|
|
13883
|
-
name: "Bird"
|
|
13884
|
-
icon: "🐦"
|
|
13876
|
+
name: "Bird"
|
|
13885
13877
|
},
|
|
13886
13878
|
{
|
|
13887
13879
|
id: "animal",
|
|
13888
|
-
name: "Animal (other)"
|
|
13889
|
-
icon: "🐾"
|
|
13880
|
+
name: "Animal (other)"
|
|
13890
13881
|
},
|
|
13891
13882
|
{
|
|
13892
13883
|
id: "alarm",
|
|
13893
|
-
name: "Alarm / Siren"
|
|
13894
|
-
icon: "🚨"
|
|
13884
|
+
name: "Alarm / Siren"
|
|
13895
13885
|
},
|
|
13896
13886
|
{
|
|
13897
13887
|
id: "doorbell",
|
|
13898
|
-
name: "Doorbell / Knock"
|
|
13899
|
-
icon: "🔔"
|
|
13888
|
+
name: "Doorbell / Knock"
|
|
13900
13889
|
},
|
|
13901
13890
|
{
|
|
13902
13891
|
id: "glass_breaking",
|
|
13903
|
-
name: "Glass Breaking"
|
|
13904
|
-
icon: "💥"
|
|
13892
|
+
name: "Glass Breaking"
|
|
13905
13893
|
},
|
|
13906
13894
|
{
|
|
13907
13895
|
id: "gunshot",
|
|
13908
|
-
name: "Gunshot / Explosion"
|
|
13909
|
-
icon: "💣"
|
|
13896
|
+
name: "Gunshot / Explosion"
|
|
13910
13897
|
},
|
|
13911
13898
|
{
|
|
13912
13899
|
id: "vehicle",
|
|
13913
|
-
name: "Vehicle"
|
|
13914
|
-
icon: "🚗"
|
|
13900
|
+
name: "Vehicle"
|
|
13915
13901
|
},
|
|
13916
13902
|
{
|
|
13917
13903
|
id: "siren",
|
|
13918
|
-
name: "Emergency Siren"
|
|
13919
|
-
icon: "🚑"
|
|
13904
|
+
name: "Emergency Siren"
|
|
13920
13905
|
},
|
|
13921
13906
|
{
|
|
13922
13907
|
id: "fire",
|
|
13923
|
-
name: "Fire / Smoke"
|
|
13924
|
-
icon: "🔥"
|
|
13908
|
+
name: "Fire / Smoke"
|
|
13925
13909
|
},
|
|
13926
13910
|
{
|
|
13927
13911
|
id: "water",
|
|
13928
|
-
name: "Water"
|
|
13929
|
-
icon: "💧"
|
|
13912
|
+
name: "Water"
|
|
13930
13913
|
},
|
|
13931
13914
|
{
|
|
13932
13915
|
id: "wind",
|
|
13933
|
-
name: "Wind / Weather"
|
|
13934
|
-
icon: "🌬️"
|
|
13916
|
+
name: "Wind / Weather"
|
|
13935
13917
|
},
|
|
13936
13918
|
{
|
|
13937
13919
|
id: "door",
|
|
13938
|
-
name: "Door"
|
|
13939
|
-
icon: "🚪"
|
|
13920
|
+
name: "Door"
|
|
13940
13921
|
},
|
|
13941
13922
|
{
|
|
13942
13923
|
id: "footsteps",
|
|
13943
|
-
name: "Footsteps"
|
|
13944
|
-
icon: "👣"
|
|
13924
|
+
name: "Footsteps"
|
|
13945
13925
|
},
|
|
13946
13926
|
{
|
|
13947
13927
|
id: "crowd",
|
|
13948
|
-
name: "Crowd / Chatter"
|
|
13949
|
-
icon: "👥"
|
|
13928
|
+
name: "Crowd / Chatter"
|
|
13950
13929
|
},
|
|
13951
13930
|
{
|
|
13952
13931
|
id: "telephone",
|
|
13953
|
-
name: "Telephone"
|
|
13954
|
-
icon: "📞"
|
|
13932
|
+
name: "Telephone"
|
|
13955
13933
|
},
|
|
13956
13934
|
{
|
|
13957
13935
|
id: "engine",
|
|
13958
|
-
name: "Engine / Motor"
|
|
13959
|
-
icon: "⚙️"
|
|
13936
|
+
name: "Engine / Motor"
|
|
13960
13937
|
},
|
|
13961
13938
|
{
|
|
13962
13939
|
id: "tools",
|
|
13963
|
-
name: "Tools / Construction"
|
|
13964
|
-
icon: "🔨"
|
|
13940
|
+
name: "Tools / Construction"
|
|
13965
13941
|
},
|
|
13966
13942
|
{
|
|
13967
13943
|
id: "silence",
|
|
13968
|
-
name: "Silence"
|
|
13969
|
-
icon: "🤫"
|
|
13944
|
+
name: "Silence"
|
|
13970
13945
|
}
|
|
13971
13946
|
];
|
|
13972
13947
|
var YAMNET_TO_MACRO = {
|
|
@@ -16468,7 +16443,7 @@ var TrackEnvelopeSchema = object({
|
|
|
16468
16443
|
* `snapshots[]` references — megabytes across a page of tracks. `slim`
|
|
16469
16444
|
* keeps every scalar the list surfaces actually render (ids, class(es),
|
|
16470
16445
|
* label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
|
|
16471
|
-
* zonesVisited, bestEventId, envelope, hasFace, hasRider) and returns `positions` /
|
|
16446
|
+
* zonesVisited, bestEventId, envelope, hasFace, hasEmbeddedFace, hasRider) and returns `positions` /
|
|
16472
16447
|
* `snapshots` as EMPTY arrays — detail views re-fetch the full row via
|
|
16473
16448
|
* `getTrack`. Mirrors the event-store `projection` convention
|
|
16474
16449
|
* (`getObjectEvents` et al.).
|
|
@@ -16763,6 +16738,35 @@ var TrackSchema = object({
|
|
|
16763
16738
|
*/
|
|
16764
16739
|
hasFace: boolean().optional(),
|
|
16765
16740
|
/**
|
|
16741
|
+
* This track has a face row IN THE GALLERY: a crop **and** an embedding — a
|
|
16742
|
+
* face an operator could ASSIGN to an identity.
|
|
16743
|
+
*
|
|
16744
|
+
* The STRICT twin of {@link hasFace}, and the pair only earns its keep
|
|
16745
|
+
* because the two disagree. `hasFace` is stamped at the TOP of the face
|
|
16746
|
+
* branch, before every gate, and means no more than "a face detector produced
|
|
16747
|
+
* a face detail". This one is stamped at the single moment the gallery row
|
|
16748
|
+
* LANDS — after `FaceRecognizer.onTrackEnd` successfully persists it, i.e.
|
|
16749
|
+
* past the embedding-magnitude verdict, the `minFacePx` detection gate, the
|
|
16750
|
+
* candidate gate, the imageless-track drop (no crop was ever captured) and
|
|
16751
|
+
* the crop-store drop. Everything between the detector and that insert can
|
|
16752
|
+
* legitimately refuse the face, so a flag written any earlier promises the
|
|
16753
|
+
* operator something to assign and delivers nothing.
|
|
16754
|
+
*
|
|
16755
|
+
* **Independent of recognition.** A face collected but never auto-matched is
|
|
16756
|
+
* still assignable — it is in fact the face an operator most wants to reach —
|
|
16757
|
+
* so this is NOT gated on `recognizedIdentityId`. Recognition lands in
|
|
16758
|
+
* `subLabel`; this says only that the raw material exists.
|
|
16759
|
+
*
|
|
16760
|
+
* **Set once, never cleared.** A track that produced a gallery row produced
|
|
16761
|
+
* one; deleting the row later is the gallery's business, not this flag's.
|
|
16762
|
+
*
|
|
16763
|
+
* **Absent ≠ false**, the same rule as {@link hasFace}: every row written
|
|
16764
|
+
* before the column omits it, and so does every server that predates the
|
|
16765
|
+
* field. A consumer must test `=== true` and render nothing otherwise —
|
|
16766
|
+
* never infer "no assignable face".
|
|
16767
|
+
*/
|
|
16768
|
+
hasEmbeddedFace: boolean().optional(),
|
|
16769
|
+
/**
|
|
16766
16770
|
* This subject CONTAINS a folded rider — a person the rider-pairing step
|
|
16767
16771
|
* ([D34](../decisions/adr-0034.md)) removed from the frame BEFORE the tracker,
|
|
16768
16772
|
* so the passage is tracked once and as a VEHICLE.
|
|
@@ -18152,6 +18156,32 @@ var DetailResultSchema = object({
|
|
|
18152
18156
|
/** FRAME-space bbox (already mapped back from crop space). */
|
|
18153
18157
|
bbox: NativeCropBboxSchema.optional(),
|
|
18154
18158
|
embedding: string().optional(),
|
|
18159
|
+
/**
|
|
18160
|
+
* L2 magnitude of the RAW pre-normalization embedding. Additive and optional
|
|
18161
|
+
* so an older runner that does not send it degrades to "unmeasurable", which
|
|
18162
|
+
* the consuming gate treats as accept — never as reject.
|
|
18163
|
+
*/
|
|
18164
|
+
embeddingMagnitude: number().optional(),
|
|
18165
|
+
/**
|
|
18166
|
+
* Model that produced `embedding` — the SAME contract `labelModelId` has for
|
|
18167
|
+
* `label`, and for the same reason: the producing node is the only side that
|
|
18168
|
+
* knows which model actually ran, and re-deriving it downstream is exactly
|
|
18169
|
+
* the inference this model exists to forbid.
|
|
18170
|
+
*
|
|
18171
|
+
* Additive and optional, so a runner that predates it degrades to
|
|
18172
|
+
* "unmeasurable" rather than to a wrong answer — the consumer falls back to
|
|
18173
|
+
* its previous assumption instead of refusing.
|
|
18174
|
+
*
|
|
18175
|
+
* Its absence was not cosmetic. `FaceRecognizer` needs the probe's model id
|
|
18176
|
+
* to use `face-matcher`'s same-model gate (`sample.modelId !== probe.modelId`);
|
|
18177
|
+
* with nothing on the wire it took the id from the GALLERY, so the gate
|
|
18178
|
+
* compared the gallery against itself and could never fire. That turned the
|
|
18179
|
+
* one guard protecting the face feature space into a tautology, and it is
|
|
18180
|
+
* why swapping `face-embedding`'s model would NOT have stranded the enrolled
|
|
18181
|
+
* gallery as the catalog comment predicts — it would have scored the new
|
|
18182
|
+
* model's vectors against the old model's samples in one cosine space.
|
|
18183
|
+
*/
|
|
18184
|
+
embeddingModelId: string().optional(),
|
|
18155
18185
|
label: string().optional(),
|
|
18156
18186
|
/**
|
|
18157
18187
|
* The tier `label` occupies, copied VERBATIM from the producing step's
|
|
@@ -19562,6 +19592,7 @@ DeviceType.Camera, method(object({
|
|
|
19562
19592
|
isBattery: boolean(),
|
|
19563
19593
|
reason: _enum([
|
|
19564
19594
|
"disabled",
|
|
19595
|
+
"offline",
|
|
19565
19596
|
"sleeping",
|
|
19566
19597
|
"unreachable",
|
|
19567
19598
|
"waking"
|
|
@@ -19607,9 +19638,17 @@ targets: array(object({
|
|
|
19607
19638
|
sleeping: boolean(),
|
|
19608
19639
|
/** Current device state rendered over the cached frame. State images
|
|
19609
19640
|
* remain authoritative even when their photographic background is
|
|
19610
|
-
* old; null means the link must carry a current camera frame.
|
|
19641
|
+
* old; null means the link must carry a current camera frame.
|
|
19642
|
+
*
|
|
19643
|
+
* **This is the ONLY source a surface may derive an inactive tile
|
|
19644
|
+
* from.** A client that reads a device's `online`/`disabled` flags and
|
|
19645
|
+
* draws its own verdict will disagree with the pixels it is painting
|
|
19646
|
+
* — the frame comes from here, and so must the sentence over it
|
|
19647
|
+
* (D190). Pair with `ageMs` for the age of the photograph behind the
|
|
19648
|
+
* state. */
|
|
19611
19649
|
stateReason: _enum([
|
|
19612
19650
|
"disabled",
|
|
19651
|
+
"offline",
|
|
19613
19652
|
"sleeping",
|
|
19614
19653
|
"unreachable",
|
|
19615
19654
|
"waking"
|
|
@@ -26328,9 +26367,21 @@ var RecordingLocationUsageSchema = object({
|
|
|
26328
26367
|
* previously rendered as two identical "disks" with a nonsensical used
|
|
26329
26368
|
* split — hydrate attribution across aliases is arbitrary by nature. */
|
|
26330
26369
|
locationIds: array(string()).optional(),
|
|
26331
|
-
/**
|
|
26370
|
+
/**
|
|
26371
|
+
* Filesystem root of the physical volume this row accounts — the only
|
|
26372
|
+
* operator-legible identity when a location has no `displayName` yet, and
|
|
26373
|
+
* what a "which disk is full" alert has to name. OPTIONAL for the same
|
|
26374
|
+
* train-skew reason as `oldestMs`: a recorder that predates the field omits
|
|
26375
|
+
* it, and this schema must keep validating that older provider's payload.
|
|
26376
|
+
*/
|
|
26377
|
+
root: string().optional(),
|
|
26378
|
+
/** Bytes of recordings stored on this PHYSICAL volume (all aliases). This is
|
|
26379
|
+
* the footage's SHARE of the volume, not how full the volume is — the disk
|
|
26380
|
+
* also holds everything that is not recordings. Volume fill is
|
|
26381
|
+
* `(totalBytes - availableBytes) / totalBytes`. */
|
|
26332
26382
|
usedBytes: number(),
|
|
26333
|
-
/** Free bytes on the location's volume; null when capacity is unknown
|
|
26383
|
+
/** Free bytes on the location's volume; null when capacity is unknown
|
|
26384
|
+
* (remote/unstattable — the recorder logs the statfs failure with the root). */
|
|
26334
26385
|
availableBytes: number().nullable(),
|
|
26335
26386
|
/** Total bytes of the location's volume; null when unknown. */
|
|
26336
26387
|
totalBytes: number().nullable()
|
|
@@ -26342,7 +26393,15 @@ var RecordingStorageUsageSchema = object({
|
|
|
26342
26393
|
nodeId: string(),
|
|
26343
26394
|
totalUsedBytes: number(),
|
|
26344
26395
|
devices: array(RecordingDeviceUsageSchema),
|
|
26345
|
-
|
|
26396
|
+
/**
|
|
26397
|
+
* Per-physical-volume capacity. OPTIONAL, and consumers must render the rest
|
|
26398
|
+
* of the payload without it: the hub serves this method through a BAKED
|
|
26399
|
+
* router, so a hub whose framework train predates a change to this array
|
|
26400
|
+
* strips it out of an answer a newer recorder happily produced. A UI that
|
|
26401
|
+
* dereferences it unconditionally crashes the whole Storage page over a
|
|
26402
|
+
* missing disk bar.
|
|
26403
|
+
*/
|
|
26404
|
+
locations: array(RecordingLocationUsageSchema).optional()
|
|
26346
26405
|
});
|
|
26347
26406
|
/**
|
|
26348
26407
|
* The OPERATOR-ARMED half of multi-location recordings (D116).
|
|
@@ -37127,8 +37186,13 @@ Object.freeze({
|
|
|
37127
37186
|
"network-access": "ingress",
|
|
37128
37187
|
"smtp-provider": "email"
|
|
37129
37188
|
});
|
|
37130
|
-
|
|
37189
|
+
/** Schema defaults — an untouched sub-field must author exactly these. */
|
|
37190
|
+
var NC_AUDIO_DEFAULTS = {
|
|
37191
|
+
hitPercent: 60,
|
|
37192
|
+
samplingSeconds: 10
|
|
37193
|
+
};
|
|
37131
37194
|
new Set(["devices", "classes"]);
|
|
37195
|
+
NC_AUDIO_DEFAULTS.hitPercent, NC_AUDIO_DEFAULTS.samplingSeconds;
|
|
37132
37196
|
/**
|
|
37133
37197
|
* TimelapseRule — the STANDALONE scheduled timelapse producer's rule model.
|
|
37134
37198
|
*
|
|
@@ -37360,6 +37424,39 @@ TimelapseRuleInputSchema.extend({
|
|
|
37360
37424
|
createdAt: number(),
|
|
37361
37425
|
updatedAt: number()
|
|
37362
37426
|
});
|
|
37427
|
+
Object.freeze(Object.fromEntries([{
|
|
37428
|
+
stepId: "face-embedding",
|
|
37429
|
+
label: "Face recognition model",
|
|
37430
|
+
defaultModelId: "arcface-r100",
|
|
37431
|
+
indexName: "the enrolled face gallery",
|
|
37432
|
+
options: [
|
|
37433
|
+
{
|
|
37434
|
+
id: "arcface-r100",
|
|
37435
|
+
label: "ArcFace (ResNet34)"
|
|
37436
|
+
},
|
|
37437
|
+
{
|
|
37438
|
+
id: "auraface-r100",
|
|
37439
|
+
label: "AuraFace R100"
|
|
37440
|
+
},
|
|
37441
|
+
{
|
|
37442
|
+
id: "inception-resnet-v1",
|
|
37443
|
+
label: "Inception ResNet V1"
|
|
37444
|
+
}
|
|
37445
|
+
]
|
|
37446
|
+
}, {
|
|
37447
|
+
stepId: "clip-embedding",
|
|
37448
|
+
label: "Semantic search model",
|
|
37449
|
+
defaultModelId: "mobileclip-s1",
|
|
37450
|
+
indexName: "the object semantic-search index",
|
|
37451
|
+
options: [{
|
|
37452
|
+
id: "mobileclip-s1",
|
|
37453
|
+
label: "MobileCLIP S1"
|
|
37454
|
+
}, {
|
|
37455
|
+
id: "mobileclip-s2",
|
|
37456
|
+
label: "MobileCLIP S2"
|
|
37457
|
+
}]
|
|
37458
|
+
}].map((s) => [s.stepId, s.defaultModelId])));
|
|
37459
|
+
string().min(1);
|
|
37363
37460
|
object({
|
|
37364
37461
|
/**
|
|
37365
37462
|
* Fraction of the box's own size added on EACH side before cutting.
|
|
@@ -37380,10 +37477,21 @@ object({
|
|
|
37380
37477
|
*/
|
|
37381
37478
|
square: boolean()
|
|
37382
37479
|
});
|
|
37383
|
-
|
|
37480
|
+
/**
|
|
37481
|
+
* The convention in force when nobody has configured one — byte-for-byte the
|
|
37482
|
+
* behaviour of the pre-unification LIVE path (`DETAIL_CROP_PADDING_RATIO`).
|
|
37483
|
+
*/
|
|
37484
|
+
var DEFAULT_DETAIL_CROP_CONVENTION = {
|
|
37384
37485
|
paddingRatio: .15,
|
|
37385
37486
|
square: false
|
|
37386
|
-
}
|
|
37487
|
+
};
|
|
37488
|
+
Object.freeze({
|
|
37489
|
+
x: 0,
|
|
37490
|
+
y: 0,
|
|
37491
|
+
w: 1,
|
|
37492
|
+
h: 1
|
|
37493
|
+
});
|
|
37494
|
+
DEFAULT_DETAIL_CROP_CONVENTION.paddingRatio;
|
|
37387
37495
|
/**
|
|
37388
37496
|
* WHICH delivered frames the decode worker retains a native copy of.
|
|
37389
37497
|
*
|
package/package.json
CHANGED