@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
|
@@ -5567,7 +5567,7 @@ var ZodIssueCode = {
|
|
|
5567
5567
|
var ZodFirstPartyTypeKind;
|
|
5568
5568
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5569
5569
|
//#endregion
|
|
5570
|
-
//#region ../types/dist/sleep-
|
|
5570
|
+
//#region ../types/dist/sleep-B81gwQuR.mjs
|
|
5571
5571
|
/**
|
|
5572
5572
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5573
5573
|
* window to float samples (D455).
|
|
@@ -8302,6 +8302,99 @@ function defineEntryKind(name, spec) {
|
|
|
8302
8302
|
if (defined === void 0) throw new DeclarationRefusedError(`entry kind "${name}" was not built`);
|
|
8303
8303
|
return defined;
|
|
8304
8304
|
}
|
|
8305
|
+
var READING_QUANTITIES = [
|
|
8306
|
+
"temperature",
|
|
8307
|
+
"pressure",
|
|
8308
|
+
"speed",
|
|
8309
|
+
"precipitation",
|
|
8310
|
+
"precipitation-rate",
|
|
8311
|
+
"length",
|
|
8312
|
+
"area",
|
|
8313
|
+
"illuminance",
|
|
8314
|
+
"irradiance",
|
|
8315
|
+
"power",
|
|
8316
|
+
"energy",
|
|
8317
|
+
"voltage",
|
|
8318
|
+
"current",
|
|
8319
|
+
"apparent-power",
|
|
8320
|
+
"humidity",
|
|
8321
|
+
"percentage",
|
|
8322
|
+
"concentration-volume",
|
|
8323
|
+
"concentration-mass",
|
|
8324
|
+
"concentration-ppb",
|
|
8325
|
+
"volume",
|
|
8326
|
+
"duration",
|
|
8327
|
+
"duration-ms",
|
|
8328
|
+
"information",
|
|
8329
|
+
"sound-level",
|
|
8330
|
+
"signal-level",
|
|
8331
|
+
"colour-temperature",
|
|
8332
|
+
"angle",
|
|
8333
|
+
"bitrate",
|
|
8334
|
+
"rate",
|
|
8335
|
+
"mass",
|
|
8336
|
+
"index",
|
|
8337
|
+
"ratio",
|
|
8338
|
+
"count",
|
|
8339
|
+
"none",
|
|
8340
|
+
"device"
|
|
8341
|
+
];
|
|
8342
|
+
var ReadingQuantitySchema = _enum(READING_QUANTITIES);
|
|
8343
|
+
new Set(READING_QUANTITIES);
|
|
8344
|
+
/**
|
|
8345
|
+
* Stored unit symbol for a quantity. `none` means the number is dimensionless
|
|
8346
|
+
* (or an index / ratio / count). `device` means the cap has no single unit.
|
|
8347
|
+
*/
|
|
8348
|
+
var QUANTITY_BASE = {
|
|
8349
|
+
temperature: "°C",
|
|
8350
|
+
pressure: "hPa",
|
|
8351
|
+
speed: "m/s",
|
|
8352
|
+
precipitation: "mm",
|
|
8353
|
+
"precipitation-rate": "mm/h",
|
|
8354
|
+
length: "m",
|
|
8355
|
+
area: "m²",
|
|
8356
|
+
illuminance: "lx",
|
|
8357
|
+
irradiance: "W/m²",
|
|
8358
|
+
power: "W",
|
|
8359
|
+
energy: "kWh",
|
|
8360
|
+
voltage: "V",
|
|
8361
|
+
current: "A",
|
|
8362
|
+
"apparent-power": "VA",
|
|
8363
|
+
humidity: "%",
|
|
8364
|
+
percentage: "%",
|
|
8365
|
+
"concentration-volume": "ppm",
|
|
8366
|
+
"concentration-mass": "µg/m³",
|
|
8367
|
+
"concentration-ppb": "ppb",
|
|
8368
|
+
volume: "L",
|
|
8369
|
+
duration: "s",
|
|
8370
|
+
"duration-ms": "ms",
|
|
8371
|
+
information: "B",
|
|
8372
|
+
"sound-level": "dBFS",
|
|
8373
|
+
"signal-level": "dBm",
|
|
8374
|
+
"colour-temperature": "mired",
|
|
8375
|
+
angle: "°",
|
|
8376
|
+
bitrate: "kbps",
|
|
8377
|
+
rate: "fps",
|
|
8378
|
+
mass: "kg",
|
|
8379
|
+
index: "none",
|
|
8380
|
+
ratio: "none",
|
|
8381
|
+
count: "none",
|
|
8382
|
+
none: "none",
|
|
8383
|
+
device: "device"
|
|
8384
|
+
};
|
|
8385
|
+
/** The stored unit, or `undefined` when the quantity has no unit symbol. */
|
|
8386
|
+
function baseUnitOf(quantity) {
|
|
8387
|
+
const symbol = QUANTITY_BASE[quantity];
|
|
8388
|
+
if (symbol === "none" || symbol === "device") return void 0;
|
|
8389
|
+
return symbol;
|
|
8390
|
+
}
|
|
8391
|
+
function readingMeta(quantity, extras) {
|
|
8392
|
+
return {
|
|
8393
|
+
quantity,
|
|
8394
|
+
...extras?.precision !== void 0 ? { precision: extras.precision } : {},
|
|
8395
|
+
...extras?.label !== void 0 ? { label: extras.label } : {}
|
|
8396
|
+
};
|
|
8397
|
+
}
|
|
8305
8398
|
/** Shared Zod schemas used across streaming capabilities. */
|
|
8306
8399
|
var CamProfileSchema = _enum([
|
|
8307
8400
|
"high",
|
|
@@ -8329,8 +8422,8 @@ var CamStreamKindSchema = _enum([
|
|
|
8329
8422
|
"derived"
|
|
8330
8423
|
]);
|
|
8331
8424
|
var CamStreamResolutionSchema = object({
|
|
8332
|
-
width: number().int().positive(),
|
|
8333
|
-
height: number().int().positive()
|
|
8425
|
+
width: number().int().positive().meta(readingMeta("none")),
|
|
8426
|
+
height: number().int().positive().meta(readingMeta("none"))
|
|
8334
8427
|
});
|
|
8335
8428
|
var CameraStreamSchema = object({
|
|
8336
8429
|
/** Stable, provider-assigned id unique within the (deviceId) scope. */
|
|
@@ -8844,6 +8937,7 @@ var CAP_NAMES = Object.freeze([
|
|
|
8844
8937
|
"filesystem-browse",
|
|
8845
8938
|
"flood",
|
|
8846
8939
|
"gas",
|
|
8940
|
+
"group-status",
|
|
8847
8941
|
"heating-valve",
|
|
8848
8942
|
"humidifier",
|
|
8849
8943
|
"humidity-sensor",
|
|
@@ -8973,14 +9067,6 @@ Object.freeze({
|
|
|
8973
9067
|
{
|
|
8974
9068
|
"path": "aqi",
|
|
8975
9069
|
"valueType": "number"
|
|
8976
|
-
},
|
|
8977
|
-
{
|
|
8978
|
-
"path": "unit",
|
|
8979
|
-
"valueType": "string"
|
|
8980
|
-
},
|
|
8981
|
-
{
|
|
8982
|
-
"path": "precision",
|
|
8983
|
-
"valueType": "number"
|
|
8984
9070
|
}
|
|
8985
9071
|
],
|
|
8986
9072
|
"alarm-panel": [
|
|
@@ -9016,20 +9102,10 @@ Object.freeze({
|
|
|
9016
9102
|
"valueType": "boolean"
|
|
9017
9103
|
}
|
|
9018
9104
|
],
|
|
9019
|
-
"ambient-light-sensor": [
|
|
9020
|
-
|
|
9021
|
-
|
|
9022
|
-
|
|
9023
|
-
},
|
|
9024
|
-
{
|
|
9025
|
-
"path": "unit",
|
|
9026
|
-
"valueType": "string"
|
|
9027
|
-
},
|
|
9028
|
-
{
|
|
9029
|
-
"path": "precision",
|
|
9030
|
-
"valueType": "number"
|
|
9031
|
-
}
|
|
9032
|
-
],
|
|
9105
|
+
"ambient-light-sensor": [{
|
|
9106
|
+
"path": "lux",
|
|
9107
|
+
"valueType": "number"
|
|
9108
|
+
}],
|
|
9033
9109
|
"audio-metrics": [
|
|
9034
9110
|
{
|
|
9035
9111
|
"path": "ts",
|
|
@@ -9109,6 +9185,10 @@ Object.freeze({
|
|
|
9109
9185
|
"path": "lastUpdated",
|
|
9110
9186
|
"valueType": "number"
|
|
9111
9187
|
},
|
|
9188
|
+
{
|
|
9189
|
+
"path": "volts",
|
|
9190
|
+
"valueType": "number"
|
|
9191
|
+
},
|
|
9112
9192
|
{
|
|
9113
9193
|
"path": "lastContactAt",
|
|
9114
9194
|
"valueType": "number"
|
|
@@ -9351,10 +9431,6 @@ Object.freeze({
|
|
|
9351
9431
|
"datetime"
|
|
9352
9432
|
]
|
|
9353
9433
|
},
|
|
9354
|
-
{
|
|
9355
|
-
"path": "unit",
|
|
9356
|
-
"valueType": "string"
|
|
9357
|
-
},
|
|
9358
9434
|
{
|
|
9359
9435
|
"path": "min",
|
|
9360
9436
|
"valueType": "number"
|
|
@@ -9366,19 +9442,6 @@ Object.freeze({
|
|
|
9366
9442
|
{
|
|
9367
9443
|
"path": "step",
|
|
9368
9444
|
"valueType": "number"
|
|
9369
|
-
},
|
|
9370
|
-
{
|
|
9371
|
-
"path": "precision",
|
|
9372
|
-
"valueType": "number"
|
|
9373
|
-
},
|
|
9374
|
-
{
|
|
9375
|
-
"path": "format",
|
|
9376
|
-
"valueType": "enum",
|
|
9377
|
-
"enumValues": [
|
|
9378
|
-
"date",
|
|
9379
|
-
"time",
|
|
9380
|
-
"datetime"
|
|
9381
|
-
]
|
|
9382
9445
|
}
|
|
9383
9446
|
],
|
|
9384
9447
|
"cover": [
|
|
@@ -9619,13 +9682,8 @@ Object.freeze({
|
|
|
9619
9682
|
"path": "value",
|
|
9620
9683
|
"valueType": "string"
|
|
9621
9684
|
}, {
|
|
9622
|
-
"path": "
|
|
9623
|
-
"valueType": "
|
|
9624
|
-
"enumValues": [
|
|
9625
|
-
"date",
|
|
9626
|
-
"time",
|
|
9627
|
-
"datetime"
|
|
9628
|
-
]
|
|
9685
|
+
"path": "timestamp",
|
|
9686
|
+
"valueType": "boolean"
|
|
9629
9687
|
}],
|
|
9630
9688
|
"event-emitter": [
|
|
9631
9689
|
{
|
|
@@ -9698,6 +9756,20 @@ Object.freeze({
|
|
|
9698
9756
|
"path": "detected",
|
|
9699
9757
|
"valueType": "boolean"
|
|
9700
9758
|
}],
|
|
9759
|
+
"group-status": [
|
|
9760
|
+
{
|
|
9761
|
+
"path": "included",
|
|
9762
|
+
"valueType": "number"
|
|
9763
|
+
},
|
|
9764
|
+
{
|
|
9765
|
+
"path": "excluded",
|
|
9766
|
+
"valueType": "number"
|
|
9767
|
+
},
|
|
9768
|
+
{
|
|
9769
|
+
"path": "total",
|
|
9770
|
+
"valueType": "number"
|
|
9771
|
+
}
|
|
9772
|
+
],
|
|
9701
9773
|
"heating-valve": [{
|
|
9702
9774
|
"path": "position",
|
|
9703
9775
|
"valueType": "number"
|
|
@@ -9732,20 +9804,10 @@ Object.freeze({
|
|
|
9732
9804
|
"valueType": "number"
|
|
9733
9805
|
}
|
|
9734
9806
|
],
|
|
9735
|
-
"humidity-sensor": [
|
|
9736
|
-
|
|
9737
|
-
|
|
9738
|
-
|
|
9739
|
-
},
|
|
9740
|
-
{
|
|
9741
|
-
"path": "unit",
|
|
9742
|
-
"valueType": "string"
|
|
9743
|
-
},
|
|
9744
|
-
{
|
|
9745
|
-
"path": "precision",
|
|
9746
|
-
"valueType": "number"
|
|
9747
|
-
}
|
|
9748
|
-
],
|
|
9807
|
+
"humidity-sensor": [{
|
|
9808
|
+
"path": "percent",
|
|
9809
|
+
"valueType": "number"
|
|
9810
|
+
}],
|
|
9749
9811
|
"image": [{
|
|
9750
9812
|
"path": "url",
|
|
9751
9813
|
"valueType": "string"
|
|
@@ -10084,20 +10146,10 @@ Object.freeze({
|
|
|
10084
10146
|
"valueType": "boolean"
|
|
10085
10147
|
}
|
|
10086
10148
|
],
|
|
10087
|
-
"numeric-sensor": [
|
|
10088
|
-
|
|
10089
|
-
|
|
10090
|
-
|
|
10091
|
-
},
|
|
10092
|
-
{
|
|
10093
|
-
"path": "unit",
|
|
10094
|
-
"valueType": "string"
|
|
10095
|
-
},
|
|
10096
|
-
{
|
|
10097
|
-
"path": "precision",
|
|
10098
|
-
"valueType": "number"
|
|
10099
|
-
}
|
|
10100
|
-
],
|
|
10149
|
+
"numeric-sensor": [{
|
|
10150
|
+
"path": "value",
|
|
10151
|
+
"valueType": "number"
|
|
10152
|
+
}],
|
|
10101
10153
|
"pet-feeder": [
|
|
10102
10154
|
{
|
|
10103
10155
|
"path": "foodLevel",
|
|
@@ -10189,14 +10241,6 @@ Object.freeze({
|
|
|
10189
10241
|
{
|
|
10190
10242
|
"path": "powerFactor",
|
|
10191
10243
|
"valueType": "number"
|
|
10192
|
-
},
|
|
10193
|
-
{
|
|
10194
|
-
"path": "unit",
|
|
10195
|
-
"valueType": "string"
|
|
10196
|
-
},
|
|
10197
|
-
{
|
|
10198
|
-
"path": "precision",
|
|
10199
|
-
"valueType": "number"
|
|
10200
10244
|
}
|
|
10201
10245
|
],
|
|
10202
10246
|
"presence": [
|
|
@@ -10225,20 +10269,10 @@ Object.freeze({
|
|
|
10225
10269
|
"valueType": "number"
|
|
10226
10270
|
}
|
|
10227
10271
|
],
|
|
10228
|
-
"pressure-sensor": [
|
|
10229
|
-
|
|
10230
|
-
|
|
10231
|
-
|
|
10232
|
-
},
|
|
10233
|
-
{
|
|
10234
|
-
"path": "unit",
|
|
10235
|
-
"valueType": "string"
|
|
10236
|
-
},
|
|
10237
|
-
{
|
|
10238
|
-
"path": "precision",
|
|
10239
|
-
"valueType": "number"
|
|
10240
|
-
}
|
|
10241
|
-
],
|
|
10272
|
+
"pressure-sensor": [{
|
|
10273
|
+
"path": "hpa",
|
|
10274
|
+
"valueType": "number"
|
|
10275
|
+
}],
|
|
10242
10276
|
"privacy-mask": [{
|
|
10243
10277
|
"path": "enabled",
|
|
10244
10278
|
"valueType": "boolean"
|
|
@@ -10549,20 +10583,10 @@ Object.freeze({
|
|
|
10549
10583
|
"path": "tampered",
|
|
10550
10584
|
"valueType": "boolean"
|
|
10551
10585
|
}],
|
|
10552
|
-
"temperature-sensor": [
|
|
10553
|
-
|
|
10554
|
-
|
|
10555
|
-
|
|
10556
|
-
},
|
|
10557
|
-
{
|
|
10558
|
-
"path": "unit",
|
|
10559
|
-
"valueType": "string"
|
|
10560
|
-
},
|
|
10561
|
-
{
|
|
10562
|
-
"path": "precision",
|
|
10563
|
-
"valueType": "number"
|
|
10564
|
-
}
|
|
10565
|
-
],
|
|
10586
|
+
"temperature-sensor": [{
|
|
10587
|
+
"path": "celsius",
|
|
10588
|
+
"valueType": "number"
|
|
10589
|
+
}],
|
|
10566
10590
|
"update": [
|
|
10567
10591
|
{
|
|
10568
10592
|
"path": "currentVersion",
|
|
@@ -10673,10 +10697,6 @@ Object.freeze({
|
|
|
10673
10697
|
"path": "temperature",
|
|
10674
10698
|
"valueType": "number"
|
|
10675
10699
|
},
|
|
10676
|
-
{
|
|
10677
|
-
"path": "temperatureUnit",
|
|
10678
|
-
"valueType": "string"
|
|
10679
|
-
},
|
|
10680
10700
|
{
|
|
10681
10701
|
"path": "humidity",
|
|
10682
10702
|
"valueType": "number"
|
|
@@ -10685,18 +10705,10 @@ Object.freeze({
|
|
|
10685
10705
|
"path": "pressure",
|
|
10686
10706
|
"valueType": "number"
|
|
10687
10707
|
},
|
|
10688
|
-
{
|
|
10689
|
-
"path": "pressureUnit",
|
|
10690
|
-
"valueType": "string"
|
|
10691
|
-
},
|
|
10692
10708
|
{
|
|
10693
10709
|
"path": "windSpeed",
|
|
10694
10710
|
"valueType": "number"
|
|
10695
10711
|
},
|
|
10696
|
-
{
|
|
10697
|
-
"path": "windSpeedUnit",
|
|
10698
|
-
"valueType": "string"
|
|
10699
|
-
},
|
|
10700
10712
|
{
|
|
10701
10713
|
"path": "windBearing",
|
|
10702
10714
|
"valueType": "number"
|
|
@@ -11089,7 +11101,7 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
|
|
|
11089
11101
|
return DeviceRole;
|
|
11090
11102
|
}({});
|
|
11091
11103
|
//#endregion
|
|
11092
|
-
//#region ../types/dist/composition-
|
|
11104
|
+
//#region ../types/dist/composition-B85l9j1M.mjs
|
|
11093
11105
|
/**
|
|
11094
11106
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
11095
11107
|
*
|
|
@@ -11844,15 +11856,67 @@ function validateExpressionSource(src) {
|
|
|
11844
11856
|
}
|
|
11845
11857
|
return null;
|
|
11846
11858
|
}
|
|
11847
|
-
/**
|
|
11848
|
-
|
|
11849
|
-
|
|
11850
|
-
|
|
11859
|
+
/**
|
|
11860
|
+
* A composition source identity: `(addonId, stableId)`, never a numeric device
|
|
11861
|
+
* id. Split out so helper schemas can name it without a cycle through
|
|
11862
|
+
* `composition.ts` (D659).
|
|
11863
|
+
*/
|
|
11851
11864
|
var CompositionSourceRefSchema = object({
|
|
11852
11865
|
/** The owning addon; `stableId` is unique only within it. */
|
|
11853
11866
|
addonId: string().min(1),
|
|
11854
11867
|
stableId: string().min(1)
|
|
11855
11868
|
});
|
|
11869
|
+
var GROUP_TEMPLATE_IDS = [
|
|
11870
|
+
"temperature",
|
|
11871
|
+
"humidity",
|
|
11872
|
+
"pressure",
|
|
11873
|
+
"illuminance",
|
|
11874
|
+
"power",
|
|
11875
|
+
"energy",
|
|
11876
|
+
"battery",
|
|
11877
|
+
"numeric",
|
|
11878
|
+
"motion",
|
|
11879
|
+
"contact",
|
|
11880
|
+
"leak",
|
|
11881
|
+
"smoke",
|
|
11882
|
+
"occupancy",
|
|
11883
|
+
"binary"
|
|
11884
|
+
];
|
|
11885
|
+
var NUMERIC_AGGREGATES = [
|
|
11886
|
+
"mean",
|
|
11887
|
+
"median",
|
|
11888
|
+
"min",
|
|
11889
|
+
"max",
|
|
11890
|
+
"sum"
|
|
11891
|
+
];
|
|
11892
|
+
var BINARY_AGGREGATES = ["any", "all"];
|
|
11893
|
+
var AGGREGATE_REDUCERS = [
|
|
11894
|
+
"mean",
|
|
11895
|
+
"median",
|
|
11896
|
+
"min",
|
|
11897
|
+
"max",
|
|
11898
|
+
"sum",
|
|
11899
|
+
"any",
|
|
11900
|
+
"all"
|
|
11901
|
+
];
|
|
11902
|
+
var GroupTemplateIdSchema = _enum(GROUP_TEMPLATE_IDS);
|
|
11903
|
+
var AggregateReducerSchema = _enum(AGGREGATE_REDUCERS);
|
|
11904
|
+
/** One member. The field is stored so occupancy can name motion or binary. */
|
|
11905
|
+
var HelperMemberSchema = object({
|
|
11906
|
+
source: CompositionSourceRefSchema,
|
|
11907
|
+
cap: string().min(1),
|
|
11908
|
+
fieldPath: string().min(1)
|
|
11909
|
+
});
|
|
11910
|
+
var HelperSpecSchema = discriminatedUnion("kind", [object({
|
|
11911
|
+
kind: literal("group"),
|
|
11912
|
+
templateId: GroupTemplateIdSchema,
|
|
11913
|
+
aggregate: AggregateReducerSchema,
|
|
11914
|
+
members: array(HelperMemberSchema).min(1).max(64)
|
|
11915
|
+
})]);
|
|
11916
|
+
/** A composed device's stableId is this prefix plus the block id. */
|
|
11917
|
+
var COMPOSED_DEVICE_STABLE_ID_PREFIX = "composed-";
|
|
11918
|
+
/** Longest snippet a `code` source may carry (slice 4). */
|
|
11919
|
+
var MAX_COMPOSITION_CODE_LENGTH = 2e4;
|
|
11856
11920
|
/** One field of one capability of one source device. */
|
|
11857
11921
|
var CompositionFieldReadSchema = object({
|
|
11858
11922
|
source: CompositionSourceRefSchema,
|
|
@@ -11896,7 +11960,33 @@ var CompositionCodeSourceSchema = object({
|
|
|
11896
11960
|
var CompositionFieldSourceSchema = discriminatedUnion("kind", [
|
|
11897
11961
|
CompositionFromSourceSchema,
|
|
11898
11962
|
CompositionExpressionSourceSchema,
|
|
11899
|
-
CompositionCodeSourceSchema
|
|
11963
|
+
CompositionCodeSourceSchema,
|
|
11964
|
+
object({
|
|
11965
|
+
kind: literal("aggregate"),
|
|
11966
|
+
reducer: _enum([
|
|
11967
|
+
"mean",
|
|
11968
|
+
"median",
|
|
11969
|
+
"min",
|
|
11970
|
+
"max",
|
|
11971
|
+
"sum",
|
|
11972
|
+
"any",
|
|
11973
|
+
"all"
|
|
11974
|
+
]),
|
|
11975
|
+
reads: array(CompositionFieldReadSchema).min(1).max(64),
|
|
11976
|
+
/** `value` is the reading; the others are the member counts. */
|
|
11977
|
+
publish: _enum([
|
|
11978
|
+
"value",
|
|
11979
|
+
"included",
|
|
11980
|
+
"excluded",
|
|
11981
|
+
"total"
|
|
11982
|
+
]),
|
|
11983
|
+
/** What a `value` publish does when nobody is included. Counts ignore this. */
|
|
11984
|
+
empty: _enum([
|
|
11985
|
+
"null",
|
|
11986
|
+
"omit",
|
|
11987
|
+
"offline"
|
|
11988
|
+
])
|
|
11989
|
+
})
|
|
11900
11990
|
]);
|
|
11901
11991
|
var CompositionCommandTargetSchema = discriminatedUnion("kind", [object({
|
|
11902
11992
|
kind: literal("forward"),
|
|
@@ -11942,7 +12032,13 @@ var CompositionSchema = object({
|
|
|
11942
12032
|
kind: literal("existing"),
|
|
11943
12033
|
device: CompositionSourceRefSchema
|
|
11944
12034
|
})]),
|
|
11945
|
-
features: array(CompositionFeatureSchema).min(1).max(16)
|
|
12035
|
+
features: array(CompositionFeatureSchema).min(1).max(16),
|
|
12036
|
+
/**
|
|
12037
|
+
* Present when the block is a helper template. Absent on a free
|
|
12038
|
+
* composition (the room example, device 4603). The editor reads this,
|
|
12039
|
+
* never the compiled features.
|
|
12040
|
+
*/
|
|
12041
|
+
helper: HelperSpecSchema.optional()
|
|
11946
12042
|
}).superRefine((composition, ctx) => {
|
|
11947
12043
|
const seen = /* @__PURE__ */ new Set();
|
|
11948
12044
|
composition.features.forEach((feature, index) => {
|
|
@@ -18079,7 +18175,11 @@ var CompositionProblemSchema = object({
|
|
|
18079
18175
|
"item-field-reserved",
|
|
18080
18176
|
"target-missing",
|
|
18081
18177
|
"target-unreadable",
|
|
18082
|
-
"not-replaceable"
|
|
18178
|
+
"not-replaceable",
|
|
18179
|
+
"native-capability-replace",
|
|
18180
|
+
"mixed-quantity",
|
|
18181
|
+
"helper-mismatch",
|
|
18182
|
+
"member-constraint"
|
|
18083
18183
|
]),
|
|
18084
18184
|
path: string(),
|
|
18085
18185
|
message: string()
|
|
@@ -18100,7 +18200,8 @@ var CompositionUnavailableModeSchema = _enum([
|
|
|
18100
18200
|
"null",
|
|
18101
18201
|
"offline",
|
|
18102
18202
|
"unknown",
|
|
18103
|
-
"release"
|
|
18203
|
+
"release",
|
|
18204
|
+
"omit"
|
|
18104
18205
|
]);
|
|
18105
18206
|
/**
|
|
18106
18207
|
* `derived` reads a source · `clock` reads only `now`, recomputed when a sibling
|
|
@@ -18137,9 +18238,11 @@ var CompositionFieldPlanSchema = object({
|
|
|
18137
18238
|
reads: array(CompositionFieldReadSchema)
|
|
18138
18239
|
});
|
|
18139
18240
|
/**
|
|
18140
|
-
* What a feature does to its target (D663): `new` builds a capability on a
|
|
18141
|
-
* device; on an existing device it `add`s a capability the device lacks
|
|
18142
|
-
*
|
|
18241
|
+
* What a feature does to its target (D663, D944): `new` builds a capability on a
|
|
18242
|
+
* new device; on an existing device it `add`s a capability the device lacks.
|
|
18243
|
+
* Replacing a capability the device already serves is refused
|
|
18244
|
+
* (`native-capability-replace`), not planned. `replace` remains on the claim
|
|
18245
|
+
* wire for a claim the hub already holds.
|
|
18143
18246
|
*/
|
|
18144
18247
|
var CompositionFeatureModeSchema = _enum([
|
|
18145
18248
|
"new",
|
|
@@ -18312,6 +18415,235 @@ Object.freeze({
|
|
|
18312
18415
|
result: ["number", "null"]
|
|
18313
18416
|
}
|
|
18314
18417
|
});
|
|
18418
|
+
/**
|
|
18419
|
+
* One catalog row per base reading a group helper can build (D944 §3).
|
|
18420
|
+
* Data, not a form default written into the block.
|
|
18421
|
+
*/
|
|
18422
|
+
var NOW = {
|
|
18423
|
+
fieldPath: "lastFetchedAt",
|
|
18424
|
+
expr: "now"
|
|
18425
|
+
};
|
|
18426
|
+
var CHANGED = {
|
|
18427
|
+
fieldPath: "lastChangedAt",
|
|
18428
|
+
expr: "now"
|
|
18429
|
+
};
|
|
18430
|
+
function numeric(input) {
|
|
18431
|
+
return {
|
|
18432
|
+
...input,
|
|
18433
|
+
family: "numeric",
|
|
18434
|
+
deviceType: DeviceType.Sensor,
|
|
18435
|
+
memberDeviceType: DeviceType.Sensor,
|
|
18436
|
+
baseUnit: baseUnitOf(input.quantity),
|
|
18437
|
+
aggregates: NUMERIC_AGGREGATES,
|
|
18438
|
+
accept: [{
|
|
18439
|
+
cap: input.outputCap,
|
|
18440
|
+
fieldPath: input.outputField
|
|
18441
|
+
}]
|
|
18442
|
+
};
|
|
18443
|
+
}
|
|
18444
|
+
function binary(input) {
|
|
18445
|
+
return {
|
|
18446
|
+
...input,
|
|
18447
|
+
family: "binary",
|
|
18448
|
+
deviceType: DeviceType.Sensor,
|
|
18449
|
+
memberDeviceType: DeviceType.Sensor,
|
|
18450
|
+
quantity: "none",
|
|
18451
|
+
baseUnit: void 0,
|
|
18452
|
+
aggregates: BINARY_AGGREGATES,
|
|
18453
|
+
empty: "offline"
|
|
18454
|
+
};
|
|
18455
|
+
}
|
|
18456
|
+
var GROUP_TEMPLATES = [
|
|
18457
|
+
numeric({
|
|
18458
|
+
id: "temperature",
|
|
18459
|
+
summary: "Mean, median, min, max or sum of temperatures. Offline and unknown members are left out, never read as 0 °C.",
|
|
18460
|
+
role: DeviceRole.TemperatureSensor,
|
|
18461
|
+
outputCap: "temperature-sensor",
|
|
18462
|
+
outputField: "celsius",
|
|
18463
|
+
quantity: "temperature",
|
|
18464
|
+
defaultAggregate: "mean",
|
|
18465
|
+
empty: "null",
|
|
18466
|
+
companions: [NOW]
|
|
18467
|
+
}),
|
|
18468
|
+
numeric({
|
|
18469
|
+
id: "humidity",
|
|
18470
|
+
summary: "Humidity in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
18471
|
+
role: DeviceRole.HumiditySensor,
|
|
18472
|
+
outputCap: "humidity-sensor",
|
|
18473
|
+
outputField: "percent",
|
|
18474
|
+
quantity: "humidity",
|
|
18475
|
+
defaultAggregate: "mean",
|
|
18476
|
+
empty: "null",
|
|
18477
|
+
companions: [NOW]
|
|
18478
|
+
}),
|
|
18479
|
+
numeric({
|
|
18480
|
+
id: "pressure",
|
|
18481
|
+
summary: "Pressure in hectopascals. Offline and unknown members are left out, never read as 0 hPa.",
|
|
18482
|
+
role: DeviceRole.PressureSensor,
|
|
18483
|
+
outputCap: "pressure-sensor",
|
|
18484
|
+
outputField: "hpa",
|
|
18485
|
+
quantity: "pressure",
|
|
18486
|
+
defaultAggregate: "mean",
|
|
18487
|
+
empty: "null",
|
|
18488
|
+
companions: [NOW]
|
|
18489
|
+
}),
|
|
18490
|
+
numeric({
|
|
18491
|
+
id: "illuminance",
|
|
18492
|
+
summary: "Illuminance in lux. Offline and unknown members are left out, never read as 0 lx.",
|
|
18493
|
+
role: DeviceRole.AmbientLightSensor,
|
|
18494
|
+
outputCap: "ambient-light-sensor",
|
|
18495
|
+
outputField: "lux",
|
|
18496
|
+
quantity: "illuminance",
|
|
18497
|
+
defaultAggregate: "mean",
|
|
18498
|
+
empty: "null",
|
|
18499
|
+
companions: [NOW]
|
|
18500
|
+
}),
|
|
18501
|
+
numeric({
|
|
18502
|
+
id: "power",
|
|
18503
|
+
summary: "Power in watts, summed by default. Nobody reporting omits the key rather than writing 0 W.",
|
|
18504
|
+
role: DeviceRole.PowerSensor,
|
|
18505
|
+
outputCap: "power-meter",
|
|
18506
|
+
outputField: "watts",
|
|
18507
|
+
quantity: "power",
|
|
18508
|
+
defaultAggregate: "sum",
|
|
18509
|
+
empty: "omit",
|
|
18510
|
+
companions: [NOW]
|
|
18511
|
+
}),
|
|
18512
|
+
numeric({
|
|
18513
|
+
id: "energy",
|
|
18514
|
+
summary: "Energy in kilowatt-hours, summed by default. Nobody reporting omits the key rather than writing 0 kWh.",
|
|
18515
|
+
role: DeviceRole.EnergySensor,
|
|
18516
|
+
outputCap: "power-meter",
|
|
18517
|
+
outputField: "kwhTotal",
|
|
18518
|
+
quantity: "energy",
|
|
18519
|
+
defaultAggregate: "sum",
|
|
18520
|
+
empty: "omit",
|
|
18521
|
+
companions: [NOW]
|
|
18522
|
+
}),
|
|
18523
|
+
numeric({
|
|
18524
|
+
id: "battery",
|
|
18525
|
+
summary: "Battery charge in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
18526
|
+
role: DeviceRole.BatterySensor,
|
|
18527
|
+
outputCap: "battery",
|
|
18528
|
+
outputField: "percentage",
|
|
18529
|
+
quantity: "percentage",
|
|
18530
|
+
defaultAggregate: "mean",
|
|
18531
|
+
empty: "null",
|
|
18532
|
+
companions: [
|
|
18533
|
+
{
|
|
18534
|
+
fieldPath: "charging",
|
|
18535
|
+
expr: "\"unknown\""
|
|
18536
|
+
},
|
|
18537
|
+
{
|
|
18538
|
+
fieldPath: "sleeping",
|
|
18539
|
+
expr: "false"
|
|
18540
|
+
},
|
|
18541
|
+
{
|
|
18542
|
+
fieldPath: "lastUpdated",
|
|
18543
|
+
expr: "now"
|
|
18544
|
+
}
|
|
18545
|
+
]
|
|
18546
|
+
}),
|
|
18547
|
+
numeric({
|
|
18548
|
+
id: "numeric",
|
|
18549
|
+
summary: "A numeric reading in the members’ shared quantity. Mixed quantities are refused. Nobody reporting publishes null, not 0.",
|
|
18550
|
+
role: DeviceRole.NumericSensor,
|
|
18551
|
+
outputCap: "numeric-sensor",
|
|
18552
|
+
outputField: "value",
|
|
18553
|
+
quantity: "device",
|
|
18554
|
+
defaultAggregate: "mean",
|
|
18555
|
+
empty: "null",
|
|
18556
|
+
companions: [NOW]
|
|
18557
|
+
}),
|
|
18558
|
+
binary({
|
|
18559
|
+
id: "motion",
|
|
18560
|
+
summary: "Any or all motion. Offline and unknown members are left out, never read as off. Nobody reporting takes the device offline.",
|
|
18561
|
+
role: DeviceRole.MotionSensor,
|
|
18562
|
+
outputCap: "motion",
|
|
18563
|
+
outputField: "detected",
|
|
18564
|
+
defaultAggregate: "any",
|
|
18565
|
+
accept: [{
|
|
18566
|
+
cap: "motion",
|
|
18567
|
+
fieldPath: "detected"
|
|
18568
|
+
}],
|
|
18569
|
+
companions: [{
|
|
18570
|
+
fieldPath: "lastDetectedAt",
|
|
18571
|
+
expr: "null"
|
|
18572
|
+
}, {
|
|
18573
|
+
fieldPath: "autoClearAfterMs",
|
|
18574
|
+
expr: "null"
|
|
18575
|
+
}]
|
|
18576
|
+
}),
|
|
18577
|
+
binary({
|
|
18578
|
+
id: "contact",
|
|
18579
|
+
summary: "Any or all open contacts. Offline and unknown members are left out, never read as closed.",
|
|
18580
|
+
role: DeviceRole.ContactSensor,
|
|
18581
|
+
outputCap: "contact",
|
|
18582
|
+
outputField: "entryOpen",
|
|
18583
|
+
defaultAggregate: "any",
|
|
18584
|
+
accept: [{
|
|
18585
|
+
cap: "contact",
|
|
18586
|
+
fieldPath: "entryOpen"
|
|
18587
|
+
}],
|
|
18588
|
+
companions: [CHANGED]
|
|
18589
|
+
}),
|
|
18590
|
+
binary({
|
|
18591
|
+
id: "leak",
|
|
18592
|
+
summary: "Any or all leak detections. Offline and unknown members are left out, never read as dry.",
|
|
18593
|
+
role: DeviceRole.LeakSensor,
|
|
18594
|
+
outputCap: "flood",
|
|
18595
|
+
outputField: "flooded",
|
|
18596
|
+
defaultAggregate: "any",
|
|
18597
|
+
accept: [{
|
|
18598
|
+
cap: "flood",
|
|
18599
|
+
fieldPath: "flooded"
|
|
18600
|
+
}],
|
|
18601
|
+
companions: [CHANGED]
|
|
18602
|
+
}),
|
|
18603
|
+
binary({
|
|
18604
|
+
id: "smoke",
|
|
18605
|
+
summary: "Any or all smoke detections. Offline and unknown members are left out, never read as clear.",
|
|
18606
|
+
role: DeviceRole.SmokeSensor,
|
|
18607
|
+
outputCap: "smoke",
|
|
18608
|
+
outputField: "detected",
|
|
18609
|
+
defaultAggregate: "any",
|
|
18610
|
+
accept: [{
|
|
18611
|
+
cap: "smoke",
|
|
18612
|
+
fieldPath: "detected"
|
|
18613
|
+
}],
|
|
18614
|
+
companions: [CHANGED]
|
|
18615
|
+
}),
|
|
18616
|
+
binary({
|
|
18617
|
+
id: "occupancy",
|
|
18618
|
+
summary: "Any or all of motion or binary sensors, published as a binary. Presence zones are not aggregated. Nobody reporting is offline, not off.",
|
|
18619
|
+
role: DeviceRole.BinarySensor,
|
|
18620
|
+
outputCap: "binary",
|
|
18621
|
+
outputField: "on",
|
|
18622
|
+
defaultAggregate: "any",
|
|
18623
|
+
accept: [{
|
|
18624
|
+
cap: "motion",
|
|
18625
|
+
fieldPath: "detected"
|
|
18626
|
+
}, {
|
|
18627
|
+
cap: "binary",
|
|
18628
|
+
fieldPath: "on"
|
|
18629
|
+
}],
|
|
18630
|
+
companions: [CHANGED]
|
|
18631
|
+
}),
|
|
18632
|
+
binary({
|
|
18633
|
+
id: "binary",
|
|
18634
|
+
summary: "Any or all generic binary sensors. Offline and unknown members are left out, never read as off.",
|
|
18635
|
+
role: DeviceRole.BinarySensor,
|
|
18636
|
+
outputCap: "binary",
|
|
18637
|
+
outputField: "on",
|
|
18638
|
+
defaultAggregate: "any",
|
|
18639
|
+
accept: [{
|
|
18640
|
+
cap: "binary",
|
|
18641
|
+
fieldPath: "on"
|
|
18642
|
+
}],
|
|
18643
|
+
companions: [CHANGED]
|
|
18644
|
+
})
|
|
18645
|
+
];
|
|
18646
|
+
new Map(GROUP_TEMPLATES.map((template) => [template.id, template]));
|
|
18315
18647
|
`${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
|
|
18316
18648
|
/**
|
|
18317
18649
|
* What a composition may BUILD on a device type (G2, D676): the caps a new
|
|
@@ -20025,12 +20357,12 @@ method(object({ deviceId: number().int().nonnegative() }), DeviceAdminLinkSchema
|
|
|
20025
20357
|
* providers detect renames by matching `uniqueId` and patch `id`
|
|
20026
20358
|
* in-place so dispatch keeps working.
|
|
20027
20359
|
*
|
|
20028
|
-
* **
|
|
20029
|
-
*
|
|
20030
|
-
*
|
|
20031
|
-
*
|
|
20032
|
-
* (`ha-domain-mapping`)
|
|
20033
|
-
* stored after that point.
|
|
20360
|
+
* **Display unit and precision are NOT stored here.** They are a read-time
|
|
20361
|
+
* preference (D944). A polymorphic reading stores its `quantity` here once,
|
|
20362
|
+
* at adopt, and a date/time value stores `dateTimeShape` the same way —
|
|
20363
|
+
* neither is repeated on each sample. The `device_class` tag is an
|
|
20364
|
+
* HA-specific input consumed at the discovery boundary (`ha-domain-mapping`)
|
|
20365
|
+
* to derive the CamStack `DeviceRole`; it is never stored after that point.
|
|
20034
20366
|
*
|
|
20035
20367
|
* The `raw` escape hatch carries provider-specific attributes that don't
|
|
20036
20368
|
* fit the structured slots (HA `attributes` whitelist, Reolink `deviceCache`
|
|
@@ -20044,6 +20376,14 @@ var SourceInfoSchema = object({
|
|
|
20044
20376
|
/** Immutable upstream identifier when available (HA `unique_id`, … ).
|
|
20045
20377
|
* Used to detect rename when `id` changes. */
|
|
20046
20378
|
uniqueId: string().optional(),
|
|
20379
|
+
/** Quantity of a polymorphic reading, written once at adopt (D944). */
|
|
20380
|
+
quantity: ReadingQuantitySchema.optional(),
|
|
20381
|
+
/** Date / time / datetime shape of a string reading, written once at adopt. */
|
|
20382
|
+
dateTimeShape: _enum([
|
|
20383
|
+
"date",
|
|
20384
|
+
"time",
|
|
20385
|
+
"datetime"
|
|
20386
|
+
]).optional(),
|
|
20047
20387
|
/** Provider-specific extras that don't fit the structured slots.
|
|
20048
20388
|
* Whitelist what goes here per provider — do NOT dump entire HA
|
|
20049
20389
|
* attribute blobs (would explode the meta JSON column). */
|
|
@@ -40956,7 +41296,8 @@ method(object({
|
|
|
40956
41296
|
"enum"
|
|
40957
41297
|
]),
|
|
40958
41298
|
enumValues: array(string()).optional(),
|
|
40959
|
-
item: boolean().optional()
|
|
41299
|
+
item: boolean().optional(),
|
|
41300
|
+
quantity: ReadingQuantitySchema.optional()
|
|
40960
41301
|
})).readonly(),
|
|
40961
41302
|
itemArray: object({
|
|
40962
41303
|
path: string(),
|
|
@@ -44756,8 +45097,8 @@ var MaskPolygonShapeSchema = object({
|
|
|
44756
45097
|
/** Boolean cell grid — row-major, length === gridWidth*gridHeight. */
|
|
44757
45098
|
var MaskGridShapeSchema = object({
|
|
44758
45099
|
kind: literal("grid"),
|
|
44759
|
-
gridWidth: number(),
|
|
44760
|
-
gridHeight: number(),
|
|
45100
|
+
gridWidth: number().meta(readingMeta("none")),
|
|
45101
|
+
gridHeight: number().meta(readingMeta("none")),
|
|
44761
45102
|
cells: array(boolean())
|
|
44762
45103
|
});
|
|
44763
45104
|
discriminatedUnion("kind", [
|
|
@@ -56151,46 +56492,27 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
|
|
|
56151
56492
|
}), LogStreamEntrySchema, { kind: "subscription" });
|
|
56152
56493
|
object({
|
|
56153
56494
|
/** Carbon dioxide concentration in ppm. */
|
|
56154
|
-
co2Ppm: number().min(0).optional(),
|
|
56495
|
+
co2Ppm: number().min(0).optional().meta(readingMeta("concentration-volume")),
|
|
56155
56496
|
/** Total volatile organic compounds in ppb. */
|
|
56156
|
-
vocPpb: number().min(0).optional(),
|
|
56497
|
+
vocPpb: number().min(0).optional().meta(readingMeta("concentration-ppb")),
|
|
56157
56498
|
/** Particulate matter ≤ 2.5 μm in µg/m³. */
|
|
56158
|
-
pm25: number().min(0).optional(),
|
|
56499
|
+
pm25: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
56159
56500
|
/** Particulate matter ≤ 10 μm in µg/m³. */
|
|
56160
|
-
pm10: number().min(0).optional(),
|
|
56501
|
+
pm10: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
56161
56502
|
/** Composite AQI value (typically 0..500). */
|
|
56162
|
-
aqi: number().optional(),
|
|
56503
|
+
aqi: number().optional().meta(readingMeta("index")),
|
|
56163
56504
|
/** Ms epoch when the slice was last updated. */
|
|
56164
|
-
lastFetchedAt: number()
|
|
56165
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
56166
|
-
* `attributes.unit_of_measurement` → 'ppm' / 'ppb' / 'µg/m³'). Each
|
|
56167
|
-
* upstream `sensor.*` entity surfaces ONE device_class, so one unit
|
|
56168
|
-
* per slice is unambiguous. */
|
|
56169
|
-
unit: string().optional(),
|
|
56170
|
-
/** Suggested decimal places for numeric display.
|
|
56171
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
56172
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
56173
|
-
* auto-formatting when absent. */
|
|
56174
|
-
precision: number().int().min(0).max(10).optional()
|
|
56505
|
+
lastFetchedAt: number()
|
|
56175
56506
|
});
|
|
56176
56507
|
DeviceType.Sensor;
|
|
56177
56508
|
object({
|
|
56178
|
-
/** Current illuminance in lux (lx). */
|
|
56179
|
-
lux: number().min(0).meta({
|
|
56180
|
-
|
|
56509
|
+
/** Current illuminance in lux (lx). `null` when the sample was refused (D393). */
|
|
56510
|
+
lux: number().min(0).nullable().meta(readingMeta("illuminance", {
|
|
56511
|
+
precision: 0,
|
|
56181
56512
|
label: "Illuminance"
|
|
56182
|
-
}),
|
|
56513
|
+
})),
|
|
56183
56514
|
/** Ms epoch when the slice was last updated. */
|
|
56184
|
-
lastFetchedAt: number()
|
|
56185
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
56186
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
56187
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
56188
|
-
unit: string().optional(),
|
|
56189
|
-
/** Suggested decimal places for numeric display.
|
|
56190
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
56191
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
56192
|
-
* auto-formatting when absent. */
|
|
56193
|
-
precision: number().int().min(0).max(10).optional()
|
|
56515
|
+
lastFetchedAt: number()
|
|
56194
56516
|
});
|
|
56195
56517
|
DeviceType.Sensor;
|
|
56196
56518
|
/**
|
|
@@ -56335,10 +56657,7 @@ var BatteryStatusSchema = object({
|
|
|
56335
56657
|
* Consumers must SKIP a null rather than coerce it — `battery-band` already
|
|
56336
56658
|
* declines to band a non-finite reading, which is the correct shape.
|
|
56337
56659
|
*/
|
|
56338
|
-
percentage: number().min(0).max(100).nullable().meta({
|
|
56339
|
-
unit: "%",
|
|
56340
|
-
label: "Charge"
|
|
56341
|
-
}),
|
|
56660
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage", { label: "Charge" })),
|
|
56342
56661
|
/**
|
|
56343
56662
|
* Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
|
|
56344
56663
|
* Reolink-specific for the Solar Panel 2 accessory (will become
|
|
@@ -56365,7 +56684,14 @@ var BatteryStatusSchema = object({
|
|
|
56365
56684
|
*/
|
|
56366
56685
|
sleeping: boolean().meta({ label: "Sleeping" }),
|
|
56367
56686
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
56368
|
-
lastUpdated: number(),
|
|
56687
|
+
lastUpdated: number().meta(readingMeta("none")),
|
|
56688
|
+
/**
|
|
56689
|
+
* Battery voltage in volts, for a cell the firmware reports as voltage
|
|
56690
|
+
* rather than a percentage (Ecowitt capacitor packs). Absent on cameras
|
|
56691
|
+
* that only report charge. A second reading on this cap, not a second
|
|
56692
|
+
* `numeric-sensor` on the same device.
|
|
56693
|
+
*/
|
|
56694
|
+
volts: number().nullable().optional().meta(readingMeta("voltage", { label: "Voltage" })),
|
|
56369
56695
|
/**
|
|
56370
56696
|
* Ms epoch of the last time the device PROVED it was reachable — a
|
|
56371
56697
|
* completed firmware round-trip, an observed wake, or an inbound push
|
|
@@ -56425,7 +56751,7 @@ object({
|
|
|
56425
56751
|
DeviceType.Sensor;
|
|
56426
56752
|
object({
|
|
56427
56753
|
/** Current level as 0..100 inclusive. Firmware-reported. */
|
|
56428
|
-
percentage: number().min(0).max(100),
|
|
56754
|
+
percentage: number().min(0).max(100).meta(readingMeta("percentage")),
|
|
56429
56755
|
/** Ms epoch of the last operator-driven change. Useful for UI freshness. */
|
|
56430
56756
|
lastChangedAt: number()
|
|
56431
56757
|
});
|
|
@@ -56810,21 +57136,21 @@ object({
|
|
|
56810
57136
|
/** Single setpoint in Celsius. Used by single-target modes
|
|
56811
57137
|
* (heat / cool / dry). Null when the device is in a range mode
|
|
56812
57138
|
* (`heat_cool`) or has no setpoint at all (`fan_only`/`off`). */
|
|
56813
|
-
target: number().nullable(),
|
|
57139
|
+
target: number().nullable().meta(readingMeta("temperature")),
|
|
56814
57140
|
/** Upper bound of the dual setpoint in Celsius. Populated only
|
|
56815
57141
|
* in `heat_cool` mode. */
|
|
56816
|
-
targetHigh: number().nullable(),
|
|
57142
|
+
targetHigh: number().nullable().meta(readingMeta("temperature")),
|
|
56817
57143
|
/** Lower bound of the dual setpoint in Celsius. Populated only
|
|
56818
57144
|
* in `heat_cool` mode. */
|
|
56819
|
-
targetLow: number().nullable(),
|
|
57145
|
+
targetLow: number().nullable().meta(readingMeta("temperature")),
|
|
56820
57146
|
/** Target relative humidity (0..100). Null when the device has no
|
|
56821
57147
|
* humidity control. */
|
|
56822
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
57148
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
56823
57149
|
/** Current measured temperature in Celsius. Read-only — pushed by
|
|
56824
57150
|
* the device's internal sensor. */
|
|
56825
|
-
currentTemp: number().nullable(),
|
|
57151
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
56826
57152
|
/** Current measured relative humidity (0..100). Read-only. */
|
|
56827
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
57153
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
56828
57154
|
/** Vertical louver swing on/off. Null when the device has no vertical
|
|
56829
57155
|
* swing surface (gate with `DeviceFeature.ClimateSwingVertical`). */
|
|
56830
57156
|
swingVertical: boolean().nullable(),
|
|
@@ -56832,11 +57158,11 @@ object({
|
|
|
56832
57158
|
* horizontal swing surface (gate with `DeviceFeature.ClimateSwingHorizontal`). */
|
|
56833
57159
|
swingHorizontal: boolean().nullable(),
|
|
56834
57160
|
/** Lowest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
56835
|
-
minTemp: number().nullable().optional(),
|
|
57161
|
+
minTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
56836
57162
|
/** Highest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
56837
|
-
maxTemp: number().nullable().optional(),
|
|
57163
|
+
maxTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
56838
57164
|
/** Setpoint granularity, Celsius (0.5, 1). Absent / null = not reported. */
|
|
56839
|
-
tempStep: number().positive().nullable().optional(),
|
|
57165
|
+
tempStep: number().positive().nullable().optional().meta(readingMeta("temperature")),
|
|
56840
57166
|
/** Ms epoch when the slice was last updated (push or command). */
|
|
56841
57167
|
lastFetchedAt: number()
|
|
56842
57168
|
});
|
|
@@ -56915,17 +57241,17 @@ DeviceType.Thermostat, DeviceType.Climate, method(object({
|
|
|
56915
57241
|
* modes to expose in the picker without a slice fetch.
|
|
56916
57242
|
*/
|
|
56917
57243
|
var RgbTripletSchema = object({
|
|
56918
|
-
r: number().int().min(0).max(255),
|
|
56919
|
-
g: number().int().min(0).max(255),
|
|
56920
|
-
b: number().int().min(0).max(255)
|
|
57244
|
+
r: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
57245
|
+
g: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
57246
|
+
b: number().int().min(0).max(255).meta(readingMeta("none"))
|
|
56921
57247
|
});
|
|
56922
57248
|
var HsvTripletSchema = object({
|
|
56923
57249
|
/** Hue in degrees, 0..360. */
|
|
56924
|
-
h: number().min(0).max(360),
|
|
57250
|
+
h: number().min(0).max(360).meta(readingMeta("none")),
|
|
56925
57251
|
/** Saturation as 0..100 inclusive. */
|
|
56926
|
-
s: number().min(0).max(100),
|
|
57252
|
+
s: number().min(0).max(100).meta(readingMeta("none")),
|
|
56927
57253
|
/** Value/brightness as 0..100 inclusive. */
|
|
56928
|
-
v: number().min(0).max(100)
|
|
57254
|
+
v: number().min(0).max(100).meta(readingMeta("none"))
|
|
56929
57255
|
});
|
|
56930
57256
|
var ColorInputSchema = discriminatedUnion("mode", [
|
|
56931
57257
|
object({
|
|
@@ -56954,7 +57280,7 @@ object({
|
|
|
56954
57280
|
/** Populated when `mode === 'hsv'`. */
|
|
56955
57281
|
hsv: HsvTripletSchema.optional(),
|
|
56956
57282
|
/** Populated when `mode === 'mired'`. */
|
|
56957
|
-
mireds: number().int().optional(),
|
|
57283
|
+
mireds: number().int().optional().meta(readingMeta("colour-temperature")),
|
|
56958
57284
|
/** Ms epoch of the last operator-driven change. */
|
|
56959
57285
|
lastChangedAt: number()
|
|
56960
57286
|
});
|
|
@@ -57078,18 +57404,12 @@ _enum([
|
|
|
57078
57404
|
"empty",
|
|
57079
57405
|
"full"
|
|
57080
57406
|
]);
|
|
57081
|
-
/**
|
|
57082
|
-
|
|
57083
|
-
|
|
57084
|
-
"days",
|
|
57085
|
-
"hours",
|
|
57086
|
-
"cycles"
|
|
57087
|
-
]);
|
|
57088
|
-
/** Remaining life as a COUNT, not a percentage (the PetKit desiccant reports
|
|
57089
|
-
* days). `value` null = unknown (D393). */
|
|
57407
|
+
/** Whether `remaining.value` is a duration in seconds or a dimensionless count. */
|
|
57408
|
+
var ConsumableRemainingKindSchema = _enum(["duration", "count"]);
|
|
57409
|
+
/** Remaining life. `value` null = unknown (D393). Duration is seconds. */
|
|
57090
57410
|
var ConsumableRemainingSchema = object({
|
|
57091
|
-
value: number().min(0).nullable(),
|
|
57092
|
-
|
|
57411
|
+
value: number().min(0).nullable().meta(readingMeta("device")),
|
|
57412
|
+
kind: ConsumableRemainingKindSchema
|
|
57093
57413
|
});
|
|
57094
57414
|
var ConsumablesStatusSchema = object({
|
|
57095
57415
|
items: array(object({
|
|
@@ -57098,7 +57418,7 @@ var ConsumablesStatusSchema = object({
|
|
|
57098
57418
|
/** Display name. */
|
|
57099
57419
|
label: string().min(1),
|
|
57100
57420
|
/** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
|
|
57101
|
-
level: number().min(0).max(100).nullable(),
|
|
57421
|
+
level: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
57102
57422
|
/** The provider's discrete verdict when known (binary mode). */
|
|
57103
57423
|
status: ConsumableStatusSchema.nullable(),
|
|
57104
57424
|
/** What the item is — decides whether low or full is bad. Absent = `wear`. */
|
|
@@ -57115,7 +57435,7 @@ var ConsumablesStatusSchema = object({
|
|
|
57115
57435
|
})),
|
|
57116
57436
|
lastChangedAt: number()
|
|
57117
57437
|
});
|
|
57118
|
-
Object.values(DeviceType), [...
|
|
57438
|
+
Object.values(DeviceType), [...ConsumableRemainingKindSchema.options], [...ConsumableStatusSchema.options], [...ConsumableKindSchema.options], [...ConsumableFormSchema.options];
|
|
57119
57439
|
Object.values(DeviceType), method(object({
|
|
57120
57440
|
deviceId: number().int().nonnegative(),
|
|
57121
57441
|
key: string().min(1)
|
|
@@ -57140,39 +57460,17 @@ object({
|
|
|
57140
57460
|
/** Current value. Numeric kind → number; select/text/datetime → string.
|
|
57141
57461
|
* Datetime values are ISO 8601 strings (full timestamp, date-only,
|
|
57142
57462
|
* or time-only — HA accepts all three forms). */
|
|
57143
|
-
value: union([number(), string()]),
|
|
57463
|
+
value: union([number().meta(readingMeta("device")), string()]),
|
|
57144
57464
|
/** Acceptable values when `kind === 'select'`. Empty for other kinds. */
|
|
57145
57465
|
options: array(string()),
|
|
57146
57466
|
/** Ms epoch when the slice was last updated. */
|
|
57147
57467
|
lastChangedAt: number(),
|
|
57148
|
-
/**
|
|
57149
|
-
|
|
57150
|
-
|
|
57151
|
-
|
|
57152
|
-
/**
|
|
57153
|
-
|
|
57154
|
-
min: number().optional(),
|
|
57155
|
-
/** Maximum allowed value. Populated live from HA `attributes.max`.
|
|
57156
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
57157
|
-
max: number().optional(),
|
|
57158
|
-
/** Step increment. Populated live from HA `attributes.step`.
|
|
57159
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
57160
|
-
step: number().optional(),
|
|
57161
|
-
/** Suggested decimal places for numeric display. Populated live from HA
|
|
57162
|
-
* `attributes.suggested_display_precision`, or derived from `step` when the
|
|
57163
|
-
* HA attribute is absent. Meaningful for `kind === 'numeric'`; absent for
|
|
57164
|
-
* other kinds. Falls back to auto-formatting when absent. */
|
|
57165
|
-
precision: number().int().min(0).max(10).optional(),
|
|
57166
|
-
/** Date-picker granularity for `kind === 'datetime'`. 'date' → date-only,
|
|
57167
|
-
* 'time' → time-only, 'datetime' → full timestamp. Absent for other kinds
|
|
57168
|
-
* (UI defaults to 'datetime'). Derived live from the device's HA domain
|
|
57169
|
-
* (date.* / time.* / datetime.*) or, for input_datetime, from the entity's
|
|
57170
|
-
* `has_date`/`has_time` attributes on each push. */
|
|
57171
|
-
format: _enum([
|
|
57172
|
-
"date",
|
|
57173
|
-
"time",
|
|
57174
|
-
"datetime"
|
|
57175
|
-
]).optional()
|
|
57468
|
+
/** Minimum allowed value, in the device quantity's base unit. */
|
|
57469
|
+
min: number().optional().meta(readingMeta("device")),
|
|
57470
|
+
/** Maximum allowed value, in the device quantity's base unit. */
|
|
57471
|
+
max: number().optional().meta(readingMeta("device")),
|
|
57472
|
+
/** Step increment, in the device quantity's base unit. */
|
|
57473
|
+
step: number().optional().meta(readingMeta("device"))
|
|
57176
57474
|
});
|
|
57177
57475
|
var ControlSetValueInputSchema = discriminatedUnion("kind", [
|
|
57178
57476
|
object({
|
|
@@ -57210,9 +57508,9 @@ object({
|
|
|
57210
57508
|
]),
|
|
57211
57509
|
/** 0 = fully closed, 100 = fully open. Null when the device has
|
|
57212
57510
|
* no intermediate position surface. */
|
|
57213
|
-
position: number().min(0).max(100).nullable(),
|
|
57511
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
57214
57512
|
/** 0 = closed slats, 100 = open slats. Null when no tilt support. */
|
|
57215
|
-
tiltPosition: number().min(0).max(100).nullable(),
|
|
57513
|
+
tiltPosition: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
57216
57514
|
/** Ms epoch when the slice was last updated. */
|
|
57217
57515
|
lastChangedAt: number()
|
|
57218
57516
|
});
|
|
@@ -57270,9 +57568,9 @@ var NormalizedRangeSchema$1 = object({
|
|
|
57270
57568
|
object({
|
|
57271
57569
|
mode: DayNightModeSchema,
|
|
57272
57570
|
/** IR-cut trigger sensitivity, NORMALIZED 0–100 (higher = switches to night sooner). */
|
|
57273
|
-
sensitivity: number().optional(),
|
|
57571
|
+
sensitivity: number().optional().meta(readingMeta("none")),
|
|
57274
57572
|
/** Delay before the IR-cut filter flips, in seconds. */
|
|
57275
|
-
switchDelaySec: number().optional(),
|
|
57573
|
+
switchDelaySec: number().optional().meta(readingMeta("duration")),
|
|
57276
57574
|
lastFetchedAt: number()
|
|
57277
57575
|
});
|
|
57278
57576
|
/**
|
|
@@ -57427,11 +57725,11 @@ object({
|
|
|
57427
57725
|
/** Feature keys of the programs the appliance currently offers — drives the UI selector. */
|
|
57428
57726
|
availablePrograms: array(string()),
|
|
57429
57727
|
/** Seconds remaining on the active cycle, or null when not running / not known. */
|
|
57430
|
-
remainingSeconds: number().int().nonnegative().nullable(),
|
|
57728
|
+
remainingSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
57431
57729
|
/** Seconds the delayed start is set to (time until the cycle starts), or null. */
|
|
57432
|
-
delayedStartSeconds: number().int().nonnegative().nullable(),
|
|
57730
|
+
delayedStartSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
57433
57731
|
/** Cycle completion 0..100, or null when not applicable. */
|
|
57434
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
57732
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
57435
57733
|
/** True when the door is reported open; null when the door state is not known. */
|
|
57436
57734
|
doorOpen: boolean().nullable(),
|
|
57437
57735
|
/** True when the door is latched (locked) during a cycle; null when not reported. */
|
|
@@ -57455,7 +57753,7 @@ object({
|
|
|
57455
57753
|
/** True while the machine-care (descaling / cleaning-program) reminder is raised; false when clear; null when not reported. */
|
|
57456
57754
|
machineCareDue: boolean().nullable(),
|
|
57457
57755
|
/** Program runs left before the machine-care reminder is due; null when the appliance does not say. */
|
|
57458
|
-
machineCareRemainingRuns: number().int().nonnegative().nullable(),
|
|
57756
|
+
machineCareRemainingRuns: number().int().nonnegative().nullable().meta(readingMeta("count")),
|
|
57459
57757
|
/** Option states: null when the appliance does not expose the option or has not said. */
|
|
57460
57758
|
halfLoad: boolean().nullable(),
|
|
57461
57759
|
hygienePlus: boolean().nullable(),
|
|
@@ -57470,7 +57768,7 @@ object({
|
|
|
57470
57768
|
/** Feature keys of the events currently raised (salt low, rinse aid low, program finished, …). */
|
|
57471
57769
|
activeEvents: array(string()),
|
|
57472
57770
|
/** Numeric error code when the appliance reports one; null otherwise. */
|
|
57473
|
-
errorCode: number().nullable(),
|
|
57771
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
57474
57772
|
/** Name of the raised alert-level event while the appliance is in error; null otherwise. */
|
|
57475
57773
|
errorLabel: string().nullable(),
|
|
57476
57774
|
/** Ms epoch of the last value received from the appliance; 0 = never. */
|
|
@@ -57616,24 +57914,14 @@ object({
|
|
|
57616
57914
|
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
57617
57915
|
lastPressedAt: number().nullable(),
|
|
57618
57916
|
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
57619
|
-
pressCountSinceStart: number()
|
|
57917
|
+
pressCountSinceStart: number().meta(readingMeta("count"))
|
|
57620
57918
|
});
|
|
57621
57919
|
object({
|
|
57622
57920
|
deviceId: number(),
|
|
57623
57921
|
timestamp: number()
|
|
57624
57922
|
});
|
|
57625
57923
|
DeviceType.Button, DeviceType.Camera;
|
|
57626
|
-
|
|
57627
|
-
* Enum-state sensor — a string value picked from a finite option set.
|
|
57628
|
-
* Drives HA `sensor` entries with `state_class: enum` (HVAC action
|
|
57629
|
-
* states, weather conditions, contact-source channels, mode strings).
|
|
57630
|
-
* The option set is stable across observations; it is persisted in the
|
|
57631
|
-
* device config blob (via the control slice at adoption) and is NOT
|
|
57632
|
-
* stored in `sourceInfo`.
|
|
57633
|
-
*/
|
|
57634
|
-
/** Locale-render shape for an ISO `value` carried by a `DateTimeSensor`-role
|
|
57635
|
-
* enum sensor: `date` (date-only), `time` (time-only), `datetime` (both). */
|
|
57636
|
-
var EnumSensorDateTimeFormatSchema = _enum([
|
|
57924
|
+
_enum([
|
|
57637
57925
|
"date",
|
|
57638
57926
|
"time",
|
|
57639
57927
|
"datetime"
|
|
@@ -57641,12 +57929,11 @@ var EnumSensorDateTimeFormatSchema = _enum([
|
|
|
57641
57929
|
object({
|
|
57642
57930
|
value: string(),
|
|
57643
57931
|
/**
|
|
57644
|
-
* Set
|
|
57645
|
-
* as
|
|
57646
|
-
*
|
|
57647
|
-
* a time-only sensor → `'time'`.
|
|
57932
|
+
* Set when `value` is a timestamp rather than an enum state, so history
|
|
57933
|
+
* does not learn ISO strings as states. The display shape (date / time /
|
|
57934
|
+
* datetime) lives on `SourceInfo.dateTimeShape`, written once at adopt.
|
|
57648
57935
|
*/
|
|
57649
|
-
|
|
57936
|
+
timestamp: boolean().optional(),
|
|
57650
57937
|
/** Ms epoch when the slice was last updated. */
|
|
57651
57938
|
lastFetchedAt: number()
|
|
57652
57939
|
});
|
|
@@ -57665,13 +57952,13 @@ var EventFireSchema = object({
|
|
|
57665
57952
|
deviceId: number(),
|
|
57666
57953
|
eventType: string(),
|
|
57667
57954
|
data: record(string(), unknown()).nullable(),
|
|
57668
|
-
timestamp: number(),
|
|
57669
|
-
seq: number()
|
|
57955
|
+
timestamp: number().meta(readingMeta("none")),
|
|
57956
|
+
seq: number().meta(readingMeta("count"))
|
|
57670
57957
|
});
|
|
57671
57958
|
object({
|
|
57672
57959
|
eventTypes: array(string()),
|
|
57673
57960
|
lastEvent: EventFireSchema.nullable(),
|
|
57674
|
-
eventCountSinceStart: number()
|
|
57961
|
+
eventCountSinceStart: number().meta(readingMeta("count"))
|
|
57675
57962
|
});
|
|
57676
57963
|
DeviceType.EventEmitter;
|
|
57677
57964
|
var IdentitySchema = object({
|
|
@@ -58060,10 +58347,10 @@ var FanDirectionSchema = _enum(["forward", "reverse"]);
|
|
|
58060
58347
|
object({
|
|
58061
58348
|
/** Active speed as 0..100 inclusive. Null when the device has no
|
|
58062
58349
|
* speed surface (single-speed fan). */
|
|
58063
|
-
percentage: number().min(0).max(100).nullable(),
|
|
58350
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58064
58351
|
/** Speed granularity the device accepts (HA `percentage_step`, e.g. 25 for
|
|
58065
58352
|
* a 4-speed fan). Absent when unknown — the UI then falls back to step 1. */
|
|
58066
|
-
percentageStep: number().positive().optional(),
|
|
58353
|
+
percentageStep: number().positive().optional().meta(readingMeta("percentage")),
|
|
58067
58354
|
/** Active preset mode (`auto` / `quiet` / `turbo` / vendor-specific)
|
|
58068
58355
|
* — empty string when no preset is active or supported. */
|
|
58069
58356
|
preset: string(),
|
|
@@ -58145,7 +58432,7 @@ var FeatureProbeStatusSchema = object({
|
|
|
58145
58432
|
/** Camera/firmware model string. `null` when the firmware doesn't expose it. */
|
|
58146
58433
|
model: string().nullable(),
|
|
58147
58434
|
/** Channel count for NVR/Hub devices; `1` for standalone cameras; `null` pre-probe. */
|
|
58148
|
-
channelCount: number().nullable(),
|
|
58435
|
+
channelCount: number().nullable().meta(readingMeta("count")),
|
|
58149
58436
|
/**
|
|
58150
58437
|
* Ms epoch of the last SUCCESSFUL probe. `0` before the first probe
|
|
58151
58438
|
* completes — drivers' `getAccessoryChildren()` should treat zero as
|
|
@@ -58177,9 +58464,27 @@ object({
|
|
|
58177
58464
|
lastChangedAt: number()
|
|
58178
58465
|
});
|
|
58179
58466
|
DeviceType.Sensor;
|
|
58467
|
+
object({
|
|
58468
|
+
/** Members whose current value entered the aggregate. */
|
|
58469
|
+
included: number().int().nonnegative().meta(readingMeta("count", {
|
|
58470
|
+
precision: 0,
|
|
58471
|
+
label: "Reporting"
|
|
58472
|
+
})),
|
|
58473
|
+
/** Members left out: offline, unknown, or not a finite reading (D393). */
|
|
58474
|
+
excluded: number().int().nonnegative().meta(readingMeta("count", {
|
|
58475
|
+
precision: 0,
|
|
58476
|
+
label: "Excluded"
|
|
58477
|
+
})),
|
|
58478
|
+
/** `included` + `excluded`. */
|
|
58479
|
+
total: number().int().nonnegative().meta(readingMeta("count", {
|
|
58480
|
+
precision: 0,
|
|
58481
|
+
label: "Members"
|
|
58482
|
+
}))
|
|
58483
|
+
});
|
|
58484
|
+
DeviceType.Sensor;
|
|
58180
58485
|
object({
|
|
58181
58486
|
/** Radiator valve opening 0 (closed) .. 100 (open). Null = not yet known. */
|
|
58182
|
-
position: number().min(0).max(100).nullable(),
|
|
58487
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58183
58488
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
58184
58489
|
lastFetchedAt: number()
|
|
58185
58490
|
});
|
|
@@ -58188,9 +58493,9 @@ object({
|
|
|
58188
58493
|
/** Whether the humidifier is currently on. */
|
|
58189
58494
|
on: boolean(),
|
|
58190
58495
|
/** Current measured relative humidity (0..100). Null when not reported. */
|
|
58191
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
58496
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
58192
58497
|
/** Target relative humidity (0..100). Null when no setpoint surface. */
|
|
58193
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
58498
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
58194
58499
|
/** Active mode (`auto` / `normal` / `baby` / vendor). Null when the
|
|
58195
58500
|
* device has no mode surface. */
|
|
58196
58501
|
mode: string().nullable(),
|
|
@@ -58200,9 +58505,9 @@ object({
|
|
|
58200
58505
|
* `idle` / `off`). Null when the device doesn't report it. */
|
|
58201
58506
|
action: string().nullable(),
|
|
58202
58507
|
/** HA `min_humidity` attribute. Null → UI uses 0. */
|
|
58203
|
-
minHumidity: number().nullable(),
|
|
58508
|
+
minHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
58204
58509
|
/** HA `max_humidity` attribute. Null → UI uses 100. */
|
|
58205
|
-
maxHumidity: number().nullable(),
|
|
58510
|
+
maxHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
58206
58511
|
/** Ms epoch when the slice was last updated. */
|
|
58207
58512
|
lastChangedAt: number()
|
|
58208
58513
|
});
|
|
@@ -58226,22 +58531,13 @@ DeviceType.Humidifier, method(object({
|
|
|
58226
58531
|
auth: "protected"
|
|
58227
58532
|
});
|
|
58228
58533
|
object({
|
|
58229
|
-
/** Current relative humidity, 0..100. */
|
|
58230
|
-
percent: number().min(0).max(100).meta({
|
|
58231
|
-
|
|
58534
|
+
/** Current relative humidity, 0..100. `null` when the sample was refused (D393). */
|
|
58535
|
+
percent: number().min(0).max(100).nullable().meta(readingMeta("humidity", {
|
|
58536
|
+
precision: 0,
|
|
58232
58537
|
label: "Humidity"
|
|
58233
|
-
}),
|
|
58538
|
+
})),
|
|
58234
58539
|
/** Ms epoch when the slice was last updated. */
|
|
58235
|
-
lastFetchedAt: number()
|
|
58236
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
58237
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
58238
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
58239
|
-
unit: string().optional(),
|
|
58240
|
-
/** Suggested decimal places for numeric display.
|
|
58241
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
58242
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
58243
|
-
* auto-formatting when absent. */
|
|
58244
|
-
precision: number().int().min(0).max(10).optional()
|
|
58540
|
+
lastFetchedAt: number()
|
|
58245
58541
|
});
|
|
58246
58542
|
DeviceType.Sensor, DeviceType.Thermostat;
|
|
58247
58543
|
object({
|
|
@@ -58249,7 +58545,7 @@ object({
|
|
|
58249
58545
|
* entity exposes no `entity_picture` (yet). */
|
|
58250
58546
|
url: string().nullable(),
|
|
58251
58547
|
/** Ms epoch of the upstream last-updated timestamp. Null at cold-start. */
|
|
58252
|
-
lastUpdated: number().nullable()
|
|
58548
|
+
lastUpdated: number().nullable().meta(readingMeta("none"))
|
|
58253
58549
|
});
|
|
58254
58550
|
DeviceType.Image;
|
|
58255
58551
|
/**
|
|
@@ -58305,19 +58601,19 @@ var NormalizedRangeSchema = object({
|
|
|
58305
58601
|
});
|
|
58306
58602
|
object({
|
|
58307
58603
|
/** Normalized 0–100. */
|
|
58308
|
-
brightness: number().optional(),
|
|
58604
|
+
brightness: number().optional().meta(readingMeta("none")),
|
|
58309
58605
|
/** Normalized 0–100. */
|
|
58310
|
-
contrast: number().optional(),
|
|
58606
|
+
contrast: number().optional().meta(readingMeta("none")),
|
|
58311
58607
|
/** Normalized 0–100. */
|
|
58312
|
-
saturation: number().optional(),
|
|
58608
|
+
saturation: number().optional().meta(readingMeta("none")),
|
|
58313
58609
|
/** Normalized 0–100. */
|
|
58314
|
-
sharpness: number().optional(),
|
|
58610
|
+
sharpness: number().optional().meta(readingMeta("none")),
|
|
58315
58611
|
mirror: boolean().optional(),
|
|
58316
58612
|
flip: boolean().optional(),
|
|
58317
58613
|
rotate: ImageRotateSchema.optional(),
|
|
58318
58614
|
whiteBalance: WhiteBalanceModeSchema.optional(),
|
|
58319
58615
|
/** Manual white-balance warmth, NORMALIZED 0–100. Meaningful only when `whiteBalance === 'manual'`. */
|
|
58320
|
-
warmth: number().optional(),
|
|
58616
|
+
warmth: number().optional().meta(readingMeta("none")),
|
|
58321
58617
|
exposureMode: ExposureModeSchema.optional(),
|
|
58322
58618
|
backlightMode: BacklightModeSchema.optional(),
|
|
58323
58619
|
lastFetchedAt: number()
|
|
@@ -58562,10 +58858,10 @@ var IntercomAbilitySchema = object({
|
|
|
58562
58858
|
/** Codecs accepted by firmware, in preference order. Driver-authored strings. */
|
|
58563
58859
|
codecs: array(string()),
|
|
58564
58860
|
/** Sample rate (Hz) the firmware expects. Reolink typical: 16000. */
|
|
58565
|
-
sampleRate: number(),
|
|
58861
|
+
sampleRate: number().meta(readingMeta("none")),
|
|
58566
58862
|
duplex: _enum(["half", "full"]),
|
|
58567
58863
|
/** Max in-flight audio backlog before drop (ms). Server uses this to bound latency. */
|
|
58568
|
-
maxBacklogMs: number()
|
|
58864
|
+
maxBacklogMs: number().meta(readingMeta("duration-ms"))
|
|
58569
58865
|
});
|
|
58570
58866
|
var IntercomStatusSchema = object({
|
|
58571
58867
|
/** True while a talk session is open. */
|
|
@@ -58676,13 +58972,13 @@ object({
|
|
|
58676
58972
|
activity: LawnMowerActivitySchema,
|
|
58677
58973
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
58678
58974
|
* reading. */
|
|
58679
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
58975
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58680
58976
|
/** 0..100 mowing-completion percentage of the current task, or null when no
|
|
58681
58977
|
* task is active / progress is unavailable. */
|
|
58682
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
58978
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58683
58979
|
/** Current device/event code (dynamic — mostly status, sometimes an error),
|
|
58684
58980
|
* or null when unknown. */
|
|
58685
|
-
currentCode: number().nullable(),
|
|
58981
|
+
currentCode: number().nullable().meta(readingMeta("none")),
|
|
58686
58982
|
/** Human label for {@link currentCode}, or null when undecodable. */
|
|
58687
58983
|
currentCodeLabel: string().nullable(),
|
|
58688
58984
|
/** Severity of {@link currentCode}. `error` (and often `warning`) warrants UI
|
|
@@ -59144,7 +59440,7 @@ object({
|
|
|
59144
59440
|
state: MediaPlayerStateSchema,
|
|
59145
59441
|
/** Volume as 0..100 inclusive. Null when the device has no volume
|
|
59146
59442
|
* surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
|
|
59147
|
-
volumeLevel: number().min(0).max(100).nullable(),
|
|
59443
|
+
volumeLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59148
59444
|
/** Mute toggle distinct from volume=0. Null when no mute surface.
|
|
59149
59445
|
* Pair with `DeviceFeature.MediaPlayerMute`. */
|
|
59150
59446
|
isMuted: boolean().nullable(),
|
|
@@ -59157,10 +59453,10 @@ object({
|
|
|
59157
59453
|
currentMedia: MediaInfoSchema.nullable(),
|
|
59158
59454
|
/** Current playback position in ms. Null when not seekable or
|
|
59159
59455
|
* nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
|
|
59160
|
-
positionMs: number().int().nonnegative().nullable(),
|
|
59456
|
+
positionMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
59161
59457
|
/** Total duration of the current media in ms. Null when unknown
|
|
59162
59458
|
* (live stream) or nothing is playing. */
|
|
59163
|
-
durationMs: number().int().nonnegative().nullable(),
|
|
59459
|
+
durationMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
59164
59460
|
/** Shuffle toggle. Null when no shuffle surface.
|
|
59165
59461
|
* Pair with `DeviceFeature.MediaPlayerShuffle`. */
|
|
59166
59462
|
shuffle: boolean().nullable(),
|
|
@@ -59460,7 +59756,7 @@ object({
|
|
|
59460
59756
|
* it, every provider seeded it at boot, and every session left it
|
|
59461
59757
|
* `detected: true` after its detach.
|
|
59462
59758
|
*/
|
|
59463
|
-
autoClearAfterMs: number().nullable()
|
|
59759
|
+
autoClearAfterMs: number().nullable().meta(readingMeta("duration-ms"))
|
|
59464
59760
|
});
|
|
59465
59761
|
/**
|
|
59466
59762
|
* Payload of `motion.onMotionChanged` event + the corresponding bus
|
|
@@ -59510,7 +59806,7 @@ var MotionZoneRegionSchema = object({
|
|
|
59510
59806
|
});
|
|
59511
59807
|
object({
|
|
59512
59808
|
enabled: boolean(),
|
|
59513
|
-
sensitivity: number(),
|
|
59809
|
+
sensitivity: number().meta(readingMeta("none")),
|
|
59514
59810
|
/** Grid region(s). Today exactly one `grid` shape. */
|
|
59515
59811
|
regions: array(MotionZoneRegionSchema),
|
|
59516
59812
|
lastFetchedAt: number()
|
|
@@ -59814,7 +60110,7 @@ var NavigationStatusSchema = object({
|
|
|
59814
60110
|
following: boolean(),
|
|
59815
60111
|
flash: boolean(),
|
|
59816
60112
|
lightMode: NavigationLightModeSchema,
|
|
59817
|
-
lightLevel: number().min(40).max(100),
|
|
60113
|
+
lightLevel: number().min(40).max(100).meta(readingMeta("none")),
|
|
59818
60114
|
/** Ms epoch when the slice was last updated. */
|
|
59819
60115
|
lastChangedAt: number()
|
|
59820
60116
|
});
|
|
@@ -59860,13 +60156,13 @@ var NetworkLinkStatusSchema = object({
|
|
|
59860
60156
|
* one whose reading has not landed must not be drawn at 0 %. Consumers
|
|
59861
60157
|
* SKIP a null rather than coerce it.
|
|
59862
60158
|
*/
|
|
59863
|
-
signalPercent: number().min(0).max(100).nullable(),
|
|
60159
|
+
signalPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59864
60160
|
/** Raw received signal strength in dBm, when the firmware reports one. */
|
|
59865
|
-
rssiDbm: number().optional(),
|
|
60161
|
+
rssiDbm: number().optional().meta(readingMeta("signal-level")),
|
|
59866
60162
|
/** Network name of a wireless link, when the firmware reports it. */
|
|
59867
60163
|
ssid: string().optional(),
|
|
59868
60164
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
59869
|
-
lastUpdated: number()
|
|
60165
|
+
lastUpdated: number().meta(readingMeta("none"))
|
|
59870
60166
|
});
|
|
59871
60167
|
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.Light, DeviceType.Lock, DeviceType.Siren, object({
|
|
59872
60168
|
deviceId: number(),
|
|
@@ -60185,7 +60481,7 @@ object({
|
|
|
60185
60481
|
lastError: string().nullable(),
|
|
60186
60482
|
/** Number of deliveries currently buffered server-side (rate-limited
|
|
60187
60483
|
* notifiers may queue). 0 when the provider sends synchronously. */
|
|
60188
|
-
queueDepth: number().int().nonnegative(),
|
|
60484
|
+
queueDepth: number().int().nonnegative().meta(readingMeta("count")),
|
|
60189
60485
|
/** Per-feature capability matrix — authoritative source for the
|
|
60190
60486
|
* compose-form field gating. */
|
|
60191
60487
|
supports: NotifierSupportsSchema
|
|
@@ -60235,15 +60531,8 @@ DeviceType.Notifier, method(NotifierSendInputSchema, NotifierSendResultSchema, {
|
|
|
60235
60531
|
acceptedAt: number()
|
|
60236
60532
|
});
|
|
60237
60533
|
object({
|
|
60238
|
-
|
|
60239
|
-
|
|
60240
|
-
* Populated live from the upstream source on each state push.
|
|
60241
|
-
* Absent for unitless sensors. */
|
|
60242
|
-
unit: string().optional(),
|
|
60243
|
-
/** Suggested decimal places for numeric display.
|
|
60244
|
-
* Populated live from the upstream source when provided.
|
|
60245
|
-
* Falls back to auto-formatting when absent. */
|
|
60246
|
-
precision: number().int().min(0).max(10).optional(),
|
|
60534
|
+
/** Reading in the device quantity's base unit. `null` when refused (D393). */
|
|
60535
|
+
value: number().nullable().meta(readingMeta("device")),
|
|
60247
60536
|
/** Ms epoch when the slice was last updated. */
|
|
60248
60537
|
lastFetchedAt: number()
|
|
60249
60538
|
});
|
|
@@ -60533,23 +60822,26 @@ object({
|
|
|
60533
60822
|
/** Food currently in the bowl (grams). Null when the device has not
|
|
60534
60823
|
* reported a reading yet. On dual-hopper models this is the combined
|
|
60535
60824
|
* bowl reading; per-hopper levels live in `food1`/`food2`. */
|
|
60536
|
-
foodLevel: number().nullable(),
|
|
60825
|
+
foodLevel: number().nullable().meta(readingMeta("none")),
|
|
60537
60826
|
/** Hopper-1 food level (grams) on dual-hopper feeders; null on
|
|
60538
60827
|
* single-hopper models. */
|
|
60539
|
-
food1: number().nullable(),
|
|
60828
|
+
food1: number().nullable().meta(readingMeta("none")),
|
|
60540
60829
|
/** Hopper-2 food level (grams) on dual-hopper feeders; null on
|
|
60541
60830
|
* single-hopper models. */
|
|
60542
|
-
food2: number().nullable(),
|
|
60831
|
+
food2: number().nullable().meta(readingMeta("none")),
|
|
60543
60832
|
/** Derived low-food flag — mirrors the HA `food_level` binary_sensor
|
|
60544
60833
|
* (`device_class: problem`, on = low). True when the bowl is empty /
|
|
60545
60834
|
* below the feeder's low threshold. */
|
|
60546
60835
|
lowFood: boolean(),
|
|
60547
60836
|
/** Battery charge 0..100 (%). Null on mains-powered models or when the
|
|
60548
60837
|
* device has no battery reading. */
|
|
60549
|
-
batteryPower: number().min(0).max(100).nullable(),
|
|
60550
|
-
/**
|
|
60551
|
-
*
|
|
60552
|
-
|
|
60838
|
+
batteryPower: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
60839
|
+
/**
|
|
60840
|
+
* Desiccant life remaining, stored in seconds (duration base, D944).
|
|
60841
|
+
* Providers convert from the days the feeder reports. Null when the
|
|
60842
|
+
* model has no desiccant sensor.
|
|
60843
|
+
*/
|
|
60844
|
+
desiccantLeftDays: number().nullable().meta(readingMeta("duration")),
|
|
60553
60845
|
/** True while a feed is in progress. */
|
|
60554
60846
|
feeding: boolean(),
|
|
60555
60847
|
/** Decoded connectivity / power status (HA petkit device-status enum).
|
|
@@ -60560,7 +60852,7 @@ object({
|
|
|
60560
60852
|
* with `errorCode` for consumers that want the raw integer. */
|
|
60561
60853
|
error: string().nullable(),
|
|
60562
60854
|
/** Raw device error code (0 / null = no error). */
|
|
60563
|
-
errorCode: number().nullable(),
|
|
60855
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
60564
60856
|
/** True for D4S/D4SH dual-hopper hardware — gates the per-hopper UI. */
|
|
60565
60857
|
isDualHopper: boolean(),
|
|
60566
60858
|
/** Child-lock (manual-lock) setting — buttons on the unit are disabled. */
|
|
@@ -60570,7 +60862,7 @@ object({
|
|
|
60570
60862
|
/** Play a chime when dispensing. */
|
|
60571
60863
|
feedSound: boolean(),
|
|
60572
60864
|
/** Speaker / prompt volume level (device-scaled integer). */
|
|
60573
|
-
volume: number(),
|
|
60865
|
+
volume: number().meta(readingMeta("none")),
|
|
60574
60866
|
/** Ms epoch when the slice was last refreshed from the cloud. */
|
|
60575
60867
|
lastFetchedAt: number()
|
|
60576
60868
|
});
|
|
@@ -61007,36 +61299,19 @@ method(_void(), PlatformCapabilitiesSchema), method(_void(), HardwareInfoSchema)
|
|
|
61007
61299
|
});
|
|
61008
61300
|
object({
|
|
61009
61301
|
/** Instantaneous power draw in watts. */
|
|
61010
|
-
watts: number().optional().meta({
|
|
61011
|
-
unit: "W",
|
|
61012
|
-
label: "Power"
|
|
61013
|
-
}),
|
|
61302
|
+
watts: number().optional().meta(readingMeta("power", { label: "Power" })),
|
|
61014
61303
|
/** Cumulative energy in kilowatt-hours since the meter was reset. */
|
|
61015
|
-
kwhTotal: number().optional().meta({
|
|
61016
|
-
unit: "kWh",
|
|
61017
|
-
label: "Energy"
|
|
61018
|
-
}),
|
|
61304
|
+
kwhTotal: number().optional().meta(readingMeta("energy", { label: "Energy" })),
|
|
61019
61305
|
/** Voltage in volts. */
|
|
61020
|
-
volts: number().optional(),
|
|
61306
|
+
volts: number().optional().meta(readingMeta("voltage")),
|
|
61021
61307
|
/** Current in amperes. */
|
|
61022
|
-
amps: number().optional(),
|
|
61023
|
-
/** Apparent power in volt-amperes
|
|
61024
|
-
va: number().optional(),
|
|
61308
|
+
amps: number().optional().meta(readingMeta("current")),
|
|
61309
|
+
/** Apparent power in volt-amperes. */
|
|
61310
|
+
va: number().optional().meta(readingMeta("apparent-power")),
|
|
61025
61311
|
/** Power factor (0..1) if reported. */
|
|
61026
|
-
powerFactor: number().min(0).max(1).optional(),
|
|
61312
|
+
powerFactor: number().min(0).max(1).optional().meta(readingMeta("ratio")),
|
|
61027
61313
|
/** Ms epoch when the slice was last updated. */
|
|
61028
|
-
lastFetchedAt: number()
|
|
61029
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
61030
|
-
* `attributes.unit_of_measurement` → 'V' / 'A' / 'W' / 'kW' / 'kWh').
|
|
61031
|
-
* Each upstream `sensor.*` entity surfaces ONE device_class, so one
|
|
61032
|
-
* unit per slice is unambiguous. The UI prefers this over the role's
|
|
61033
|
-
* canonical unit so a 'kW' / 'Wh' feed renders verbatim. */
|
|
61034
|
-
unit: string().optional(),
|
|
61035
|
-
/** Suggested decimal places for numeric display.
|
|
61036
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
61037
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
61038
|
-
* auto-formatting when absent. */
|
|
61039
|
-
precision: number().int().min(0).max(10).optional()
|
|
61314
|
+
lastFetchedAt: number()
|
|
61040
61315
|
});
|
|
61041
61316
|
DeviceType.Sensor;
|
|
61042
61317
|
/**
|
|
@@ -61057,11 +61332,11 @@ DeviceType.Sensor;
|
|
|
61057
61332
|
*/
|
|
61058
61333
|
var GpsLocationSchema = object({
|
|
61059
61334
|
/** Latitude in decimal degrees, -90..90. */
|
|
61060
|
-
latitude: number().min(-90).max(90),
|
|
61335
|
+
latitude: number().min(-90).max(90).meta(readingMeta("angle")),
|
|
61061
61336
|
/** Longitude in decimal degrees, -180..180. */
|
|
61062
|
-
longitude: number().min(-180).max(180),
|
|
61337
|
+
longitude: number().min(-180).max(180).meta(readingMeta("angle")),
|
|
61063
61338
|
/** Reported accuracy in meters (lower = better). */
|
|
61064
|
-
accuracyMeters: number().nonnegative()
|
|
61339
|
+
accuracyMeters: number().nonnegative().meta(readingMeta("length"))
|
|
61065
61340
|
});
|
|
61066
61341
|
object({
|
|
61067
61342
|
/** `home` / `not_home` / any user-defined zone name. */
|
|
@@ -61073,25 +61348,16 @@ object({
|
|
|
61073
61348
|
gps: GpsLocationSchema.nullable(),
|
|
61074
61349
|
/** Optional battery level of the tracking device (0..100). Null
|
|
61075
61350
|
* when not reported. */
|
|
61076
|
-
batteryPercent: number().min(0).max(100).nullable(),
|
|
61351
|
+
batteryPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61077
61352
|
/** Ms epoch when the slice was last updated. */
|
|
61078
61353
|
lastChangedAt: number()
|
|
61079
61354
|
});
|
|
61080
61355
|
DeviceType.Presence;
|
|
61081
61356
|
object({
|
|
61082
|
-
/** Current pressure in hPa. */
|
|
61083
|
-
hpa: number(),
|
|
61357
|
+
/** Current pressure in hPa. `null` when the sample was refused (D393). */
|
|
61358
|
+
hpa: number().nullable().meta(readingMeta("pressure", { precision: 0 })),
|
|
61084
61359
|
/** Ms epoch when the slice was last updated. */
|
|
61085
|
-
lastFetchedAt: number()
|
|
61086
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
61087
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
61088
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
61089
|
-
unit: string().optional(),
|
|
61090
|
-
/** Suggested decimal places for numeric display.
|
|
61091
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
61092
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
61093
|
-
* auto-formatting when absent. */
|
|
61094
|
-
precision: number().int().min(0).max(10).optional()
|
|
61360
|
+
lastFetchedAt: number()
|
|
61095
61361
|
});
|
|
61096
61362
|
DeviceType.Sensor;
|
|
61097
61363
|
/**
|
|
@@ -61424,8 +61690,8 @@ DeviceType.Camera, method(PtzMoveCommandSchema.extend({ deviceId: number() }), _
|
|
|
61424
61690
|
}), _void(), { kind: "mutation" });
|
|
61425
61691
|
var PtzAutotrackSettingsSchema = object({
|
|
61426
61692
|
targetType: string().describe("Vendor target string (people/vehicle/pet); empty = camera default"),
|
|
61427
|
-
stopDelaySeconds: number().int().min(0).max(300),
|
|
61428
|
-
disappearDelaySeconds: number().int().min(0).max(300)
|
|
61693
|
+
stopDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration")),
|
|
61694
|
+
disappearDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration"))
|
|
61429
61695
|
});
|
|
61430
61696
|
/**
|
|
61431
61697
|
* One option the camera advertises as a valid `targetType`. Drivers
|
|
@@ -61482,7 +61748,7 @@ object({
|
|
|
61482
61748
|
/** null = unknown — never coerced to false (D393). */
|
|
61483
61749
|
running: boolean().nullable(),
|
|
61484
61750
|
/** Epoch ms the current boolean began; null while `running` is null. */
|
|
61485
|
-
since: number().nullable(),
|
|
61751
|
+
since: number().nullable().meta(readingMeta("none")),
|
|
61486
61752
|
source: RunningStateSourceSchema.meta({ label: "Source" }),
|
|
61487
61753
|
phase: string().nullable(),
|
|
61488
61754
|
/** null until a reading has been published (D393). */
|
|
@@ -62680,9 +62946,9 @@ var RecordTriggerSchema = _enum([
|
|
|
62680
62946
|
*/
|
|
62681
62947
|
var RecordWindowSchema = object({
|
|
62682
62948
|
trigger: RecordTriggerSchema,
|
|
62683
|
-
day: number().int().min(0).max(6),
|
|
62684
|
-
startMinute: number().int().min(0).max(1439),
|
|
62685
|
-
endMinute: number().int().min(1).max(1440)
|
|
62949
|
+
day: number().int().min(0).max(6).meta(readingMeta("none")),
|
|
62950
|
+
startMinute: number().int().min(0).max(1439).meta(readingMeta("none")),
|
|
62951
|
+
endMinute: number().int().min(1).max(1440).meta(readingMeta("none"))
|
|
62686
62952
|
});
|
|
62687
62953
|
/** Status of one physical volume, as the camera itself describes it. */
|
|
62688
62954
|
var OnboardStorageVolumeSchema = object({
|
|
@@ -62751,10 +63017,10 @@ object({
|
|
|
62751
63017
|
/** Master "record to the card at all" switch. */
|
|
62752
63018
|
enabled: boolean().nullable(),
|
|
62753
63019
|
overwriteWhenFull: boolean().nullable(),
|
|
62754
|
-
preRecordSec: number().nullable(),
|
|
62755
|
-
postRecordSec: number().nullable(),
|
|
63020
|
+
preRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
63021
|
+
postRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
62756
63022
|
/** Length of one recorded file, in minutes. */
|
|
62757
|
-
segmentMinutes: number().nullable(),
|
|
63023
|
+
segmentMinutes: number().nullable().meta(readingMeta("none")),
|
|
62758
63024
|
/** The primary track's weekly windows, flattened. */
|
|
62759
63025
|
windows: array(RecordWindowSchema),
|
|
62760
63026
|
/**
|
|
@@ -62770,7 +63036,7 @@ object({
|
|
|
62770
63036
|
* provider reporting a non-zero count also reports the schedule as not
|
|
62771
63037
|
* writable.
|
|
62772
63038
|
*/
|
|
62773
|
-
unreadableWindows: number(),
|
|
63039
|
+
unreadableWindows: number().meta(readingMeta("count")),
|
|
62774
63040
|
/**
|
|
62775
63041
|
* The camera is scheduled to record and has NO usable storage.
|
|
62776
63042
|
*
|
|
@@ -63407,7 +63673,7 @@ var CamStreamDescriptorSchema = object({
|
|
|
63407
63673
|
url: string().optional(),
|
|
63408
63674
|
codec: string().optional(),
|
|
63409
63675
|
resolution: CamStreamResolutionSchema.optional(),
|
|
63410
|
-
fps: number().positive().optional(),
|
|
63676
|
+
fps: number().positive().optional().meta(readingMeta("rate")),
|
|
63411
63677
|
label: string().optional(),
|
|
63412
63678
|
/** Device-level features (e.g. `battery-operated`) — drives broker policy. */
|
|
63413
63679
|
deviceFeatures: array(string()).optional(),
|
|
@@ -63437,18 +63703,18 @@ var StreamProfileSchema = _enum([
|
|
|
63437
63703
|
]);
|
|
63438
63704
|
/** The current encoding config of one stream profile. */
|
|
63439
63705
|
var StreamProfileConfigSchema = object({
|
|
63440
|
-
width: number(),
|
|
63441
|
-
height: number(),
|
|
63706
|
+
width: number().meta(readingMeta("none")),
|
|
63707
|
+
height: number().meta(readingMeta("none")),
|
|
63442
63708
|
codec: _enum(["h264", "h265"]),
|
|
63443
|
-
framerate: number(),
|
|
63444
|
-
bitrate: number(),
|
|
63709
|
+
framerate: number().meta(readingMeta("rate")),
|
|
63710
|
+
bitrate: number().meta(readingMeta("bitrate")),
|
|
63445
63711
|
bitrateMode: _enum(["vbr", "cbr"]).optional(),
|
|
63446
63712
|
encoderProfile: _enum([
|
|
63447
63713
|
"high",
|
|
63448
63714
|
"main",
|
|
63449
63715
|
"baseline"
|
|
63450
63716
|
]).optional(),
|
|
63451
|
-
gop: number().optional(),
|
|
63717
|
+
gop: number().optional().meta(readingMeta("none")),
|
|
63452
63718
|
/**
|
|
63453
63719
|
* Whether THIS profile currently carries an audio track. READ-ONLY here.
|
|
63454
63720
|
*
|
|
@@ -64091,23 +64357,13 @@ object({
|
|
|
64091
64357
|
});
|
|
64092
64358
|
DeviceType.Sensor;
|
|
64093
64359
|
object({
|
|
64094
|
-
/** Current temperature in Celsius. */
|
|
64095
|
-
celsius: number().meta({
|
|
64096
|
-
|
|
64360
|
+
/** Current temperature in Celsius. `null` when the sample was refused (D393). */
|
|
64361
|
+
celsius: number().nullable().meta(readingMeta("temperature", {
|
|
64362
|
+
precision: 1,
|
|
64097
64363
|
label: "Temperature"
|
|
64098
|
-
}),
|
|
64364
|
+
})),
|
|
64099
64365
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
64100
|
-
lastFetchedAt: number()
|
|
64101
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
64102
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
64103
|
-
* role's canonical unit, so a Fahrenheit feed renders '°F' not '°C'.
|
|
64104
|
-
* Absent → the UI falls back to the role's canonical unit. */
|
|
64105
|
-
unit: string().optional(),
|
|
64106
|
-
/** Suggested decimal places for numeric display.
|
|
64107
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
64108
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
64109
|
-
* auto-formatting when absent. */
|
|
64110
|
-
precision: number().int().min(0).max(10).optional()
|
|
64366
|
+
lastFetchedAt: number()
|
|
64111
64367
|
});
|
|
64112
64368
|
DeviceType.Sensor, DeviceType.Thermostat;
|
|
64113
64369
|
/**
|
|
@@ -64359,16 +64615,16 @@ object({
|
|
|
64359
64615
|
]),
|
|
64360
64616
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
64361
64617
|
* reading. */
|
|
64362
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
64618
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
64363
64619
|
/** Current fan-speed token (provider-verbatim). Null when unknown or
|
|
64364
64620
|
* the vacuum has no speed control. */
|
|
64365
64621
|
fanSpeed: string().nullable(),
|
|
64366
64622
|
/** Speed tokens the hardware accepts — drives the UI selector. */
|
|
64367
64623
|
availableFanSpeeds: array(string()),
|
|
64368
64624
|
/** 0..100 cleaning-completion percentage of the current task, or null. */
|
|
64369
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
64625
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
64370
64626
|
/** Current error code (0 / null = no error). */
|
|
64371
|
-
errorCode: number().nullable(),
|
|
64627
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
64372
64628
|
/** Human label for {@link errorCode}, or null when none / undecodable. */
|
|
64373
64629
|
errorLabel: string().nullable(),
|
|
64374
64630
|
/** Ms epoch when the slice was last updated. */
|
|
@@ -64407,7 +64663,7 @@ object({
|
|
|
64407
64663
|
]),
|
|
64408
64664
|
/** 0 = fully closed, 100 = fully open. Null when the device has no
|
|
64409
64665
|
* intermediate position surface. */
|
|
64410
|
-
position: number().min(0).max(100).nullable(),
|
|
64666
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
64411
64667
|
/** Ms epoch when the slice was last updated. */
|
|
64412
64668
|
lastChangedAt: number()
|
|
64413
64669
|
});
|
|
@@ -64435,9 +64691,9 @@ object({
|
|
|
64435
64691
|
DeviceType.Sensor;
|
|
64436
64692
|
object({
|
|
64437
64693
|
/** Current measured temperature. Null when not reported. */
|
|
64438
|
-
currentTemp: number().nullable(),
|
|
64694
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
64439
64695
|
/** Target temperature setpoint. Null when no setpoint surface. */
|
|
64440
|
-
targetTemp: number().nullable(),
|
|
64696
|
+
targetTemp: number().nullable().meta(readingMeta("temperature")),
|
|
64441
64697
|
/** Active operation mode = HA `state` (`eco` / `electric` / `gas` /
|
|
64442
64698
|
* `heat_pump` / `high_demand` / `performance` / `off`). Null when the
|
|
64443
64699
|
* device reports an unknown state. */
|
|
@@ -64448,9 +64704,9 @@ object({
|
|
|
64448
64704
|
* has no away surface. */
|
|
64449
64705
|
away: boolean().nullable(),
|
|
64450
64706
|
/** HA `min_temp` attribute. Null when not reported. */
|
|
64451
|
-
minTemp: number().nullable(),
|
|
64707
|
+
minTemp: number().nullable().meta(readingMeta("temperature")),
|
|
64452
64708
|
/** HA `max_temp` attribute. Null when not reported. */
|
|
64453
|
-
maxTemp: number().nullable(),
|
|
64709
|
+
maxTemp: number().nullable().meta(readingMeta("temperature")),
|
|
64454
64710
|
/** Ms epoch when the slice was last updated. */
|
|
64455
64711
|
lastChangedAt: number()
|
|
64456
64712
|
});
|
|
@@ -64474,25 +64730,18 @@ DeviceType.WaterHeater, method(object({
|
|
|
64474
64730
|
auth: "protected"
|
|
64475
64731
|
});
|
|
64476
64732
|
object({
|
|
64477
|
-
/** Verbatim
|
|
64478
|
-
* when no condition has been reported yet. */
|
|
64733
|
+
/** Verbatim condition state (`sunny`, `cloudy`, `rainy`, …). Null when none yet. */
|
|
64479
64734
|
condition: string().nullable(),
|
|
64480
|
-
/** Current temperature in
|
|
64481
|
-
temperature: number().nullable(),
|
|
64482
|
-
/** Temperature unit string (e.g. `°C` / `°F`). Null when not provided. */
|
|
64483
|
-
temperatureUnit: string().nullable(),
|
|
64735
|
+
/** Current temperature in Celsius. Null when not provided or refused. */
|
|
64736
|
+
temperature: number().nullable().meta(readingMeta("temperature", { precision: 1 })),
|
|
64484
64737
|
/** Relative humidity (0..100). Null when not provided. */
|
|
64485
|
-
humidity: number().min(0).max(100).nullable(),
|
|
64486
|
-
/** Barometric pressure in
|
|
64487
|
-
pressure: number().nullable(),
|
|
64488
|
-
/**
|
|
64489
|
-
|
|
64490
|
-
/** Wind speed in the reported unit. Null when not provided. */
|
|
64491
|
-
windSpeed: number().nullable(),
|
|
64492
|
-
/** Wind-speed unit string (e.g. `km/h` / `mph`). Null when not provided. */
|
|
64493
|
-
windSpeedUnit: string().nullable(),
|
|
64738
|
+
humidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
64739
|
+
/** Barometric pressure in hPa. Null when not provided or refused. */
|
|
64740
|
+
pressure: number().nullable().meta(readingMeta("pressure")),
|
|
64741
|
+
/** Wind speed in metres per second. Null when not provided or refused. */
|
|
64742
|
+
windSpeed: number().nullable().meta(readingMeta("speed")),
|
|
64494
64743
|
/** Wind bearing in degrees (0..360, meteorological). Null when not provided. */
|
|
64495
|
-
windBearing: number().nullable(),
|
|
64744
|
+
windBearing: number().nullable().meta(readingMeta("angle")),
|
|
64496
64745
|
/** Ms epoch when the slice was last updated. */
|
|
64497
64746
|
lastFetchedAt: number()
|
|
64498
64747
|
});
|
|
@@ -68614,6 +68863,13 @@ Object.freeze({
|
|
|
68614
68863
|
access: "view",
|
|
68615
68864
|
role: "viewer"
|
|
68616
68865
|
},
|
|
68866
|
+
"groupStatus.getStatus": {
|
|
68867
|
+
capName: "group-status",
|
|
68868
|
+
capScope: "device",
|
|
68869
|
+
addonId: null,
|
|
68870
|
+
access: "view",
|
|
68871
|
+
role: "viewer"
|
|
68872
|
+
},
|
|
68617
68873
|
"heatingValve.getStatus": {
|
|
68618
68874
|
capName: "heating-valve",
|
|
68619
68875
|
capScope: "device",
|
|
@@ -78436,6 +78692,33 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78436
78692
|
icon: "flame"
|
|
78437
78693
|
}]
|
|
78438
78694
|
},
|
|
78695
|
+
"group-status": {
|
|
78696
|
+
scope: "device",
|
|
78697
|
+
noun: t("Group", "Gruppo"),
|
|
78698
|
+
state: [
|
|
78699
|
+
{
|
|
78700
|
+
kind: "numeric",
|
|
78701
|
+
field: "included",
|
|
78702
|
+
quantity: t("the members reporting", "i membri che rispondono"),
|
|
78703
|
+
label: t("Reporting", "Rispondono"),
|
|
78704
|
+
icon: "users"
|
|
78705
|
+
},
|
|
78706
|
+
{
|
|
78707
|
+
kind: "numeric",
|
|
78708
|
+
field: "excluded",
|
|
78709
|
+
quantity: t("the members left out", "i membri esclusi"),
|
|
78710
|
+
label: t("Excluded", "Esclusi"),
|
|
78711
|
+
icon: "users"
|
|
78712
|
+
},
|
|
78713
|
+
{
|
|
78714
|
+
kind: "numeric",
|
|
78715
|
+
field: "total",
|
|
78716
|
+
quantity: t("the member count", "il numero di membri"),
|
|
78717
|
+
label: t("Members", "Membri"),
|
|
78718
|
+
icon: "sigma"
|
|
78719
|
+
}
|
|
78720
|
+
]
|
|
78721
|
+
},
|
|
78439
78722
|
"humidity-sensor": {
|
|
78440
78723
|
scope: "device",
|
|
78441
78724
|
noun: t("Humidity", "Umidità"),
|
|
@@ -78469,7 +78752,6 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78469
78752
|
field: "value",
|
|
78470
78753
|
quantity: t("the reading", "il valore"),
|
|
78471
78754
|
label: t("Reading", "Valore"),
|
|
78472
|
-
unitField: "unit",
|
|
78473
78755
|
icon: "gauge"
|
|
78474
78756
|
}]
|
|
78475
78757
|
},
|
|
@@ -78605,7 +78887,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78605
78887
|
field: "temperature",
|
|
78606
78888
|
quantity: t("the outdoor temperature", "la temperatura esterna"),
|
|
78607
78889
|
label: t("Temperature", "Temperatura"),
|
|
78608
|
-
|
|
78890
|
+
unit: "°C",
|
|
78609
78891
|
icon: "thermometer"
|
|
78610
78892
|
},
|
|
78611
78893
|
{
|
|
@@ -78621,7 +78903,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78621
78903
|
field: "windSpeed",
|
|
78622
78904
|
quantity: t("the wind speed", "la velocità del vento"),
|
|
78623
78905
|
label: t("Wind", "Vento"),
|
|
78624
|
-
|
|
78906
|
+
unit: "m/s",
|
|
78625
78907
|
icon: "wind"
|
|
78626
78908
|
},
|
|
78627
78909
|
{
|
|
@@ -78629,7 +78911,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78629
78911
|
field: "pressure",
|
|
78630
78912
|
quantity: t("the air pressure", "la pressione atmosferica"),
|
|
78631
78913
|
label: t("Pressure", "Pressione"),
|
|
78632
|
-
|
|
78914
|
+
unit: "hPa",
|
|
78633
78915
|
icon: "gauge"
|
|
78634
78916
|
}
|
|
78635
78917
|
]
|
|
@@ -79902,6 +80184,11 @@ Object.freeze({
|
|
|
79902
80184
|
form: "single",
|
|
79903
80185
|
optional: false
|
|
79904
80186
|
}],
|
|
80187
|
+
"groupStatus.getStatus": [{
|
|
80188
|
+
name: "deviceId",
|
|
80189
|
+
form: "single",
|
|
80190
|
+
optional: false
|
|
80191
|
+
}],
|
|
79905
80192
|
"heatingValve.getStatus": [{
|
|
79906
80193
|
name: "deviceId",
|
|
79907
80194
|
form: "single",
|