@camstack/addon-provider-velux 0.2.146 → 0.2.147
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
|
});
|
|
@@ -57466,21 +57870,21 @@ var ClimateControlStatusSchema = object({
|
|
|
57466
57870
|
/** Single setpoint in Celsius. Used by single-target modes
|
|
57467
57871
|
* (heat / cool / dry). Null when the device is in a range mode
|
|
57468
57872
|
* (`heat_cool`) or has no setpoint at all (`fan_only`/`off`). */
|
|
57469
|
-
target: number().nullable(),
|
|
57873
|
+
target: number().nullable().meta(readingMeta("temperature")),
|
|
57470
57874
|
/** Upper bound of the dual setpoint in Celsius. Populated only
|
|
57471
57875
|
* in `heat_cool` mode. */
|
|
57472
|
-
targetHigh: number().nullable(),
|
|
57876
|
+
targetHigh: number().nullable().meta(readingMeta("temperature")),
|
|
57473
57877
|
/** Lower bound of the dual setpoint in Celsius. Populated only
|
|
57474
57878
|
* in `heat_cool` mode. */
|
|
57475
|
-
targetLow: number().nullable(),
|
|
57879
|
+
targetLow: number().nullable().meta(readingMeta("temperature")),
|
|
57476
57880
|
/** Target relative humidity (0..100). Null when the device has no
|
|
57477
57881
|
* humidity control. */
|
|
57478
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
57882
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
57479
57883
|
/** Current measured temperature in Celsius. Read-only — pushed by
|
|
57480
57884
|
* the device's internal sensor. */
|
|
57481
|
-
currentTemp: number().nullable(),
|
|
57885
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
57482
57886
|
/** Current measured relative humidity (0..100). Read-only. */
|
|
57483
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
57887
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
57484
57888
|
/** Vertical louver swing on/off. Null when the device has no vertical
|
|
57485
57889
|
* swing surface (gate with `DeviceFeature.ClimateSwingVertical`). */
|
|
57486
57890
|
swingVertical: boolean().nullable(),
|
|
@@ -57488,11 +57892,11 @@ var ClimateControlStatusSchema = object({
|
|
|
57488
57892
|
* horizontal swing surface (gate with `DeviceFeature.ClimateSwingHorizontal`). */
|
|
57489
57893
|
swingHorizontal: boolean().nullable(),
|
|
57490
57894
|
/** Lowest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
57491
|
-
minTemp: number().nullable().optional(),
|
|
57895
|
+
minTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
57492
57896
|
/** Highest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
57493
|
-
maxTemp: number().nullable().optional(),
|
|
57897
|
+
maxTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
57494
57898
|
/** Setpoint granularity, Celsius (0.5, 1). Absent / null = not reported. */
|
|
57495
|
-
tempStep: number().positive().nullable().optional(),
|
|
57899
|
+
tempStep: number().positive().nullable().optional().meta(readingMeta("temperature")),
|
|
57496
57900
|
/** Ms epoch when the slice was last updated (push or command). */
|
|
57497
57901
|
lastFetchedAt: number()
|
|
57498
57902
|
});
|
|
@@ -57634,17 +58038,17 @@ var climateControlCapability = {
|
|
|
57634
58038
|
* modes to expose in the picker without a slice fetch.
|
|
57635
58039
|
*/
|
|
57636
58040
|
var RgbTripletSchema = object({
|
|
57637
|
-
r: number().int().min(0).max(255),
|
|
57638
|
-
g: number().int().min(0).max(255),
|
|
57639
|
-
b: number().int().min(0).max(255)
|
|
58041
|
+
r: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
58042
|
+
g: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
58043
|
+
b: number().int().min(0).max(255).meta(readingMeta("none"))
|
|
57640
58044
|
});
|
|
57641
58045
|
var HsvTripletSchema = object({
|
|
57642
58046
|
/** Hue in degrees, 0..360. */
|
|
57643
|
-
h: number().min(0).max(360),
|
|
58047
|
+
h: number().min(0).max(360).meta(readingMeta("none")),
|
|
57644
58048
|
/** Saturation as 0..100 inclusive. */
|
|
57645
|
-
s: number().min(0).max(100),
|
|
58049
|
+
s: number().min(0).max(100).meta(readingMeta("none")),
|
|
57646
58050
|
/** Value/brightness as 0..100 inclusive. */
|
|
57647
|
-
v: number().min(0).max(100)
|
|
58051
|
+
v: number().min(0).max(100).meta(readingMeta("none"))
|
|
57648
58052
|
});
|
|
57649
58053
|
var ColorInputSchema = discriminatedUnion("mode", [
|
|
57650
58054
|
object({
|
|
@@ -57673,7 +58077,7 @@ var ColorStatusSchema = object({
|
|
|
57673
58077
|
/** Populated when `mode === 'hsv'`. */
|
|
57674
58078
|
hsv: HsvTripletSchema.optional(),
|
|
57675
58079
|
/** Populated when `mode === 'mired'`. */
|
|
57676
|
-
mireds: number().int().optional(),
|
|
58080
|
+
mireds: number().int().optional().meta(readingMeta("colour-temperature")),
|
|
57677
58081
|
/** Ms epoch of the last operator-driven change. */
|
|
57678
58082
|
lastChangedAt: number()
|
|
57679
58083
|
});
|
|
@@ -57868,18 +58272,12 @@ _enum([
|
|
|
57868
58272
|
"empty",
|
|
57869
58273
|
"full"
|
|
57870
58274
|
]);
|
|
57871
|
-
/**
|
|
57872
|
-
|
|
57873
|
-
|
|
57874
|
-
"days",
|
|
57875
|
-
"hours",
|
|
57876
|
-
"cycles"
|
|
57877
|
-
]);
|
|
57878
|
-
/** Remaining life as a COUNT, not a percentage (the PetKit desiccant reports
|
|
57879
|
-
* days). `value` null = unknown (D393). */
|
|
58275
|
+
/** Whether `remaining.value` is a duration in seconds or a dimensionless count. */
|
|
58276
|
+
var ConsumableRemainingKindSchema = _enum(["duration", "count"]);
|
|
58277
|
+
/** Remaining life. `value` null = unknown (D393). Duration is seconds. */
|
|
57880
58278
|
var ConsumableRemainingSchema = object({
|
|
57881
|
-
value: number().min(0).nullable(),
|
|
57882
|
-
|
|
58279
|
+
value: number().min(0).nullable().meta(readingMeta("device")),
|
|
58280
|
+
kind: ConsumableRemainingKindSchema
|
|
57883
58281
|
});
|
|
57884
58282
|
/** A single consumable item. Either a continuous `level` (remaining
|
|
57885
58283
|
* life %, or fill % for a `supply` / `waste` item) or a discrete `status`
|
|
@@ -57892,7 +58290,7 @@ var ConsumableItemSchema = object({
|
|
|
57892
58290
|
/** Display name. */
|
|
57893
58291
|
label: string().min(1),
|
|
57894
58292
|
/** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
|
|
57895
|
-
level: number().min(0).max(100).nullable(),
|
|
58293
|
+
level: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
57896
58294
|
/** The provider's discrete verdict when known (binary mode). */
|
|
57897
58295
|
status: ConsumableStatusSchema.nullable(),
|
|
57898
58296
|
/** What the item is — decides whether low or full is bad. Absent = `wear`. */
|
|
@@ -57974,8 +58372,8 @@ var consumablesCustomize = {
|
|
|
57974
58372
|
transforms: [{ kind: "identity" }]
|
|
57975
58373
|
}],
|
|
57976
58374
|
literals: [{
|
|
57977
|
-
path: "remaining.
|
|
57978
|
-
values: [...
|
|
58375
|
+
path: "remaining.kind",
|
|
58376
|
+
values: [...ConsumableRemainingKindSchema.options]
|
|
57979
58377
|
}]
|
|
57980
58378
|
},
|
|
57981
58379
|
{
|
|
@@ -58104,7 +58502,6 @@ reset: method(object({
|
|
|
58104
58502
|
},
|
|
58105
58503
|
"remaining.value": {
|
|
58106
58504
|
kind: "gauge",
|
|
58107
|
-
unitFrom: "remaining.unit",
|
|
58108
58505
|
deadband: 1,
|
|
58109
58506
|
displayName: "Remaining"
|
|
58110
58507
|
}
|
|
@@ -58174,10 +58571,9 @@ var contactCapability = {
|
|
|
58174
58571
|
* (empty array for the other kinds). It lives in the slice because
|
|
58175
58572
|
* HA `select.*` entities may update their options at runtime.
|
|
58176
58573
|
*
|
|
58177
|
-
*
|
|
58178
|
-
*
|
|
58179
|
-
*
|
|
58180
|
-
* push — consistent with `options` and the sensor-unit approach.
|
|
58574
|
+
* Numeric `min` / `max` / `step` live in the slice and share the device
|
|
58575
|
+
* quantity (`SourceInfo.quantity`, D944). Display precision is a read-time
|
|
58576
|
+
* preference. A datetime control's shape is `SourceInfo.dateTimeShape`.
|
|
58181
58577
|
*/
|
|
58182
58578
|
var ControlStatusSchema = object({
|
|
58183
58579
|
kind: _enum([
|
|
@@ -58189,39 +58585,17 @@ var ControlStatusSchema = object({
|
|
|
58189
58585
|
/** Current value. Numeric kind → number; select/text/datetime → string.
|
|
58190
58586
|
* Datetime values are ISO 8601 strings (full timestamp, date-only,
|
|
58191
58587
|
* or time-only — HA accepts all three forms). */
|
|
58192
|
-
value: union([number(), string()]),
|
|
58588
|
+
value: union([number().meta(readingMeta("device")), string()]),
|
|
58193
58589
|
/** Acceptable values when `kind === 'select'`. Empty for other kinds. */
|
|
58194
58590
|
options: array(string()),
|
|
58195
58591
|
/** Ms epoch when the slice was last updated. */
|
|
58196
58592
|
lastChangedAt: number(),
|
|
58197
|
-
/**
|
|
58198
|
-
|
|
58199
|
-
|
|
58200
|
-
|
|
58201
|
-
/**
|
|
58202
|
-
|
|
58203
|
-
min: number().optional(),
|
|
58204
|
-
/** Maximum allowed value. Populated live from HA `attributes.max`.
|
|
58205
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
58206
|
-
max: number().optional(),
|
|
58207
|
-
/** Step increment. Populated live from HA `attributes.step`.
|
|
58208
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
58209
|
-
step: number().optional(),
|
|
58210
|
-
/** Suggested decimal places for numeric display. Populated live from HA
|
|
58211
|
-
* `attributes.suggested_display_precision`, or derived from `step` when the
|
|
58212
|
-
* HA attribute is absent. Meaningful for `kind === 'numeric'`; absent for
|
|
58213
|
-
* other kinds. Falls back to auto-formatting when absent. */
|
|
58214
|
-
precision: number().int().min(0).max(10).optional(),
|
|
58215
|
-
/** Date-picker granularity for `kind === 'datetime'`. 'date' → date-only,
|
|
58216
|
-
* 'time' → time-only, 'datetime' → full timestamp. Absent for other kinds
|
|
58217
|
-
* (UI defaults to 'datetime'). Derived live from the device's HA domain
|
|
58218
|
-
* (date.* / time.* / datetime.*) or, for input_datetime, from the entity's
|
|
58219
|
-
* `has_date`/`has_time` attributes on each push. */
|
|
58220
|
-
format: _enum([
|
|
58221
|
-
"date",
|
|
58222
|
-
"time",
|
|
58223
|
-
"datetime"
|
|
58224
|
-
]).optional()
|
|
58593
|
+
/** Minimum allowed value, in the device quantity's base unit. */
|
|
58594
|
+
min: number().optional().meta(readingMeta("device")),
|
|
58595
|
+
/** Maximum allowed value, in the device quantity's base unit. */
|
|
58596
|
+
max: number().optional().meta(readingMeta("device")),
|
|
58597
|
+
/** Step increment, in the device quantity's base unit. */
|
|
58598
|
+
step: number().optional().meta(readingMeta("device"))
|
|
58225
58599
|
});
|
|
58226
58600
|
var ControlSetValueInputSchema = discriminatedUnion("kind", [
|
|
58227
58601
|
object({
|
|
@@ -58287,9 +58661,9 @@ var CoverStatusSchema = object({
|
|
|
58287
58661
|
]),
|
|
58288
58662
|
/** 0 = fully closed, 100 = fully open. Null when the device has
|
|
58289
58663
|
* no intermediate position surface. */
|
|
58290
|
-
position: number().min(0).max(100).nullable(),
|
|
58664
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58291
58665
|
/** 0 = closed slats, 100 = open slats. Null when no tilt support. */
|
|
58292
|
-
tiltPosition: number().min(0).max(100).nullable(),
|
|
58666
|
+
tiltPosition: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58293
58667
|
/** Ms epoch when the slice was last updated. */
|
|
58294
58668
|
lastChangedAt: number()
|
|
58295
58669
|
});
|
|
@@ -58392,9 +58766,9 @@ var NormalizedRangeSchema$1 = object({
|
|
|
58392
58766
|
var DayNightStatusSchema = object({
|
|
58393
58767
|
mode: DayNightModeSchema,
|
|
58394
58768
|
/** IR-cut trigger sensitivity, NORMALIZED 0–100 (higher = switches to night sooner). */
|
|
58395
|
-
sensitivity: number().optional(),
|
|
58769
|
+
sensitivity: number().optional().meta(readingMeta("none")),
|
|
58396
58770
|
/** Delay before the IR-cut filter flips, in seconds. */
|
|
58397
|
-
switchDelaySec: number().optional(),
|
|
58771
|
+
switchDelaySec: number().optional().meta(readingMeta("duration")),
|
|
58398
58772
|
lastFetchedAt: number()
|
|
58399
58773
|
});
|
|
58400
58774
|
/**
|
|
@@ -58612,11 +58986,11 @@ var DishwasherStatusSchema = object({
|
|
|
58612
58986
|
/** Feature keys of the programs the appliance currently offers — drives the UI selector. */
|
|
58613
58987
|
availablePrograms: array(string()),
|
|
58614
58988
|
/** Seconds remaining on the active cycle, or null when not running / not known. */
|
|
58615
|
-
remainingSeconds: number().int().nonnegative().nullable(),
|
|
58989
|
+
remainingSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
58616
58990
|
/** Seconds the delayed start is set to (time until the cycle starts), or null. */
|
|
58617
|
-
delayedStartSeconds: number().int().nonnegative().nullable(),
|
|
58991
|
+
delayedStartSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
58618
58992
|
/** Cycle completion 0..100, or null when not applicable. */
|
|
58619
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
58993
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58620
58994
|
/** True when the door is reported open; null when the door state is not known. */
|
|
58621
58995
|
doorOpen: boolean().nullable(),
|
|
58622
58996
|
/** True when the door is latched (locked) during a cycle; null when not reported. */
|
|
@@ -58640,7 +59014,7 @@ var DishwasherStatusSchema = object({
|
|
|
58640
59014
|
/** True while the machine-care (descaling / cleaning-program) reminder is raised; false when clear; null when not reported. */
|
|
58641
59015
|
machineCareDue: boolean().nullable(),
|
|
58642
59016
|
/** Program runs left before the machine-care reminder is due; null when the appliance does not say. */
|
|
58643
|
-
machineCareRemainingRuns: number().int().nonnegative().nullable(),
|
|
59017
|
+
machineCareRemainingRuns: number().int().nonnegative().nullable().meta(readingMeta("count")),
|
|
58644
59018
|
/** Option states: null when the appliance does not expose the option or has not said. */
|
|
58645
59019
|
halfLoad: boolean().nullable(),
|
|
58646
59020
|
hygienePlus: boolean().nullable(),
|
|
@@ -58655,7 +59029,7 @@ var DishwasherStatusSchema = object({
|
|
|
58655
59029
|
/** Feature keys of the events currently raised (salt low, rinse aid low, program finished, …). */
|
|
58656
59030
|
activeEvents: array(string()),
|
|
58657
59031
|
/** Numeric error code when the appliance reports one; null otherwise. */
|
|
58658
|
-
errorCode: number().nullable(),
|
|
59032
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
58659
59033
|
/** Name of the raised alert-level event while the appliance is in error; null otherwise. */
|
|
58660
59034
|
errorLabel: string().nullable(),
|
|
58661
59035
|
/** Ms epoch of the last value received from the appliance; 0 = never. */
|
|
@@ -58886,7 +59260,7 @@ var DoorbellStatusSchema = object({
|
|
|
58886
59260
|
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
58887
59261
|
lastPressedAt: number().nullable(),
|
|
58888
59262
|
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
58889
|
-
pressCountSinceStart: number()
|
|
59263
|
+
pressCountSinceStart: number().meta(readingMeta("count"))
|
|
58890
59264
|
});
|
|
58891
59265
|
var DoorbellPressEventSchema = object({
|
|
58892
59266
|
deviceId: number(),
|
|
@@ -58951,17 +59325,7 @@ onPressed: {
|
|
|
58951
59325
|
history: "none",
|
|
58952
59326
|
customize: doorbellCustomize
|
|
58953
59327
|
};
|
|
58954
|
-
|
|
58955
|
-
* Enum-state sensor — a string value picked from a finite option set.
|
|
58956
|
-
* Drives HA `sensor` entries with `state_class: enum` (HVAC action
|
|
58957
|
-
* states, weather conditions, contact-source channels, mode strings).
|
|
58958
|
-
* The option set is stable across observations; it is persisted in the
|
|
58959
|
-
* device config blob (via the control slice at adoption) and is NOT
|
|
58960
|
-
* stored in `sourceInfo`.
|
|
58961
|
-
*/
|
|
58962
|
-
/** Locale-render shape for an ISO `value` carried by a `DateTimeSensor`-role
|
|
58963
|
-
* enum sensor: `date` (date-only), `time` (time-only), `datetime` (both). */
|
|
58964
|
-
var EnumSensorDateTimeFormatSchema = _enum([
|
|
59328
|
+
_enum([
|
|
58965
59329
|
"date",
|
|
58966
59330
|
"time",
|
|
58967
59331
|
"datetime"
|
|
@@ -58969,12 +59333,11 @@ var EnumSensorDateTimeFormatSchema = _enum([
|
|
|
58969
59333
|
var EnumSensorStatusSchema = object({
|
|
58970
59334
|
value: string(),
|
|
58971
59335
|
/**
|
|
58972
|
-
* Set
|
|
58973
|
-
* as
|
|
58974
|
-
*
|
|
58975
|
-
* a time-only sensor → `'time'`.
|
|
59336
|
+
* Set when `value` is a timestamp rather than an enum state, so history
|
|
59337
|
+
* does not learn ISO strings as states. The display shape (date / time /
|
|
59338
|
+
* datetime) lives on `SourceInfo.dateTimeShape`, written once at adopt.
|
|
58976
59339
|
*/
|
|
58977
|
-
|
|
59340
|
+
timestamp: boolean().optional(),
|
|
58978
59341
|
/** Ms epoch when the slice was last updated. */
|
|
58979
59342
|
lastFetchedAt: number()
|
|
58980
59343
|
});
|
|
@@ -59001,11 +59364,11 @@ var enumSensorCapability = {
|
|
|
59001
59364
|
* History (D850): the value as an `enum` series (an appliance's program or
|
|
59002
59365
|
* operation state, an HVAC action). The option set is per device, so the
|
|
59003
59366
|
* value list is LEARNED as values are first seen (bounded). A sensor with a
|
|
59004
|
-
* `
|
|
59367
|
+
* `timestamp` carries a clock, not a state, and is not recorded.
|
|
59005
59368
|
*/
|
|
59006
59369
|
history: { fields: { value: {
|
|
59007
59370
|
kind: "enum",
|
|
59008
|
-
skipWhenSet: "
|
|
59371
|
+
skipWhenSet: "timestamp"
|
|
59009
59372
|
} } },
|
|
59010
59373
|
/** Clock fields: written, but excluded from the compare that decides
|
|
59011
59374
|
* whether persisting is worth a SQLite commit. */
|
|
@@ -59025,13 +59388,13 @@ var EventFireSchema = object({
|
|
|
59025
59388
|
deviceId: number(),
|
|
59026
59389
|
eventType: string(),
|
|
59027
59390
|
data: record(string(), unknown()).nullable(),
|
|
59028
|
-
timestamp: number(),
|
|
59029
|
-
seq: number()
|
|
59391
|
+
timestamp: number().meta(readingMeta("none")),
|
|
59392
|
+
seq: number().meta(readingMeta("count"))
|
|
59030
59393
|
});
|
|
59031
59394
|
var EventEmitterStatusSchema = object({
|
|
59032
59395
|
eventTypes: array(string()),
|
|
59033
59396
|
lastEvent: EventFireSchema.nullable(),
|
|
59034
|
-
eventCountSinceStart: number()
|
|
59397
|
+
eventCountSinceStart: number().meta(readingMeta("count"))
|
|
59035
59398
|
});
|
|
59036
59399
|
var eventEmitterCapability = {
|
|
59037
59400
|
name: "event-emitter",
|
|
@@ -59444,10 +59807,10 @@ var FanDirectionSchema = _enum(["forward", "reverse"]);
|
|
|
59444
59807
|
var FanControlStatusSchema = object({
|
|
59445
59808
|
/** Active speed as 0..100 inclusive. Null when the device has no
|
|
59446
59809
|
* speed surface (single-speed fan). */
|
|
59447
|
-
percentage: number().min(0).max(100).nullable(),
|
|
59810
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59448
59811
|
/** Speed granularity the device accepts (HA `percentage_step`, e.g. 25 for
|
|
59449
59812
|
* a 4-speed fan). Absent when unknown — the UI then falls back to step 1. */
|
|
59450
|
-
percentageStep: number().positive().optional(),
|
|
59813
|
+
percentageStep: number().positive().optional().meta(readingMeta("percentage")),
|
|
59451
59814
|
/** Active preset mode (`auto` / `quiet` / `turbo` / vendor-specific)
|
|
59452
59815
|
* — empty string when no preset is active or supported. */
|
|
59453
59816
|
preset: string(),
|
|
@@ -59568,7 +59931,7 @@ var FeatureProbeStatusSchema = object({
|
|
|
59568
59931
|
/** Camera/firmware model string. `null` when the firmware doesn't expose it. */
|
|
59569
59932
|
model: string().nullable(),
|
|
59570
59933
|
/** Channel count for NVR/Hub devices; `1` for standalone cameras; `null` pre-probe. */
|
|
59571
|
-
channelCount: number().nullable(),
|
|
59934
|
+
channelCount: number().nullable().meta(readingMeta("count")),
|
|
59572
59935
|
/**
|
|
59573
59936
|
* Ms epoch of the last SUCCESSFUL probe. `0` before the first probe
|
|
59574
59937
|
* completes — drivers' `getAccessoryChildren()` should treat zero as
|
|
@@ -59691,9 +60054,91 @@ var gasCapability = {
|
|
|
59691
60054
|
* whether persisting is worth a SQLite commit. */
|
|
59692
60055
|
volatileStateFields: ["lastChangedAt"]
|
|
59693
60056
|
};
|
|
60057
|
+
var GroupCommandsSchema = object({
|
|
60058
|
+
/** One row per member that has been commanded. A later command replaces that member's row. */
|
|
60059
|
+
results: array(object({
|
|
60060
|
+
deviceId: number().int().nonnegative(),
|
|
60061
|
+
cap: string().min(1),
|
|
60062
|
+
method: string().min(1),
|
|
60063
|
+
ok: boolean(),
|
|
60064
|
+
error: string().optional(),
|
|
60065
|
+
/** Ms epoch of the attempt. */
|
|
60066
|
+
at: number()
|
|
60067
|
+
})) });
|
|
60068
|
+
var groupCommandsCapability = {
|
|
60069
|
+
name: "group-commands",
|
|
60070
|
+
scope: "device",
|
|
60071
|
+
deviceNative: true,
|
|
60072
|
+
mode: "singleton",
|
|
60073
|
+
deviceTypes: [DeviceType.Switch, DeviceType.Light],
|
|
60074
|
+
methods: {},
|
|
60075
|
+
status: {
|
|
60076
|
+
schema: GroupCommandsSchema,
|
|
60077
|
+
kind: "push"
|
|
60078
|
+
},
|
|
60079
|
+
runtimeState: GroupCommandsSchema,
|
|
60080
|
+
/**
|
|
60081
|
+
* Runtime-state durability: **session** — the last attempt. A restored
|
|
60082
|
+
* failure would outlive the command that caused it.
|
|
60083
|
+
*
|
|
60084
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
60085
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
60086
|
+
*/
|
|
60087
|
+
durability: "session",
|
|
60088
|
+
history: "none"
|
|
60089
|
+
};
|
|
60090
|
+
/**
|
|
60091
|
+
* How many members of a helper group answered (D944). Counts are integers,
|
|
60092
|
+
* not measurements: zero included is a real count, never a stand-in reading.
|
|
60093
|
+
* The reading itself stays on the output capability. History is none — the
|
|
60094
|
+
* series that later statistics read is the output cap's own history block.
|
|
60095
|
+
*/
|
|
60096
|
+
var GroupStatusSchema = object({
|
|
60097
|
+
/** Members whose current value entered the aggregate. */
|
|
60098
|
+
included: number().int().nonnegative().meta(readingMeta("count", {
|
|
60099
|
+
precision: 0,
|
|
60100
|
+
label: "Reporting"
|
|
60101
|
+
})),
|
|
60102
|
+
/** Members left out: offline, unknown, or not a finite reading (D393). */
|
|
60103
|
+
excluded: number().int().nonnegative().meta(readingMeta("count", {
|
|
60104
|
+
precision: 0,
|
|
60105
|
+
label: "Excluded"
|
|
60106
|
+
})),
|
|
60107
|
+
/** `included` + `excluded`. */
|
|
60108
|
+
total: number().int().nonnegative().meta(readingMeta("count", {
|
|
60109
|
+
precision: 0,
|
|
60110
|
+
label: "Members"
|
|
60111
|
+
}))
|
|
60112
|
+
});
|
|
60113
|
+
var groupStatusCapability = {
|
|
60114
|
+
name: "group-status",
|
|
60115
|
+
scope: "device",
|
|
60116
|
+
deviceNative: true,
|
|
60117
|
+
mode: "singleton",
|
|
60118
|
+
deviceTypes: [
|
|
60119
|
+
DeviceType.Sensor,
|
|
60120
|
+
DeviceType.Switch,
|
|
60121
|
+
DeviceType.Light
|
|
60122
|
+
],
|
|
60123
|
+
methods: {},
|
|
60124
|
+
status: {
|
|
60125
|
+
schema: GroupStatusSchema,
|
|
60126
|
+
kind: "push"
|
|
60127
|
+
},
|
|
60128
|
+
runtimeState: GroupStatusSchema,
|
|
60129
|
+
/**
|
|
60130
|
+
* Runtime-state durability: **session** — recomputed from members on the
|
|
60131
|
+
* next source event; a restored count would outlive the readings it named.
|
|
60132
|
+
*
|
|
60133
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
60134
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
60135
|
+
*/
|
|
60136
|
+
durability: "session",
|
|
60137
|
+
history: "none"
|
|
60138
|
+
};
|
|
59694
60139
|
var HeatingValveStatusSchema = object({
|
|
59695
60140
|
/** Radiator valve opening 0 (closed) .. 100 (open). Null = not yet known. */
|
|
59696
|
-
position: number().min(0).max(100).nullable(),
|
|
60141
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59697
60142
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
59698
60143
|
lastFetchedAt: number()
|
|
59699
60144
|
});
|
|
@@ -59736,9 +60181,9 @@ var HumidifierStatusSchema = object({
|
|
|
59736
60181
|
/** Whether the humidifier is currently on. */
|
|
59737
60182
|
on: boolean(),
|
|
59738
60183
|
/** Current measured relative humidity (0..100). Null when not reported. */
|
|
59739
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
60184
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
59740
60185
|
/** Target relative humidity (0..100). Null when no setpoint surface. */
|
|
59741
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
60186
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
59742
60187
|
/** Active mode (`auto` / `normal` / `baby` / vendor). Null when the
|
|
59743
60188
|
* device has no mode surface. */
|
|
59744
60189
|
mode: string().nullable(),
|
|
@@ -59748,9 +60193,9 @@ var HumidifierStatusSchema = object({
|
|
|
59748
60193
|
* `idle` / `off`). Null when the device doesn't report it. */
|
|
59749
60194
|
action: string().nullable(),
|
|
59750
60195
|
/** HA `min_humidity` attribute. Null → UI uses 0. */
|
|
59751
|
-
minHumidity: number().nullable(),
|
|
60196
|
+
minHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
59752
60197
|
/** HA `max_humidity` attribute. Null → UI uses 100. */
|
|
59753
|
-
maxHumidity: number().nullable(),
|
|
60198
|
+
maxHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
59754
60199
|
/** Ms epoch when the slice was last updated. */
|
|
59755
60200
|
lastChangedAt: number()
|
|
59756
60201
|
});
|
|
@@ -59820,22 +60265,13 @@ var humidifierCapability = {
|
|
|
59820
60265
|
* `sourceInfo`.
|
|
59821
60266
|
*/
|
|
59822
60267
|
var HumiditySensorStatusSchema = object({
|
|
59823
|
-
/** Current relative humidity, 0..100. */
|
|
59824
|
-
percent: number().min(0).max(100).meta({
|
|
59825
|
-
|
|
60268
|
+
/** Current relative humidity, 0..100. `null` when the sample was refused (D393). */
|
|
60269
|
+
percent: number().min(0).max(100).nullable().meta(readingMeta("humidity", {
|
|
60270
|
+
precision: 0,
|
|
59826
60271
|
label: "Humidity"
|
|
59827
|
-
}),
|
|
60272
|
+
})),
|
|
59828
60273
|
/** Ms epoch when the slice was last updated. */
|
|
59829
|
-
lastFetchedAt: number()
|
|
59830
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
59831
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
59832
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
59833
|
-
unit: string().optional(),
|
|
59834
|
-
/** Suggested decimal places for numeric display.
|
|
59835
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
59836
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
59837
|
-
* auto-formatting when absent. */
|
|
59838
|
-
precision: number().int().min(0).max(10).optional()
|
|
60274
|
+
lastFetchedAt: number()
|
|
59839
60275
|
});
|
|
59840
60276
|
var humiditySensorCapability = {
|
|
59841
60277
|
name: "humidity-sensor",
|
|
@@ -59866,12 +60302,7 @@ var humiditySensorCapability = {
|
|
|
59866
60302
|
} } },
|
|
59867
60303
|
/** Clock fields: written, but excluded from the compare that decides
|
|
59868
60304
|
* whether persisting is worth a SQLite commit. */
|
|
59869
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
59870
|
-
customize: {
|
|
59871
|
-
version: 1,
|
|
59872
|
-
advanced: "derive",
|
|
59873
|
-
targets: []
|
|
59874
|
-
}
|
|
60305
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
59875
60306
|
};
|
|
59876
60307
|
/**
|
|
59877
60308
|
* Image display cap. Models a single still image exposed by an integration —
|
|
@@ -59892,7 +60323,7 @@ var ImageStatusSchema = object({
|
|
|
59892
60323
|
* entity exposes no `entity_picture` (yet). */
|
|
59893
60324
|
url: string().nullable(),
|
|
59894
60325
|
/** Ms epoch of the upstream last-updated timestamp. Null at cold-start. */
|
|
59895
|
-
lastUpdated: number().nullable()
|
|
60326
|
+
lastUpdated: number().nullable().meta(readingMeta("none"))
|
|
59896
60327
|
});
|
|
59897
60328
|
var imageCapability = {
|
|
59898
60329
|
name: "image",
|
|
@@ -59980,19 +60411,19 @@ var NormalizedRangeSchema = object({
|
|
|
59980
60411
|
*/
|
|
59981
60412
|
var ImageSettingsStatusSchema = object({
|
|
59982
60413
|
/** Normalized 0–100. */
|
|
59983
|
-
brightness: number().optional(),
|
|
60414
|
+
brightness: number().optional().meta(readingMeta("none")),
|
|
59984
60415
|
/** Normalized 0–100. */
|
|
59985
|
-
contrast: number().optional(),
|
|
60416
|
+
contrast: number().optional().meta(readingMeta("none")),
|
|
59986
60417
|
/** Normalized 0–100. */
|
|
59987
|
-
saturation: number().optional(),
|
|
60418
|
+
saturation: number().optional().meta(readingMeta("none")),
|
|
59988
60419
|
/** Normalized 0–100. */
|
|
59989
|
-
sharpness: number().optional(),
|
|
60420
|
+
sharpness: number().optional().meta(readingMeta("none")),
|
|
59990
60421
|
mirror: boolean().optional(),
|
|
59991
60422
|
flip: boolean().optional(),
|
|
59992
60423
|
rotate: ImageRotateSchema.optional(),
|
|
59993
60424
|
whiteBalance: WhiteBalanceModeSchema.optional(),
|
|
59994
60425
|
/** Manual white-balance warmth, NORMALIZED 0–100. Meaningful only when `whiteBalance === 'manual'`. */
|
|
59995
|
-
warmth: number().optional(),
|
|
60426
|
+
warmth: number().optional().meta(readingMeta("none")),
|
|
59996
60427
|
exposureMode: ExposureModeSchema.optional(),
|
|
59997
60428
|
backlightMode: BacklightModeSchema.optional(),
|
|
59998
60429
|
lastFetchedAt: number()
|
|
@@ -60271,10 +60702,10 @@ var IntercomAbilitySchema = object({
|
|
|
60271
60702
|
/** Codecs accepted by firmware, in preference order. Driver-authored strings. */
|
|
60272
60703
|
codecs: array(string()),
|
|
60273
60704
|
/** Sample rate (Hz) the firmware expects. Reolink typical: 16000. */
|
|
60274
|
-
sampleRate: number(),
|
|
60705
|
+
sampleRate: number().meta(readingMeta("none")),
|
|
60275
60706
|
duplex: _enum(["half", "full"]),
|
|
60276
60707
|
/** Max in-flight audio backlog before drop (ms). Server uses this to bound latency. */
|
|
60277
|
-
maxBacklogMs: number()
|
|
60708
|
+
maxBacklogMs: number().meta(readingMeta("duration-ms"))
|
|
60278
60709
|
});
|
|
60279
60710
|
var IntercomStatusSchema = object({
|
|
60280
60711
|
/** True while a talk session is open. */
|
|
@@ -60501,13 +60932,13 @@ var LawnMowerControlStatusSchema = object({
|
|
|
60501
60932
|
activity: LawnMowerActivitySchema,
|
|
60502
60933
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
60503
60934
|
* reading. */
|
|
60504
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
60935
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
60505
60936
|
/** 0..100 mowing-completion percentage of the current task, or null when no
|
|
60506
60937
|
* task is active / progress is unavailable. */
|
|
60507
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
60938
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
60508
60939
|
/** Current device/event code (dynamic — mostly status, sometimes an error),
|
|
60509
60940
|
* or null when unknown. */
|
|
60510
|
-
currentCode: number().nullable(),
|
|
60941
|
+
currentCode: number().nullable().meta(readingMeta("none")),
|
|
60511
60942
|
/** Human label for {@link currentCode}, or null when undecodable. */
|
|
60512
60943
|
currentCodeLabel: string().nullable(),
|
|
60513
60944
|
/** Severity of {@link currentCode}. `error` (and often `warning`) warrants UI
|
|
@@ -61040,7 +61471,7 @@ var MediaPlayerStatusSchema = object({
|
|
|
61040
61471
|
state: MediaPlayerStateSchema,
|
|
61041
61472
|
/** Volume as 0..100 inclusive. Null when the device has no volume
|
|
61042
61473
|
* surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
|
|
61043
|
-
volumeLevel: number().min(0).max(100).nullable(),
|
|
61474
|
+
volumeLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61044
61475
|
/** Mute toggle distinct from volume=0. Null when no mute surface.
|
|
61045
61476
|
* Pair with `DeviceFeature.MediaPlayerMute`. */
|
|
61046
61477
|
isMuted: boolean().nullable(),
|
|
@@ -61053,10 +61484,10 @@ var MediaPlayerStatusSchema = object({
|
|
|
61053
61484
|
currentMedia: MediaInfoSchema.nullable(),
|
|
61054
61485
|
/** Current playback position in ms. Null when not seekable or
|
|
61055
61486
|
* nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
|
|
61056
|
-
positionMs: number().int().nonnegative().nullable(),
|
|
61487
|
+
positionMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
61057
61488
|
/** Total duration of the current media in ms. Null when unknown
|
|
61058
61489
|
* (live stream) or nothing is playing. */
|
|
61059
|
-
durationMs: number().int().nonnegative().nullable(),
|
|
61490
|
+
durationMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
61060
61491
|
/** Shuffle toggle. Null when no shuffle surface.
|
|
61061
61492
|
* Pair with `DeviceFeature.MediaPlayerShuffle`. */
|
|
61062
61493
|
shuffle: boolean().nullable(),
|
|
@@ -61365,7 +61796,7 @@ var motionCustomize = {
|
|
|
61365
61796
|
eventName: "onMotionChanged"
|
|
61366
61797
|
},
|
|
61367
61798
|
deviceTypes: [DeviceType.Camera],
|
|
61368
|
-
apply: "
|
|
61799
|
+
apply: "add",
|
|
61369
61800
|
applyAuthority: {
|
|
61370
61801
|
kind: "camera-sensors",
|
|
61371
61802
|
timeoutField: "motionCooldownMs"
|
|
@@ -61437,7 +61868,7 @@ var MotionStatusSchema = object({
|
|
|
61437
61868
|
* it, every provider seeded it at boot, and every session left it
|
|
61438
61869
|
* `detected: true` after its detach.
|
|
61439
61870
|
*/
|
|
61440
|
-
autoClearAfterMs: number().nullable()
|
|
61871
|
+
autoClearAfterMs: number().nullable().meta(readingMeta("duration-ms"))
|
|
61441
61872
|
});
|
|
61442
61873
|
/**
|
|
61443
61874
|
* Payload of `motion.onMotionChanged` event + the corresponding bus
|
|
@@ -61474,12 +61905,18 @@ var motionCapability = {
|
|
|
61474
61905
|
methods: {
|
|
61475
61906
|
/**
|
|
61476
61907
|
* Pull the current motion state synchronously. Convenience shortcut
|
|
61477
|
-
* for consumers that don't need the full status object
|
|
61478
|
-
*
|
|
61479
|
-
* `getStatus` once the auto-injected status surface lands in every
|
|
61480
|
-
* consumer.
|
|
61908
|
+
* for consumers that don't need the full status object. A composed
|
|
61909
|
+
* group answers from its slice (D944): unknown throws, it is not off.
|
|
61481
61910
|
*/
|
|
61482
61911
|
isDetected: method(object({ deviceId: number() }), boolean()) },
|
|
61912
|
+
/**
|
|
61913
|
+
* A composed motion group serves `isDetected` from `detected` (D944).
|
|
61914
|
+
* Without this the cap stays uncomposable (`has-commands`).
|
|
61915
|
+
*/
|
|
61916
|
+
composedMethods: { isDetected: {
|
|
61917
|
+
kind: "slice",
|
|
61918
|
+
field: "detected"
|
|
61919
|
+
} },
|
|
61483
61920
|
events: {
|
|
61484
61921
|
/**
|
|
61485
61922
|
* Fires every time the runner transitions a camera between
|
|
@@ -61619,7 +62056,7 @@ var MotionZoneRegionSchema = object({
|
|
|
61619
62056
|
* the grid region(s). */
|
|
61620
62057
|
var MotionZoneStatusSchema = object({
|
|
61621
62058
|
enabled: boolean(),
|
|
61622
|
-
sensitivity: number(),
|
|
62059
|
+
sensitivity: number().meta(readingMeta("none")),
|
|
61623
62060
|
/** Grid region(s). Today exactly one `grid` shape. */
|
|
61624
62061
|
regions: array(MotionZoneRegionSchema),
|
|
61625
62062
|
lastFetchedAt: number()
|
|
@@ -61989,7 +62426,7 @@ var NavigationStatusSchema = object({
|
|
|
61989
62426
|
following: boolean(),
|
|
61990
62427
|
flash: boolean(),
|
|
61991
62428
|
lightMode: NavigationLightModeSchema,
|
|
61992
|
-
lightLevel: number().min(40).max(100),
|
|
62429
|
+
lightLevel: number().min(40).max(100).meta(readingMeta("none")),
|
|
61993
62430
|
/** Ms epoch when the slice was last updated. */
|
|
61994
62431
|
lastChangedAt: number()
|
|
61995
62432
|
});
|
|
@@ -62123,13 +62560,13 @@ var NetworkLinkStatusSchema = object({
|
|
|
62123
62560
|
* one whose reading has not landed must not be drawn at 0 %. Consumers
|
|
62124
62561
|
* SKIP a null rather than coerce it.
|
|
62125
62562
|
*/
|
|
62126
|
-
signalPercent: number().min(0).max(100).nullable(),
|
|
62563
|
+
signalPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
62127
62564
|
/** Raw received signal strength in dBm, when the firmware reports one. */
|
|
62128
|
-
rssiDbm: number().optional(),
|
|
62565
|
+
rssiDbm: number().optional().meta(readingMeta("signal-level")),
|
|
62129
62566
|
/** Network name of a wireless link, when the firmware reports it. */
|
|
62130
62567
|
ssid: string().optional(),
|
|
62131
62568
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
62132
|
-
lastUpdated: number()
|
|
62569
|
+
lastUpdated: number().meta(readingMeta("none"))
|
|
62133
62570
|
});
|
|
62134
62571
|
var networkLinkCapability = {
|
|
62135
62572
|
name: "network-link",
|
|
@@ -62514,7 +62951,7 @@ var NotifierStatusSchema = object({
|
|
|
62514
62951
|
lastError: string().nullable(),
|
|
62515
62952
|
/** Number of deliveries currently buffered server-side (rate-limited
|
|
62516
62953
|
* notifiers may queue). 0 when the provider sends synchronously. */
|
|
62517
|
-
queueDepth: number().int().nonnegative(),
|
|
62954
|
+
queueDepth: number().int().nonnegative().meta(readingMeta("count")),
|
|
62518
62955
|
/** Per-feature capability matrix — authoritative source for the
|
|
62519
62956
|
* compose-form field gating. */
|
|
62520
62957
|
supports: NotifierSupportsSchema
|
|
@@ -62606,11 +63043,9 @@ onSent: { data: object({
|
|
|
62606
63043
|
* cap fits (HA `sensor` whose `device_class` we don't have a typed cap
|
|
62607
63044
|
* for: water flow, distance, weight, frequency, signal strength, …).
|
|
62608
63045
|
*
|
|
62609
|
-
* The
|
|
62610
|
-
*
|
|
62611
|
-
*
|
|
62612
|
-
* The UI reads them directly from the slice — they are the single source
|
|
62613
|
-
* of truth for generic numeric rendering and do NOT live on `sourceInfo`.
|
|
63046
|
+
* The quantity is not on this slice. It is chosen when the device is
|
|
63047
|
+
* adopted and stored once on `SourceInfo.quantity` (D944). `value` is in
|
|
63048
|
+
* that quantity's base unit. `null` is a refused sample (D393).
|
|
62614
63049
|
*
|
|
62615
63050
|
* Prefer the typed alternatives (`temperature-sensor`, `humidity-sensor`,
|
|
62616
63051
|
* `ambient-light-sensor`, `pressure-sensor`, `power-meter`,
|
|
@@ -62619,15 +63054,8 @@ onSent: { data: object({
|
|
|
62619
63054
|
* numeric values land here.
|
|
62620
63055
|
*/
|
|
62621
63056
|
var NumericSensorStatusSchema = object({
|
|
62622
|
-
|
|
62623
|
-
|
|
62624
|
-
* Populated live from the upstream source on each state push.
|
|
62625
|
-
* Absent for unitless sensors. */
|
|
62626
|
-
unit: string().optional(),
|
|
62627
|
-
/** Suggested decimal places for numeric display.
|
|
62628
|
-
* Populated live from the upstream source when provided.
|
|
62629
|
-
* Falls back to auto-formatting when absent. */
|
|
62630
|
-
precision: number().int().min(0).max(10).optional(),
|
|
63057
|
+
/** Reading in the device quantity's base unit. `null` when refused (D393). */
|
|
63058
|
+
value: number().nullable().meta(readingMeta("device")),
|
|
62631
63059
|
/** Ms epoch when the slice was last updated. */
|
|
62632
63060
|
lastFetchedAt: number()
|
|
62633
63061
|
});
|
|
@@ -62651,11 +63079,11 @@ var numericSensorCapability = {
|
|
|
62651
63079
|
*/
|
|
62652
63080
|
durability: "restored",
|
|
62653
63081
|
/**
|
|
62654
|
-
* History (D850): recorded series. The unit is
|
|
63082
|
+
* History (D850): recorded series. The unit is the device quantity's base,
|
|
63083
|
+
* resolved when the series is read — the cap has no single unit.
|
|
62655
63084
|
*/
|
|
62656
63085
|
history: { fields: { value: {
|
|
62657
63086
|
kind: "gauge",
|
|
62658
|
-
unitFrom: "unit",
|
|
62659
63087
|
minIntervalMs: 3e4
|
|
62660
63088
|
} } },
|
|
62661
63089
|
/** Clock fields: written, but excluded from the compare that decides
|
|
@@ -62947,23 +63375,26 @@ var PetFeederStatusSchema = object({
|
|
|
62947
63375
|
/** Food currently in the bowl (grams). Null when the device has not
|
|
62948
63376
|
* reported a reading yet. On dual-hopper models this is the combined
|
|
62949
63377
|
* bowl reading; per-hopper levels live in `food1`/`food2`. */
|
|
62950
|
-
foodLevel: number().nullable(),
|
|
63378
|
+
foodLevel: number().nullable().meta(readingMeta("none")),
|
|
62951
63379
|
/** Hopper-1 food level (grams) on dual-hopper feeders; null on
|
|
62952
63380
|
* single-hopper models. */
|
|
62953
|
-
food1: number().nullable(),
|
|
63381
|
+
food1: number().nullable().meta(readingMeta("none")),
|
|
62954
63382
|
/** Hopper-2 food level (grams) on dual-hopper feeders; null on
|
|
62955
63383
|
* single-hopper models. */
|
|
62956
|
-
food2: number().nullable(),
|
|
63384
|
+
food2: number().nullable().meta(readingMeta("none")),
|
|
62957
63385
|
/** Derived low-food flag — mirrors the HA `food_level` binary_sensor
|
|
62958
63386
|
* (`device_class: problem`, on = low). True when the bowl is empty /
|
|
62959
63387
|
* below the feeder's low threshold. */
|
|
62960
63388
|
lowFood: boolean(),
|
|
62961
63389
|
/** Battery charge 0..100 (%). Null on mains-powered models or when the
|
|
62962
63390
|
* device has no battery reading. */
|
|
62963
|
-
batteryPower: number().min(0).max(100).nullable(),
|
|
62964
|
-
/**
|
|
62965
|
-
*
|
|
62966
|
-
|
|
63391
|
+
batteryPower: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
63392
|
+
/**
|
|
63393
|
+
* Desiccant life remaining, stored in seconds (duration base, D944).
|
|
63394
|
+
* Providers convert from the days the feeder reports. Null when the
|
|
63395
|
+
* model has no desiccant sensor.
|
|
63396
|
+
*/
|
|
63397
|
+
desiccantLeftDays: number().nullable().meta(readingMeta("duration")),
|
|
62967
63398
|
/** True while a feed is in progress. */
|
|
62968
63399
|
feeding: boolean(),
|
|
62969
63400
|
/** Decoded connectivity / power status (HA petkit device-status enum).
|
|
@@ -62974,7 +63405,7 @@ var PetFeederStatusSchema = object({
|
|
|
62974
63405
|
* with `errorCode` for consumers that want the raw integer. */
|
|
62975
63406
|
error: string().nullable(),
|
|
62976
63407
|
/** Raw device error code (0 / null = no error). */
|
|
62977
|
-
errorCode: number().nullable(),
|
|
63408
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
62978
63409
|
/** True for D4S/D4SH dual-hopper hardware — gates the per-hopper UI. */
|
|
62979
63410
|
isDualHopper: boolean(),
|
|
62980
63411
|
/** Child-lock (manual-lock) setting — buttons on the unit are disabled. */
|
|
@@ -62984,7 +63415,7 @@ var PetFeederStatusSchema = object({
|
|
|
62984
63415
|
/** Play a chime when dispensing. */
|
|
62985
63416
|
feedSound: boolean(),
|
|
62986
63417
|
/** Speaker / prompt volume level (device-scaled integer). */
|
|
62987
|
-
volume: number(),
|
|
63418
|
+
volume: number().meta(readingMeta("none")),
|
|
62988
63419
|
/** Ms epoch when the slice was last refreshed from the cloud. */
|
|
62989
63420
|
lastFetchedAt: number()
|
|
62990
63421
|
});
|
|
@@ -63103,7 +63534,7 @@ var petFeederCapability = {
|
|
|
63103
63534
|
},
|
|
63104
63535
|
desiccantLeftDays: {
|
|
63105
63536
|
kind: "gauge",
|
|
63106
|
-
unit: "
|
|
63537
|
+
unit: "s"
|
|
63107
63538
|
}
|
|
63108
63539
|
} }
|
|
63109
63540
|
};
|
|
@@ -63504,36 +63935,19 @@ method(_void(), PlatformCapabilitiesSchema), method(_void(), HardwareInfoSchema)
|
|
|
63504
63935
|
*/
|
|
63505
63936
|
var PowerMeterStatusSchema = object({
|
|
63506
63937
|
/** Instantaneous power draw in watts. */
|
|
63507
|
-
watts: number().optional().meta({
|
|
63508
|
-
unit: "W",
|
|
63509
|
-
label: "Power"
|
|
63510
|
-
}),
|
|
63938
|
+
watts: number().optional().meta(readingMeta("power", { label: "Power" })),
|
|
63511
63939
|
/** Cumulative energy in kilowatt-hours since the meter was reset. */
|
|
63512
|
-
kwhTotal: number().optional().meta({
|
|
63513
|
-
unit: "kWh",
|
|
63514
|
-
label: "Energy"
|
|
63515
|
-
}),
|
|
63940
|
+
kwhTotal: number().optional().meta(readingMeta("energy", { label: "Energy" })),
|
|
63516
63941
|
/** Voltage in volts. */
|
|
63517
|
-
volts: number().optional(),
|
|
63942
|
+
volts: number().optional().meta(readingMeta("voltage")),
|
|
63518
63943
|
/** Current in amperes. */
|
|
63519
|
-
amps: number().optional(),
|
|
63520
|
-
/** Apparent power in volt-amperes
|
|
63521
|
-
va: number().optional(),
|
|
63944
|
+
amps: number().optional().meta(readingMeta("current")),
|
|
63945
|
+
/** Apparent power in volt-amperes. */
|
|
63946
|
+
va: number().optional().meta(readingMeta("apparent-power")),
|
|
63522
63947
|
/** Power factor (0..1) if reported. */
|
|
63523
|
-
powerFactor: number().min(0).max(1).optional(),
|
|
63948
|
+
powerFactor: number().min(0).max(1).optional().meta(readingMeta("ratio")),
|
|
63524
63949
|
/** Ms epoch when the slice was last updated. */
|
|
63525
|
-
lastFetchedAt: number()
|
|
63526
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
63527
|
-
* `attributes.unit_of_measurement` → 'V' / 'A' / 'W' / 'kW' / 'kWh').
|
|
63528
|
-
* Each upstream `sensor.*` entity surfaces ONE device_class, so one
|
|
63529
|
-
* unit per slice is unambiguous. The UI prefers this over the role's
|
|
63530
|
-
* canonical unit so a 'kW' / 'Wh' feed renders verbatim. */
|
|
63531
|
-
unit: string().optional(),
|
|
63532
|
-
/** Suggested decimal places for numeric display.
|
|
63533
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
63534
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
63535
|
-
* auto-formatting when absent. */
|
|
63536
|
-
precision: number().int().min(0).max(10).optional()
|
|
63950
|
+
lastFetchedAt: number()
|
|
63537
63951
|
});
|
|
63538
63952
|
var powerMeterCapability = {
|
|
63539
63953
|
name: "power-meter",
|
|
@@ -63597,12 +64011,7 @@ var powerMeterCapability = {
|
|
|
63597
64011
|
} },
|
|
63598
64012
|
/** Clock fields: written, but excluded from the compare that decides
|
|
63599
64013
|
* whether persisting is worth a SQLite commit. */
|
|
63600
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
63601
|
-
customize: {
|
|
63602
|
-
version: 1,
|
|
63603
|
-
advanced: "derive",
|
|
63604
|
-
targets: []
|
|
63605
|
-
}
|
|
64014
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
63606
64015
|
};
|
|
63607
64016
|
/**
|
|
63608
64017
|
* Presence cap. Models HA `person.*` and `device_tracker.*` entities
|
|
@@ -63622,11 +64031,11 @@ var powerMeterCapability = {
|
|
|
63622
64031
|
*/
|
|
63623
64032
|
var GpsLocationSchema = object({
|
|
63624
64033
|
/** Latitude in decimal degrees, -90..90. */
|
|
63625
|
-
latitude: number().min(-90).max(90),
|
|
64034
|
+
latitude: number().min(-90).max(90).meta(readingMeta("angle")),
|
|
63626
64035
|
/** Longitude in decimal degrees, -180..180. */
|
|
63627
|
-
longitude: number().min(-180).max(180),
|
|
64036
|
+
longitude: number().min(-180).max(180).meta(readingMeta("angle")),
|
|
63628
64037
|
/** Reported accuracy in meters (lower = better). */
|
|
63629
|
-
accuracyMeters: number().nonnegative()
|
|
64038
|
+
accuracyMeters: number().nonnegative().meta(readingMeta("length"))
|
|
63630
64039
|
});
|
|
63631
64040
|
var PresenceStatusSchema = object({
|
|
63632
64041
|
/** `home` / `not_home` / any user-defined zone name. */
|
|
@@ -63638,7 +64047,7 @@ var PresenceStatusSchema = object({
|
|
|
63638
64047
|
gps: GpsLocationSchema.nullable(),
|
|
63639
64048
|
/** Optional battery level of the tracking device (0..100). Null
|
|
63640
64049
|
* when not reported. */
|
|
63641
|
-
batteryPercent: number().min(0).max(100).nullable(),
|
|
64050
|
+
batteryPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
63642
64051
|
/** Ms epoch when the slice was last updated. */
|
|
63643
64052
|
lastChangedAt: number()
|
|
63644
64053
|
});
|
|
@@ -63688,19 +64097,10 @@ var presenceCapability = {
|
|
|
63688
64097
|
* `sourceInfo`.
|
|
63689
64098
|
*/
|
|
63690
64099
|
var PressureSensorStatusSchema = object({
|
|
63691
|
-
/** Current pressure in hPa. */
|
|
63692
|
-
hpa: number(),
|
|
64100
|
+
/** Current pressure in hPa. `null` when the sample was refused (D393). */
|
|
64101
|
+
hpa: number().nullable().meta(readingMeta("pressure", { precision: 0 })),
|
|
63693
64102
|
/** Ms epoch when the slice was last updated. */
|
|
63694
|
-
lastFetchedAt: number()
|
|
63695
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
63696
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
63697
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
63698
|
-
unit: string().optional(),
|
|
63699
|
-
/** Suggested decimal places for numeric display.
|
|
63700
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
63701
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
63702
|
-
* auto-formatting when absent. */
|
|
63703
|
-
precision: number().int().min(0).max(10).optional()
|
|
64103
|
+
lastFetchedAt: number()
|
|
63704
64104
|
});
|
|
63705
64105
|
var pressureSensorCapability = {
|
|
63706
64106
|
name: "pressure-sensor",
|
|
@@ -64114,8 +64514,8 @@ DeviceType.Camera, method(PtzMoveCommandSchema.extend({ deviceId: number() }), _
|
|
|
64114
64514
|
}), _void(), { kind: "mutation" });
|
|
64115
64515
|
var PtzAutotrackSettingsSchema = object({
|
|
64116
64516
|
targetType: string().describe("Vendor target string (people/vehicle/pet); empty = camera default"),
|
|
64117
|
-
stopDelaySeconds: number().int().min(0).max(300),
|
|
64118
|
-
disappearDelaySeconds: number().int().min(0).max(300)
|
|
64517
|
+
stopDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration")),
|
|
64518
|
+
disappearDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration"))
|
|
64119
64519
|
});
|
|
64120
64520
|
/**
|
|
64121
64521
|
* One option the camera advertises as a valid `targetType`. Drivers
|
|
@@ -64269,7 +64669,7 @@ var RunningStateStatusSchema = object({
|
|
|
64269
64669
|
/** null = unknown — never coerced to false (D393). */
|
|
64270
64670
|
running: boolean().nullable(),
|
|
64271
64671
|
/** Epoch ms the current boolean began; null while `running` is null. */
|
|
64272
|
-
since: number().nullable(),
|
|
64672
|
+
since: number().nullable().meta(readingMeta("none")),
|
|
64273
64673
|
source: RunningStateSourceSchema.meta({ label: "Source" }),
|
|
64274
64674
|
phase: string().nullable(),
|
|
64275
64675
|
/** null until a reading has been published (D393). */
|
|
@@ -64284,7 +64684,6 @@ var RUNNING_DEVICE_TYPES = Object.values(DeviceType);
|
|
|
64284
64684
|
/** Generic Customize target for the running boolean (D936). */
|
|
64285
64685
|
var runningCustomize = {
|
|
64286
64686
|
version: 1,
|
|
64287
|
-
advanced: "derive",
|
|
64288
64687
|
targets: [{
|
|
64289
64688
|
id: "running",
|
|
64290
64689
|
cardinality: "scalar",
|
|
@@ -64304,7 +64703,7 @@ var runningCustomize = {
|
|
|
64304
64703
|
DeviceType.Thermostat,
|
|
64305
64704
|
DeviceType.PetFeeder
|
|
64306
64705
|
],
|
|
64307
|
-
apply: "add
|
|
64706
|
+
apply: "add",
|
|
64308
64707
|
path: "running",
|
|
64309
64708
|
sources: [
|
|
64310
64709
|
{
|
|
@@ -65568,9 +65967,9 @@ var RecordTriggerSchema = _enum([
|
|
|
65568
65967
|
*/
|
|
65569
65968
|
var RecordWindowSchema = object({
|
|
65570
65969
|
trigger: RecordTriggerSchema,
|
|
65571
|
-
day: number().int().min(0).max(6),
|
|
65572
|
-
startMinute: number().int().min(0).max(1439),
|
|
65573
|
-
endMinute: number().int().min(1).max(1440)
|
|
65970
|
+
day: number().int().min(0).max(6).meta(readingMeta("none")),
|
|
65971
|
+
startMinute: number().int().min(0).max(1439).meta(readingMeta("none")),
|
|
65972
|
+
endMinute: number().int().min(1).max(1440).meta(readingMeta("none"))
|
|
65574
65973
|
});
|
|
65575
65974
|
/** Status of one physical volume, as the camera itself describes it. */
|
|
65576
65975
|
var OnboardStorageVolumeSchema = object({
|
|
@@ -65646,10 +66045,10 @@ var RecordingOnboardStatusSchema = object({
|
|
|
65646
66045
|
/** Master "record to the card at all" switch. */
|
|
65647
66046
|
enabled: boolean().nullable(),
|
|
65648
66047
|
overwriteWhenFull: boolean().nullable(),
|
|
65649
|
-
preRecordSec: number().nullable(),
|
|
65650
|
-
postRecordSec: number().nullable(),
|
|
66048
|
+
preRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
66049
|
+
postRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
65651
66050
|
/** Length of one recorded file, in minutes. */
|
|
65652
|
-
segmentMinutes: number().nullable(),
|
|
66051
|
+
segmentMinutes: number().nullable().meta(readingMeta("none")),
|
|
65653
66052
|
/** The primary track's weekly windows, flattened. */
|
|
65654
66053
|
windows: array(RecordWindowSchema),
|
|
65655
66054
|
/**
|
|
@@ -65665,7 +66064,7 @@ var RecordingOnboardStatusSchema = object({
|
|
|
65665
66064
|
* provider reporting a non-zero count also reports the schedule as not
|
|
65666
66065
|
* writable.
|
|
65667
66066
|
*/
|
|
65668
|
-
unreadableWindows: number(),
|
|
66067
|
+
unreadableWindows: number().meta(readingMeta("count")),
|
|
65669
66068
|
/**
|
|
65670
66069
|
* The camera is scheduled to record and has NO usable storage.
|
|
65671
66070
|
*
|
|
@@ -66510,7 +66909,7 @@ var CamStreamDescriptorSchema = object({
|
|
|
66510
66909
|
url: string().optional(),
|
|
66511
66910
|
codec: string().optional(),
|
|
66512
66911
|
resolution: CamStreamResolutionSchema.optional(),
|
|
66513
|
-
fps: number().positive().optional(),
|
|
66912
|
+
fps: number().positive().optional().meta(readingMeta("rate")),
|
|
66514
66913
|
label: string().optional(),
|
|
66515
66914
|
/** Device-level features (e.g. `battery-operated`) — drives broker policy. */
|
|
66516
66915
|
deviceFeatures: array(string()).optional(),
|
|
@@ -66597,18 +66996,18 @@ var StreamProfileSchema = _enum([
|
|
|
66597
66996
|
]);
|
|
66598
66997
|
/** The current encoding config of one stream profile. */
|
|
66599
66998
|
var StreamProfileConfigSchema = object({
|
|
66600
|
-
width: number(),
|
|
66601
|
-
height: number(),
|
|
66999
|
+
width: number().meta(readingMeta("none")),
|
|
67000
|
+
height: number().meta(readingMeta("none")),
|
|
66602
67001
|
codec: _enum(["h264", "h265"]),
|
|
66603
|
-
framerate: number(),
|
|
66604
|
-
bitrate: number(),
|
|
67002
|
+
framerate: number().meta(readingMeta("rate")),
|
|
67003
|
+
bitrate: number().meta(readingMeta("bitrate")),
|
|
66605
67004
|
bitrateMode: _enum(["vbr", "cbr"]).optional(),
|
|
66606
67005
|
encoderProfile: _enum([
|
|
66607
67006
|
"high",
|
|
66608
67007
|
"main",
|
|
66609
67008
|
"baseline"
|
|
66610
67009
|
]).optional(),
|
|
66611
|
-
gop: number().optional(),
|
|
67010
|
+
gop: number().optional().meta(readingMeta("none")),
|
|
66612
67011
|
/**
|
|
66613
67012
|
* Whether THIS profile currently carries an audio track. READ-ONLY here.
|
|
66614
67013
|
*
|
|
@@ -66829,12 +67228,7 @@ var switchCapability = {
|
|
|
66829
67228
|
label: "On",
|
|
66830
67229
|
kind: "boolean"
|
|
66831
67230
|
}
|
|
66832
|
-
}] }
|
|
66833
|
-
customize: {
|
|
66834
|
-
version: 1,
|
|
66835
|
-
advanced: "derive",
|
|
66836
|
-
targets: []
|
|
66837
|
-
}
|
|
67231
|
+
}] }
|
|
66838
67232
|
};
|
|
66839
67233
|
/** C0 controls, DEL and the C1 range: none of them belongs in a name. */
|
|
66840
67234
|
function hasControlCharacter(value) {
|
|
@@ -67417,35 +67811,21 @@ var tamperCapability = {
|
|
|
67417
67811
|
* entries with `device_class: temperature` and any future native
|
|
67418
67812
|
* thermometer.
|
|
67419
67813
|
*
|
|
67420
|
-
*
|
|
67421
|
-
*
|
|
67422
|
-
* (climate-control's `currentTemp`, energy analytics) can compose
|
|
67423
|
-
* without per-source unit fixups. The canonical display unit (`°C`) is
|
|
67424
|
-
* a descriptor constant in the UI (ROLE_DESCRIPTOR), not stored in
|
|
67425
|
-
* `sourceInfo`.
|
|
67814
|
+
* The number is Celsius (D944). Providers convert on ingest. A failed
|
|
67815
|
+
* conversion is `null`, never a guess. Display unit is a read-time preference.
|
|
67426
67816
|
*
|
|
67427
67817
|
* Status `lastFetchedAt` lets staleness-aware consumers detect a
|
|
67428
67818
|
* frozen feed (provider hung) distinct from a "temperature hasn't
|
|
67429
67819
|
* changed" steady state.
|
|
67430
67820
|
*/
|
|
67431
67821
|
var TemperatureSensorStatusSchema = object({
|
|
67432
|
-
/** Current temperature in Celsius. */
|
|
67433
|
-
celsius: number().meta({
|
|
67434
|
-
|
|
67822
|
+
/** Current temperature in Celsius. `null` when the sample was refused (D393). */
|
|
67823
|
+
celsius: number().nullable().meta(readingMeta("temperature", {
|
|
67824
|
+
precision: 1,
|
|
67435
67825
|
label: "Temperature"
|
|
67436
|
-
}),
|
|
67826
|
+
})),
|
|
67437
67827
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
67438
|
-
lastFetchedAt: number()
|
|
67439
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
67440
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
67441
|
-
* role's canonical unit, so a Fahrenheit feed renders '°F' not '°C'.
|
|
67442
|
-
* Absent → the UI falls back to the role's canonical unit. */
|
|
67443
|
-
unit: string().optional(),
|
|
67444
|
-
/** Suggested decimal places for numeric display.
|
|
67445
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
67446
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
67447
|
-
* auto-formatting when absent. */
|
|
67448
|
-
precision: number().int().min(0).max(10).optional()
|
|
67828
|
+
lastFetchedAt: number()
|
|
67449
67829
|
});
|
|
67450
67830
|
var temperatureSensorCapability = {
|
|
67451
67831
|
name: "temperature-sensor",
|
|
@@ -67476,12 +67856,7 @@ var temperatureSensorCapability = {
|
|
|
67476
67856
|
} } },
|
|
67477
67857
|
/** Clock fields: written, but excluded from the compare that decides
|
|
67478
67858
|
* whether persisting is worth a SQLite commit. */
|
|
67479
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
67480
|
-
customize: {
|
|
67481
|
-
version: 1,
|
|
67482
|
-
advanced: "derive",
|
|
67483
|
-
targets: []
|
|
67484
|
-
}
|
|
67859
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
67485
67860
|
};
|
|
67486
67861
|
/**
|
|
67487
67862
|
* toast — system-scoped singleton capability that streams toast
|
|
@@ -67764,16 +68139,16 @@ var VacuumControlStatusSchema = object({
|
|
|
67764
68139
|
]),
|
|
67765
68140
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
67766
68141
|
* reading. */
|
|
67767
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
68142
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
67768
68143
|
/** Current fan-speed token (provider-verbatim). Null when unknown or
|
|
67769
68144
|
* the vacuum has no speed control. */
|
|
67770
68145
|
fanSpeed: string().nullable(),
|
|
67771
68146
|
/** Speed tokens the hardware accepts — drives the UI selector. */
|
|
67772
68147
|
availableFanSpeeds: array(string()),
|
|
67773
68148
|
/** 0..100 cleaning-completion percentage of the current task, or null. */
|
|
67774
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
68149
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
67775
68150
|
/** Current error code (0 / null = no error). */
|
|
67776
|
-
errorCode: number().nullable(),
|
|
68151
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
67777
68152
|
/** Human label for {@link errorCode}, or null when none / undecodable. */
|
|
67778
68153
|
errorLabel: string().nullable(),
|
|
67779
68154
|
/** Ms epoch when the slice was last updated. */
|
|
@@ -67851,7 +68226,7 @@ var ValveStatusSchema = object({
|
|
|
67851
68226
|
]),
|
|
67852
68227
|
/** 0 = fully closed, 100 = fully open. Null when the device has no
|
|
67853
68228
|
* intermediate position surface. */
|
|
67854
|
-
position: number().min(0).max(100).nullable(),
|
|
68229
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
67855
68230
|
/** Ms epoch when the slice was last updated. */
|
|
67856
68231
|
lastChangedAt: number()
|
|
67857
68232
|
});
|
|
@@ -67959,9 +68334,9 @@ var vibrationCapability = {
|
|
|
67959
68334
|
*/
|
|
67960
68335
|
var WaterHeaterStatusSchema = object({
|
|
67961
68336
|
/** Current measured temperature. Null when not reported. */
|
|
67962
|
-
currentTemp: number().nullable(),
|
|
68337
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
67963
68338
|
/** Target temperature setpoint. Null when no setpoint surface. */
|
|
67964
|
-
targetTemp: number().nullable(),
|
|
68339
|
+
targetTemp: number().nullable().meta(readingMeta("temperature")),
|
|
67965
68340
|
/** Active operation mode = HA `state` (`eco` / `electric` / `gas` /
|
|
67966
68341
|
* `heat_pump` / `high_demand` / `performance` / `off`). Null when the
|
|
67967
68342
|
* device reports an unknown state. */
|
|
@@ -67972,9 +68347,9 @@ var WaterHeaterStatusSchema = object({
|
|
|
67972
68347
|
* has no away surface. */
|
|
67973
68348
|
away: boolean().nullable(),
|
|
67974
68349
|
/** HA `min_temp` attribute. Null when not reported. */
|
|
67975
|
-
minTemp: number().nullable(),
|
|
68350
|
+
minTemp: number().nullable().meta(readingMeta("temperature")),
|
|
67976
68351
|
/** HA `max_temp` attribute. Null when not reported. */
|
|
67977
|
-
maxTemp: number().nullable(),
|
|
68352
|
+
maxTemp: number().nullable().meta(readingMeta("temperature")),
|
|
67978
68353
|
/** Ms epoch when the slice was last updated. */
|
|
67979
68354
|
lastChangedAt: number()
|
|
67980
68355
|
});
|
|
@@ -68059,25 +68434,18 @@ var waterHeaterCapability = {
|
|
|
68059
68434
|
* Forecast deferred — current conditions only for v1.
|
|
68060
68435
|
*/
|
|
68061
68436
|
var WeatherStatusSchema = object({
|
|
68062
|
-
/** Verbatim
|
|
68063
|
-
* when no condition has been reported yet. */
|
|
68437
|
+
/** Verbatim condition state (`sunny`, `cloudy`, `rainy`, …). Null when none yet. */
|
|
68064
68438
|
condition: string().nullable(),
|
|
68065
|
-
/** Current temperature in
|
|
68066
|
-
temperature: number().nullable(),
|
|
68067
|
-
/** Temperature unit string (e.g. `°C` / `°F`). Null when not provided. */
|
|
68068
|
-
temperatureUnit: string().nullable(),
|
|
68439
|
+
/** Current temperature in Celsius. Null when not provided or refused. */
|
|
68440
|
+
temperature: number().nullable().meta(readingMeta("temperature", { precision: 1 })),
|
|
68069
68441
|
/** Relative humidity (0..100). Null when not provided. */
|
|
68070
|
-
humidity: number().min(0).max(100).nullable(),
|
|
68071
|
-
/** Barometric pressure in
|
|
68072
|
-
pressure: number().nullable(),
|
|
68073
|
-
/**
|
|
68074
|
-
|
|
68075
|
-
/** Wind speed in the reported unit. Null when not provided. */
|
|
68076
|
-
windSpeed: number().nullable(),
|
|
68077
|
-
/** Wind-speed unit string (e.g. `km/h` / `mph`). Null when not provided. */
|
|
68078
|
-
windSpeedUnit: string().nullable(),
|
|
68442
|
+
humidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
68443
|
+
/** Barometric pressure in hPa. Null when not provided or refused. */
|
|
68444
|
+
pressure: number().nullable().meta(readingMeta("pressure")),
|
|
68445
|
+
/** Wind speed in metres per second. Null when not provided or refused. */
|
|
68446
|
+
windSpeed: number().nullable().meta(readingMeta("speed")),
|
|
68079
68447
|
/** Wind bearing in degrees (0..360, meteorological). Null when not provided. */
|
|
68080
|
-
windBearing: number().nullable(),
|
|
68448
|
+
windBearing: number().nullable().meta(readingMeta("angle")),
|
|
68081
68449
|
/** Ms epoch when the slice was last updated. */
|
|
68082
68450
|
lastFetchedAt: number()
|
|
68083
68451
|
});
|
|
@@ -68105,12 +68473,12 @@ var weatherCapability = {
|
|
|
68105
68473
|
*/
|
|
68106
68474
|
durability: "session",
|
|
68107
68475
|
/**
|
|
68108
|
-
* History (D850): recorded series.
|
|
68476
|
+
* History (D850): recorded series. Numbers are the quantity base (D944).
|
|
68109
68477
|
*/
|
|
68110
68478
|
history: { fields: {
|
|
68111
68479
|
temperature: {
|
|
68112
68480
|
kind: "gauge",
|
|
68113
|
-
|
|
68481
|
+
unit: "°C",
|
|
68114
68482
|
deadband: .2
|
|
68115
68483
|
},
|
|
68116
68484
|
humidity: {
|
|
@@ -68120,12 +68488,12 @@ var weatherCapability = {
|
|
|
68120
68488
|
},
|
|
68121
68489
|
pressure: {
|
|
68122
68490
|
kind: "gauge",
|
|
68123
|
-
|
|
68491
|
+
unit: "hPa",
|
|
68124
68492
|
deadband: .5
|
|
68125
68493
|
},
|
|
68126
68494
|
windSpeed: {
|
|
68127
68495
|
kind: "gauge",
|
|
68128
|
-
|
|
68496
|
+
unit: "m/s",
|
|
68129
68497
|
deadband: .5
|
|
68130
68498
|
}
|
|
68131
68499
|
} }
|
|
@@ -69356,6 +69724,8 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
69356
69724
|
featureProbe: featureProbeCapability,
|
|
69357
69725
|
flood: floodCapability,
|
|
69358
69726
|
gas: gasCapability,
|
|
69727
|
+
groupCommands: groupCommandsCapability,
|
|
69728
|
+
groupStatus: groupStatusCapability,
|
|
69359
69729
|
heatingValve: heatingValveCapability,
|
|
69360
69730
|
humidifier: humidifierCapability,
|
|
69361
69731
|
humiditySensor: humiditySensorCapability,
|
|
@@ -70732,6 +71102,13 @@ Object.freeze({
|
|
|
70732
71102
|
access: "view",
|
|
70733
71103
|
role: "admin"
|
|
70734
71104
|
},
|
|
71105
|
+
"addons.getPackageDocs": {
|
|
71106
|
+
capName: "addons",
|
|
71107
|
+
capScope: "system",
|
|
71108
|
+
addonId: null,
|
|
71109
|
+
access: "view",
|
|
71110
|
+
role: "admin"
|
|
71111
|
+
},
|
|
70735
71112
|
"addons.getVersions": {
|
|
70736
71113
|
capName: "addons",
|
|
70737
71114
|
capScope: "system",
|
|
@@ -73840,6 +74217,20 @@ Object.freeze({
|
|
|
73840
74217
|
access: "view",
|
|
73841
74218
|
role: "viewer"
|
|
73842
74219
|
},
|
|
74220
|
+
"groupCommands.getStatus": {
|
|
74221
|
+
capName: "group-commands",
|
|
74222
|
+
capScope: "device",
|
|
74223
|
+
addonId: null,
|
|
74224
|
+
access: "view",
|
|
74225
|
+
role: "viewer"
|
|
74226
|
+
},
|
|
74227
|
+
"groupStatus.getStatus": {
|
|
74228
|
+
capName: "group-status",
|
|
74229
|
+
capScope: "device",
|
|
74230
|
+
addonId: null,
|
|
74231
|
+
access: "view",
|
|
74232
|
+
role: "viewer"
|
|
74233
|
+
},
|
|
73843
74234
|
"heatingValve.getStatus": {
|
|
73844
74235
|
capName: "heating-valve",
|
|
73845
74236
|
capScope: "device",
|
|
@@ -83662,6 +84053,37 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83662
84053
|
icon: "flame"
|
|
83663
84054
|
}]
|
|
83664
84055
|
},
|
|
84056
|
+
"group-commands": {
|
|
84057
|
+
scope: "device",
|
|
84058
|
+
noun: t("Group command", "Comando di gruppo")
|
|
84059
|
+
},
|
|
84060
|
+
"group-status": {
|
|
84061
|
+
scope: "device",
|
|
84062
|
+
noun: t("Group", "Gruppo"),
|
|
84063
|
+
state: [
|
|
84064
|
+
{
|
|
84065
|
+
kind: "numeric",
|
|
84066
|
+
field: "included",
|
|
84067
|
+
quantity: t("the members reporting", "i membri che rispondono"),
|
|
84068
|
+
label: t("Reporting", "Rispondono"),
|
|
84069
|
+
icon: "users"
|
|
84070
|
+
},
|
|
84071
|
+
{
|
|
84072
|
+
kind: "numeric",
|
|
84073
|
+
field: "excluded",
|
|
84074
|
+
quantity: t("the members left out", "i membri esclusi"),
|
|
84075
|
+
label: t("Excluded", "Esclusi"),
|
|
84076
|
+
icon: "users"
|
|
84077
|
+
},
|
|
84078
|
+
{
|
|
84079
|
+
kind: "numeric",
|
|
84080
|
+
field: "total",
|
|
84081
|
+
quantity: t("the member count", "il numero di membri"),
|
|
84082
|
+
label: t("Members", "Membri"),
|
|
84083
|
+
icon: "sigma"
|
|
84084
|
+
}
|
|
84085
|
+
]
|
|
84086
|
+
},
|
|
83665
84087
|
"humidity-sensor": {
|
|
83666
84088
|
scope: "device",
|
|
83667
84089
|
noun: t("Humidity", "Umidità"),
|
|
@@ -83695,7 +84117,6 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83695
84117
|
field: "value",
|
|
83696
84118
|
quantity: t("the reading", "il valore"),
|
|
83697
84119
|
label: t("Reading", "Valore"),
|
|
83698
|
-
unitField: "unit",
|
|
83699
84120
|
icon: "gauge"
|
|
83700
84121
|
}]
|
|
83701
84122
|
},
|
|
@@ -83831,7 +84252,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83831
84252
|
field: "temperature",
|
|
83832
84253
|
quantity: t("the outdoor temperature", "la temperatura esterna"),
|
|
83833
84254
|
label: t("Temperature", "Temperatura"),
|
|
83834
|
-
|
|
84255
|
+
unit: "°C",
|
|
83835
84256
|
icon: "thermometer"
|
|
83836
84257
|
},
|
|
83837
84258
|
{
|
|
@@ -83847,7 +84268,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83847
84268
|
field: "windSpeed",
|
|
83848
84269
|
quantity: t("the wind speed", "la velocità del vento"),
|
|
83849
84270
|
label: t("Wind", "Vento"),
|
|
83850
|
-
|
|
84271
|
+
unit: "m/s",
|
|
83851
84272
|
icon: "wind"
|
|
83852
84273
|
},
|
|
83853
84274
|
{
|
|
@@ -83855,7 +84276,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83855
84276
|
field: "pressure",
|
|
83856
84277
|
quantity: t("the air pressure", "la pressione atmosferica"),
|
|
83857
84278
|
label: t("Pressure", "Pressione"),
|
|
83858
|
-
|
|
84279
|
+
unit: "hPa",
|
|
83859
84280
|
icon: "gauge"
|
|
83860
84281
|
}
|
|
83861
84282
|
]
|
|
@@ -85128,6 +85549,16 @@ Object.freeze({
|
|
|
85128
85549
|
form: "single",
|
|
85129
85550
|
optional: false
|
|
85130
85551
|
}],
|
|
85552
|
+
"groupCommands.getStatus": [{
|
|
85553
|
+
name: "deviceId",
|
|
85554
|
+
form: "single",
|
|
85555
|
+
optional: false
|
|
85556
|
+
}],
|
|
85557
|
+
"groupStatus.getStatus": [{
|
|
85558
|
+
name: "deviceId",
|
|
85559
|
+
form: "single",
|
|
85560
|
+
optional: false
|
|
85561
|
+
}],
|
|
85131
85562
|
"heatingValve.getStatus": [{
|
|
85132
85563
|
name: "deviceId",
|
|
85133
85564
|
form: "single",
|
|
@@ -87112,6 +87543,8 @@ new Map(Object.entries({
|
|
|
87112
87543
|
"detection-blind": "device-events",
|
|
87113
87544
|
"motion-noisy": "device-events",
|
|
87114
87545
|
"motion-calm": "device-events",
|
|
87546
|
+
"package-llm-silent": "device-events",
|
|
87547
|
+
"package-llm-answered": "device-events",
|
|
87115
87548
|
"recording-stalled": "device-events",
|
|
87116
87549
|
"recording-healthy": "device-events",
|
|
87117
87550
|
"recording-degraded": "device-events",
|
|
@@ -87195,6 +87628,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
|
|
|
87195
87628
|
label: "Motion without a subject",
|
|
87196
87629
|
kinds: ["motion-noisy", "motion-calm"]
|
|
87197
87630
|
},
|
|
87631
|
+
{
|
|
87632
|
+
id: "package-llm",
|
|
87633
|
+
family: "device-events",
|
|
87634
|
+
label: "Package confirm",
|
|
87635
|
+
kinds: ["package-llm-silent", "package-llm-answered"]
|
|
87636
|
+
},
|
|
87198
87637
|
{
|
|
87199
87638
|
id: "recording",
|
|
87200
87639
|
family: "device-events",
|
|
@@ -87376,6 +87815,8 @@ var DEVICE_EVENTS = [
|
|
|
87376
87815
|
"detection-blind",
|
|
87377
87816
|
"motion-noisy",
|
|
87378
87817
|
"motion-calm",
|
|
87818
|
+
"package-llm-silent",
|
|
87819
|
+
"package-llm-answered",
|
|
87379
87820
|
"recording-stalled",
|
|
87380
87821
|
"recording-healthy",
|
|
87381
87822
|
"recording-degraded",
|
|
@@ -87644,6 +88085,15 @@ new Map([
|
|
|
87644
88085
|
snapshotLabel: "Cameras with constant motion now",
|
|
87645
88086
|
snapshotSection: null
|
|
87646
88087
|
},
|
|
88088
|
+
{
|
|
88089
|
+
id: "package-llm-confirm",
|
|
88090
|
+
family: "device-events",
|
|
88091
|
+
label: "Package confirm (not answering / answering again)",
|
|
88092
|
+
bad: ["package-llm-silent"],
|
|
88093
|
+
recovery: ["package-llm-answered"],
|
|
88094
|
+
snapshotLabel: "Cameras whose package confirm is not answering",
|
|
88095
|
+
snapshotSection: null
|
|
88096
|
+
},
|
|
87647
88097
|
{
|
|
87648
88098
|
id: "recording-health",
|
|
87649
88099
|
family: "device-events",
|