@camstack/addon-agent-ui 1.2.269 → 1.2.271
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/addon.js +718 -431
- package/dist/assets/{MotionZonesSettings-BK04Lz4x.js → MotionZonesSettings-Bhrt_-ur.js} +1 -1
- package/dist/assets/{PrivacyMaskSettings-DZzCwCEZ.js → PrivacyMaskSettings-DhvPNx5s.js} +1 -1
- package/dist/assets/{SceneMonitorEditor-ClGgtsRS.js → SceneMonitorEditor-BIFghxXM.js} +1 -1
- package/dist/assets/index-C61nCzh8.js +112 -0
- package/dist/index.html +1 -1
- package/package.json +1 -1
- package/dist/assets/index-C5nL5eUA.js +0 -112
package/dist/addon.js
CHANGED
|
@@ -5435,7 +5435,7 @@ var ZodIssueCode = {
|
|
|
5435
5435
|
var ZodFirstPartyTypeKind;
|
|
5436
5436
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5437
5437
|
//#endregion
|
|
5438
|
-
//#region ../types/dist/sleep-
|
|
5438
|
+
//#region ../types/dist/sleep-B81gwQuR.mjs
|
|
5439
5439
|
/**
|
|
5440
5440
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5441
5441
|
* window to float samples (D455).
|
|
@@ -7922,6 +7922,99 @@ var RecordKindDeclarationSchema = object({
|
|
|
7922
7922
|
}).strict();
|
|
7923
7923
|
/** The kind names: lower-case, dash separated, short enough for an index name. */
|
|
7924
7924
|
var RecordKindNameSchema = string().regex(/^[a-z][a-z0-9-]{0,47}$/);
|
|
7925
|
+
var READING_QUANTITIES = [
|
|
7926
|
+
"temperature",
|
|
7927
|
+
"pressure",
|
|
7928
|
+
"speed",
|
|
7929
|
+
"precipitation",
|
|
7930
|
+
"precipitation-rate",
|
|
7931
|
+
"length",
|
|
7932
|
+
"area",
|
|
7933
|
+
"illuminance",
|
|
7934
|
+
"irradiance",
|
|
7935
|
+
"power",
|
|
7936
|
+
"energy",
|
|
7937
|
+
"voltage",
|
|
7938
|
+
"current",
|
|
7939
|
+
"apparent-power",
|
|
7940
|
+
"humidity",
|
|
7941
|
+
"percentage",
|
|
7942
|
+
"concentration-volume",
|
|
7943
|
+
"concentration-mass",
|
|
7944
|
+
"concentration-ppb",
|
|
7945
|
+
"volume",
|
|
7946
|
+
"duration",
|
|
7947
|
+
"duration-ms",
|
|
7948
|
+
"information",
|
|
7949
|
+
"sound-level",
|
|
7950
|
+
"signal-level",
|
|
7951
|
+
"colour-temperature",
|
|
7952
|
+
"angle",
|
|
7953
|
+
"bitrate",
|
|
7954
|
+
"rate",
|
|
7955
|
+
"mass",
|
|
7956
|
+
"index",
|
|
7957
|
+
"ratio",
|
|
7958
|
+
"count",
|
|
7959
|
+
"none",
|
|
7960
|
+
"device"
|
|
7961
|
+
];
|
|
7962
|
+
var ReadingQuantitySchema = _enum(READING_QUANTITIES);
|
|
7963
|
+
new Set(READING_QUANTITIES);
|
|
7964
|
+
/**
|
|
7965
|
+
* Stored unit symbol for a quantity. `none` means the number is dimensionless
|
|
7966
|
+
* (or an index / ratio / count). `device` means the cap has no single unit.
|
|
7967
|
+
*/
|
|
7968
|
+
var QUANTITY_BASE = {
|
|
7969
|
+
temperature: "°C",
|
|
7970
|
+
pressure: "hPa",
|
|
7971
|
+
speed: "m/s",
|
|
7972
|
+
precipitation: "mm",
|
|
7973
|
+
"precipitation-rate": "mm/h",
|
|
7974
|
+
length: "m",
|
|
7975
|
+
area: "m²",
|
|
7976
|
+
illuminance: "lx",
|
|
7977
|
+
irradiance: "W/m²",
|
|
7978
|
+
power: "W",
|
|
7979
|
+
energy: "kWh",
|
|
7980
|
+
voltage: "V",
|
|
7981
|
+
current: "A",
|
|
7982
|
+
"apparent-power": "VA",
|
|
7983
|
+
humidity: "%",
|
|
7984
|
+
percentage: "%",
|
|
7985
|
+
"concentration-volume": "ppm",
|
|
7986
|
+
"concentration-mass": "µg/m³",
|
|
7987
|
+
"concentration-ppb": "ppb",
|
|
7988
|
+
volume: "L",
|
|
7989
|
+
duration: "s",
|
|
7990
|
+
"duration-ms": "ms",
|
|
7991
|
+
information: "B",
|
|
7992
|
+
"sound-level": "dBFS",
|
|
7993
|
+
"signal-level": "dBm",
|
|
7994
|
+
"colour-temperature": "mired",
|
|
7995
|
+
angle: "°",
|
|
7996
|
+
bitrate: "kbps",
|
|
7997
|
+
rate: "fps",
|
|
7998
|
+
mass: "kg",
|
|
7999
|
+
index: "none",
|
|
8000
|
+
ratio: "none",
|
|
8001
|
+
count: "none",
|
|
8002
|
+
none: "none",
|
|
8003
|
+
device: "device"
|
|
8004
|
+
};
|
|
8005
|
+
/** The stored unit, or `undefined` when the quantity has no unit symbol. */
|
|
8006
|
+
function baseUnitOf(quantity) {
|
|
8007
|
+
const symbol = QUANTITY_BASE[quantity];
|
|
8008
|
+
if (symbol === "none" || symbol === "device") return void 0;
|
|
8009
|
+
return symbol;
|
|
8010
|
+
}
|
|
8011
|
+
function readingMeta(quantity, extras) {
|
|
8012
|
+
return {
|
|
8013
|
+
quantity,
|
|
8014
|
+
...extras?.precision !== void 0 ? { precision: extras.precision } : {},
|
|
8015
|
+
...extras?.label !== void 0 ? { label: extras.label } : {}
|
|
8016
|
+
};
|
|
8017
|
+
}
|
|
7925
8018
|
/** Shared Zod schemas used across streaming capabilities. */
|
|
7926
8019
|
var CamProfileSchema = _enum([
|
|
7927
8020
|
"high",
|
|
@@ -7949,8 +8042,8 @@ var CamStreamKindSchema = _enum([
|
|
|
7949
8042
|
"derived"
|
|
7950
8043
|
]);
|
|
7951
8044
|
var CamStreamResolutionSchema = object({
|
|
7952
|
-
width: number().int().positive(),
|
|
7953
|
-
height: number().int().positive()
|
|
8045
|
+
width: number().int().positive().meta(readingMeta("none")),
|
|
8046
|
+
height: number().int().positive().meta(readingMeta("none"))
|
|
7954
8047
|
});
|
|
7955
8048
|
var CameraStreamSchema = object({
|
|
7956
8049
|
/** Stable, provider-assigned id unique within the (deviceId) scope. */
|
|
@@ -8482,6 +8575,7 @@ var CAP_NAMES = Object.freeze([
|
|
|
8482
8575
|
"filesystem-browse",
|
|
8483
8576
|
"flood",
|
|
8484
8577
|
"gas",
|
|
8578
|
+
"group-status",
|
|
8485
8579
|
"heating-valve",
|
|
8486
8580
|
"humidifier",
|
|
8487
8581
|
"humidity-sensor",
|
|
@@ -8611,14 +8705,6 @@ Object.freeze({
|
|
|
8611
8705
|
{
|
|
8612
8706
|
"path": "aqi",
|
|
8613
8707
|
"valueType": "number"
|
|
8614
|
-
},
|
|
8615
|
-
{
|
|
8616
|
-
"path": "unit",
|
|
8617
|
-
"valueType": "string"
|
|
8618
|
-
},
|
|
8619
|
-
{
|
|
8620
|
-
"path": "precision",
|
|
8621
|
-
"valueType": "number"
|
|
8622
8708
|
}
|
|
8623
8709
|
],
|
|
8624
8710
|
"alarm-panel": [
|
|
@@ -8654,20 +8740,10 @@ Object.freeze({
|
|
|
8654
8740
|
"valueType": "boolean"
|
|
8655
8741
|
}
|
|
8656
8742
|
],
|
|
8657
|
-
"ambient-light-sensor": [
|
|
8658
|
-
|
|
8659
|
-
|
|
8660
|
-
|
|
8661
|
-
},
|
|
8662
|
-
{
|
|
8663
|
-
"path": "unit",
|
|
8664
|
-
"valueType": "string"
|
|
8665
|
-
},
|
|
8666
|
-
{
|
|
8667
|
-
"path": "precision",
|
|
8668
|
-
"valueType": "number"
|
|
8669
|
-
}
|
|
8670
|
-
],
|
|
8743
|
+
"ambient-light-sensor": [{
|
|
8744
|
+
"path": "lux",
|
|
8745
|
+
"valueType": "number"
|
|
8746
|
+
}],
|
|
8671
8747
|
"audio-metrics": [
|
|
8672
8748
|
{
|
|
8673
8749
|
"path": "ts",
|
|
@@ -8747,6 +8823,10 @@ Object.freeze({
|
|
|
8747
8823
|
"path": "lastUpdated",
|
|
8748
8824
|
"valueType": "number"
|
|
8749
8825
|
},
|
|
8826
|
+
{
|
|
8827
|
+
"path": "volts",
|
|
8828
|
+
"valueType": "number"
|
|
8829
|
+
},
|
|
8750
8830
|
{
|
|
8751
8831
|
"path": "lastContactAt",
|
|
8752
8832
|
"valueType": "number"
|
|
@@ -8989,10 +9069,6 @@ Object.freeze({
|
|
|
8989
9069
|
"datetime"
|
|
8990
9070
|
]
|
|
8991
9071
|
},
|
|
8992
|
-
{
|
|
8993
|
-
"path": "unit",
|
|
8994
|
-
"valueType": "string"
|
|
8995
|
-
},
|
|
8996
9072
|
{
|
|
8997
9073
|
"path": "min",
|
|
8998
9074
|
"valueType": "number"
|
|
@@ -9004,19 +9080,6 @@ Object.freeze({
|
|
|
9004
9080
|
{
|
|
9005
9081
|
"path": "step",
|
|
9006
9082
|
"valueType": "number"
|
|
9007
|
-
},
|
|
9008
|
-
{
|
|
9009
|
-
"path": "precision",
|
|
9010
|
-
"valueType": "number"
|
|
9011
|
-
},
|
|
9012
|
-
{
|
|
9013
|
-
"path": "format",
|
|
9014
|
-
"valueType": "enum",
|
|
9015
|
-
"enumValues": [
|
|
9016
|
-
"date",
|
|
9017
|
-
"time",
|
|
9018
|
-
"datetime"
|
|
9019
|
-
]
|
|
9020
9083
|
}
|
|
9021
9084
|
],
|
|
9022
9085
|
"cover": [
|
|
@@ -9257,13 +9320,8 @@ Object.freeze({
|
|
|
9257
9320
|
"path": "value",
|
|
9258
9321
|
"valueType": "string"
|
|
9259
9322
|
}, {
|
|
9260
|
-
"path": "
|
|
9261
|
-
"valueType": "
|
|
9262
|
-
"enumValues": [
|
|
9263
|
-
"date",
|
|
9264
|
-
"time",
|
|
9265
|
-
"datetime"
|
|
9266
|
-
]
|
|
9323
|
+
"path": "timestamp",
|
|
9324
|
+
"valueType": "boolean"
|
|
9267
9325
|
}],
|
|
9268
9326
|
"event-emitter": [
|
|
9269
9327
|
{
|
|
@@ -9336,6 +9394,20 @@ Object.freeze({
|
|
|
9336
9394
|
"path": "detected",
|
|
9337
9395
|
"valueType": "boolean"
|
|
9338
9396
|
}],
|
|
9397
|
+
"group-status": [
|
|
9398
|
+
{
|
|
9399
|
+
"path": "included",
|
|
9400
|
+
"valueType": "number"
|
|
9401
|
+
},
|
|
9402
|
+
{
|
|
9403
|
+
"path": "excluded",
|
|
9404
|
+
"valueType": "number"
|
|
9405
|
+
},
|
|
9406
|
+
{
|
|
9407
|
+
"path": "total",
|
|
9408
|
+
"valueType": "number"
|
|
9409
|
+
}
|
|
9410
|
+
],
|
|
9339
9411
|
"heating-valve": [{
|
|
9340
9412
|
"path": "position",
|
|
9341
9413
|
"valueType": "number"
|
|
@@ -9370,20 +9442,10 @@ Object.freeze({
|
|
|
9370
9442
|
"valueType": "number"
|
|
9371
9443
|
}
|
|
9372
9444
|
],
|
|
9373
|
-
"humidity-sensor": [
|
|
9374
|
-
|
|
9375
|
-
|
|
9376
|
-
|
|
9377
|
-
},
|
|
9378
|
-
{
|
|
9379
|
-
"path": "unit",
|
|
9380
|
-
"valueType": "string"
|
|
9381
|
-
},
|
|
9382
|
-
{
|
|
9383
|
-
"path": "precision",
|
|
9384
|
-
"valueType": "number"
|
|
9385
|
-
}
|
|
9386
|
-
],
|
|
9445
|
+
"humidity-sensor": [{
|
|
9446
|
+
"path": "percent",
|
|
9447
|
+
"valueType": "number"
|
|
9448
|
+
}],
|
|
9387
9449
|
"image": [{
|
|
9388
9450
|
"path": "url",
|
|
9389
9451
|
"valueType": "string"
|
|
@@ -9722,20 +9784,10 @@ Object.freeze({
|
|
|
9722
9784
|
"valueType": "boolean"
|
|
9723
9785
|
}
|
|
9724
9786
|
],
|
|
9725
|
-
"numeric-sensor": [
|
|
9726
|
-
|
|
9727
|
-
|
|
9728
|
-
|
|
9729
|
-
},
|
|
9730
|
-
{
|
|
9731
|
-
"path": "unit",
|
|
9732
|
-
"valueType": "string"
|
|
9733
|
-
},
|
|
9734
|
-
{
|
|
9735
|
-
"path": "precision",
|
|
9736
|
-
"valueType": "number"
|
|
9737
|
-
}
|
|
9738
|
-
],
|
|
9787
|
+
"numeric-sensor": [{
|
|
9788
|
+
"path": "value",
|
|
9789
|
+
"valueType": "number"
|
|
9790
|
+
}],
|
|
9739
9791
|
"pet-feeder": [
|
|
9740
9792
|
{
|
|
9741
9793
|
"path": "foodLevel",
|
|
@@ -9827,14 +9879,6 @@ Object.freeze({
|
|
|
9827
9879
|
{
|
|
9828
9880
|
"path": "powerFactor",
|
|
9829
9881
|
"valueType": "number"
|
|
9830
|
-
},
|
|
9831
|
-
{
|
|
9832
|
-
"path": "unit",
|
|
9833
|
-
"valueType": "string"
|
|
9834
|
-
},
|
|
9835
|
-
{
|
|
9836
|
-
"path": "precision",
|
|
9837
|
-
"valueType": "number"
|
|
9838
9882
|
}
|
|
9839
9883
|
],
|
|
9840
9884
|
"presence": [
|
|
@@ -9863,20 +9907,10 @@ Object.freeze({
|
|
|
9863
9907
|
"valueType": "number"
|
|
9864
9908
|
}
|
|
9865
9909
|
],
|
|
9866
|
-
"pressure-sensor": [
|
|
9867
|
-
|
|
9868
|
-
|
|
9869
|
-
|
|
9870
|
-
},
|
|
9871
|
-
{
|
|
9872
|
-
"path": "unit",
|
|
9873
|
-
"valueType": "string"
|
|
9874
|
-
},
|
|
9875
|
-
{
|
|
9876
|
-
"path": "precision",
|
|
9877
|
-
"valueType": "number"
|
|
9878
|
-
}
|
|
9879
|
-
],
|
|
9910
|
+
"pressure-sensor": [{
|
|
9911
|
+
"path": "hpa",
|
|
9912
|
+
"valueType": "number"
|
|
9913
|
+
}],
|
|
9880
9914
|
"privacy-mask": [{
|
|
9881
9915
|
"path": "enabled",
|
|
9882
9916
|
"valueType": "boolean"
|
|
@@ -10187,20 +10221,10 @@ Object.freeze({
|
|
|
10187
10221
|
"path": "tampered",
|
|
10188
10222
|
"valueType": "boolean"
|
|
10189
10223
|
}],
|
|
10190
|
-
"temperature-sensor": [
|
|
10191
|
-
|
|
10192
|
-
|
|
10193
|
-
|
|
10194
|
-
},
|
|
10195
|
-
{
|
|
10196
|
-
"path": "unit",
|
|
10197
|
-
"valueType": "string"
|
|
10198
|
-
},
|
|
10199
|
-
{
|
|
10200
|
-
"path": "precision",
|
|
10201
|
-
"valueType": "number"
|
|
10202
|
-
}
|
|
10203
|
-
],
|
|
10224
|
+
"temperature-sensor": [{
|
|
10225
|
+
"path": "celsius",
|
|
10226
|
+
"valueType": "number"
|
|
10227
|
+
}],
|
|
10204
10228
|
"update": [
|
|
10205
10229
|
{
|
|
10206
10230
|
"path": "currentVersion",
|
|
@@ -10311,10 +10335,6 @@ Object.freeze({
|
|
|
10311
10335
|
"path": "temperature",
|
|
10312
10336
|
"valueType": "number"
|
|
10313
10337
|
},
|
|
10314
|
-
{
|
|
10315
|
-
"path": "temperatureUnit",
|
|
10316
|
-
"valueType": "string"
|
|
10317
|
-
},
|
|
10318
10338
|
{
|
|
10319
10339
|
"path": "humidity",
|
|
10320
10340
|
"valueType": "number"
|
|
@@ -10323,18 +10343,10 @@ Object.freeze({
|
|
|
10323
10343
|
"path": "pressure",
|
|
10324
10344
|
"valueType": "number"
|
|
10325
10345
|
},
|
|
10326
|
-
{
|
|
10327
|
-
"path": "pressureUnit",
|
|
10328
|
-
"valueType": "string"
|
|
10329
|
-
},
|
|
10330
10346
|
{
|
|
10331
10347
|
"path": "windSpeed",
|
|
10332
10348
|
"valueType": "number"
|
|
10333
10349
|
},
|
|
10334
|
-
{
|
|
10335
|
-
"path": "windSpeedUnit",
|
|
10336
|
-
"valueType": "string"
|
|
10337
|
-
},
|
|
10338
10350
|
{
|
|
10339
10351
|
"path": "windBearing",
|
|
10340
10352
|
"valueType": "number"
|
|
@@ -10727,7 +10739,7 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
|
|
|
10727
10739
|
return DeviceRole;
|
|
10728
10740
|
}({});
|
|
10729
10741
|
//#endregion
|
|
10730
|
-
//#region ../types/dist/composition-
|
|
10742
|
+
//#region ../types/dist/composition-B85l9j1M.mjs
|
|
10731
10743
|
/**
|
|
10732
10744
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
10733
10745
|
*
|
|
@@ -11482,15 +11494,67 @@ function validateExpressionSource(src) {
|
|
|
11482
11494
|
}
|
|
11483
11495
|
return null;
|
|
11484
11496
|
}
|
|
11485
|
-
/**
|
|
11486
|
-
|
|
11487
|
-
|
|
11488
|
-
|
|
11497
|
+
/**
|
|
11498
|
+
* A composition source identity: `(addonId, stableId)`, never a numeric device
|
|
11499
|
+
* id. Split out so helper schemas can name it without a cycle through
|
|
11500
|
+
* `composition.ts` (D659).
|
|
11501
|
+
*/
|
|
11489
11502
|
var CompositionSourceRefSchema = object({
|
|
11490
11503
|
/** The owning addon; `stableId` is unique only within it. */
|
|
11491
11504
|
addonId: string().min(1),
|
|
11492
11505
|
stableId: string().min(1)
|
|
11493
11506
|
});
|
|
11507
|
+
var GROUP_TEMPLATE_IDS = [
|
|
11508
|
+
"temperature",
|
|
11509
|
+
"humidity",
|
|
11510
|
+
"pressure",
|
|
11511
|
+
"illuminance",
|
|
11512
|
+
"power",
|
|
11513
|
+
"energy",
|
|
11514
|
+
"battery",
|
|
11515
|
+
"numeric",
|
|
11516
|
+
"motion",
|
|
11517
|
+
"contact",
|
|
11518
|
+
"leak",
|
|
11519
|
+
"smoke",
|
|
11520
|
+
"occupancy",
|
|
11521
|
+
"binary"
|
|
11522
|
+
];
|
|
11523
|
+
var NUMERIC_AGGREGATES = [
|
|
11524
|
+
"mean",
|
|
11525
|
+
"median",
|
|
11526
|
+
"min",
|
|
11527
|
+
"max",
|
|
11528
|
+
"sum"
|
|
11529
|
+
];
|
|
11530
|
+
var BINARY_AGGREGATES = ["any", "all"];
|
|
11531
|
+
var AGGREGATE_REDUCERS = [
|
|
11532
|
+
"mean",
|
|
11533
|
+
"median",
|
|
11534
|
+
"min",
|
|
11535
|
+
"max",
|
|
11536
|
+
"sum",
|
|
11537
|
+
"any",
|
|
11538
|
+
"all"
|
|
11539
|
+
];
|
|
11540
|
+
var GroupTemplateIdSchema = _enum(GROUP_TEMPLATE_IDS);
|
|
11541
|
+
var AggregateReducerSchema = _enum(AGGREGATE_REDUCERS);
|
|
11542
|
+
/** One member. The field is stored so occupancy can name motion or binary. */
|
|
11543
|
+
var HelperMemberSchema = object({
|
|
11544
|
+
source: CompositionSourceRefSchema,
|
|
11545
|
+
cap: string().min(1),
|
|
11546
|
+
fieldPath: string().min(1)
|
|
11547
|
+
});
|
|
11548
|
+
var HelperSpecSchema = discriminatedUnion("kind", [object({
|
|
11549
|
+
kind: literal("group"),
|
|
11550
|
+
templateId: GroupTemplateIdSchema,
|
|
11551
|
+
aggregate: AggregateReducerSchema,
|
|
11552
|
+
members: array(HelperMemberSchema).min(1).max(64)
|
|
11553
|
+
})]);
|
|
11554
|
+
/** A composed device's stableId is this prefix plus the block id. */
|
|
11555
|
+
var COMPOSED_DEVICE_STABLE_ID_PREFIX = "composed-";
|
|
11556
|
+
/** Longest snippet a `code` source may carry (slice 4). */
|
|
11557
|
+
var MAX_COMPOSITION_CODE_LENGTH = 2e4;
|
|
11494
11558
|
/** One field of one capability of one source device. */
|
|
11495
11559
|
var CompositionFieldReadSchema = object({
|
|
11496
11560
|
source: CompositionSourceRefSchema,
|
|
@@ -11534,7 +11598,33 @@ var CompositionCodeSourceSchema = object({
|
|
|
11534
11598
|
var CompositionFieldSourceSchema = discriminatedUnion("kind", [
|
|
11535
11599
|
CompositionFromSourceSchema,
|
|
11536
11600
|
CompositionExpressionSourceSchema,
|
|
11537
|
-
CompositionCodeSourceSchema
|
|
11601
|
+
CompositionCodeSourceSchema,
|
|
11602
|
+
object({
|
|
11603
|
+
kind: literal("aggregate"),
|
|
11604
|
+
reducer: _enum([
|
|
11605
|
+
"mean",
|
|
11606
|
+
"median",
|
|
11607
|
+
"min",
|
|
11608
|
+
"max",
|
|
11609
|
+
"sum",
|
|
11610
|
+
"any",
|
|
11611
|
+
"all"
|
|
11612
|
+
]),
|
|
11613
|
+
reads: array(CompositionFieldReadSchema).min(1).max(64),
|
|
11614
|
+
/** `value` is the reading; the others are the member counts. */
|
|
11615
|
+
publish: _enum([
|
|
11616
|
+
"value",
|
|
11617
|
+
"included",
|
|
11618
|
+
"excluded",
|
|
11619
|
+
"total"
|
|
11620
|
+
]),
|
|
11621
|
+
/** What a `value` publish does when nobody is included. Counts ignore this. */
|
|
11622
|
+
empty: _enum([
|
|
11623
|
+
"null",
|
|
11624
|
+
"omit",
|
|
11625
|
+
"offline"
|
|
11626
|
+
])
|
|
11627
|
+
})
|
|
11538
11628
|
]);
|
|
11539
11629
|
var CompositionCommandTargetSchema = discriminatedUnion("kind", [object({
|
|
11540
11630
|
kind: literal("forward"),
|
|
@@ -11580,7 +11670,13 @@ var CompositionSchema = object({
|
|
|
11580
11670
|
kind: literal("existing"),
|
|
11581
11671
|
device: CompositionSourceRefSchema
|
|
11582
11672
|
})]),
|
|
11583
|
-
features: array(CompositionFeatureSchema).min(1).max(16)
|
|
11673
|
+
features: array(CompositionFeatureSchema).min(1).max(16),
|
|
11674
|
+
/**
|
|
11675
|
+
* Present when the block is a helper template. Absent on a free
|
|
11676
|
+
* composition (the room example, device 4603). The editor reads this,
|
|
11677
|
+
* never the compiled features.
|
|
11678
|
+
*/
|
|
11679
|
+
helper: HelperSpecSchema.optional()
|
|
11584
11680
|
}).superRefine((composition, ctx) => {
|
|
11585
11681
|
const seen = /* @__PURE__ */ new Set();
|
|
11586
11682
|
composition.features.forEach((feature, index) => {
|
|
@@ -17682,7 +17778,11 @@ var CompositionProblemSchema = object({
|
|
|
17682
17778
|
"item-field-reserved",
|
|
17683
17779
|
"target-missing",
|
|
17684
17780
|
"target-unreadable",
|
|
17685
|
-
"not-replaceable"
|
|
17781
|
+
"not-replaceable",
|
|
17782
|
+
"native-capability-replace",
|
|
17783
|
+
"mixed-quantity",
|
|
17784
|
+
"helper-mismatch",
|
|
17785
|
+
"member-constraint"
|
|
17686
17786
|
]),
|
|
17687
17787
|
path: string(),
|
|
17688
17788
|
message: string()
|
|
@@ -17703,7 +17803,8 @@ var CompositionUnavailableModeSchema = _enum([
|
|
|
17703
17803
|
"null",
|
|
17704
17804
|
"offline",
|
|
17705
17805
|
"unknown",
|
|
17706
|
-
"release"
|
|
17806
|
+
"release",
|
|
17807
|
+
"omit"
|
|
17707
17808
|
]);
|
|
17708
17809
|
/**
|
|
17709
17810
|
* `derived` reads a source · `clock` reads only `now`, recomputed when a sibling
|
|
@@ -17740,9 +17841,11 @@ var CompositionFieldPlanSchema = object({
|
|
|
17740
17841
|
reads: array(CompositionFieldReadSchema)
|
|
17741
17842
|
});
|
|
17742
17843
|
/**
|
|
17743
|
-
* What a feature does to its target (D663): `new` builds a capability on a
|
|
17744
|
-
* device; on an existing device it `add`s a capability the device lacks
|
|
17745
|
-
*
|
|
17844
|
+
* What a feature does to its target (D663, D944): `new` builds a capability on a
|
|
17845
|
+
* new device; on an existing device it `add`s a capability the device lacks.
|
|
17846
|
+
* Replacing a capability the device already serves is refused
|
|
17847
|
+
* (`native-capability-replace`), not planned. `replace` remains on the claim
|
|
17848
|
+
* wire for a claim the hub already holds.
|
|
17746
17849
|
*/
|
|
17747
17850
|
var CompositionFeatureModeSchema = _enum([
|
|
17748
17851
|
"new",
|
|
@@ -17915,6 +18018,235 @@ Object.freeze({
|
|
|
17915
18018
|
result: ["number", "null"]
|
|
17916
18019
|
}
|
|
17917
18020
|
});
|
|
18021
|
+
/**
|
|
18022
|
+
* One catalog row per base reading a group helper can build (D944 §3).
|
|
18023
|
+
* Data, not a form default written into the block.
|
|
18024
|
+
*/
|
|
18025
|
+
var NOW = {
|
|
18026
|
+
fieldPath: "lastFetchedAt",
|
|
18027
|
+
expr: "now"
|
|
18028
|
+
};
|
|
18029
|
+
var CHANGED = {
|
|
18030
|
+
fieldPath: "lastChangedAt",
|
|
18031
|
+
expr: "now"
|
|
18032
|
+
};
|
|
18033
|
+
function numeric(input) {
|
|
18034
|
+
return {
|
|
18035
|
+
...input,
|
|
18036
|
+
family: "numeric",
|
|
18037
|
+
deviceType: DeviceType.Sensor,
|
|
18038
|
+
memberDeviceType: DeviceType.Sensor,
|
|
18039
|
+
baseUnit: baseUnitOf(input.quantity),
|
|
18040
|
+
aggregates: NUMERIC_AGGREGATES,
|
|
18041
|
+
accept: [{
|
|
18042
|
+
cap: input.outputCap,
|
|
18043
|
+
fieldPath: input.outputField
|
|
18044
|
+
}]
|
|
18045
|
+
};
|
|
18046
|
+
}
|
|
18047
|
+
function binary(input) {
|
|
18048
|
+
return {
|
|
18049
|
+
...input,
|
|
18050
|
+
family: "binary",
|
|
18051
|
+
deviceType: DeviceType.Sensor,
|
|
18052
|
+
memberDeviceType: DeviceType.Sensor,
|
|
18053
|
+
quantity: "none",
|
|
18054
|
+
baseUnit: void 0,
|
|
18055
|
+
aggregates: BINARY_AGGREGATES,
|
|
18056
|
+
empty: "offline"
|
|
18057
|
+
};
|
|
18058
|
+
}
|
|
18059
|
+
var GROUP_TEMPLATES = [
|
|
18060
|
+
numeric({
|
|
18061
|
+
id: "temperature",
|
|
18062
|
+
summary: "Mean, median, min, max or sum of temperatures. Offline and unknown members are left out, never read as 0 °C.",
|
|
18063
|
+
role: DeviceRole.TemperatureSensor,
|
|
18064
|
+
outputCap: "temperature-sensor",
|
|
18065
|
+
outputField: "celsius",
|
|
18066
|
+
quantity: "temperature",
|
|
18067
|
+
defaultAggregate: "mean",
|
|
18068
|
+
empty: "null",
|
|
18069
|
+
companions: [NOW]
|
|
18070
|
+
}),
|
|
18071
|
+
numeric({
|
|
18072
|
+
id: "humidity",
|
|
18073
|
+
summary: "Humidity in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
18074
|
+
role: DeviceRole.HumiditySensor,
|
|
18075
|
+
outputCap: "humidity-sensor",
|
|
18076
|
+
outputField: "percent",
|
|
18077
|
+
quantity: "humidity",
|
|
18078
|
+
defaultAggregate: "mean",
|
|
18079
|
+
empty: "null",
|
|
18080
|
+
companions: [NOW]
|
|
18081
|
+
}),
|
|
18082
|
+
numeric({
|
|
18083
|
+
id: "pressure",
|
|
18084
|
+
summary: "Pressure in hectopascals. Offline and unknown members are left out, never read as 0 hPa.",
|
|
18085
|
+
role: DeviceRole.PressureSensor,
|
|
18086
|
+
outputCap: "pressure-sensor",
|
|
18087
|
+
outputField: "hpa",
|
|
18088
|
+
quantity: "pressure",
|
|
18089
|
+
defaultAggregate: "mean",
|
|
18090
|
+
empty: "null",
|
|
18091
|
+
companions: [NOW]
|
|
18092
|
+
}),
|
|
18093
|
+
numeric({
|
|
18094
|
+
id: "illuminance",
|
|
18095
|
+
summary: "Illuminance in lux. Offline and unknown members are left out, never read as 0 lx.",
|
|
18096
|
+
role: DeviceRole.AmbientLightSensor,
|
|
18097
|
+
outputCap: "ambient-light-sensor",
|
|
18098
|
+
outputField: "lux",
|
|
18099
|
+
quantity: "illuminance",
|
|
18100
|
+
defaultAggregate: "mean",
|
|
18101
|
+
empty: "null",
|
|
18102
|
+
companions: [NOW]
|
|
18103
|
+
}),
|
|
18104
|
+
numeric({
|
|
18105
|
+
id: "power",
|
|
18106
|
+
summary: "Power in watts, summed by default. Nobody reporting omits the key rather than writing 0 W.",
|
|
18107
|
+
role: DeviceRole.PowerSensor,
|
|
18108
|
+
outputCap: "power-meter",
|
|
18109
|
+
outputField: "watts",
|
|
18110
|
+
quantity: "power",
|
|
18111
|
+
defaultAggregate: "sum",
|
|
18112
|
+
empty: "omit",
|
|
18113
|
+
companions: [NOW]
|
|
18114
|
+
}),
|
|
18115
|
+
numeric({
|
|
18116
|
+
id: "energy",
|
|
18117
|
+
summary: "Energy in kilowatt-hours, summed by default. Nobody reporting omits the key rather than writing 0 kWh.",
|
|
18118
|
+
role: DeviceRole.EnergySensor,
|
|
18119
|
+
outputCap: "power-meter",
|
|
18120
|
+
outputField: "kwhTotal",
|
|
18121
|
+
quantity: "energy",
|
|
18122
|
+
defaultAggregate: "sum",
|
|
18123
|
+
empty: "omit",
|
|
18124
|
+
companions: [NOW]
|
|
18125
|
+
}),
|
|
18126
|
+
numeric({
|
|
18127
|
+
id: "battery",
|
|
18128
|
+
summary: "Battery charge in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
18129
|
+
role: DeviceRole.BatterySensor,
|
|
18130
|
+
outputCap: "battery",
|
|
18131
|
+
outputField: "percentage",
|
|
18132
|
+
quantity: "percentage",
|
|
18133
|
+
defaultAggregate: "mean",
|
|
18134
|
+
empty: "null",
|
|
18135
|
+
companions: [
|
|
18136
|
+
{
|
|
18137
|
+
fieldPath: "charging",
|
|
18138
|
+
expr: "\"unknown\""
|
|
18139
|
+
},
|
|
18140
|
+
{
|
|
18141
|
+
fieldPath: "sleeping",
|
|
18142
|
+
expr: "false"
|
|
18143
|
+
},
|
|
18144
|
+
{
|
|
18145
|
+
fieldPath: "lastUpdated",
|
|
18146
|
+
expr: "now"
|
|
18147
|
+
}
|
|
18148
|
+
]
|
|
18149
|
+
}),
|
|
18150
|
+
numeric({
|
|
18151
|
+
id: "numeric",
|
|
18152
|
+
summary: "A numeric reading in the members’ shared quantity. Mixed quantities are refused. Nobody reporting publishes null, not 0.",
|
|
18153
|
+
role: DeviceRole.NumericSensor,
|
|
18154
|
+
outputCap: "numeric-sensor",
|
|
18155
|
+
outputField: "value",
|
|
18156
|
+
quantity: "device",
|
|
18157
|
+
defaultAggregate: "mean",
|
|
18158
|
+
empty: "null",
|
|
18159
|
+
companions: [NOW]
|
|
18160
|
+
}),
|
|
18161
|
+
binary({
|
|
18162
|
+
id: "motion",
|
|
18163
|
+
summary: "Any or all motion. Offline and unknown members are left out, never read as off. Nobody reporting takes the device offline.",
|
|
18164
|
+
role: DeviceRole.MotionSensor,
|
|
18165
|
+
outputCap: "motion",
|
|
18166
|
+
outputField: "detected",
|
|
18167
|
+
defaultAggregate: "any",
|
|
18168
|
+
accept: [{
|
|
18169
|
+
cap: "motion",
|
|
18170
|
+
fieldPath: "detected"
|
|
18171
|
+
}],
|
|
18172
|
+
companions: [{
|
|
18173
|
+
fieldPath: "lastDetectedAt",
|
|
18174
|
+
expr: "null"
|
|
18175
|
+
}, {
|
|
18176
|
+
fieldPath: "autoClearAfterMs",
|
|
18177
|
+
expr: "null"
|
|
18178
|
+
}]
|
|
18179
|
+
}),
|
|
18180
|
+
binary({
|
|
18181
|
+
id: "contact",
|
|
18182
|
+
summary: "Any or all open contacts. Offline and unknown members are left out, never read as closed.",
|
|
18183
|
+
role: DeviceRole.ContactSensor,
|
|
18184
|
+
outputCap: "contact",
|
|
18185
|
+
outputField: "entryOpen",
|
|
18186
|
+
defaultAggregate: "any",
|
|
18187
|
+
accept: [{
|
|
18188
|
+
cap: "contact",
|
|
18189
|
+
fieldPath: "entryOpen"
|
|
18190
|
+
}],
|
|
18191
|
+
companions: [CHANGED]
|
|
18192
|
+
}),
|
|
18193
|
+
binary({
|
|
18194
|
+
id: "leak",
|
|
18195
|
+
summary: "Any or all leak detections. Offline and unknown members are left out, never read as dry.",
|
|
18196
|
+
role: DeviceRole.LeakSensor,
|
|
18197
|
+
outputCap: "flood",
|
|
18198
|
+
outputField: "flooded",
|
|
18199
|
+
defaultAggregate: "any",
|
|
18200
|
+
accept: [{
|
|
18201
|
+
cap: "flood",
|
|
18202
|
+
fieldPath: "flooded"
|
|
18203
|
+
}],
|
|
18204
|
+
companions: [CHANGED]
|
|
18205
|
+
}),
|
|
18206
|
+
binary({
|
|
18207
|
+
id: "smoke",
|
|
18208
|
+
summary: "Any or all smoke detections. Offline and unknown members are left out, never read as clear.",
|
|
18209
|
+
role: DeviceRole.SmokeSensor,
|
|
18210
|
+
outputCap: "smoke",
|
|
18211
|
+
outputField: "detected",
|
|
18212
|
+
defaultAggregate: "any",
|
|
18213
|
+
accept: [{
|
|
18214
|
+
cap: "smoke",
|
|
18215
|
+
fieldPath: "detected"
|
|
18216
|
+
}],
|
|
18217
|
+
companions: [CHANGED]
|
|
18218
|
+
}),
|
|
18219
|
+
binary({
|
|
18220
|
+
id: "occupancy",
|
|
18221
|
+
summary: "Any or all of motion or binary sensors, published as a binary. Presence zones are not aggregated. Nobody reporting is offline, not off.",
|
|
18222
|
+
role: DeviceRole.BinarySensor,
|
|
18223
|
+
outputCap: "binary",
|
|
18224
|
+
outputField: "on",
|
|
18225
|
+
defaultAggregate: "any",
|
|
18226
|
+
accept: [{
|
|
18227
|
+
cap: "motion",
|
|
18228
|
+
fieldPath: "detected"
|
|
18229
|
+
}, {
|
|
18230
|
+
cap: "binary",
|
|
18231
|
+
fieldPath: "on"
|
|
18232
|
+
}],
|
|
18233
|
+
companions: [CHANGED]
|
|
18234
|
+
}),
|
|
18235
|
+
binary({
|
|
18236
|
+
id: "binary",
|
|
18237
|
+
summary: "Any or all generic binary sensors. Offline and unknown members are left out, never read as off.",
|
|
18238
|
+
role: DeviceRole.BinarySensor,
|
|
18239
|
+
outputCap: "binary",
|
|
18240
|
+
outputField: "on",
|
|
18241
|
+
defaultAggregate: "any",
|
|
18242
|
+
accept: [{
|
|
18243
|
+
cap: "binary",
|
|
18244
|
+
fieldPath: "on"
|
|
18245
|
+
}],
|
|
18246
|
+
companions: [CHANGED]
|
|
18247
|
+
})
|
|
18248
|
+
];
|
|
18249
|
+
new Map(GROUP_TEMPLATES.map((template) => [template.id, template]));
|
|
17918
18250
|
`${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
|
|
17919
18251
|
/**
|
|
17920
18252
|
* What a composition may BUILD on a device type (G2, D676): the caps a new
|
|
@@ -19628,12 +19960,12 @@ method(object({ deviceId: number().int().nonnegative() }), DeviceAdminLinkSchema
|
|
|
19628
19960
|
* providers detect renames by matching `uniqueId` and patch `id`
|
|
19629
19961
|
* in-place so dispatch keeps working.
|
|
19630
19962
|
*
|
|
19631
|
-
* **
|
|
19632
|
-
*
|
|
19633
|
-
*
|
|
19634
|
-
*
|
|
19635
|
-
* (`ha-domain-mapping`)
|
|
19636
|
-
* stored after that point.
|
|
19963
|
+
* **Display unit and precision are NOT stored here.** They are a read-time
|
|
19964
|
+
* preference (D944). A polymorphic reading stores its `quantity` here once,
|
|
19965
|
+
* at adopt, and a date/time value stores `dateTimeShape` the same way —
|
|
19966
|
+
* neither is repeated on each sample. The `device_class` tag is an
|
|
19967
|
+
* HA-specific input consumed at the discovery boundary (`ha-domain-mapping`)
|
|
19968
|
+
* to derive the CamStack `DeviceRole`; it is never stored after that point.
|
|
19637
19969
|
*
|
|
19638
19970
|
* The `raw` escape hatch carries provider-specific attributes that don't
|
|
19639
19971
|
* fit the structured slots (HA `attributes` whitelist, Reolink `deviceCache`
|
|
@@ -19647,6 +19979,14 @@ var SourceInfoSchema = object({
|
|
|
19647
19979
|
/** Immutable upstream identifier when available (HA `unique_id`, … ).
|
|
19648
19980
|
* Used to detect rename when `id` changes. */
|
|
19649
19981
|
uniqueId: string().optional(),
|
|
19982
|
+
/** Quantity of a polymorphic reading, written once at adopt (D944). */
|
|
19983
|
+
quantity: ReadingQuantitySchema.optional(),
|
|
19984
|
+
/** Date / time / datetime shape of a string reading, written once at adopt. */
|
|
19985
|
+
dateTimeShape: _enum([
|
|
19986
|
+
"date",
|
|
19987
|
+
"time",
|
|
19988
|
+
"datetime"
|
|
19989
|
+
]).optional(),
|
|
19650
19990
|
/** Provider-specific extras that don't fit the structured slots.
|
|
19651
19991
|
* Whitelist what goes here per provider — do NOT dump entire HA
|
|
19652
19992
|
* attribute blobs (would explode the meta JSON column). */
|
|
@@ -40559,7 +40899,8 @@ method(object({
|
|
|
40559
40899
|
"enum"
|
|
40560
40900
|
]),
|
|
40561
40901
|
enumValues: array(string()).optional(),
|
|
40562
|
-
item: boolean().optional()
|
|
40902
|
+
item: boolean().optional(),
|
|
40903
|
+
quantity: ReadingQuantitySchema.optional()
|
|
40563
40904
|
})).readonly(),
|
|
40564
40905
|
itemArray: object({
|
|
40565
40906
|
path: string(),
|
|
@@ -44359,8 +44700,8 @@ var MaskPolygonShapeSchema = object({
|
|
|
44359
44700
|
/** Boolean cell grid — row-major, length === gridWidth*gridHeight. */
|
|
44360
44701
|
var MaskGridShapeSchema = object({
|
|
44361
44702
|
kind: literal("grid"),
|
|
44362
|
-
gridWidth: number(),
|
|
44363
|
-
gridHeight: number(),
|
|
44703
|
+
gridWidth: number().meta(readingMeta("none")),
|
|
44704
|
+
gridHeight: number().meta(readingMeta("none")),
|
|
44364
44705
|
cells: array(boolean())
|
|
44365
44706
|
});
|
|
44366
44707
|
discriminatedUnion("kind", [
|
|
@@ -55754,46 +56095,27 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
|
|
|
55754
56095
|
}), LogStreamEntrySchema, { kind: "subscription" });
|
|
55755
56096
|
object({
|
|
55756
56097
|
/** Carbon dioxide concentration in ppm. */
|
|
55757
|
-
co2Ppm: number().min(0).optional(),
|
|
56098
|
+
co2Ppm: number().min(0).optional().meta(readingMeta("concentration-volume")),
|
|
55758
56099
|
/** Total volatile organic compounds in ppb. */
|
|
55759
|
-
vocPpb: number().min(0).optional(),
|
|
56100
|
+
vocPpb: number().min(0).optional().meta(readingMeta("concentration-ppb")),
|
|
55760
56101
|
/** Particulate matter ≤ 2.5 μm in µg/m³. */
|
|
55761
|
-
pm25: number().min(0).optional(),
|
|
56102
|
+
pm25: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
55762
56103
|
/** Particulate matter ≤ 10 μm in µg/m³. */
|
|
55763
|
-
pm10: number().min(0).optional(),
|
|
56104
|
+
pm10: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
55764
56105
|
/** Composite AQI value (typically 0..500). */
|
|
55765
|
-
aqi: number().optional(),
|
|
56106
|
+
aqi: number().optional().meta(readingMeta("index")),
|
|
55766
56107
|
/** Ms epoch when the slice was last updated. */
|
|
55767
|
-
lastFetchedAt: number()
|
|
55768
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
55769
|
-
* `attributes.unit_of_measurement` → 'ppm' / 'ppb' / 'µg/m³'). Each
|
|
55770
|
-
* upstream `sensor.*` entity surfaces ONE device_class, so one unit
|
|
55771
|
-
* per slice is unambiguous. */
|
|
55772
|
-
unit: string().optional(),
|
|
55773
|
-
/** Suggested decimal places for numeric display.
|
|
55774
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
55775
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
55776
|
-
* auto-formatting when absent. */
|
|
55777
|
-
precision: number().int().min(0).max(10).optional()
|
|
56108
|
+
lastFetchedAt: number()
|
|
55778
56109
|
});
|
|
55779
56110
|
DeviceType.Sensor;
|
|
55780
56111
|
object({
|
|
55781
|
-
/** Current illuminance in lux (lx). */
|
|
55782
|
-
lux: number().min(0).meta({
|
|
55783
|
-
|
|
56112
|
+
/** Current illuminance in lux (lx). `null` when the sample was refused (D393). */
|
|
56113
|
+
lux: number().min(0).nullable().meta(readingMeta("illuminance", {
|
|
56114
|
+
precision: 0,
|
|
55784
56115
|
label: "Illuminance"
|
|
55785
|
-
}),
|
|
56116
|
+
})),
|
|
55786
56117
|
/** Ms epoch when the slice was last updated. */
|
|
55787
|
-
lastFetchedAt: number()
|
|
55788
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
55789
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
55790
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
55791
|
-
unit: string().optional(),
|
|
55792
|
-
/** Suggested decimal places for numeric display.
|
|
55793
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
55794
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
55795
|
-
* auto-formatting when absent. */
|
|
55796
|
-
precision: number().int().min(0).max(10).optional()
|
|
56118
|
+
lastFetchedAt: number()
|
|
55797
56119
|
});
|
|
55798
56120
|
DeviceType.Sensor;
|
|
55799
56121
|
/**
|
|
@@ -55938,10 +56260,7 @@ var BatteryStatusSchema = object({
|
|
|
55938
56260
|
* Consumers must SKIP a null rather than coerce it — `battery-band` already
|
|
55939
56261
|
* declines to band a non-finite reading, which is the correct shape.
|
|
55940
56262
|
*/
|
|
55941
|
-
percentage: number().min(0).max(100).nullable().meta({
|
|
55942
|
-
unit: "%",
|
|
55943
|
-
label: "Charge"
|
|
55944
|
-
}),
|
|
56263
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage", { label: "Charge" })),
|
|
55945
56264
|
/**
|
|
55946
56265
|
* Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
|
|
55947
56266
|
* Reolink-specific for the Solar Panel 2 accessory (will become
|
|
@@ -55968,7 +56287,14 @@ var BatteryStatusSchema = object({
|
|
|
55968
56287
|
*/
|
|
55969
56288
|
sleeping: boolean().meta({ label: "Sleeping" }),
|
|
55970
56289
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
55971
|
-
lastUpdated: number(),
|
|
56290
|
+
lastUpdated: number().meta(readingMeta("none")),
|
|
56291
|
+
/**
|
|
56292
|
+
* Battery voltage in volts, for a cell the firmware reports as voltage
|
|
56293
|
+
* rather than a percentage (Ecowitt capacitor packs). Absent on cameras
|
|
56294
|
+
* that only report charge. A second reading on this cap, not a second
|
|
56295
|
+
* `numeric-sensor` on the same device.
|
|
56296
|
+
*/
|
|
56297
|
+
volts: number().nullable().optional().meta(readingMeta("voltage", { label: "Voltage" })),
|
|
55972
56298
|
/**
|
|
55973
56299
|
* Ms epoch of the last time the device PROVED it was reachable — a
|
|
55974
56300
|
* completed firmware round-trip, an observed wake, or an inbound push
|
|
@@ -56028,7 +56354,7 @@ object({
|
|
|
56028
56354
|
DeviceType.Sensor;
|
|
56029
56355
|
object({
|
|
56030
56356
|
/** Current level as 0..100 inclusive. Firmware-reported. */
|
|
56031
|
-
percentage: number().min(0).max(100),
|
|
56357
|
+
percentage: number().min(0).max(100).meta(readingMeta("percentage")),
|
|
56032
56358
|
/** Ms epoch of the last operator-driven change. Useful for UI freshness. */
|
|
56033
56359
|
lastChangedAt: number()
|
|
56034
56360
|
});
|
|
@@ -56413,21 +56739,21 @@ object({
|
|
|
56413
56739
|
/** Single setpoint in Celsius. Used by single-target modes
|
|
56414
56740
|
* (heat / cool / dry). Null when the device is in a range mode
|
|
56415
56741
|
* (`heat_cool`) or has no setpoint at all (`fan_only`/`off`). */
|
|
56416
|
-
target: number().nullable(),
|
|
56742
|
+
target: number().nullable().meta(readingMeta("temperature")),
|
|
56417
56743
|
/** Upper bound of the dual setpoint in Celsius. Populated only
|
|
56418
56744
|
* in `heat_cool` mode. */
|
|
56419
|
-
targetHigh: number().nullable(),
|
|
56745
|
+
targetHigh: number().nullable().meta(readingMeta("temperature")),
|
|
56420
56746
|
/** Lower bound of the dual setpoint in Celsius. Populated only
|
|
56421
56747
|
* in `heat_cool` mode. */
|
|
56422
|
-
targetLow: number().nullable(),
|
|
56748
|
+
targetLow: number().nullable().meta(readingMeta("temperature")),
|
|
56423
56749
|
/** Target relative humidity (0..100). Null when the device has no
|
|
56424
56750
|
* humidity control. */
|
|
56425
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
56751
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
56426
56752
|
/** Current measured temperature in Celsius. Read-only — pushed by
|
|
56427
56753
|
* the device's internal sensor. */
|
|
56428
|
-
currentTemp: number().nullable(),
|
|
56754
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
56429
56755
|
/** Current measured relative humidity (0..100). Read-only. */
|
|
56430
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
56756
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
56431
56757
|
/** Vertical louver swing on/off. Null when the device has no vertical
|
|
56432
56758
|
* swing surface (gate with `DeviceFeature.ClimateSwingVertical`). */
|
|
56433
56759
|
swingVertical: boolean().nullable(),
|
|
@@ -56435,11 +56761,11 @@ object({
|
|
|
56435
56761
|
* horizontal swing surface (gate with `DeviceFeature.ClimateSwingHorizontal`). */
|
|
56436
56762
|
swingHorizontal: boolean().nullable(),
|
|
56437
56763
|
/** Lowest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
56438
|
-
minTemp: number().nullable().optional(),
|
|
56764
|
+
minTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
56439
56765
|
/** Highest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
56440
|
-
maxTemp: number().nullable().optional(),
|
|
56766
|
+
maxTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
56441
56767
|
/** Setpoint granularity, Celsius (0.5, 1). Absent / null = not reported. */
|
|
56442
|
-
tempStep: number().positive().nullable().optional(),
|
|
56768
|
+
tempStep: number().positive().nullable().optional().meta(readingMeta("temperature")),
|
|
56443
56769
|
/** Ms epoch when the slice was last updated (push or command). */
|
|
56444
56770
|
lastFetchedAt: number()
|
|
56445
56771
|
});
|
|
@@ -56518,17 +56844,17 @@ DeviceType.Thermostat, DeviceType.Climate, method(object({
|
|
|
56518
56844
|
* modes to expose in the picker without a slice fetch.
|
|
56519
56845
|
*/
|
|
56520
56846
|
var RgbTripletSchema = object({
|
|
56521
|
-
r: number().int().min(0).max(255),
|
|
56522
|
-
g: number().int().min(0).max(255),
|
|
56523
|
-
b: number().int().min(0).max(255)
|
|
56847
|
+
r: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
56848
|
+
g: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
56849
|
+
b: number().int().min(0).max(255).meta(readingMeta("none"))
|
|
56524
56850
|
});
|
|
56525
56851
|
var HsvTripletSchema = object({
|
|
56526
56852
|
/** Hue in degrees, 0..360. */
|
|
56527
|
-
h: number().min(0).max(360),
|
|
56853
|
+
h: number().min(0).max(360).meta(readingMeta("none")),
|
|
56528
56854
|
/** Saturation as 0..100 inclusive. */
|
|
56529
|
-
s: number().min(0).max(100),
|
|
56855
|
+
s: number().min(0).max(100).meta(readingMeta("none")),
|
|
56530
56856
|
/** Value/brightness as 0..100 inclusive. */
|
|
56531
|
-
v: number().min(0).max(100)
|
|
56857
|
+
v: number().min(0).max(100).meta(readingMeta("none"))
|
|
56532
56858
|
});
|
|
56533
56859
|
var ColorInputSchema = discriminatedUnion("mode", [
|
|
56534
56860
|
object({
|
|
@@ -56557,7 +56883,7 @@ object({
|
|
|
56557
56883
|
/** Populated when `mode === 'hsv'`. */
|
|
56558
56884
|
hsv: HsvTripletSchema.optional(),
|
|
56559
56885
|
/** Populated when `mode === 'mired'`. */
|
|
56560
|
-
mireds: number().int().optional(),
|
|
56886
|
+
mireds: number().int().optional().meta(readingMeta("colour-temperature")),
|
|
56561
56887
|
/** Ms epoch of the last operator-driven change. */
|
|
56562
56888
|
lastChangedAt: number()
|
|
56563
56889
|
});
|
|
@@ -56681,18 +57007,12 @@ _enum([
|
|
|
56681
57007
|
"empty",
|
|
56682
57008
|
"full"
|
|
56683
57009
|
]);
|
|
56684
|
-
/**
|
|
56685
|
-
|
|
56686
|
-
|
|
56687
|
-
"days",
|
|
56688
|
-
"hours",
|
|
56689
|
-
"cycles"
|
|
56690
|
-
]);
|
|
56691
|
-
/** Remaining life as a COUNT, not a percentage (the PetKit desiccant reports
|
|
56692
|
-
* days). `value` null = unknown (D393). */
|
|
57010
|
+
/** Whether `remaining.value` is a duration in seconds or a dimensionless count. */
|
|
57011
|
+
var ConsumableRemainingKindSchema = _enum(["duration", "count"]);
|
|
57012
|
+
/** Remaining life. `value` null = unknown (D393). Duration is seconds. */
|
|
56693
57013
|
var ConsumableRemainingSchema = object({
|
|
56694
|
-
value: number().min(0).nullable(),
|
|
56695
|
-
|
|
57014
|
+
value: number().min(0).nullable().meta(readingMeta("device")),
|
|
57015
|
+
kind: ConsumableRemainingKindSchema
|
|
56696
57016
|
});
|
|
56697
57017
|
var ConsumablesStatusSchema = object({
|
|
56698
57018
|
items: array(object({
|
|
@@ -56701,7 +57021,7 @@ var ConsumablesStatusSchema = object({
|
|
|
56701
57021
|
/** Display name. */
|
|
56702
57022
|
label: string().min(1),
|
|
56703
57023
|
/** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
|
|
56704
|
-
level: number().min(0).max(100).nullable(),
|
|
57024
|
+
level: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
56705
57025
|
/** The provider's discrete verdict when known (binary mode). */
|
|
56706
57026
|
status: ConsumableStatusSchema.nullable(),
|
|
56707
57027
|
/** What the item is — decides whether low or full is bad. Absent = `wear`. */
|
|
@@ -56718,7 +57038,7 @@ var ConsumablesStatusSchema = object({
|
|
|
56718
57038
|
})),
|
|
56719
57039
|
lastChangedAt: number()
|
|
56720
57040
|
});
|
|
56721
|
-
Object.values(DeviceType), [...
|
|
57041
|
+
Object.values(DeviceType), [...ConsumableRemainingKindSchema.options], [...ConsumableStatusSchema.options], [...ConsumableKindSchema.options], [...ConsumableFormSchema.options];
|
|
56722
57042
|
Object.values(DeviceType), method(object({
|
|
56723
57043
|
deviceId: number().int().nonnegative(),
|
|
56724
57044
|
key: string().min(1)
|
|
@@ -56743,39 +57063,17 @@ object({
|
|
|
56743
57063
|
/** Current value. Numeric kind → number; select/text/datetime → string.
|
|
56744
57064
|
* Datetime values are ISO 8601 strings (full timestamp, date-only,
|
|
56745
57065
|
* or time-only — HA accepts all three forms). */
|
|
56746
|
-
value: union([number(), string()]),
|
|
57066
|
+
value: union([number().meta(readingMeta("device")), string()]),
|
|
56747
57067
|
/** Acceptable values when `kind === 'select'`. Empty for other kinds. */
|
|
56748
57068
|
options: array(string()),
|
|
56749
57069
|
/** Ms epoch when the slice was last updated. */
|
|
56750
57070
|
lastChangedAt: number(),
|
|
56751
|
-
/**
|
|
56752
|
-
|
|
56753
|
-
|
|
56754
|
-
|
|
56755
|
-
/**
|
|
56756
|
-
|
|
56757
|
-
min: number().optional(),
|
|
56758
|
-
/** Maximum allowed value. Populated live from HA `attributes.max`.
|
|
56759
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
56760
|
-
max: number().optional(),
|
|
56761
|
-
/** Step increment. Populated live from HA `attributes.step`.
|
|
56762
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
56763
|
-
step: number().optional(),
|
|
56764
|
-
/** Suggested decimal places for numeric display. Populated live from HA
|
|
56765
|
-
* `attributes.suggested_display_precision`, or derived from `step` when the
|
|
56766
|
-
* HA attribute is absent. Meaningful for `kind === 'numeric'`; absent for
|
|
56767
|
-
* other kinds. Falls back to auto-formatting when absent. */
|
|
56768
|
-
precision: number().int().min(0).max(10).optional(),
|
|
56769
|
-
/** Date-picker granularity for `kind === 'datetime'`. 'date' → date-only,
|
|
56770
|
-
* 'time' → time-only, 'datetime' → full timestamp. Absent for other kinds
|
|
56771
|
-
* (UI defaults to 'datetime'). Derived live from the device's HA domain
|
|
56772
|
-
* (date.* / time.* / datetime.*) or, for input_datetime, from the entity's
|
|
56773
|
-
* `has_date`/`has_time` attributes on each push. */
|
|
56774
|
-
format: _enum([
|
|
56775
|
-
"date",
|
|
56776
|
-
"time",
|
|
56777
|
-
"datetime"
|
|
56778
|
-
]).optional()
|
|
57071
|
+
/** Minimum allowed value, in the device quantity's base unit. */
|
|
57072
|
+
min: number().optional().meta(readingMeta("device")),
|
|
57073
|
+
/** Maximum allowed value, in the device quantity's base unit. */
|
|
57074
|
+
max: number().optional().meta(readingMeta("device")),
|
|
57075
|
+
/** Step increment, in the device quantity's base unit. */
|
|
57076
|
+
step: number().optional().meta(readingMeta("device"))
|
|
56779
57077
|
});
|
|
56780
57078
|
var ControlSetValueInputSchema = discriminatedUnion("kind", [
|
|
56781
57079
|
object({
|
|
@@ -56813,9 +57111,9 @@ object({
|
|
|
56813
57111
|
]),
|
|
56814
57112
|
/** 0 = fully closed, 100 = fully open. Null when the device has
|
|
56815
57113
|
* no intermediate position surface. */
|
|
56816
|
-
position: number().min(0).max(100).nullable(),
|
|
57114
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
56817
57115
|
/** 0 = closed slats, 100 = open slats. Null when no tilt support. */
|
|
56818
|
-
tiltPosition: number().min(0).max(100).nullable(),
|
|
57116
|
+
tiltPosition: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
56819
57117
|
/** Ms epoch when the slice was last updated. */
|
|
56820
57118
|
lastChangedAt: number()
|
|
56821
57119
|
});
|
|
@@ -56873,9 +57171,9 @@ var NormalizedRangeSchema$1 = object({
|
|
|
56873
57171
|
object({
|
|
56874
57172
|
mode: DayNightModeSchema,
|
|
56875
57173
|
/** IR-cut trigger sensitivity, NORMALIZED 0–100 (higher = switches to night sooner). */
|
|
56876
|
-
sensitivity: number().optional(),
|
|
57174
|
+
sensitivity: number().optional().meta(readingMeta("none")),
|
|
56877
57175
|
/** Delay before the IR-cut filter flips, in seconds. */
|
|
56878
|
-
switchDelaySec: number().optional(),
|
|
57176
|
+
switchDelaySec: number().optional().meta(readingMeta("duration")),
|
|
56879
57177
|
lastFetchedAt: number()
|
|
56880
57178
|
});
|
|
56881
57179
|
/**
|
|
@@ -57030,11 +57328,11 @@ object({
|
|
|
57030
57328
|
/** Feature keys of the programs the appliance currently offers — drives the UI selector. */
|
|
57031
57329
|
availablePrograms: array(string()),
|
|
57032
57330
|
/** Seconds remaining on the active cycle, or null when not running / not known. */
|
|
57033
|
-
remainingSeconds: number().int().nonnegative().nullable(),
|
|
57331
|
+
remainingSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
57034
57332
|
/** Seconds the delayed start is set to (time until the cycle starts), or null. */
|
|
57035
|
-
delayedStartSeconds: number().int().nonnegative().nullable(),
|
|
57333
|
+
delayedStartSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
57036
57334
|
/** Cycle completion 0..100, or null when not applicable. */
|
|
57037
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
57335
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
57038
57336
|
/** True when the door is reported open; null when the door state is not known. */
|
|
57039
57337
|
doorOpen: boolean().nullable(),
|
|
57040
57338
|
/** True when the door is latched (locked) during a cycle; null when not reported. */
|
|
@@ -57058,7 +57356,7 @@ object({
|
|
|
57058
57356
|
/** True while the machine-care (descaling / cleaning-program) reminder is raised; false when clear; null when not reported. */
|
|
57059
57357
|
machineCareDue: boolean().nullable(),
|
|
57060
57358
|
/** Program runs left before the machine-care reminder is due; null when the appliance does not say. */
|
|
57061
|
-
machineCareRemainingRuns: number().int().nonnegative().nullable(),
|
|
57359
|
+
machineCareRemainingRuns: number().int().nonnegative().nullable().meta(readingMeta("count")),
|
|
57062
57360
|
/** Option states: null when the appliance does not expose the option or has not said. */
|
|
57063
57361
|
halfLoad: boolean().nullable(),
|
|
57064
57362
|
hygienePlus: boolean().nullable(),
|
|
@@ -57073,7 +57371,7 @@ object({
|
|
|
57073
57371
|
/** Feature keys of the events currently raised (salt low, rinse aid low, program finished, …). */
|
|
57074
57372
|
activeEvents: array(string()),
|
|
57075
57373
|
/** Numeric error code when the appliance reports one; null otherwise. */
|
|
57076
|
-
errorCode: number().nullable(),
|
|
57374
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
57077
57375
|
/** Name of the raised alert-level event while the appliance is in error; null otherwise. */
|
|
57078
57376
|
errorLabel: string().nullable(),
|
|
57079
57377
|
/** Ms epoch of the last value received from the appliance; 0 = never. */
|
|
@@ -57219,24 +57517,14 @@ object({
|
|
|
57219
57517
|
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
57220
57518
|
lastPressedAt: number().nullable(),
|
|
57221
57519
|
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
57222
|
-
pressCountSinceStart: number()
|
|
57520
|
+
pressCountSinceStart: number().meta(readingMeta("count"))
|
|
57223
57521
|
});
|
|
57224
57522
|
object({
|
|
57225
57523
|
deviceId: number(),
|
|
57226
57524
|
timestamp: number()
|
|
57227
57525
|
});
|
|
57228
57526
|
DeviceType.Button, DeviceType.Camera;
|
|
57229
|
-
|
|
57230
|
-
* Enum-state sensor — a string value picked from a finite option set.
|
|
57231
|
-
* Drives HA `sensor` entries with `state_class: enum` (HVAC action
|
|
57232
|
-
* states, weather conditions, contact-source channels, mode strings).
|
|
57233
|
-
* The option set is stable across observations; it is persisted in the
|
|
57234
|
-
* device config blob (via the control slice at adoption) and is NOT
|
|
57235
|
-
* stored in `sourceInfo`.
|
|
57236
|
-
*/
|
|
57237
|
-
/** Locale-render shape for an ISO `value` carried by a `DateTimeSensor`-role
|
|
57238
|
-
* enum sensor: `date` (date-only), `time` (time-only), `datetime` (both). */
|
|
57239
|
-
var EnumSensorDateTimeFormatSchema = _enum([
|
|
57527
|
+
_enum([
|
|
57240
57528
|
"date",
|
|
57241
57529
|
"time",
|
|
57242
57530
|
"datetime"
|
|
@@ -57244,12 +57532,11 @@ var EnumSensorDateTimeFormatSchema = _enum([
|
|
|
57244
57532
|
object({
|
|
57245
57533
|
value: string(),
|
|
57246
57534
|
/**
|
|
57247
|
-
* Set
|
|
57248
|
-
* as
|
|
57249
|
-
*
|
|
57250
|
-
* a time-only sensor → `'time'`.
|
|
57535
|
+
* Set when `value` is a timestamp rather than an enum state, so history
|
|
57536
|
+
* does not learn ISO strings as states. The display shape (date / time /
|
|
57537
|
+
* datetime) lives on `SourceInfo.dateTimeShape`, written once at adopt.
|
|
57251
57538
|
*/
|
|
57252
|
-
|
|
57539
|
+
timestamp: boolean().optional(),
|
|
57253
57540
|
/** Ms epoch when the slice was last updated. */
|
|
57254
57541
|
lastFetchedAt: number()
|
|
57255
57542
|
});
|
|
@@ -57268,13 +57555,13 @@ var EventFireSchema = object({
|
|
|
57268
57555
|
deviceId: number(),
|
|
57269
57556
|
eventType: string(),
|
|
57270
57557
|
data: record(string(), unknown()).nullable(),
|
|
57271
|
-
timestamp: number(),
|
|
57272
|
-
seq: number()
|
|
57558
|
+
timestamp: number().meta(readingMeta("none")),
|
|
57559
|
+
seq: number().meta(readingMeta("count"))
|
|
57273
57560
|
});
|
|
57274
57561
|
object({
|
|
57275
57562
|
eventTypes: array(string()),
|
|
57276
57563
|
lastEvent: EventFireSchema.nullable(),
|
|
57277
|
-
eventCountSinceStart: number()
|
|
57564
|
+
eventCountSinceStart: number().meta(readingMeta("count"))
|
|
57278
57565
|
});
|
|
57279
57566
|
DeviceType.EventEmitter;
|
|
57280
57567
|
var IdentitySchema = object({
|
|
@@ -57663,10 +57950,10 @@ var FanDirectionSchema = _enum(["forward", "reverse"]);
|
|
|
57663
57950
|
object({
|
|
57664
57951
|
/** Active speed as 0..100 inclusive. Null when the device has no
|
|
57665
57952
|
* speed surface (single-speed fan). */
|
|
57666
|
-
percentage: number().min(0).max(100).nullable(),
|
|
57953
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
57667
57954
|
/** Speed granularity the device accepts (HA `percentage_step`, e.g. 25 for
|
|
57668
57955
|
* a 4-speed fan). Absent when unknown — the UI then falls back to step 1. */
|
|
57669
|
-
percentageStep: number().positive().optional(),
|
|
57956
|
+
percentageStep: number().positive().optional().meta(readingMeta("percentage")),
|
|
57670
57957
|
/** Active preset mode (`auto` / `quiet` / `turbo` / vendor-specific)
|
|
57671
57958
|
* — empty string when no preset is active or supported. */
|
|
57672
57959
|
preset: string(),
|
|
@@ -57748,7 +58035,7 @@ var FeatureProbeStatusSchema = object({
|
|
|
57748
58035
|
/** Camera/firmware model string. `null` when the firmware doesn't expose it. */
|
|
57749
58036
|
model: string().nullable(),
|
|
57750
58037
|
/** Channel count for NVR/Hub devices; `1` for standalone cameras; `null` pre-probe. */
|
|
57751
|
-
channelCount: number().nullable(),
|
|
58038
|
+
channelCount: number().nullable().meta(readingMeta("count")),
|
|
57752
58039
|
/**
|
|
57753
58040
|
* Ms epoch of the last SUCCESSFUL probe. `0` before the first probe
|
|
57754
58041
|
* completes — drivers' `getAccessoryChildren()` should treat zero as
|
|
@@ -57780,9 +58067,27 @@ object({
|
|
|
57780
58067
|
lastChangedAt: number()
|
|
57781
58068
|
});
|
|
57782
58069
|
DeviceType.Sensor;
|
|
58070
|
+
object({
|
|
58071
|
+
/** Members whose current value entered the aggregate. */
|
|
58072
|
+
included: number().int().nonnegative().meta(readingMeta("count", {
|
|
58073
|
+
precision: 0,
|
|
58074
|
+
label: "Reporting"
|
|
58075
|
+
})),
|
|
58076
|
+
/** Members left out: offline, unknown, or not a finite reading (D393). */
|
|
58077
|
+
excluded: number().int().nonnegative().meta(readingMeta("count", {
|
|
58078
|
+
precision: 0,
|
|
58079
|
+
label: "Excluded"
|
|
58080
|
+
})),
|
|
58081
|
+
/** `included` + `excluded`. */
|
|
58082
|
+
total: number().int().nonnegative().meta(readingMeta("count", {
|
|
58083
|
+
precision: 0,
|
|
58084
|
+
label: "Members"
|
|
58085
|
+
}))
|
|
58086
|
+
});
|
|
58087
|
+
DeviceType.Sensor;
|
|
57783
58088
|
object({
|
|
57784
58089
|
/** Radiator valve opening 0 (closed) .. 100 (open). Null = not yet known. */
|
|
57785
|
-
position: number().min(0).max(100).nullable(),
|
|
58090
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
57786
58091
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
57787
58092
|
lastFetchedAt: number()
|
|
57788
58093
|
});
|
|
@@ -57791,9 +58096,9 @@ object({
|
|
|
57791
58096
|
/** Whether the humidifier is currently on. */
|
|
57792
58097
|
on: boolean(),
|
|
57793
58098
|
/** Current measured relative humidity (0..100). Null when not reported. */
|
|
57794
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
58099
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
57795
58100
|
/** Target relative humidity (0..100). Null when no setpoint surface. */
|
|
57796
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
58101
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
57797
58102
|
/** Active mode (`auto` / `normal` / `baby` / vendor). Null when the
|
|
57798
58103
|
* device has no mode surface. */
|
|
57799
58104
|
mode: string().nullable(),
|
|
@@ -57803,9 +58108,9 @@ object({
|
|
|
57803
58108
|
* `idle` / `off`). Null when the device doesn't report it. */
|
|
57804
58109
|
action: string().nullable(),
|
|
57805
58110
|
/** HA `min_humidity` attribute. Null → UI uses 0. */
|
|
57806
|
-
minHumidity: number().nullable(),
|
|
58111
|
+
minHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
57807
58112
|
/** HA `max_humidity` attribute. Null → UI uses 100. */
|
|
57808
|
-
maxHumidity: number().nullable(),
|
|
58113
|
+
maxHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
57809
58114
|
/** Ms epoch when the slice was last updated. */
|
|
57810
58115
|
lastChangedAt: number()
|
|
57811
58116
|
});
|
|
@@ -57829,22 +58134,13 @@ DeviceType.Humidifier, method(object({
|
|
|
57829
58134
|
auth: "protected"
|
|
57830
58135
|
});
|
|
57831
58136
|
object({
|
|
57832
|
-
/** Current relative humidity, 0..100. */
|
|
57833
|
-
percent: number().min(0).max(100).meta({
|
|
57834
|
-
|
|
58137
|
+
/** Current relative humidity, 0..100. `null` when the sample was refused (D393). */
|
|
58138
|
+
percent: number().min(0).max(100).nullable().meta(readingMeta("humidity", {
|
|
58139
|
+
precision: 0,
|
|
57835
58140
|
label: "Humidity"
|
|
57836
|
-
}),
|
|
58141
|
+
})),
|
|
57837
58142
|
/** Ms epoch when the slice was last updated. */
|
|
57838
|
-
lastFetchedAt: number()
|
|
57839
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
57840
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
57841
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
57842
|
-
unit: string().optional(),
|
|
57843
|
-
/** Suggested decimal places for numeric display.
|
|
57844
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
57845
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
57846
|
-
* auto-formatting when absent. */
|
|
57847
|
-
precision: number().int().min(0).max(10).optional()
|
|
58143
|
+
lastFetchedAt: number()
|
|
57848
58144
|
});
|
|
57849
58145
|
DeviceType.Sensor, DeviceType.Thermostat;
|
|
57850
58146
|
object({
|
|
@@ -57852,7 +58148,7 @@ object({
|
|
|
57852
58148
|
* entity exposes no `entity_picture` (yet). */
|
|
57853
58149
|
url: string().nullable(),
|
|
57854
58150
|
/** Ms epoch of the upstream last-updated timestamp. Null at cold-start. */
|
|
57855
|
-
lastUpdated: number().nullable()
|
|
58151
|
+
lastUpdated: number().nullable().meta(readingMeta("none"))
|
|
57856
58152
|
});
|
|
57857
58153
|
DeviceType.Image;
|
|
57858
58154
|
/**
|
|
@@ -57908,19 +58204,19 @@ var NormalizedRangeSchema = object({
|
|
|
57908
58204
|
});
|
|
57909
58205
|
object({
|
|
57910
58206
|
/** Normalized 0–100. */
|
|
57911
|
-
brightness: number().optional(),
|
|
58207
|
+
brightness: number().optional().meta(readingMeta("none")),
|
|
57912
58208
|
/** Normalized 0–100. */
|
|
57913
|
-
contrast: number().optional(),
|
|
58209
|
+
contrast: number().optional().meta(readingMeta("none")),
|
|
57914
58210
|
/** Normalized 0–100. */
|
|
57915
|
-
saturation: number().optional(),
|
|
58211
|
+
saturation: number().optional().meta(readingMeta("none")),
|
|
57916
58212
|
/** Normalized 0–100. */
|
|
57917
|
-
sharpness: number().optional(),
|
|
58213
|
+
sharpness: number().optional().meta(readingMeta("none")),
|
|
57918
58214
|
mirror: boolean().optional(),
|
|
57919
58215
|
flip: boolean().optional(),
|
|
57920
58216
|
rotate: ImageRotateSchema.optional(),
|
|
57921
58217
|
whiteBalance: WhiteBalanceModeSchema.optional(),
|
|
57922
58218
|
/** Manual white-balance warmth, NORMALIZED 0–100. Meaningful only when `whiteBalance === 'manual'`. */
|
|
57923
|
-
warmth: number().optional(),
|
|
58219
|
+
warmth: number().optional().meta(readingMeta("none")),
|
|
57924
58220
|
exposureMode: ExposureModeSchema.optional(),
|
|
57925
58221
|
backlightMode: BacklightModeSchema.optional(),
|
|
57926
58222
|
lastFetchedAt: number()
|
|
@@ -58165,10 +58461,10 @@ var IntercomAbilitySchema = object({
|
|
|
58165
58461
|
/** Codecs accepted by firmware, in preference order. Driver-authored strings. */
|
|
58166
58462
|
codecs: array(string()),
|
|
58167
58463
|
/** Sample rate (Hz) the firmware expects. Reolink typical: 16000. */
|
|
58168
|
-
sampleRate: number(),
|
|
58464
|
+
sampleRate: number().meta(readingMeta("none")),
|
|
58169
58465
|
duplex: _enum(["half", "full"]),
|
|
58170
58466
|
/** Max in-flight audio backlog before drop (ms). Server uses this to bound latency. */
|
|
58171
|
-
maxBacklogMs: number()
|
|
58467
|
+
maxBacklogMs: number().meta(readingMeta("duration-ms"))
|
|
58172
58468
|
});
|
|
58173
58469
|
var IntercomStatusSchema = object({
|
|
58174
58470
|
/** True while a talk session is open. */
|
|
@@ -58279,13 +58575,13 @@ object({
|
|
|
58279
58575
|
activity: LawnMowerActivitySchema,
|
|
58280
58576
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
58281
58577
|
* reading. */
|
|
58282
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
58578
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58283
58579
|
/** 0..100 mowing-completion percentage of the current task, or null when no
|
|
58284
58580
|
* task is active / progress is unavailable. */
|
|
58285
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
58581
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58286
58582
|
/** Current device/event code (dynamic — mostly status, sometimes an error),
|
|
58287
58583
|
* or null when unknown. */
|
|
58288
|
-
currentCode: number().nullable(),
|
|
58584
|
+
currentCode: number().nullable().meta(readingMeta("none")),
|
|
58289
58585
|
/** Human label for {@link currentCode}, or null when undecodable. */
|
|
58290
58586
|
currentCodeLabel: string().nullable(),
|
|
58291
58587
|
/** Severity of {@link currentCode}. `error` (and often `warning`) warrants UI
|
|
@@ -58747,7 +59043,7 @@ object({
|
|
|
58747
59043
|
state: MediaPlayerStateSchema,
|
|
58748
59044
|
/** Volume as 0..100 inclusive. Null when the device has no volume
|
|
58749
59045
|
* surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
|
|
58750
|
-
volumeLevel: number().min(0).max(100).nullable(),
|
|
59046
|
+
volumeLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58751
59047
|
/** Mute toggle distinct from volume=0. Null when no mute surface.
|
|
58752
59048
|
* Pair with `DeviceFeature.MediaPlayerMute`. */
|
|
58753
59049
|
isMuted: boolean().nullable(),
|
|
@@ -58760,10 +59056,10 @@ object({
|
|
|
58760
59056
|
currentMedia: MediaInfoSchema.nullable(),
|
|
58761
59057
|
/** Current playback position in ms. Null when not seekable or
|
|
58762
59058
|
* nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
|
|
58763
|
-
positionMs: number().int().nonnegative().nullable(),
|
|
59059
|
+
positionMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
58764
59060
|
/** Total duration of the current media in ms. Null when unknown
|
|
58765
59061
|
* (live stream) or nothing is playing. */
|
|
58766
|
-
durationMs: number().int().nonnegative().nullable(),
|
|
59062
|
+
durationMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
58767
59063
|
/** Shuffle toggle. Null when no shuffle surface.
|
|
58768
59064
|
* Pair with `DeviceFeature.MediaPlayerShuffle`. */
|
|
58769
59065
|
shuffle: boolean().nullable(),
|
|
@@ -59063,7 +59359,7 @@ object({
|
|
|
59063
59359
|
* it, every provider seeded it at boot, and every session left it
|
|
59064
59360
|
* `detected: true` after its detach.
|
|
59065
59361
|
*/
|
|
59066
|
-
autoClearAfterMs: number().nullable()
|
|
59362
|
+
autoClearAfterMs: number().nullable().meta(readingMeta("duration-ms"))
|
|
59067
59363
|
});
|
|
59068
59364
|
/**
|
|
59069
59365
|
* Payload of `motion.onMotionChanged` event + the corresponding bus
|
|
@@ -59113,7 +59409,7 @@ var MotionZoneRegionSchema = object({
|
|
|
59113
59409
|
});
|
|
59114
59410
|
object({
|
|
59115
59411
|
enabled: boolean(),
|
|
59116
|
-
sensitivity: number(),
|
|
59412
|
+
sensitivity: number().meta(readingMeta("none")),
|
|
59117
59413
|
/** Grid region(s). Today exactly one `grid` shape. */
|
|
59118
59414
|
regions: array(MotionZoneRegionSchema),
|
|
59119
59415
|
lastFetchedAt: number()
|
|
@@ -59417,7 +59713,7 @@ var NavigationStatusSchema = object({
|
|
|
59417
59713
|
following: boolean(),
|
|
59418
59714
|
flash: boolean(),
|
|
59419
59715
|
lightMode: NavigationLightModeSchema,
|
|
59420
|
-
lightLevel: number().min(40).max(100),
|
|
59716
|
+
lightLevel: number().min(40).max(100).meta(readingMeta("none")),
|
|
59421
59717
|
/** Ms epoch when the slice was last updated. */
|
|
59422
59718
|
lastChangedAt: number()
|
|
59423
59719
|
});
|
|
@@ -59463,13 +59759,13 @@ var NetworkLinkStatusSchema = object({
|
|
|
59463
59759
|
* one whose reading has not landed must not be drawn at 0 %. Consumers
|
|
59464
59760
|
* SKIP a null rather than coerce it.
|
|
59465
59761
|
*/
|
|
59466
|
-
signalPercent: number().min(0).max(100).nullable(),
|
|
59762
|
+
signalPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59467
59763
|
/** Raw received signal strength in dBm, when the firmware reports one. */
|
|
59468
|
-
rssiDbm: number().optional(),
|
|
59764
|
+
rssiDbm: number().optional().meta(readingMeta("signal-level")),
|
|
59469
59765
|
/** Network name of a wireless link, when the firmware reports it. */
|
|
59470
59766
|
ssid: string().optional(),
|
|
59471
59767
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
59472
|
-
lastUpdated: number()
|
|
59768
|
+
lastUpdated: number().meta(readingMeta("none"))
|
|
59473
59769
|
});
|
|
59474
59770
|
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.Light, DeviceType.Lock, DeviceType.Siren, object({
|
|
59475
59771
|
deviceId: number(),
|
|
@@ -59788,7 +60084,7 @@ object({
|
|
|
59788
60084
|
lastError: string().nullable(),
|
|
59789
60085
|
/** Number of deliveries currently buffered server-side (rate-limited
|
|
59790
60086
|
* notifiers may queue). 0 when the provider sends synchronously. */
|
|
59791
|
-
queueDepth: number().int().nonnegative(),
|
|
60087
|
+
queueDepth: number().int().nonnegative().meta(readingMeta("count")),
|
|
59792
60088
|
/** Per-feature capability matrix — authoritative source for the
|
|
59793
60089
|
* compose-form field gating. */
|
|
59794
60090
|
supports: NotifierSupportsSchema
|
|
@@ -59838,15 +60134,8 @@ DeviceType.Notifier, method(NotifierSendInputSchema, NotifierSendResultSchema, {
|
|
|
59838
60134
|
acceptedAt: number()
|
|
59839
60135
|
});
|
|
59840
60136
|
object({
|
|
59841
|
-
|
|
59842
|
-
|
|
59843
|
-
* Populated live from the upstream source on each state push.
|
|
59844
|
-
* Absent for unitless sensors. */
|
|
59845
|
-
unit: string().optional(),
|
|
59846
|
-
/** Suggested decimal places for numeric display.
|
|
59847
|
-
* Populated live from the upstream source when provided.
|
|
59848
|
-
* Falls back to auto-formatting when absent. */
|
|
59849
|
-
precision: number().int().min(0).max(10).optional(),
|
|
60137
|
+
/** Reading in the device quantity's base unit. `null` when refused (D393). */
|
|
60138
|
+
value: number().nullable().meta(readingMeta("device")),
|
|
59850
60139
|
/** Ms epoch when the slice was last updated. */
|
|
59851
60140
|
lastFetchedAt: number()
|
|
59852
60141
|
});
|
|
@@ -60136,23 +60425,26 @@ object({
|
|
|
60136
60425
|
/** Food currently in the bowl (grams). Null when the device has not
|
|
60137
60426
|
* reported a reading yet. On dual-hopper models this is the combined
|
|
60138
60427
|
* bowl reading; per-hopper levels live in `food1`/`food2`. */
|
|
60139
|
-
foodLevel: number().nullable(),
|
|
60428
|
+
foodLevel: number().nullable().meta(readingMeta("none")),
|
|
60140
60429
|
/** Hopper-1 food level (grams) on dual-hopper feeders; null on
|
|
60141
60430
|
* single-hopper models. */
|
|
60142
|
-
food1: number().nullable(),
|
|
60431
|
+
food1: number().nullable().meta(readingMeta("none")),
|
|
60143
60432
|
/** Hopper-2 food level (grams) on dual-hopper feeders; null on
|
|
60144
60433
|
* single-hopper models. */
|
|
60145
|
-
food2: number().nullable(),
|
|
60434
|
+
food2: number().nullable().meta(readingMeta("none")),
|
|
60146
60435
|
/** Derived low-food flag — mirrors the HA `food_level` binary_sensor
|
|
60147
60436
|
* (`device_class: problem`, on = low). True when the bowl is empty /
|
|
60148
60437
|
* below the feeder's low threshold. */
|
|
60149
60438
|
lowFood: boolean(),
|
|
60150
60439
|
/** Battery charge 0..100 (%). Null on mains-powered models or when the
|
|
60151
60440
|
* device has no battery reading. */
|
|
60152
|
-
batteryPower: number().min(0).max(100).nullable(),
|
|
60153
|
-
/**
|
|
60154
|
-
*
|
|
60155
|
-
|
|
60441
|
+
batteryPower: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
60442
|
+
/**
|
|
60443
|
+
* Desiccant life remaining, stored in seconds (duration base, D944).
|
|
60444
|
+
* Providers convert from the days the feeder reports. Null when the
|
|
60445
|
+
* model has no desiccant sensor.
|
|
60446
|
+
*/
|
|
60447
|
+
desiccantLeftDays: number().nullable().meta(readingMeta("duration")),
|
|
60156
60448
|
/** True while a feed is in progress. */
|
|
60157
60449
|
feeding: boolean(),
|
|
60158
60450
|
/** Decoded connectivity / power status (HA petkit device-status enum).
|
|
@@ -60163,7 +60455,7 @@ object({
|
|
|
60163
60455
|
* with `errorCode` for consumers that want the raw integer. */
|
|
60164
60456
|
error: string().nullable(),
|
|
60165
60457
|
/** Raw device error code (0 / null = no error). */
|
|
60166
|
-
errorCode: number().nullable(),
|
|
60458
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
60167
60459
|
/** True for D4S/D4SH dual-hopper hardware — gates the per-hopper UI. */
|
|
60168
60460
|
isDualHopper: boolean(),
|
|
60169
60461
|
/** Child-lock (manual-lock) setting — buttons on the unit are disabled. */
|
|
@@ -60173,7 +60465,7 @@ object({
|
|
|
60173
60465
|
/** Play a chime when dispensing. */
|
|
60174
60466
|
feedSound: boolean(),
|
|
60175
60467
|
/** Speaker / prompt volume level (device-scaled integer). */
|
|
60176
|
-
volume: number(),
|
|
60468
|
+
volume: number().meta(readingMeta("none")),
|
|
60177
60469
|
/** Ms epoch when the slice was last refreshed from the cloud. */
|
|
60178
60470
|
lastFetchedAt: number()
|
|
60179
60471
|
});
|
|
@@ -60610,36 +60902,19 @@ method(_void(), PlatformCapabilitiesSchema), method(_void(), HardwareInfoSchema)
|
|
|
60610
60902
|
});
|
|
60611
60903
|
object({
|
|
60612
60904
|
/** Instantaneous power draw in watts. */
|
|
60613
|
-
watts: number().optional().meta({
|
|
60614
|
-
unit: "W",
|
|
60615
|
-
label: "Power"
|
|
60616
|
-
}),
|
|
60905
|
+
watts: number().optional().meta(readingMeta("power", { label: "Power" })),
|
|
60617
60906
|
/** Cumulative energy in kilowatt-hours since the meter was reset. */
|
|
60618
|
-
kwhTotal: number().optional().meta({
|
|
60619
|
-
unit: "kWh",
|
|
60620
|
-
label: "Energy"
|
|
60621
|
-
}),
|
|
60907
|
+
kwhTotal: number().optional().meta(readingMeta("energy", { label: "Energy" })),
|
|
60622
60908
|
/** Voltage in volts. */
|
|
60623
|
-
volts: number().optional(),
|
|
60909
|
+
volts: number().optional().meta(readingMeta("voltage")),
|
|
60624
60910
|
/** Current in amperes. */
|
|
60625
|
-
amps: number().optional(),
|
|
60626
|
-
/** Apparent power in volt-amperes
|
|
60627
|
-
va: number().optional(),
|
|
60911
|
+
amps: number().optional().meta(readingMeta("current")),
|
|
60912
|
+
/** Apparent power in volt-amperes. */
|
|
60913
|
+
va: number().optional().meta(readingMeta("apparent-power")),
|
|
60628
60914
|
/** Power factor (0..1) if reported. */
|
|
60629
|
-
powerFactor: number().min(0).max(1).optional(),
|
|
60915
|
+
powerFactor: number().min(0).max(1).optional().meta(readingMeta("ratio")),
|
|
60630
60916
|
/** Ms epoch when the slice was last updated. */
|
|
60631
|
-
lastFetchedAt: number()
|
|
60632
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
60633
|
-
* `attributes.unit_of_measurement` → 'V' / 'A' / 'W' / 'kW' / 'kWh').
|
|
60634
|
-
* Each upstream `sensor.*` entity surfaces ONE device_class, so one
|
|
60635
|
-
* unit per slice is unambiguous. The UI prefers this over the role's
|
|
60636
|
-
* canonical unit so a 'kW' / 'Wh' feed renders verbatim. */
|
|
60637
|
-
unit: string().optional(),
|
|
60638
|
-
/** Suggested decimal places for numeric display.
|
|
60639
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
60640
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
60641
|
-
* auto-formatting when absent. */
|
|
60642
|
-
precision: number().int().min(0).max(10).optional()
|
|
60917
|
+
lastFetchedAt: number()
|
|
60643
60918
|
});
|
|
60644
60919
|
DeviceType.Sensor;
|
|
60645
60920
|
/**
|
|
@@ -60660,11 +60935,11 @@ DeviceType.Sensor;
|
|
|
60660
60935
|
*/
|
|
60661
60936
|
var GpsLocationSchema = object({
|
|
60662
60937
|
/** Latitude in decimal degrees, -90..90. */
|
|
60663
|
-
latitude: number().min(-90).max(90),
|
|
60938
|
+
latitude: number().min(-90).max(90).meta(readingMeta("angle")),
|
|
60664
60939
|
/** Longitude in decimal degrees, -180..180. */
|
|
60665
|
-
longitude: number().min(-180).max(180),
|
|
60940
|
+
longitude: number().min(-180).max(180).meta(readingMeta("angle")),
|
|
60666
60941
|
/** Reported accuracy in meters (lower = better). */
|
|
60667
|
-
accuracyMeters: number().nonnegative()
|
|
60942
|
+
accuracyMeters: number().nonnegative().meta(readingMeta("length"))
|
|
60668
60943
|
});
|
|
60669
60944
|
object({
|
|
60670
60945
|
/** `home` / `not_home` / any user-defined zone name. */
|
|
@@ -60676,25 +60951,16 @@ object({
|
|
|
60676
60951
|
gps: GpsLocationSchema.nullable(),
|
|
60677
60952
|
/** Optional battery level of the tracking device (0..100). Null
|
|
60678
60953
|
* when not reported. */
|
|
60679
|
-
batteryPercent: number().min(0).max(100).nullable(),
|
|
60954
|
+
batteryPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
60680
60955
|
/** Ms epoch when the slice was last updated. */
|
|
60681
60956
|
lastChangedAt: number()
|
|
60682
60957
|
});
|
|
60683
60958
|
DeviceType.Presence;
|
|
60684
60959
|
object({
|
|
60685
|
-
/** Current pressure in hPa. */
|
|
60686
|
-
hpa: number(),
|
|
60960
|
+
/** Current pressure in hPa. `null` when the sample was refused (D393). */
|
|
60961
|
+
hpa: number().nullable().meta(readingMeta("pressure", { precision: 0 })),
|
|
60687
60962
|
/** Ms epoch when the slice was last updated. */
|
|
60688
|
-
lastFetchedAt: number()
|
|
60689
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
60690
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
60691
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
60692
|
-
unit: string().optional(),
|
|
60693
|
-
/** Suggested decimal places for numeric display.
|
|
60694
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
60695
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
60696
|
-
* auto-formatting when absent. */
|
|
60697
|
-
precision: number().int().min(0).max(10).optional()
|
|
60963
|
+
lastFetchedAt: number()
|
|
60698
60964
|
});
|
|
60699
60965
|
DeviceType.Sensor;
|
|
60700
60966
|
/**
|
|
@@ -61027,8 +61293,8 @@ DeviceType.Camera, method(PtzMoveCommandSchema.extend({ deviceId: number() }), _
|
|
|
61027
61293
|
}), _void(), { kind: "mutation" });
|
|
61028
61294
|
var PtzAutotrackSettingsSchema = object({
|
|
61029
61295
|
targetType: string().describe("Vendor target string (people/vehicle/pet); empty = camera default"),
|
|
61030
|
-
stopDelaySeconds: number().int().min(0).max(300),
|
|
61031
|
-
disappearDelaySeconds: number().int().min(0).max(300)
|
|
61296
|
+
stopDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration")),
|
|
61297
|
+
disappearDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration"))
|
|
61032
61298
|
});
|
|
61033
61299
|
/**
|
|
61034
61300
|
* One option the camera advertises as a valid `targetType`. Drivers
|
|
@@ -61085,7 +61351,7 @@ object({
|
|
|
61085
61351
|
/** null = unknown — never coerced to false (D393). */
|
|
61086
61352
|
running: boolean().nullable(),
|
|
61087
61353
|
/** Epoch ms the current boolean began; null while `running` is null. */
|
|
61088
|
-
since: number().nullable(),
|
|
61354
|
+
since: number().nullable().meta(readingMeta("none")),
|
|
61089
61355
|
source: RunningStateSourceSchema.meta({ label: "Source" }),
|
|
61090
61356
|
phase: string().nullable(),
|
|
61091
61357
|
/** null until a reading has been published (D393). */
|
|
@@ -62283,9 +62549,9 @@ var RecordTriggerSchema = _enum([
|
|
|
62283
62549
|
*/
|
|
62284
62550
|
var RecordWindowSchema = object({
|
|
62285
62551
|
trigger: RecordTriggerSchema,
|
|
62286
|
-
day: number().int().min(0).max(6),
|
|
62287
|
-
startMinute: number().int().min(0).max(1439),
|
|
62288
|
-
endMinute: number().int().min(1).max(1440)
|
|
62552
|
+
day: number().int().min(0).max(6).meta(readingMeta("none")),
|
|
62553
|
+
startMinute: number().int().min(0).max(1439).meta(readingMeta("none")),
|
|
62554
|
+
endMinute: number().int().min(1).max(1440).meta(readingMeta("none"))
|
|
62289
62555
|
});
|
|
62290
62556
|
/** Status of one physical volume, as the camera itself describes it. */
|
|
62291
62557
|
var OnboardStorageVolumeSchema = object({
|
|
@@ -62354,10 +62620,10 @@ object({
|
|
|
62354
62620
|
/** Master "record to the card at all" switch. */
|
|
62355
62621
|
enabled: boolean().nullable(),
|
|
62356
62622
|
overwriteWhenFull: boolean().nullable(),
|
|
62357
|
-
preRecordSec: number().nullable(),
|
|
62358
|
-
postRecordSec: number().nullable(),
|
|
62623
|
+
preRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
62624
|
+
postRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
62359
62625
|
/** Length of one recorded file, in minutes. */
|
|
62360
|
-
segmentMinutes: number().nullable(),
|
|
62626
|
+
segmentMinutes: number().nullable().meta(readingMeta("none")),
|
|
62361
62627
|
/** The primary track's weekly windows, flattened. */
|
|
62362
62628
|
windows: array(RecordWindowSchema),
|
|
62363
62629
|
/**
|
|
@@ -62373,7 +62639,7 @@ object({
|
|
|
62373
62639
|
* provider reporting a non-zero count also reports the schedule as not
|
|
62374
62640
|
* writable.
|
|
62375
62641
|
*/
|
|
62376
|
-
unreadableWindows: number(),
|
|
62642
|
+
unreadableWindows: number().meta(readingMeta("count")),
|
|
62377
62643
|
/**
|
|
62378
62644
|
* The camera is scheduled to record and has NO usable storage.
|
|
62379
62645
|
*
|
|
@@ -63010,7 +63276,7 @@ var CamStreamDescriptorSchema = object({
|
|
|
63010
63276
|
url: string().optional(),
|
|
63011
63277
|
codec: string().optional(),
|
|
63012
63278
|
resolution: CamStreamResolutionSchema.optional(),
|
|
63013
|
-
fps: number().positive().optional(),
|
|
63279
|
+
fps: number().positive().optional().meta(readingMeta("rate")),
|
|
63014
63280
|
label: string().optional(),
|
|
63015
63281
|
/** Device-level features (e.g. `battery-operated`) — drives broker policy. */
|
|
63016
63282
|
deviceFeatures: array(string()).optional(),
|
|
@@ -63040,18 +63306,18 @@ var StreamProfileSchema = _enum([
|
|
|
63040
63306
|
]);
|
|
63041
63307
|
/** The current encoding config of one stream profile. */
|
|
63042
63308
|
var StreamProfileConfigSchema = object({
|
|
63043
|
-
width: number(),
|
|
63044
|
-
height: number(),
|
|
63309
|
+
width: number().meta(readingMeta("none")),
|
|
63310
|
+
height: number().meta(readingMeta("none")),
|
|
63045
63311
|
codec: _enum(["h264", "h265"]),
|
|
63046
|
-
framerate: number(),
|
|
63047
|
-
bitrate: number(),
|
|
63312
|
+
framerate: number().meta(readingMeta("rate")),
|
|
63313
|
+
bitrate: number().meta(readingMeta("bitrate")),
|
|
63048
63314
|
bitrateMode: _enum(["vbr", "cbr"]).optional(),
|
|
63049
63315
|
encoderProfile: _enum([
|
|
63050
63316
|
"high",
|
|
63051
63317
|
"main",
|
|
63052
63318
|
"baseline"
|
|
63053
63319
|
]).optional(),
|
|
63054
|
-
gop: number().optional(),
|
|
63320
|
+
gop: number().optional().meta(readingMeta("none")),
|
|
63055
63321
|
/**
|
|
63056
63322
|
* Whether THIS profile currently carries an audio track. READ-ONLY here.
|
|
63057
63323
|
*
|
|
@@ -63694,23 +63960,13 @@ object({
|
|
|
63694
63960
|
});
|
|
63695
63961
|
DeviceType.Sensor;
|
|
63696
63962
|
object({
|
|
63697
|
-
/** Current temperature in Celsius. */
|
|
63698
|
-
celsius: number().meta({
|
|
63699
|
-
|
|
63963
|
+
/** Current temperature in Celsius. `null` when the sample was refused (D393). */
|
|
63964
|
+
celsius: number().nullable().meta(readingMeta("temperature", {
|
|
63965
|
+
precision: 1,
|
|
63700
63966
|
label: "Temperature"
|
|
63701
|
-
}),
|
|
63967
|
+
})),
|
|
63702
63968
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
63703
|
-
lastFetchedAt: number()
|
|
63704
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
63705
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
63706
|
-
* role's canonical unit, so a Fahrenheit feed renders '°F' not '°C'.
|
|
63707
|
-
* Absent → the UI falls back to the role's canonical unit. */
|
|
63708
|
-
unit: string().optional(),
|
|
63709
|
-
/** Suggested decimal places for numeric display.
|
|
63710
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
63711
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
63712
|
-
* auto-formatting when absent. */
|
|
63713
|
-
precision: number().int().min(0).max(10).optional()
|
|
63969
|
+
lastFetchedAt: number()
|
|
63714
63970
|
});
|
|
63715
63971
|
DeviceType.Sensor, DeviceType.Thermostat;
|
|
63716
63972
|
/**
|
|
@@ -63962,16 +64218,16 @@ object({
|
|
|
63962
64218
|
]),
|
|
63963
64219
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
63964
64220
|
* reading. */
|
|
63965
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
64221
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
63966
64222
|
/** Current fan-speed token (provider-verbatim). Null when unknown or
|
|
63967
64223
|
* the vacuum has no speed control. */
|
|
63968
64224
|
fanSpeed: string().nullable(),
|
|
63969
64225
|
/** Speed tokens the hardware accepts — drives the UI selector. */
|
|
63970
64226
|
availableFanSpeeds: array(string()),
|
|
63971
64227
|
/** 0..100 cleaning-completion percentage of the current task, or null. */
|
|
63972
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
64228
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
63973
64229
|
/** Current error code (0 / null = no error). */
|
|
63974
|
-
errorCode: number().nullable(),
|
|
64230
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
63975
64231
|
/** Human label for {@link errorCode}, or null when none / undecodable. */
|
|
63976
64232
|
errorLabel: string().nullable(),
|
|
63977
64233
|
/** Ms epoch when the slice was last updated. */
|
|
@@ -64010,7 +64266,7 @@ object({
|
|
|
64010
64266
|
]),
|
|
64011
64267
|
/** 0 = fully closed, 100 = fully open. Null when the device has no
|
|
64012
64268
|
* intermediate position surface. */
|
|
64013
|
-
position: number().min(0).max(100).nullable(),
|
|
64269
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
64014
64270
|
/** Ms epoch when the slice was last updated. */
|
|
64015
64271
|
lastChangedAt: number()
|
|
64016
64272
|
});
|
|
@@ -64038,9 +64294,9 @@ object({
|
|
|
64038
64294
|
DeviceType.Sensor;
|
|
64039
64295
|
object({
|
|
64040
64296
|
/** Current measured temperature. Null when not reported. */
|
|
64041
|
-
currentTemp: number().nullable(),
|
|
64297
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
64042
64298
|
/** Target temperature setpoint. Null when no setpoint surface. */
|
|
64043
|
-
targetTemp: number().nullable(),
|
|
64299
|
+
targetTemp: number().nullable().meta(readingMeta("temperature")),
|
|
64044
64300
|
/** Active operation mode = HA `state` (`eco` / `electric` / `gas` /
|
|
64045
64301
|
* `heat_pump` / `high_demand` / `performance` / `off`). Null when the
|
|
64046
64302
|
* device reports an unknown state. */
|
|
@@ -64051,9 +64307,9 @@ object({
|
|
|
64051
64307
|
* has no away surface. */
|
|
64052
64308
|
away: boolean().nullable(),
|
|
64053
64309
|
/** HA `min_temp` attribute. Null when not reported. */
|
|
64054
|
-
minTemp: number().nullable(),
|
|
64310
|
+
minTemp: number().nullable().meta(readingMeta("temperature")),
|
|
64055
64311
|
/** HA `max_temp` attribute. Null when not reported. */
|
|
64056
|
-
maxTemp: number().nullable(),
|
|
64312
|
+
maxTemp: number().nullable().meta(readingMeta("temperature")),
|
|
64057
64313
|
/** Ms epoch when the slice was last updated. */
|
|
64058
64314
|
lastChangedAt: number()
|
|
64059
64315
|
});
|
|
@@ -64077,25 +64333,18 @@ DeviceType.WaterHeater, method(object({
|
|
|
64077
64333
|
auth: "protected"
|
|
64078
64334
|
});
|
|
64079
64335
|
object({
|
|
64080
|
-
/** Verbatim
|
|
64081
|
-
* when no condition has been reported yet. */
|
|
64336
|
+
/** Verbatim condition state (`sunny`, `cloudy`, `rainy`, …). Null when none yet. */
|
|
64082
64337
|
condition: string().nullable(),
|
|
64083
|
-
/** Current temperature in
|
|
64084
|
-
temperature: number().nullable(),
|
|
64085
|
-
/** Temperature unit string (e.g. `°C` / `°F`). Null when not provided. */
|
|
64086
|
-
temperatureUnit: string().nullable(),
|
|
64338
|
+
/** Current temperature in Celsius. Null when not provided or refused. */
|
|
64339
|
+
temperature: number().nullable().meta(readingMeta("temperature", { precision: 1 })),
|
|
64087
64340
|
/** Relative humidity (0..100). Null when not provided. */
|
|
64088
|
-
humidity: number().min(0).max(100).nullable(),
|
|
64089
|
-
/** Barometric pressure in
|
|
64090
|
-
pressure: number().nullable(),
|
|
64091
|
-
/**
|
|
64092
|
-
|
|
64093
|
-
/** Wind speed in the reported unit. Null when not provided. */
|
|
64094
|
-
windSpeed: number().nullable(),
|
|
64095
|
-
/** Wind-speed unit string (e.g. `km/h` / `mph`). Null when not provided. */
|
|
64096
|
-
windSpeedUnit: string().nullable(),
|
|
64341
|
+
humidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
64342
|
+
/** Barometric pressure in hPa. Null when not provided or refused. */
|
|
64343
|
+
pressure: number().nullable().meta(readingMeta("pressure")),
|
|
64344
|
+
/** Wind speed in metres per second. Null when not provided or refused. */
|
|
64345
|
+
windSpeed: number().nullable().meta(readingMeta("speed")),
|
|
64097
64346
|
/** Wind bearing in degrees (0..360, meteorological). Null when not provided. */
|
|
64098
|
-
windBearing: number().nullable(),
|
|
64347
|
+
windBearing: number().nullable().meta(readingMeta("angle")),
|
|
64099
64348
|
/** Ms epoch when the slice was last updated. */
|
|
64100
64349
|
lastFetchedAt: number()
|
|
64101
64350
|
});
|
|
@@ -68115,6 +68364,13 @@ Object.freeze({
|
|
|
68115
68364
|
access: "view",
|
|
68116
68365
|
role: "viewer"
|
|
68117
68366
|
},
|
|
68367
|
+
"groupStatus.getStatus": {
|
|
68368
|
+
capName: "group-status",
|
|
68369
|
+
capScope: "device",
|
|
68370
|
+
addonId: null,
|
|
68371
|
+
access: "view",
|
|
68372
|
+
role: "viewer"
|
|
68373
|
+
},
|
|
68118
68374
|
"heatingValve.getStatus": {
|
|
68119
68375
|
capName: "heating-valve",
|
|
68120
68376
|
capScope: "device",
|
|
@@ -77937,6 +78193,33 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
77937
78193
|
icon: "flame"
|
|
77938
78194
|
}]
|
|
77939
78195
|
},
|
|
78196
|
+
"group-status": {
|
|
78197
|
+
scope: "device",
|
|
78198
|
+
noun: t("Group", "Gruppo"),
|
|
78199
|
+
state: [
|
|
78200
|
+
{
|
|
78201
|
+
kind: "numeric",
|
|
78202
|
+
field: "included",
|
|
78203
|
+
quantity: t("the members reporting", "i membri che rispondono"),
|
|
78204
|
+
label: t("Reporting", "Rispondono"),
|
|
78205
|
+
icon: "users"
|
|
78206
|
+
},
|
|
78207
|
+
{
|
|
78208
|
+
kind: "numeric",
|
|
78209
|
+
field: "excluded",
|
|
78210
|
+
quantity: t("the members left out", "i membri esclusi"),
|
|
78211
|
+
label: t("Excluded", "Esclusi"),
|
|
78212
|
+
icon: "users"
|
|
78213
|
+
},
|
|
78214
|
+
{
|
|
78215
|
+
kind: "numeric",
|
|
78216
|
+
field: "total",
|
|
78217
|
+
quantity: t("the member count", "il numero di membri"),
|
|
78218
|
+
label: t("Members", "Membri"),
|
|
78219
|
+
icon: "sigma"
|
|
78220
|
+
}
|
|
78221
|
+
]
|
|
78222
|
+
},
|
|
77940
78223
|
"humidity-sensor": {
|
|
77941
78224
|
scope: "device",
|
|
77942
78225
|
noun: t("Humidity", "Umidità"),
|
|
@@ -77970,7 +78253,6 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
77970
78253
|
field: "value",
|
|
77971
78254
|
quantity: t("the reading", "il valore"),
|
|
77972
78255
|
label: t("Reading", "Valore"),
|
|
77973
|
-
unitField: "unit",
|
|
77974
78256
|
icon: "gauge"
|
|
77975
78257
|
}]
|
|
77976
78258
|
},
|
|
@@ -78106,7 +78388,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78106
78388
|
field: "temperature",
|
|
78107
78389
|
quantity: t("the outdoor temperature", "la temperatura esterna"),
|
|
78108
78390
|
label: t("Temperature", "Temperatura"),
|
|
78109
|
-
|
|
78391
|
+
unit: "°C",
|
|
78110
78392
|
icon: "thermometer"
|
|
78111
78393
|
},
|
|
78112
78394
|
{
|
|
@@ -78122,7 +78404,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78122
78404
|
field: "windSpeed",
|
|
78123
78405
|
quantity: t("the wind speed", "la velocità del vento"),
|
|
78124
78406
|
label: t("Wind", "Vento"),
|
|
78125
|
-
|
|
78407
|
+
unit: "m/s",
|
|
78126
78408
|
icon: "wind"
|
|
78127
78409
|
},
|
|
78128
78410
|
{
|
|
@@ -78130,7 +78412,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78130
78412
|
field: "pressure",
|
|
78131
78413
|
quantity: t("the air pressure", "la pressione atmosferica"),
|
|
78132
78414
|
label: t("Pressure", "Pressione"),
|
|
78133
|
-
|
|
78415
|
+
unit: "hPa",
|
|
78134
78416
|
icon: "gauge"
|
|
78135
78417
|
}
|
|
78136
78418
|
]
|
|
@@ -79403,6 +79685,11 @@ Object.freeze({
|
|
|
79403
79685
|
form: "single",
|
|
79404
79686
|
optional: false
|
|
79405
79687
|
}],
|
|
79688
|
+
"groupStatus.getStatus": [{
|
|
79689
|
+
name: "deviceId",
|
|
79690
|
+
form: "single",
|
|
79691
|
+
optional: false
|
|
79692
|
+
}],
|
|
79406
79693
|
"heatingValve.getStatus": [{
|
|
79407
79694
|
name: "deviceId",
|
|
79408
79695
|
form: "single",
|
|
@@ -82518,7 +82805,7 @@ var AgentUIAddon = class extends BaseAddon {
|
|
|
82518
82805
|
capability: adminUiCapability,
|
|
82519
82806
|
provider: {
|
|
82520
82807
|
getStaticDir: async () => ({ staticDir: path.resolve(__dirname) }),
|
|
82521
|
-
getVersion: async () => ({ version: "1.2.
|
|
82808
|
+
getVersion: async () => ({ version: "1.2.271" })
|
|
82522
82809
|
}
|
|
82523
82810
|
}];
|
|
82524
82811
|
}
|