@camstack/addon-provider-unifi 0.2.147 → 0.2.148
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/CHANGELOG.md +12 -0
- package/README.md +18 -0
- package/dist/addon.js +959 -509
- package/dist/addon.mjs +959 -509
- package/package.json +4 -2
package/dist/addon.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//#region ../types/dist/event-category-
|
|
1
|
+
//#region ../types/dist/event-category-CT-hz5Rb.mjs
|
|
2
2
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
3
3
|
EventCategory["SystemBoot"] = "system.boot";
|
|
4
4
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -324,6 +324,14 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
324
324
|
/** The recovery edge of {@link PipelineMotionNoisy}: the motion fell back, or a detection arrived. */
|
|
325
325
|
EventCategory["PipelineMotionCalm"] = "pipeline.motion-calm";
|
|
326
326
|
/**
|
|
327
|
+
* A camera's package LLM confirm has failed closed three times in a row
|
|
328
|
+
* (D931, 2026-10-26). One edge per camera until
|
|
329
|
+
* {@link PipelinePackageLlmAnswered}.
|
|
330
|
+
*/
|
|
331
|
+
EventCategory["PipelinePackageLlmSilent"] = "pipeline.package-llm-silent";
|
|
332
|
+
/** The recovery edge of {@link PipelinePackageLlmSilent}: a confirm returned yes or no. */
|
|
333
|
+
EventCategory["PipelinePackageLlmAnswered"] = "pipeline.package-llm-answered";
|
|
334
|
+
/**
|
|
327
335
|
* Per-camera pipeline config was mutated by the orchestrator
|
|
328
336
|
* (a settings change via `setAgentInferenceDevices` /
|
|
329
337
|
* `setCameraStepToggle` / `setCameraStepSettings`). Orchestrator
|
|
@@ -5433,7 +5441,7 @@ var ZodIssueCode = {
|
|
|
5433
5441
|
var ZodFirstPartyTypeKind;
|
|
5434
5442
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5435
5443
|
//#endregion
|
|
5436
|
-
//#region ../types/dist/sleep-
|
|
5444
|
+
//#region ../types/dist/sleep-bykKrTgu.mjs
|
|
5437
5445
|
/**
|
|
5438
5446
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5439
5447
|
* window to float samples (D455).
|
|
@@ -7987,6 +7995,99 @@ var RecordKindDeclarationSchema = object({
|
|
|
7987
7995
|
}).strict();
|
|
7988
7996
|
/** The kind names: lower-case, dash separated, short enough for an index name. */
|
|
7989
7997
|
var RecordKindNameSchema = string().regex(/^[a-z][a-z0-9-]{0,47}$/);
|
|
7998
|
+
var READING_QUANTITIES = [
|
|
7999
|
+
"temperature",
|
|
8000
|
+
"pressure",
|
|
8001
|
+
"speed",
|
|
8002
|
+
"precipitation",
|
|
8003
|
+
"precipitation-rate",
|
|
8004
|
+
"length",
|
|
8005
|
+
"area",
|
|
8006
|
+
"illuminance",
|
|
8007
|
+
"irradiance",
|
|
8008
|
+
"power",
|
|
8009
|
+
"energy",
|
|
8010
|
+
"voltage",
|
|
8011
|
+
"current",
|
|
8012
|
+
"apparent-power",
|
|
8013
|
+
"humidity",
|
|
8014
|
+
"percentage",
|
|
8015
|
+
"concentration-volume",
|
|
8016
|
+
"concentration-mass",
|
|
8017
|
+
"concentration-ppb",
|
|
8018
|
+
"volume",
|
|
8019
|
+
"duration",
|
|
8020
|
+
"duration-ms",
|
|
8021
|
+
"information",
|
|
8022
|
+
"sound-level",
|
|
8023
|
+
"signal-level",
|
|
8024
|
+
"colour-temperature",
|
|
8025
|
+
"angle",
|
|
8026
|
+
"bitrate",
|
|
8027
|
+
"rate",
|
|
8028
|
+
"mass",
|
|
8029
|
+
"index",
|
|
8030
|
+
"ratio",
|
|
8031
|
+
"count",
|
|
8032
|
+
"none",
|
|
8033
|
+
"device"
|
|
8034
|
+
];
|
|
8035
|
+
var ReadingQuantitySchema = _enum(READING_QUANTITIES);
|
|
8036
|
+
new Set(READING_QUANTITIES);
|
|
8037
|
+
/**
|
|
8038
|
+
* Stored unit symbol for a quantity. `none` means the number is dimensionless
|
|
8039
|
+
* (or an index / ratio / count). `device` means the cap has no single unit.
|
|
8040
|
+
*/
|
|
8041
|
+
var QUANTITY_BASE = {
|
|
8042
|
+
temperature: "°C",
|
|
8043
|
+
pressure: "hPa",
|
|
8044
|
+
speed: "m/s",
|
|
8045
|
+
precipitation: "mm",
|
|
8046
|
+
"precipitation-rate": "mm/h",
|
|
8047
|
+
length: "m",
|
|
8048
|
+
area: "m²",
|
|
8049
|
+
illuminance: "lx",
|
|
8050
|
+
irradiance: "W/m²",
|
|
8051
|
+
power: "W",
|
|
8052
|
+
energy: "kWh",
|
|
8053
|
+
voltage: "V",
|
|
8054
|
+
current: "A",
|
|
8055
|
+
"apparent-power": "VA",
|
|
8056
|
+
humidity: "%",
|
|
8057
|
+
percentage: "%",
|
|
8058
|
+
"concentration-volume": "ppm",
|
|
8059
|
+
"concentration-mass": "µg/m³",
|
|
8060
|
+
"concentration-ppb": "ppb",
|
|
8061
|
+
volume: "L",
|
|
8062
|
+
duration: "s",
|
|
8063
|
+
"duration-ms": "ms",
|
|
8064
|
+
information: "B",
|
|
8065
|
+
"sound-level": "dBFS",
|
|
8066
|
+
"signal-level": "dBm",
|
|
8067
|
+
"colour-temperature": "mired",
|
|
8068
|
+
angle: "°",
|
|
8069
|
+
bitrate: "kbps",
|
|
8070
|
+
rate: "fps",
|
|
8071
|
+
mass: "kg",
|
|
8072
|
+
index: "none",
|
|
8073
|
+
ratio: "none",
|
|
8074
|
+
count: "none",
|
|
8075
|
+
none: "none",
|
|
8076
|
+
device: "device"
|
|
8077
|
+
};
|
|
8078
|
+
/** The stored unit, or `undefined` when the quantity has no unit symbol. */
|
|
8079
|
+
function baseUnitOf(quantity) {
|
|
8080
|
+
const symbol = QUANTITY_BASE[quantity];
|
|
8081
|
+
if (symbol === "none" || symbol === "device") return void 0;
|
|
8082
|
+
return symbol;
|
|
8083
|
+
}
|
|
8084
|
+
function readingMeta(quantity, extras) {
|
|
8085
|
+
return {
|
|
8086
|
+
quantity,
|
|
8087
|
+
...extras?.precision !== void 0 ? { precision: extras.precision } : {},
|
|
8088
|
+
...extras?.label !== void 0 ? { label: extras.label } : {}
|
|
8089
|
+
};
|
|
8090
|
+
}
|
|
7990
8091
|
/** Shared Zod schemas used across streaming capabilities. */
|
|
7991
8092
|
var CamProfileSchema = _enum([
|
|
7992
8093
|
"high",
|
|
@@ -8014,8 +8115,8 @@ var CamStreamKindSchema = _enum([
|
|
|
8014
8115
|
"derived"
|
|
8015
8116
|
]);
|
|
8016
8117
|
var CamStreamResolutionSchema = object({
|
|
8017
|
-
width: number().int().positive(),
|
|
8018
|
-
height: number().int().positive()
|
|
8118
|
+
width: number().int().positive().meta(readingMeta("none")),
|
|
8119
|
+
height: number().int().positive().meta(readingMeta("none"))
|
|
8019
8120
|
});
|
|
8020
8121
|
var CameraStreamSchema = object({
|
|
8021
8122
|
/** Stable, provider-assigned id unique within the (deviceId) scope. */
|
|
@@ -8533,6 +8634,8 @@ var CAP_NAMES = Object.freeze([
|
|
|
8533
8634
|
"filesystem-browse",
|
|
8534
8635
|
"flood",
|
|
8535
8636
|
"gas",
|
|
8637
|
+
"group-commands",
|
|
8638
|
+
"group-status",
|
|
8536
8639
|
"heating-valve",
|
|
8537
8640
|
"humidifier",
|
|
8538
8641
|
"humidity-sensor",
|
|
@@ -8662,14 +8765,6 @@ Object.freeze({
|
|
|
8662
8765
|
{
|
|
8663
8766
|
"path": "aqi",
|
|
8664
8767
|
"valueType": "number"
|
|
8665
|
-
},
|
|
8666
|
-
{
|
|
8667
|
-
"path": "unit",
|
|
8668
|
-
"valueType": "string"
|
|
8669
|
-
},
|
|
8670
|
-
{
|
|
8671
|
-
"path": "precision",
|
|
8672
|
-
"valueType": "number"
|
|
8673
8768
|
}
|
|
8674
8769
|
],
|
|
8675
8770
|
"alarm-panel": [
|
|
@@ -8705,20 +8800,10 @@ Object.freeze({
|
|
|
8705
8800
|
"valueType": "boolean"
|
|
8706
8801
|
}
|
|
8707
8802
|
],
|
|
8708
|
-
"ambient-light-sensor": [
|
|
8709
|
-
|
|
8710
|
-
|
|
8711
|
-
|
|
8712
|
-
},
|
|
8713
|
-
{
|
|
8714
|
-
"path": "unit",
|
|
8715
|
-
"valueType": "string"
|
|
8716
|
-
},
|
|
8717
|
-
{
|
|
8718
|
-
"path": "precision",
|
|
8719
|
-
"valueType": "number"
|
|
8720
|
-
}
|
|
8721
|
-
],
|
|
8803
|
+
"ambient-light-sensor": [{
|
|
8804
|
+
"path": "lux",
|
|
8805
|
+
"valueType": "number"
|
|
8806
|
+
}],
|
|
8722
8807
|
"audio-metrics": [
|
|
8723
8808
|
{
|
|
8724
8809
|
"path": "ts",
|
|
@@ -8798,6 +8883,10 @@ Object.freeze({
|
|
|
8798
8883
|
"path": "lastUpdated",
|
|
8799
8884
|
"valueType": "number"
|
|
8800
8885
|
},
|
|
8886
|
+
{
|
|
8887
|
+
"path": "volts",
|
|
8888
|
+
"valueType": "number"
|
|
8889
|
+
},
|
|
8801
8890
|
{
|
|
8802
8891
|
"path": "lastContactAt",
|
|
8803
8892
|
"valueType": "number"
|
|
@@ -9040,10 +9129,6 @@ Object.freeze({
|
|
|
9040
9129
|
"datetime"
|
|
9041
9130
|
]
|
|
9042
9131
|
},
|
|
9043
|
-
{
|
|
9044
|
-
"path": "unit",
|
|
9045
|
-
"valueType": "string"
|
|
9046
|
-
},
|
|
9047
9132
|
{
|
|
9048
9133
|
"path": "min",
|
|
9049
9134
|
"valueType": "number"
|
|
@@ -9055,19 +9140,6 @@ Object.freeze({
|
|
|
9055
9140
|
{
|
|
9056
9141
|
"path": "step",
|
|
9057
9142
|
"valueType": "number"
|
|
9058
|
-
},
|
|
9059
|
-
{
|
|
9060
|
-
"path": "precision",
|
|
9061
|
-
"valueType": "number"
|
|
9062
|
-
},
|
|
9063
|
-
{
|
|
9064
|
-
"path": "format",
|
|
9065
|
-
"valueType": "enum",
|
|
9066
|
-
"enumValues": [
|
|
9067
|
-
"date",
|
|
9068
|
-
"time",
|
|
9069
|
-
"datetime"
|
|
9070
|
-
]
|
|
9071
9143
|
}
|
|
9072
9144
|
],
|
|
9073
9145
|
"cover": [
|
|
@@ -9308,13 +9380,8 @@ Object.freeze({
|
|
|
9308
9380
|
"path": "value",
|
|
9309
9381
|
"valueType": "string"
|
|
9310
9382
|
}, {
|
|
9311
|
-
"path": "
|
|
9312
|
-
"valueType": "
|
|
9313
|
-
"enumValues": [
|
|
9314
|
-
"date",
|
|
9315
|
-
"time",
|
|
9316
|
-
"datetime"
|
|
9317
|
-
]
|
|
9383
|
+
"path": "timestamp",
|
|
9384
|
+
"valueType": "boolean"
|
|
9318
9385
|
}],
|
|
9319
9386
|
"event-emitter": [
|
|
9320
9387
|
{
|
|
@@ -9387,6 +9454,20 @@ Object.freeze({
|
|
|
9387
9454
|
"path": "detected",
|
|
9388
9455
|
"valueType": "boolean"
|
|
9389
9456
|
}],
|
|
9457
|
+
"group-status": [
|
|
9458
|
+
{
|
|
9459
|
+
"path": "included",
|
|
9460
|
+
"valueType": "number"
|
|
9461
|
+
},
|
|
9462
|
+
{
|
|
9463
|
+
"path": "excluded",
|
|
9464
|
+
"valueType": "number"
|
|
9465
|
+
},
|
|
9466
|
+
{
|
|
9467
|
+
"path": "total",
|
|
9468
|
+
"valueType": "number"
|
|
9469
|
+
}
|
|
9470
|
+
],
|
|
9390
9471
|
"heating-valve": [{
|
|
9391
9472
|
"path": "position",
|
|
9392
9473
|
"valueType": "number"
|
|
@@ -9421,20 +9502,10 @@ Object.freeze({
|
|
|
9421
9502
|
"valueType": "number"
|
|
9422
9503
|
}
|
|
9423
9504
|
],
|
|
9424
|
-
"humidity-sensor": [
|
|
9425
|
-
|
|
9426
|
-
|
|
9427
|
-
|
|
9428
|
-
},
|
|
9429
|
-
{
|
|
9430
|
-
"path": "unit",
|
|
9431
|
-
"valueType": "string"
|
|
9432
|
-
},
|
|
9433
|
-
{
|
|
9434
|
-
"path": "precision",
|
|
9435
|
-
"valueType": "number"
|
|
9436
|
-
}
|
|
9437
|
-
],
|
|
9505
|
+
"humidity-sensor": [{
|
|
9506
|
+
"path": "percent",
|
|
9507
|
+
"valueType": "number"
|
|
9508
|
+
}],
|
|
9438
9509
|
"image": [{
|
|
9439
9510
|
"path": "url",
|
|
9440
9511
|
"valueType": "string"
|
|
@@ -9773,20 +9844,10 @@ Object.freeze({
|
|
|
9773
9844
|
"valueType": "boolean"
|
|
9774
9845
|
}
|
|
9775
9846
|
],
|
|
9776
|
-
"numeric-sensor": [
|
|
9777
|
-
|
|
9778
|
-
|
|
9779
|
-
|
|
9780
|
-
},
|
|
9781
|
-
{
|
|
9782
|
-
"path": "unit",
|
|
9783
|
-
"valueType": "string"
|
|
9784
|
-
},
|
|
9785
|
-
{
|
|
9786
|
-
"path": "precision",
|
|
9787
|
-
"valueType": "number"
|
|
9788
|
-
}
|
|
9789
|
-
],
|
|
9847
|
+
"numeric-sensor": [{
|
|
9848
|
+
"path": "value",
|
|
9849
|
+
"valueType": "number"
|
|
9850
|
+
}],
|
|
9790
9851
|
"pet-feeder": [
|
|
9791
9852
|
{
|
|
9792
9853
|
"path": "foodLevel",
|
|
@@ -9878,14 +9939,6 @@ Object.freeze({
|
|
|
9878
9939
|
{
|
|
9879
9940
|
"path": "powerFactor",
|
|
9880
9941
|
"valueType": "number"
|
|
9881
|
-
},
|
|
9882
|
-
{
|
|
9883
|
-
"path": "unit",
|
|
9884
|
-
"valueType": "string"
|
|
9885
|
-
},
|
|
9886
|
-
{
|
|
9887
|
-
"path": "precision",
|
|
9888
|
-
"valueType": "number"
|
|
9889
9942
|
}
|
|
9890
9943
|
],
|
|
9891
9944
|
"presence": [
|
|
@@ -9914,20 +9967,10 @@ Object.freeze({
|
|
|
9914
9967
|
"valueType": "number"
|
|
9915
9968
|
}
|
|
9916
9969
|
],
|
|
9917
|
-
"pressure-sensor": [
|
|
9918
|
-
|
|
9919
|
-
|
|
9920
|
-
|
|
9921
|
-
},
|
|
9922
|
-
{
|
|
9923
|
-
"path": "unit",
|
|
9924
|
-
"valueType": "string"
|
|
9925
|
-
},
|
|
9926
|
-
{
|
|
9927
|
-
"path": "precision",
|
|
9928
|
-
"valueType": "number"
|
|
9929
|
-
}
|
|
9930
|
-
],
|
|
9970
|
+
"pressure-sensor": [{
|
|
9971
|
+
"path": "hpa",
|
|
9972
|
+
"valueType": "number"
|
|
9973
|
+
}],
|
|
9931
9974
|
"privacy-mask": [{
|
|
9932
9975
|
"path": "enabled",
|
|
9933
9976
|
"valueType": "boolean"
|
|
@@ -10238,20 +10281,10 @@ Object.freeze({
|
|
|
10238
10281
|
"path": "tampered",
|
|
10239
10282
|
"valueType": "boolean"
|
|
10240
10283
|
}],
|
|
10241
|
-
"temperature-sensor": [
|
|
10242
|
-
|
|
10243
|
-
|
|
10244
|
-
|
|
10245
|
-
},
|
|
10246
|
-
{
|
|
10247
|
-
"path": "unit",
|
|
10248
|
-
"valueType": "string"
|
|
10249
|
-
},
|
|
10250
|
-
{
|
|
10251
|
-
"path": "precision",
|
|
10252
|
-
"valueType": "number"
|
|
10253
|
-
}
|
|
10254
|
-
],
|
|
10284
|
+
"temperature-sensor": [{
|
|
10285
|
+
"path": "celsius",
|
|
10286
|
+
"valueType": "number"
|
|
10287
|
+
}],
|
|
10255
10288
|
"update": [
|
|
10256
10289
|
{
|
|
10257
10290
|
"path": "currentVersion",
|
|
@@ -10362,10 +10395,6 @@ Object.freeze({
|
|
|
10362
10395
|
"path": "temperature",
|
|
10363
10396
|
"valueType": "number"
|
|
10364
10397
|
},
|
|
10365
|
-
{
|
|
10366
|
-
"path": "temperatureUnit",
|
|
10367
|
-
"valueType": "string"
|
|
10368
|
-
},
|
|
10369
10398
|
{
|
|
10370
10399
|
"path": "humidity",
|
|
10371
10400
|
"valueType": "number"
|
|
@@ -10374,18 +10403,10 @@ Object.freeze({
|
|
|
10374
10403
|
"path": "pressure",
|
|
10375
10404
|
"valueType": "number"
|
|
10376
10405
|
},
|
|
10377
|
-
{
|
|
10378
|
-
"path": "pressureUnit",
|
|
10379
|
-
"valueType": "string"
|
|
10380
|
-
},
|
|
10381
10406
|
{
|
|
10382
10407
|
"path": "windSpeed",
|
|
10383
10408
|
"valueType": "number"
|
|
10384
10409
|
},
|
|
10385
|
-
{
|
|
10386
|
-
"path": "windSpeedUnit",
|
|
10387
|
-
"valueType": "string"
|
|
10388
|
-
},
|
|
10389
10410
|
{
|
|
10390
10411
|
"path": "windBearing",
|
|
10391
10412
|
"valueType": "number"
|
|
@@ -10802,7 +10823,7 @@ function errMsg(err) {
|
|
|
10802
10823
|
return String(err);
|
|
10803
10824
|
}
|
|
10804
10825
|
//#endregion
|
|
10805
|
-
//#region ../types/dist/composition-
|
|
10826
|
+
//#region ../types/dist/composition-OhpuespA.mjs
|
|
10806
10827
|
/**
|
|
10807
10828
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
10808
10829
|
*
|
|
@@ -11557,15 +11578,74 @@ function validateExpressionSource(src) {
|
|
|
11557
11578
|
}
|
|
11558
11579
|
return null;
|
|
11559
11580
|
}
|
|
11560
|
-
/**
|
|
11561
|
-
|
|
11562
|
-
|
|
11563
|
-
|
|
11581
|
+
/**
|
|
11582
|
+
* A composition source identity: `(addonId, stableId)`, never a numeric device
|
|
11583
|
+
* id. Split out so helper schemas can name it without a cycle through
|
|
11584
|
+
* `composition.ts` (D659).
|
|
11585
|
+
*/
|
|
11564
11586
|
var CompositionSourceRefSchema = object({
|
|
11565
11587
|
/** The owning addon; `stableId` is unique only within it. */
|
|
11566
11588
|
addonId: string().min(1),
|
|
11567
11589
|
stableId: string().min(1)
|
|
11568
11590
|
});
|
|
11591
|
+
var GROUP_TEMPLATE_IDS = [
|
|
11592
|
+
"temperature",
|
|
11593
|
+
"humidity",
|
|
11594
|
+
"pressure",
|
|
11595
|
+
"illuminance",
|
|
11596
|
+
"power",
|
|
11597
|
+
"energy",
|
|
11598
|
+
"battery",
|
|
11599
|
+
"numeric",
|
|
11600
|
+
"motion",
|
|
11601
|
+
"contact",
|
|
11602
|
+
"leak",
|
|
11603
|
+
"smoke",
|
|
11604
|
+
"occupancy",
|
|
11605
|
+
"binary",
|
|
11606
|
+
"switch",
|
|
11607
|
+
"light"
|
|
11608
|
+
];
|
|
11609
|
+
var NUMERIC_AGGREGATES = [
|
|
11610
|
+
"mean",
|
|
11611
|
+
"median",
|
|
11612
|
+
"min",
|
|
11613
|
+
"max",
|
|
11614
|
+
"sum"
|
|
11615
|
+
];
|
|
11616
|
+
var BINARY_AGGREGATES = ["any", "all"];
|
|
11617
|
+
/** How an actuator group decides it is on. Unknown members never count as off. */
|
|
11618
|
+
var ACTIVE_CRITERIA = ["at-least-one", "all"];
|
|
11619
|
+
var AGGREGATE_REDUCERS = [
|
|
11620
|
+
"mean",
|
|
11621
|
+
"median",
|
|
11622
|
+
"min",
|
|
11623
|
+
"max",
|
|
11624
|
+
"sum",
|
|
11625
|
+
"any",
|
|
11626
|
+
"all"
|
|
11627
|
+
];
|
|
11628
|
+
var GroupTemplateIdSchema = _enum(GROUP_TEMPLATE_IDS);
|
|
11629
|
+
var AggregateReducerSchema = _enum(AGGREGATE_REDUCERS);
|
|
11630
|
+
var ActiveCriterionSchema = _enum(ACTIVE_CRITERIA);
|
|
11631
|
+
/** One member. The field is stored so occupancy can name motion or binary. */
|
|
11632
|
+
var HelperMemberSchema = object({
|
|
11633
|
+
source: CompositionSourceRefSchema,
|
|
11634
|
+
cap: string().min(1),
|
|
11635
|
+
fieldPath: string().min(1)
|
|
11636
|
+
});
|
|
11637
|
+
var HelperSpecSchema = discriminatedUnion("kind", [object({
|
|
11638
|
+
kind: literal("group"),
|
|
11639
|
+
templateId: GroupTemplateIdSchema,
|
|
11640
|
+
aggregate: AggregateReducerSchema,
|
|
11641
|
+
members: array(HelperMemberSchema).min(1).max(64),
|
|
11642
|
+
/** Actuator groups only. Readings leave this unset. */
|
|
11643
|
+
active: ActiveCriterionSchema.optional()
|
|
11644
|
+
})]);
|
|
11645
|
+
/** A composed device's stableId is this prefix plus the block id. */
|
|
11646
|
+
var COMPOSED_DEVICE_STABLE_ID_PREFIX = "composed-";
|
|
11647
|
+
/** Longest snippet a `code` source may carry (slice 4). */
|
|
11648
|
+
var MAX_COMPOSITION_CODE_LENGTH = 2e4;
|
|
11569
11649
|
/** One field of one capability of one source device. */
|
|
11570
11650
|
var CompositionFieldReadSchema = object({
|
|
11571
11651
|
source: CompositionSourceRefSchema,
|
|
@@ -11609,7 +11689,33 @@ var CompositionCodeSourceSchema = object({
|
|
|
11609
11689
|
var CompositionFieldSourceSchema = discriminatedUnion("kind", [
|
|
11610
11690
|
CompositionFromSourceSchema,
|
|
11611
11691
|
CompositionExpressionSourceSchema,
|
|
11612
|
-
CompositionCodeSourceSchema
|
|
11692
|
+
CompositionCodeSourceSchema,
|
|
11693
|
+
object({
|
|
11694
|
+
kind: literal("aggregate"),
|
|
11695
|
+
reducer: _enum([
|
|
11696
|
+
"mean",
|
|
11697
|
+
"median",
|
|
11698
|
+
"min",
|
|
11699
|
+
"max",
|
|
11700
|
+
"sum",
|
|
11701
|
+
"any",
|
|
11702
|
+
"all"
|
|
11703
|
+
]),
|
|
11704
|
+
reads: array(CompositionFieldReadSchema).min(1).max(64),
|
|
11705
|
+
/** `value` is the reading; the others are the member counts. */
|
|
11706
|
+
publish: _enum([
|
|
11707
|
+
"value",
|
|
11708
|
+
"included",
|
|
11709
|
+
"excluded",
|
|
11710
|
+
"total"
|
|
11711
|
+
]),
|
|
11712
|
+
/** What a `value` publish does when nobody is included. Counts ignore this. */
|
|
11713
|
+
empty: _enum([
|
|
11714
|
+
"null",
|
|
11715
|
+
"omit",
|
|
11716
|
+
"offline"
|
|
11717
|
+
])
|
|
11718
|
+
})
|
|
11613
11719
|
]);
|
|
11614
11720
|
var CompositionCommandTargetSchema = discriminatedUnion("kind", [object({
|
|
11615
11721
|
kind: literal("forward"),
|
|
@@ -11655,7 +11761,13 @@ var CompositionSchema = object({
|
|
|
11655
11761
|
kind: literal("existing"),
|
|
11656
11762
|
device: CompositionSourceRefSchema
|
|
11657
11763
|
})]),
|
|
11658
|
-
features: array(CompositionFeatureSchema).min(1).max(16)
|
|
11764
|
+
features: array(CompositionFeatureSchema).min(1).max(16),
|
|
11765
|
+
/**
|
|
11766
|
+
* Present when the block is a helper template. Absent on a free
|
|
11767
|
+
* composition (the room example, device 4603). The editor reads this,
|
|
11768
|
+
* never the compiled features.
|
|
11769
|
+
*/
|
|
11770
|
+
helper: HelperSpecSchema.optional()
|
|
11659
11771
|
}).superRefine((composition, ctx) => {
|
|
11660
11772
|
const seen = /* @__PURE__ */ new Set();
|
|
11661
11773
|
composition.features.forEach((feature, index) => {
|
|
@@ -17863,7 +17975,11 @@ var CompositionProblemSchema = object({
|
|
|
17863
17975
|
"item-field-reserved",
|
|
17864
17976
|
"target-missing",
|
|
17865
17977
|
"target-unreadable",
|
|
17866
|
-
"not-replaceable"
|
|
17978
|
+
"not-replaceable",
|
|
17979
|
+
"native-capability-replace",
|
|
17980
|
+
"mixed-quantity",
|
|
17981
|
+
"helper-mismatch",
|
|
17982
|
+
"member-constraint"
|
|
17867
17983
|
]),
|
|
17868
17984
|
path: string(),
|
|
17869
17985
|
message: string()
|
|
@@ -17884,7 +18000,8 @@ var CompositionUnavailableModeSchema = _enum([
|
|
|
17884
18000
|
"null",
|
|
17885
18001
|
"offline",
|
|
17886
18002
|
"unknown",
|
|
17887
|
-
"release"
|
|
18003
|
+
"release",
|
|
18004
|
+
"omit"
|
|
17888
18005
|
]);
|
|
17889
18006
|
/**
|
|
17890
18007
|
* `derived` reads a source · `clock` reads only `now`, recomputed when a sibling
|
|
@@ -17921,9 +18038,11 @@ var CompositionFieldPlanSchema = object({
|
|
|
17921
18038
|
reads: array(CompositionFieldReadSchema)
|
|
17922
18039
|
});
|
|
17923
18040
|
/**
|
|
17924
|
-
* What a feature does to its target (D663): `new` builds a capability on a
|
|
17925
|
-
* device; on an existing device it `add`s a capability the device lacks
|
|
17926
|
-
*
|
|
18041
|
+
* What a feature does to its target (D663, D944): `new` builds a capability on a
|
|
18042
|
+
* new device; on an existing device it `add`s a capability the device lacks.
|
|
18043
|
+
* Replacing a capability the device already serves is refused
|
|
18044
|
+
* (`native-capability-replace`), not planned. `replace` remains on the claim
|
|
18045
|
+
* wire for a claim the hub already holds.
|
|
17927
18046
|
*/
|
|
17928
18047
|
var CompositionFeatureModeSchema = _enum([
|
|
17929
18048
|
"new",
|
|
@@ -18096,6 +18215,275 @@ Object.freeze({
|
|
|
18096
18215
|
result: ["number", "null"]
|
|
18097
18216
|
}
|
|
18098
18217
|
});
|
|
18218
|
+
/**
|
|
18219
|
+
* One catalog row per base reading a group helper can build (D944 §3).
|
|
18220
|
+
* Data, not a form default written into the block.
|
|
18221
|
+
*/
|
|
18222
|
+
var NOW = {
|
|
18223
|
+
fieldPath: "lastFetchedAt",
|
|
18224
|
+
expr: "now"
|
|
18225
|
+
};
|
|
18226
|
+
var CHANGED = {
|
|
18227
|
+
fieldPath: "lastChangedAt",
|
|
18228
|
+
expr: "now"
|
|
18229
|
+
};
|
|
18230
|
+
function numeric(input) {
|
|
18231
|
+
return {
|
|
18232
|
+
...input,
|
|
18233
|
+
family: "numeric",
|
|
18234
|
+
deviceType: DeviceType.Sensor,
|
|
18235
|
+
memberDeviceType: DeviceType.Sensor,
|
|
18236
|
+
commandCaps: [],
|
|
18237
|
+
baseUnit: baseUnitOf(input.quantity),
|
|
18238
|
+
aggregates: NUMERIC_AGGREGATES,
|
|
18239
|
+
accept: [{
|
|
18240
|
+
cap: input.outputCap,
|
|
18241
|
+
fieldPath: input.outputField
|
|
18242
|
+
}]
|
|
18243
|
+
};
|
|
18244
|
+
}
|
|
18245
|
+
function binary(input) {
|
|
18246
|
+
return {
|
|
18247
|
+
...input,
|
|
18248
|
+
family: "binary",
|
|
18249
|
+
deviceType: DeviceType.Sensor,
|
|
18250
|
+
memberDeviceType: DeviceType.Sensor,
|
|
18251
|
+
commandCaps: [],
|
|
18252
|
+
quantity: "none",
|
|
18253
|
+
baseUnit: void 0,
|
|
18254
|
+
aggregates: BINARY_AGGREGATES,
|
|
18255
|
+
empty: "offline"
|
|
18256
|
+
};
|
|
18257
|
+
}
|
|
18258
|
+
var GROUP_TEMPLATES = [
|
|
18259
|
+
numeric({
|
|
18260
|
+
id: "temperature",
|
|
18261
|
+
summary: "Mean, median, min, max or sum of temperatures. Offline and unknown members are left out, never read as 0 °C.",
|
|
18262
|
+
role: DeviceRole.TemperatureSensor,
|
|
18263
|
+
outputCap: "temperature-sensor",
|
|
18264
|
+
outputField: "celsius",
|
|
18265
|
+
quantity: "temperature",
|
|
18266
|
+
defaultAggregate: "mean",
|
|
18267
|
+
empty: "null",
|
|
18268
|
+
companions: [NOW]
|
|
18269
|
+
}),
|
|
18270
|
+
numeric({
|
|
18271
|
+
id: "humidity",
|
|
18272
|
+
summary: "Humidity in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
18273
|
+
role: DeviceRole.HumiditySensor,
|
|
18274
|
+
outputCap: "humidity-sensor",
|
|
18275
|
+
outputField: "percent",
|
|
18276
|
+
quantity: "humidity",
|
|
18277
|
+
defaultAggregate: "mean",
|
|
18278
|
+
empty: "null",
|
|
18279
|
+
companions: [NOW]
|
|
18280
|
+
}),
|
|
18281
|
+
numeric({
|
|
18282
|
+
id: "pressure",
|
|
18283
|
+
summary: "Pressure in hectopascals. Offline and unknown members are left out, never read as 0 hPa.",
|
|
18284
|
+
role: DeviceRole.PressureSensor,
|
|
18285
|
+
outputCap: "pressure-sensor",
|
|
18286
|
+
outputField: "hpa",
|
|
18287
|
+
quantity: "pressure",
|
|
18288
|
+
defaultAggregate: "mean",
|
|
18289
|
+
empty: "null",
|
|
18290
|
+
companions: [NOW]
|
|
18291
|
+
}),
|
|
18292
|
+
numeric({
|
|
18293
|
+
id: "illuminance",
|
|
18294
|
+
summary: "Illuminance in lux. Offline and unknown members are left out, never read as 0 lx.",
|
|
18295
|
+
role: DeviceRole.AmbientLightSensor,
|
|
18296
|
+
outputCap: "ambient-light-sensor",
|
|
18297
|
+
outputField: "lux",
|
|
18298
|
+
quantity: "illuminance",
|
|
18299
|
+
defaultAggregate: "mean",
|
|
18300
|
+
empty: "null",
|
|
18301
|
+
companions: [NOW]
|
|
18302
|
+
}),
|
|
18303
|
+
numeric({
|
|
18304
|
+
id: "power",
|
|
18305
|
+
summary: "Power in watts, summed by default. Nobody reporting omits the key rather than writing 0 W.",
|
|
18306
|
+
role: DeviceRole.PowerSensor,
|
|
18307
|
+
outputCap: "power-meter",
|
|
18308
|
+
outputField: "watts",
|
|
18309
|
+
quantity: "power",
|
|
18310
|
+
defaultAggregate: "sum",
|
|
18311
|
+
empty: "omit",
|
|
18312
|
+
companions: [NOW]
|
|
18313
|
+
}),
|
|
18314
|
+
numeric({
|
|
18315
|
+
id: "energy",
|
|
18316
|
+
summary: "Energy in kilowatt-hours, summed by default. Nobody reporting omits the key rather than writing 0 kWh.",
|
|
18317
|
+
role: DeviceRole.EnergySensor,
|
|
18318
|
+
outputCap: "power-meter",
|
|
18319
|
+
outputField: "kwhTotal",
|
|
18320
|
+
quantity: "energy",
|
|
18321
|
+
defaultAggregate: "sum",
|
|
18322
|
+
empty: "omit",
|
|
18323
|
+
companions: [NOW]
|
|
18324
|
+
}),
|
|
18325
|
+
numeric({
|
|
18326
|
+
id: "battery",
|
|
18327
|
+
summary: "Battery charge in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
18328
|
+
role: DeviceRole.BatterySensor,
|
|
18329
|
+
outputCap: "battery",
|
|
18330
|
+
outputField: "percentage",
|
|
18331
|
+
quantity: "percentage",
|
|
18332
|
+
defaultAggregate: "mean",
|
|
18333
|
+
empty: "null",
|
|
18334
|
+
companions: [
|
|
18335
|
+
{
|
|
18336
|
+
fieldPath: "charging",
|
|
18337
|
+
expr: "\"unknown\""
|
|
18338
|
+
},
|
|
18339
|
+
{
|
|
18340
|
+
fieldPath: "sleeping",
|
|
18341
|
+
expr: "false"
|
|
18342
|
+
},
|
|
18343
|
+
{
|
|
18344
|
+
fieldPath: "lastUpdated",
|
|
18345
|
+
expr: "now"
|
|
18346
|
+
}
|
|
18347
|
+
]
|
|
18348
|
+
}),
|
|
18349
|
+
numeric({
|
|
18350
|
+
id: "numeric",
|
|
18351
|
+
summary: "A numeric reading in the members’ shared quantity. Mixed quantities are refused. Nobody reporting publishes null, not 0.",
|
|
18352
|
+
role: DeviceRole.NumericSensor,
|
|
18353
|
+
outputCap: "numeric-sensor",
|
|
18354
|
+
outputField: "value",
|
|
18355
|
+
quantity: "device",
|
|
18356
|
+
defaultAggregate: "mean",
|
|
18357
|
+
empty: "null",
|
|
18358
|
+
companions: [NOW]
|
|
18359
|
+
}),
|
|
18360
|
+
binary({
|
|
18361
|
+
id: "motion",
|
|
18362
|
+
summary: "Any or all motion. Offline and unknown members are left out, never read as off. Nobody reporting takes the device offline.",
|
|
18363
|
+
role: DeviceRole.MotionSensor,
|
|
18364
|
+
outputCap: "motion",
|
|
18365
|
+
outputField: "detected",
|
|
18366
|
+
defaultAggregate: "any",
|
|
18367
|
+
accept: [{
|
|
18368
|
+
cap: "motion",
|
|
18369
|
+
fieldPath: "detected"
|
|
18370
|
+
}],
|
|
18371
|
+
companions: [{
|
|
18372
|
+
fieldPath: "lastDetectedAt",
|
|
18373
|
+
expr: "null"
|
|
18374
|
+
}, {
|
|
18375
|
+
fieldPath: "autoClearAfterMs",
|
|
18376
|
+
expr: "null"
|
|
18377
|
+
}]
|
|
18378
|
+
}),
|
|
18379
|
+
binary({
|
|
18380
|
+
id: "contact",
|
|
18381
|
+
summary: "Any or all open contacts. Offline and unknown members are left out, never read as closed.",
|
|
18382
|
+
role: DeviceRole.ContactSensor,
|
|
18383
|
+
outputCap: "contact",
|
|
18384
|
+
outputField: "entryOpen",
|
|
18385
|
+
defaultAggregate: "any",
|
|
18386
|
+
accept: [{
|
|
18387
|
+
cap: "contact",
|
|
18388
|
+
fieldPath: "entryOpen"
|
|
18389
|
+
}],
|
|
18390
|
+
companions: [CHANGED]
|
|
18391
|
+
}),
|
|
18392
|
+
binary({
|
|
18393
|
+
id: "leak",
|
|
18394
|
+
summary: "Any or all leak detections. Offline and unknown members are left out, never read as dry.",
|
|
18395
|
+
role: DeviceRole.LeakSensor,
|
|
18396
|
+
outputCap: "flood",
|
|
18397
|
+
outputField: "flooded",
|
|
18398
|
+
defaultAggregate: "any",
|
|
18399
|
+
accept: [{
|
|
18400
|
+
cap: "flood",
|
|
18401
|
+
fieldPath: "flooded"
|
|
18402
|
+
}],
|
|
18403
|
+
companions: [CHANGED]
|
|
18404
|
+
}),
|
|
18405
|
+
binary({
|
|
18406
|
+
id: "smoke",
|
|
18407
|
+
summary: "Any or all smoke detections. Offline and unknown members are left out, never read as clear.",
|
|
18408
|
+
role: DeviceRole.SmokeSensor,
|
|
18409
|
+
outputCap: "smoke",
|
|
18410
|
+
outputField: "detected",
|
|
18411
|
+
defaultAggregate: "any",
|
|
18412
|
+
accept: [{
|
|
18413
|
+
cap: "smoke",
|
|
18414
|
+
fieldPath: "detected"
|
|
18415
|
+
}],
|
|
18416
|
+
companions: [CHANGED]
|
|
18417
|
+
}),
|
|
18418
|
+
binary({
|
|
18419
|
+
id: "occupancy",
|
|
18420
|
+
summary: "Any or all of motion or binary sensors, published as a binary. Presence zones are not aggregated. Nobody reporting is offline, not off.",
|
|
18421
|
+
role: DeviceRole.BinarySensor,
|
|
18422
|
+
outputCap: "binary",
|
|
18423
|
+
outputField: "on",
|
|
18424
|
+
defaultAggregate: "any",
|
|
18425
|
+
accept: [{
|
|
18426
|
+
cap: "motion",
|
|
18427
|
+
fieldPath: "detected"
|
|
18428
|
+
}, {
|
|
18429
|
+
cap: "binary",
|
|
18430
|
+
fieldPath: "on"
|
|
18431
|
+
}],
|
|
18432
|
+
companions: [CHANGED]
|
|
18433
|
+
}),
|
|
18434
|
+
binary({
|
|
18435
|
+
id: "binary",
|
|
18436
|
+
summary: "Any or all generic binary sensors. Offline and unknown members are left out, never read as off.",
|
|
18437
|
+
role: DeviceRole.BinarySensor,
|
|
18438
|
+
outputCap: "binary",
|
|
18439
|
+
outputField: "on",
|
|
18440
|
+
defaultAggregate: "any",
|
|
18441
|
+
accept: [{
|
|
18442
|
+
cap: "binary",
|
|
18443
|
+
fieldPath: "on"
|
|
18444
|
+
}],
|
|
18445
|
+
companions: [CHANGED]
|
|
18446
|
+
}),
|
|
18447
|
+
actuator({
|
|
18448
|
+
id: "switch",
|
|
18449
|
+
summary: "On when at least one switch is on, or when all of them are. Offline and unknown members are left out of that decision, never read as off, and still receive the command.",
|
|
18450
|
+
deviceType: DeviceType.Switch,
|
|
18451
|
+
outputCap: "switch",
|
|
18452
|
+
commandCaps: ["switch"]
|
|
18453
|
+
}),
|
|
18454
|
+
actuator({
|
|
18455
|
+
id: "light",
|
|
18456
|
+
summary: "On when at least one light is on, or when all of them are. Brightness and colour are offered only when every member has them. A command is not sent to a member that lacks it.",
|
|
18457
|
+
deviceType: DeviceType.Light,
|
|
18458
|
+
outputCap: "switch",
|
|
18459
|
+
commandCaps: [
|
|
18460
|
+
"switch",
|
|
18461
|
+
"brightness",
|
|
18462
|
+
"color"
|
|
18463
|
+
]
|
|
18464
|
+
})
|
|
18465
|
+
];
|
|
18466
|
+
function actuator(input) {
|
|
18467
|
+
return {
|
|
18468
|
+
...input,
|
|
18469
|
+
family: "actuator",
|
|
18470
|
+
role: void 0,
|
|
18471
|
+
memberDeviceType: input.deviceType,
|
|
18472
|
+
outputField: "on",
|
|
18473
|
+
quantity: "none",
|
|
18474
|
+
baseUnit: void 0,
|
|
18475
|
+
aggregates: BINARY_AGGREGATES,
|
|
18476
|
+
defaultAggregate: "any",
|
|
18477
|
+
empty: "offline",
|
|
18478
|
+
accept: [{
|
|
18479
|
+
cap: "switch",
|
|
18480
|
+
fieldPath: "on"
|
|
18481
|
+
}],
|
|
18482
|
+
companions: [CHANGED]
|
|
18483
|
+
};
|
|
18484
|
+
}
|
|
18485
|
+
new Map(GROUP_TEMPLATES.map((template) => [template.id, template]));
|
|
18486
|
+
DeviceFeature.LightColorRgb, DeviceFeature.LightColorHsv, DeviceFeature.LightColorMired;
|
|
18099
18487
|
`${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
|
|
18100
18488
|
/**
|
|
18101
18489
|
* What a composition may BUILD on a device type (G2, D676): the caps a new
|
|
@@ -19922,12 +20310,12 @@ function buildDeviceAdminUrl(parts) {
|
|
|
19922
20310
|
* providers detect renames by matching `uniqueId` and patch `id`
|
|
19923
20311
|
* in-place so dispatch keeps working.
|
|
19924
20312
|
*
|
|
19925
|
-
* **
|
|
19926
|
-
*
|
|
19927
|
-
*
|
|
19928
|
-
*
|
|
19929
|
-
* (`ha-domain-mapping`)
|
|
19930
|
-
* stored after that point.
|
|
20313
|
+
* **Display unit and precision are NOT stored here.** They are a read-time
|
|
20314
|
+
* preference (D944). A polymorphic reading stores its `quantity` here once,
|
|
20315
|
+
* at adopt, and a date/time value stores `dateTimeShape` the same way —
|
|
20316
|
+
* neither is repeated on each sample. The `device_class` tag is an
|
|
20317
|
+
* HA-specific input consumed at the discovery boundary (`ha-domain-mapping`)
|
|
20318
|
+
* to derive the CamStack `DeviceRole`; it is never stored after that point.
|
|
19931
20319
|
*
|
|
19932
20320
|
* The `raw` escape hatch carries provider-specific attributes that don't
|
|
19933
20321
|
* fit the structured slots (HA `attributes` whitelist, Reolink `deviceCache`
|
|
@@ -19941,6 +20329,14 @@ var SourceInfoSchema = object({
|
|
|
19941
20329
|
/** Immutable upstream identifier when available (HA `unique_id`, … ).
|
|
19942
20330
|
* Used to detect rename when `id` changes. */
|
|
19943
20331
|
uniqueId: string().optional(),
|
|
20332
|
+
/** Quantity of a polymorphic reading, written once at adopt (D944). */
|
|
20333
|
+
quantity: ReadingQuantitySchema.optional(),
|
|
20334
|
+
/** Date / time / datetime shape of a string reading, written once at adopt. */
|
|
20335
|
+
dateTimeShape: _enum([
|
|
20336
|
+
"date",
|
|
20337
|
+
"time",
|
|
20338
|
+
"datetime"
|
|
20339
|
+
]).optional(),
|
|
19944
20340
|
/** Provider-specific extras that don't fit the structured slots.
|
|
19945
20341
|
* Whitelist what goes here per provider — do NOT dump entire HA
|
|
19946
20342
|
* attribute blobs (would explode the meta JSON column). */
|
|
@@ -41045,7 +41441,8 @@ method(object({
|
|
|
41045
41441
|
"enum"
|
|
41046
41442
|
]),
|
|
41047
41443
|
enumValues: array(string()).optional(),
|
|
41048
|
-
item: boolean().optional()
|
|
41444
|
+
item: boolean().optional(),
|
|
41445
|
+
quantity: ReadingQuantitySchema.optional()
|
|
41049
41446
|
})).readonly(),
|
|
41050
41447
|
itemArray: object({
|
|
41051
41448
|
path: string(),
|
|
@@ -44889,8 +45286,8 @@ var MaskPolygonShapeSchema = object({
|
|
|
44889
45286
|
/** Boolean cell grid — row-major, length === gridWidth*gridHeight. */
|
|
44890
45287
|
var MaskGridShapeSchema = object({
|
|
44891
45288
|
kind: literal("grid"),
|
|
44892
|
-
gridWidth: number(),
|
|
44893
|
-
gridHeight: number(),
|
|
45289
|
+
gridWidth: number().meta(readingMeta("none")),
|
|
45290
|
+
gridHeight: number().meta(readingMeta("none")),
|
|
44894
45291
|
cells: array(boolean())
|
|
44895
45292
|
});
|
|
44896
45293
|
discriminatedUnion("kind", [
|
|
@@ -45002,6 +45399,8 @@ var NcSystemEventKindSchema = _enum([
|
|
|
45002
45399
|
"detection-blind",
|
|
45003
45400
|
"motion-noisy",
|
|
45004
45401
|
"motion-calm",
|
|
45402
|
+
"package-llm-silent",
|
|
45403
|
+
"package-llm-answered",
|
|
45005
45404
|
"recording-stalled",
|
|
45006
45405
|
"recording-healthy",
|
|
45007
45406
|
"recording-degraded",
|
|
@@ -56093,6 +56492,28 @@ var PackageVersionInfoSchema = object({
|
|
|
56093
56492
|
deprecated: string().optional(),
|
|
56094
56493
|
distTags: array(string()).readonly()
|
|
56095
56494
|
});
|
|
56495
|
+
/**
|
|
56496
|
+
* One published document. `ok` is markdown from the registry. `missing` means
|
|
56497
|
+
* the registry answered and the file was not there. `error` is a registry or
|
|
56498
|
+
* tarball failure — never an empty string standing in for either.
|
|
56499
|
+
*/
|
|
56500
|
+
var PackageDocBodySchema = discriminatedUnion("status", [
|
|
56501
|
+
object({
|
|
56502
|
+
status: literal("ok"),
|
|
56503
|
+
markdown: string()
|
|
56504
|
+
}),
|
|
56505
|
+
object({ status: literal("missing") }),
|
|
56506
|
+
object({
|
|
56507
|
+
status: literal("error"),
|
|
56508
|
+
message: string()
|
|
56509
|
+
})
|
|
56510
|
+
]);
|
|
56511
|
+
var PackageDocsSchema = object({
|
|
56512
|
+
name: string(),
|
|
56513
|
+
version: string(),
|
|
56514
|
+
readme: PackageDocBodySchema,
|
|
56515
|
+
changelog: PackageDocBodySchema
|
|
56516
|
+
});
|
|
56096
56517
|
var SearchResultSchema = object({
|
|
56097
56518
|
name: string(),
|
|
56098
56519
|
version: string(),
|
|
@@ -56311,7 +56732,10 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
|
|
|
56311
56732
|
}), object({ success: literal(true) }), {
|
|
56312
56733
|
kind: "mutation",
|
|
56313
56734
|
auth: "admin"
|
|
56314
|
-
}), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({
|
|
56735
|
+
}), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({
|
|
56736
|
+
name: string().min(1),
|
|
56737
|
+
version: string().min(1).optional()
|
|
56738
|
+
}), PackageDocsSchema, { auth: "admin" }), method(object({ addonId: string() }), RestartAddonResultSchema, {
|
|
56315
56739
|
kind: "mutation",
|
|
56316
56740
|
auth: "admin"
|
|
56317
56741
|
}), method(object({ packageName: string() }), object({ success: literal(true) }), {
|
|
@@ -56370,27 +56794,17 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
|
|
|
56370
56794
|
*/
|
|
56371
56795
|
var AirQualitySensorStatusSchema = object({
|
|
56372
56796
|
/** Carbon dioxide concentration in ppm. */
|
|
56373
|
-
co2Ppm: number().min(0).optional(),
|
|
56797
|
+
co2Ppm: number().min(0).optional().meta(readingMeta("concentration-volume")),
|
|
56374
56798
|
/** Total volatile organic compounds in ppb. */
|
|
56375
|
-
vocPpb: number().min(0).optional(),
|
|
56799
|
+
vocPpb: number().min(0).optional().meta(readingMeta("concentration-ppb")),
|
|
56376
56800
|
/** Particulate matter ≤ 2.5 μm in µg/m³. */
|
|
56377
|
-
pm25: number().min(0).optional(),
|
|
56801
|
+
pm25: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
56378
56802
|
/** Particulate matter ≤ 10 μm in µg/m³. */
|
|
56379
|
-
pm10: number().min(0).optional(),
|
|
56803
|
+
pm10: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
56380
56804
|
/** Composite AQI value (typically 0..500). */
|
|
56381
|
-
aqi: number().optional(),
|
|
56805
|
+
aqi: number().optional().meta(readingMeta("index")),
|
|
56382
56806
|
/** Ms epoch when the slice was last updated. */
|
|
56383
|
-
lastFetchedAt: number()
|
|
56384
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
56385
|
-
* `attributes.unit_of_measurement` → 'ppm' / 'ppb' / 'µg/m³'). Each
|
|
56386
|
-
* upstream `sensor.*` entity surfaces ONE device_class, so one unit
|
|
56387
|
-
* per slice is unambiguous. */
|
|
56388
|
-
unit: string().optional(),
|
|
56389
|
-
/** Suggested decimal places for numeric display.
|
|
56390
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
56391
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
56392
|
-
* auto-formatting when absent. */
|
|
56393
|
-
precision: number().int().min(0).max(10).optional()
|
|
56807
|
+
lastFetchedAt: number()
|
|
56394
56808
|
});
|
|
56395
56809
|
var airQualitySensorCapability = {
|
|
56396
56810
|
name: "air-quality-sensor",
|
|
@@ -56427,12 +56841,12 @@ var airQualitySensorCapability = {
|
|
|
56427
56841
|
},
|
|
56428
56842
|
pm25: {
|
|
56429
56843
|
kind: "gauge",
|
|
56430
|
-
unit: "
|
|
56844
|
+
unit: "µg/m³",
|
|
56431
56845
|
deadband: 1
|
|
56432
56846
|
},
|
|
56433
56847
|
pm10: {
|
|
56434
56848
|
kind: "gauge",
|
|
56435
|
-
unit: "
|
|
56849
|
+
unit: "µg/m³",
|
|
56436
56850
|
deadband: 1
|
|
56437
56851
|
},
|
|
56438
56852
|
aqi: {
|
|
@@ -56450,22 +56864,13 @@ var airQualitySensorCapability = {
|
|
|
56450
56864
|
* entries with `device_class: illuminance`.
|
|
56451
56865
|
*/
|
|
56452
56866
|
var AmbientLightSensorStatusSchema = object({
|
|
56453
|
-
/** Current illuminance in lux (lx). */
|
|
56454
|
-
lux: number().min(0).meta({
|
|
56455
|
-
|
|
56867
|
+
/** Current illuminance in lux (lx). `null` when the sample was refused (D393). */
|
|
56868
|
+
lux: number().min(0).nullable().meta(readingMeta("illuminance", {
|
|
56869
|
+
precision: 0,
|
|
56456
56870
|
label: "Illuminance"
|
|
56457
|
-
}),
|
|
56871
|
+
})),
|
|
56458
56872
|
/** Ms epoch when the slice was last updated. */
|
|
56459
|
-
lastFetchedAt: number()
|
|
56460
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
56461
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
56462
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
56463
|
-
unit: string().optional(),
|
|
56464
|
-
/** Suggested decimal places for numeric display.
|
|
56465
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
56466
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
56467
|
-
* auto-formatting when absent. */
|
|
56468
|
-
precision: number().int().min(0).max(10).optional()
|
|
56873
|
+
lastFetchedAt: number()
|
|
56469
56874
|
});
|
|
56470
56875
|
var ambientLightSensorCapability = {
|
|
56471
56876
|
name: "ambient-light-sensor",
|
|
@@ -56497,12 +56902,7 @@ var ambientLightSensorCapability = {
|
|
|
56497
56902
|
} } },
|
|
56498
56903
|
/** Clock fields: written, but excluded from the compare that decides
|
|
56499
56904
|
* whether persisting is worth a SQLite commit. */
|
|
56500
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
56501
|
-
customize: {
|
|
56502
|
-
version: 1,
|
|
56503
|
-
advanced: "derive",
|
|
56504
|
-
targets: []
|
|
56505
|
-
}
|
|
56905
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
56506
56906
|
};
|
|
56507
56907
|
/**
|
|
56508
56908
|
* Per-class audio metrics aggregated over a sliding window.
|
|
@@ -56729,10 +57129,7 @@ var BatteryStatusSchema = object({
|
|
|
56729
57129
|
* Consumers must SKIP a null rather than coerce it — `battery-band` already
|
|
56730
57130
|
* declines to band a non-finite reading, which is the correct shape.
|
|
56731
57131
|
*/
|
|
56732
|
-
percentage: number().min(0).max(100).nullable().meta({
|
|
56733
|
-
unit: "%",
|
|
56734
|
-
label: "Charge"
|
|
56735
|
-
}),
|
|
57132
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage", { label: "Charge" })),
|
|
56736
57133
|
/**
|
|
56737
57134
|
* Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
|
|
56738
57135
|
* Reolink-specific for the Solar Panel 2 accessory (will become
|
|
@@ -56759,7 +57156,14 @@ var BatteryStatusSchema = object({
|
|
|
56759
57156
|
*/
|
|
56760
57157
|
sleeping: boolean().meta({ label: "Sleeping" }),
|
|
56761
57158
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
56762
|
-
lastUpdated: number(),
|
|
57159
|
+
lastUpdated: number().meta(readingMeta("none")),
|
|
57160
|
+
/**
|
|
57161
|
+
* Battery voltage in volts, for a cell the firmware reports as voltage
|
|
57162
|
+
* rather than a percentage (Ecowitt capacitor packs). Absent on cameras
|
|
57163
|
+
* that only report charge. A second reading on this cap, not a second
|
|
57164
|
+
* `numeric-sensor` on the same device.
|
|
57165
|
+
*/
|
|
57166
|
+
volts: number().nullable().optional().meta(readingMeta("voltage", { label: "Voltage" })),
|
|
56763
57167
|
/**
|
|
56764
57168
|
* Ms epoch of the last time the device PROVED it was reachable — a
|
|
56765
57169
|
* completed firmware round-trip, an observed wake, or an inbound push
|
|
@@ -56811,7 +57215,6 @@ var BATTERY_DEVICE_TYPES = [
|
|
|
56811
57215
|
/** Generic Customize target for the percentage reading (D936). */
|
|
56812
57216
|
var batteryCustomize = {
|
|
56813
57217
|
version: 1,
|
|
56814
|
-
advanced: "derive",
|
|
56815
57218
|
targets: [{
|
|
56816
57219
|
id: "percentage",
|
|
56817
57220
|
cardinality: "scalar",
|
|
@@ -56820,7 +57223,7 @@ var batteryCustomize = {
|
|
|
56820
57223
|
stateField: "percentage"
|
|
56821
57224
|
},
|
|
56822
57225
|
deviceTypes: BATTERY_DEVICE_TYPES,
|
|
56823
|
-
apply: "add
|
|
57226
|
+
apply: "add",
|
|
56824
57227
|
path: "percentage",
|
|
56825
57228
|
sources: [{
|
|
56826
57229
|
kind: "field",
|
|
@@ -56941,10 +57344,16 @@ onStatusChanged: { data: object({
|
|
|
56941
57344
|
/**
|
|
56942
57345
|
* History (D850): recorded series. The generic capture replaces the `battery` series of `pipeline-analytics:stats-5m`.
|
|
56943
57346
|
*/
|
|
56944
|
-
history: { fields: {
|
|
56945
|
-
|
|
56946
|
-
|
|
56947
|
-
|
|
57347
|
+
history: { fields: {
|
|
57348
|
+
percentage: {
|
|
57349
|
+
kind: "gauge",
|
|
57350
|
+
unit: "%"
|
|
57351
|
+
},
|
|
57352
|
+
volts: {
|
|
57353
|
+
kind: "gauge",
|
|
57354
|
+
unit: "V"
|
|
57355
|
+
}
|
|
57356
|
+
} },
|
|
56948
57357
|
customize: batteryCustomize,
|
|
56949
57358
|
/** Clock fields: written, but excluded from the compare that decides
|
|
56950
57359
|
* whether persisting is worth a SQLite commit. */
|
|
@@ -56991,12 +57400,7 @@ var binaryCapability = {
|
|
|
56991
57400
|
history: { fields: { on: { kind: "boolean" } } },
|
|
56992
57401
|
/** Clock fields: written, but excluded from the compare that decides
|
|
56993
57402
|
* whether persisting is worth a SQLite commit. */
|
|
56994
|
-
volatileStateFields: ["lastChangedAt"]
|
|
56995
|
-
customize: {
|
|
56996
|
-
version: 1,
|
|
56997
|
-
advanced: "derive",
|
|
56998
|
-
targets: []
|
|
56999
|
-
}
|
|
57403
|
+
volatileStateFields: ["lastChangedAt"]
|
|
57000
57404
|
};
|
|
57001
57405
|
/**
|
|
57002
57406
|
* Dimmable-light brightness control. Co-exists with `switch` on the
|
|
@@ -57012,7 +57416,7 @@ var binaryCapability = {
|
|
|
57012
57416
|
*/
|
|
57013
57417
|
var BrightnessStatusSchema = object({
|
|
57014
57418
|
/** Current level as 0..100 inclusive. Firmware-reported. */
|
|
57015
|
-
percentage: number().min(0).max(100),
|
|
57419
|
+
percentage: number().min(0).max(100).meta(readingMeta("percentage")),
|
|
57016
57420
|
/** Ms epoch of the last operator-driven change. Useful for UI freshness. */
|
|
57017
57421
|
lastChangedAt: number()
|
|
57018
57422
|
});
|
|
@@ -57483,21 +57887,21 @@ var ClimateControlStatusSchema = object({
|
|
|
57483
57887
|
/** Single setpoint in Celsius. Used by single-target modes
|
|
57484
57888
|
* (heat / cool / dry). Null when the device is in a range mode
|
|
57485
57889
|
* (`heat_cool`) or has no setpoint at all (`fan_only`/`off`). */
|
|
57486
|
-
target: number().nullable(),
|
|
57890
|
+
target: number().nullable().meta(readingMeta("temperature")),
|
|
57487
57891
|
/** Upper bound of the dual setpoint in Celsius. Populated only
|
|
57488
57892
|
* in `heat_cool` mode. */
|
|
57489
|
-
targetHigh: number().nullable(),
|
|
57893
|
+
targetHigh: number().nullable().meta(readingMeta("temperature")),
|
|
57490
57894
|
/** Lower bound of the dual setpoint in Celsius. Populated only
|
|
57491
57895
|
* in `heat_cool` mode. */
|
|
57492
|
-
targetLow: number().nullable(),
|
|
57896
|
+
targetLow: number().nullable().meta(readingMeta("temperature")),
|
|
57493
57897
|
/** Target relative humidity (0..100). Null when the device has no
|
|
57494
57898
|
* humidity control. */
|
|
57495
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
57899
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
57496
57900
|
/** Current measured temperature in Celsius. Read-only — pushed by
|
|
57497
57901
|
* the device's internal sensor. */
|
|
57498
|
-
currentTemp: number().nullable(),
|
|
57902
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
57499
57903
|
/** Current measured relative humidity (0..100). Read-only. */
|
|
57500
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
57904
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
57501
57905
|
/** Vertical louver swing on/off. Null when the device has no vertical
|
|
57502
57906
|
* swing surface (gate with `DeviceFeature.ClimateSwingVertical`). */
|
|
57503
57907
|
swingVertical: boolean().nullable(),
|
|
@@ -57505,11 +57909,11 @@ var ClimateControlStatusSchema = object({
|
|
|
57505
57909
|
* horizontal swing surface (gate with `DeviceFeature.ClimateSwingHorizontal`). */
|
|
57506
57910
|
swingHorizontal: boolean().nullable(),
|
|
57507
57911
|
/** Lowest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
57508
|
-
minTemp: number().nullable().optional(),
|
|
57912
|
+
minTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
57509
57913
|
/** Highest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
57510
|
-
maxTemp: number().nullable().optional(),
|
|
57914
|
+
maxTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
57511
57915
|
/** Setpoint granularity, Celsius (0.5, 1). Absent / null = not reported. */
|
|
57512
|
-
tempStep: number().positive().nullable().optional(),
|
|
57916
|
+
tempStep: number().positive().nullable().optional().meta(readingMeta("temperature")),
|
|
57513
57917
|
/** Ms epoch when the slice was last updated (push or command). */
|
|
57514
57918
|
lastFetchedAt: number()
|
|
57515
57919
|
});
|
|
@@ -57651,17 +58055,17 @@ var climateControlCapability = {
|
|
|
57651
58055
|
* modes to expose in the picker without a slice fetch.
|
|
57652
58056
|
*/
|
|
57653
58057
|
var RgbTripletSchema = object({
|
|
57654
|
-
r: number().int().min(0).max(255),
|
|
57655
|
-
g: number().int().min(0).max(255),
|
|
57656
|
-
b: number().int().min(0).max(255)
|
|
58058
|
+
r: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
58059
|
+
g: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
58060
|
+
b: number().int().min(0).max(255).meta(readingMeta("none"))
|
|
57657
58061
|
});
|
|
57658
58062
|
var HsvTripletSchema = object({
|
|
57659
58063
|
/** Hue in degrees, 0..360. */
|
|
57660
|
-
h: number().min(0).max(360),
|
|
58064
|
+
h: number().min(0).max(360).meta(readingMeta("none")),
|
|
57661
58065
|
/** Saturation as 0..100 inclusive. */
|
|
57662
|
-
s: number().min(0).max(100),
|
|
58066
|
+
s: number().min(0).max(100).meta(readingMeta("none")),
|
|
57663
58067
|
/** Value/brightness as 0..100 inclusive. */
|
|
57664
|
-
v: number().min(0).max(100)
|
|
58068
|
+
v: number().min(0).max(100).meta(readingMeta("none"))
|
|
57665
58069
|
});
|
|
57666
58070
|
var ColorInputSchema = discriminatedUnion("mode", [
|
|
57667
58071
|
object({
|
|
@@ -57690,7 +58094,7 @@ var ColorStatusSchema = object({
|
|
|
57690
58094
|
/** Populated when `mode === 'hsv'`. */
|
|
57691
58095
|
hsv: HsvTripletSchema.optional(),
|
|
57692
58096
|
/** Populated when `mode === 'mired'`. */
|
|
57693
|
-
mireds: number().int().optional(),
|
|
58097
|
+
mireds: number().int().optional().meta(readingMeta("colour-temperature")),
|
|
57694
58098
|
/** Ms epoch of the last operator-driven change. */
|
|
57695
58099
|
lastChangedAt: number()
|
|
57696
58100
|
});
|
|
@@ -57885,18 +58289,12 @@ _enum([
|
|
|
57885
58289
|
"empty",
|
|
57886
58290
|
"full"
|
|
57887
58291
|
]);
|
|
57888
|
-
/**
|
|
57889
|
-
|
|
57890
|
-
|
|
57891
|
-
"days",
|
|
57892
|
-
"hours",
|
|
57893
|
-
"cycles"
|
|
57894
|
-
]);
|
|
57895
|
-
/** Remaining life as a COUNT, not a percentage (the PetKit desiccant reports
|
|
57896
|
-
* days). `value` null = unknown (D393). */
|
|
58292
|
+
/** Whether `remaining.value` is a duration in seconds or a dimensionless count. */
|
|
58293
|
+
var ConsumableRemainingKindSchema = _enum(["duration", "count"]);
|
|
58294
|
+
/** Remaining life. `value` null = unknown (D393). Duration is seconds. */
|
|
57897
58295
|
var ConsumableRemainingSchema = object({
|
|
57898
|
-
value: number().min(0).nullable(),
|
|
57899
|
-
|
|
58296
|
+
value: number().min(0).nullable().meta(readingMeta("device")),
|
|
58297
|
+
kind: ConsumableRemainingKindSchema
|
|
57900
58298
|
});
|
|
57901
58299
|
/** A single consumable item. Either a continuous `level` (remaining
|
|
57902
58300
|
* life %, or fill % for a `supply` / `waste` item) or a discrete `status`
|
|
@@ -57909,7 +58307,7 @@ var ConsumableItemSchema = object({
|
|
|
57909
58307
|
/** Display name. */
|
|
57910
58308
|
label: string().min(1),
|
|
57911
58309
|
/** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
|
|
57912
|
-
level: number().min(0).max(100).nullable(),
|
|
58310
|
+
level: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
57913
58311
|
/** The provider's discrete verdict when known (binary mode). */
|
|
57914
58312
|
status: ConsumableStatusSchema.nullable(),
|
|
57915
58313
|
/** What the item is — decides whether low or full is bad. Absent = `wear`. */
|
|
@@ -57991,8 +58389,8 @@ var consumablesCustomize = {
|
|
|
57991
58389
|
transforms: [{ kind: "identity" }]
|
|
57992
58390
|
}],
|
|
57993
58391
|
literals: [{
|
|
57994
|
-
path: "remaining.
|
|
57995
|
-
values: [...
|
|
58392
|
+
path: "remaining.kind",
|
|
58393
|
+
values: [...ConsumableRemainingKindSchema.options]
|
|
57996
58394
|
}]
|
|
57997
58395
|
},
|
|
57998
58396
|
{
|
|
@@ -58121,7 +58519,6 @@ reset: method(object({
|
|
|
58121
58519
|
},
|
|
58122
58520
|
"remaining.value": {
|
|
58123
58521
|
kind: "gauge",
|
|
58124
|
-
unitFrom: "remaining.unit",
|
|
58125
58522
|
deadband: 1,
|
|
58126
58523
|
displayName: "Remaining"
|
|
58127
58524
|
}
|
|
@@ -58191,10 +58588,9 @@ var contactCapability = {
|
|
|
58191
58588
|
* (empty array for the other kinds). It lives in the slice because
|
|
58192
58589
|
* HA `select.*` entities may update their options at runtime.
|
|
58193
58590
|
*
|
|
58194
|
-
*
|
|
58195
|
-
*
|
|
58196
|
-
*
|
|
58197
|
-
* push — consistent with `options` and the sensor-unit approach.
|
|
58591
|
+
* Numeric `min` / `max` / `step` live in the slice and share the device
|
|
58592
|
+
* quantity (`SourceInfo.quantity`, D944). Display precision is a read-time
|
|
58593
|
+
* preference. A datetime control's shape is `SourceInfo.dateTimeShape`.
|
|
58198
58594
|
*/
|
|
58199
58595
|
var ControlStatusSchema = object({
|
|
58200
58596
|
kind: _enum([
|
|
@@ -58206,39 +58602,17 @@ var ControlStatusSchema = object({
|
|
|
58206
58602
|
/** Current value. Numeric kind → number; select/text/datetime → string.
|
|
58207
58603
|
* Datetime values are ISO 8601 strings (full timestamp, date-only,
|
|
58208
58604
|
* or time-only — HA accepts all three forms). */
|
|
58209
|
-
value: union([number(), string()]),
|
|
58605
|
+
value: union([number().meta(readingMeta("device")), string()]),
|
|
58210
58606
|
/** Acceptable values when `kind === 'select'`. Empty for other kinds. */
|
|
58211
58607
|
options: array(string()),
|
|
58212
58608
|
/** Ms epoch when the slice was last updated. */
|
|
58213
58609
|
lastChangedAt: number(),
|
|
58214
|
-
/**
|
|
58215
|
-
|
|
58216
|
-
|
|
58217
|
-
|
|
58218
|
-
/**
|
|
58219
|
-
|
|
58220
|
-
min: number().optional(),
|
|
58221
|
-
/** Maximum allowed value. Populated live from HA `attributes.max`.
|
|
58222
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
58223
|
-
max: number().optional(),
|
|
58224
|
-
/** Step increment. Populated live from HA `attributes.step`.
|
|
58225
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
58226
|
-
step: number().optional(),
|
|
58227
|
-
/** Suggested decimal places for numeric display. Populated live from HA
|
|
58228
|
-
* `attributes.suggested_display_precision`, or derived from `step` when the
|
|
58229
|
-
* HA attribute is absent. Meaningful for `kind === 'numeric'`; absent for
|
|
58230
|
-
* other kinds. Falls back to auto-formatting when absent. */
|
|
58231
|
-
precision: number().int().min(0).max(10).optional(),
|
|
58232
|
-
/** Date-picker granularity for `kind === 'datetime'`. 'date' → date-only,
|
|
58233
|
-
* 'time' → time-only, 'datetime' → full timestamp. Absent for other kinds
|
|
58234
|
-
* (UI defaults to 'datetime'). Derived live from the device's HA domain
|
|
58235
|
-
* (date.* / time.* / datetime.*) or, for input_datetime, from the entity's
|
|
58236
|
-
* `has_date`/`has_time` attributes on each push. */
|
|
58237
|
-
format: _enum([
|
|
58238
|
-
"date",
|
|
58239
|
-
"time",
|
|
58240
|
-
"datetime"
|
|
58241
|
-
]).optional()
|
|
58610
|
+
/** Minimum allowed value, in the device quantity's base unit. */
|
|
58611
|
+
min: number().optional().meta(readingMeta("device")),
|
|
58612
|
+
/** Maximum allowed value, in the device quantity's base unit. */
|
|
58613
|
+
max: number().optional().meta(readingMeta("device")),
|
|
58614
|
+
/** Step increment, in the device quantity's base unit. */
|
|
58615
|
+
step: number().optional().meta(readingMeta("device"))
|
|
58242
58616
|
});
|
|
58243
58617
|
var ControlSetValueInputSchema = discriminatedUnion("kind", [
|
|
58244
58618
|
object({
|
|
@@ -58304,9 +58678,9 @@ var CoverStatusSchema = object({
|
|
|
58304
58678
|
]),
|
|
58305
58679
|
/** 0 = fully closed, 100 = fully open. Null when the device has
|
|
58306
58680
|
* no intermediate position surface. */
|
|
58307
|
-
position: number().min(0).max(100).nullable(),
|
|
58681
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58308
58682
|
/** 0 = closed slats, 100 = open slats. Null when no tilt support. */
|
|
58309
|
-
tiltPosition: number().min(0).max(100).nullable(),
|
|
58683
|
+
tiltPosition: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58310
58684
|
/** Ms epoch when the slice was last updated. */
|
|
58311
58685
|
lastChangedAt: number()
|
|
58312
58686
|
});
|
|
@@ -58409,9 +58783,9 @@ var NormalizedRangeSchema$1 = object({
|
|
|
58409
58783
|
var DayNightStatusSchema = object({
|
|
58410
58784
|
mode: DayNightModeSchema,
|
|
58411
58785
|
/** IR-cut trigger sensitivity, NORMALIZED 0–100 (higher = switches to night sooner). */
|
|
58412
|
-
sensitivity: number().optional(),
|
|
58786
|
+
sensitivity: number().optional().meta(readingMeta("none")),
|
|
58413
58787
|
/** Delay before the IR-cut filter flips, in seconds. */
|
|
58414
|
-
switchDelaySec: number().optional(),
|
|
58788
|
+
switchDelaySec: number().optional().meta(readingMeta("duration")),
|
|
58415
58789
|
lastFetchedAt: number()
|
|
58416
58790
|
});
|
|
58417
58791
|
/**
|
|
@@ -58629,11 +59003,11 @@ var DishwasherStatusSchema = object({
|
|
|
58629
59003
|
/** Feature keys of the programs the appliance currently offers — drives the UI selector. */
|
|
58630
59004
|
availablePrograms: array(string()),
|
|
58631
59005
|
/** Seconds remaining on the active cycle, or null when not running / not known. */
|
|
58632
|
-
remainingSeconds: number().int().nonnegative().nullable(),
|
|
59006
|
+
remainingSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
58633
59007
|
/** Seconds the delayed start is set to (time until the cycle starts), or null. */
|
|
58634
|
-
delayedStartSeconds: number().int().nonnegative().nullable(),
|
|
59008
|
+
delayedStartSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
58635
59009
|
/** Cycle completion 0..100, or null when not applicable. */
|
|
58636
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
59010
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58637
59011
|
/** True when the door is reported open; null when the door state is not known. */
|
|
58638
59012
|
doorOpen: boolean().nullable(),
|
|
58639
59013
|
/** True when the door is latched (locked) during a cycle; null when not reported. */
|
|
@@ -58657,7 +59031,7 @@ var DishwasherStatusSchema = object({
|
|
|
58657
59031
|
/** True while the machine-care (descaling / cleaning-program) reminder is raised; false when clear; null when not reported. */
|
|
58658
59032
|
machineCareDue: boolean().nullable(),
|
|
58659
59033
|
/** Program runs left before the machine-care reminder is due; null when the appliance does not say. */
|
|
58660
|
-
machineCareRemainingRuns: number().int().nonnegative().nullable(),
|
|
59034
|
+
machineCareRemainingRuns: number().int().nonnegative().nullable().meta(readingMeta("count")),
|
|
58661
59035
|
/** Option states: null when the appliance does not expose the option or has not said. */
|
|
58662
59036
|
halfLoad: boolean().nullable(),
|
|
58663
59037
|
hygienePlus: boolean().nullable(),
|
|
@@ -58672,7 +59046,7 @@ var DishwasherStatusSchema = object({
|
|
|
58672
59046
|
/** Feature keys of the events currently raised (salt low, rinse aid low, program finished, …). */
|
|
58673
59047
|
activeEvents: array(string()),
|
|
58674
59048
|
/** Numeric error code when the appliance reports one; null otherwise. */
|
|
58675
|
-
errorCode: number().nullable(),
|
|
59049
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
58676
59050
|
/** Name of the raised alert-level event while the appliance is in error; null otherwise. */
|
|
58677
59051
|
errorLabel: string().nullable(),
|
|
58678
59052
|
/** Ms epoch of the last value received from the appliance; 0 = never. */
|
|
@@ -58903,7 +59277,7 @@ var DoorbellStatusSchema = object({
|
|
|
58903
59277
|
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
58904
59278
|
lastPressedAt: number().nullable(),
|
|
58905
59279
|
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
58906
|
-
pressCountSinceStart: number()
|
|
59280
|
+
pressCountSinceStart: number().meta(readingMeta("count"))
|
|
58907
59281
|
});
|
|
58908
59282
|
var DoorbellPressEventSchema = object({
|
|
58909
59283
|
deviceId: number(),
|
|
@@ -58968,17 +59342,7 @@ onPressed: {
|
|
|
58968
59342
|
history: "none",
|
|
58969
59343
|
customize: doorbellCustomize
|
|
58970
59344
|
};
|
|
58971
|
-
|
|
58972
|
-
* Enum-state sensor — a string value picked from a finite option set.
|
|
58973
|
-
* Drives HA `sensor` entries with `state_class: enum` (HVAC action
|
|
58974
|
-
* states, weather conditions, contact-source channels, mode strings).
|
|
58975
|
-
* The option set is stable across observations; it is persisted in the
|
|
58976
|
-
* device config blob (via the control slice at adoption) and is NOT
|
|
58977
|
-
* stored in `sourceInfo`.
|
|
58978
|
-
*/
|
|
58979
|
-
/** Locale-render shape for an ISO `value` carried by a `DateTimeSensor`-role
|
|
58980
|
-
* enum sensor: `date` (date-only), `time` (time-only), `datetime` (both). */
|
|
58981
|
-
var EnumSensorDateTimeFormatSchema = _enum([
|
|
59345
|
+
_enum([
|
|
58982
59346
|
"date",
|
|
58983
59347
|
"time",
|
|
58984
59348
|
"datetime"
|
|
@@ -58986,12 +59350,11 @@ var EnumSensorDateTimeFormatSchema = _enum([
|
|
|
58986
59350
|
var EnumSensorStatusSchema = object({
|
|
58987
59351
|
value: string(),
|
|
58988
59352
|
/**
|
|
58989
|
-
* Set
|
|
58990
|
-
* as
|
|
58991
|
-
*
|
|
58992
|
-
* a time-only sensor → `'time'`.
|
|
59353
|
+
* Set when `value` is a timestamp rather than an enum state, so history
|
|
59354
|
+
* does not learn ISO strings as states. The display shape (date / time /
|
|
59355
|
+
* datetime) lives on `SourceInfo.dateTimeShape`, written once at adopt.
|
|
58993
59356
|
*/
|
|
58994
|
-
|
|
59357
|
+
timestamp: boolean().optional(),
|
|
58995
59358
|
/** Ms epoch when the slice was last updated. */
|
|
58996
59359
|
lastFetchedAt: number()
|
|
58997
59360
|
});
|
|
@@ -59018,11 +59381,11 @@ var enumSensorCapability = {
|
|
|
59018
59381
|
* History (D850): the value as an `enum` series (an appliance's program or
|
|
59019
59382
|
* operation state, an HVAC action). The option set is per device, so the
|
|
59020
59383
|
* value list is LEARNED as values are first seen (bounded). A sensor with a
|
|
59021
|
-
* `
|
|
59384
|
+
* `timestamp` carries a clock, not a state, and is not recorded.
|
|
59022
59385
|
*/
|
|
59023
59386
|
history: { fields: { value: {
|
|
59024
59387
|
kind: "enum",
|
|
59025
|
-
skipWhenSet: "
|
|
59388
|
+
skipWhenSet: "timestamp"
|
|
59026
59389
|
} } },
|
|
59027
59390
|
/** Clock fields: written, but excluded from the compare that decides
|
|
59028
59391
|
* whether persisting is worth a SQLite commit. */
|
|
@@ -59042,13 +59405,13 @@ var EventFireSchema = object({
|
|
|
59042
59405
|
deviceId: number(),
|
|
59043
59406
|
eventType: string(),
|
|
59044
59407
|
data: record(string(), unknown()).nullable(),
|
|
59045
|
-
timestamp: number(),
|
|
59046
|
-
seq: number()
|
|
59408
|
+
timestamp: number().meta(readingMeta("none")),
|
|
59409
|
+
seq: number().meta(readingMeta("count"))
|
|
59047
59410
|
});
|
|
59048
59411
|
var EventEmitterStatusSchema = object({
|
|
59049
59412
|
eventTypes: array(string()),
|
|
59050
59413
|
lastEvent: EventFireSchema.nullable(),
|
|
59051
|
-
eventCountSinceStart: number()
|
|
59414
|
+
eventCountSinceStart: number().meta(readingMeta("count"))
|
|
59052
59415
|
});
|
|
59053
59416
|
var eventEmitterCapability = {
|
|
59054
59417
|
name: "event-emitter",
|
|
@@ -59461,10 +59824,10 @@ var FanDirectionSchema = _enum(["forward", "reverse"]);
|
|
|
59461
59824
|
var FanControlStatusSchema = object({
|
|
59462
59825
|
/** Active speed as 0..100 inclusive. Null when the device has no
|
|
59463
59826
|
* speed surface (single-speed fan). */
|
|
59464
|
-
percentage: number().min(0).max(100).nullable(),
|
|
59827
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59465
59828
|
/** Speed granularity the device accepts (HA `percentage_step`, e.g. 25 for
|
|
59466
59829
|
* a 4-speed fan). Absent when unknown — the UI then falls back to step 1. */
|
|
59467
|
-
percentageStep: number().positive().optional(),
|
|
59830
|
+
percentageStep: number().positive().optional().meta(readingMeta("percentage")),
|
|
59468
59831
|
/** Active preset mode (`auto` / `quiet` / `turbo` / vendor-specific)
|
|
59469
59832
|
* — empty string when no preset is active or supported. */
|
|
59470
59833
|
preset: string(),
|
|
@@ -59585,7 +59948,7 @@ var FeatureProbeStatusSchema = object({
|
|
|
59585
59948
|
/** Camera/firmware model string. `null` when the firmware doesn't expose it. */
|
|
59586
59949
|
model: string().nullable(),
|
|
59587
59950
|
/** Channel count for NVR/Hub devices; `1` for standalone cameras; `null` pre-probe. */
|
|
59588
|
-
channelCount: number().nullable(),
|
|
59951
|
+
channelCount: number().nullable().meta(readingMeta("count")),
|
|
59589
59952
|
/**
|
|
59590
59953
|
* Ms epoch of the last SUCCESSFUL probe. `0` before the first probe
|
|
59591
59954
|
* completes — drivers' `getAccessoryChildren()` should treat zero as
|
|
@@ -59708,9 +60071,91 @@ var gasCapability = {
|
|
|
59708
60071
|
* whether persisting is worth a SQLite commit. */
|
|
59709
60072
|
volatileStateFields: ["lastChangedAt"]
|
|
59710
60073
|
};
|
|
60074
|
+
var GroupCommandsSchema = object({
|
|
60075
|
+
/** One row per member that has been commanded. A later command replaces that member's row. */
|
|
60076
|
+
results: array(object({
|
|
60077
|
+
deviceId: number().int().nonnegative(),
|
|
60078
|
+
cap: string().min(1),
|
|
60079
|
+
method: string().min(1),
|
|
60080
|
+
ok: boolean(),
|
|
60081
|
+
error: string().optional(),
|
|
60082
|
+
/** Ms epoch of the attempt. */
|
|
60083
|
+
at: number()
|
|
60084
|
+
})) });
|
|
60085
|
+
var groupCommandsCapability = {
|
|
60086
|
+
name: "group-commands",
|
|
60087
|
+
scope: "device",
|
|
60088
|
+
deviceNative: true,
|
|
60089
|
+
mode: "singleton",
|
|
60090
|
+
deviceTypes: [DeviceType.Switch, DeviceType.Light],
|
|
60091
|
+
methods: {},
|
|
60092
|
+
status: {
|
|
60093
|
+
schema: GroupCommandsSchema,
|
|
60094
|
+
kind: "push"
|
|
60095
|
+
},
|
|
60096
|
+
runtimeState: GroupCommandsSchema,
|
|
60097
|
+
/**
|
|
60098
|
+
* Runtime-state durability: **session** — the last attempt. A restored
|
|
60099
|
+
* failure would outlive the command that caused it.
|
|
60100
|
+
*
|
|
60101
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
60102
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
60103
|
+
*/
|
|
60104
|
+
durability: "session",
|
|
60105
|
+
history: "none"
|
|
60106
|
+
};
|
|
60107
|
+
/**
|
|
60108
|
+
* How many members of a helper group answered (D944). Counts are integers,
|
|
60109
|
+
* not measurements: zero included is a real count, never a stand-in reading.
|
|
60110
|
+
* The reading itself stays on the output capability. History is none — the
|
|
60111
|
+
* series that later statistics read is the output cap's own history block.
|
|
60112
|
+
*/
|
|
60113
|
+
var GroupStatusSchema = object({
|
|
60114
|
+
/** Members whose current value entered the aggregate. */
|
|
60115
|
+
included: number().int().nonnegative().meta(readingMeta("count", {
|
|
60116
|
+
precision: 0,
|
|
60117
|
+
label: "Reporting"
|
|
60118
|
+
})),
|
|
60119
|
+
/** Members left out: offline, unknown, or not a finite reading (D393). */
|
|
60120
|
+
excluded: number().int().nonnegative().meta(readingMeta("count", {
|
|
60121
|
+
precision: 0,
|
|
60122
|
+
label: "Excluded"
|
|
60123
|
+
})),
|
|
60124
|
+
/** `included` + `excluded`. */
|
|
60125
|
+
total: number().int().nonnegative().meta(readingMeta("count", {
|
|
60126
|
+
precision: 0,
|
|
60127
|
+
label: "Members"
|
|
60128
|
+
}))
|
|
60129
|
+
});
|
|
60130
|
+
var groupStatusCapability = {
|
|
60131
|
+
name: "group-status",
|
|
60132
|
+
scope: "device",
|
|
60133
|
+
deviceNative: true,
|
|
60134
|
+
mode: "singleton",
|
|
60135
|
+
deviceTypes: [
|
|
60136
|
+
DeviceType.Sensor,
|
|
60137
|
+
DeviceType.Switch,
|
|
60138
|
+
DeviceType.Light
|
|
60139
|
+
],
|
|
60140
|
+
methods: {},
|
|
60141
|
+
status: {
|
|
60142
|
+
schema: GroupStatusSchema,
|
|
60143
|
+
kind: "push"
|
|
60144
|
+
},
|
|
60145
|
+
runtimeState: GroupStatusSchema,
|
|
60146
|
+
/**
|
|
60147
|
+
* Runtime-state durability: **session** — recomputed from members on the
|
|
60148
|
+
* next source event; a restored count would outlive the readings it named.
|
|
60149
|
+
*
|
|
60150
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
60151
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
60152
|
+
*/
|
|
60153
|
+
durability: "session",
|
|
60154
|
+
history: "none"
|
|
60155
|
+
};
|
|
59711
60156
|
var HeatingValveStatusSchema = object({
|
|
59712
60157
|
/** Radiator valve opening 0 (closed) .. 100 (open). Null = not yet known. */
|
|
59713
|
-
position: number().min(0).max(100).nullable(),
|
|
60158
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59714
60159
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
59715
60160
|
lastFetchedAt: number()
|
|
59716
60161
|
});
|
|
@@ -59753,9 +60198,9 @@ var HumidifierStatusSchema = object({
|
|
|
59753
60198
|
/** Whether the humidifier is currently on. */
|
|
59754
60199
|
on: boolean(),
|
|
59755
60200
|
/** Current measured relative humidity (0..100). Null when not reported. */
|
|
59756
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
60201
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
59757
60202
|
/** Target relative humidity (0..100). Null when no setpoint surface. */
|
|
59758
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
60203
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
59759
60204
|
/** Active mode (`auto` / `normal` / `baby` / vendor). Null when the
|
|
59760
60205
|
* device has no mode surface. */
|
|
59761
60206
|
mode: string().nullable(),
|
|
@@ -59765,9 +60210,9 @@ var HumidifierStatusSchema = object({
|
|
|
59765
60210
|
* `idle` / `off`). Null when the device doesn't report it. */
|
|
59766
60211
|
action: string().nullable(),
|
|
59767
60212
|
/** HA `min_humidity` attribute. Null → UI uses 0. */
|
|
59768
|
-
minHumidity: number().nullable(),
|
|
60213
|
+
minHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
59769
60214
|
/** HA `max_humidity` attribute. Null → UI uses 100. */
|
|
59770
|
-
maxHumidity: number().nullable(),
|
|
60215
|
+
maxHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
59771
60216
|
/** Ms epoch when the slice was last updated. */
|
|
59772
60217
|
lastChangedAt: number()
|
|
59773
60218
|
});
|
|
@@ -59837,22 +60282,13 @@ var humidifierCapability = {
|
|
|
59837
60282
|
* `sourceInfo`.
|
|
59838
60283
|
*/
|
|
59839
60284
|
var HumiditySensorStatusSchema = object({
|
|
59840
|
-
/** Current relative humidity, 0..100. */
|
|
59841
|
-
percent: number().min(0).max(100).meta({
|
|
59842
|
-
|
|
60285
|
+
/** Current relative humidity, 0..100. `null` when the sample was refused (D393). */
|
|
60286
|
+
percent: number().min(0).max(100).nullable().meta(readingMeta("humidity", {
|
|
60287
|
+
precision: 0,
|
|
59843
60288
|
label: "Humidity"
|
|
59844
|
-
}),
|
|
60289
|
+
})),
|
|
59845
60290
|
/** Ms epoch when the slice was last updated. */
|
|
59846
|
-
lastFetchedAt: number()
|
|
59847
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
59848
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
59849
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
59850
|
-
unit: string().optional(),
|
|
59851
|
-
/** Suggested decimal places for numeric display.
|
|
59852
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
59853
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
59854
|
-
* auto-formatting when absent. */
|
|
59855
|
-
precision: number().int().min(0).max(10).optional()
|
|
60291
|
+
lastFetchedAt: number()
|
|
59856
60292
|
});
|
|
59857
60293
|
var humiditySensorCapability = {
|
|
59858
60294
|
name: "humidity-sensor",
|
|
@@ -59883,12 +60319,7 @@ var humiditySensorCapability = {
|
|
|
59883
60319
|
} } },
|
|
59884
60320
|
/** Clock fields: written, but excluded from the compare that decides
|
|
59885
60321
|
* whether persisting is worth a SQLite commit. */
|
|
59886
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
59887
|
-
customize: {
|
|
59888
|
-
version: 1,
|
|
59889
|
-
advanced: "derive",
|
|
59890
|
-
targets: []
|
|
59891
|
-
}
|
|
60322
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
59892
60323
|
};
|
|
59893
60324
|
/**
|
|
59894
60325
|
* Image display cap. Models a single still image exposed by an integration —
|
|
@@ -59909,7 +60340,7 @@ var ImageStatusSchema = object({
|
|
|
59909
60340
|
* entity exposes no `entity_picture` (yet). */
|
|
59910
60341
|
url: string().nullable(),
|
|
59911
60342
|
/** Ms epoch of the upstream last-updated timestamp. Null at cold-start. */
|
|
59912
|
-
lastUpdated: number().nullable()
|
|
60343
|
+
lastUpdated: number().nullable().meta(readingMeta("none"))
|
|
59913
60344
|
});
|
|
59914
60345
|
var imageCapability = {
|
|
59915
60346
|
name: "image",
|
|
@@ -59997,19 +60428,19 @@ var NormalizedRangeSchema = object({
|
|
|
59997
60428
|
*/
|
|
59998
60429
|
var ImageSettingsStatusSchema = object({
|
|
59999
60430
|
/** Normalized 0–100. */
|
|
60000
|
-
brightness: number().optional(),
|
|
60431
|
+
brightness: number().optional().meta(readingMeta("none")),
|
|
60001
60432
|
/** Normalized 0–100. */
|
|
60002
|
-
contrast: number().optional(),
|
|
60433
|
+
contrast: number().optional().meta(readingMeta("none")),
|
|
60003
60434
|
/** Normalized 0–100. */
|
|
60004
|
-
saturation: number().optional(),
|
|
60435
|
+
saturation: number().optional().meta(readingMeta("none")),
|
|
60005
60436
|
/** Normalized 0–100. */
|
|
60006
|
-
sharpness: number().optional(),
|
|
60437
|
+
sharpness: number().optional().meta(readingMeta("none")),
|
|
60007
60438
|
mirror: boolean().optional(),
|
|
60008
60439
|
flip: boolean().optional(),
|
|
60009
60440
|
rotate: ImageRotateSchema.optional(),
|
|
60010
60441
|
whiteBalance: WhiteBalanceModeSchema.optional(),
|
|
60011
60442
|
/** Manual white-balance warmth, NORMALIZED 0–100. Meaningful only when `whiteBalance === 'manual'`. */
|
|
60012
|
-
warmth: number().optional(),
|
|
60443
|
+
warmth: number().optional().meta(readingMeta("none")),
|
|
60013
60444
|
exposureMode: ExposureModeSchema.optional(),
|
|
60014
60445
|
backlightMode: BacklightModeSchema.optional(),
|
|
60015
60446
|
lastFetchedAt: number()
|
|
@@ -60288,10 +60719,10 @@ var IntercomAbilitySchema = object({
|
|
|
60288
60719
|
/** Codecs accepted by firmware, in preference order. Driver-authored strings. */
|
|
60289
60720
|
codecs: array(string()),
|
|
60290
60721
|
/** Sample rate (Hz) the firmware expects. Reolink typical: 16000. */
|
|
60291
|
-
sampleRate: number(),
|
|
60722
|
+
sampleRate: number().meta(readingMeta("none")),
|
|
60292
60723
|
duplex: _enum(["half", "full"]),
|
|
60293
60724
|
/** Max in-flight audio backlog before drop (ms). Server uses this to bound latency. */
|
|
60294
|
-
maxBacklogMs: number()
|
|
60725
|
+
maxBacklogMs: number().meta(readingMeta("duration-ms"))
|
|
60295
60726
|
});
|
|
60296
60727
|
var IntercomStatusSchema = object({
|
|
60297
60728
|
/** True while a talk session is open. */
|
|
@@ -60518,13 +60949,13 @@ var LawnMowerControlStatusSchema = object({
|
|
|
60518
60949
|
activity: LawnMowerActivitySchema,
|
|
60519
60950
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
60520
60951
|
* reading. */
|
|
60521
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
60952
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
60522
60953
|
/** 0..100 mowing-completion percentage of the current task, or null when no
|
|
60523
60954
|
* task is active / progress is unavailable. */
|
|
60524
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
60955
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
60525
60956
|
/** Current device/event code (dynamic — mostly status, sometimes an error),
|
|
60526
60957
|
* or null when unknown. */
|
|
60527
|
-
currentCode: number().nullable(),
|
|
60958
|
+
currentCode: number().nullable().meta(readingMeta("none")),
|
|
60528
60959
|
/** Human label for {@link currentCode}, or null when undecodable. */
|
|
60529
60960
|
currentCodeLabel: string().nullable(),
|
|
60530
60961
|
/** Severity of {@link currentCode}. `error` (and often `warning`) warrants UI
|
|
@@ -61057,7 +61488,7 @@ var MediaPlayerStatusSchema = object({
|
|
|
61057
61488
|
state: MediaPlayerStateSchema,
|
|
61058
61489
|
/** Volume as 0..100 inclusive. Null when the device has no volume
|
|
61059
61490
|
* surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
|
|
61060
|
-
volumeLevel: number().min(0).max(100).nullable(),
|
|
61491
|
+
volumeLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61061
61492
|
/** Mute toggle distinct from volume=0. Null when no mute surface.
|
|
61062
61493
|
* Pair with `DeviceFeature.MediaPlayerMute`. */
|
|
61063
61494
|
isMuted: boolean().nullable(),
|
|
@@ -61070,10 +61501,10 @@ var MediaPlayerStatusSchema = object({
|
|
|
61070
61501
|
currentMedia: MediaInfoSchema.nullable(),
|
|
61071
61502
|
/** Current playback position in ms. Null when not seekable or
|
|
61072
61503
|
* nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
|
|
61073
|
-
positionMs: number().int().nonnegative().nullable(),
|
|
61504
|
+
positionMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
61074
61505
|
/** Total duration of the current media in ms. Null when unknown
|
|
61075
61506
|
* (live stream) or nothing is playing. */
|
|
61076
|
-
durationMs: number().int().nonnegative().nullable(),
|
|
61507
|
+
durationMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
61077
61508
|
/** Shuffle toggle. Null when no shuffle surface.
|
|
61078
61509
|
* Pair with `DeviceFeature.MediaPlayerShuffle`. */
|
|
61079
61510
|
shuffle: boolean().nullable(),
|
|
@@ -61382,7 +61813,7 @@ var motionCustomize = {
|
|
|
61382
61813
|
eventName: "onMotionChanged"
|
|
61383
61814
|
},
|
|
61384
61815
|
deviceTypes: [DeviceType.Camera],
|
|
61385
|
-
apply: "
|
|
61816
|
+
apply: "add",
|
|
61386
61817
|
applyAuthority: {
|
|
61387
61818
|
kind: "camera-sensors",
|
|
61388
61819
|
timeoutField: "motionCooldownMs"
|
|
@@ -61454,7 +61885,7 @@ var MotionStatusSchema = object({
|
|
|
61454
61885
|
* it, every provider seeded it at boot, and every session left it
|
|
61455
61886
|
* `detected: true` after its detach.
|
|
61456
61887
|
*/
|
|
61457
|
-
autoClearAfterMs: number().nullable()
|
|
61888
|
+
autoClearAfterMs: number().nullable().meta(readingMeta("duration-ms"))
|
|
61458
61889
|
});
|
|
61459
61890
|
/**
|
|
61460
61891
|
* Payload of `motion.onMotionChanged` event + the corresponding bus
|
|
@@ -61491,12 +61922,18 @@ var motionCapability = {
|
|
|
61491
61922
|
methods: {
|
|
61492
61923
|
/**
|
|
61493
61924
|
* Pull the current motion state synchronously. Convenience shortcut
|
|
61494
|
-
* for consumers that don't need the full status object
|
|
61495
|
-
*
|
|
61496
|
-
* `getStatus` once the auto-injected status surface lands in every
|
|
61497
|
-
* consumer.
|
|
61925
|
+
* for consumers that don't need the full status object. A composed
|
|
61926
|
+
* group answers from its slice (D944): unknown throws, it is not off.
|
|
61498
61927
|
*/
|
|
61499
61928
|
isDetected: method(object({ deviceId: number() }), boolean()) },
|
|
61929
|
+
/**
|
|
61930
|
+
* A composed motion group serves `isDetected` from `detected` (D944).
|
|
61931
|
+
* Without this the cap stays uncomposable (`has-commands`).
|
|
61932
|
+
*/
|
|
61933
|
+
composedMethods: { isDetected: {
|
|
61934
|
+
kind: "slice",
|
|
61935
|
+
field: "detected"
|
|
61936
|
+
} },
|
|
61500
61937
|
events: {
|
|
61501
61938
|
/**
|
|
61502
61939
|
* Fires every time the runner transitions a camera between
|
|
@@ -61636,7 +62073,7 @@ var MotionZoneRegionSchema = object({
|
|
|
61636
62073
|
* the grid region(s). */
|
|
61637
62074
|
var MotionZoneStatusSchema = object({
|
|
61638
62075
|
enabled: boolean(),
|
|
61639
|
-
sensitivity: number(),
|
|
62076
|
+
sensitivity: number().meta(readingMeta("none")),
|
|
61640
62077
|
/** Grid region(s). Today exactly one `grid` shape. */
|
|
61641
62078
|
regions: array(MotionZoneRegionSchema),
|
|
61642
62079
|
lastFetchedAt: number()
|
|
@@ -62006,7 +62443,7 @@ var NavigationStatusSchema = object({
|
|
|
62006
62443
|
following: boolean(),
|
|
62007
62444
|
flash: boolean(),
|
|
62008
62445
|
lightMode: NavigationLightModeSchema,
|
|
62009
|
-
lightLevel: number().min(40).max(100),
|
|
62446
|
+
lightLevel: number().min(40).max(100).meta(readingMeta("none")),
|
|
62010
62447
|
/** Ms epoch when the slice was last updated. */
|
|
62011
62448
|
lastChangedAt: number()
|
|
62012
62449
|
});
|
|
@@ -62140,13 +62577,13 @@ var NetworkLinkStatusSchema = object({
|
|
|
62140
62577
|
* one whose reading has not landed must not be drawn at 0 %. Consumers
|
|
62141
62578
|
* SKIP a null rather than coerce it.
|
|
62142
62579
|
*/
|
|
62143
|
-
signalPercent: number().min(0).max(100).nullable(),
|
|
62580
|
+
signalPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
62144
62581
|
/** Raw received signal strength in dBm, when the firmware reports one. */
|
|
62145
|
-
rssiDbm: number().optional(),
|
|
62582
|
+
rssiDbm: number().optional().meta(readingMeta("signal-level")),
|
|
62146
62583
|
/** Network name of a wireless link, when the firmware reports it. */
|
|
62147
62584
|
ssid: string().optional(),
|
|
62148
62585
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
62149
|
-
lastUpdated: number()
|
|
62586
|
+
lastUpdated: number().meta(readingMeta("none"))
|
|
62150
62587
|
});
|
|
62151
62588
|
var networkLinkCapability = {
|
|
62152
62589
|
name: "network-link",
|
|
@@ -62531,7 +62968,7 @@ var NotifierStatusSchema = object({
|
|
|
62531
62968
|
lastError: string().nullable(),
|
|
62532
62969
|
/** Number of deliveries currently buffered server-side (rate-limited
|
|
62533
62970
|
* notifiers may queue). 0 when the provider sends synchronously. */
|
|
62534
|
-
queueDepth: number().int().nonnegative(),
|
|
62971
|
+
queueDepth: number().int().nonnegative().meta(readingMeta("count")),
|
|
62535
62972
|
/** Per-feature capability matrix — authoritative source for the
|
|
62536
62973
|
* compose-form field gating. */
|
|
62537
62974
|
supports: NotifierSupportsSchema
|
|
@@ -62623,11 +63060,9 @@ onSent: { data: object({
|
|
|
62623
63060
|
* cap fits (HA `sensor` whose `device_class` we don't have a typed cap
|
|
62624
63061
|
* for: water flow, distance, weight, frequency, signal strength, …).
|
|
62625
63062
|
*
|
|
62626
|
-
* The
|
|
62627
|
-
*
|
|
62628
|
-
*
|
|
62629
|
-
* The UI reads them directly from the slice — they are the single source
|
|
62630
|
-
* of truth for generic numeric rendering and do NOT live on `sourceInfo`.
|
|
63063
|
+
* The quantity is not on this slice. It is chosen when the device is
|
|
63064
|
+
* adopted and stored once on `SourceInfo.quantity` (D944). `value` is in
|
|
63065
|
+
* that quantity's base unit. `null` is a refused sample (D393).
|
|
62631
63066
|
*
|
|
62632
63067
|
* Prefer the typed alternatives (`temperature-sensor`, `humidity-sensor`,
|
|
62633
63068
|
* `ambient-light-sensor`, `pressure-sensor`, `power-meter`,
|
|
@@ -62636,15 +63071,8 @@ onSent: { data: object({
|
|
|
62636
63071
|
* numeric values land here.
|
|
62637
63072
|
*/
|
|
62638
63073
|
var NumericSensorStatusSchema = object({
|
|
62639
|
-
|
|
62640
|
-
|
|
62641
|
-
* Populated live from the upstream source on each state push.
|
|
62642
|
-
* Absent for unitless sensors. */
|
|
62643
|
-
unit: string().optional(),
|
|
62644
|
-
/** Suggested decimal places for numeric display.
|
|
62645
|
-
* Populated live from the upstream source when provided.
|
|
62646
|
-
* Falls back to auto-formatting when absent. */
|
|
62647
|
-
precision: number().int().min(0).max(10).optional(),
|
|
63074
|
+
/** Reading in the device quantity's base unit. `null` when refused (D393). */
|
|
63075
|
+
value: number().nullable().meta(readingMeta("device")),
|
|
62648
63076
|
/** Ms epoch when the slice was last updated. */
|
|
62649
63077
|
lastFetchedAt: number()
|
|
62650
63078
|
});
|
|
@@ -62668,11 +63096,11 @@ var numericSensorCapability = {
|
|
|
62668
63096
|
*/
|
|
62669
63097
|
durability: "restored",
|
|
62670
63098
|
/**
|
|
62671
|
-
* History (D850): recorded series. The unit is
|
|
63099
|
+
* History (D850): recorded series. The unit is the device quantity's base,
|
|
63100
|
+
* resolved when the series is read — the cap has no single unit.
|
|
62672
63101
|
*/
|
|
62673
63102
|
history: { fields: { value: {
|
|
62674
63103
|
kind: "gauge",
|
|
62675
|
-
unitFrom: "unit",
|
|
62676
63104
|
minIntervalMs: 3e4
|
|
62677
63105
|
} } },
|
|
62678
63106
|
/** Clock fields: written, but excluded from the compare that decides
|
|
@@ -62964,23 +63392,26 @@ var PetFeederStatusSchema = object({
|
|
|
62964
63392
|
/** Food currently in the bowl (grams). Null when the device has not
|
|
62965
63393
|
* reported a reading yet. On dual-hopper models this is the combined
|
|
62966
63394
|
* bowl reading; per-hopper levels live in `food1`/`food2`. */
|
|
62967
|
-
foodLevel: number().nullable(),
|
|
63395
|
+
foodLevel: number().nullable().meta(readingMeta("none")),
|
|
62968
63396
|
/** Hopper-1 food level (grams) on dual-hopper feeders; null on
|
|
62969
63397
|
* single-hopper models. */
|
|
62970
|
-
food1: number().nullable(),
|
|
63398
|
+
food1: number().nullable().meta(readingMeta("none")),
|
|
62971
63399
|
/** Hopper-2 food level (grams) on dual-hopper feeders; null on
|
|
62972
63400
|
* single-hopper models. */
|
|
62973
|
-
food2: number().nullable(),
|
|
63401
|
+
food2: number().nullable().meta(readingMeta("none")),
|
|
62974
63402
|
/** Derived low-food flag — mirrors the HA `food_level` binary_sensor
|
|
62975
63403
|
* (`device_class: problem`, on = low). True when the bowl is empty /
|
|
62976
63404
|
* below the feeder's low threshold. */
|
|
62977
63405
|
lowFood: boolean(),
|
|
62978
63406
|
/** Battery charge 0..100 (%). Null on mains-powered models or when the
|
|
62979
63407
|
* device has no battery reading. */
|
|
62980
|
-
batteryPower: number().min(0).max(100).nullable(),
|
|
62981
|
-
/**
|
|
62982
|
-
*
|
|
62983
|
-
|
|
63408
|
+
batteryPower: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
63409
|
+
/**
|
|
63410
|
+
* Desiccant life remaining, stored in seconds (duration base, D944).
|
|
63411
|
+
* Providers convert from the days the feeder reports. Null when the
|
|
63412
|
+
* model has no desiccant sensor.
|
|
63413
|
+
*/
|
|
63414
|
+
desiccantLeftDays: number().nullable().meta(readingMeta("duration")),
|
|
62984
63415
|
/** True while a feed is in progress. */
|
|
62985
63416
|
feeding: boolean(),
|
|
62986
63417
|
/** Decoded connectivity / power status (HA petkit device-status enum).
|
|
@@ -62991,7 +63422,7 @@ var PetFeederStatusSchema = object({
|
|
|
62991
63422
|
* with `errorCode` for consumers that want the raw integer. */
|
|
62992
63423
|
error: string().nullable(),
|
|
62993
63424
|
/** Raw device error code (0 / null = no error). */
|
|
62994
|
-
errorCode: number().nullable(),
|
|
63425
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
62995
63426
|
/** True for D4S/D4SH dual-hopper hardware — gates the per-hopper UI. */
|
|
62996
63427
|
isDualHopper: boolean(),
|
|
62997
63428
|
/** Child-lock (manual-lock) setting — buttons on the unit are disabled. */
|
|
@@ -63001,7 +63432,7 @@ var PetFeederStatusSchema = object({
|
|
|
63001
63432
|
/** Play a chime when dispensing. */
|
|
63002
63433
|
feedSound: boolean(),
|
|
63003
63434
|
/** Speaker / prompt volume level (device-scaled integer). */
|
|
63004
|
-
volume: number(),
|
|
63435
|
+
volume: number().meta(readingMeta("none")),
|
|
63005
63436
|
/** Ms epoch when the slice was last refreshed from the cloud. */
|
|
63006
63437
|
lastFetchedAt: number()
|
|
63007
63438
|
});
|
|
@@ -63120,7 +63551,7 @@ var petFeederCapability = {
|
|
|
63120
63551
|
},
|
|
63121
63552
|
desiccantLeftDays: {
|
|
63122
63553
|
kind: "gauge",
|
|
63123
|
-
unit: "
|
|
63554
|
+
unit: "s"
|
|
63124
63555
|
}
|
|
63125
63556
|
} }
|
|
63126
63557
|
};
|
|
@@ -63521,36 +63952,19 @@ method(_void(), PlatformCapabilitiesSchema), method(_void(), HardwareInfoSchema)
|
|
|
63521
63952
|
*/
|
|
63522
63953
|
var PowerMeterStatusSchema = object({
|
|
63523
63954
|
/** Instantaneous power draw in watts. */
|
|
63524
|
-
watts: number().optional().meta({
|
|
63525
|
-
unit: "W",
|
|
63526
|
-
label: "Power"
|
|
63527
|
-
}),
|
|
63955
|
+
watts: number().optional().meta(readingMeta("power", { label: "Power" })),
|
|
63528
63956
|
/** Cumulative energy in kilowatt-hours since the meter was reset. */
|
|
63529
|
-
kwhTotal: number().optional().meta({
|
|
63530
|
-
unit: "kWh",
|
|
63531
|
-
label: "Energy"
|
|
63532
|
-
}),
|
|
63957
|
+
kwhTotal: number().optional().meta(readingMeta("energy", { label: "Energy" })),
|
|
63533
63958
|
/** Voltage in volts. */
|
|
63534
|
-
volts: number().optional(),
|
|
63959
|
+
volts: number().optional().meta(readingMeta("voltage")),
|
|
63535
63960
|
/** Current in amperes. */
|
|
63536
|
-
amps: number().optional(),
|
|
63537
|
-
/** Apparent power in volt-amperes
|
|
63538
|
-
va: number().optional(),
|
|
63961
|
+
amps: number().optional().meta(readingMeta("current")),
|
|
63962
|
+
/** Apparent power in volt-amperes. */
|
|
63963
|
+
va: number().optional().meta(readingMeta("apparent-power")),
|
|
63539
63964
|
/** Power factor (0..1) if reported. */
|
|
63540
|
-
powerFactor: number().min(0).max(1).optional(),
|
|
63965
|
+
powerFactor: number().min(0).max(1).optional().meta(readingMeta("ratio")),
|
|
63541
63966
|
/** Ms epoch when the slice was last updated. */
|
|
63542
|
-
lastFetchedAt: number()
|
|
63543
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
63544
|
-
* `attributes.unit_of_measurement` → 'V' / 'A' / 'W' / 'kW' / 'kWh').
|
|
63545
|
-
* Each upstream `sensor.*` entity surfaces ONE device_class, so one
|
|
63546
|
-
* unit per slice is unambiguous. The UI prefers this over the role's
|
|
63547
|
-
* canonical unit so a 'kW' / 'Wh' feed renders verbatim. */
|
|
63548
|
-
unit: string().optional(),
|
|
63549
|
-
/** Suggested decimal places for numeric display.
|
|
63550
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
63551
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
63552
|
-
* auto-formatting when absent. */
|
|
63553
|
-
precision: number().int().min(0).max(10).optional()
|
|
63967
|
+
lastFetchedAt: number()
|
|
63554
63968
|
});
|
|
63555
63969
|
var powerMeterCapability = {
|
|
63556
63970
|
name: "power-meter",
|
|
@@ -63614,12 +64028,7 @@ var powerMeterCapability = {
|
|
|
63614
64028
|
} },
|
|
63615
64029
|
/** Clock fields: written, but excluded from the compare that decides
|
|
63616
64030
|
* whether persisting is worth a SQLite commit. */
|
|
63617
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
63618
|
-
customize: {
|
|
63619
|
-
version: 1,
|
|
63620
|
-
advanced: "derive",
|
|
63621
|
-
targets: []
|
|
63622
|
-
}
|
|
64031
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
63623
64032
|
};
|
|
63624
64033
|
/**
|
|
63625
64034
|
* Presence cap. Models HA `person.*` and `device_tracker.*` entities
|
|
@@ -63639,11 +64048,11 @@ var powerMeterCapability = {
|
|
|
63639
64048
|
*/
|
|
63640
64049
|
var GpsLocationSchema = object({
|
|
63641
64050
|
/** Latitude in decimal degrees, -90..90. */
|
|
63642
|
-
latitude: number().min(-90).max(90),
|
|
64051
|
+
latitude: number().min(-90).max(90).meta(readingMeta("angle")),
|
|
63643
64052
|
/** Longitude in decimal degrees, -180..180. */
|
|
63644
|
-
longitude: number().min(-180).max(180),
|
|
64053
|
+
longitude: number().min(-180).max(180).meta(readingMeta("angle")),
|
|
63645
64054
|
/** Reported accuracy in meters (lower = better). */
|
|
63646
|
-
accuracyMeters: number().nonnegative()
|
|
64055
|
+
accuracyMeters: number().nonnegative().meta(readingMeta("length"))
|
|
63647
64056
|
});
|
|
63648
64057
|
var PresenceStatusSchema = object({
|
|
63649
64058
|
/** `home` / `not_home` / any user-defined zone name. */
|
|
@@ -63655,7 +64064,7 @@ var PresenceStatusSchema = object({
|
|
|
63655
64064
|
gps: GpsLocationSchema.nullable(),
|
|
63656
64065
|
/** Optional battery level of the tracking device (0..100). Null
|
|
63657
64066
|
* when not reported. */
|
|
63658
|
-
batteryPercent: number().min(0).max(100).nullable(),
|
|
64067
|
+
batteryPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
63659
64068
|
/** Ms epoch when the slice was last updated. */
|
|
63660
64069
|
lastChangedAt: number()
|
|
63661
64070
|
});
|
|
@@ -63705,19 +64114,10 @@ var presenceCapability = {
|
|
|
63705
64114
|
* `sourceInfo`.
|
|
63706
64115
|
*/
|
|
63707
64116
|
var PressureSensorStatusSchema = object({
|
|
63708
|
-
/** Current pressure in hPa. */
|
|
63709
|
-
hpa: number(),
|
|
64117
|
+
/** Current pressure in hPa. `null` when the sample was refused (D393). */
|
|
64118
|
+
hpa: number().nullable().meta(readingMeta("pressure", { precision: 0 })),
|
|
63710
64119
|
/** Ms epoch when the slice was last updated. */
|
|
63711
|
-
lastFetchedAt: number()
|
|
63712
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
63713
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
63714
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
63715
|
-
unit: string().optional(),
|
|
63716
|
-
/** Suggested decimal places for numeric display.
|
|
63717
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
63718
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
63719
|
-
* auto-formatting when absent. */
|
|
63720
|
-
precision: number().int().min(0).max(10).optional()
|
|
64120
|
+
lastFetchedAt: number()
|
|
63721
64121
|
});
|
|
63722
64122
|
var pressureSensorCapability = {
|
|
63723
64123
|
name: "pressure-sensor",
|
|
@@ -64131,8 +64531,8 @@ DeviceType.Camera, method(PtzMoveCommandSchema.extend({ deviceId: number() }), _
|
|
|
64131
64531
|
}), _void(), { kind: "mutation" });
|
|
64132
64532
|
var PtzAutotrackSettingsSchema = object({
|
|
64133
64533
|
targetType: string().describe("Vendor target string (people/vehicle/pet); empty = camera default"),
|
|
64134
|
-
stopDelaySeconds: number().int().min(0).max(300),
|
|
64135
|
-
disappearDelaySeconds: number().int().min(0).max(300)
|
|
64534
|
+
stopDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration")),
|
|
64535
|
+
disappearDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration"))
|
|
64136
64536
|
});
|
|
64137
64537
|
/**
|
|
64138
64538
|
* One option the camera advertises as a valid `targetType`. Drivers
|
|
@@ -64286,7 +64686,7 @@ var RunningStateStatusSchema = object({
|
|
|
64286
64686
|
/** null = unknown — never coerced to false (D393). */
|
|
64287
64687
|
running: boolean().nullable(),
|
|
64288
64688
|
/** Epoch ms the current boolean began; null while `running` is null. */
|
|
64289
|
-
since: number().nullable(),
|
|
64689
|
+
since: number().nullable().meta(readingMeta("none")),
|
|
64290
64690
|
source: RunningStateSourceSchema.meta({ label: "Source" }),
|
|
64291
64691
|
phase: string().nullable(),
|
|
64292
64692
|
/** null until a reading has been published (D393). */
|
|
@@ -64301,7 +64701,6 @@ var RUNNING_DEVICE_TYPES = Object.values(DeviceType);
|
|
|
64301
64701
|
/** Generic Customize target for the running boolean (D936). */
|
|
64302
64702
|
var runningCustomize = {
|
|
64303
64703
|
version: 1,
|
|
64304
|
-
advanced: "derive",
|
|
64305
64704
|
targets: [{
|
|
64306
64705
|
id: "running",
|
|
64307
64706
|
cardinality: "scalar",
|
|
@@ -64321,7 +64720,7 @@ var runningCustomize = {
|
|
|
64321
64720
|
DeviceType.Thermostat,
|
|
64322
64721
|
DeviceType.PetFeeder
|
|
64323
64722
|
],
|
|
64324
|
-
apply: "add
|
|
64723
|
+
apply: "add",
|
|
64325
64724
|
path: "running",
|
|
64326
64725
|
sources: [
|
|
64327
64726
|
{
|
|
@@ -65585,9 +65984,9 @@ var RecordTriggerSchema = _enum([
|
|
|
65585
65984
|
*/
|
|
65586
65985
|
var RecordWindowSchema = object({
|
|
65587
65986
|
trigger: RecordTriggerSchema,
|
|
65588
|
-
day: number().int().min(0).max(6),
|
|
65589
|
-
startMinute: number().int().min(0).max(1439),
|
|
65590
|
-
endMinute: number().int().min(1).max(1440)
|
|
65987
|
+
day: number().int().min(0).max(6).meta(readingMeta("none")),
|
|
65988
|
+
startMinute: number().int().min(0).max(1439).meta(readingMeta("none")),
|
|
65989
|
+
endMinute: number().int().min(1).max(1440).meta(readingMeta("none"))
|
|
65591
65990
|
});
|
|
65592
65991
|
/** Status of one physical volume, as the camera itself describes it. */
|
|
65593
65992
|
var OnboardStorageVolumeSchema = object({
|
|
@@ -65663,10 +66062,10 @@ var RecordingOnboardStatusSchema = object({
|
|
|
65663
66062
|
/** Master "record to the card at all" switch. */
|
|
65664
66063
|
enabled: boolean().nullable(),
|
|
65665
66064
|
overwriteWhenFull: boolean().nullable(),
|
|
65666
|
-
preRecordSec: number().nullable(),
|
|
65667
|
-
postRecordSec: number().nullable(),
|
|
66065
|
+
preRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
66066
|
+
postRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
65668
66067
|
/** Length of one recorded file, in minutes. */
|
|
65669
|
-
segmentMinutes: number().nullable(),
|
|
66068
|
+
segmentMinutes: number().nullable().meta(readingMeta("none")),
|
|
65670
66069
|
/** The primary track's weekly windows, flattened. */
|
|
65671
66070
|
windows: array(RecordWindowSchema),
|
|
65672
66071
|
/**
|
|
@@ -65682,7 +66081,7 @@ var RecordingOnboardStatusSchema = object({
|
|
|
65682
66081
|
* provider reporting a non-zero count also reports the schedule as not
|
|
65683
66082
|
* writable.
|
|
65684
66083
|
*/
|
|
65685
|
-
unreadableWindows: number(),
|
|
66084
|
+
unreadableWindows: number().meta(readingMeta("count")),
|
|
65686
66085
|
/**
|
|
65687
66086
|
* The camera is scheduled to record and has NO usable storage.
|
|
65688
66087
|
*
|
|
@@ -66527,7 +66926,7 @@ var CamStreamDescriptorSchema = object({
|
|
|
66527
66926
|
url: string().optional(),
|
|
66528
66927
|
codec: string().optional(),
|
|
66529
66928
|
resolution: CamStreamResolutionSchema.optional(),
|
|
66530
|
-
fps: number().positive().optional(),
|
|
66929
|
+
fps: number().positive().optional().meta(readingMeta("rate")),
|
|
66531
66930
|
label: string().optional(),
|
|
66532
66931
|
/** Device-level features (e.g. `battery-operated`) — drives broker policy. */
|
|
66533
66932
|
deviceFeatures: array(string()).optional(),
|
|
@@ -66614,18 +67013,18 @@ var StreamProfileSchema = _enum([
|
|
|
66614
67013
|
]);
|
|
66615
67014
|
/** The current encoding config of one stream profile. */
|
|
66616
67015
|
var StreamProfileConfigSchema = object({
|
|
66617
|
-
width: number(),
|
|
66618
|
-
height: number(),
|
|
67016
|
+
width: number().meta(readingMeta("none")),
|
|
67017
|
+
height: number().meta(readingMeta("none")),
|
|
66619
67018
|
codec: _enum(["h264", "h265"]),
|
|
66620
|
-
framerate: number(),
|
|
66621
|
-
bitrate: number(),
|
|
67019
|
+
framerate: number().meta(readingMeta("rate")),
|
|
67020
|
+
bitrate: number().meta(readingMeta("bitrate")),
|
|
66622
67021
|
bitrateMode: _enum(["vbr", "cbr"]).optional(),
|
|
66623
67022
|
encoderProfile: _enum([
|
|
66624
67023
|
"high",
|
|
66625
67024
|
"main",
|
|
66626
67025
|
"baseline"
|
|
66627
67026
|
]).optional(),
|
|
66628
|
-
gop: number().optional(),
|
|
67027
|
+
gop: number().optional().meta(readingMeta("none")),
|
|
66629
67028
|
/**
|
|
66630
67029
|
* Whether THIS profile currently carries an audio track. READ-ONLY here.
|
|
66631
67030
|
*
|
|
@@ -66846,12 +67245,7 @@ var switchCapability = {
|
|
|
66846
67245
|
label: "On",
|
|
66847
67246
|
kind: "boolean"
|
|
66848
67247
|
}
|
|
66849
|
-
}] }
|
|
66850
|
-
customize: {
|
|
66851
|
-
version: 1,
|
|
66852
|
-
advanced: "derive",
|
|
66853
|
-
targets: []
|
|
66854
|
-
}
|
|
67248
|
+
}] }
|
|
66855
67249
|
};
|
|
66856
67250
|
/** C0 controls, DEL and the C1 range: none of them belongs in a name. */
|
|
66857
67251
|
function hasControlCharacter(value) {
|
|
@@ -67434,35 +67828,21 @@ var tamperCapability = {
|
|
|
67434
67828
|
* entries with `device_class: temperature` and any future native
|
|
67435
67829
|
* thermometer.
|
|
67436
67830
|
*
|
|
67437
|
-
*
|
|
67438
|
-
*
|
|
67439
|
-
* (climate-control's `currentTemp`, energy analytics) can compose
|
|
67440
|
-
* without per-source unit fixups. The canonical display unit (`°C`) is
|
|
67441
|
-
* a descriptor constant in the UI (ROLE_DESCRIPTOR), not stored in
|
|
67442
|
-
* `sourceInfo`.
|
|
67831
|
+
* The number is Celsius (D944). Providers convert on ingest. A failed
|
|
67832
|
+
* conversion is `null`, never a guess. Display unit is a read-time preference.
|
|
67443
67833
|
*
|
|
67444
67834
|
* Status `lastFetchedAt` lets staleness-aware consumers detect a
|
|
67445
67835
|
* frozen feed (provider hung) distinct from a "temperature hasn't
|
|
67446
67836
|
* changed" steady state.
|
|
67447
67837
|
*/
|
|
67448
67838
|
var TemperatureSensorStatusSchema = object({
|
|
67449
|
-
/** Current temperature in Celsius. */
|
|
67450
|
-
celsius: number().meta({
|
|
67451
|
-
|
|
67839
|
+
/** Current temperature in Celsius. `null` when the sample was refused (D393). */
|
|
67840
|
+
celsius: number().nullable().meta(readingMeta("temperature", {
|
|
67841
|
+
precision: 1,
|
|
67452
67842
|
label: "Temperature"
|
|
67453
|
-
}),
|
|
67843
|
+
})),
|
|
67454
67844
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
67455
|
-
lastFetchedAt: number()
|
|
67456
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
67457
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
67458
|
-
* role's canonical unit, so a Fahrenheit feed renders '°F' not '°C'.
|
|
67459
|
-
* Absent → the UI falls back to the role's canonical unit. */
|
|
67460
|
-
unit: string().optional(),
|
|
67461
|
-
/** Suggested decimal places for numeric display.
|
|
67462
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
67463
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
67464
|
-
* auto-formatting when absent. */
|
|
67465
|
-
precision: number().int().min(0).max(10).optional()
|
|
67845
|
+
lastFetchedAt: number()
|
|
67466
67846
|
});
|
|
67467
67847
|
var temperatureSensorCapability = {
|
|
67468
67848
|
name: "temperature-sensor",
|
|
@@ -67493,12 +67873,7 @@ var temperatureSensorCapability = {
|
|
|
67493
67873
|
} } },
|
|
67494
67874
|
/** Clock fields: written, but excluded from the compare that decides
|
|
67495
67875
|
* whether persisting is worth a SQLite commit. */
|
|
67496
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
67497
|
-
customize: {
|
|
67498
|
-
version: 1,
|
|
67499
|
-
advanced: "derive",
|
|
67500
|
-
targets: []
|
|
67501
|
-
}
|
|
67876
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
67502
67877
|
};
|
|
67503
67878
|
/**
|
|
67504
67879
|
* toast — system-scoped singleton capability that streams toast
|
|
@@ -67781,16 +68156,16 @@ var VacuumControlStatusSchema = object({
|
|
|
67781
68156
|
]),
|
|
67782
68157
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
67783
68158
|
* reading. */
|
|
67784
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
68159
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
67785
68160
|
/** Current fan-speed token (provider-verbatim). Null when unknown or
|
|
67786
68161
|
* the vacuum has no speed control. */
|
|
67787
68162
|
fanSpeed: string().nullable(),
|
|
67788
68163
|
/** Speed tokens the hardware accepts — drives the UI selector. */
|
|
67789
68164
|
availableFanSpeeds: array(string()),
|
|
67790
68165
|
/** 0..100 cleaning-completion percentage of the current task, or null. */
|
|
67791
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
68166
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
67792
68167
|
/** Current error code (0 / null = no error). */
|
|
67793
|
-
errorCode: number().nullable(),
|
|
68168
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
67794
68169
|
/** Human label for {@link errorCode}, or null when none / undecodable. */
|
|
67795
68170
|
errorLabel: string().nullable(),
|
|
67796
68171
|
/** Ms epoch when the slice was last updated. */
|
|
@@ -67868,7 +68243,7 @@ var ValveStatusSchema = object({
|
|
|
67868
68243
|
]),
|
|
67869
68244
|
/** 0 = fully closed, 100 = fully open. Null when the device has no
|
|
67870
68245
|
* intermediate position surface. */
|
|
67871
|
-
position: number().min(0).max(100).nullable(),
|
|
68246
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
67872
68247
|
/** Ms epoch when the slice was last updated. */
|
|
67873
68248
|
lastChangedAt: number()
|
|
67874
68249
|
});
|
|
@@ -67976,9 +68351,9 @@ var vibrationCapability = {
|
|
|
67976
68351
|
*/
|
|
67977
68352
|
var WaterHeaterStatusSchema = object({
|
|
67978
68353
|
/** Current measured temperature. Null when not reported. */
|
|
67979
|
-
currentTemp: number().nullable(),
|
|
68354
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
67980
68355
|
/** Target temperature setpoint. Null when no setpoint surface. */
|
|
67981
|
-
targetTemp: number().nullable(),
|
|
68356
|
+
targetTemp: number().nullable().meta(readingMeta("temperature")),
|
|
67982
68357
|
/** Active operation mode = HA `state` (`eco` / `electric` / `gas` /
|
|
67983
68358
|
* `heat_pump` / `high_demand` / `performance` / `off`). Null when the
|
|
67984
68359
|
* device reports an unknown state. */
|
|
@@ -67989,9 +68364,9 @@ var WaterHeaterStatusSchema = object({
|
|
|
67989
68364
|
* has no away surface. */
|
|
67990
68365
|
away: boolean().nullable(),
|
|
67991
68366
|
/** HA `min_temp` attribute. Null when not reported. */
|
|
67992
|
-
minTemp: number().nullable(),
|
|
68367
|
+
minTemp: number().nullable().meta(readingMeta("temperature")),
|
|
67993
68368
|
/** HA `max_temp` attribute. Null when not reported. */
|
|
67994
|
-
maxTemp: number().nullable(),
|
|
68369
|
+
maxTemp: number().nullable().meta(readingMeta("temperature")),
|
|
67995
68370
|
/** Ms epoch when the slice was last updated. */
|
|
67996
68371
|
lastChangedAt: number()
|
|
67997
68372
|
});
|
|
@@ -68076,25 +68451,18 @@ var waterHeaterCapability = {
|
|
|
68076
68451
|
* Forecast deferred — current conditions only for v1.
|
|
68077
68452
|
*/
|
|
68078
68453
|
var WeatherStatusSchema = object({
|
|
68079
|
-
/** Verbatim
|
|
68080
|
-
* when no condition has been reported yet. */
|
|
68454
|
+
/** Verbatim condition state (`sunny`, `cloudy`, `rainy`, …). Null when none yet. */
|
|
68081
68455
|
condition: string().nullable(),
|
|
68082
|
-
/** Current temperature in
|
|
68083
|
-
temperature: number().nullable(),
|
|
68084
|
-
/** Temperature unit string (e.g. `°C` / `°F`). Null when not provided. */
|
|
68085
|
-
temperatureUnit: string().nullable(),
|
|
68456
|
+
/** Current temperature in Celsius. Null when not provided or refused. */
|
|
68457
|
+
temperature: number().nullable().meta(readingMeta("temperature", { precision: 1 })),
|
|
68086
68458
|
/** Relative humidity (0..100). Null when not provided. */
|
|
68087
|
-
humidity: number().min(0).max(100).nullable(),
|
|
68088
|
-
/** Barometric pressure in
|
|
68089
|
-
pressure: number().nullable(),
|
|
68090
|
-
/**
|
|
68091
|
-
|
|
68092
|
-
/** Wind speed in the reported unit. Null when not provided. */
|
|
68093
|
-
windSpeed: number().nullable(),
|
|
68094
|
-
/** Wind-speed unit string (e.g. `km/h` / `mph`). Null when not provided. */
|
|
68095
|
-
windSpeedUnit: string().nullable(),
|
|
68459
|
+
humidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
68460
|
+
/** Barometric pressure in hPa. Null when not provided or refused. */
|
|
68461
|
+
pressure: number().nullable().meta(readingMeta("pressure")),
|
|
68462
|
+
/** Wind speed in metres per second. Null when not provided or refused. */
|
|
68463
|
+
windSpeed: number().nullable().meta(readingMeta("speed")),
|
|
68096
68464
|
/** Wind bearing in degrees (0..360, meteorological). Null when not provided. */
|
|
68097
|
-
windBearing: number().nullable(),
|
|
68465
|
+
windBearing: number().nullable().meta(readingMeta("angle")),
|
|
68098
68466
|
/** Ms epoch when the slice was last updated. */
|
|
68099
68467
|
lastFetchedAt: number()
|
|
68100
68468
|
});
|
|
@@ -68122,12 +68490,12 @@ var weatherCapability = {
|
|
|
68122
68490
|
*/
|
|
68123
68491
|
durability: "session",
|
|
68124
68492
|
/**
|
|
68125
|
-
* History (D850): recorded series.
|
|
68493
|
+
* History (D850): recorded series. Numbers are the quantity base (D944).
|
|
68126
68494
|
*/
|
|
68127
68495
|
history: { fields: {
|
|
68128
68496
|
temperature: {
|
|
68129
68497
|
kind: "gauge",
|
|
68130
|
-
|
|
68498
|
+
unit: "°C",
|
|
68131
68499
|
deadband: .2
|
|
68132
68500
|
},
|
|
68133
68501
|
humidity: {
|
|
@@ -68137,12 +68505,12 @@ var weatherCapability = {
|
|
|
68137
68505
|
},
|
|
68138
68506
|
pressure: {
|
|
68139
68507
|
kind: "gauge",
|
|
68140
|
-
|
|
68508
|
+
unit: "hPa",
|
|
68141
68509
|
deadband: .5
|
|
68142
68510
|
},
|
|
68143
68511
|
windSpeed: {
|
|
68144
68512
|
kind: "gauge",
|
|
68145
|
-
|
|
68513
|
+
unit: "m/s",
|
|
68146
68514
|
deadband: .5
|
|
68147
68515
|
}
|
|
68148
68516
|
} }
|
|
@@ -69373,6 +69741,8 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
69373
69741
|
featureProbe: featureProbeCapability,
|
|
69374
69742
|
flood: floodCapability,
|
|
69375
69743
|
gas: gasCapability,
|
|
69744
|
+
groupCommands: groupCommandsCapability,
|
|
69745
|
+
groupStatus: groupStatusCapability,
|
|
69376
69746
|
heatingValve: heatingValveCapability,
|
|
69377
69747
|
humidifier: humidifierCapability,
|
|
69378
69748
|
humiditySensor: humiditySensorCapability,
|
|
@@ -70749,6 +71119,13 @@ Object.freeze({
|
|
|
70749
71119
|
access: "view",
|
|
70750
71120
|
role: "admin"
|
|
70751
71121
|
},
|
|
71122
|
+
"addons.getPackageDocs": {
|
|
71123
|
+
capName: "addons",
|
|
71124
|
+
capScope: "system",
|
|
71125
|
+
addonId: null,
|
|
71126
|
+
access: "view",
|
|
71127
|
+
role: "admin"
|
|
71128
|
+
},
|
|
70752
71129
|
"addons.getVersions": {
|
|
70753
71130
|
capName: "addons",
|
|
70754
71131
|
capScope: "system",
|
|
@@ -73857,6 +74234,20 @@ Object.freeze({
|
|
|
73857
74234
|
access: "view",
|
|
73858
74235
|
role: "viewer"
|
|
73859
74236
|
},
|
|
74237
|
+
"groupCommands.getStatus": {
|
|
74238
|
+
capName: "group-commands",
|
|
74239
|
+
capScope: "device",
|
|
74240
|
+
addonId: null,
|
|
74241
|
+
access: "view",
|
|
74242
|
+
role: "viewer"
|
|
74243
|
+
},
|
|
74244
|
+
"groupStatus.getStatus": {
|
|
74245
|
+
capName: "group-status",
|
|
74246
|
+
capScope: "device",
|
|
74247
|
+
addonId: null,
|
|
74248
|
+
access: "view",
|
|
74249
|
+
role: "viewer"
|
|
74250
|
+
},
|
|
73860
74251
|
"heatingValve.getStatus": {
|
|
73861
74252
|
capName: "heating-valve",
|
|
73862
74253
|
capScope: "device",
|
|
@@ -83679,6 +84070,37 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83679
84070
|
icon: "flame"
|
|
83680
84071
|
}]
|
|
83681
84072
|
},
|
|
84073
|
+
"group-commands": {
|
|
84074
|
+
scope: "device",
|
|
84075
|
+
noun: t("Group command", "Comando di gruppo")
|
|
84076
|
+
},
|
|
84077
|
+
"group-status": {
|
|
84078
|
+
scope: "device",
|
|
84079
|
+
noun: t("Group", "Gruppo"),
|
|
84080
|
+
state: [
|
|
84081
|
+
{
|
|
84082
|
+
kind: "numeric",
|
|
84083
|
+
field: "included",
|
|
84084
|
+
quantity: t("the members reporting", "i membri che rispondono"),
|
|
84085
|
+
label: t("Reporting", "Rispondono"),
|
|
84086
|
+
icon: "users"
|
|
84087
|
+
},
|
|
84088
|
+
{
|
|
84089
|
+
kind: "numeric",
|
|
84090
|
+
field: "excluded",
|
|
84091
|
+
quantity: t("the members left out", "i membri esclusi"),
|
|
84092
|
+
label: t("Excluded", "Esclusi"),
|
|
84093
|
+
icon: "users"
|
|
84094
|
+
},
|
|
84095
|
+
{
|
|
84096
|
+
kind: "numeric",
|
|
84097
|
+
field: "total",
|
|
84098
|
+
quantity: t("the member count", "il numero di membri"),
|
|
84099
|
+
label: t("Members", "Membri"),
|
|
84100
|
+
icon: "sigma"
|
|
84101
|
+
}
|
|
84102
|
+
]
|
|
84103
|
+
},
|
|
83682
84104
|
"humidity-sensor": {
|
|
83683
84105
|
scope: "device",
|
|
83684
84106
|
noun: t("Humidity", "Umidità"),
|
|
@@ -83712,7 +84134,6 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83712
84134
|
field: "value",
|
|
83713
84135
|
quantity: t("the reading", "il valore"),
|
|
83714
84136
|
label: t("Reading", "Valore"),
|
|
83715
|
-
unitField: "unit",
|
|
83716
84137
|
icon: "gauge"
|
|
83717
84138
|
}]
|
|
83718
84139
|
},
|
|
@@ -83848,7 +84269,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83848
84269
|
field: "temperature",
|
|
83849
84270
|
quantity: t("the outdoor temperature", "la temperatura esterna"),
|
|
83850
84271
|
label: t("Temperature", "Temperatura"),
|
|
83851
|
-
|
|
84272
|
+
unit: "°C",
|
|
83852
84273
|
icon: "thermometer"
|
|
83853
84274
|
},
|
|
83854
84275
|
{
|
|
@@ -83864,7 +84285,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83864
84285
|
field: "windSpeed",
|
|
83865
84286
|
quantity: t("the wind speed", "la velocità del vento"),
|
|
83866
84287
|
label: t("Wind", "Vento"),
|
|
83867
|
-
|
|
84288
|
+
unit: "m/s",
|
|
83868
84289
|
icon: "wind"
|
|
83869
84290
|
},
|
|
83870
84291
|
{
|
|
@@ -83872,7 +84293,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83872
84293
|
field: "pressure",
|
|
83873
84294
|
quantity: t("the air pressure", "la pressione atmosferica"),
|
|
83874
84295
|
label: t("Pressure", "Pressione"),
|
|
83875
|
-
|
|
84296
|
+
unit: "hPa",
|
|
83876
84297
|
icon: "gauge"
|
|
83877
84298
|
}
|
|
83878
84299
|
]
|
|
@@ -85145,6 +85566,16 @@ Object.freeze({
|
|
|
85145
85566
|
form: "single",
|
|
85146
85567
|
optional: false
|
|
85147
85568
|
}],
|
|
85569
|
+
"groupCommands.getStatus": [{
|
|
85570
|
+
name: "deviceId",
|
|
85571
|
+
form: "single",
|
|
85572
|
+
optional: false
|
|
85573
|
+
}],
|
|
85574
|
+
"groupStatus.getStatus": [{
|
|
85575
|
+
name: "deviceId",
|
|
85576
|
+
form: "single",
|
|
85577
|
+
optional: false
|
|
85578
|
+
}],
|
|
85148
85579
|
"heatingValve.getStatus": [{
|
|
85149
85580
|
name: "deviceId",
|
|
85150
85581
|
form: "single",
|
|
@@ -87129,6 +87560,8 @@ new Map(Object.entries({
|
|
|
87129
87560
|
"detection-blind": "device-events",
|
|
87130
87561
|
"motion-noisy": "device-events",
|
|
87131
87562
|
"motion-calm": "device-events",
|
|
87563
|
+
"package-llm-silent": "device-events",
|
|
87564
|
+
"package-llm-answered": "device-events",
|
|
87132
87565
|
"recording-stalled": "device-events",
|
|
87133
87566
|
"recording-healthy": "device-events",
|
|
87134
87567
|
"recording-degraded": "device-events",
|
|
@@ -87212,6 +87645,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
|
|
|
87212
87645
|
label: "Motion without a subject",
|
|
87213
87646
|
kinds: ["motion-noisy", "motion-calm"]
|
|
87214
87647
|
},
|
|
87648
|
+
{
|
|
87649
|
+
id: "package-llm",
|
|
87650
|
+
family: "device-events",
|
|
87651
|
+
label: "Package confirm",
|
|
87652
|
+
kinds: ["package-llm-silent", "package-llm-answered"]
|
|
87653
|
+
},
|
|
87215
87654
|
{
|
|
87216
87655
|
id: "recording",
|
|
87217
87656
|
family: "device-events",
|
|
@@ -87393,6 +87832,8 @@ var DEVICE_EVENTS = [
|
|
|
87393
87832
|
"detection-blind",
|
|
87394
87833
|
"motion-noisy",
|
|
87395
87834
|
"motion-calm",
|
|
87835
|
+
"package-llm-silent",
|
|
87836
|
+
"package-llm-answered",
|
|
87396
87837
|
"recording-stalled",
|
|
87397
87838
|
"recording-healthy",
|
|
87398
87839
|
"recording-degraded",
|
|
@@ -87661,6 +88102,15 @@ new Map([
|
|
|
87661
88102
|
snapshotLabel: "Cameras with constant motion now",
|
|
87662
88103
|
snapshotSection: null
|
|
87663
88104
|
},
|
|
88105
|
+
{
|
|
88106
|
+
id: "package-llm-confirm",
|
|
88107
|
+
family: "device-events",
|
|
88108
|
+
label: "Package confirm (not answering / answering again)",
|
|
88109
|
+
bad: ["package-llm-silent"],
|
|
88110
|
+
recovery: ["package-llm-answered"],
|
|
88111
|
+
snapshotLabel: "Cameras whose package confirm is not answering",
|
|
88112
|
+
snapshotSection: null
|
|
88113
|
+
},
|
|
87664
88114
|
{
|
|
87665
88115
|
id: "recording-health",
|
|
87666
88116
|
family: "device-events",
|