@camstack/addon-training 0.1.82 → 0.1.84
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/{MotionZonesSettings-Ca-6XXfI.mjs → MotionZonesSettings-B2LROgdO.mjs} +2 -2
- package/dist/{PrivacyMaskSettings-BCUM9T8S.mjs → PrivacyMaskSettings-BI-wLtO5.mjs} +2 -2
- package/dist/{SceneMonitorEditor-CjJ891SK.mjs → SceneMonitorEditor-BsXMgLZ2.mjs} +1 -1
- package/dist/_stub.js +5358 -5290
- package/dist/{_virtual_mf-localSharedImportMap___mfe_internal__addon_training_page-vEOlZUQt.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_training_page-B1uLtRe1.mjs} +3 -3
- package/dist/_virtual_mf___mfe_internal__addon_training_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-CCYqyYqc.mjs +26 -0
- package/dist/{dist-VJTyi7FX.js → dist-DIvqaK45.js} +717 -430
- package/dist/{dist-CQOH32eF.mjs → dist-vmoGj7S3.mjs} +717 -430
- package/dist/{hostInit-CvOJdSqn.mjs → hostInit-DjoeThKQ.mjs} +2 -2
- package/dist/index.js +1 -1
- package/dist/orchestrator/training.addon.js +1 -1
- package/dist/orchestrator/training.addon.mjs +1 -1
- package/dist/{player-overlays-Bk8LUHwl.mjs → player-overlays-D6Na2rHN.mjs} +1 -1
- package/dist/providers/modal/training-modal.addon.js +1 -1
- package/dist/providers/modal/training-modal.addon.mjs +1 -1
- package/dist/remoteEntry.js +1 -1
- package/dist/{responsive-DkRlf-GQ.mjs → responsive-CagNQyj-.mjs} +16 -13
- package/dist/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_training_page__remoteEntry_js-DNg-tEZh.mjs → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_training_page__remoteEntry_js-OkrY_yeX.mjs} +1 -1
- package/package.json +1 -1
- package/dist/_virtual_mf___mfe_internal__addon_training_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-9NmkfCw8.mjs +0 -26
|
@@ -5600,7 +5600,7 @@ var ZodIssueCode = {
|
|
|
5600
5600
|
var ZodFirstPartyTypeKind;
|
|
5601
5601
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5602
5602
|
//#endregion
|
|
5603
|
-
//#region ../types/dist/sleep-
|
|
5603
|
+
//#region ../types/dist/sleep-B81gwQuR.mjs
|
|
5604
5604
|
/**
|
|
5605
5605
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5606
5606
|
* window to float samples (D455).
|
|
@@ -8335,6 +8335,99 @@ function defineEntryKind(name, spec) {
|
|
|
8335
8335
|
if (defined === void 0) throw new DeclarationRefusedError(`entry kind "${name}" was not built`);
|
|
8336
8336
|
return defined;
|
|
8337
8337
|
}
|
|
8338
|
+
var READING_QUANTITIES = [
|
|
8339
|
+
"temperature",
|
|
8340
|
+
"pressure",
|
|
8341
|
+
"speed",
|
|
8342
|
+
"precipitation",
|
|
8343
|
+
"precipitation-rate",
|
|
8344
|
+
"length",
|
|
8345
|
+
"area",
|
|
8346
|
+
"illuminance",
|
|
8347
|
+
"irradiance",
|
|
8348
|
+
"power",
|
|
8349
|
+
"energy",
|
|
8350
|
+
"voltage",
|
|
8351
|
+
"current",
|
|
8352
|
+
"apparent-power",
|
|
8353
|
+
"humidity",
|
|
8354
|
+
"percentage",
|
|
8355
|
+
"concentration-volume",
|
|
8356
|
+
"concentration-mass",
|
|
8357
|
+
"concentration-ppb",
|
|
8358
|
+
"volume",
|
|
8359
|
+
"duration",
|
|
8360
|
+
"duration-ms",
|
|
8361
|
+
"information",
|
|
8362
|
+
"sound-level",
|
|
8363
|
+
"signal-level",
|
|
8364
|
+
"colour-temperature",
|
|
8365
|
+
"angle",
|
|
8366
|
+
"bitrate",
|
|
8367
|
+
"rate",
|
|
8368
|
+
"mass",
|
|
8369
|
+
"index",
|
|
8370
|
+
"ratio",
|
|
8371
|
+
"count",
|
|
8372
|
+
"none",
|
|
8373
|
+
"device"
|
|
8374
|
+
];
|
|
8375
|
+
var ReadingQuantitySchema = _enum(READING_QUANTITIES);
|
|
8376
|
+
new Set(READING_QUANTITIES);
|
|
8377
|
+
/**
|
|
8378
|
+
* Stored unit symbol for a quantity. `none` means the number is dimensionless
|
|
8379
|
+
* (or an index / ratio / count). `device` means the cap has no single unit.
|
|
8380
|
+
*/
|
|
8381
|
+
var QUANTITY_BASE = {
|
|
8382
|
+
temperature: "°C",
|
|
8383
|
+
pressure: "hPa",
|
|
8384
|
+
speed: "m/s",
|
|
8385
|
+
precipitation: "mm",
|
|
8386
|
+
"precipitation-rate": "mm/h",
|
|
8387
|
+
length: "m",
|
|
8388
|
+
area: "m²",
|
|
8389
|
+
illuminance: "lx",
|
|
8390
|
+
irradiance: "W/m²",
|
|
8391
|
+
power: "W",
|
|
8392
|
+
energy: "kWh",
|
|
8393
|
+
voltage: "V",
|
|
8394
|
+
current: "A",
|
|
8395
|
+
"apparent-power": "VA",
|
|
8396
|
+
humidity: "%",
|
|
8397
|
+
percentage: "%",
|
|
8398
|
+
"concentration-volume": "ppm",
|
|
8399
|
+
"concentration-mass": "µg/m³",
|
|
8400
|
+
"concentration-ppb": "ppb",
|
|
8401
|
+
volume: "L",
|
|
8402
|
+
duration: "s",
|
|
8403
|
+
"duration-ms": "ms",
|
|
8404
|
+
information: "B",
|
|
8405
|
+
"sound-level": "dBFS",
|
|
8406
|
+
"signal-level": "dBm",
|
|
8407
|
+
"colour-temperature": "mired",
|
|
8408
|
+
angle: "°",
|
|
8409
|
+
bitrate: "kbps",
|
|
8410
|
+
rate: "fps",
|
|
8411
|
+
mass: "kg",
|
|
8412
|
+
index: "none",
|
|
8413
|
+
ratio: "none",
|
|
8414
|
+
count: "none",
|
|
8415
|
+
none: "none",
|
|
8416
|
+
device: "device"
|
|
8417
|
+
};
|
|
8418
|
+
/** The stored unit, or `undefined` when the quantity has no unit symbol. */
|
|
8419
|
+
function baseUnitOf(quantity) {
|
|
8420
|
+
const symbol = QUANTITY_BASE[quantity];
|
|
8421
|
+
if (symbol === "none" || symbol === "device") return void 0;
|
|
8422
|
+
return symbol;
|
|
8423
|
+
}
|
|
8424
|
+
function readingMeta(quantity, extras) {
|
|
8425
|
+
return {
|
|
8426
|
+
quantity,
|
|
8427
|
+
...extras?.precision !== void 0 ? { precision: extras.precision } : {},
|
|
8428
|
+
...extras?.label !== void 0 ? { label: extras.label } : {}
|
|
8429
|
+
};
|
|
8430
|
+
}
|
|
8338
8431
|
/** Shared Zod schemas used across streaming capabilities. */
|
|
8339
8432
|
var CamProfileSchema = _enum([
|
|
8340
8433
|
"high",
|
|
@@ -8362,8 +8455,8 @@ var CamStreamKindSchema = _enum([
|
|
|
8362
8455
|
"derived"
|
|
8363
8456
|
]);
|
|
8364
8457
|
var CamStreamResolutionSchema = object({
|
|
8365
|
-
width: number().int().positive(),
|
|
8366
|
-
height: number().int().positive()
|
|
8458
|
+
width: number().int().positive().meta(readingMeta("none")),
|
|
8459
|
+
height: number().int().positive().meta(readingMeta("none"))
|
|
8367
8460
|
});
|
|
8368
8461
|
var CameraStreamSchema = object({
|
|
8369
8462
|
/** Stable, provider-assigned id unique within the (deviceId) scope. */
|
|
@@ -8877,6 +8970,7 @@ var CAP_NAMES = Object.freeze([
|
|
|
8877
8970
|
"filesystem-browse",
|
|
8878
8971
|
"flood",
|
|
8879
8972
|
"gas",
|
|
8973
|
+
"group-status",
|
|
8880
8974
|
"heating-valve",
|
|
8881
8975
|
"humidifier",
|
|
8882
8976
|
"humidity-sensor",
|
|
@@ -9006,14 +9100,6 @@ Object.freeze({
|
|
|
9006
9100
|
{
|
|
9007
9101
|
"path": "aqi",
|
|
9008
9102
|
"valueType": "number"
|
|
9009
|
-
},
|
|
9010
|
-
{
|
|
9011
|
-
"path": "unit",
|
|
9012
|
-
"valueType": "string"
|
|
9013
|
-
},
|
|
9014
|
-
{
|
|
9015
|
-
"path": "precision",
|
|
9016
|
-
"valueType": "number"
|
|
9017
9103
|
}
|
|
9018
9104
|
],
|
|
9019
9105
|
"alarm-panel": [
|
|
@@ -9049,20 +9135,10 @@ Object.freeze({
|
|
|
9049
9135
|
"valueType": "boolean"
|
|
9050
9136
|
}
|
|
9051
9137
|
],
|
|
9052
|
-
"ambient-light-sensor": [
|
|
9053
|
-
|
|
9054
|
-
|
|
9055
|
-
|
|
9056
|
-
},
|
|
9057
|
-
{
|
|
9058
|
-
"path": "unit",
|
|
9059
|
-
"valueType": "string"
|
|
9060
|
-
},
|
|
9061
|
-
{
|
|
9062
|
-
"path": "precision",
|
|
9063
|
-
"valueType": "number"
|
|
9064
|
-
}
|
|
9065
|
-
],
|
|
9138
|
+
"ambient-light-sensor": [{
|
|
9139
|
+
"path": "lux",
|
|
9140
|
+
"valueType": "number"
|
|
9141
|
+
}],
|
|
9066
9142
|
"audio-metrics": [
|
|
9067
9143
|
{
|
|
9068
9144
|
"path": "ts",
|
|
@@ -9142,6 +9218,10 @@ Object.freeze({
|
|
|
9142
9218
|
"path": "lastUpdated",
|
|
9143
9219
|
"valueType": "number"
|
|
9144
9220
|
},
|
|
9221
|
+
{
|
|
9222
|
+
"path": "volts",
|
|
9223
|
+
"valueType": "number"
|
|
9224
|
+
},
|
|
9145
9225
|
{
|
|
9146
9226
|
"path": "lastContactAt",
|
|
9147
9227
|
"valueType": "number"
|
|
@@ -9384,10 +9464,6 @@ Object.freeze({
|
|
|
9384
9464
|
"datetime"
|
|
9385
9465
|
]
|
|
9386
9466
|
},
|
|
9387
|
-
{
|
|
9388
|
-
"path": "unit",
|
|
9389
|
-
"valueType": "string"
|
|
9390
|
-
},
|
|
9391
9467
|
{
|
|
9392
9468
|
"path": "min",
|
|
9393
9469
|
"valueType": "number"
|
|
@@ -9399,19 +9475,6 @@ Object.freeze({
|
|
|
9399
9475
|
{
|
|
9400
9476
|
"path": "step",
|
|
9401
9477
|
"valueType": "number"
|
|
9402
|
-
},
|
|
9403
|
-
{
|
|
9404
|
-
"path": "precision",
|
|
9405
|
-
"valueType": "number"
|
|
9406
|
-
},
|
|
9407
|
-
{
|
|
9408
|
-
"path": "format",
|
|
9409
|
-
"valueType": "enum",
|
|
9410
|
-
"enumValues": [
|
|
9411
|
-
"date",
|
|
9412
|
-
"time",
|
|
9413
|
-
"datetime"
|
|
9414
|
-
]
|
|
9415
9478
|
}
|
|
9416
9479
|
],
|
|
9417
9480
|
"cover": [
|
|
@@ -9652,13 +9715,8 @@ Object.freeze({
|
|
|
9652
9715
|
"path": "value",
|
|
9653
9716
|
"valueType": "string"
|
|
9654
9717
|
}, {
|
|
9655
|
-
"path": "
|
|
9656
|
-
"valueType": "
|
|
9657
|
-
"enumValues": [
|
|
9658
|
-
"date",
|
|
9659
|
-
"time",
|
|
9660
|
-
"datetime"
|
|
9661
|
-
]
|
|
9718
|
+
"path": "timestamp",
|
|
9719
|
+
"valueType": "boolean"
|
|
9662
9720
|
}],
|
|
9663
9721
|
"event-emitter": [
|
|
9664
9722
|
{
|
|
@@ -9731,6 +9789,20 @@ Object.freeze({
|
|
|
9731
9789
|
"path": "detected",
|
|
9732
9790
|
"valueType": "boolean"
|
|
9733
9791
|
}],
|
|
9792
|
+
"group-status": [
|
|
9793
|
+
{
|
|
9794
|
+
"path": "included",
|
|
9795
|
+
"valueType": "number"
|
|
9796
|
+
},
|
|
9797
|
+
{
|
|
9798
|
+
"path": "excluded",
|
|
9799
|
+
"valueType": "number"
|
|
9800
|
+
},
|
|
9801
|
+
{
|
|
9802
|
+
"path": "total",
|
|
9803
|
+
"valueType": "number"
|
|
9804
|
+
}
|
|
9805
|
+
],
|
|
9734
9806
|
"heating-valve": [{
|
|
9735
9807
|
"path": "position",
|
|
9736
9808
|
"valueType": "number"
|
|
@@ -9765,20 +9837,10 @@ Object.freeze({
|
|
|
9765
9837
|
"valueType": "number"
|
|
9766
9838
|
}
|
|
9767
9839
|
],
|
|
9768
|
-
"humidity-sensor": [
|
|
9769
|
-
|
|
9770
|
-
|
|
9771
|
-
|
|
9772
|
-
},
|
|
9773
|
-
{
|
|
9774
|
-
"path": "unit",
|
|
9775
|
-
"valueType": "string"
|
|
9776
|
-
},
|
|
9777
|
-
{
|
|
9778
|
-
"path": "precision",
|
|
9779
|
-
"valueType": "number"
|
|
9780
|
-
}
|
|
9781
|
-
],
|
|
9840
|
+
"humidity-sensor": [{
|
|
9841
|
+
"path": "percent",
|
|
9842
|
+
"valueType": "number"
|
|
9843
|
+
}],
|
|
9782
9844
|
"image": [{
|
|
9783
9845
|
"path": "url",
|
|
9784
9846
|
"valueType": "string"
|
|
@@ -10117,20 +10179,10 @@ Object.freeze({
|
|
|
10117
10179
|
"valueType": "boolean"
|
|
10118
10180
|
}
|
|
10119
10181
|
],
|
|
10120
|
-
"numeric-sensor": [
|
|
10121
|
-
|
|
10122
|
-
|
|
10123
|
-
|
|
10124
|
-
},
|
|
10125
|
-
{
|
|
10126
|
-
"path": "unit",
|
|
10127
|
-
"valueType": "string"
|
|
10128
|
-
},
|
|
10129
|
-
{
|
|
10130
|
-
"path": "precision",
|
|
10131
|
-
"valueType": "number"
|
|
10132
|
-
}
|
|
10133
|
-
],
|
|
10182
|
+
"numeric-sensor": [{
|
|
10183
|
+
"path": "value",
|
|
10184
|
+
"valueType": "number"
|
|
10185
|
+
}],
|
|
10134
10186
|
"pet-feeder": [
|
|
10135
10187
|
{
|
|
10136
10188
|
"path": "foodLevel",
|
|
@@ -10222,14 +10274,6 @@ Object.freeze({
|
|
|
10222
10274
|
{
|
|
10223
10275
|
"path": "powerFactor",
|
|
10224
10276
|
"valueType": "number"
|
|
10225
|
-
},
|
|
10226
|
-
{
|
|
10227
|
-
"path": "unit",
|
|
10228
|
-
"valueType": "string"
|
|
10229
|
-
},
|
|
10230
|
-
{
|
|
10231
|
-
"path": "precision",
|
|
10232
|
-
"valueType": "number"
|
|
10233
10277
|
}
|
|
10234
10278
|
],
|
|
10235
10279
|
"presence": [
|
|
@@ -10258,20 +10302,10 @@ Object.freeze({
|
|
|
10258
10302
|
"valueType": "number"
|
|
10259
10303
|
}
|
|
10260
10304
|
],
|
|
10261
|
-
"pressure-sensor": [
|
|
10262
|
-
|
|
10263
|
-
|
|
10264
|
-
|
|
10265
|
-
},
|
|
10266
|
-
{
|
|
10267
|
-
"path": "unit",
|
|
10268
|
-
"valueType": "string"
|
|
10269
|
-
},
|
|
10270
|
-
{
|
|
10271
|
-
"path": "precision",
|
|
10272
|
-
"valueType": "number"
|
|
10273
|
-
}
|
|
10274
|
-
],
|
|
10305
|
+
"pressure-sensor": [{
|
|
10306
|
+
"path": "hpa",
|
|
10307
|
+
"valueType": "number"
|
|
10308
|
+
}],
|
|
10275
10309
|
"privacy-mask": [{
|
|
10276
10310
|
"path": "enabled",
|
|
10277
10311
|
"valueType": "boolean"
|
|
@@ -10582,20 +10616,10 @@ Object.freeze({
|
|
|
10582
10616
|
"path": "tampered",
|
|
10583
10617
|
"valueType": "boolean"
|
|
10584
10618
|
}],
|
|
10585
|
-
"temperature-sensor": [
|
|
10586
|
-
|
|
10587
|
-
|
|
10588
|
-
|
|
10589
|
-
},
|
|
10590
|
-
{
|
|
10591
|
-
"path": "unit",
|
|
10592
|
-
"valueType": "string"
|
|
10593
|
-
},
|
|
10594
|
-
{
|
|
10595
|
-
"path": "precision",
|
|
10596
|
-
"valueType": "number"
|
|
10597
|
-
}
|
|
10598
|
-
],
|
|
10619
|
+
"temperature-sensor": [{
|
|
10620
|
+
"path": "celsius",
|
|
10621
|
+
"valueType": "number"
|
|
10622
|
+
}],
|
|
10599
10623
|
"update": [
|
|
10600
10624
|
{
|
|
10601
10625
|
"path": "currentVersion",
|
|
@@ -10706,10 +10730,6 @@ Object.freeze({
|
|
|
10706
10730
|
"path": "temperature",
|
|
10707
10731
|
"valueType": "number"
|
|
10708
10732
|
},
|
|
10709
|
-
{
|
|
10710
|
-
"path": "temperatureUnit",
|
|
10711
|
-
"valueType": "string"
|
|
10712
|
-
},
|
|
10713
10733
|
{
|
|
10714
10734
|
"path": "humidity",
|
|
10715
10735
|
"valueType": "number"
|
|
@@ -10718,18 +10738,10 @@ Object.freeze({
|
|
|
10718
10738
|
"path": "pressure",
|
|
10719
10739
|
"valueType": "number"
|
|
10720
10740
|
},
|
|
10721
|
-
{
|
|
10722
|
-
"path": "pressureUnit",
|
|
10723
|
-
"valueType": "string"
|
|
10724
|
-
},
|
|
10725
10741
|
{
|
|
10726
10742
|
"path": "windSpeed",
|
|
10727
10743
|
"valueType": "number"
|
|
10728
10744
|
},
|
|
10729
|
-
{
|
|
10730
|
-
"path": "windSpeedUnit",
|
|
10731
|
-
"valueType": "string"
|
|
10732
|
-
},
|
|
10733
10745
|
{
|
|
10734
10746
|
"path": "windBearing",
|
|
10735
10747
|
"valueType": "number"
|
|
@@ -11122,7 +11134,7 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
|
|
|
11122
11134
|
return DeviceRole;
|
|
11123
11135
|
}({});
|
|
11124
11136
|
//#endregion
|
|
11125
|
-
//#region ../types/dist/composition-
|
|
11137
|
+
//#region ../types/dist/composition-B85l9j1M.mjs
|
|
11126
11138
|
/**
|
|
11127
11139
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
11128
11140
|
*
|
|
@@ -11877,15 +11889,67 @@ function validateExpressionSource(src) {
|
|
|
11877
11889
|
}
|
|
11878
11890
|
return null;
|
|
11879
11891
|
}
|
|
11880
|
-
/**
|
|
11881
|
-
|
|
11882
|
-
|
|
11883
|
-
|
|
11892
|
+
/**
|
|
11893
|
+
* A composition source identity: `(addonId, stableId)`, never a numeric device
|
|
11894
|
+
* id. Split out so helper schemas can name it without a cycle through
|
|
11895
|
+
* `composition.ts` (D659).
|
|
11896
|
+
*/
|
|
11884
11897
|
var CompositionSourceRefSchema = object({
|
|
11885
11898
|
/** The owning addon; `stableId` is unique only within it. */
|
|
11886
11899
|
addonId: string().min(1),
|
|
11887
11900
|
stableId: string().min(1)
|
|
11888
11901
|
});
|
|
11902
|
+
var GROUP_TEMPLATE_IDS = [
|
|
11903
|
+
"temperature",
|
|
11904
|
+
"humidity",
|
|
11905
|
+
"pressure",
|
|
11906
|
+
"illuminance",
|
|
11907
|
+
"power",
|
|
11908
|
+
"energy",
|
|
11909
|
+
"battery",
|
|
11910
|
+
"numeric",
|
|
11911
|
+
"motion",
|
|
11912
|
+
"contact",
|
|
11913
|
+
"leak",
|
|
11914
|
+
"smoke",
|
|
11915
|
+
"occupancy",
|
|
11916
|
+
"binary"
|
|
11917
|
+
];
|
|
11918
|
+
var NUMERIC_AGGREGATES = [
|
|
11919
|
+
"mean",
|
|
11920
|
+
"median",
|
|
11921
|
+
"min",
|
|
11922
|
+
"max",
|
|
11923
|
+
"sum"
|
|
11924
|
+
];
|
|
11925
|
+
var BINARY_AGGREGATES = ["any", "all"];
|
|
11926
|
+
var AGGREGATE_REDUCERS = [
|
|
11927
|
+
"mean",
|
|
11928
|
+
"median",
|
|
11929
|
+
"min",
|
|
11930
|
+
"max",
|
|
11931
|
+
"sum",
|
|
11932
|
+
"any",
|
|
11933
|
+
"all"
|
|
11934
|
+
];
|
|
11935
|
+
var GroupTemplateIdSchema = _enum(GROUP_TEMPLATE_IDS);
|
|
11936
|
+
var AggregateReducerSchema = _enum(AGGREGATE_REDUCERS);
|
|
11937
|
+
/** One member. The field is stored so occupancy can name motion or binary. */
|
|
11938
|
+
var HelperMemberSchema = object({
|
|
11939
|
+
source: CompositionSourceRefSchema,
|
|
11940
|
+
cap: string().min(1),
|
|
11941
|
+
fieldPath: string().min(1)
|
|
11942
|
+
});
|
|
11943
|
+
var HelperSpecSchema = discriminatedUnion("kind", [object({
|
|
11944
|
+
kind: literal("group"),
|
|
11945
|
+
templateId: GroupTemplateIdSchema,
|
|
11946
|
+
aggregate: AggregateReducerSchema,
|
|
11947
|
+
members: array(HelperMemberSchema).min(1).max(64)
|
|
11948
|
+
})]);
|
|
11949
|
+
/** A composed device's stableId is this prefix plus the block id. */
|
|
11950
|
+
var COMPOSED_DEVICE_STABLE_ID_PREFIX = "composed-";
|
|
11951
|
+
/** Longest snippet a `code` source may carry (slice 4). */
|
|
11952
|
+
var MAX_COMPOSITION_CODE_LENGTH = 2e4;
|
|
11889
11953
|
/** One field of one capability of one source device. */
|
|
11890
11954
|
var CompositionFieldReadSchema = object({
|
|
11891
11955
|
source: CompositionSourceRefSchema,
|
|
@@ -11929,7 +11993,33 @@ var CompositionCodeSourceSchema = object({
|
|
|
11929
11993
|
var CompositionFieldSourceSchema = discriminatedUnion("kind", [
|
|
11930
11994
|
CompositionFromSourceSchema,
|
|
11931
11995
|
CompositionExpressionSourceSchema,
|
|
11932
|
-
CompositionCodeSourceSchema
|
|
11996
|
+
CompositionCodeSourceSchema,
|
|
11997
|
+
object({
|
|
11998
|
+
kind: literal("aggregate"),
|
|
11999
|
+
reducer: _enum([
|
|
12000
|
+
"mean",
|
|
12001
|
+
"median",
|
|
12002
|
+
"min",
|
|
12003
|
+
"max",
|
|
12004
|
+
"sum",
|
|
12005
|
+
"any",
|
|
12006
|
+
"all"
|
|
12007
|
+
]),
|
|
12008
|
+
reads: array(CompositionFieldReadSchema).min(1).max(64),
|
|
12009
|
+
/** `value` is the reading; the others are the member counts. */
|
|
12010
|
+
publish: _enum([
|
|
12011
|
+
"value",
|
|
12012
|
+
"included",
|
|
12013
|
+
"excluded",
|
|
12014
|
+
"total"
|
|
12015
|
+
]),
|
|
12016
|
+
/** What a `value` publish does when nobody is included. Counts ignore this. */
|
|
12017
|
+
empty: _enum([
|
|
12018
|
+
"null",
|
|
12019
|
+
"omit",
|
|
12020
|
+
"offline"
|
|
12021
|
+
])
|
|
12022
|
+
})
|
|
11933
12023
|
]);
|
|
11934
12024
|
var CompositionCommandTargetSchema = discriminatedUnion("kind", [object({
|
|
11935
12025
|
kind: literal("forward"),
|
|
@@ -11975,7 +12065,13 @@ var CompositionSchema = object({
|
|
|
11975
12065
|
kind: literal("existing"),
|
|
11976
12066
|
device: CompositionSourceRefSchema
|
|
11977
12067
|
})]),
|
|
11978
|
-
features: array(CompositionFeatureSchema).min(1).max(16)
|
|
12068
|
+
features: array(CompositionFeatureSchema).min(1).max(16),
|
|
12069
|
+
/**
|
|
12070
|
+
* Present when the block is a helper template. Absent on a free
|
|
12071
|
+
* composition (the room example, device 4603). The editor reads this,
|
|
12072
|
+
* never the compiled features.
|
|
12073
|
+
*/
|
|
12074
|
+
helper: HelperSpecSchema.optional()
|
|
11979
12075
|
}).superRefine((composition, ctx) => {
|
|
11980
12076
|
const seen = /* @__PURE__ */ new Set();
|
|
11981
12077
|
composition.features.forEach((feature, index) => {
|
|
@@ -18112,7 +18208,11 @@ var CompositionProblemSchema = object({
|
|
|
18112
18208
|
"item-field-reserved",
|
|
18113
18209
|
"target-missing",
|
|
18114
18210
|
"target-unreadable",
|
|
18115
|
-
"not-replaceable"
|
|
18211
|
+
"not-replaceable",
|
|
18212
|
+
"native-capability-replace",
|
|
18213
|
+
"mixed-quantity",
|
|
18214
|
+
"helper-mismatch",
|
|
18215
|
+
"member-constraint"
|
|
18116
18216
|
]),
|
|
18117
18217
|
path: string(),
|
|
18118
18218
|
message: string()
|
|
@@ -18133,7 +18233,8 @@ var CompositionUnavailableModeSchema = _enum([
|
|
|
18133
18233
|
"null",
|
|
18134
18234
|
"offline",
|
|
18135
18235
|
"unknown",
|
|
18136
|
-
"release"
|
|
18236
|
+
"release",
|
|
18237
|
+
"omit"
|
|
18137
18238
|
]);
|
|
18138
18239
|
/**
|
|
18139
18240
|
* `derived` reads a source · `clock` reads only `now`, recomputed when a sibling
|
|
@@ -18170,9 +18271,11 @@ var CompositionFieldPlanSchema = object({
|
|
|
18170
18271
|
reads: array(CompositionFieldReadSchema)
|
|
18171
18272
|
});
|
|
18172
18273
|
/**
|
|
18173
|
-
* What a feature does to its target (D663): `new` builds a capability on a
|
|
18174
|
-
* device; on an existing device it `add`s a capability the device lacks
|
|
18175
|
-
*
|
|
18274
|
+
* What a feature does to its target (D663, D944): `new` builds a capability on a
|
|
18275
|
+
* new device; on an existing device it `add`s a capability the device lacks.
|
|
18276
|
+
* Replacing a capability the device already serves is refused
|
|
18277
|
+
* (`native-capability-replace`), not planned. `replace` remains on the claim
|
|
18278
|
+
* wire for a claim the hub already holds.
|
|
18176
18279
|
*/
|
|
18177
18280
|
var CompositionFeatureModeSchema = _enum([
|
|
18178
18281
|
"new",
|
|
@@ -18345,6 +18448,235 @@ Object.freeze({
|
|
|
18345
18448
|
result: ["number", "null"]
|
|
18346
18449
|
}
|
|
18347
18450
|
});
|
|
18451
|
+
/**
|
|
18452
|
+
* One catalog row per base reading a group helper can build (D944 §3).
|
|
18453
|
+
* Data, not a form default written into the block.
|
|
18454
|
+
*/
|
|
18455
|
+
var NOW = {
|
|
18456
|
+
fieldPath: "lastFetchedAt",
|
|
18457
|
+
expr: "now"
|
|
18458
|
+
};
|
|
18459
|
+
var CHANGED = {
|
|
18460
|
+
fieldPath: "lastChangedAt",
|
|
18461
|
+
expr: "now"
|
|
18462
|
+
};
|
|
18463
|
+
function numeric(input) {
|
|
18464
|
+
return {
|
|
18465
|
+
...input,
|
|
18466
|
+
family: "numeric",
|
|
18467
|
+
deviceType: DeviceType.Sensor,
|
|
18468
|
+
memberDeviceType: DeviceType.Sensor,
|
|
18469
|
+
baseUnit: baseUnitOf(input.quantity),
|
|
18470
|
+
aggregates: NUMERIC_AGGREGATES,
|
|
18471
|
+
accept: [{
|
|
18472
|
+
cap: input.outputCap,
|
|
18473
|
+
fieldPath: input.outputField
|
|
18474
|
+
}]
|
|
18475
|
+
};
|
|
18476
|
+
}
|
|
18477
|
+
function binary(input) {
|
|
18478
|
+
return {
|
|
18479
|
+
...input,
|
|
18480
|
+
family: "binary",
|
|
18481
|
+
deviceType: DeviceType.Sensor,
|
|
18482
|
+
memberDeviceType: DeviceType.Sensor,
|
|
18483
|
+
quantity: "none",
|
|
18484
|
+
baseUnit: void 0,
|
|
18485
|
+
aggregates: BINARY_AGGREGATES,
|
|
18486
|
+
empty: "offline"
|
|
18487
|
+
};
|
|
18488
|
+
}
|
|
18489
|
+
var GROUP_TEMPLATES = [
|
|
18490
|
+
numeric({
|
|
18491
|
+
id: "temperature",
|
|
18492
|
+
summary: "Mean, median, min, max or sum of temperatures. Offline and unknown members are left out, never read as 0 °C.",
|
|
18493
|
+
role: DeviceRole.TemperatureSensor,
|
|
18494
|
+
outputCap: "temperature-sensor",
|
|
18495
|
+
outputField: "celsius",
|
|
18496
|
+
quantity: "temperature",
|
|
18497
|
+
defaultAggregate: "mean",
|
|
18498
|
+
empty: "null",
|
|
18499
|
+
companions: [NOW]
|
|
18500
|
+
}),
|
|
18501
|
+
numeric({
|
|
18502
|
+
id: "humidity",
|
|
18503
|
+
summary: "Humidity in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
18504
|
+
role: DeviceRole.HumiditySensor,
|
|
18505
|
+
outputCap: "humidity-sensor",
|
|
18506
|
+
outputField: "percent",
|
|
18507
|
+
quantity: "humidity",
|
|
18508
|
+
defaultAggregate: "mean",
|
|
18509
|
+
empty: "null",
|
|
18510
|
+
companions: [NOW]
|
|
18511
|
+
}),
|
|
18512
|
+
numeric({
|
|
18513
|
+
id: "pressure",
|
|
18514
|
+
summary: "Pressure in hectopascals. Offline and unknown members are left out, never read as 0 hPa.",
|
|
18515
|
+
role: DeviceRole.PressureSensor,
|
|
18516
|
+
outputCap: "pressure-sensor",
|
|
18517
|
+
outputField: "hpa",
|
|
18518
|
+
quantity: "pressure",
|
|
18519
|
+
defaultAggregate: "mean",
|
|
18520
|
+
empty: "null",
|
|
18521
|
+
companions: [NOW]
|
|
18522
|
+
}),
|
|
18523
|
+
numeric({
|
|
18524
|
+
id: "illuminance",
|
|
18525
|
+
summary: "Illuminance in lux. Offline and unknown members are left out, never read as 0 lx.",
|
|
18526
|
+
role: DeviceRole.AmbientLightSensor,
|
|
18527
|
+
outputCap: "ambient-light-sensor",
|
|
18528
|
+
outputField: "lux",
|
|
18529
|
+
quantity: "illuminance",
|
|
18530
|
+
defaultAggregate: "mean",
|
|
18531
|
+
empty: "null",
|
|
18532
|
+
companions: [NOW]
|
|
18533
|
+
}),
|
|
18534
|
+
numeric({
|
|
18535
|
+
id: "power",
|
|
18536
|
+
summary: "Power in watts, summed by default. Nobody reporting omits the key rather than writing 0 W.",
|
|
18537
|
+
role: DeviceRole.PowerSensor,
|
|
18538
|
+
outputCap: "power-meter",
|
|
18539
|
+
outputField: "watts",
|
|
18540
|
+
quantity: "power",
|
|
18541
|
+
defaultAggregate: "sum",
|
|
18542
|
+
empty: "omit",
|
|
18543
|
+
companions: [NOW]
|
|
18544
|
+
}),
|
|
18545
|
+
numeric({
|
|
18546
|
+
id: "energy",
|
|
18547
|
+
summary: "Energy in kilowatt-hours, summed by default. Nobody reporting omits the key rather than writing 0 kWh.",
|
|
18548
|
+
role: DeviceRole.EnergySensor,
|
|
18549
|
+
outputCap: "power-meter",
|
|
18550
|
+
outputField: "kwhTotal",
|
|
18551
|
+
quantity: "energy",
|
|
18552
|
+
defaultAggregate: "sum",
|
|
18553
|
+
empty: "omit",
|
|
18554
|
+
companions: [NOW]
|
|
18555
|
+
}),
|
|
18556
|
+
numeric({
|
|
18557
|
+
id: "battery",
|
|
18558
|
+
summary: "Battery charge in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
18559
|
+
role: DeviceRole.BatterySensor,
|
|
18560
|
+
outputCap: "battery",
|
|
18561
|
+
outputField: "percentage",
|
|
18562
|
+
quantity: "percentage",
|
|
18563
|
+
defaultAggregate: "mean",
|
|
18564
|
+
empty: "null",
|
|
18565
|
+
companions: [
|
|
18566
|
+
{
|
|
18567
|
+
fieldPath: "charging",
|
|
18568
|
+
expr: "\"unknown\""
|
|
18569
|
+
},
|
|
18570
|
+
{
|
|
18571
|
+
fieldPath: "sleeping",
|
|
18572
|
+
expr: "false"
|
|
18573
|
+
},
|
|
18574
|
+
{
|
|
18575
|
+
fieldPath: "lastUpdated",
|
|
18576
|
+
expr: "now"
|
|
18577
|
+
}
|
|
18578
|
+
]
|
|
18579
|
+
}),
|
|
18580
|
+
numeric({
|
|
18581
|
+
id: "numeric",
|
|
18582
|
+
summary: "A numeric reading in the members’ shared quantity. Mixed quantities are refused. Nobody reporting publishes null, not 0.",
|
|
18583
|
+
role: DeviceRole.NumericSensor,
|
|
18584
|
+
outputCap: "numeric-sensor",
|
|
18585
|
+
outputField: "value",
|
|
18586
|
+
quantity: "device",
|
|
18587
|
+
defaultAggregate: "mean",
|
|
18588
|
+
empty: "null",
|
|
18589
|
+
companions: [NOW]
|
|
18590
|
+
}),
|
|
18591
|
+
binary({
|
|
18592
|
+
id: "motion",
|
|
18593
|
+
summary: "Any or all motion. Offline and unknown members are left out, never read as off. Nobody reporting takes the device offline.",
|
|
18594
|
+
role: DeviceRole.MotionSensor,
|
|
18595
|
+
outputCap: "motion",
|
|
18596
|
+
outputField: "detected",
|
|
18597
|
+
defaultAggregate: "any",
|
|
18598
|
+
accept: [{
|
|
18599
|
+
cap: "motion",
|
|
18600
|
+
fieldPath: "detected"
|
|
18601
|
+
}],
|
|
18602
|
+
companions: [{
|
|
18603
|
+
fieldPath: "lastDetectedAt",
|
|
18604
|
+
expr: "null"
|
|
18605
|
+
}, {
|
|
18606
|
+
fieldPath: "autoClearAfterMs",
|
|
18607
|
+
expr: "null"
|
|
18608
|
+
}]
|
|
18609
|
+
}),
|
|
18610
|
+
binary({
|
|
18611
|
+
id: "contact",
|
|
18612
|
+
summary: "Any or all open contacts. Offline and unknown members are left out, never read as closed.",
|
|
18613
|
+
role: DeviceRole.ContactSensor,
|
|
18614
|
+
outputCap: "contact",
|
|
18615
|
+
outputField: "entryOpen",
|
|
18616
|
+
defaultAggregate: "any",
|
|
18617
|
+
accept: [{
|
|
18618
|
+
cap: "contact",
|
|
18619
|
+
fieldPath: "entryOpen"
|
|
18620
|
+
}],
|
|
18621
|
+
companions: [CHANGED]
|
|
18622
|
+
}),
|
|
18623
|
+
binary({
|
|
18624
|
+
id: "leak",
|
|
18625
|
+
summary: "Any or all leak detections. Offline and unknown members are left out, never read as dry.",
|
|
18626
|
+
role: DeviceRole.LeakSensor,
|
|
18627
|
+
outputCap: "flood",
|
|
18628
|
+
outputField: "flooded",
|
|
18629
|
+
defaultAggregate: "any",
|
|
18630
|
+
accept: [{
|
|
18631
|
+
cap: "flood",
|
|
18632
|
+
fieldPath: "flooded"
|
|
18633
|
+
}],
|
|
18634
|
+
companions: [CHANGED]
|
|
18635
|
+
}),
|
|
18636
|
+
binary({
|
|
18637
|
+
id: "smoke",
|
|
18638
|
+
summary: "Any or all smoke detections. Offline and unknown members are left out, never read as clear.",
|
|
18639
|
+
role: DeviceRole.SmokeSensor,
|
|
18640
|
+
outputCap: "smoke",
|
|
18641
|
+
outputField: "detected",
|
|
18642
|
+
defaultAggregate: "any",
|
|
18643
|
+
accept: [{
|
|
18644
|
+
cap: "smoke",
|
|
18645
|
+
fieldPath: "detected"
|
|
18646
|
+
}],
|
|
18647
|
+
companions: [CHANGED]
|
|
18648
|
+
}),
|
|
18649
|
+
binary({
|
|
18650
|
+
id: "occupancy",
|
|
18651
|
+
summary: "Any or all of motion or binary sensors, published as a binary. Presence zones are not aggregated. Nobody reporting is offline, not off.",
|
|
18652
|
+
role: DeviceRole.BinarySensor,
|
|
18653
|
+
outputCap: "binary",
|
|
18654
|
+
outputField: "on",
|
|
18655
|
+
defaultAggregate: "any",
|
|
18656
|
+
accept: [{
|
|
18657
|
+
cap: "motion",
|
|
18658
|
+
fieldPath: "detected"
|
|
18659
|
+
}, {
|
|
18660
|
+
cap: "binary",
|
|
18661
|
+
fieldPath: "on"
|
|
18662
|
+
}],
|
|
18663
|
+
companions: [CHANGED]
|
|
18664
|
+
}),
|
|
18665
|
+
binary({
|
|
18666
|
+
id: "binary",
|
|
18667
|
+
summary: "Any or all generic binary sensors. Offline and unknown members are left out, never read as off.",
|
|
18668
|
+
role: DeviceRole.BinarySensor,
|
|
18669
|
+
outputCap: "binary",
|
|
18670
|
+
outputField: "on",
|
|
18671
|
+
defaultAggregate: "any",
|
|
18672
|
+
accept: [{
|
|
18673
|
+
cap: "binary",
|
|
18674
|
+
fieldPath: "on"
|
|
18675
|
+
}],
|
|
18676
|
+
companions: [CHANGED]
|
|
18677
|
+
})
|
|
18678
|
+
];
|
|
18679
|
+
new Map(GROUP_TEMPLATES.map((template) => [template.id, template]));
|
|
18348
18680
|
`${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
|
|
18349
18681
|
/**
|
|
18350
18682
|
* What a composition may BUILD on a device type (G2, D676): the caps a new
|
|
@@ -20058,12 +20390,12 @@ method(object({ deviceId: number().int().nonnegative() }), DeviceAdminLinkSchema
|
|
|
20058
20390
|
* providers detect renames by matching `uniqueId` and patch `id`
|
|
20059
20391
|
* in-place so dispatch keeps working.
|
|
20060
20392
|
*
|
|
20061
|
-
* **
|
|
20062
|
-
*
|
|
20063
|
-
*
|
|
20064
|
-
*
|
|
20065
|
-
* (`ha-domain-mapping`)
|
|
20066
|
-
* stored after that point.
|
|
20393
|
+
* **Display unit and precision are NOT stored here.** They are a read-time
|
|
20394
|
+
* preference (D944). A polymorphic reading stores its `quantity` here once,
|
|
20395
|
+
* at adopt, and a date/time value stores `dateTimeShape` the same way —
|
|
20396
|
+
* neither is repeated on each sample. The `device_class` tag is an
|
|
20397
|
+
* HA-specific input consumed at the discovery boundary (`ha-domain-mapping`)
|
|
20398
|
+
* to derive the CamStack `DeviceRole`; it is never stored after that point.
|
|
20067
20399
|
*
|
|
20068
20400
|
* The `raw` escape hatch carries provider-specific attributes that don't
|
|
20069
20401
|
* fit the structured slots (HA `attributes` whitelist, Reolink `deviceCache`
|
|
@@ -20077,6 +20409,14 @@ var SourceInfoSchema = object({
|
|
|
20077
20409
|
/** Immutable upstream identifier when available (HA `unique_id`, … ).
|
|
20078
20410
|
* Used to detect rename when `id` changes. */
|
|
20079
20411
|
uniqueId: string().optional(),
|
|
20412
|
+
/** Quantity of a polymorphic reading, written once at adopt (D944). */
|
|
20413
|
+
quantity: ReadingQuantitySchema.optional(),
|
|
20414
|
+
/** Date / time / datetime shape of a string reading, written once at adopt. */
|
|
20415
|
+
dateTimeShape: _enum([
|
|
20416
|
+
"date",
|
|
20417
|
+
"time",
|
|
20418
|
+
"datetime"
|
|
20419
|
+
]).optional(),
|
|
20080
20420
|
/** Provider-specific extras that don't fit the structured slots.
|
|
20081
20421
|
* Whitelist what goes here per provider — do NOT dump entire HA
|
|
20082
20422
|
* attribute blobs (would explode the meta JSON column). */
|
|
@@ -40989,7 +41329,8 @@ method(object({
|
|
|
40989
41329
|
"enum"
|
|
40990
41330
|
]),
|
|
40991
41331
|
enumValues: array(string()).optional(),
|
|
40992
|
-
item: boolean().optional()
|
|
41332
|
+
item: boolean().optional(),
|
|
41333
|
+
quantity: ReadingQuantitySchema.optional()
|
|
40993
41334
|
})).readonly(),
|
|
40994
41335
|
itemArray: object({
|
|
40995
41336
|
path: string(),
|
|
@@ -44789,8 +45130,8 @@ var MaskPolygonShapeSchema = object({
|
|
|
44789
45130
|
/** Boolean cell grid — row-major, length === gridWidth*gridHeight. */
|
|
44790
45131
|
var MaskGridShapeSchema = object({
|
|
44791
45132
|
kind: literal("grid"),
|
|
44792
|
-
gridWidth: number(),
|
|
44793
|
-
gridHeight: number(),
|
|
45133
|
+
gridWidth: number().meta(readingMeta("none")),
|
|
45134
|
+
gridHeight: number().meta(readingMeta("none")),
|
|
44794
45135
|
cells: array(boolean())
|
|
44795
45136
|
});
|
|
44796
45137
|
discriminatedUnion("kind", [
|
|
@@ -56184,46 +56525,27 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
|
|
|
56184
56525
|
}), LogStreamEntrySchema, { kind: "subscription" });
|
|
56185
56526
|
object({
|
|
56186
56527
|
/** Carbon dioxide concentration in ppm. */
|
|
56187
|
-
co2Ppm: number().min(0).optional(),
|
|
56528
|
+
co2Ppm: number().min(0).optional().meta(readingMeta("concentration-volume")),
|
|
56188
56529
|
/** Total volatile organic compounds in ppb. */
|
|
56189
|
-
vocPpb: number().min(0).optional(),
|
|
56530
|
+
vocPpb: number().min(0).optional().meta(readingMeta("concentration-ppb")),
|
|
56190
56531
|
/** Particulate matter ≤ 2.5 μm in µg/m³. */
|
|
56191
|
-
pm25: number().min(0).optional(),
|
|
56532
|
+
pm25: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
56192
56533
|
/** Particulate matter ≤ 10 μm in µg/m³. */
|
|
56193
|
-
pm10: number().min(0).optional(),
|
|
56534
|
+
pm10: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
56194
56535
|
/** Composite AQI value (typically 0..500). */
|
|
56195
|
-
aqi: number().optional(),
|
|
56536
|
+
aqi: number().optional().meta(readingMeta("index")),
|
|
56196
56537
|
/** Ms epoch when the slice was last updated. */
|
|
56197
|
-
lastFetchedAt: number()
|
|
56198
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
56199
|
-
* `attributes.unit_of_measurement` → 'ppm' / 'ppb' / 'µg/m³'). Each
|
|
56200
|
-
* upstream `sensor.*` entity surfaces ONE device_class, so one unit
|
|
56201
|
-
* per slice is unambiguous. */
|
|
56202
|
-
unit: string().optional(),
|
|
56203
|
-
/** Suggested decimal places for numeric display.
|
|
56204
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
56205
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
56206
|
-
* auto-formatting when absent. */
|
|
56207
|
-
precision: number().int().min(0).max(10).optional()
|
|
56538
|
+
lastFetchedAt: number()
|
|
56208
56539
|
});
|
|
56209
56540
|
DeviceType.Sensor;
|
|
56210
56541
|
object({
|
|
56211
|
-
/** Current illuminance in lux (lx). */
|
|
56212
|
-
lux: number().min(0).meta({
|
|
56213
|
-
|
|
56542
|
+
/** Current illuminance in lux (lx). `null` when the sample was refused (D393). */
|
|
56543
|
+
lux: number().min(0).nullable().meta(readingMeta("illuminance", {
|
|
56544
|
+
precision: 0,
|
|
56214
56545
|
label: "Illuminance"
|
|
56215
|
-
}),
|
|
56546
|
+
})),
|
|
56216
56547
|
/** Ms epoch when the slice was last updated. */
|
|
56217
|
-
lastFetchedAt: number()
|
|
56218
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
56219
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
56220
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
56221
|
-
unit: string().optional(),
|
|
56222
|
-
/** Suggested decimal places for numeric display.
|
|
56223
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
56224
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
56225
|
-
* auto-formatting when absent. */
|
|
56226
|
-
precision: number().int().min(0).max(10).optional()
|
|
56548
|
+
lastFetchedAt: number()
|
|
56227
56549
|
});
|
|
56228
56550
|
DeviceType.Sensor;
|
|
56229
56551
|
/**
|
|
@@ -56368,10 +56690,7 @@ var BatteryStatusSchema = object({
|
|
|
56368
56690
|
* Consumers must SKIP a null rather than coerce it — `battery-band` already
|
|
56369
56691
|
* declines to band a non-finite reading, which is the correct shape.
|
|
56370
56692
|
*/
|
|
56371
|
-
percentage: number().min(0).max(100).nullable().meta({
|
|
56372
|
-
unit: "%",
|
|
56373
|
-
label: "Charge"
|
|
56374
|
-
}),
|
|
56693
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage", { label: "Charge" })),
|
|
56375
56694
|
/**
|
|
56376
56695
|
* Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
|
|
56377
56696
|
* Reolink-specific for the Solar Panel 2 accessory (will become
|
|
@@ -56398,7 +56717,14 @@ var BatteryStatusSchema = object({
|
|
|
56398
56717
|
*/
|
|
56399
56718
|
sleeping: boolean().meta({ label: "Sleeping" }),
|
|
56400
56719
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
56401
|
-
lastUpdated: number(),
|
|
56720
|
+
lastUpdated: number().meta(readingMeta("none")),
|
|
56721
|
+
/**
|
|
56722
|
+
* Battery voltage in volts, for a cell the firmware reports as voltage
|
|
56723
|
+
* rather than a percentage (Ecowitt capacitor packs). Absent on cameras
|
|
56724
|
+
* that only report charge. A second reading on this cap, not a second
|
|
56725
|
+
* `numeric-sensor` on the same device.
|
|
56726
|
+
*/
|
|
56727
|
+
volts: number().nullable().optional().meta(readingMeta("voltage", { label: "Voltage" })),
|
|
56402
56728
|
/**
|
|
56403
56729
|
* Ms epoch of the last time the device PROVED it was reachable — a
|
|
56404
56730
|
* completed firmware round-trip, an observed wake, or an inbound push
|
|
@@ -56458,7 +56784,7 @@ object({
|
|
|
56458
56784
|
DeviceType.Sensor;
|
|
56459
56785
|
object({
|
|
56460
56786
|
/** Current level as 0..100 inclusive. Firmware-reported. */
|
|
56461
|
-
percentage: number().min(0).max(100),
|
|
56787
|
+
percentage: number().min(0).max(100).meta(readingMeta("percentage")),
|
|
56462
56788
|
/** Ms epoch of the last operator-driven change. Useful for UI freshness. */
|
|
56463
56789
|
lastChangedAt: number()
|
|
56464
56790
|
});
|
|
@@ -56843,21 +57169,21 @@ object({
|
|
|
56843
57169
|
/** Single setpoint in Celsius. Used by single-target modes
|
|
56844
57170
|
* (heat / cool / dry). Null when the device is in a range mode
|
|
56845
57171
|
* (`heat_cool`) or has no setpoint at all (`fan_only`/`off`). */
|
|
56846
|
-
target: number().nullable(),
|
|
57172
|
+
target: number().nullable().meta(readingMeta("temperature")),
|
|
56847
57173
|
/** Upper bound of the dual setpoint in Celsius. Populated only
|
|
56848
57174
|
* in `heat_cool` mode. */
|
|
56849
|
-
targetHigh: number().nullable(),
|
|
57175
|
+
targetHigh: number().nullable().meta(readingMeta("temperature")),
|
|
56850
57176
|
/** Lower bound of the dual setpoint in Celsius. Populated only
|
|
56851
57177
|
* in `heat_cool` mode. */
|
|
56852
|
-
targetLow: number().nullable(),
|
|
57178
|
+
targetLow: number().nullable().meta(readingMeta("temperature")),
|
|
56853
57179
|
/** Target relative humidity (0..100). Null when the device has no
|
|
56854
57180
|
* humidity control. */
|
|
56855
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
57181
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
56856
57182
|
/** Current measured temperature in Celsius. Read-only — pushed by
|
|
56857
57183
|
* the device's internal sensor. */
|
|
56858
|
-
currentTemp: number().nullable(),
|
|
57184
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
56859
57185
|
/** Current measured relative humidity (0..100). Read-only. */
|
|
56860
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
57186
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
56861
57187
|
/** Vertical louver swing on/off. Null when the device has no vertical
|
|
56862
57188
|
* swing surface (gate with `DeviceFeature.ClimateSwingVertical`). */
|
|
56863
57189
|
swingVertical: boolean().nullable(),
|
|
@@ -56865,11 +57191,11 @@ object({
|
|
|
56865
57191
|
* horizontal swing surface (gate with `DeviceFeature.ClimateSwingHorizontal`). */
|
|
56866
57192
|
swingHorizontal: boolean().nullable(),
|
|
56867
57193
|
/** Lowest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
56868
|
-
minTemp: number().nullable().optional(),
|
|
57194
|
+
minTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
56869
57195
|
/** Highest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
56870
|
-
maxTemp: number().nullable().optional(),
|
|
57196
|
+
maxTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
56871
57197
|
/** Setpoint granularity, Celsius (0.5, 1). Absent / null = not reported. */
|
|
56872
|
-
tempStep: number().positive().nullable().optional(),
|
|
57198
|
+
tempStep: number().positive().nullable().optional().meta(readingMeta("temperature")),
|
|
56873
57199
|
/** Ms epoch when the slice was last updated (push or command). */
|
|
56874
57200
|
lastFetchedAt: number()
|
|
56875
57201
|
});
|
|
@@ -56948,17 +57274,17 @@ DeviceType.Thermostat, DeviceType.Climate, method(object({
|
|
|
56948
57274
|
* modes to expose in the picker without a slice fetch.
|
|
56949
57275
|
*/
|
|
56950
57276
|
var RgbTripletSchema = object({
|
|
56951
|
-
r: number().int().min(0).max(255),
|
|
56952
|
-
g: number().int().min(0).max(255),
|
|
56953
|
-
b: number().int().min(0).max(255)
|
|
57277
|
+
r: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
57278
|
+
g: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
57279
|
+
b: number().int().min(0).max(255).meta(readingMeta("none"))
|
|
56954
57280
|
});
|
|
56955
57281
|
var HsvTripletSchema = object({
|
|
56956
57282
|
/** Hue in degrees, 0..360. */
|
|
56957
|
-
h: number().min(0).max(360),
|
|
57283
|
+
h: number().min(0).max(360).meta(readingMeta("none")),
|
|
56958
57284
|
/** Saturation as 0..100 inclusive. */
|
|
56959
|
-
s: number().min(0).max(100),
|
|
57285
|
+
s: number().min(0).max(100).meta(readingMeta("none")),
|
|
56960
57286
|
/** Value/brightness as 0..100 inclusive. */
|
|
56961
|
-
v: number().min(0).max(100)
|
|
57287
|
+
v: number().min(0).max(100).meta(readingMeta("none"))
|
|
56962
57288
|
});
|
|
56963
57289
|
var ColorInputSchema = discriminatedUnion("mode", [
|
|
56964
57290
|
object({
|
|
@@ -56987,7 +57313,7 @@ object({
|
|
|
56987
57313
|
/** Populated when `mode === 'hsv'`. */
|
|
56988
57314
|
hsv: HsvTripletSchema.optional(),
|
|
56989
57315
|
/** Populated when `mode === 'mired'`. */
|
|
56990
|
-
mireds: number().int().optional(),
|
|
57316
|
+
mireds: number().int().optional().meta(readingMeta("colour-temperature")),
|
|
56991
57317
|
/** Ms epoch of the last operator-driven change. */
|
|
56992
57318
|
lastChangedAt: number()
|
|
56993
57319
|
});
|
|
@@ -57111,18 +57437,12 @@ _enum([
|
|
|
57111
57437
|
"empty",
|
|
57112
57438
|
"full"
|
|
57113
57439
|
]);
|
|
57114
|
-
/**
|
|
57115
|
-
|
|
57116
|
-
|
|
57117
|
-
"days",
|
|
57118
|
-
"hours",
|
|
57119
|
-
"cycles"
|
|
57120
|
-
]);
|
|
57121
|
-
/** Remaining life as a COUNT, not a percentage (the PetKit desiccant reports
|
|
57122
|
-
* days). `value` null = unknown (D393). */
|
|
57440
|
+
/** Whether `remaining.value` is a duration in seconds or a dimensionless count. */
|
|
57441
|
+
var ConsumableRemainingKindSchema = _enum(["duration", "count"]);
|
|
57442
|
+
/** Remaining life. `value` null = unknown (D393). Duration is seconds. */
|
|
57123
57443
|
var ConsumableRemainingSchema = object({
|
|
57124
|
-
value: number().min(0).nullable(),
|
|
57125
|
-
|
|
57444
|
+
value: number().min(0).nullable().meta(readingMeta("device")),
|
|
57445
|
+
kind: ConsumableRemainingKindSchema
|
|
57126
57446
|
});
|
|
57127
57447
|
var ConsumablesStatusSchema = object({
|
|
57128
57448
|
items: array(object({
|
|
@@ -57131,7 +57451,7 @@ var ConsumablesStatusSchema = object({
|
|
|
57131
57451
|
/** Display name. */
|
|
57132
57452
|
label: string().min(1),
|
|
57133
57453
|
/** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
|
|
57134
|
-
level: number().min(0).max(100).nullable(),
|
|
57454
|
+
level: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
57135
57455
|
/** The provider's discrete verdict when known (binary mode). */
|
|
57136
57456
|
status: ConsumableStatusSchema.nullable(),
|
|
57137
57457
|
/** What the item is — decides whether low or full is bad. Absent = `wear`. */
|
|
@@ -57148,7 +57468,7 @@ var ConsumablesStatusSchema = object({
|
|
|
57148
57468
|
})),
|
|
57149
57469
|
lastChangedAt: number()
|
|
57150
57470
|
});
|
|
57151
|
-
Object.values(DeviceType), [...
|
|
57471
|
+
Object.values(DeviceType), [...ConsumableRemainingKindSchema.options], [...ConsumableStatusSchema.options], [...ConsumableKindSchema.options], [...ConsumableFormSchema.options];
|
|
57152
57472
|
Object.values(DeviceType), method(object({
|
|
57153
57473
|
deviceId: number().int().nonnegative(),
|
|
57154
57474
|
key: string().min(1)
|
|
@@ -57173,39 +57493,17 @@ object({
|
|
|
57173
57493
|
/** Current value. Numeric kind → number; select/text/datetime → string.
|
|
57174
57494
|
* Datetime values are ISO 8601 strings (full timestamp, date-only,
|
|
57175
57495
|
* or time-only — HA accepts all three forms). */
|
|
57176
|
-
value: union([number(), string()]),
|
|
57496
|
+
value: union([number().meta(readingMeta("device")), string()]),
|
|
57177
57497
|
/** Acceptable values when `kind === 'select'`. Empty for other kinds. */
|
|
57178
57498
|
options: array(string()),
|
|
57179
57499
|
/** Ms epoch when the slice was last updated. */
|
|
57180
57500
|
lastChangedAt: number(),
|
|
57181
|
-
/**
|
|
57182
|
-
|
|
57183
|
-
|
|
57184
|
-
|
|
57185
|
-
/**
|
|
57186
|
-
|
|
57187
|
-
min: number().optional(),
|
|
57188
|
-
/** Maximum allowed value. Populated live from HA `attributes.max`.
|
|
57189
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
57190
|
-
max: number().optional(),
|
|
57191
|
-
/** Step increment. Populated live from HA `attributes.step`.
|
|
57192
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
57193
|
-
step: number().optional(),
|
|
57194
|
-
/** Suggested decimal places for numeric display. Populated live from HA
|
|
57195
|
-
* `attributes.suggested_display_precision`, or derived from `step` when the
|
|
57196
|
-
* HA attribute is absent. Meaningful for `kind === 'numeric'`; absent for
|
|
57197
|
-
* other kinds. Falls back to auto-formatting when absent. */
|
|
57198
|
-
precision: number().int().min(0).max(10).optional(),
|
|
57199
|
-
/** Date-picker granularity for `kind === 'datetime'`. 'date' → date-only,
|
|
57200
|
-
* 'time' → time-only, 'datetime' → full timestamp. Absent for other kinds
|
|
57201
|
-
* (UI defaults to 'datetime'). Derived live from the device's HA domain
|
|
57202
|
-
* (date.* / time.* / datetime.*) or, for input_datetime, from the entity's
|
|
57203
|
-
* `has_date`/`has_time` attributes on each push. */
|
|
57204
|
-
format: _enum([
|
|
57205
|
-
"date",
|
|
57206
|
-
"time",
|
|
57207
|
-
"datetime"
|
|
57208
|
-
]).optional()
|
|
57501
|
+
/** Minimum allowed value, in the device quantity's base unit. */
|
|
57502
|
+
min: number().optional().meta(readingMeta("device")),
|
|
57503
|
+
/** Maximum allowed value, in the device quantity's base unit. */
|
|
57504
|
+
max: number().optional().meta(readingMeta("device")),
|
|
57505
|
+
/** Step increment, in the device quantity's base unit. */
|
|
57506
|
+
step: number().optional().meta(readingMeta("device"))
|
|
57209
57507
|
});
|
|
57210
57508
|
var ControlSetValueInputSchema = discriminatedUnion("kind", [
|
|
57211
57509
|
object({
|
|
@@ -57243,9 +57541,9 @@ object({
|
|
|
57243
57541
|
]),
|
|
57244
57542
|
/** 0 = fully closed, 100 = fully open. Null when the device has
|
|
57245
57543
|
* no intermediate position surface. */
|
|
57246
|
-
position: number().min(0).max(100).nullable(),
|
|
57544
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
57247
57545
|
/** 0 = closed slats, 100 = open slats. Null when no tilt support. */
|
|
57248
|
-
tiltPosition: number().min(0).max(100).nullable(),
|
|
57546
|
+
tiltPosition: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
57249
57547
|
/** Ms epoch when the slice was last updated. */
|
|
57250
57548
|
lastChangedAt: number()
|
|
57251
57549
|
});
|
|
@@ -57303,9 +57601,9 @@ var NormalizedRangeSchema$1 = object({
|
|
|
57303
57601
|
object({
|
|
57304
57602
|
mode: DayNightModeSchema,
|
|
57305
57603
|
/** IR-cut trigger sensitivity, NORMALIZED 0–100 (higher = switches to night sooner). */
|
|
57306
|
-
sensitivity: number().optional(),
|
|
57604
|
+
sensitivity: number().optional().meta(readingMeta("none")),
|
|
57307
57605
|
/** Delay before the IR-cut filter flips, in seconds. */
|
|
57308
|
-
switchDelaySec: number().optional(),
|
|
57606
|
+
switchDelaySec: number().optional().meta(readingMeta("duration")),
|
|
57309
57607
|
lastFetchedAt: number()
|
|
57310
57608
|
});
|
|
57311
57609
|
/**
|
|
@@ -57460,11 +57758,11 @@ object({
|
|
|
57460
57758
|
/** Feature keys of the programs the appliance currently offers — drives the UI selector. */
|
|
57461
57759
|
availablePrograms: array(string()),
|
|
57462
57760
|
/** Seconds remaining on the active cycle, or null when not running / not known. */
|
|
57463
|
-
remainingSeconds: number().int().nonnegative().nullable(),
|
|
57761
|
+
remainingSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
57464
57762
|
/** Seconds the delayed start is set to (time until the cycle starts), or null. */
|
|
57465
|
-
delayedStartSeconds: number().int().nonnegative().nullable(),
|
|
57763
|
+
delayedStartSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
57466
57764
|
/** Cycle completion 0..100, or null when not applicable. */
|
|
57467
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
57765
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
57468
57766
|
/** True when the door is reported open; null when the door state is not known. */
|
|
57469
57767
|
doorOpen: boolean().nullable(),
|
|
57470
57768
|
/** True when the door is latched (locked) during a cycle; null when not reported. */
|
|
@@ -57488,7 +57786,7 @@ object({
|
|
|
57488
57786
|
/** True while the machine-care (descaling / cleaning-program) reminder is raised; false when clear; null when not reported. */
|
|
57489
57787
|
machineCareDue: boolean().nullable(),
|
|
57490
57788
|
/** Program runs left before the machine-care reminder is due; null when the appliance does not say. */
|
|
57491
|
-
machineCareRemainingRuns: number().int().nonnegative().nullable(),
|
|
57789
|
+
machineCareRemainingRuns: number().int().nonnegative().nullable().meta(readingMeta("count")),
|
|
57492
57790
|
/** Option states: null when the appliance does not expose the option or has not said. */
|
|
57493
57791
|
halfLoad: boolean().nullable(),
|
|
57494
57792
|
hygienePlus: boolean().nullable(),
|
|
@@ -57503,7 +57801,7 @@ object({
|
|
|
57503
57801
|
/** Feature keys of the events currently raised (salt low, rinse aid low, program finished, …). */
|
|
57504
57802
|
activeEvents: array(string()),
|
|
57505
57803
|
/** Numeric error code when the appliance reports one; null otherwise. */
|
|
57506
|
-
errorCode: number().nullable(),
|
|
57804
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
57507
57805
|
/** Name of the raised alert-level event while the appliance is in error; null otherwise. */
|
|
57508
57806
|
errorLabel: string().nullable(),
|
|
57509
57807
|
/** Ms epoch of the last value received from the appliance; 0 = never. */
|
|
@@ -57649,24 +57947,14 @@ object({
|
|
|
57649
57947
|
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
57650
57948
|
lastPressedAt: number().nullable(),
|
|
57651
57949
|
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
57652
|
-
pressCountSinceStart: number()
|
|
57950
|
+
pressCountSinceStart: number().meta(readingMeta("count"))
|
|
57653
57951
|
});
|
|
57654
57952
|
object({
|
|
57655
57953
|
deviceId: number(),
|
|
57656
57954
|
timestamp: number()
|
|
57657
57955
|
});
|
|
57658
57956
|
DeviceType.Button, DeviceType.Camera;
|
|
57659
|
-
|
|
57660
|
-
* Enum-state sensor — a string value picked from a finite option set.
|
|
57661
|
-
* Drives HA `sensor` entries with `state_class: enum` (HVAC action
|
|
57662
|
-
* states, weather conditions, contact-source channels, mode strings).
|
|
57663
|
-
* The option set is stable across observations; it is persisted in the
|
|
57664
|
-
* device config blob (via the control slice at adoption) and is NOT
|
|
57665
|
-
* stored in `sourceInfo`.
|
|
57666
|
-
*/
|
|
57667
|
-
/** Locale-render shape for an ISO `value` carried by a `DateTimeSensor`-role
|
|
57668
|
-
* enum sensor: `date` (date-only), `time` (time-only), `datetime` (both). */
|
|
57669
|
-
var EnumSensorDateTimeFormatSchema = _enum([
|
|
57957
|
+
_enum([
|
|
57670
57958
|
"date",
|
|
57671
57959
|
"time",
|
|
57672
57960
|
"datetime"
|
|
@@ -57674,12 +57962,11 @@ var EnumSensorDateTimeFormatSchema = _enum([
|
|
|
57674
57962
|
object({
|
|
57675
57963
|
value: string(),
|
|
57676
57964
|
/**
|
|
57677
|
-
* Set
|
|
57678
|
-
* as
|
|
57679
|
-
*
|
|
57680
|
-
* a time-only sensor → `'time'`.
|
|
57965
|
+
* Set when `value` is a timestamp rather than an enum state, so history
|
|
57966
|
+
* does not learn ISO strings as states. The display shape (date / time /
|
|
57967
|
+
* datetime) lives on `SourceInfo.dateTimeShape`, written once at adopt.
|
|
57681
57968
|
*/
|
|
57682
|
-
|
|
57969
|
+
timestamp: boolean().optional(),
|
|
57683
57970
|
/** Ms epoch when the slice was last updated. */
|
|
57684
57971
|
lastFetchedAt: number()
|
|
57685
57972
|
});
|
|
@@ -57698,13 +57985,13 @@ var EventFireSchema = object({
|
|
|
57698
57985
|
deviceId: number(),
|
|
57699
57986
|
eventType: string(),
|
|
57700
57987
|
data: record(string(), unknown()).nullable(),
|
|
57701
|
-
timestamp: number(),
|
|
57702
|
-
seq: number()
|
|
57988
|
+
timestamp: number().meta(readingMeta("none")),
|
|
57989
|
+
seq: number().meta(readingMeta("count"))
|
|
57703
57990
|
});
|
|
57704
57991
|
object({
|
|
57705
57992
|
eventTypes: array(string()),
|
|
57706
57993
|
lastEvent: EventFireSchema.nullable(),
|
|
57707
|
-
eventCountSinceStart: number()
|
|
57994
|
+
eventCountSinceStart: number().meta(readingMeta("count"))
|
|
57708
57995
|
});
|
|
57709
57996
|
DeviceType.EventEmitter;
|
|
57710
57997
|
var IdentitySchema = object({
|
|
@@ -58093,10 +58380,10 @@ var FanDirectionSchema = _enum(["forward", "reverse"]);
|
|
|
58093
58380
|
object({
|
|
58094
58381
|
/** Active speed as 0..100 inclusive. Null when the device has no
|
|
58095
58382
|
* speed surface (single-speed fan). */
|
|
58096
|
-
percentage: number().min(0).max(100).nullable(),
|
|
58383
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58097
58384
|
/** Speed granularity the device accepts (HA `percentage_step`, e.g. 25 for
|
|
58098
58385
|
* a 4-speed fan). Absent when unknown — the UI then falls back to step 1. */
|
|
58099
|
-
percentageStep: number().positive().optional(),
|
|
58386
|
+
percentageStep: number().positive().optional().meta(readingMeta("percentage")),
|
|
58100
58387
|
/** Active preset mode (`auto` / `quiet` / `turbo` / vendor-specific)
|
|
58101
58388
|
* — empty string when no preset is active or supported. */
|
|
58102
58389
|
preset: string(),
|
|
@@ -58178,7 +58465,7 @@ var FeatureProbeStatusSchema = object({
|
|
|
58178
58465
|
/** Camera/firmware model string. `null` when the firmware doesn't expose it. */
|
|
58179
58466
|
model: string().nullable(),
|
|
58180
58467
|
/** Channel count for NVR/Hub devices; `1` for standalone cameras; `null` pre-probe. */
|
|
58181
|
-
channelCount: number().nullable(),
|
|
58468
|
+
channelCount: number().nullable().meta(readingMeta("count")),
|
|
58182
58469
|
/**
|
|
58183
58470
|
* Ms epoch of the last SUCCESSFUL probe. `0` before the first probe
|
|
58184
58471
|
* completes — drivers' `getAccessoryChildren()` should treat zero as
|
|
@@ -58210,9 +58497,27 @@ object({
|
|
|
58210
58497
|
lastChangedAt: number()
|
|
58211
58498
|
});
|
|
58212
58499
|
DeviceType.Sensor;
|
|
58500
|
+
object({
|
|
58501
|
+
/** Members whose current value entered the aggregate. */
|
|
58502
|
+
included: number().int().nonnegative().meta(readingMeta("count", {
|
|
58503
|
+
precision: 0,
|
|
58504
|
+
label: "Reporting"
|
|
58505
|
+
})),
|
|
58506
|
+
/** Members left out: offline, unknown, or not a finite reading (D393). */
|
|
58507
|
+
excluded: number().int().nonnegative().meta(readingMeta("count", {
|
|
58508
|
+
precision: 0,
|
|
58509
|
+
label: "Excluded"
|
|
58510
|
+
})),
|
|
58511
|
+
/** `included` + `excluded`. */
|
|
58512
|
+
total: number().int().nonnegative().meta(readingMeta("count", {
|
|
58513
|
+
precision: 0,
|
|
58514
|
+
label: "Members"
|
|
58515
|
+
}))
|
|
58516
|
+
});
|
|
58517
|
+
DeviceType.Sensor;
|
|
58213
58518
|
object({
|
|
58214
58519
|
/** Radiator valve opening 0 (closed) .. 100 (open). Null = not yet known. */
|
|
58215
|
-
position: number().min(0).max(100).nullable(),
|
|
58520
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58216
58521
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
58217
58522
|
lastFetchedAt: number()
|
|
58218
58523
|
});
|
|
@@ -58221,9 +58526,9 @@ object({
|
|
|
58221
58526
|
/** Whether the humidifier is currently on. */
|
|
58222
58527
|
on: boolean(),
|
|
58223
58528
|
/** Current measured relative humidity (0..100). Null when not reported. */
|
|
58224
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
58529
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
58225
58530
|
/** Target relative humidity (0..100). Null when no setpoint surface. */
|
|
58226
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
58531
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
58227
58532
|
/** Active mode (`auto` / `normal` / `baby` / vendor). Null when the
|
|
58228
58533
|
* device has no mode surface. */
|
|
58229
58534
|
mode: string().nullable(),
|
|
@@ -58233,9 +58538,9 @@ object({
|
|
|
58233
58538
|
* `idle` / `off`). Null when the device doesn't report it. */
|
|
58234
58539
|
action: string().nullable(),
|
|
58235
58540
|
/** HA `min_humidity` attribute. Null → UI uses 0. */
|
|
58236
|
-
minHumidity: number().nullable(),
|
|
58541
|
+
minHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
58237
58542
|
/** HA `max_humidity` attribute. Null → UI uses 100. */
|
|
58238
|
-
maxHumidity: number().nullable(),
|
|
58543
|
+
maxHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
58239
58544
|
/** Ms epoch when the slice was last updated. */
|
|
58240
58545
|
lastChangedAt: number()
|
|
58241
58546
|
});
|
|
@@ -58259,22 +58564,13 @@ DeviceType.Humidifier, method(object({
|
|
|
58259
58564
|
auth: "protected"
|
|
58260
58565
|
});
|
|
58261
58566
|
object({
|
|
58262
|
-
/** Current relative humidity, 0..100. */
|
|
58263
|
-
percent: number().min(0).max(100).meta({
|
|
58264
|
-
|
|
58567
|
+
/** Current relative humidity, 0..100. `null` when the sample was refused (D393). */
|
|
58568
|
+
percent: number().min(0).max(100).nullable().meta(readingMeta("humidity", {
|
|
58569
|
+
precision: 0,
|
|
58265
58570
|
label: "Humidity"
|
|
58266
|
-
}),
|
|
58571
|
+
})),
|
|
58267
58572
|
/** Ms epoch when the slice was last updated. */
|
|
58268
|
-
lastFetchedAt: number()
|
|
58269
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
58270
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
58271
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
58272
|
-
unit: string().optional(),
|
|
58273
|
-
/** Suggested decimal places for numeric display.
|
|
58274
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
58275
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
58276
|
-
* auto-formatting when absent. */
|
|
58277
|
-
precision: number().int().min(0).max(10).optional()
|
|
58573
|
+
lastFetchedAt: number()
|
|
58278
58574
|
});
|
|
58279
58575
|
DeviceType.Sensor, DeviceType.Thermostat;
|
|
58280
58576
|
object({
|
|
@@ -58282,7 +58578,7 @@ object({
|
|
|
58282
58578
|
* entity exposes no `entity_picture` (yet). */
|
|
58283
58579
|
url: string().nullable(),
|
|
58284
58580
|
/** Ms epoch of the upstream last-updated timestamp. Null at cold-start. */
|
|
58285
|
-
lastUpdated: number().nullable()
|
|
58581
|
+
lastUpdated: number().nullable().meta(readingMeta("none"))
|
|
58286
58582
|
});
|
|
58287
58583
|
DeviceType.Image;
|
|
58288
58584
|
/**
|
|
@@ -58338,19 +58634,19 @@ var NormalizedRangeSchema = object({
|
|
|
58338
58634
|
});
|
|
58339
58635
|
object({
|
|
58340
58636
|
/** Normalized 0–100. */
|
|
58341
|
-
brightness: number().optional(),
|
|
58637
|
+
brightness: number().optional().meta(readingMeta("none")),
|
|
58342
58638
|
/** Normalized 0–100. */
|
|
58343
|
-
contrast: number().optional(),
|
|
58639
|
+
contrast: number().optional().meta(readingMeta("none")),
|
|
58344
58640
|
/** Normalized 0–100. */
|
|
58345
|
-
saturation: number().optional(),
|
|
58641
|
+
saturation: number().optional().meta(readingMeta("none")),
|
|
58346
58642
|
/** Normalized 0–100. */
|
|
58347
|
-
sharpness: number().optional(),
|
|
58643
|
+
sharpness: number().optional().meta(readingMeta("none")),
|
|
58348
58644
|
mirror: boolean().optional(),
|
|
58349
58645
|
flip: boolean().optional(),
|
|
58350
58646
|
rotate: ImageRotateSchema.optional(),
|
|
58351
58647
|
whiteBalance: WhiteBalanceModeSchema.optional(),
|
|
58352
58648
|
/** Manual white-balance warmth, NORMALIZED 0–100. Meaningful only when `whiteBalance === 'manual'`. */
|
|
58353
|
-
warmth: number().optional(),
|
|
58649
|
+
warmth: number().optional().meta(readingMeta("none")),
|
|
58354
58650
|
exposureMode: ExposureModeSchema.optional(),
|
|
58355
58651
|
backlightMode: BacklightModeSchema.optional(),
|
|
58356
58652
|
lastFetchedAt: number()
|
|
@@ -58595,10 +58891,10 @@ var IntercomAbilitySchema = object({
|
|
|
58595
58891
|
/** Codecs accepted by firmware, in preference order. Driver-authored strings. */
|
|
58596
58892
|
codecs: array(string()),
|
|
58597
58893
|
/** Sample rate (Hz) the firmware expects. Reolink typical: 16000. */
|
|
58598
|
-
sampleRate: number(),
|
|
58894
|
+
sampleRate: number().meta(readingMeta("none")),
|
|
58599
58895
|
duplex: _enum(["half", "full"]),
|
|
58600
58896
|
/** Max in-flight audio backlog before drop (ms). Server uses this to bound latency. */
|
|
58601
|
-
maxBacklogMs: number()
|
|
58897
|
+
maxBacklogMs: number().meta(readingMeta("duration-ms"))
|
|
58602
58898
|
});
|
|
58603
58899
|
var IntercomStatusSchema = object({
|
|
58604
58900
|
/** True while a talk session is open. */
|
|
@@ -58709,13 +59005,13 @@ object({
|
|
|
58709
59005
|
activity: LawnMowerActivitySchema,
|
|
58710
59006
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
58711
59007
|
* reading. */
|
|
58712
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
59008
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58713
59009
|
/** 0..100 mowing-completion percentage of the current task, or null when no
|
|
58714
59010
|
* task is active / progress is unavailable. */
|
|
58715
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
59011
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58716
59012
|
/** Current device/event code (dynamic — mostly status, sometimes an error),
|
|
58717
59013
|
* or null when unknown. */
|
|
58718
|
-
currentCode: number().nullable(),
|
|
59014
|
+
currentCode: number().nullable().meta(readingMeta("none")),
|
|
58719
59015
|
/** Human label for {@link currentCode}, or null when undecodable. */
|
|
58720
59016
|
currentCodeLabel: string().nullable(),
|
|
58721
59017
|
/** Severity of {@link currentCode}. `error` (and often `warning`) warrants UI
|
|
@@ -59177,7 +59473,7 @@ object({
|
|
|
59177
59473
|
state: MediaPlayerStateSchema,
|
|
59178
59474
|
/** Volume as 0..100 inclusive. Null when the device has no volume
|
|
59179
59475
|
* surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
|
|
59180
|
-
volumeLevel: number().min(0).max(100).nullable(),
|
|
59476
|
+
volumeLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59181
59477
|
/** Mute toggle distinct from volume=0. Null when no mute surface.
|
|
59182
59478
|
* Pair with `DeviceFeature.MediaPlayerMute`. */
|
|
59183
59479
|
isMuted: boolean().nullable(),
|
|
@@ -59190,10 +59486,10 @@ object({
|
|
|
59190
59486
|
currentMedia: MediaInfoSchema.nullable(),
|
|
59191
59487
|
/** Current playback position in ms. Null when not seekable or
|
|
59192
59488
|
* nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
|
|
59193
|
-
positionMs: number().int().nonnegative().nullable(),
|
|
59489
|
+
positionMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
59194
59490
|
/** Total duration of the current media in ms. Null when unknown
|
|
59195
59491
|
* (live stream) or nothing is playing. */
|
|
59196
|
-
durationMs: number().int().nonnegative().nullable(),
|
|
59492
|
+
durationMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
59197
59493
|
/** Shuffle toggle. Null when no shuffle surface.
|
|
59198
59494
|
* Pair with `DeviceFeature.MediaPlayerShuffle`. */
|
|
59199
59495
|
shuffle: boolean().nullable(),
|
|
@@ -59493,7 +59789,7 @@ object({
|
|
|
59493
59789
|
* it, every provider seeded it at boot, and every session left it
|
|
59494
59790
|
* `detected: true` after its detach.
|
|
59495
59791
|
*/
|
|
59496
|
-
autoClearAfterMs: number().nullable()
|
|
59792
|
+
autoClearAfterMs: number().nullable().meta(readingMeta("duration-ms"))
|
|
59497
59793
|
});
|
|
59498
59794
|
/**
|
|
59499
59795
|
* Payload of `motion.onMotionChanged` event + the corresponding bus
|
|
@@ -59543,7 +59839,7 @@ var MotionZoneRegionSchema = object({
|
|
|
59543
59839
|
});
|
|
59544
59840
|
object({
|
|
59545
59841
|
enabled: boolean(),
|
|
59546
|
-
sensitivity: number(),
|
|
59842
|
+
sensitivity: number().meta(readingMeta("none")),
|
|
59547
59843
|
/** Grid region(s). Today exactly one `grid` shape. */
|
|
59548
59844
|
regions: array(MotionZoneRegionSchema),
|
|
59549
59845
|
lastFetchedAt: number()
|
|
@@ -59847,7 +60143,7 @@ var NavigationStatusSchema = object({
|
|
|
59847
60143
|
following: boolean(),
|
|
59848
60144
|
flash: boolean(),
|
|
59849
60145
|
lightMode: NavigationLightModeSchema,
|
|
59850
|
-
lightLevel: number().min(40).max(100),
|
|
60146
|
+
lightLevel: number().min(40).max(100).meta(readingMeta("none")),
|
|
59851
60147
|
/** Ms epoch when the slice was last updated. */
|
|
59852
60148
|
lastChangedAt: number()
|
|
59853
60149
|
});
|
|
@@ -59893,13 +60189,13 @@ var NetworkLinkStatusSchema = object({
|
|
|
59893
60189
|
* one whose reading has not landed must not be drawn at 0 %. Consumers
|
|
59894
60190
|
* SKIP a null rather than coerce it.
|
|
59895
60191
|
*/
|
|
59896
|
-
signalPercent: number().min(0).max(100).nullable(),
|
|
60192
|
+
signalPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59897
60193
|
/** Raw received signal strength in dBm, when the firmware reports one. */
|
|
59898
|
-
rssiDbm: number().optional(),
|
|
60194
|
+
rssiDbm: number().optional().meta(readingMeta("signal-level")),
|
|
59899
60195
|
/** Network name of a wireless link, when the firmware reports it. */
|
|
59900
60196
|
ssid: string().optional(),
|
|
59901
60197
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
59902
|
-
lastUpdated: number()
|
|
60198
|
+
lastUpdated: number().meta(readingMeta("none"))
|
|
59903
60199
|
});
|
|
59904
60200
|
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.Light, DeviceType.Lock, DeviceType.Siren, object({
|
|
59905
60201
|
deviceId: number(),
|
|
@@ -60218,7 +60514,7 @@ object({
|
|
|
60218
60514
|
lastError: string().nullable(),
|
|
60219
60515
|
/** Number of deliveries currently buffered server-side (rate-limited
|
|
60220
60516
|
* notifiers may queue). 0 when the provider sends synchronously. */
|
|
60221
|
-
queueDepth: number().int().nonnegative(),
|
|
60517
|
+
queueDepth: number().int().nonnegative().meta(readingMeta("count")),
|
|
60222
60518
|
/** Per-feature capability matrix — authoritative source for the
|
|
60223
60519
|
* compose-form field gating. */
|
|
60224
60520
|
supports: NotifierSupportsSchema
|
|
@@ -60268,15 +60564,8 @@ DeviceType.Notifier, method(NotifierSendInputSchema, NotifierSendResultSchema, {
|
|
|
60268
60564
|
acceptedAt: number()
|
|
60269
60565
|
});
|
|
60270
60566
|
object({
|
|
60271
|
-
|
|
60272
|
-
|
|
60273
|
-
* Populated live from the upstream source on each state push.
|
|
60274
|
-
* Absent for unitless sensors. */
|
|
60275
|
-
unit: string().optional(),
|
|
60276
|
-
/** Suggested decimal places for numeric display.
|
|
60277
|
-
* Populated live from the upstream source when provided.
|
|
60278
|
-
* Falls back to auto-formatting when absent. */
|
|
60279
|
-
precision: number().int().min(0).max(10).optional(),
|
|
60567
|
+
/** Reading in the device quantity's base unit. `null` when refused (D393). */
|
|
60568
|
+
value: number().nullable().meta(readingMeta("device")),
|
|
60280
60569
|
/** Ms epoch when the slice was last updated. */
|
|
60281
60570
|
lastFetchedAt: number()
|
|
60282
60571
|
});
|
|
@@ -60566,23 +60855,26 @@ object({
|
|
|
60566
60855
|
/** Food currently in the bowl (grams). Null when the device has not
|
|
60567
60856
|
* reported a reading yet. On dual-hopper models this is the combined
|
|
60568
60857
|
* bowl reading; per-hopper levels live in `food1`/`food2`. */
|
|
60569
|
-
foodLevel: number().nullable(),
|
|
60858
|
+
foodLevel: number().nullable().meta(readingMeta("none")),
|
|
60570
60859
|
/** Hopper-1 food level (grams) on dual-hopper feeders; null on
|
|
60571
60860
|
* single-hopper models. */
|
|
60572
|
-
food1: number().nullable(),
|
|
60861
|
+
food1: number().nullable().meta(readingMeta("none")),
|
|
60573
60862
|
/** Hopper-2 food level (grams) on dual-hopper feeders; null on
|
|
60574
60863
|
* single-hopper models. */
|
|
60575
|
-
food2: number().nullable(),
|
|
60864
|
+
food2: number().nullable().meta(readingMeta("none")),
|
|
60576
60865
|
/** Derived low-food flag — mirrors the HA `food_level` binary_sensor
|
|
60577
60866
|
* (`device_class: problem`, on = low). True when the bowl is empty /
|
|
60578
60867
|
* below the feeder's low threshold. */
|
|
60579
60868
|
lowFood: boolean(),
|
|
60580
60869
|
/** Battery charge 0..100 (%). Null on mains-powered models or when the
|
|
60581
60870
|
* device has no battery reading. */
|
|
60582
|
-
batteryPower: number().min(0).max(100).nullable(),
|
|
60583
|
-
/**
|
|
60584
|
-
*
|
|
60585
|
-
|
|
60871
|
+
batteryPower: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
60872
|
+
/**
|
|
60873
|
+
* Desiccant life remaining, stored in seconds (duration base, D944).
|
|
60874
|
+
* Providers convert from the days the feeder reports. Null when the
|
|
60875
|
+
* model has no desiccant sensor.
|
|
60876
|
+
*/
|
|
60877
|
+
desiccantLeftDays: number().nullable().meta(readingMeta("duration")),
|
|
60586
60878
|
/** True while a feed is in progress. */
|
|
60587
60879
|
feeding: boolean(),
|
|
60588
60880
|
/** Decoded connectivity / power status (HA petkit device-status enum).
|
|
@@ -60593,7 +60885,7 @@ object({
|
|
|
60593
60885
|
* with `errorCode` for consumers that want the raw integer. */
|
|
60594
60886
|
error: string().nullable(),
|
|
60595
60887
|
/** Raw device error code (0 / null = no error). */
|
|
60596
|
-
errorCode: number().nullable(),
|
|
60888
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
60597
60889
|
/** True for D4S/D4SH dual-hopper hardware — gates the per-hopper UI. */
|
|
60598
60890
|
isDualHopper: boolean(),
|
|
60599
60891
|
/** Child-lock (manual-lock) setting — buttons on the unit are disabled. */
|
|
@@ -60603,7 +60895,7 @@ object({
|
|
|
60603
60895
|
/** Play a chime when dispensing. */
|
|
60604
60896
|
feedSound: boolean(),
|
|
60605
60897
|
/** Speaker / prompt volume level (device-scaled integer). */
|
|
60606
|
-
volume: number(),
|
|
60898
|
+
volume: number().meta(readingMeta("none")),
|
|
60607
60899
|
/** Ms epoch when the slice was last refreshed from the cloud. */
|
|
60608
60900
|
lastFetchedAt: number()
|
|
60609
60901
|
});
|
|
@@ -61040,36 +61332,19 @@ method(_void(), PlatformCapabilitiesSchema), method(_void(), HardwareInfoSchema)
|
|
|
61040
61332
|
});
|
|
61041
61333
|
object({
|
|
61042
61334
|
/** Instantaneous power draw in watts. */
|
|
61043
|
-
watts: number().optional().meta({
|
|
61044
|
-
unit: "W",
|
|
61045
|
-
label: "Power"
|
|
61046
|
-
}),
|
|
61335
|
+
watts: number().optional().meta(readingMeta("power", { label: "Power" })),
|
|
61047
61336
|
/** Cumulative energy in kilowatt-hours since the meter was reset. */
|
|
61048
|
-
kwhTotal: number().optional().meta({
|
|
61049
|
-
unit: "kWh",
|
|
61050
|
-
label: "Energy"
|
|
61051
|
-
}),
|
|
61337
|
+
kwhTotal: number().optional().meta(readingMeta("energy", { label: "Energy" })),
|
|
61052
61338
|
/** Voltage in volts. */
|
|
61053
|
-
volts: number().optional(),
|
|
61339
|
+
volts: number().optional().meta(readingMeta("voltage")),
|
|
61054
61340
|
/** Current in amperes. */
|
|
61055
|
-
amps: number().optional(),
|
|
61056
|
-
/** Apparent power in volt-amperes
|
|
61057
|
-
va: number().optional(),
|
|
61341
|
+
amps: number().optional().meta(readingMeta("current")),
|
|
61342
|
+
/** Apparent power in volt-amperes. */
|
|
61343
|
+
va: number().optional().meta(readingMeta("apparent-power")),
|
|
61058
61344
|
/** Power factor (0..1) if reported. */
|
|
61059
|
-
powerFactor: number().min(0).max(1).optional(),
|
|
61345
|
+
powerFactor: number().min(0).max(1).optional().meta(readingMeta("ratio")),
|
|
61060
61346
|
/** Ms epoch when the slice was last updated. */
|
|
61061
|
-
lastFetchedAt: number()
|
|
61062
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
61063
|
-
* `attributes.unit_of_measurement` → 'V' / 'A' / 'W' / 'kW' / 'kWh').
|
|
61064
|
-
* Each upstream `sensor.*` entity surfaces ONE device_class, so one
|
|
61065
|
-
* unit per slice is unambiguous. The UI prefers this over the role's
|
|
61066
|
-
* canonical unit so a 'kW' / 'Wh' feed renders verbatim. */
|
|
61067
|
-
unit: string().optional(),
|
|
61068
|
-
/** Suggested decimal places for numeric display.
|
|
61069
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
61070
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
61071
|
-
* auto-formatting when absent. */
|
|
61072
|
-
precision: number().int().min(0).max(10).optional()
|
|
61347
|
+
lastFetchedAt: number()
|
|
61073
61348
|
});
|
|
61074
61349
|
DeviceType.Sensor;
|
|
61075
61350
|
/**
|
|
@@ -61090,11 +61365,11 @@ DeviceType.Sensor;
|
|
|
61090
61365
|
*/
|
|
61091
61366
|
var GpsLocationSchema = object({
|
|
61092
61367
|
/** Latitude in decimal degrees, -90..90. */
|
|
61093
|
-
latitude: number().min(-90).max(90),
|
|
61368
|
+
latitude: number().min(-90).max(90).meta(readingMeta("angle")),
|
|
61094
61369
|
/** Longitude in decimal degrees, -180..180. */
|
|
61095
|
-
longitude: number().min(-180).max(180),
|
|
61370
|
+
longitude: number().min(-180).max(180).meta(readingMeta("angle")),
|
|
61096
61371
|
/** Reported accuracy in meters (lower = better). */
|
|
61097
|
-
accuracyMeters: number().nonnegative()
|
|
61372
|
+
accuracyMeters: number().nonnegative().meta(readingMeta("length"))
|
|
61098
61373
|
});
|
|
61099
61374
|
object({
|
|
61100
61375
|
/** `home` / `not_home` / any user-defined zone name. */
|
|
@@ -61106,25 +61381,16 @@ object({
|
|
|
61106
61381
|
gps: GpsLocationSchema.nullable(),
|
|
61107
61382
|
/** Optional battery level of the tracking device (0..100). Null
|
|
61108
61383
|
* when not reported. */
|
|
61109
|
-
batteryPercent: number().min(0).max(100).nullable(),
|
|
61384
|
+
batteryPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61110
61385
|
/** Ms epoch when the slice was last updated. */
|
|
61111
61386
|
lastChangedAt: number()
|
|
61112
61387
|
});
|
|
61113
61388
|
DeviceType.Presence;
|
|
61114
61389
|
object({
|
|
61115
|
-
/** Current pressure in hPa. */
|
|
61116
|
-
hpa: number(),
|
|
61390
|
+
/** Current pressure in hPa. `null` when the sample was refused (D393). */
|
|
61391
|
+
hpa: number().nullable().meta(readingMeta("pressure", { precision: 0 })),
|
|
61117
61392
|
/** Ms epoch when the slice was last updated. */
|
|
61118
|
-
lastFetchedAt: number()
|
|
61119
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
61120
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
61121
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
61122
|
-
unit: string().optional(),
|
|
61123
|
-
/** Suggested decimal places for numeric display.
|
|
61124
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
61125
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
61126
|
-
* auto-formatting when absent. */
|
|
61127
|
-
precision: number().int().min(0).max(10).optional()
|
|
61393
|
+
lastFetchedAt: number()
|
|
61128
61394
|
});
|
|
61129
61395
|
DeviceType.Sensor;
|
|
61130
61396
|
/**
|
|
@@ -61457,8 +61723,8 @@ DeviceType.Camera, method(PtzMoveCommandSchema.extend({ deviceId: number() }), _
|
|
|
61457
61723
|
}), _void(), { kind: "mutation" });
|
|
61458
61724
|
var PtzAutotrackSettingsSchema = object({
|
|
61459
61725
|
targetType: string().describe("Vendor target string (people/vehicle/pet); empty = camera default"),
|
|
61460
|
-
stopDelaySeconds: number().int().min(0).max(300),
|
|
61461
|
-
disappearDelaySeconds: number().int().min(0).max(300)
|
|
61726
|
+
stopDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration")),
|
|
61727
|
+
disappearDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration"))
|
|
61462
61728
|
});
|
|
61463
61729
|
/**
|
|
61464
61730
|
* One option the camera advertises as a valid `targetType`. Drivers
|
|
@@ -61515,7 +61781,7 @@ object({
|
|
|
61515
61781
|
/** null = unknown — never coerced to false (D393). */
|
|
61516
61782
|
running: boolean().nullable(),
|
|
61517
61783
|
/** Epoch ms the current boolean began; null while `running` is null. */
|
|
61518
|
-
since: number().nullable(),
|
|
61784
|
+
since: number().nullable().meta(readingMeta("none")),
|
|
61519
61785
|
source: RunningStateSourceSchema.meta({ label: "Source" }),
|
|
61520
61786
|
phase: string().nullable(),
|
|
61521
61787
|
/** null until a reading has been published (D393). */
|
|
@@ -62713,9 +62979,9 @@ var RecordTriggerSchema = _enum([
|
|
|
62713
62979
|
*/
|
|
62714
62980
|
var RecordWindowSchema = object({
|
|
62715
62981
|
trigger: RecordTriggerSchema,
|
|
62716
|
-
day: number().int().min(0).max(6),
|
|
62717
|
-
startMinute: number().int().min(0).max(1439),
|
|
62718
|
-
endMinute: number().int().min(1).max(1440)
|
|
62982
|
+
day: number().int().min(0).max(6).meta(readingMeta("none")),
|
|
62983
|
+
startMinute: number().int().min(0).max(1439).meta(readingMeta("none")),
|
|
62984
|
+
endMinute: number().int().min(1).max(1440).meta(readingMeta("none"))
|
|
62719
62985
|
});
|
|
62720
62986
|
/** Status of one physical volume, as the camera itself describes it. */
|
|
62721
62987
|
var OnboardStorageVolumeSchema = object({
|
|
@@ -62784,10 +63050,10 @@ object({
|
|
|
62784
63050
|
/** Master "record to the card at all" switch. */
|
|
62785
63051
|
enabled: boolean().nullable(),
|
|
62786
63052
|
overwriteWhenFull: boolean().nullable(),
|
|
62787
|
-
preRecordSec: number().nullable(),
|
|
62788
|
-
postRecordSec: number().nullable(),
|
|
63053
|
+
preRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
63054
|
+
postRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
62789
63055
|
/** Length of one recorded file, in minutes. */
|
|
62790
|
-
segmentMinutes: number().nullable(),
|
|
63056
|
+
segmentMinutes: number().nullable().meta(readingMeta("none")),
|
|
62791
63057
|
/** The primary track's weekly windows, flattened. */
|
|
62792
63058
|
windows: array(RecordWindowSchema),
|
|
62793
63059
|
/**
|
|
@@ -62803,7 +63069,7 @@ object({
|
|
|
62803
63069
|
* provider reporting a non-zero count also reports the schedule as not
|
|
62804
63070
|
* writable.
|
|
62805
63071
|
*/
|
|
62806
|
-
unreadableWindows: number(),
|
|
63072
|
+
unreadableWindows: number().meta(readingMeta("count")),
|
|
62807
63073
|
/**
|
|
62808
63074
|
* The camera is scheduled to record and has NO usable storage.
|
|
62809
63075
|
*
|
|
@@ -63440,7 +63706,7 @@ var CamStreamDescriptorSchema = object({
|
|
|
63440
63706
|
url: string().optional(),
|
|
63441
63707
|
codec: string().optional(),
|
|
63442
63708
|
resolution: CamStreamResolutionSchema.optional(),
|
|
63443
|
-
fps: number().positive().optional(),
|
|
63709
|
+
fps: number().positive().optional().meta(readingMeta("rate")),
|
|
63444
63710
|
label: string().optional(),
|
|
63445
63711
|
/** Device-level features (e.g. `battery-operated`) — drives broker policy. */
|
|
63446
63712
|
deviceFeatures: array(string()).optional(),
|
|
@@ -63470,18 +63736,18 @@ var StreamProfileSchema = _enum([
|
|
|
63470
63736
|
]);
|
|
63471
63737
|
/** The current encoding config of one stream profile. */
|
|
63472
63738
|
var StreamProfileConfigSchema = object({
|
|
63473
|
-
width: number(),
|
|
63474
|
-
height: number(),
|
|
63739
|
+
width: number().meta(readingMeta("none")),
|
|
63740
|
+
height: number().meta(readingMeta("none")),
|
|
63475
63741
|
codec: _enum(["h264", "h265"]),
|
|
63476
|
-
framerate: number(),
|
|
63477
|
-
bitrate: number(),
|
|
63742
|
+
framerate: number().meta(readingMeta("rate")),
|
|
63743
|
+
bitrate: number().meta(readingMeta("bitrate")),
|
|
63478
63744
|
bitrateMode: _enum(["vbr", "cbr"]).optional(),
|
|
63479
63745
|
encoderProfile: _enum([
|
|
63480
63746
|
"high",
|
|
63481
63747
|
"main",
|
|
63482
63748
|
"baseline"
|
|
63483
63749
|
]).optional(),
|
|
63484
|
-
gop: number().optional(),
|
|
63750
|
+
gop: number().optional().meta(readingMeta("none")),
|
|
63485
63751
|
/**
|
|
63486
63752
|
* Whether THIS profile currently carries an audio track. READ-ONLY here.
|
|
63487
63753
|
*
|
|
@@ -64124,23 +64390,13 @@ object({
|
|
|
64124
64390
|
});
|
|
64125
64391
|
DeviceType.Sensor;
|
|
64126
64392
|
object({
|
|
64127
|
-
/** Current temperature in Celsius. */
|
|
64128
|
-
celsius: number().meta({
|
|
64129
|
-
|
|
64393
|
+
/** Current temperature in Celsius. `null` when the sample was refused (D393). */
|
|
64394
|
+
celsius: number().nullable().meta(readingMeta("temperature", {
|
|
64395
|
+
precision: 1,
|
|
64130
64396
|
label: "Temperature"
|
|
64131
|
-
}),
|
|
64397
|
+
})),
|
|
64132
64398
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
64133
|
-
lastFetchedAt: number()
|
|
64134
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
64135
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
64136
|
-
* role's canonical unit, so a Fahrenheit feed renders '°F' not '°C'.
|
|
64137
|
-
* Absent → the UI falls back to the role's canonical unit. */
|
|
64138
|
-
unit: string().optional(),
|
|
64139
|
-
/** Suggested decimal places for numeric display.
|
|
64140
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
64141
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
64142
|
-
* auto-formatting when absent. */
|
|
64143
|
-
precision: number().int().min(0).max(10).optional()
|
|
64399
|
+
lastFetchedAt: number()
|
|
64144
64400
|
});
|
|
64145
64401
|
DeviceType.Sensor, DeviceType.Thermostat;
|
|
64146
64402
|
/**
|
|
@@ -64392,16 +64648,16 @@ object({
|
|
|
64392
64648
|
]),
|
|
64393
64649
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
64394
64650
|
* reading. */
|
|
64395
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
64651
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
64396
64652
|
/** Current fan-speed token (provider-verbatim). Null when unknown or
|
|
64397
64653
|
* the vacuum has no speed control. */
|
|
64398
64654
|
fanSpeed: string().nullable(),
|
|
64399
64655
|
/** Speed tokens the hardware accepts — drives the UI selector. */
|
|
64400
64656
|
availableFanSpeeds: array(string()),
|
|
64401
64657
|
/** 0..100 cleaning-completion percentage of the current task, or null. */
|
|
64402
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
64658
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
64403
64659
|
/** Current error code (0 / null = no error). */
|
|
64404
|
-
errorCode: number().nullable(),
|
|
64660
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
64405
64661
|
/** Human label for {@link errorCode}, or null when none / undecodable. */
|
|
64406
64662
|
errorLabel: string().nullable(),
|
|
64407
64663
|
/** Ms epoch when the slice was last updated. */
|
|
@@ -64440,7 +64696,7 @@ object({
|
|
|
64440
64696
|
]),
|
|
64441
64697
|
/** 0 = fully closed, 100 = fully open. Null when the device has no
|
|
64442
64698
|
* intermediate position surface. */
|
|
64443
|
-
position: number().min(0).max(100).nullable(),
|
|
64699
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
64444
64700
|
/** Ms epoch when the slice was last updated. */
|
|
64445
64701
|
lastChangedAt: number()
|
|
64446
64702
|
});
|
|
@@ -64468,9 +64724,9 @@ object({
|
|
|
64468
64724
|
DeviceType.Sensor;
|
|
64469
64725
|
object({
|
|
64470
64726
|
/** Current measured temperature. Null when not reported. */
|
|
64471
|
-
currentTemp: number().nullable(),
|
|
64727
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
64472
64728
|
/** Target temperature setpoint. Null when no setpoint surface. */
|
|
64473
|
-
targetTemp: number().nullable(),
|
|
64729
|
+
targetTemp: number().nullable().meta(readingMeta("temperature")),
|
|
64474
64730
|
/** Active operation mode = HA `state` (`eco` / `electric` / `gas` /
|
|
64475
64731
|
* `heat_pump` / `high_demand` / `performance` / `off`). Null when the
|
|
64476
64732
|
* device reports an unknown state. */
|
|
@@ -64481,9 +64737,9 @@ object({
|
|
|
64481
64737
|
* has no away surface. */
|
|
64482
64738
|
away: boolean().nullable(),
|
|
64483
64739
|
/** HA `min_temp` attribute. Null when not reported. */
|
|
64484
|
-
minTemp: number().nullable(),
|
|
64740
|
+
minTemp: number().nullable().meta(readingMeta("temperature")),
|
|
64485
64741
|
/** HA `max_temp` attribute. Null when not reported. */
|
|
64486
|
-
maxTemp: number().nullable(),
|
|
64742
|
+
maxTemp: number().nullable().meta(readingMeta("temperature")),
|
|
64487
64743
|
/** Ms epoch when the slice was last updated. */
|
|
64488
64744
|
lastChangedAt: number()
|
|
64489
64745
|
});
|
|
@@ -64507,25 +64763,18 @@ DeviceType.WaterHeater, method(object({
|
|
|
64507
64763
|
auth: "protected"
|
|
64508
64764
|
});
|
|
64509
64765
|
object({
|
|
64510
|
-
/** Verbatim
|
|
64511
|
-
* when no condition has been reported yet. */
|
|
64766
|
+
/** Verbatim condition state (`sunny`, `cloudy`, `rainy`, …). Null when none yet. */
|
|
64512
64767
|
condition: string().nullable(),
|
|
64513
|
-
/** Current temperature in
|
|
64514
|
-
temperature: number().nullable(),
|
|
64515
|
-
/** Temperature unit string (e.g. `°C` / `°F`). Null when not provided. */
|
|
64516
|
-
temperatureUnit: string().nullable(),
|
|
64768
|
+
/** Current temperature in Celsius. Null when not provided or refused. */
|
|
64769
|
+
temperature: number().nullable().meta(readingMeta("temperature", { precision: 1 })),
|
|
64517
64770
|
/** Relative humidity (0..100). Null when not provided. */
|
|
64518
|
-
humidity: number().min(0).max(100).nullable(),
|
|
64519
|
-
/** Barometric pressure in
|
|
64520
|
-
pressure: number().nullable(),
|
|
64521
|
-
/**
|
|
64522
|
-
|
|
64523
|
-
/** Wind speed in the reported unit. Null when not provided. */
|
|
64524
|
-
windSpeed: number().nullable(),
|
|
64525
|
-
/** Wind-speed unit string (e.g. `km/h` / `mph`). Null when not provided. */
|
|
64526
|
-
windSpeedUnit: string().nullable(),
|
|
64771
|
+
humidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
64772
|
+
/** Barometric pressure in hPa. Null when not provided or refused. */
|
|
64773
|
+
pressure: number().nullable().meta(readingMeta("pressure")),
|
|
64774
|
+
/** Wind speed in metres per second. Null when not provided or refused. */
|
|
64775
|
+
windSpeed: number().nullable().meta(readingMeta("speed")),
|
|
64527
64776
|
/** Wind bearing in degrees (0..360, meteorological). Null when not provided. */
|
|
64528
|
-
windBearing: number().nullable(),
|
|
64777
|
+
windBearing: number().nullable().meta(readingMeta("angle")),
|
|
64529
64778
|
/** Ms epoch when the slice was last updated. */
|
|
64530
64779
|
lastFetchedAt: number()
|
|
64531
64780
|
});
|
|
@@ -68647,6 +68896,13 @@ Object.freeze({
|
|
|
68647
68896
|
access: "view",
|
|
68648
68897
|
role: "viewer"
|
|
68649
68898
|
},
|
|
68899
|
+
"groupStatus.getStatus": {
|
|
68900
|
+
capName: "group-status",
|
|
68901
|
+
capScope: "device",
|
|
68902
|
+
addonId: null,
|
|
68903
|
+
access: "view",
|
|
68904
|
+
role: "viewer"
|
|
68905
|
+
},
|
|
68650
68906
|
"heatingValve.getStatus": {
|
|
68651
68907
|
capName: "heating-valve",
|
|
68652
68908
|
capScope: "device",
|
|
@@ -78469,6 +78725,33 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78469
78725
|
icon: "flame"
|
|
78470
78726
|
}]
|
|
78471
78727
|
},
|
|
78728
|
+
"group-status": {
|
|
78729
|
+
scope: "device",
|
|
78730
|
+
noun: t("Group", "Gruppo"),
|
|
78731
|
+
state: [
|
|
78732
|
+
{
|
|
78733
|
+
kind: "numeric",
|
|
78734
|
+
field: "included",
|
|
78735
|
+
quantity: t("the members reporting", "i membri che rispondono"),
|
|
78736
|
+
label: t("Reporting", "Rispondono"),
|
|
78737
|
+
icon: "users"
|
|
78738
|
+
},
|
|
78739
|
+
{
|
|
78740
|
+
kind: "numeric",
|
|
78741
|
+
field: "excluded",
|
|
78742
|
+
quantity: t("the members left out", "i membri esclusi"),
|
|
78743
|
+
label: t("Excluded", "Esclusi"),
|
|
78744
|
+
icon: "users"
|
|
78745
|
+
},
|
|
78746
|
+
{
|
|
78747
|
+
kind: "numeric",
|
|
78748
|
+
field: "total",
|
|
78749
|
+
quantity: t("the member count", "il numero di membri"),
|
|
78750
|
+
label: t("Members", "Membri"),
|
|
78751
|
+
icon: "sigma"
|
|
78752
|
+
}
|
|
78753
|
+
]
|
|
78754
|
+
},
|
|
78472
78755
|
"humidity-sensor": {
|
|
78473
78756
|
scope: "device",
|
|
78474
78757
|
noun: t("Humidity", "Umidità"),
|
|
@@ -78502,7 +78785,6 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78502
78785
|
field: "value",
|
|
78503
78786
|
quantity: t("the reading", "il valore"),
|
|
78504
78787
|
label: t("Reading", "Valore"),
|
|
78505
|
-
unitField: "unit",
|
|
78506
78788
|
icon: "gauge"
|
|
78507
78789
|
}]
|
|
78508
78790
|
},
|
|
@@ -78638,7 +78920,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78638
78920
|
field: "temperature",
|
|
78639
78921
|
quantity: t("the outdoor temperature", "la temperatura esterna"),
|
|
78640
78922
|
label: t("Temperature", "Temperatura"),
|
|
78641
|
-
|
|
78923
|
+
unit: "°C",
|
|
78642
78924
|
icon: "thermometer"
|
|
78643
78925
|
},
|
|
78644
78926
|
{
|
|
@@ -78654,7 +78936,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78654
78936
|
field: "windSpeed",
|
|
78655
78937
|
quantity: t("the wind speed", "la velocità del vento"),
|
|
78656
78938
|
label: t("Wind", "Vento"),
|
|
78657
|
-
|
|
78939
|
+
unit: "m/s",
|
|
78658
78940
|
icon: "wind"
|
|
78659
78941
|
},
|
|
78660
78942
|
{
|
|
@@ -78662,7 +78944,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78662
78944
|
field: "pressure",
|
|
78663
78945
|
quantity: t("the air pressure", "la pressione atmosferica"),
|
|
78664
78946
|
label: t("Pressure", "Pressione"),
|
|
78665
|
-
|
|
78947
|
+
unit: "hPa",
|
|
78666
78948
|
icon: "gauge"
|
|
78667
78949
|
}
|
|
78668
78950
|
]
|
|
@@ -79935,6 +80217,11 @@ Object.freeze({
|
|
|
79935
80217
|
form: "single",
|
|
79936
80218
|
optional: false
|
|
79937
80219
|
}],
|
|
80220
|
+
"groupStatus.getStatus": [{
|
|
80221
|
+
name: "deviceId",
|
|
80222
|
+
form: "single",
|
|
80223
|
+
optional: false
|
|
80224
|
+
}],
|
|
79938
80225
|
"heatingValve.getStatus": [{
|
|
79939
80226
|
name: "deviceId",
|
|
79940
80227
|
form: "single",
|