@camstack/addon-model-studio 1.1.296 → 1.1.298
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-DOhuE4t6.mjs → MotionZonesSettings-B9K4WWi1.mjs} +21 -21
- package/dist/{PrivacyMaskSettings-BtQIysUm.mjs → PrivacyMaskSettings-onRhNbik.mjs} +4 -4
- package/dist/{SceneMonitorEditor-B4cEP3UH.mjs → SceneMonitorEditor-DKUa9q8G.mjs} +71 -71
- package/dist/_stub.js +4255 -4182
- package/dist/{_virtual_mf-localSharedImportMap___mfe_internal__addon_model_studio_page-DoLsYz9K.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_model_studio_page-DeNyK8AH.mjs} +3 -3
- package/dist/_virtual_mf___mfe_internal__addon_model_studio_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-Bkw5bZBe.mjs +26 -0
- package/dist/{hostInit-BfsN6Dh3.mjs → hostInit-ChdJLKG2.mjs} +2 -2
- package/dist/model-studio.addon.js +717 -430
- package/dist/model-studio.addon.mjs +717 -430
- package/dist/{player-overlays-BVHDRE8f.mjs → player-overlays-DAdFiwTN.mjs} +1 -1
- package/dist/remoteEntry.js +1 -1
- package/dist/{responsive-CI-NtcQi.mjs → responsive-D_nfEXa_.mjs} +13 -10
- package/dist/{scene-monitor-copy-CvzuJJ8Z.mjs → scene-monitor-copy-CnNe3kRP.mjs} +1 -1
- package/dist/{square-CsljmL2M.mjs → square-DqNJ_s4z.mjs} +1 -1
- package/dist/{trash-2-DwX9K1LA.mjs → trash-2-GWwk-1z0.mjs} +1 -1
- package/dist/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_model_studio_page__remoteEntry_js-CoN9WY8L.mjs → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_model_studio_page__remoteEntry_js-TjjXHsNj.mjs} +1 -1
- package/package.json +1 -1
- package/dist/_virtual_mf___mfe_internal__addon_model_studio_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-CDZyIXC0.mjs +0 -26
|
@@ -5829,7 +5829,7 @@ var ZodIssueCode = {
|
|
|
5829
5829
|
var ZodFirstPartyTypeKind;
|
|
5830
5830
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5831
5831
|
//#endregion
|
|
5832
|
-
//#region ../types/dist/sleep-
|
|
5832
|
+
//#region ../types/dist/sleep-B81gwQuR.mjs
|
|
5833
5833
|
/**
|
|
5834
5834
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5835
5835
|
* window to float samples (D455).
|
|
@@ -8316,6 +8316,99 @@ var RecordKindDeclarationSchema = object({
|
|
|
8316
8316
|
}).strict();
|
|
8317
8317
|
/** The kind names: lower-case, dash separated, short enough for an index name. */
|
|
8318
8318
|
var RecordKindNameSchema = string().regex(/^[a-z][a-z0-9-]{0,47}$/);
|
|
8319
|
+
var READING_QUANTITIES = [
|
|
8320
|
+
"temperature",
|
|
8321
|
+
"pressure",
|
|
8322
|
+
"speed",
|
|
8323
|
+
"precipitation",
|
|
8324
|
+
"precipitation-rate",
|
|
8325
|
+
"length",
|
|
8326
|
+
"area",
|
|
8327
|
+
"illuminance",
|
|
8328
|
+
"irradiance",
|
|
8329
|
+
"power",
|
|
8330
|
+
"energy",
|
|
8331
|
+
"voltage",
|
|
8332
|
+
"current",
|
|
8333
|
+
"apparent-power",
|
|
8334
|
+
"humidity",
|
|
8335
|
+
"percentage",
|
|
8336
|
+
"concentration-volume",
|
|
8337
|
+
"concentration-mass",
|
|
8338
|
+
"concentration-ppb",
|
|
8339
|
+
"volume",
|
|
8340
|
+
"duration",
|
|
8341
|
+
"duration-ms",
|
|
8342
|
+
"information",
|
|
8343
|
+
"sound-level",
|
|
8344
|
+
"signal-level",
|
|
8345
|
+
"colour-temperature",
|
|
8346
|
+
"angle",
|
|
8347
|
+
"bitrate",
|
|
8348
|
+
"rate",
|
|
8349
|
+
"mass",
|
|
8350
|
+
"index",
|
|
8351
|
+
"ratio",
|
|
8352
|
+
"count",
|
|
8353
|
+
"none",
|
|
8354
|
+
"device"
|
|
8355
|
+
];
|
|
8356
|
+
var ReadingQuantitySchema = _enum(READING_QUANTITIES);
|
|
8357
|
+
new Set(READING_QUANTITIES);
|
|
8358
|
+
/**
|
|
8359
|
+
* Stored unit symbol for a quantity. `none` means the number is dimensionless
|
|
8360
|
+
* (or an index / ratio / count). `device` means the cap has no single unit.
|
|
8361
|
+
*/
|
|
8362
|
+
var QUANTITY_BASE = {
|
|
8363
|
+
temperature: "°C",
|
|
8364
|
+
pressure: "hPa",
|
|
8365
|
+
speed: "m/s",
|
|
8366
|
+
precipitation: "mm",
|
|
8367
|
+
"precipitation-rate": "mm/h",
|
|
8368
|
+
length: "m",
|
|
8369
|
+
area: "m²",
|
|
8370
|
+
illuminance: "lx",
|
|
8371
|
+
irradiance: "W/m²",
|
|
8372
|
+
power: "W",
|
|
8373
|
+
energy: "kWh",
|
|
8374
|
+
voltage: "V",
|
|
8375
|
+
current: "A",
|
|
8376
|
+
"apparent-power": "VA",
|
|
8377
|
+
humidity: "%",
|
|
8378
|
+
percentage: "%",
|
|
8379
|
+
"concentration-volume": "ppm",
|
|
8380
|
+
"concentration-mass": "µg/m³",
|
|
8381
|
+
"concentration-ppb": "ppb",
|
|
8382
|
+
volume: "L",
|
|
8383
|
+
duration: "s",
|
|
8384
|
+
"duration-ms": "ms",
|
|
8385
|
+
information: "B",
|
|
8386
|
+
"sound-level": "dBFS",
|
|
8387
|
+
"signal-level": "dBm",
|
|
8388
|
+
"colour-temperature": "mired",
|
|
8389
|
+
angle: "°",
|
|
8390
|
+
bitrate: "kbps",
|
|
8391
|
+
rate: "fps",
|
|
8392
|
+
mass: "kg",
|
|
8393
|
+
index: "none",
|
|
8394
|
+
ratio: "none",
|
|
8395
|
+
count: "none",
|
|
8396
|
+
none: "none",
|
|
8397
|
+
device: "device"
|
|
8398
|
+
};
|
|
8399
|
+
/** The stored unit, or `undefined` when the quantity has no unit symbol. */
|
|
8400
|
+
function baseUnitOf(quantity) {
|
|
8401
|
+
const symbol = QUANTITY_BASE[quantity];
|
|
8402
|
+
if (symbol === "none" || symbol === "device") return void 0;
|
|
8403
|
+
return symbol;
|
|
8404
|
+
}
|
|
8405
|
+
function readingMeta(quantity, extras) {
|
|
8406
|
+
return {
|
|
8407
|
+
quantity,
|
|
8408
|
+
...extras?.precision !== void 0 ? { precision: extras.precision } : {},
|
|
8409
|
+
...extras?.label !== void 0 ? { label: extras.label } : {}
|
|
8410
|
+
};
|
|
8411
|
+
}
|
|
8319
8412
|
/** Shared Zod schemas used across streaming capabilities. */
|
|
8320
8413
|
var CamProfileSchema = _enum([
|
|
8321
8414
|
"high",
|
|
@@ -8343,8 +8436,8 @@ var CamStreamKindSchema = _enum([
|
|
|
8343
8436
|
"derived"
|
|
8344
8437
|
]);
|
|
8345
8438
|
var CamStreamResolutionSchema = object({
|
|
8346
|
-
width: number().int().positive(),
|
|
8347
|
-
height: number().int().positive()
|
|
8439
|
+
width: number().int().positive().meta(readingMeta("none")),
|
|
8440
|
+
height: number().int().positive().meta(readingMeta("none"))
|
|
8348
8441
|
});
|
|
8349
8442
|
var CameraStreamSchema = object({
|
|
8350
8443
|
/** Stable, provider-assigned id unique within the (deviceId) scope. */
|
|
@@ -8939,6 +9032,7 @@ var CAP_NAMES = Object.freeze([
|
|
|
8939
9032
|
"filesystem-browse",
|
|
8940
9033
|
"flood",
|
|
8941
9034
|
"gas",
|
|
9035
|
+
"group-status",
|
|
8942
9036
|
"heating-valve",
|
|
8943
9037
|
"humidifier",
|
|
8944
9038
|
"humidity-sensor",
|
|
@@ -9068,14 +9162,6 @@ Object.freeze({
|
|
|
9068
9162
|
{
|
|
9069
9163
|
"path": "aqi",
|
|
9070
9164
|
"valueType": "number"
|
|
9071
|
-
},
|
|
9072
|
-
{
|
|
9073
|
-
"path": "unit",
|
|
9074
|
-
"valueType": "string"
|
|
9075
|
-
},
|
|
9076
|
-
{
|
|
9077
|
-
"path": "precision",
|
|
9078
|
-
"valueType": "number"
|
|
9079
9165
|
}
|
|
9080
9166
|
],
|
|
9081
9167
|
"alarm-panel": [
|
|
@@ -9111,20 +9197,10 @@ Object.freeze({
|
|
|
9111
9197
|
"valueType": "boolean"
|
|
9112
9198
|
}
|
|
9113
9199
|
],
|
|
9114
|
-
"ambient-light-sensor": [
|
|
9115
|
-
|
|
9116
|
-
|
|
9117
|
-
|
|
9118
|
-
},
|
|
9119
|
-
{
|
|
9120
|
-
"path": "unit",
|
|
9121
|
-
"valueType": "string"
|
|
9122
|
-
},
|
|
9123
|
-
{
|
|
9124
|
-
"path": "precision",
|
|
9125
|
-
"valueType": "number"
|
|
9126
|
-
}
|
|
9127
|
-
],
|
|
9200
|
+
"ambient-light-sensor": [{
|
|
9201
|
+
"path": "lux",
|
|
9202
|
+
"valueType": "number"
|
|
9203
|
+
}],
|
|
9128
9204
|
"audio-metrics": [
|
|
9129
9205
|
{
|
|
9130
9206
|
"path": "ts",
|
|
@@ -9204,6 +9280,10 @@ Object.freeze({
|
|
|
9204
9280
|
"path": "lastUpdated",
|
|
9205
9281
|
"valueType": "number"
|
|
9206
9282
|
},
|
|
9283
|
+
{
|
|
9284
|
+
"path": "volts",
|
|
9285
|
+
"valueType": "number"
|
|
9286
|
+
},
|
|
9207
9287
|
{
|
|
9208
9288
|
"path": "lastContactAt",
|
|
9209
9289
|
"valueType": "number"
|
|
@@ -9446,10 +9526,6 @@ Object.freeze({
|
|
|
9446
9526
|
"datetime"
|
|
9447
9527
|
]
|
|
9448
9528
|
},
|
|
9449
|
-
{
|
|
9450
|
-
"path": "unit",
|
|
9451
|
-
"valueType": "string"
|
|
9452
|
-
},
|
|
9453
9529
|
{
|
|
9454
9530
|
"path": "min",
|
|
9455
9531
|
"valueType": "number"
|
|
@@ -9461,19 +9537,6 @@ Object.freeze({
|
|
|
9461
9537
|
{
|
|
9462
9538
|
"path": "step",
|
|
9463
9539
|
"valueType": "number"
|
|
9464
|
-
},
|
|
9465
|
-
{
|
|
9466
|
-
"path": "precision",
|
|
9467
|
-
"valueType": "number"
|
|
9468
|
-
},
|
|
9469
|
-
{
|
|
9470
|
-
"path": "format",
|
|
9471
|
-
"valueType": "enum",
|
|
9472
|
-
"enumValues": [
|
|
9473
|
-
"date",
|
|
9474
|
-
"time",
|
|
9475
|
-
"datetime"
|
|
9476
|
-
]
|
|
9477
9540
|
}
|
|
9478
9541
|
],
|
|
9479
9542
|
"cover": [
|
|
@@ -9714,13 +9777,8 @@ Object.freeze({
|
|
|
9714
9777
|
"path": "value",
|
|
9715
9778
|
"valueType": "string"
|
|
9716
9779
|
}, {
|
|
9717
|
-
"path": "
|
|
9718
|
-
"valueType": "
|
|
9719
|
-
"enumValues": [
|
|
9720
|
-
"date",
|
|
9721
|
-
"time",
|
|
9722
|
-
"datetime"
|
|
9723
|
-
]
|
|
9780
|
+
"path": "timestamp",
|
|
9781
|
+
"valueType": "boolean"
|
|
9724
9782
|
}],
|
|
9725
9783
|
"event-emitter": [
|
|
9726
9784
|
{
|
|
@@ -9793,6 +9851,20 @@ Object.freeze({
|
|
|
9793
9851
|
"path": "detected",
|
|
9794
9852
|
"valueType": "boolean"
|
|
9795
9853
|
}],
|
|
9854
|
+
"group-status": [
|
|
9855
|
+
{
|
|
9856
|
+
"path": "included",
|
|
9857
|
+
"valueType": "number"
|
|
9858
|
+
},
|
|
9859
|
+
{
|
|
9860
|
+
"path": "excluded",
|
|
9861
|
+
"valueType": "number"
|
|
9862
|
+
},
|
|
9863
|
+
{
|
|
9864
|
+
"path": "total",
|
|
9865
|
+
"valueType": "number"
|
|
9866
|
+
}
|
|
9867
|
+
],
|
|
9796
9868
|
"heating-valve": [{
|
|
9797
9869
|
"path": "position",
|
|
9798
9870
|
"valueType": "number"
|
|
@@ -9827,20 +9899,10 @@ Object.freeze({
|
|
|
9827
9899
|
"valueType": "number"
|
|
9828
9900
|
}
|
|
9829
9901
|
],
|
|
9830
|
-
"humidity-sensor": [
|
|
9831
|
-
|
|
9832
|
-
|
|
9833
|
-
|
|
9834
|
-
},
|
|
9835
|
-
{
|
|
9836
|
-
"path": "unit",
|
|
9837
|
-
"valueType": "string"
|
|
9838
|
-
},
|
|
9839
|
-
{
|
|
9840
|
-
"path": "precision",
|
|
9841
|
-
"valueType": "number"
|
|
9842
|
-
}
|
|
9843
|
-
],
|
|
9902
|
+
"humidity-sensor": [{
|
|
9903
|
+
"path": "percent",
|
|
9904
|
+
"valueType": "number"
|
|
9905
|
+
}],
|
|
9844
9906
|
"image": [{
|
|
9845
9907
|
"path": "url",
|
|
9846
9908
|
"valueType": "string"
|
|
@@ -10179,20 +10241,10 @@ Object.freeze({
|
|
|
10179
10241
|
"valueType": "boolean"
|
|
10180
10242
|
}
|
|
10181
10243
|
],
|
|
10182
|
-
"numeric-sensor": [
|
|
10183
|
-
|
|
10184
|
-
|
|
10185
|
-
|
|
10186
|
-
},
|
|
10187
|
-
{
|
|
10188
|
-
"path": "unit",
|
|
10189
|
-
"valueType": "string"
|
|
10190
|
-
},
|
|
10191
|
-
{
|
|
10192
|
-
"path": "precision",
|
|
10193
|
-
"valueType": "number"
|
|
10194
|
-
}
|
|
10195
|
-
],
|
|
10244
|
+
"numeric-sensor": [{
|
|
10245
|
+
"path": "value",
|
|
10246
|
+
"valueType": "number"
|
|
10247
|
+
}],
|
|
10196
10248
|
"pet-feeder": [
|
|
10197
10249
|
{
|
|
10198
10250
|
"path": "foodLevel",
|
|
@@ -10284,14 +10336,6 @@ Object.freeze({
|
|
|
10284
10336
|
{
|
|
10285
10337
|
"path": "powerFactor",
|
|
10286
10338
|
"valueType": "number"
|
|
10287
|
-
},
|
|
10288
|
-
{
|
|
10289
|
-
"path": "unit",
|
|
10290
|
-
"valueType": "string"
|
|
10291
|
-
},
|
|
10292
|
-
{
|
|
10293
|
-
"path": "precision",
|
|
10294
|
-
"valueType": "number"
|
|
10295
10339
|
}
|
|
10296
10340
|
],
|
|
10297
10341
|
"presence": [
|
|
@@ -10320,20 +10364,10 @@ Object.freeze({
|
|
|
10320
10364
|
"valueType": "number"
|
|
10321
10365
|
}
|
|
10322
10366
|
],
|
|
10323
|
-
"pressure-sensor": [
|
|
10324
|
-
|
|
10325
|
-
|
|
10326
|
-
|
|
10327
|
-
},
|
|
10328
|
-
{
|
|
10329
|
-
"path": "unit",
|
|
10330
|
-
"valueType": "string"
|
|
10331
|
-
},
|
|
10332
|
-
{
|
|
10333
|
-
"path": "precision",
|
|
10334
|
-
"valueType": "number"
|
|
10335
|
-
}
|
|
10336
|
-
],
|
|
10367
|
+
"pressure-sensor": [{
|
|
10368
|
+
"path": "hpa",
|
|
10369
|
+
"valueType": "number"
|
|
10370
|
+
}],
|
|
10337
10371
|
"privacy-mask": [{
|
|
10338
10372
|
"path": "enabled",
|
|
10339
10373
|
"valueType": "boolean"
|
|
@@ -10644,20 +10678,10 @@ Object.freeze({
|
|
|
10644
10678
|
"path": "tampered",
|
|
10645
10679
|
"valueType": "boolean"
|
|
10646
10680
|
}],
|
|
10647
|
-
"temperature-sensor": [
|
|
10648
|
-
|
|
10649
|
-
|
|
10650
|
-
|
|
10651
|
-
},
|
|
10652
|
-
{
|
|
10653
|
-
"path": "unit",
|
|
10654
|
-
"valueType": "string"
|
|
10655
|
-
},
|
|
10656
|
-
{
|
|
10657
|
-
"path": "precision",
|
|
10658
|
-
"valueType": "number"
|
|
10659
|
-
}
|
|
10660
|
-
],
|
|
10681
|
+
"temperature-sensor": [{
|
|
10682
|
+
"path": "celsius",
|
|
10683
|
+
"valueType": "number"
|
|
10684
|
+
}],
|
|
10661
10685
|
"update": [
|
|
10662
10686
|
{
|
|
10663
10687
|
"path": "currentVersion",
|
|
@@ -10768,10 +10792,6 @@ Object.freeze({
|
|
|
10768
10792
|
"path": "temperature",
|
|
10769
10793
|
"valueType": "number"
|
|
10770
10794
|
},
|
|
10771
|
-
{
|
|
10772
|
-
"path": "temperatureUnit",
|
|
10773
|
-
"valueType": "string"
|
|
10774
|
-
},
|
|
10775
10795
|
{
|
|
10776
10796
|
"path": "humidity",
|
|
10777
10797
|
"valueType": "number"
|
|
@@ -10780,18 +10800,10 @@ Object.freeze({
|
|
|
10780
10800
|
"path": "pressure",
|
|
10781
10801
|
"valueType": "number"
|
|
10782
10802
|
},
|
|
10783
|
-
{
|
|
10784
|
-
"path": "pressureUnit",
|
|
10785
|
-
"valueType": "string"
|
|
10786
|
-
},
|
|
10787
10803
|
{
|
|
10788
10804
|
"path": "windSpeed",
|
|
10789
10805
|
"valueType": "number"
|
|
10790
10806
|
},
|
|
10791
|
-
{
|
|
10792
|
-
"path": "windSpeedUnit",
|
|
10793
|
-
"valueType": "string"
|
|
10794
|
-
},
|
|
10795
10807
|
{
|
|
10796
10808
|
"path": "windBearing",
|
|
10797
10809
|
"valueType": "number"
|
|
@@ -11184,7 +11196,7 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
|
|
|
11184
11196
|
return DeviceRole;
|
|
11185
11197
|
}({});
|
|
11186
11198
|
//#endregion
|
|
11187
|
-
//#region ../types/dist/composition-
|
|
11199
|
+
//#region ../types/dist/composition-B85l9j1M.mjs
|
|
11188
11200
|
/**
|
|
11189
11201
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
11190
11202
|
*
|
|
@@ -11939,15 +11951,67 @@ function validateExpressionSource(src) {
|
|
|
11939
11951
|
}
|
|
11940
11952
|
return null;
|
|
11941
11953
|
}
|
|
11942
|
-
/**
|
|
11943
|
-
|
|
11944
|
-
|
|
11945
|
-
|
|
11954
|
+
/**
|
|
11955
|
+
* A composition source identity: `(addonId, stableId)`, never a numeric device
|
|
11956
|
+
* id. Split out so helper schemas can name it without a cycle through
|
|
11957
|
+
* `composition.ts` (D659).
|
|
11958
|
+
*/
|
|
11946
11959
|
var CompositionSourceRefSchema = object({
|
|
11947
11960
|
/** The owning addon; `stableId` is unique only within it. */
|
|
11948
11961
|
addonId: string().min(1),
|
|
11949
11962
|
stableId: string().min(1)
|
|
11950
11963
|
});
|
|
11964
|
+
var GROUP_TEMPLATE_IDS = [
|
|
11965
|
+
"temperature",
|
|
11966
|
+
"humidity",
|
|
11967
|
+
"pressure",
|
|
11968
|
+
"illuminance",
|
|
11969
|
+
"power",
|
|
11970
|
+
"energy",
|
|
11971
|
+
"battery",
|
|
11972
|
+
"numeric",
|
|
11973
|
+
"motion",
|
|
11974
|
+
"contact",
|
|
11975
|
+
"leak",
|
|
11976
|
+
"smoke",
|
|
11977
|
+
"occupancy",
|
|
11978
|
+
"binary"
|
|
11979
|
+
];
|
|
11980
|
+
var NUMERIC_AGGREGATES = [
|
|
11981
|
+
"mean",
|
|
11982
|
+
"median",
|
|
11983
|
+
"min",
|
|
11984
|
+
"max",
|
|
11985
|
+
"sum"
|
|
11986
|
+
];
|
|
11987
|
+
var BINARY_AGGREGATES = ["any", "all"];
|
|
11988
|
+
var AGGREGATE_REDUCERS = [
|
|
11989
|
+
"mean",
|
|
11990
|
+
"median",
|
|
11991
|
+
"min",
|
|
11992
|
+
"max",
|
|
11993
|
+
"sum",
|
|
11994
|
+
"any",
|
|
11995
|
+
"all"
|
|
11996
|
+
];
|
|
11997
|
+
var GroupTemplateIdSchema = _enum(GROUP_TEMPLATE_IDS);
|
|
11998
|
+
var AggregateReducerSchema = _enum(AGGREGATE_REDUCERS);
|
|
11999
|
+
/** One member. The field is stored so occupancy can name motion or binary. */
|
|
12000
|
+
var HelperMemberSchema = object({
|
|
12001
|
+
source: CompositionSourceRefSchema,
|
|
12002
|
+
cap: string().min(1),
|
|
12003
|
+
fieldPath: string().min(1)
|
|
12004
|
+
});
|
|
12005
|
+
var HelperSpecSchema = discriminatedUnion("kind", [object({
|
|
12006
|
+
kind: literal("group"),
|
|
12007
|
+
templateId: GroupTemplateIdSchema,
|
|
12008
|
+
aggregate: AggregateReducerSchema,
|
|
12009
|
+
members: array(HelperMemberSchema).min(1).max(64)
|
|
12010
|
+
})]);
|
|
12011
|
+
/** A composed device's stableId is this prefix plus the block id. */
|
|
12012
|
+
var COMPOSED_DEVICE_STABLE_ID_PREFIX = "composed-";
|
|
12013
|
+
/** Longest snippet a `code` source may carry (slice 4). */
|
|
12014
|
+
var MAX_COMPOSITION_CODE_LENGTH = 2e4;
|
|
11951
12015
|
/** One field of one capability of one source device. */
|
|
11952
12016
|
var CompositionFieldReadSchema = object({
|
|
11953
12017
|
source: CompositionSourceRefSchema,
|
|
@@ -11991,7 +12055,33 @@ var CompositionCodeSourceSchema = object({
|
|
|
11991
12055
|
var CompositionFieldSourceSchema = discriminatedUnion("kind", [
|
|
11992
12056
|
CompositionFromSourceSchema,
|
|
11993
12057
|
CompositionExpressionSourceSchema,
|
|
11994
|
-
CompositionCodeSourceSchema
|
|
12058
|
+
CompositionCodeSourceSchema,
|
|
12059
|
+
object({
|
|
12060
|
+
kind: literal("aggregate"),
|
|
12061
|
+
reducer: _enum([
|
|
12062
|
+
"mean",
|
|
12063
|
+
"median",
|
|
12064
|
+
"min",
|
|
12065
|
+
"max",
|
|
12066
|
+
"sum",
|
|
12067
|
+
"any",
|
|
12068
|
+
"all"
|
|
12069
|
+
]),
|
|
12070
|
+
reads: array(CompositionFieldReadSchema).min(1).max(64),
|
|
12071
|
+
/** `value` is the reading; the others are the member counts. */
|
|
12072
|
+
publish: _enum([
|
|
12073
|
+
"value",
|
|
12074
|
+
"included",
|
|
12075
|
+
"excluded",
|
|
12076
|
+
"total"
|
|
12077
|
+
]),
|
|
12078
|
+
/** What a `value` publish does when nobody is included. Counts ignore this. */
|
|
12079
|
+
empty: _enum([
|
|
12080
|
+
"null",
|
|
12081
|
+
"omit",
|
|
12082
|
+
"offline"
|
|
12083
|
+
])
|
|
12084
|
+
})
|
|
11995
12085
|
]);
|
|
11996
12086
|
var CompositionCommandTargetSchema = discriminatedUnion("kind", [object({
|
|
11997
12087
|
kind: literal("forward"),
|
|
@@ -12037,7 +12127,13 @@ var CompositionSchema = object({
|
|
|
12037
12127
|
kind: literal("existing"),
|
|
12038
12128
|
device: CompositionSourceRefSchema
|
|
12039
12129
|
})]),
|
|
12040
|
-
features: array(CompositionFeatureSchema).min(1).max(16)
|
|
12130
|
+
features: array(CompositionFeatureSchema).min(1).max(16),
|
|
12131
|
+
/**
|
|
12132
|
+
* Present when the block is a helper template. Absent on a free
|
|
12133
|
+
* composition (the room example, device 4603). The editor reads this,
|
|
12134
|
+
* never the compiled features.
|
|
12135
|
+
*/
|
|
12136
|
+
helper: HelperSpecSchema.optional()
|
|
12041
12137
|
}).superRefine((composition, ctx) => {
|
|
12042
12138
|
const seen = /* @__PURE__ */ new Set();
|
|
12043
12139
|
composition.features.forEach((feature, index) => {
|
|
@@ -18295,7 +18391,11 @@ var CompositionProblemSchema = object({
|
|
|
18295
18391
|
"item-field-reserved",
|
|
18296
18392
|
"target-missing",
|
|
18297
18393
|
"target-unreadable",
|
|
18298
|
-
"not-replaceable"
|
|
18394
|
+
"not-replaceable",
|
|
18395
|
+
"native-capability-replace",
|
|
18396
|
+
"mixed-quantity",
|
|
18397
|
+
"helper-mismatch",
|
|
18398
|
+
"member-constraint"
|
|
18299
18399
|
]),
|
|
18300
18400
|
path: string(),
|
|
18301
18401
|
message: string()
|
|
@@ -18316,7 +18416,8 @@ var CompositionUnavailableModeSchema = _enum([
|
|
|
18316
18416
|
"null",
|
|
18317
18417
|
"offline",
|
|
18318
18418
|
"unknown",
|
|
18319
|
-
"release"
|
|
18419
|
+
"release",
|
|
18420
|
+
"omit"
|
|
18320
18421
|
]);
|
|
18321
18422
|
/**
|
|
18322
18423
|
* `derived` reads a source · `clock` reads only `now`, recomputed when a sibling
|
|
@@ -18353,9 +18454,11 @@ var CompositionFieldPlanSchema = object({
|
|
|
18353
18454
|
reads: array(CompositionFieldReadSchema)
|
|
18354
18455
|
});
|
|
18355
18456
|
/**
|
|
18356
|
-
* What a feature does to its target (D663): `new` builds a capability on a
|
|
18357
|
-
* device; on an existing device it `add`s a capability the device lacks
|
|
18358
|
-
*
|
|
18457
|
+
* What a feature does to its target (D663, D944): `new` builds a capability on a
|
|
18458
|
+
* new device; on an existing device it `add`s a capability the device lacks.
|
|
18459
|
+
* Replacing a capability the device already serves is refused
|
|
18460
|
+
* (`native-capability-replace`), not planned. `replace` remains on the claim
|
|
18461
|
+
* wire for a claim the hub already holds.
|
|
18359
18462
|
*/
|
|
18360
18463
|
var CompositionFeatureModeSchema = _enum([
|
|
18361
18464
|
"new",
|
|
@@ -18528,6 +18631,235 @@ Object.freeze({
|
|
|
18528
18631
|
result: ["number", "null"]
|
|
18529
18632
|
}
|
|
18530
18633
|
});
|
|
18634
|
+
/**
|
|
18635
|
+
* One catalog row per base reading a group helper can build (D944 §3).
|
|
18636
|
+
* Data, not a form default written into the block.
|
|
18637
|
+
*/
|
|
18638
|
+
var NOW = {
|
|
18639
|
+
fieldPath: "lastFetchedAt",
|
|
18640
|
+
expr: "now"
|
|
18641
|
+
};
|
|
18642
|
+
var CHANGED = {
|
|
18643
|
+
fieldPath: "lastChangedAt",
|
|
18644
|
+
expr: "now"
|
|
18645
|
+
};
|
|
18646
|
+
function numeric(input) {
|
|
18647
|
+
return {
|
|
18648
|
+
...input,
|
|
18649
|
+
family: "numeric",
|
|
18650
|
+
deviceType: DeviceType.Sensor,
|
|
18651
|
+
memberDeviceType: DeviceType.Sensor,
|
|
18652
|
+
baseUnit: baseUnitOf(input.quantity),
|
|
18653
|
+
aggregates: NUMERIC_AGGREGATES,
|
|
18654
|
+
accept: [{
|
|
18655
|
+
cap: input.outputCap,
|
|
18656
|
+
fieldPath: input.outputField
|
|
18657
|
+
}]
|
|
18658
|
+
};
|
|
18659
|
+
}
|
|
18660
|
+
function binary(input) {
|
|
18661
|
+
return {
|
|
18662
|
+
...input,
|
|
18663
|
+
family: "binary",
|
|
18664
|
+
deviceType: DeviceType.Sensor,
|
|
18665
|
+
memberDeviceType: DeviceType.Sensor,
|
|
18666
|
+
quantity: "none",
|
|
18667
|
+
baseUnit: void 0,
|
|
18668
|
+
aggregates: BINARY_AGGREGATES,
|
|
18669
|
+
empty: "offline"
|
|
18670
|
+
};
|
|
18671
|
+
}
|
|
18672
|
+
var GROUP_TEMPLATES = [
|
|
18673
|
+
numeric({
|
|
18674
|
+
id: "temperature",
|
|
18675
|
+
summary: "Mean, median, min, max or sum of temperatures. Offline and unknown members are left out, never read as 0 °C.",
|
|
18676
|
+
role: DeviceRole.TemperatureSensor,
|
|
18677
|
+
outputCap: "temperature-sensor",
|
|
18678
|
+
outputField: "celsius",
|
|
18679
|
+
quantity: "temperature",
|
|
18680
|
+
defaultAggregate: "mean",
|
|
18681
|
+
empty: "null",
|
|
18682
|
+
companions: [NOW]
|
|
18683
|
+
}),
|
|
18684
|
+
numeric({
|
|
18685
|
+
id: "humidity",
|
|
18686
|
+
summary: "Humidity in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
18687
|
+
role: DeviceRole.HumiditySensor,
|
|
18688
|
+
outputCap: "humidity-sensor",
|
|
18689
|
+
outputField: "percent",
|
|
18690
|
+
quantity: "humidity",
|
|
18691
|
+
defaultAggregate: "mean",
|
|
18692
|
+
empty: "null",
|
|
18693
|
+
companions: [NOW]
|
|
18694
|
+
}),
|
|
18695
|
+
numeric({
|
|
18696
|
+
id: "pressure",
|
|
18697
|
+
summary: "Pressure in hectopascals. Offline and unknown members are left out, never read as 0 hPa.",
|
|
18698
|
+
role: DeviceRole.PressureSensor,
|
|
18699
|
+
outputCap: "pressure-sensor",
|
|
18700
|
+
outputField: "hpa",
|
|
18701
|
+
quantity: "pressure",
|
|
18702
|
+
defaultAggregate: "mean",
|
|
18703
|
+
empty: "null",
|
|
18704
|
+
companions: [NOW]
|
|
18705
|
+
}),
|
|
18706
|
+
numeric({
|
|
18707
|
+
id: "illuminance",
|
|
18708
|
+
summary: "Illuminance in lux. Offline and unknown members are left out, never read as 0 lx.",
|
|
18709
|
+
role: DeviceRole.AmbientLightSensor,
|
|
18710
|
+
outputCap: "ambient-light-sensor",
|
|
18711
|
+
outputField: "lux",
|
|
18712
|
+
quantity: "illuminance",
|
|
18713
|
+
defaultAggregate: "mean",
|
|
18714
|
+
empty: "null",
|
|
18715
|
+
companions: [NOW]
|
|
18716
|
+
}),
|
|
18717
|
+
numeric({
|
|
18718
|
+
id: "power",
|
|
18719
|
+
summary: "Power in watts, summed by default. Nobody reporting omits the key rather than writing 0 W.",
|
|
18720
|
+
role: DeviceRole.PowerSensor,
|
|
18721
|
+
outputCap: "power-meter",
|
|
18722
|
+
outputField: "watts",
|
|
18723
|
+
quantity: "power",
|
|
18724
|
+
defaultAggregate: "sum",
|
|
18725
|
+
empty: "omit",
|
|
18726
|
+
companions: [NOW]
|
|
18727
|
+
}),
|
|
18728
|
+
numeric({
|
|
18729
|
+
id: "energy",
|
|
18730
|
+
summary: "Energy in kilowatt-hours, summed by default. Nobody reporting omits the key rather than writing 0 kWh.",
|
|
18731
|
+
role: DeviceRole.EnergySensor,
|
|
18732
|
+
outputCap: "power-meter",
|
|
18733
|
+
outputField: "kwhTotal",
|
|
18734
|
+
quantity: "energy",
|
|
18735
|
+
defaultAggregate: "sum",
|
|
18736
|
+
empty: "omit",
|
|
18737
|
+
companions: [NOW]
|
|
18738
|
+
}),
|
|
18739
|
+
numeric({
|
|
18740
|
+
id: "battery",
|
|
18741
|
+
summary: "Battery charge in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
18742
|
+
role: DeviceRole.BatterySensor,
|
|
18743
|
+
outputCap: "battery",
|
|
18744
|
+
outputField: "percentage",
|
|
18745
|
+
quantity: "percentage",
|
|
18746
|
+
defaultAggregate: "mean",
|
|
18747
|
+
empty: "null",
|
|
18748
|
+
companions: [
|
|
18749
|
+
{
|
|
18750
|
+
fieldPath: "charging",
|
|
18751
|
+
expr: "\"unknown\""
|
|
18752
|
+
},
|
|
18753
|
+
{
|
|
18754
|
+
fieldPath: "sleeping",
|
|
18755
|
+
expr: "false"
|
|
18756
|
+
},
|
|
18757
|
+
{
|
|
18758
|
+
fieldPath: "lastUpdated",
|
|
18759
|
+
expr: "now"
|
|
18760
|
+
}
|
|
18761
|
+
]
|
|
18762
|
+
}),
|
|
18763
|
+
numeric({
|
|
18764
|
+
id: "numeric",
|
|
18765
|
+
summary: "A numeric reading in the members’ shared quantity. Mixed quantities are refused. Nobody reporting publishes null, not 0.",
|
|
18766
|
+
role: DeviceRole.NumericSensor,
|
|
18767
|
+
outputCap: "numeric-sensor",
|
|
18768
|
+
outputField: "value",
|
|
18769
|
+
quantity: "device",
|
|
18770
|
+
defaultAggregate: "mean",
|
|
18771
|
+
empty: "null",
|
|
18772
|
+
companions: [NOW]
|
|
18773
|
+
}),
|
|
18774
|
+
binary({
|
|
18775
|
+
id: "motion",
|
|
18776
|
+
summary: "Any or all motion. Offline and unknown members are left out, never read as off. Nobody reporting takes the device offline.",
|
|
18777
|
+
role: DeviceRole.MotionSensor,
|
|
18778
|
+
outputCap: "motion",
|
|
18779
|
+
outputField: "detected",
|
|
18780
|
+
defaultAggregate: "any",
|
|
18781
|
+
accept: [{
|
|
18782
|
+
cap: "motion",
|
|
18783
|
+
fieldPath: "detected"
|
|
18784
|
+
}],
|
|
18785
|
+
companions: [{
|
|
18786
|
+
fieldPath: "lastDetectedAt",
|
|
18787
|
+
expr: "null"
|
|
18788
|
+
}, {
|
|
18789
|
+
fieldPath: "autoClearAfterMs",
|
|
18790
|
+
expr: "null"
|
|
18791
|
+
}]
|
|
18792
|
+
}),
|
|
18793
|
+
binary({
|
|
18794
|
+
id: "contact",
|
|
18795
|
+
summary: "Any or all open contacts. Offline and unknown members are left out, never read as closed.",
|
|
18796
|
+
role: DeviceRole.ContactSensor,
|
|
18797
|
+
outputCap: "contact",
|
|
18798
|
+
outputField: "entryOpen",
|
|
18799
|
+
defaultAggregate: "any",
|
|
18800
|
+
accept: [{
|
|
18801
|
+
cap: "contact",
|
|
18802
|
+
fieldPath: "entryOpen"
|
|
18803
|
+
}],
|
|
18804
|
+
companions: [CHANGED]
|
|
18805
|
+
}),
|
|
18806
|
+
binary({
|
|
18807
|
+
id: "leak",
|
|
18808
|
+
summary: "Any or all leak detections. Offline and unknown members are left out, never read as dry.",
|
|
18809
|
+
role: DeviceRole.LeakSensor,
|
|
18810
|
+
outputCap: "flood",
|
|
18811
|
+
outputField: "flooded",
|
|
18812
|
+
defaultAggregate: "any",
|
|
18813
|
+
accept: [{
|
|
18814
|
+
cap: "flood",
|
|
18815
|
+
fieldPath: "flooded"
|
|
18816
|
+
}],
|
|
18817
|
+
companions: [CHANGED]
|
|
18818
|
+
}),
|
|
18819
|
+
binary({
|
|
18820
|
+
id: "smoke",
|
|
18821
|
+
summary: "Any or all smoke detections. Offline and unknown members are left out, never read as clear.",
|
|
18822
|
+
role: DeviceRole.SmokeSensor,
|
|
18823
|
+
outputCap: "smoke",
|
|
18824
|
+
outputField: "detected",
|
|
18825
|
+
defaultAggregate: "any",
|
|
18826
|
+
accept: [{
|
|
18827
|
+
cap: "smoke",
|
|
18828
|
+
fieldPath: "detected"
|
|
18829
|
+
}],
|
|
18830
|
+
companions: [CHANGED]
|
|
18831
|
+
}),
|
|
18832
|
+
binary({
|
|
18833
|
+
id: "occupancy",
|
|
18834
|
+
summary: "Any or all of motion or binary sensors, published as a binary. Presence zones are not aggregated. Nobody reporting is offline, not off.",
|
|
18835
|
+
role: DeviceRole.BinarySensor,
|
|
18836
|
+
outputCap: "binary",
|
|
18837
|
+
outputField: "on",
|
|
18838
|
+
defaultAggregate: "any",
|
|
18839
|
+
accept: [{
|
|
18840
|
+
cap: "motion",
|
|
18841
|
+
fieldPath: "detected"
|
|
18842
|
+
}, {
|
|
18843
|
+
cap: "binary",
|
|
18844
|
+
fieldPath: "on"
|
|
18845
|
+
}],
|
|
18846
|
+
companions: [CHANGED]
|
|
18847
|
+
}),
|
|
18848
|
+
binary({
|
|
18849
|
+
id: "binary",
|
|
18850
|
+
summary: "Any or all generic binary sensors. Offline and unknown members are left out, never read as off.",
|
|
18851
|
+
role: DeviceRole.BinarySensor,
|
|
18852
|
+
outputCap: "binary",
|
|
18853
|
+
outputField: "on",
|
|
18854
|
+
defaultAggregate: "any",
|
|
18855
|
+
accept: [{
|
|
18856
|
+
cap: "binary",
|
|
18857
|
+
fieldPath: "on"
|
|
18858
|
+
}],
|
|
18859
|
+
companions: [CHANGED]
|
|
18860
|
+
})
|
|
18861
|
+
];
|
|
18862
|
+
new Map(GROUP_TEMPLATES.map((template) => [template.id, template]));
|
|
18531
18863
|
`${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
|
|
18532
18864
|
/**
|
|
18533
18865
|
* What a composition may BUILD on a device type (G2, D676): the caps a new
|
|
@@ -20269,12 +20601,12 @@ method(object({ deviceId: number().int().nonnegative() }), DeviceAdminLinkSchema
|
|
|
20269
20601
|
* providers detect renames by matching `uniqueId` and patch `id`
|
|
20270
20602
|
* in-place so dispatch keeps working.
|
|
20271
20603
|
*
|
|
20272
|
-
* **
|
|
20273
|
-
*
|
|
20274
|
-
*
|
|
20275
|
-
*
|
|
20276
|
-
* (`ha-domain-mapping`)
|
|
20277
|
-
* stored after that point.
|
|
20604
|
+
* **Display unit and precision are NOT stored here.** They are a read-time
|
|
20605
|
+
* preference (D944). A polymorphic reading stores its `quantity` here once,
|
|
20606
|
+
* at adopt, and a date/time value stores `dateTimeShape` the same way —
|
|
20607
|
+
* neither is repeated on each sample. The `device_class` tag is an
|
|
20608
|
+
* HA-specific input consumed at the discovery boundary (`ha-domain-mapping`)
|
|
20609
|
+
* to derive the CamStack `DeviceRole`; it is never stored after that point.
|
|
20278
20610
|
*
|
|
20279
20611
|
* The `raw` escape hatch carries provider-specific attributes that don't
|
|
20280
20612
|
* fit the structured slots (HA `attributes` whitelist, Reolink `deviceCache`
|
|
@@ -20288,6 +20620,14 @@ var SourceInfoSchema = object({
|
|
|
20288
20620
|
/** Immutable upstream identifier when available (HA `unique_id`, … ).
|
|
20289
20621
|
* Used to detect rename when `id` changes. */
|
|
20290
20622
|
uniqueId: string().optional(),
|
|
20623
|
+
/** Quantity of a polymorphic reading, written once at adopt (D944). */
|
|
20624
|
+
quantity: ReadingQuantitySchema.optional(),
|
|
20625
|
+
/** Date / time / datetime shape of a string reading, written once at adopt. */
|
|
20626
|
+
dateTimeShape: _enum([
|
|
20627
|
+
"date",
|
|
20628
|
+
"time",
|
|
20629
|
+
"datetime"
|
|
20630
|
+
]).optional(),
|
|
20291
20631
|
/** Provider-specific extras that don't fit the structured slots.
|
|
20292
20632
|
* Whitelist what goes here per provider — do NOT dump entire HA
|
|
20293
20633
|
* attribute blobs (would explode the meta JSON column). */
|
|
@@ -41200,7 +41540,8 @@ method(object({
|
|
|
41200
41540
|
"enum"
|
|
41201
41541
|
]),
|
|
41202
41542
|
enumValues: array(string()).optional(),
|
|
41203
|
-
item: boolean().optional()
|
|
41543
|
+
item: boolean().optional(),
|
|
41544
|
+
quantity: ReadingQuantitySchema.optional()
|
|
41204
41545
|
})).readonly(),
|
|
41205
41546
|
itemArray: object({
|
|
41206
41547
|
path: string(),
|
|
@@ -45006,8 +45347,8 @@ var MaskPolygonShapeSchema = object({
|
|
|
45006
45347
|
/** Boolean cell grid — row-major, length === gridWidth*gridHeight. */
|
|
45007
45348
|
var MaskGridShapeSchema = object({
|
|
45008
45349
|
kind: literal("grid"),
|
|
45009
|
-
gridWidth: number(),
|
|
45010
|
-
gridHeight: number(),
|
|
45350
|
+
gridWidth: number().meta(readingMeta("none")),
|
|
45351
|
+
gridHeight: number().meta(readingMeta("none")),
|
|
45011
45352
|
cells: array(boolean())
|
|
45012
45353
|
});
|
|
45013
45354
|
discriminatedUnion("kind", [
|
|
@@ -56401,46 +56742,27 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
|
|
|
56401
56742
|
}), LogStreamEntrySchema, { kind: "subscription" });
|
|
56402
56743
|
object({
|
|
56403
56744
|
/** Carbon dioxide concentration in ppm. */
|
|
56404
|
-
co2Ppm: number().min(0).optional(),
|
|
56745
|
+
co2Ppm: number().min(0).optional().meta(readingMeta("concentration-volume")),
|
|
56405
56746
|
/** Total volatile organic compounds in ppb. */
|
|
56406
|
-
vocPpb: number().min(0).optional(),
|
|
56747
|
+
vocPpb: number().min(0).optional().meta(readingMeta("concentration-ppb")),
|
|
56407
56748
|
/** Particulate matter ≤ 2.5 μm in µg/m³. */
|
|
56408
|
-
pm25: number().min(0).optional(),
|
|
56749
|
+
pm25: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
56409
56750
|
/** Particulate matter ≤ 10 μm in µg/m³. */
|
|
56410
|
-
pm10: number().min(0).optional(),
|
|
56751
|
+
pm10: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
56411
56752
|
/** Composite AQI value (typically 0..500). */
|
|
56412
|
-
aqi: number().optional(),
|
|
56753
|
+
aqi: number().optional().meta(readingMeta("index")),
|
|
56413
56754
|
/** Ms epoch when the slice was last updated. */
|
|
56414
|
-
lastFetchedAt: number()
|
|
56415
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
56416
|
-
* `attributes.unit_of_measurement` → 'ppm' / 'ppb' / 'µg/m³'). Each
|
|
56417
|
-
* upstream `sensor.*` entity surfaces ONE device_class, so one unit
|
|
56418
|
-
* per slice is unambiguous. */
|
|
56419
|
-
unit: string().optional(),
|
|
56420
|
-
/** Suggested decimal places for numeric display.
|
|
56421
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
56422
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
56423
|
-
* auto-formatting when absent. */
|
|
56424
|
-
precision: number().int().min(0).max(10).optional()
|
|
56755
|
+
lastFetchedAt: number()
|
|
56425
56756
|
});
|
|
56426
56757
|
DeviceType.Sensor;
|
|
56427
56758
|
object({
|
|
56428
|
-
/** Current illuminance in lux (lx). */
|
|
56429
|
-
lux: number().min(0).meta({
|
|
56430
|
-
|
|
56759
|
+
/** Current illuminance in lux (lx). `null` when the sample was refused (D393). */
|
|
56760
|
+
lux: number().min(0).nullable().meta(readingMeta("illuminance", {
|
|
56761
|
+
precision: 0,
|
|
56431
56762
|
label: "Illuminance"
|
|
56432
|
-
}),
|
|
56763
|
+
})),
|
|
56433
56764
|
/** Ms epoch when the slice was last updated. */
|
|
56434
|
-
lastFetchedAt: number()
|
|
56435
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
56436
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
56437
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
56438
|
-
unit: string().optional(),
|
|
56439
|
-
/** Suggested decimal places for numeric display.
|
|
56440
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
56441
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
56442
|
-
* auto-formatting when absent. */
|
|
56443
|
-
precision: number().int().min(0).max(10).optional()
|
|
56765
|
+
lastFetchedAt: number()
|
|
56444
56766
|
});
|
|
56445
56767
|
DeviceType.Sensor;
|
|
56446
56768
|
/**
|
|
@@ -56585,10 +56907,7 @@ var BatteryStatusSchema = object({
|
|
|
56585
56907
|
* Consumers must SKIP a null rather than coerce it — `battery-band` already
|
|
56586
56908
|
* declines to band a non-finite reading, which is the correct shape.
|
|
56587
56909
|
*/
|
|
56588
|
-
percentage: number().min(0).max(100).nullable().meta({
|
|
56589
|
-
unit: "%",
|
|
56590
|
-
label: "Charge"
|
|
56591
|
-
}),
|
|
56910
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage", { label: "Charge" })),
|
|
56592
56911
|
/**
|
|
56593
56912
|
* Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
|
|
56594
56913
|
* Reolink-specific for the Solar Panel 2 accessory (will become
|
|
@@ -56615,7 +56934,14 @@ var BatteryStatusSchema = object({
|
|
|
56615
56934
|
*/
|
|
56616
56935
|
sleeping: boolean().meta({ label: "Sleeping" }),
|
|
56617
56936
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
56618
|
-
lastUpdated: number(),
|
|
56937
|
+
lastUpdated: number().meta(readingMeta("none")),
|
|
56938
|
+
/**
|
|
56939
|
+
* Battery voltage in volts, for a cell the firmware reports as voltage
|
|
56940
|
+
* rather than a percentage (Ecowitt capacitor packs). Absent on cameras
|
|
56941
|
+
* that only report charge. A second reading on this cap, not a second
|
|
56942
|
+
* `numeric-sensor` on the same device.
|
|
56943
|
+
*/
|
|
56944
|
+
volts: number().nullable().optional().meta(readingMeta("voltage", { label: "Voltage" })),
|
|
56619
56945
|
/**
|
|
56620
56946
|
* Ms epoch of the last time the device PROVED it was reachable — a
|
|
56621
56947
|
* completed firmware round-trip, an observed wake, or an inbound push
|
|
@@ -56675,7 +57001,7 @@ object({
|
|
|
56675
57001
|
DeviceType.Sensor;
|
|
56676
57002
|
object({
|
|
56677
57003
|
/** Current level as 0..100 inclusive. Firmware-reported. */
|
|
56678
|
-
percentage: number().min(0).max(100),
|
|
57004
|
+
percentage: number().min(0).max(100).meta(readingMeta("percentage")),
|
|
56679
57005
|
/** Ms epoch of the last operator-driven change. Useful for UI freshness. */
|
|
56680
57006
|
lastChangedAt: number()
|
|
56681
57007
|
});
|
|
@@ -57060,21 +57386,21 @@ object({
|
|
|
57060
57386
|
/** Single setpoint in Celsius. Used by single-target modes
|
|
57061
57387
|
* (heat / cool / dry). Null when the device is in a range mode
|
|
57062
57388
|
* (`heat_cool`) or has no setpoint at all (`fan_only`/`off`). */
|
|
57063
|
-
target: number().nullable(),
|
|
57389
|
+
target: number().nullable().meta(readingMeta("temperature")),
|
|
57064
57390
|
/** Upper bound of the dual setpoint in Celsius. Populated only
|
|
57065
57391
|
* in `heat_cool` mode. */
|
|
57066
|
-
targetHigh: number().nullable(),
|
|
57392
|
+
targetHigh: number().nullable().meta(readingMeta("temperature")),
|
|
57067
57393
|
/** Lower bound of the dual setpoint in Celsius. Populated only
|
|
57068
57394
|
* in `heat_cool` mode. */
|
|
57069
|
-
targetLow: number().nullable(),
|
|
57395
|
+
targetLow: number().nullable().meta(readingMeta("temperature")),
|
|
57070
57396
|
/** Target relative humidity (0..100). Null when the device has no
|
|
57071
57397
|
* humidity control. */
|
|
57072
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
57398
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
57073
57399
|
/** Current measured temperature in Celsius. Read-only — pushed by
|
|
57074
57400
|
* the device's internal sensor. */
|
|
57075
|
-
currentTemp: number().nullable(),
|
|
57401
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
57076
57402
|
/** Current measured relative humidity (0..100). Read-only. */
|
|
57077
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
57403
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
57078
57404
|
/** Vertical louver swing on/off. Null when the device has no vertical
|
|
57079
57405
|
* swing surface (gate with `DeviceFeature.ClimateSwingVertical`). */
|
|
57080
57406
|
swingVertical: boolean().nullable(),
|
|
@@ -57082,11 +57408,11 @@ object({
|
|
|
57082
57408
|
* horizontal swing surface (gate with `DeviceFeature.ClimateSwingHorizontal`). */
|
|
57083
57409
|
swingHorizontal: boolean().nullable(),
|
|
57084
57410
|
/** Lowest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
57085
|
-
minTemp: number().nullable().optional(),
|
|
57411
|
+
minTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
57086
57412
|
/** Highest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
57087
|
-
maxTemp: number().nullable().optional(),
|
|
57413
|
+
maxTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
57088
57414
|
/** Setpoint granularity, Celsius (0.5, 1). Absent / null = not reported. */
|
|
57089
|
-
tempStep: number().positive().nullable().optional(),
|
|
57415
|
+
tempStep: number().positive().nullable().optional().meta(readingMeta("temperature")),
|
|
57090
57416
|
/** Ms epoch when the slice was last updated (push or command). */
|
|
57091
57417
|
lastFetchedAt: number()
|
|
57092
57418
|
});
|
|
@@ -57165,17 +57491,17 @@ DeviceType.Thermostat, DeviceType.Climate, method(object({
|
|
|
57165
57491
|
* modes to expose in the picker without a slice fetch.
|
|
57166
57492
|
*/
|
|
57167
57493
|
var RgbTripletSchema = object({
|
|
57168
|
-
r: number().int().min(0).max(255),
|
|
57169
|
-
g: number().int().min(0).max(255),
|
|
57170
|
-
b: number().int().min(0).max(255)
|
|
57494
|
+
r: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
57495
|
+
g: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
57496
|
+
b: number().int().min(0).max(255).meta(readingMeta("none"))
|
|
57171
57497
|
});
|
|
57172
57498
|
var HsvTripletSchema = object({
|
|
57173
57499
|
/** Hue in degrees, 0..360. */
|
|
57174
|
-
h: number().min(0).max(360),
|
|
57500
|
+
h: number().min(0).max(360).meta(readingMeta("none")),
|
|
57175
57501
|
/** Saturation as 0..100 inclusive. */
|
|
57176
|
-
s: number().min(0).max(100),
|
|
57502
|
+
s: number().min(0).max(100).meta(readingMeta("none")),
|
|
57177
57503
|
/** Value/brightness as 0..100 inclusive. */
|
|
57178
|
-
v: number().min(0).max(100)
|
|
57504
|
+
v: number().min(0).max(100).meta(readingMeta("none"))
|
|
57179
57505
|
});
|
|
57180
57506
|
var ColorInputSchema = discriminatedUnion("mode", [
|
|
57181
57507
|
object({
|
|
@@ -57204,7 +57530,7 @@ object({
|
|
|
57204
57530
|
/** Populated when `mode === 'hsv'`. */
|
|
57205
57531
|
hsv: HsvTripletSchema.optional(),
|
|
57206
57532
|
/** Populated when `mode === 'mired'`. */
|
|
57207
|
-
mireds: number().int().optional(),
|
|
57533
|
+
mireds: number().int().optional().meta(readingMeta("colour-temperature")),
|
|
57208
57534
|
/** Ms epoch of the last operator-driven change. */
|
|
57209
57535
|
lastChangedAt: number()
|
|
57210
57536
|
});
|
|
@@ -57328,18 +57654,12 @@ _enum([
|
|
|
57328
57654
|
"empty",
|
|
57329
57655
|
"full"
|
|
57330
57656
|
]);
|
|
57331
|
-
/**
|
|
57332
|
-
|
|
57333
|
-
|
|
57334
|
-
"days",
|
|
57335
|
-
"hours",
|
|
57336
|
-
"cycles"
|
|
57337
|
-
]);
|
|
57338
|
-
/** Remaining life as a COUNT, not a percentage (the PetKit desiccant reports
|
|
57339
|
-
* days). `value` null = unknown (D393). */
|
|
57657
|
+
/** Whether `remaining.value` is a duration in seconds or a dimensionless count. */
|
|
57658
|
+
var ConsumableRemainingKindSchema = _enum(["duration", "count"]);
|
|
57659
|
+
/** Remaining life. `value` null = unknown (D393). Duration is seconds. */
|
|
57340
57660
|
var ConsumableRemainingSchema = object({
|
|
57341
|
-
value: number().min(0).nullable(),
|
|
57342
|
-
|
|
57661
|
+
value: number().min(0).nullable().meta(readingMeta("device")),
|
|
57662
|
+
kind: ConsumableRemainingKindSchema
|
|
57343
57663
|
});
|
|
57344
57664
|
var ConsumablesStatusSchema = object({
|
|
57345
57665
|
items: array(object({
|
|
@@ -57348,7 +57668,7 @@ var ConsumablesStatusSchema = object({
|
|
|
57348
57668
|
/** Display name. */
|
|
57349
57669
|
label: string().min(1),
|
|
57350
57670
|
/** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
|
|
57351
|
-
level: number().min(0).max(100).nullable(),
|
|
57671
|
+
level: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
57352
57672
|
/** The provider's discrete verdict when known (binary mode). */
|
|
57353
57673
|
status: ConsumableStatusSchema.nullable(),
|
|
57354
57674
|
/** What the item is — decides whether low or full is bad. Absent = `wear`. */
|
|
@@ -57365,7 +57685,7 @@ var ConsumablesStatusSchema = object({
|
|
|
57365
57685
|
})),
|
|
57366
57686
|
lastChangedAt: number()
|
|
57367
57687
|
});
|
|
57368
|
-
Object.values(DeviceType), [...
|
|
57688
|
+
Object.values(DeviceType), [...ConsumableRemainingKindSchema.options], [...ConsumableStatusSchema.options], [...ConsumableKindSchema.options], [...ConsumableFormSchema.options];
|
|
57369
57689
|
Object.values(DeviceType), method(object({
|
|
57370
57690
|
deviceId: number().int().nonnegative(),
|
|
57371
57691
|
key: string().min(1)
|
|
@@ -57390,39 +57710,17 @@ object({
|
|
|
57390
57710
|
/** Current value. Numeric kind → number; select/text/datetime → string.
|
|
57391
57711
|
* Datetime values are ISO 8601 strings (full timestamp, date-only,
|
|
57392
57712
|
* or time-only — HA accepts all three forms). */
|
|
57393
|
-
value: union([number(), string()]),
|
|
57713
|
+
value: union([number().meta(readingMeta("device")), string()]),
|
|
57394
57714
|
/** Acceptable values when `kind === 'select'`. Empty for other kinds. */
|
|
57395
57715
|
options: array(string()),
|
|
57396
57716
|
/** Ms epoch when the slice was last updated. */
|
|
57397
57717
|
lastChangedAt: number(),
|
|
57398
|
-
/**
|
|
57399
|
-
|
|
57400
|
-
|
|
57401
|
-
|
|
57402
|
-
/**
|
|
57403
|
-
|
|
57404
|
-
min: number().optional(),
|
|
57405
|
-
/** Maximum allowed value. Populated live from HA `attributes.max`.
|
|
57406
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
57407
|
-
max: number().optional(),
|
|
57408
|
-
/** Step increment. Populated live from HA `attributes.step`.
|
|
57409
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
57410
|
-
step: number().optional(),
|
|
57411
|
-
/** Suggested decimal places for numeric display. Populated live from HA
|
|
57412
|
-
* `attributes.suggested_display_precision`, or derived from `step` when the
|
|
57413
|
-
* HA attribute is absent. Meaningful for `kind === 'numeric'`; absent for
|
|
57414
|
-
* other kinds. Falls back to auto-formatting when absent. */
|
|
57415
|
-
precision: number().int().min(0).max(10).optional(),
|
|
57416
|
-
/** Date-picker granularity for `kind === 'datetime'`. 'date' → date-only,
|
|
57417
|
-
* 'time' → time-only, 'datetime' → full timestamp. Absent for other kinds
|
|
57418
|
-
* (UI defaults to 'datetime'). Derived live from the device's HA domain
|
|
57419
|
-
* (date.* / time.* / datetime.*) or, for input_datetime, from the entity's
|
|
57420
|
-
* `has_date`/`has_time` attributes on each push. */
|
|
57421
|
-
format: _enum([
|
|
57422
|
-
"date",
|
|
57423
|
-
"time",
|
|
57424
|
-
"datetime"
|
|
57425
|
-
]).optional()
|
|
57718
|
+
/** Minimum allowed value, in the device quantity's base unit. */
|
|
57719
|
+
min: number().optional().meta(readingMeta("device")),
|
|
57720
|
+
/** Maximum allowed value, in the device quantity's base unit. */
|
|
57721
|
+
max: number().optional().meta(readingMeta("device")),
|
|
57722
|
+
/** Step increment, in the device quantity's base unit. */
|
|
57723
|
+
step: number().optional().meta(readingMeta("device"))
|
|
57426
57724
|
});
|
|
57427
57725
|
var ControlSetValueInputSchema = discriminatedUnion("kind", [
|
|
57428
57726
|
object({
|
|
@@ -57460,9 +57758,9 @@ object({
|
|
|
57460
57758
|
]),
|
|
57461
57759
|
/** 0 = fully closed, 100 = fully open. Null when the device has
|
|
57462
57760
|
* no intermediate position surface. */
|
|
57463
|
-
position: number().min(0).max(100).nullable(),
|
|
57761
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
57464
57762
|
/** 0 = closed slats, 100 = open slats. Null when no tilt support. */
|
|
57465
|
-
tiltPosition: number().min(0).max(100).nullable(),
|
|
57763
|
+
tiltPosition: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
57466
57764
|
/** Ms epoch when the slice was last updated. */
|
|
57467
57765
|
lastChangedAt: number()
|
|
57468
57766
|
});
|
|
@@ -57520,9 +57818,9 @@ var NormalizedRangeSchema$1 = object({
|
|
|
57520
57818
|
object({
|
|
57521
57819
|
mode: DayNightModeSchema,
|
|
57522
57820
|
/** IR-cut trigger sensitivity, NORMALIZED 0–100 (higher = switches to night sooner). */
|
|
57523
|
-
sensitivity: number().optional(),
|
|
57821
|
+
sensitivity: number().optional().meta(readingMeta("none")),
|
|
57524
57822
|
/** Delay before the IR-cut filter flips, in seconds. */
|
|
57525
|
-
switchDelaySec: number().optional(),
|
|
57823
|
+
switchDelaySec: number().optional().meta(readingMeta("duration")),
|
|
57526
57824
|
lastFetchedAt: number()
|
|
57527
57825
|
});
|
|
57528
57826
|
/**
|
|
@@ -57677,11 +57975,11 @@ object({
|
|
|
57677
57975
|
/** Feature keys of the programs the appliance currently offers — drives the UI selector. */
|
|
57678
57976
|
availablePrograms: array(string()),
|
|
57679
57977
|
/** Seconds remaining on the active cycle, or null when not running / not known. */
|
|
57680
|
-
remainingSeconds: number().int().nonnegative().nullable(),
|
|
57978
|
+
remainingSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
57681
57979
|
/** Seconds the delayed start is set to (time until the cycle starts), or null. */
|
|
57682
|
-
delayedStartSeconds: number().int().nonnegative().nullable(),
|
|
57980
|
+
delayedStartSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
57683
57981
|
/** Cycle completion 0..100, or null when not applicable. */
|
|
57684
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
57982
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
57685
57983
|
/** True when the door is reported open; null when the door state is not known. */
|
|
57686
57984
|
doorOpen: boolean().nullable(),
|
|
57687
57985
|
/** True when the door is latched (locked) during a cycle; null when not reported. */
|
|
@@ -57705,7 +58003,7 @@ object({
|
|
|
57705
58003
|
/** True while the machine-care (descaling / cleaning-program) reminder is raised; false when clear; null when not reported. */
|
|
57706
58004
|
machineCareDue: boolean().nullable(),
|
|
57707
58005
|
/** Program runs left before the machine-care reminder is due; null when the appliance does not say. */
|
|
57708
|
-
machineCareRemainingRuns: number().int().nonnegative().nullable(),
|
|
58006
|
+
machineCareRemainingRuns: number().int().nonnegative().nullable().meta(readingMeta("count")),
|
|
57709
58007
|
/** Option states: null when the appliance does not expose the option or has not said. */
|
|
57710
58008
|
halfLoad: boolean().nullable(),
|
|
57711
58009
|
hygienePlus: boolean().nullable(),
|
|
@@ -57720,7 +58018,7 @@ object({
|
|
|
57720
58018
|
/** Feature keys of the events currently raised (salt low, rinse aid low, program finished, …). */
|
|
57721
58019
|
activeEvents: array(string()),
|
|
57722
58020
|
/** Numeric error code when the appliance reports one; null otherwise. */
|
|
57723
|
-
errorCode: number().nullable(),
|
|
58021
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
57724
58022
|
/** Name of the raised alert-level event while the appliance is in error; null otherwise. */
|
|
57725
58023
|
errorLabel: string().nullable(),
|
|
57726
58024
|
/** Ms epoch of the last value received from the appliance; 0 = never. */
|
|
@@ -57866,24 +58164,14 @@ object({
|
|
|
57866
58164
|
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
57867
58165
|
lastPressedAt: number().nullable(),
|
|
57868
58166
|
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
57869
|
-
pressCountSinceStart: number()
|
|
58167
|
+
pressCountSinceStart: number().meta(readingMeta("count"))
|
|
57870
58168
|
});
|
|
57871
58169
|
object({
|
|
57872
58170
|
deviceId: number(),
|
|
57873
58171
|
timestamp: number()
|
|
57874
58172
|
});
|
|
57875
58173
|
DeviceType.Button, DeviceType.Camera;
|
|
57876
|
-
|
|
57877
|
-
* Enum-state sensor — a string value picked from a finite option set.
|
|
57878
|
-
* Drives HA `sensor` entries with `state_class: enum` (HVAC action
|
|
57879
|
-
* states, weather conditions, contact-source channels, mode strings).
|
|
57880
|
-
* The option set is stable across observations; it is persisted in the
|
|
57881
|
-
* device config blob (via the control slice at adoption) and is NOT
|
|
57882
|
-
* stored in `sourceInfo`.
|
|
57883
|
-
*/
|
|
57884
|
-
/** Locale-render shape for an ISO `value` carried by a `DateTimeSensor`-role
|
|
57885
|
-
* enum sensor: `date` (date-only), `time` (time-only), `datetime` (both). */
|
|
57886
|
-
var EnumSensorDateTimeFormatSchema = _enum([
|
|
58174
|
+
_enum([
|
|
57887
58175
|
"date",
|
|
57888
58176
|
"time",
|
|
57889
58177
|
"datetime"
|
|
@@ -57891,12 +58179,11 @@ var EnumSensorDateTimeFormatSchema = _enum([
|
|
|
57891
58179
|
object({
|
|
57892
58180
|
value: string(),
|
|
57893
58181
|
/**
|
|
57894
|
-
* Set
|
|
57895
|
-
* as
|
|
57896
|
-
*
|
|
57897
|
-
* a time-only sensor → `'time'`.
|
|
58182
|
+
* Set when `value` is a timestamp rather than an enum state, so history
|
|
58183
|
+
* does not learn ISO strings as states. The display shape (date / time /
|
|
58184
|
+
* datetime) lives on `SourceInfo.dateTimeShape`, written once at adopt.
|
|
57898
58185
|
*/
|
|
57899
|
-
|
|
58186
|
+
timestamp: boolean().optional(),
|
|
57900
58187
|
/** Ms epoch when the slice was last updated. */
|
|
57901
58188
|
lastFetchedAt: number()
|
|
57902
58189
|
});
|
|
@@ -57915,13 +58202,13 @@ var EventFireSchema = object({
|
|
|
57915
58202
|
deviceId: number(),
|
|
57916
58203
|
eventType: string(),
|
|
57917
58204
|
data: record(string(), unknown()).nullable(),
|
|
57918
|
-
timestamp: number(),
|
|
57919
|
-
seq: number()
|
|
58205
|
+
timestamp: number().meta(readingMeta("none")),
|
|
58206
|
+
seq: number().meta(readingMeta("count"))
|
|
57920
58207
|
});
|
|
57921
58208
|
object({
|
|
57922
58209
|
eventTypes: array(string()),
|
|
57923
58210
|
lastEvent: EventFireSchema.nullable(),
|
|
57924
|
-
eventCountSinceStart: number()
|
|
58211
|
+
eventCountSinceStart: number().meta(readingMeta("count"))
|
|
57925
58212
|
});
|
|
57926
58213
|
DeviceType.EventEmitter;
|
|
57927
58214
|
var IdentitySchema = object({
|
|
@@ -58310,10 +58597,10 @@ var FanDirectionSchema = _enum(["forward", "reverse"]);
|
|
|
58310
58597
|
object({
|
|
58311
58598
|
/** Active speed as 0..100 inclusive. Null when the device has no
|
|
58312
58599
|
* speed surface (single-speed fan). */
|
|
58313
|
-
percentage: number().min(0).max(100).nullable(),
|
|
58600
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58314
58601
|
/** Speed granularity the device accepts (HA `percentage_step`, e.g. 25 for
|
|
58315
58602
|
* a 4-speed fan). Absent when unknown — the UI then falls back to step 1. */
|
|
58316
|
-
percentageStep: number().positive().optional(),
|
|
58603
|
+
percentageStep: number().positive().optional().meta(readingMeta("percentage")),
|
|
58317
58604
|
/** Active preset mode (`auto` / `quiet` / `turbo` / vendor-specific)
|
|
58318
58605
|
* — empty string when no preset is active or supported. */
|
|
58319
58606
|
preset: string(),
|
|
@@ -58395,7 +58682,7 @@ var FeatureProbeStatusSchema = object({
|
|
|
58395
58682
|
/** Camera/firmware model string. `null` when the firmware doesn't expose it. */
|
|
58396
58683
|
model: string().nullable(),
|
|
58397
58684
|
/** Channel count for NVR/Hub devices; `1` for standalone cameras; `null` pre-probe. */
|
|
58398
|
-
channelCount: number().nullable(),
|
|
58685
|
+
channelCount: number().nullable().meta(readingMeta("count")),
|
|
58399
58686
|
/**
|
|
58400
58687
|
* Ms epoch of the last SUCCESSFUL probe. `0` before the first probe
|
|
58401
58688
|
* completes — drivers' `getAccessoryChildren()` should treat zero as
|
|
@@ -58427,9 +58714,27 @@ object({
|
|
|
58427
58714
|
lastChangedAt: number()
|
|
58428
58715
|
});
|
|
58429
58716
|
DeviceType.Sensor;
|
|
58717
|
+
object({
|
|
58718
|
+
/** Members whose current value entered the aggregate. */
|
|
58719
|
+
included: number().int().nonnegative().meta(readingMeta("count", {
|
|
58720
|
+
precision: 0,
|
|
58721
|
+
label: "Reporting"
|
|
58722
|
+
})),
|
|
58723
|
+
/** Members left out: offline, unknown, or not a finite reading (D393). */
|
|
58724
|
+
excluded: number().int().nonnegative().meta(readingMeta("count", {
|
|
58725
|
+
precision: 0,
|
|
58726
|
+
label: "Excluded"
|
|
58727
|
+
})),
|
|
58728
|
+
/** `included` + `excluded`. */
|
|
58729
|
+
total: number().int().nonnegative().meta(readingMeta("count", {
|
|
58730
|
+
precision: 0,
|
|
58731
|
+
label: "Members"
|
|
58732
|
+
}))
|
|
58733
|
+
});
|
|
58734
|
+
DeviceType.Sensor;
|
|
58430
58735
|
object({
|
|
58431
58736
|
/** Radiator valve opening 0 (closed) .. 100 (open). Null = not yet known. */
|
|
58432
|
-
position: number().min(0).max(100).nullable(),
|
|
58737
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58433
58738
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
58434
58739
|
lastFetchedAt: number()
|
|
58435
58740
|
});
|
|
@@ -58438,9 +58743,9 @@ object({
|
|
|
58438
58743
|
/** Whether the humidifier is currently on. */
|
|
58439
58744
|
on: boolean(),
|
|
58440
58745
|
/** Current measured relative humidity (0..100). Null when not reported. */
|
|
58441
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
58746
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
58442
58747
|
/** Target relative humidity (0..100). Null when no setpoint surface. */
|
|
58443
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
58748
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
58444
58749
|
/** Active mode (`auto` / `normal` / `baby` / vendor). Null when the
|
|
58445
58750
|
* device has no mode surface. */
|
|
58446
58751
|
mode: string().nullable(),
|
|
@@ -58450,9 +58755,9 @@ object({
|
|
|
58450
58755
|
* `idle` / `off`). Null when the device doesn't report it. */
|
|
58451
58756
|
action: string().nullable(),
|
|
58452
58757
|
/** HA `min_humidity` attribute. Null → UI uses 0. */
|
|
58453
|
-
minHumidity: number().nullable(),
|
|
58758
|
+
minHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
58454
58759
|
/** HA `max_humidity` attribute. Null → UI uses 100. */
|
|
58455
|
-
maxHumidity: number().nullable(),
|
|
58760
|
+
maxHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
58456
58761
|
/** Ms epoch when the slice was last updated. */
|
|
58457
58762
|
lastChangedAt: number()
|
|
58458
58763
|
});
|
|
@@ -58476,22 +58781,13 @@ DeviceType.Humidifier, method(object({
|
|
|
58476
58781
|
auth: "protected"
|
|
58477
58782
|
});
|
|
58478
58783
|
object({
|
|
58479
|
-
/** Current relative humidity, 0..100. */
|
|
58480
|
-
percent: number().min(0).max(100).meta({
|
|
58481
|
-
|
|
58784
|
+
/** Current relative humidity, 0..100. `null` when the sample was refused (D393). */
|
|
58785
|
+
percent: number().min(0).max(100).nullable().meta(readingMeta("humidity", {
|
|
58786
|
+
precision: 0,
|
|
58482
58787
|
label: "Humidity"
|
|
58483
|
-
}),
|
|
58788
|
+
})),
|
|
58484
58789
|
/** Ms epoch when the slice was last updated. */
|
|
58485
|
-
lastFetchedAt: number()
|
|
58486
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
58487
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
58488
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
58489
|
-
unit: string().optional(),
|
|
58490
|
-
/** Suggested decimal places for numeric display.
|
|
58491
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
58492
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
58493
|
-
* auto-formatting when absent. */
|
|
58494
|
-
precision: number().int().min(0).max(10).optional()
|
|
58790
|
+
lastFetchedAt: number()
|
|
58495
58791
|
});
|
|
58496
58792
|
DeviceType.Sensor, DeviceType.Thermostat;
|
|
58497
58793
|
object({
|
|
@@ -58499,7 +58795,7 @@ object({
|
|
|
58499
58795
|
* entity exposes no `entity_picture` (yet). */
|
|
58500
58796
|
url: string().nullable(),
|
|
58501
58797
|
/** Ms epoch of the upstream last-updated timestamp. Null at cold-start. */
|
|
58502
|
-
lastUpdated: number().nullable()
|
|
58798
|
+
lastUpdated: number().nullable().meta(readingMeta("none"))
|
|
58503
58799
|
});
|
|
58504
58800
|
DeviceType.Image;
|
|
58505
58801
|
/**
|
|
@@ -58555,19 +58851,19 @@ var NormalizedRangeSchema = object({
|
|
|
58555
58851
|
});
|
|
58556
58852
|
object({
|
|
58557
58853
|
/** Normalized 0–100. */
|
|
58558
|
-
brightness: number().optional(),
|
|
58854
|
+
brightness: number().optional().meta(readingMeta("none")),
|
|
58559
58855
|
/** Normalized 0–100. */
|
|
58560
|
-
contrast: number().optional(),
|
|
58856
|
+
contrast: number().optional().meta(readingMeta("none")),
|
|
58561
58857
|
/** Normalized 0–100. */
|
|
58562
|
-
saturation: number().optional(),
|
|
58858
|
+
saturation: number().optional().meta(readingMeta("none")),
|
|
58563
58859
|
/** Normalized 0–100. */
|
|
58564
|
-
sharpness: number().optional(),
|
|
58860
|
+
sharpness: number().optional().meta(readingMeta("none")),
|
|
58565
58861
|
mirror: boolean().optional(),
|
|
58566
58862
|
flip: boolean().optional(),
|
|
58567
58863
|
rotate: ImageRotateSchema.optional(),
|
|
58568
58864
|
whiteBalance: WhiteBalanceModeSchema.optional(),
|
|
58569
58865
|
/** Manual white-balance warmth, NORMALIZED 0–100. Meaningful only when `whiteBalance === 'manual'`. */
|
|
58570
|
-
warmth: number().optional(),
|
|
58866
|
+
warmth: number().optional().meta(readingMeta("none")),
|
|
58571
58867
|
exposureMode: ExposureModeSchema.optional(),
|
|
58572
58868
|
backlightMode: BacklightModeSchema.optional(),
|
|
58573
58869
|
lastFetchedAt: number()
|
|
@@ -58812,10 +59108,10 @@ var IntercomAbilitySchema = object({
|
|
|
58812
59108
|
/** Codecs accepted by firmware, in preference order. Driver-authored strings. */
|
|
58813
59109
|
codecs: array(string()),
|
|
58814
59110
|
/** Sample rate (Hz) the firmware expects. Reolink typical: 16000. */
|
|
58815
|
-
sampleRate: number(),
|
|
59111
|
+
sampleRate: number().meta(readingMeta("none")),
|
|
58816
59112
|
duplex: _enum(["half", "full"]),
|
|
58817
59113
|
/** Max in-flight audio backlog before drop (ms). Server uses this to bound latency. */
|
|
58818
|
-
maxBacklogMs: number()
|
|
59114
|
+
maxBacklogMs: number().meta(readingMeta("duration-ms"))
|
|
58819
59115
|
});
|
|
58820
59116
|
var IntercomStatusSchema = object({
|
|
58821
59117
|
/** True while a talk session is open. */
|
|
@@ -58926,13 +59222,13 @@ object({
|
|
|
58926
59222
|
activity: LawnMowerActivitySchema,
|
|
58927
59223
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
58928
59224
|
* reading. */
|
|
58929
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
59225
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58930
59226
|
/** 0..100 mowing-completion percentage of the current task, or null when no
|
|
58931
59227
|
* task is active / progress is unavailable. */
|
|
58932
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
59228
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58933
59229
|
/** Current device/event code (dynamic — mostly status, sometimes an error),
|
|
58934
59230
|
* or null when unknown. */
|
|
58935
|
-
currentCode: number().nullable(),
|
|
59231
|
+
currentCode: number().nullable().meta(readingMeta("none")),
|
|
58936
59232
|
/** Human label for {@link currentCode}, or null when undecodable. */
|
|
58937
59233
|
currentCodeLabel: string().nullable(),
|
|
58938
59234
|
/** Severity of {@link currentCode}. `error` (and often `warning`) warrants UI
|
|
@@ -59394,7 +59690,7 @@ object({
|
|
|
59394
59690
|
state: MediaPlayerStateSchema,
|
|
59395
59691
|
/** Volume as 0..100 inclusive. Null when the device has no volume
|
|
59396
59692
|
* surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
|
|
59397
|
-
volumeLevel: number().min(0).max(100).nullable(),
|
|
59693
|
+
volumeLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59398
59694
|
/** Mute toggle distinct from volume=0. Null when no mute surface.
|
|
59399
59695
|
* Pair with `DeviceFeature.MediaPlayerMute`. */
|
|
59400
59696
|
isMuted: boolean().nullable(),
|
|
@@ -59407,10 +59703,10 @@ object({
|
|
|
59407
59703
|
currentMedia: MediaInfoSchema.nullable(),
|
|
59408
59704
|
/** Current playback position in ms. Null when not seekable or
|
|
59409
59705
|
* nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
|
|
59410
|
-
positionMs: number().int().nonnegative().nullable(),
|
|
59706
|
+
positionMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
59411
59707
|
/** Total duration of the current media in ms. Null when unknown
|
|
59412
59708
|
* (live stream) or nothing is playing. */
|
|
59413
|
-
durationMs: number().int().nonnegative().nullable(),
|
|
59709
|
+
durationMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
59414
59710
|
/** Shuffle toggle. Null when no shuffle surface.
|
|
59415
59711
|
* Pair with `DeviceFeature.MediaPlayerShuffle`. */
|
|
59416
59712
|
shuffle: boolean().nullable(),
|
|
@@ -59710,7 +60006,7 @@ object({
|
|
|
59710
60006
|
* it, every provider seeded it at boot, and every session left it
|
|
59711
60007
|
* `detected: true` after its detach.
|
|
59712
60008
|
*/
|
|
59713
|
-
autoClearAfterMs: number().nullable()
|
|
60009
|
+
autoClearAfterMs: number().nullable().meta(readingMeta("duration-ms"))
|
|
59714
60010
|
});
|
|
59715
60011
|
/**
|
|
59716
60012
|
* Payload of `motion.onMotionChanged` event + the corresponding bus
|
|
@@ -59760,7 +60056,7 @@ var MotionZoneRegionSchema = object({
|
|
|
59760
60056
|
});
|
|
59761
60057
|
object({
|
|
59762
60058
|
enabled: boolean(),
|
|
59763
|
-
sensitivity: number(),
|
|
60059
|
+
sensitivity: number().meta(readingMeta("none")),
|
|
59764
60060
|
/** Grid region(s). Today exactly one `grid` shape. */
|
|
59765
60061
|
regions: array(MotionZoneRegionSchema),
|
|
59766
60062
|
lastFetchedAt: number()
|
|
@@ -60064,7 +60360,7 @@ var NavigationStatusSchema = object({
|
|
|
60064
60360
|
following: boolean(),
|
|
60065
60361
|
flash: boolean(),
|
|
60066
60362
|
lightMode: NavigationLightModeSchema,
|
|
60067
|
-
lightLevel: number().min(40).max(100),
|
|
60363
|
+
lightLevel: number().min(40).max(100).meta(readingMeta("none")),
|
|
60068
60364
|
/** Ms epoch when the slice was last updated. */
|
|
60069
60365
|
lastChangedAt: number()
|
|
60070
60366
|
});
|
|
@@ -60110,13 +60406,13 @@ var NetworkLinkStatusSchema = object({
|
|
|
60110
60406
|
* one whose reading has not landed must not be drawn at 0 %. Consumers
|
|
60111
60407
|
* SKIP a null rather than coerce it.
|
|
60112
60408
|
*/
|
|
60113
|
-
signalPercent: number().min(0).max(100).nullable(),
|
|
60409
|
+
signalPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
60114
60410
|
/** Raw received signal strength in dBm, when the firmware reports one. */
|
|
60115
|
-
rssiDbm: number().optional(),
|
|
60411
|
+
rssiDbm: number().optional().meta(readingMeta("signal-level")),
|
|
60116
60412
|
/** Network name of a wireless link, when the firmware reports it. */
|
|
60117
60413
|
ssid: string().optional(),
|
|
60118
60414
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
60119
|
-
lastUpdated: number()
|
|
60415
|
+
lastUpdated: number().meta(readingMeta("none"))
|
|
60120
60416
|
});
|
|
60121
60417
|
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.Light, DeviceType.Lock, DeviceType.Siren, object({
|
|
60122
60418
|
deviceId: number(),
|
|
@@ -60435,7 +60731,7 @@ object({
|
|
|
60435
60731
|
lastError: string().nullable(),
|
|
60436
60732
|
/** Number of deliveries currently buffered server-side (rate-limited
|
|
60437
60733
|
* notifiers may queue). 0 when the provider sends synchronously. */
|
|
60438
|
-
queueDepth: number().int().nonnegative(),
|
|
60734
|
+
queueDepth: number().int().nonnegative().meta(readingMeta("count")),
|
|
60439
60735
|
/** Per-feature capability matrix — authoritative source for the
|
|
60440
60736
|
* compose-form field gating. */
|
|
60441
60737
|
supports: NotifierSupportsSchema
|
|
@@ -60485,15 +60781,8 @@ DeviceType.Notifier, method(NotifierSendInputSchema, NotifierSendResultSchema, {
|
|
|
60485
60781
|
acceptedAt: number()
|
|
60486
60782
|
});
|
|
60487
60783
|
object({
|
|
60488
|
-
|
|
60489
|
-
|
|
60490
|
-
* Populated live from the upstream source on each state push.
|
|
60491
|
-
* Absent for unitless sensors. */
|
|
60492
|
-
unit: string().optional(),
|
|
60493
|
-
/** Suggested decimal places for numeric display.
|
|
60494
|
-
* Populated live from the upstream source when provided.
|
|
60495
|
-
* Falls back to auto-formatting when absent. */
|
|
60496
|
-
precision: number().int().min(0).max(10).optional(),
|
|
60784
|
+
/** Reading in the device quantity's base unit. `null` when refused (D393). */
|
|
60785
|
+
value: number().nullable().meta(readingMeta("device")),
|
|
60497
60786
|
/** Ms epoch when the slice was last updated. */
|
|
60498
60787
|
lastFetchedAt: number()
|
|
60499
60788
|
});
|
|
@@ -60783,23 +61072,26 @@ object({
|
|
|
60783
61072
|
/** Food currently in the bowl (grams). Null when the device has not
|
|
60784
61073
|
* reported a reading yet. On dual-hopper models this is the combined
|
|
60785
61074
|
* bowl reading; per-hopper levels live in `food1`/`food2`. */
|
|
60786
|
-
foodLevel: number().nullable(),
|
|
61075
|
+
foodLevel: number().nullable().meta(readingMeta("none")),
|
|
60787
61076
|
/** Hopper-1 food level (grams) on dual-hopper feeders; null on
|
|
60788
61077
|
* single-hopper models. */
|
|
60789
|
-
food1: number().nullable(),
|
|
61078
|
+
food1: number().nullable().meta(readingMeta("none")),
|
|
60790
61079
|
/** Hopper-2 food level (grams) on dual-hopper feeders; null on
|
|
60791
61080
|
* single-hopper models. */
|
|
60792
|
-
food2: number().nullable(),
|
|
61081
|
+
food2: number().nullable().meta(readingMeta("none")),
|
|
60793
61082
|
/** Derived low-food flag — mirrors the HA `food_level` binary_sensor
|
|
60794
61083
|
* (`device_class: problem`, on = low). True when the bowl is empty /
|
|
60795
61084
|
* below the feeder's low threshold. */
|
|
60796
61085
|
lowFood: boolean(),
|
|
60797
61086
|
/** Battery charge 0..100 (%). Null on mains-powered models or when the
|
|
60798
61087
|
* device has no battery reading. */
|
|
60799
|
-
batteryPower: number().min(0).max(100).nullable(),
|
|
60800
|
-
/**
|
|
60801
|
-
*
|
|
60802
|
-
|
|
61088
|
+
batteryPower: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61089
|
+
/**
|
|
61090
|
+
* Desiccant life remaining, stored in seconds (duration base, D944).
|
|
61091
|
+
* Providers convert from the days the feeder reports. Null when the
|
|
61092
|
+
* model has no desiccant sensor.
|
|
61093
|
+
*/
|
|
61094
|
+
desiccantLeftDays: number().nullable().meta(readingMeta("duration")),
|
|
60803
61095
|
/** True while a feed is in progress. */
|
|
60804
61096
|
feeding: boolean(),
|
|
60805
61097
|
/** Decoded connectivity / power status (HA petkit device-status enum).
|
|
@@ -60810,7 +61102,7 @@ object({
|
|
|
60810
61102
|
* with `errorCode` for consumers that want the raw integer. */
|
|
60811
61103
|
error: string().nullable(),
|
|
60812
61104
|
/** Raw device error code (0 / null = no error). */
|
|
60813
|
-
errorCode: number().nullable(),
|
|
61105
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
60814
61106
|
/** True for D4S/D4SH dual-hopper hardware — gates the per-hopper UI. */
|
|
60815
61107
|
isDualHopper: boolean(),
|
|
60816
61108
|
/** Child-lock (manual-lock) setting — buttons on the unit are disabled. */
|
|
@@ -60820,7 +61112,7 @@ object({
|
|
|
60820
61112
|
/** Play a chime when dispensing. */
|
|
60821
61113
|
feedSound: boolean(),
|
|
60822
61114
|
/** Speaker / prompt volume level (device-scaled integer). */
|
|
60823
|
-
volume: number(),
|
|
61115
|
+
volume: number().meta(readingMeta("none")),
|
|
60824
61116
|
/** Ms epoch when the slice was last refreshed from the cloud. */
|
|
60825
61117
|
lastFetchedAt: number()
|
|
60826
61118
|
});
|
|
@@ -61257,36 +61549,19 @@ method(_void(), PlatformCapabilitiesSchema), method(_void(), HardwareInfoSchema)
|
|
|
61257
61549
|
});
|
|
61258
61550
|
object({
|
|
61259
61551
|
/** Instantaneous power draw in watts. */
|
|
61260
|
-
watts: number().optional().meta({
|
|
61261
|
-
unit: "W",
|
|
61262
|
-
label: "Power"
|
|
61263
|
-
}),
|
|
61552
|
+
watts: number().optional().meta(readingMeta("power", { label: "Power" })),
|
|
61264
61553
|
/** Cumulative energy in kilowatt-hours since the meter was reset. */
|
|
61265
|
-
kwhTotal: number().optional().meta({
|
|
61266
|
-
unit: "kWh",
|
|
61267
|
-
label: "Energy"
|
|
61268
|
-
}),
|
|
61554
|
+
kwhTotal: number().optional().meta(readingMeta("energy", { label: "Energy" })),
|
|
61269
61555
|
/** Voltage in volts. */
|
|
61270
|
-
volts: number().optional(),
|
|
61556
|
+
volts: number().optional().meta(readingMeta("voltage")),
|
|
61271
61557
|
/** Current in amperes. */
|
|
61272
|
-
amps: number().optional(),
|
|
61273
|
-
/** Apparent power in volt-amperes
|
|
61274
|
-
va: number().optional(),
|
|
61558
|
+
amps: number().optional().meta(readingMeta("current")),
|
|
61559
|
+
/** Apparent power in volt-amperes. */
|
|
61560
|
+
va: number().optional().meta(readingMeta("apparent-power")),
|
|
61275
61561
|
/** Power factor (0..1) if reported. */
|
|
61276
|
-
powerFactor: number().min(0).max(1).optional(),
|
|
61562
|
+
powerFactor: number().min(0).max(1).optional().meta(readingMeta("ratio")),
|
|
61277
61563
|
/** Ms epoch when the slice was last updated. */
|
|
61278
|
-
lastFetchedAt: number()
|
|
61279
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
61280
|
-
* `attributes.unit_of_measurement` → 'V' / 'A' / 'W' / 'kW' / 'kWh').
|
|
61281
|
-
* Each upstream `sensor.*` entity surfaces ONE device_class, so one
|
|
61282
|
-
* unit per slice is unambiguous. The UI prefers this over the role's
|
|
61283
|
-
* canonical unit so a 'kW' / 'Wh' feed renders verbatim. */
|
|
61284
|
-
unit: string().optional(),
|
|
61285
|
-
/** Suggested decimal places for numeric display.
|
|
61286
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
61287
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
61288
|
-
* auto-formatting when absent. */
|
|
61289
|
-
precision: number().int().min(0).max(10).optional()
|
|
61564
|
+
lastFetchedAt: number()
|
|
61290
61565
|
});
|
|
61291
61566
|
DeviceType.Sensor;
|
|
61292
61567
|
/**
|
|
@@ -61307,11 +61582,11 @@ DeviceType.Sensor;
|
|
|
61307
61582
|
*/
|
|
61308
61583
|
var GpsLocationSchema = object({
|
|
61309
61584
|
/** Latitude in decimal degrees, -90..90. */
|
|
61310
|
-
latitude: number().min(-90).max(90),
|
|
61585
|
+
latitude: number().min(-90).max(90).meta(readingMeta("angle")),
|
|
61311
61586
|
/** Longitude in decimal degrees, -180..180. */
|
|
61312
|
-
longitude: number().min(-180).max(180),
|
|
61587
|
+
longitude: number().min(-180).max(180).meta(readingMeta("angle")),
|
|
61313
61588
|
/** Reported accuracy in meters (lower = better). */
|
|
61314
|
-
accuracyMeters: number().nonnegative()
|
|
61589
|
+
accuracyMeters: number().nonnegative().meta(readingMeta("length"))
|
|
61315
61590
|
});
|
|
61316
61591
|
object({
|
|
61317
61592
|
/** `home` / `not_home` / any user-defined zone name. */
|
|
@@ -61323,25 +61598,16 @@ object({
|
|
|
61323
61598
|
gps: GpsLocationSchema.nullable(),
|
|
61324
61599
|
/** Optional battery level of the tracking device (0..100). Null
|
|
61325
61600
|
* when not reported. */
|
|
61326
|
-
batteryPercent: number().min(0).max(100).nullable(),
|
|
61601
|
+
batteryPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61327
61602
|
/** Ms epoch when the slice was last updated. */
|
|
61328
61603
|
lastChangedAt: number()
|
|
61329
61604
|
});
|
|
61330
61605
|
DeviceType.Presence;
|
|
61331
61606
|
object({
|
|
61332
|
-
/** Current pressure in hPa. */
|
|
61333
|
-
hpa: number(),
|
|
61607
|
+
/** Current pressure in hPa. `null` when the sample was refused (D393). */
|
|
61608
|
+
hpa: number().nullable().meta(readingMeta("pressure", { precision: 0 })),
|
|
61334
61609
|
/** Ms epoch when the slice was last updated. */
|
|
61335
|
-
lastFetchedAt: number()
|
|
61336
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
61337
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
61338
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
61339
|
-
unit: string().optional(),
|
|
61340
|
-
/** Suggested decimal places for numeric display.
|
|
61341
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
61342
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
61343
|
-
* auto-formatting when absent. */
|
|
61344
|
-
precision: number().int().min(0).max(10).optional()
|
|
61610
|
+
lastFetchedAt: number()
|
|
61345
61611
|
});
|
|
61346
61612
|
DeviceType.Sensor;
|
|
61347
61613
|
/**
|
|
@@ -61674,8 +61940,8 @@ DeviceType.Camera, method(PtzMoveCommandSchema.extend({ deviceId: number() }), _
|
|
|
61674
61940
|
}), _void(), { kind: "mutation" });
|
|
61675
61941
|
var PtzAutotrackSettingsSchema = object({
|
|
61676
61942
|
targetType: string().describe("Vendor target string (people/vehicle/pet); empty = camera default"),
|
|
61677
|
-
stopDelaySeconds: number().int().min(0).max(300),
|
|
61678
|
-
disappearDelaySeconds: number().int().min(0).max(300)
|
|
61943
|
+
stopDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration")),
|
|
61944
|
+
disappearDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration"))
|
|
61679
61945
|
});
|
|
61680
61946
|
/**
|
|
61681
61947
|
* One option the camera advertises as a valid `targetType`. Drivers
|
|
@@ -61732,7 +61998,7 @@ object({
|
|
|
61732
61998
|
/** null = unknown — never coerced to false (D393). */
|
|
61733
61999
|
running: boolean().nullable(),
|
|
61734
62000
|
/** Epoch ms the current boolean began; null while `running` is null. */
|
|
61735
|
-
since: number().nullable(),
|
|
62001
|
+
since: number().nullable().meta(readingMeta("none")),
|
|
61736
62002
|
source: RunningStateSourceSchema.meta({ label: "Source" }),
|
|
61737
62003
|
phase: string().nullable(),
|
|
61738
62004
|
/** null until a reading has been published (D393). */
|
|
@@ -62930,9 +63196,9 @@ var RecordTriggerSchema = _enum([
|
|
|
62930
63196
|
*/
|
|
62931
63197
|
var RecordWindowSchema = object({
|
|
62932
63198
|
trigger: RecordTriggerSchema,
|
|
62933
|
-
day: number().int().min(0).max(6),
|
|
62934
|
-
startMinute: number().int().min(0).max(1439),
|
|
62935
|
-
endMinute: number().int().min(1).max(1440)
|
|
63199
|
+
day: number().int().min(0).max(6).meta(readingMeta("none")),
|
|
63200
|
+
startMinute: number().int().min(0).max(1439).meta(readingMeta("none")),
|
|
63201
|
+
endMinute: number().int().min(1).max(1440).meta(readingMeta("none"))
|
|
62936
63202
|
});
|
|
62937
63203
|
/** Status of one physical volume, as the camera itself describes it. */
|
|
62938
63204
|
var OnboardStorageVolumeSchema = object({
|
|
@@ -63001,10 +63267,10 @@ object({
|
|
|
63001
63267
|
/** Master "record to the card at all" switch. */
|
|
63002
63268
|
enabled: boolean().nullable(),
|
|
63003
63269
|
overwriteWhenFull: boolean().nullable(),
|
|
63004
|
-
preRecordSec: number().nullable(),
|
|
63005
|
-
postRecordSec: number().nullable(),
|
|
63270
|
+
preRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
63271
|
+
postRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
63006
63272
|
/** Length of one recorded file, in minutes. */
|
|
63007
|
-
segmentMinutes: number().nullable(),
|
|
63273
|
+
segmentMinutes: number().nullable().meta(readingMeta("none")),
|
|
63008
63274
|
/** The primary track's weekly windows, flattened. */
|
|
63009
63275
|
windows: array(RecordWindowSchema),
|
|
63010
63276
|
/**
|
|
@@ -63020,7 +63286,7 @@ object({
|
|
|
63020
63286
|
* provider reporting a non-zero count also reports the schedule as not
|
|
63021
63287
|
* writable.
|
|
63022
63288
|
*/
|
|
63023
|
-
unreadableWindows: number(),
|
|
63289
|
+
unreadableWindows: number().meta(readingMeta("count")),
|
|
63024
63290
|
/**
|
|
63025
63291
|
* The camera is scheduled to record and has NO usable storage.
|
|
63026
63292
|
*
|
|
@@ -63657,7 +63923,7 @@ var CamStreamDescriptorSchema = object({
|
|
|
63657
63923
|
url: string().optional(),
|
|
63658
63924
|
codec: string().optional(),
|
|
63659
63925
|
resolution: CamStreamResolutionSchema.optional(),
|
|
63660
|
-
fps: number().positive().optional(),
|
|
63926
|
+
fps: number().positive().optional().meta(readingMeta("rate")),
|
|
63661
63927
|
label: string().optional(),
|
|
63662
63928
|
/** Device-level features (e.g. `battery-operated`) — drives broker policy. */
|
|
63663
63929
|
deviceFeatures: array(string()).optional(),
|
|
@@ -63687,18 +63953,18 @@ var StreamProfileSchema = _enum([
|
|
|
63687
63953
|
]);
|
|
63688
63954
|
/** The current encoding config of one stream profile. */
|
|
63689
63955
|
var StreamProfileConfigSchema = object({
|
|
63690
|
-
width: number(),
|
|
63691
|
-
height: number(),
|
|
63956
|
+
width: number().meta(readingMeta("none")),
|
|
63957
|
+
height: number().meta(readingMeta("none")),
|
|
63692
63958
|
codec: _enum(["h264", "h265"]),
|
|
63693
|
-
framerate: number(),
|
|
63694
|
-
bitrate: number(),
|
|
63959
|
+
framerate: number().meta(readingMeta("rate")),
|
|
63960
|
+
bitrate: number().meta(readingMeta("bitrate")),
|
|
63695
63961
|
bitrateMode: _enum(["vbr", "cbr"]).optional(),
|
|
63696
63962
|
encoderProfile: _enum([
|
|
63697
63963
|
"high",
|
|
63698
63964
|
"main",
|
|
63699
63965
|
"baseline"
|
|
63700
63966
|
]).optional(),
|
|
63701
|
-
gop: number().optional(),
|
|
63967
|
+
gop: number().optional().meta(readingMeta("none")),
|
|
63702
63968
|
/**
|
|
63703
63969
|
* Whether THIS profile currently carries an audio track. READ-ONLY here.
|
|
63704
63970
|
*
|
|
@@ -64341,23 +64607,13 @@ object({
|
|
|
64341
64607
|
});
|
|
64342
64608
|
DeviceType.Sensor;
|
|
64343
64609
|
object({
|
|
64344
|
-
/** Current temperature in Celsius. */
|
|
64345
|
-
celsius: number().meta({
|
|
64346
|
-
|
|
64610
|
+
/** Current temperature in Celsius. `null` when the sample was refused (D393). */
|
|
64611
|
+
celsius: number().nullable().meta(readingMeta("temperature", {
|
|
64612
|
+
precision: 1,
|
|
64347
64613
|
label: "Temperature"
|
|
64348
|
-
}),
|
|
64614
|
+
})),
|
|
64349
64615
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
64350
|
-
lastFetchedAt: number()
|
|
64351
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
64352
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
64353
|
-
* role's canonical unit, so a Fahrenheit feed renders '°F' not '°C'.
|
|
64354
|
-
* Absent → the UI falls back to the role's canonical unit. */
|
|
64355
|
-
unit: string().optional(),
|
|
64356
|
-
/** Suggested decimal places for numeric display.
|
|
64357
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
64358
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
64359
|
-
* auto-formatting when absent. */
|
|
64360
|
-
precision: number().int().min(0).max(10).optional()
|
|
64616
|
+
lastFetchedAt: number()
|
|
64361
64617
|
});
|
|
64362
64618
|
DeviceType.Sensor, DeviceType.Thermostat;
|
|
64363
64619
|
/**
|
|
@@ -64609,16 +64865,16 @@ object({
|
|
|
64609
64865
|
]),
|
|
64610
64866
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
64611
64867
|
* reading. */
|
|
64612
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
64868
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
64613
64869
|
/** Current fan-speed token (provider-verbatim). Null when unknown or
|
|
64614
64870
|
* the vacuum has no speed control. */
|
|
64615
64871
|
fanSpeed: string().nullable(),
|
|
64616
64872
|
/** Speed tokens the hardware accepts — drives the UI selector. */
|
|
64617
64873
|
availableFanSpeeds: array(string()),
|
|
64618
64874
|
/** 0..100 cleaning-completion percentage of the current task, or null. */
|
|
64619
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
64875
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
64620
64876
|
/** Current error code (0 / null = no error). */
|
|
64621
|
-
errorCode: number().nullable(),
|
|
64877
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
64622
64878
|
/** Human label for {@link errorCode}, or null when none / undecodable. */
|
|
64623
64879
|
errorLabel: string().nullable(),
|
|
64624
64880
|
/** Ms epoch when the slice was last updated. */
|
|
@@ -64657,7 +64913,7 @@ object({
|
|
|
64657
64913
|
]),
|
|
64658
64914
|
/** 0 = fully closed, 100 = fully open. Null when the device has no
|
|
64659
64915
|
* intermediate position surface. */
|
|
64660
|
-
position: number().min(0).max(100).nullable(),
|
|
64916
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
64661
64917
|
/** Ms epoch when the slice was last updated. */
|
|
64662
64918
|
lastChangedAt: number()
|
|
64663
64919
|
});
|
|
@@ -64685,9 +64941,9 @@ object({
|
|
|
64685
64941
|
DeviceType.Sensor;
|
|
64686
64942
|
object({
|
|
64687
64943
|
/** Current measured temperature. Null when not reported. */
|
|
64688
|
-
currentTemp: number().nullable(),
|
|
64944
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
64689
64945
|
/** Target temperature setpoint. Null when no setpoint surface. */
|
|
64690
|
-
targetTemp: number().nullable(),
|
|
64946
|
+
targetTemp: number().nullable().meta(readingMeta("temperature")),
|
|
64691
64947
|
/** Active operation mode = HA `state` (`eco` / `electric` / `gas` /
|
|
64692
64948
|
* `heat_pump` / `high_demand` / `performance` / `off`). Null when the
|
|
64693
64949
|
* device reports an unknown state. */
|
|
@@ -64698,9 +64954,9 @@ object({
|
|
|
64698
64954
|
* has no away surface. */
|
|
64699
64955
|
away: boolean().nullable(),
|
|
64700
64956
|
/** HA `min_temp` attribute. Null when not reported. */
|
|
64701
|
-
minTemp: number().nullable(),
|
|
64957
|
+
minTemp: number().nullable().meta(readingMeta("temperature")),
|
|
64702
64958
|
/** HA `max_temp` attribute. Null when not reported. */
|
|
64703
|
-
maxTemp: number().nullable(),
|
|
64959
|
+
maxTemp: number().nullable().meta(readingMeta("temperature")),
|
|
64704
64960
|
/** Ms epoch when the slice was last updated. */
|
|
64705
64961
|
lastChangedAt: number()
|
|
64706
64962
|
});
|
|
@@ -64724,25 +64980,18 @@ DeviceType.WaterHeater, method(object({
|
|
|
64724
64980
|
auth: "protected"
|
|
64725
64981
|
});
|
|
64726
64982
|
object({
|
|
64727
|
-
/** Verbatim
|
|
64728
|
-
* when no condition has been reported yet. */
|
|
64983
|
+
/** Verbatim condition state (`sunny`, `cloudy`, `rainy`, …). Null when none yet. */
|
|
64729
64984
|
condition: string().nullable(),
|
|
64730
|
-
/** Current temperature in
|
|
64731
|
-
temperature: number().nullable(),
|
|
64732
|
-
/** Temperature unit string (e.g. `°C` / `°F`). Null when not provided. */
|
|
64733
|
-
temperatureUnit: string().nullable(),
|
|
64985
|
+
/** Current temperature in Celsius. Null when not provided or refused. */
|
|
64986
|
+
temperature: number().nullable().meta(readingMeta("temperature", { precision: 1 })),
|
|
64734
64987
|
/** Relative humidity (0..100). Null when not provided. */
|
|
64735
|
-
humidity: number().min(0).max(100).nullable(),
|
|
64736
|
-
/** Barometric pressure in
|
|
64737
|
-
pressure: number().nullable(),
|
|
64738
|
-
/**
|
|
64739
|
-
|
|
64740
|
-
/** Wind speed in the reported unit. Null when not provided. */
|
|
64741
|
-
windSpeed: number().nullable(),
|
|
64742
|
-
/** Wind-speed unit string (e.g. `km/h` / `mph`). Null when not provided. */
|
|
64743
|
-
windSpeedUnit: string().nullable(),
|
|
64988
|
+
humidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
64989
|
+
/** Barometric pressure in hPa. Null when not provided or refused. */
|
|
64990
|
+
pressure: number().nullable().meta(readingMeta("pressure")),
|
|
64991
|
+
/** Wind speed in metres per second. Null when not provided or refused. */
|
|
64992
|
+
windSpeed: number().nullable().meta(readingMeta("speed")),
|
|
64744
64993
|
/** Wind bearing in degrees (0..360, meteorological). Null when not provided. */
|
|
64745
|
-
windBearing: number().nullable(),
|
|
64994
|
+
windBearing: number().nullable().meta(readingMeta("angle")),
|
|
64746
64995
|
/** Ms epoch when the slice was last updated. */
|
|
64747
64996
|
lastFetchedAt: number()
|
|
64748
64997
|
});
|
|
@@ -68860,6 +69109,13 @@ Object.freeze({
|
|
|
68860
69109
|
access: "view",
|
|
68861
69110
|
role: "viewer"
|
|
68862
69111
|
},
|
|
69112
|
+
"groupStatus.getStatus": {
|
|
69113
|
+
capName: "group-status",
|
|
69114
|
+
capScope: "device",
|
|
69115
|
+
addonId: null,
|
|
69116
|
+
access: "view",
|
|
69117
|
+
role: "viewer"
|
|
69118
|
+
},
|
|
68863
69119
|
"heatingValve.getStatus": {
|
|
68864
69120
|
capName: "heating-valve",
|
|
68865
69121
|
capScope: "device",
|
|
@@ -78682,6 +78938,33 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78682
78938
|
icon: "flame"
|
|
78683
78939
|
}]
|
|
78684
78940
|
},
|
|
78941
|
+
"group-status": {
|
|
78942
|
+
scope: "device",
|
|
78943
|
+
noun: t("Group", "Gruppo"),
|
|
78944
|
+
state: [
|
|
78945
|
+
{
|
|
78946
|
+
kind: "numeric",
|
|
78947
|
+
field: "included",
|
|
78948
|
+
quantity: t("the members reporting", "i membri che rispondono"),
|
|
78949
|
+
label: t("Reporting", "Rispondono"),
|
|
78950
|
+
icon: "users"
|
|
78951
|
+
},
|
|
78952
|
+
{
|
|
78953
|
+
kind: "numeric",
|
|
78954
|
+
field: "excluded",
|
|
78955
|
+
quantity: t("the members left out", "i membri esclusi"),
|
|
78956
|
+
label: t("Excluded", "Esclusi"),
|
|
78957
|
+
icon: "users"
|
|
78958
|
+
},
|
|
78959
|
+
{
|
|
78960
|
+
kind: "numeric",
|
|
78961
|
+
field: "total",
|
|
78962
|
+
quantity: t("the member count", "il numero di membri"),
|
|
78963
|
+
label: t("Members", "Membri"),
|
|
78964
|
+
icon: "sigma"
|
|
78965
|
+
}
|
|
78966
|
+
]
|
|
78967
|
+
},
|
|
78685
78968
|
"humidity-sensor": {
|
|
78686
78969
|
scope: "device",
|
|
78687
78970
|
noun: t("Humidity", "Umidità"),
|
|
@@ -78715,7 +78998,6 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78715
78998
|
field: "value",
|
|
78716
78999
|
quantity: t("the reading", "il valore"),
|
|
78717
79000
|
label: t("Reading", "Valore"),
|
|
78718
|
-
unitField: "unit",
|
|
78719
79001
|
icon: "gauge"
|
|
78720
79002
|
}]
|
|
78721
79003
|
},
|
|
@@ -78851,7 +79133,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78851
79133
|
field: "temperature",
|
|
78852
79134
|
quantity: t("the outdoor temperature", "la temperatura esterna"),
|
|
78853
79135
|
label: t("Temperature", "Temperatura"),
|
|
78854
|
-
|
|
79136
|
+
unit: "°C",
|
|
78855
79137
|
icon: "thermometer"
|
|
78856
79138
|
},
|
|
78857
79139
|
{
|
|
@@ -78867,7 +79149,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78867
79149
|
field: "windSpeed",
|
|
78868
79150
|
quantity: t("the wind speed", "la velocità del vento"),
|
|
78869
79151
|
label: t("Wind", "Vento"),
|
|
78870
|
-
|
|
79152
|
+
unit: "m/s",
|
|
78871
79153
|
icon: "wind"
|
|
78872
79154
|
},
|
|
78873
79155
|
{
|
|
@@ -78875,7 +79157,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78875
79157
|
field: "pressure",
|
|
78876
79158
|
quantity: t("the air pressure", "la pressione atmosferica"),
|
|
78877
79159
|
label: t("Pressure", "Pressione"),
|
|
78878
|
-
|
|
79160
|
+
unit: "hPa",
|
|
78879
79161
|
icon: "gauge"
|
|
78880
79162
|
}
|
|
78881
79163
|
]
|
|
@@ -80148,6 +80430,11 @@ Object.freeze({
|
|
|
80148
80430
|
form: "single",
|
|
80149
80431
|
optional: false
|
|
80150
80432
|
}],
|
|
80433
|
+
"groupStatus.getStatus": [{
|
|
80434
|
+
name: "deviceId",
|
|
80435
|
+
form: "single",
|
|
80436
|
+
optional: false
|
|
80437
|
+
}],
|
|
80151
80438
|
"heatingValve.getStatus": [{
|
|
80152
80439
|
name: "deviceId",
|
|
80153
80440
|
form: "single",
|