@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
|
@@ -5803,7 +5803,7 @@ var ZodIssueCode = {
|
|
|
5803
5803
|
var ZodFirstPartyTypeKind;
|
|
5804
5804
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5805
5805
|
//#endregion
|
|
5806
|
-
//#region ../types/dist/sleep-
|
|
5806
|
+
//#region ../types/dist/sleep-B81gwQuR.mjs
|
|
5807
5807
|
/**
|
|
5808
5808
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5809
5809
|
* window to float samples (D455).
|
|
@@ -8290,6 +8290,99 @@ var RecordKindDeclarationSchema = object({
|
|
|
8290
8290
|
}).strict();
|
|
8291
8291
|
/** The kind names: lower-case, dash separated, short enough for an index name. */
|
|
8292
8292
|
var RecordKindNameSchema = string().regex(/^[a-z][a-z0-9-]{0,47}$/);
|
|
8293
|
+
var READING_QUANTITIES = [
|
|
8294
|
+
"temperature",
|
|
8295
|
+
"pressure",
|
|
8296
|
+
"speed",
|
|
8297
|
+
"precipitation",
|
|
8298
|
+
"precipitation-rate",
|
|
8299
|
+
"length",
|
|
8300
|
+
"area",
|
|
8301
|
+
"illuminance",
|
|
8302
|
+
"irradiance",
|
|
8303
|
+
"power",
|
|
8304
|
+
"energy",
|
|
8305
|
+
"voltage",
|
|
8306
|
+
"current",
|
|
8307
|
+
"apparent-power",
|
|
8308
|
+
"humidity",
|
|
8309
|
+
"percentage",
|
|
8310
|
+
"concentration-volume",
|
|
8311
|
+
"concentration-mass",
|
|
8312
|
+
"concentration-ppb",
|
|
8313
|
+
"volume",
|
|
8314
|
+
"duration",
|
|
8315
|
+
"duration-ms",
|
|
8316
|
+
"information",
|
|
8317
|
+
"sound-level",
|
|
8318
|
+
"signal-level",
|
|
8319
|
+
"colour-temperature",
|
|
8320
|
+
"angle",
|
|
8321
|
+
"bitrate",
|
|
8322
|
+
"rate",
|
|
8323
|
+
"mass",
|
|
8324
|
+
"index",
|
|
8325
|
+
"ratio",
|
|
8326
|
+
"count",
|
|
8327
|
+
"none",
|
|
8328
|
+
"device"
|
|
8329
|
+
];
|
|
8330
|
+
var ReadingQuantitySchema = _enum(READING_QUANTITIES);
|
|
8331
|
+
new Set(READING_QUANTITIES);
|
|
8332
|
+
/**
|
|
8333
|
+
* Stored unit symbol for a quantity. `none` means the number is dimensionless
|
|
8334
|
+
* (or an index / ratio / count). `device` means the cap has no single unit.
|
|
8335
|
+
*/
|
|
8336
|
+
var QUANTITY_BASE = {
|
|
8337
|
+
temperature: "°C",
|
|
8338
|
+
pressure: "hPa",
|
|
8339
|
+
speed: "m/s",
|
|
8340
|
+
precipitation: "mm",
|
|
8341
|
+
"precipitation-rate": "mm/h",
|
|
8342
|
+
length: "m",
|
|
8343
|
+
area: "m²",
|
|
8344
|
+
illuminance: "lx",
|
|
8345
|
+
irradiance: "W/m²",
|
|
8346
|
+
power: "W",
|
|
8347
|
+
energy: "kWh",
|
|
8348
|
+
voltage: "V",
|
|
8349
|
+
current: "A",
|
|
8350
|
+
"apparent-power": "VA",
|
|
8351
|
+
humidity: "%",
|
|
8352
|
+
percentage: "%",
|
|
8353
|
+
"concentration-volume": "ppm",
|
|
8354
|
+
"concentration-mass": "µg/m³",
|
|
8355
|
+
"concentration-ppb": "ppb",
|
|
8356
|
+
volume: "L",
|
|
8357
|
+
duration: "s",
|
|
8358
|
+
"duration-ms": "ms",
|
|
8359
|
+
information: "B",
|
|
8360
|
+
"sound-level": "dBFS",
|
|
8361
|
+
"signal-level": "dBm",
|
|
8362
|
+
"colour-temperature": "mired",
|
|
8363
|
+
angle: "°",
|
|
8364
|
+
bitrate: "kbps",
|
|
8365
|
+
rate: "fps",
|
|
8366
|
+
mass: "kg",
|
|
8367
|
+
index: "none",
|
|
8368
|
+
ratio: "none",
|
|
8369
|
+
count: "none",
|
|
8370
|
+
none: "none",
|
|
8371
|
+
device: "device"
|
|
8372
|
+
};
|
|
8373
|
+
/** The stored unit, or `undefined` when the quantity has no unit symbol. */
|
|
8374
|
+
function baseUnitOf(quantity) {
|
|
8375
|
+
const symbol = QUANTITY_BASE[quantity];
|
|
8376
|
+
if (symbol === "none" || symbol === "device") return void 0;
|
|
8377
|
+
return symbol;
|
|
8378
|
+
}
|
|
8379
|
+
function readingMeta(quantity, extras) {
|
|
8380
|
+
return {
|
|
8381
|
+
quantity,
|
|
8382
|
+
...extras?.precision !== void 0 ? { precision: extras.precision } : {},
|
|
8383
|
+
...extras?.label !== void 0 ? { label: extras.label } : {}
|
|
8384
|
+
};
|
|
8385
|
+
}
|
|
8293
8386
|
/** Shared Zod schemas used across streaming capabilities. */
|
|
8294
8387
|
var CamProfileSchema = _enum([
|
|
8295
8388
|
"high",
|
|
@@ -8317,8 +8410,8 @@ var CamStreamKindSchema = _enum([
|
|
|
8317
8410
|
"derived"
|
|
8318
8411
|
]);
|
|
8319
8412
|
var CamStreamResolutionSchema = object({
|
|
8320
|
-
width: number().int().positive(),
|
|
8321
|
-
height: number().int().positive()
|
|
8413
|
+
width: number().int().positive().meta(readingMeta("none")),
|
|
8414
|
+
height: number().int().positive().meta(readingMeta("none"))
|
|
8322
8415
|
});
|
|
8323
8416
|
var CameraStreamSchema = object({
|
|
8324
8417
|
/** Stable, provider-assigned id unique within the (deviceId) scope. */
|
|
@@ -8913,6 +9006,7 @@ var CAP_NAMES = Object.freeze([
|
|
|
8913
9006
|
"filesystem-browse",
|
|
8914
9007
|
"flood",
|
|
8915
9008
|
"gas",
|
|
9009
|
+
"group-status",
|
|
8916
9010
|
"heating-valve",
|
|
8917
9011
|
"humidifier",
|
|
8918
9012
|
"humidity-sensor",
|
|
@@ -9042,14 +9136,6 @@ Object.freeze({
|
|
|
9042
9136
|
{
|
|
9043
9137
|
"path": "aqi",
|
|
9044
9138
|
"valueType": "number"
|
|
9045
|
-
},
|
|
9046
|
-
{
|
|
9047
|
-
"path": "unit",
|
|
9048
|
-
"valueType": "string"
|
|
9049
|
-
},
|
|
9050
|
-
{
|
|
9051
|
-
"path": "precision",
|
|
9052
|
-
"valueType": "number"
|
|
9053
9139
|
}
|
|
9054
9140
|
],
|
|
9055
9141
|
"alarm-panel": [
|
|
@@ -9085,20 +9171,10 @@ Object.freeze({
|
|
|
9085
9171
|
"valueType": "boolean"
|
|
9086
9172
|
}
|
|
9087
9173
|
],
|
|
9088
|
-
"ambient-light-sensor": [
|
|
9089
|
-
|
|
9090
|
-
|
|
9091
|
-
|
|
9092
|
-
},
|
|
9093
|
-
{
|
|
9094
|
-
"path": "unit",
|
|
9095
|
-
"valueType": "string"
|
|
9096
|
-
},
|
|
9097
|
-
{
|
|
9098
|
-
"path": "precision",
|
|
9099
|
-
"valueType": "number"
|
|
9100
|
-
}
|
|
9101
|
-
],
|
|
9174
|
+
"ambient-light-sensor": [{
|
|
9175
|
+
"path": "lux",
|
|
9176
|
+
"valueType": "number"
|
|
9177
|
+
}],
|
|
9102
9178
|
"audio-metrics": [
|
|
9103
9179
|
{
|
|
9104
9180
|
"path": "ts",
|
|
@@ -9178,6 +9254,10 @@ Object.freeze({
|
|
|
9178
9254
|
"path": "lastUpdated",
|
|
9179
9255
|
"valueType": "number"
|
|
9180
9256
|
},
|
|
9257
|
+
{
|
|
9258
|
+
"path": "volts",
|
|
9259
|
+
"valueType": "number"
|
|
9260
|
+
},
|
|
9181
9261
|
{
|
|
9182
9262
|
"path": "lastContactAt",
|
|
9183
9263
|
"valueType": "number"
|
|
@@ -9420,10 +9500,6 @@ Object.freeze({
|
|
|
9420
9500
|
"datetime"
|
|
9421
9501
|
]
|
|
9422
9502
|
},
|
|
9423
|
-
{
|
|
9424
|
-
"path": "unit",
|
|
9425
|
-
"valueType": "string"
|
|
9426
|
-
},
|
|
9427
9503
|
{
|
|
9428
9504
|
"path": "min",
|
|
9429
9505
|
"valueType": "number"
|
|
@@ -9435,19 +9511,6 @@ Object.freeze({
|
|
|
9435
9511
|
{
|
|
9436
9512
|
"path": "step",
|
|
9437
9513
|
"valueType": "number"
|
|
9438
|
-
},
|
|
9439
|
-
{
|
|
9440
|
-
"path": "precision",
|
|
9441
|
-
"valueType": "number"
|
|
9442
|
-
},
|
|
9443
|
-
{
|
|
9444
|
-
"path": "format",
|
|
9445
|
-
"valueType": "enum",
|
|
9446
|
-
"enumValues": [
|
|
9447
|
-
"date",
|
|
9448
|
-
"time",
|
|
9449
|
-
"datetime"
|
|
9450
|
-
]
|
|
9451
9514
|
}
|
|
9452
9515
|
],
|
|
9453
9516
|
"cover": [
|
|
@@ -9688,13 +9751,8 @@ Object.freeze({
|
|
|
9688
9751
|
"path": "value",
|
|
9689
9752
|
"valueType": "string"
|
|
9690
9753
|
}, {
|
|
9691
|
-
"path": "
|
|
9692
|
-
"valueType": "
|
|
9693
|
-
"enumValues": [
|
|
9694
|
-
"date",
|
|
9695
|
-
"time",
|
|
9696
|
-
"datetime"
|
|
9697
|
-
]
|
|
9754
|
+
"path": "timestamp",
|
|
9755
|
+
"valueType": "boolean"
|
|
9698
9756
|
}],
|
|
9699
9757
|
"event-emitter": [
|
|
9700
9758
|
{
|
|
@@ -9767,6 +9825,20 @@ Object.freeze({
|
|
|
9767
9825
|
"path": "detected",
|
|
9768
9826
|
"valueType": "boolean"
|
|
9769
9827
|
}],
|
|
9828
|
+
"group-status": [
|
|
9829
|
+
{
|
|
9830
|
+
"path": "included",
|
|
9831
|
+
"valueType": "number"
|
|
9832
|
+
},
|
|
9833
|
+
{
|
|
9834
|
+
"path": "excluded",
|
|
9835
|
+
"valueType": "number"
|
|
9836
|
+
},
|
|
9837
|
+
{
|
|
9838
|
+
"path": "total",
|
|
9839
|
+
"valueType": "number"
|
|
9840
|
+
}
|
|
9841
|
+
],
|
|
9770
9842
|
"heating-valve": [{
|
|
9771
9843
|
"path": "position",
|
|
9772
9844
|
"valueType": "number"
|
|
@@ -9801,20 +9873,10 @@ Object.freeze({
|
|
|
9801
9873
|
"valueType": "number"
|
|
9802
9874
|
}
|
|
9803
9875
|
],
|
|
9804
|
-
"humidity-sensor": [
|
|
9805
|
-
|
|
9806
|
-
|
|
9807
|
-
|
|
9808
|
-
},
|
|
9809
|
-
{
|
|
9810
|
-
"path": "unit",
|
|
9811
|
-
"valueType": "string"
|
|
9812
|
-
},
|
|
9813
|
-
{
|
|
9814
|
-
"path": "precision",
|
|
9815
|
-
"valueType": "number"
|
|
9816
|
-
}
|
|
9817
|
-
],
|
|
9876
|
+
"humidity-sensor": [{
|
|
9877
|
+
"path": "percent",
|
|
9878
|
+
"valueType": "number"
|
|
9879
|
+
}],
|
|
9818
9880
|
"image": [{
|
|
9819
9881
|
"path": "url",
|
|
9820
9882
|
"valueType": "string"
|
|
@@ -10153,20 +10215,10 @@ Object.freeze({
|
|
|
10153
10215
|
"valueType": "boolean"
|
|
10154
10216
|
}
|
|
10155
10217
|
],
|
|
10156
|
-
"numeric-sensor": [
|
|
10157
|
-
|
|
10158
|
-
|
|
10159
|
-
|
|
10160
|
-
},
|
|
10161
|
-
{
|
|
10162
|
-
"path": "unit",
|
|
10163
|
-
"valueType": "string"
|
|
10164
|
-
},
|
|
10165
|
-
{
|
|
10166
|
-
"path": "precision",
|
|
10167
|
-
"valueType": "number"
|
|
10168
|
-
}
|
|
10169
|
-
],
|
|
10218
|
+
"numeric-sensor": [{
|
|
10219
|
+
"path": "value",
|
|
10220
|
+
"valueType": "number"
|
|
10221
|
+
}],
|
|
10170
10222
|
"pet-feeder": [
|
|
10171
10223
|
{
|
|
10172
10224
|
"path": "foodLevel",
|
|
@@ -10258,14 +10310,6 @@ Object.freeze({
|
|
|
10258
10310
|
{
|
|
10259
10311
|
"path": "powerFactor",
|
|
10260
10312
|
"valueType": "number"
|
|
10261
|
-
},
|
|
10262
|
-
{
|
|
10263
|
-
"path": "unit",
|
|
10264
|
-
"valueType": "string"
|
|
10265
|
-
},
|
|
10266
|
-
{
|
|
10267
|
-
"path": "precision",
|
|
10268
|
-
"valueType": "number"
|
|
10269
10313
|
}
|
|
10270
10314
|
],
|
|
10271
10315
|
"presence": [
|
|
@@ -10294,20 +10338,10 @@ Object.freeze({
|
|
|
10294
10338
|
"valueType": "number"
|
|
10295
10339
|
}
|
|
10296
10340
|
],
|
|
10297
|
-
"pressure-sensor": [
|
|
10298
|
-
|
|
10299
|
-
|
|
10300
|
-
|
|
10301
|
-
},
|
|
10302
|
-
{
|
|
10303
|
-
"path": "unit",
|
|
10304
|
-
"valueType": "string"
|
|
10305
|
-
},
|
|
10306
|
-
{
|
|
10307
|
-
"path": "precision",
|
|
10308
|
-
"valueType": "number"
|
|
10309
|
-
}
|
|
10310
|
-
],
|
|
10341
|
+
"pressure-sensor": [{
|
|
10342
|
+
"path": "hpa",
|
|
10343
|
+
"valueType": "number"
|
|
10344
|
+
}],
|
|
10311
10345
|
"privacy-mask": [{
|
|
10312
10346
|
"path": "enabled",
|
|
10313
10347
|
"valueType": "boolean"
|
|
@@ -10618,20 +10652,10 @@ Object.freeze({
|
|
|
10618
10652
|
"path": "tampered",
|
|
10619
10653
|
"valueType": "boolean"
|
|
10620
10654
|
}],
|
|
10621
|
-
"temperature-sensor": [
|
|
10622
|
-
|
|
10623
|
-
|
|
10624
|
-
|
|
10625
|
-
},
|
|
10626
|
-
{
|
|
10627
|
-
"path": "unit",
|
|
10628
|
-
"valueType": "string"
|
|
10629
|
-
},
|
|
10630
|
-
{
|
|
10631
|
-
"path": "precision",
|
|
10632
|
-
"valueType": "number"
|
|
10633
|
-
}
|
|
10634
|
-
],
|
|
10655
|
+
"temperature-sensor": [{
|
|
10656
|
+
"path": "celsius",
|
|
10657
|
+
"valueType": "number"
|
|
10658
|
+
}],
|
|
10635
10659
|
"update": [
|
|
10636
10660
|
{
|
|
10637
10661
|
"path": "currentVersion",
|
|
@@ -10742,10 +10766,6 @@ Object.freeze({
|
|
|
10742
10766
|
"path": "temperature",
|
|
10743
10767
|
"valueType": "number"
|
|
10744
10768
|
},
|
|
10745
|
-
{
|
|
10746
|
-
"path": "temperatureUnit",
|
|
10747
|
-
"valueType": "string"
|
|
10748
|
-
},
|
|
10749
10769
|
{
|
|
10750
10770
|
"path": "humidity",
|
|
10751
10771
|
"valueType": "number"
|
|
@@ -10754,18 +10774,10 @@ Object.freeze({
|
|
|
10754
10774
|
"path": "pressure",
|
|
10755
10775
|
"valueType": "number"
|
|
10756
10776
|
},
|
|
10757
|
-
{
|
|
10758
|
-
"path": "pressureUnit",
|
|
10759
|
-
"valueType": "string"
|
|
10760
|
-
},
|
|
10761
10777
|
{
|
|
10762
10778
|
"path": "windSpeed",
|
|
10763
10779
|
"valueType": "number"
|
|
10764
10780
|
},
|
|
10765
|
-
{
|
|
10766
|
-
"path": "windSpeedUnit",
|
|
10767
|
-
"valueType": "string"
|
|
10768
|
-
},
|
|
10769
10781
|
{
|
|
10770
10782
|
"path": "windBearing",
|
|
10771
10783
|
"valueType": "number"
|
|
@@ -11158,7 +11170,7 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
|
|
|
11158
11170
|
return DeviceRole;
|
|
11159
11171
|
}({});
|
|
11160
11172
|
//#endregion
|
|
11161
|
-
//#region ../types/dist/composition-
|
|
11173
|
+
//#region ../types/dist/composition-B85l9j1M.mjs
|
|
11162
11174
|
/**
|
|
11163
11175
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
11164
11176
|
*
|
|
@@ -11913,15 +11925,67 @@ function validateExpressionSource(src) {
|
|
|
11913
11925
|
}
|
|
11914
11926
|
return null;
|
|
11915
11927
|
}
|
|
11916
|
-
/**
|
|
11917
|
-
|
|
11918
|
-
|
|
11919
|
-
|
|
11928
|
+
/**
|
|
11929
|
+
* A composition source identity: `(addonId, stableId)`, never a numeric device
|
|
11930
|
+
* id. Split out so helper schemas can name it without a cycle through
|
|
11931
|
+
* `composition.ts` (D659).
|
|
11932
|
+
*/
|
|
11920
11933
|
var CompositionSourceRefSchema = object({
|
|
11921
11934
|
/** The owning addon; `stableId` is unique only within it. */
|
|
11922
11935
|
addonId: string().min(1),
|
|
11923
11936
|
stableId: string().min(1)
|
|
11924
11937
|
});
|
|
11938
|
+
var GROUP_TEMPLATE_IDS = [
|
|
11939
|
+
"temperature",
|
|
11940
|
+
"humidity",
|
|
11941
|
+
"pressure",
|
|
11942
|
+
"illuminance",
|
|
11943
|
+
"power",
|
|
11944
|
+
"energy",
|
|
11945
|
+
"battery",
|
|
11946
|
+
"numeric",
|
|
11947
|
+
"motion",
|
|
11948
|
+
"contact",
|
|
11949
|
+
"leak",
|
|
11950
|
+
"smoke",
|
|
11951
|
+
"occupancy",
|
|
11952
|
+
"binary"
|
|
11953
|
+
];
|
|
11954
|
+
var NUMERIC_AGGREGATES = [
|
|
11955
|
+
"mean",
|
|
11956
|
+
"median",
|
|
11957
|
+
"min",
|
|
11958
|
+
"max",
|
|
11959
|
+
"sum"
|
|
11960
|
+
];
|
|
11961
|
+
var BINARY_AGGREGATES = ["any", "all"];
|
|
11962
|
+
var AGGREGATE_REDUCERS = [
|
|
11963
|
+
"mean",
|
|
11964
|
+
"median",
|
|
11965
|
+
"min",
|
|
11966
|
+
"max",
|
|
11967
|
+
"sum",
|
|
11968
|
+
"any",
|
|
11969
|
+
"all"
|
|
11970
|
+
];
|
|
11971
|
+
var GroupTemplateIdSchema = _enum(GROUP_TEMPLATE_IDS);
|
|
11972
|
+
var AggregateReducerSchema = _enum(AGGREGATE_REDUCERS);
|
|
11973
|
+
/** One member. The field is stored so occupancy can name motion or binary. */
|
|
11974
|
+
var HelperMemberSchema = object({
|
|
11975
|
+
source: CompositionSourceRefSchema,
|
|
11976
|
+
cap: string().min(1),
|
|
11977
|
+
fieldPath: string().min(1)
|
|
11978
|
+
});
|
|
11979
|
+
var HelperSpecSchema = discriminatedUnion("kind", [object({
|
|
11980
|
+
kind: literal("group"),
|
|
11981
|
+
templateId: GroupTemplateIdSchema,
|
|
11982
|
+
aggregate: AggregateReducerSchema,
|
|
11983
|
+
members: array(HelperMemberSchema).min(1).max(64)
|
|
11984
|
+
})]);
|
|
11985
|
+
/** A composed device's stableId is this prefix plus the block id. */
|
|
11986
|
+
var COMPOSED_DEVICE_STABLE_ID_PREFIX = "composed-";
|
|
11987
|
+
/** Longest snippet a `code` source may carry (slice 4). */
|
|
11988
|
+
var MAX_COMPOSITION_CODE_LENGTH = 2e4;
|
|
11925
11989
|
/** One field of one capability of one source device. */
|
|
11926
11990
|
var CompositionFieldReadSchema = object({
|
|
11927
11991
|
source: CompositionSourceRefSchema,
|
|
@@ -11965,7 +12029,33 @@ var CompositionCodeSourceSchema = object({
|
|
|
11965
12029
|
var CompositionFieldSourceSchema = discriminatedUnion("kind", [
|
|
11966
12030
|
CompositionFromSourceSchema,
|
|
11967
12031
|
CompositionExpressionSourceSchema,
|
|
11968
|
-
CompositionCodeSourceSchema
|
|
12032
|
+
CompositionCodeSourceSchema,
|
|
12033
|
+
object({
|
|
12034
|
+
kind: literal("aggregate"),
|
|
12035
|
+
reducer: _enum([
|
|
12036
|
+
"mean",
|
|
12037
|
+
"median",
|
|
12038
|
+
"min",
|
|
12039
|
+
"max",
|
|
12040
|
+
"sum",
|
|
12041
|
+
"any",
|
|
12042
|
+
"all"
|
|
12043
|
+
]),
|
|
12044
|
+
reads: array(CompositionFieldReadSchema).min(1).max(64),
|
|
12045
|
+
/** `value` is the reading; the others are the member counts. */
|
|
12046
|
+
publish: _enum([
|
|
12047
|
+
"value",
|
|
12048
|
+
"included",
|
|
12049
|
+
"excluded",
|
|
12050
|
+
"total"
|
|
12051
|
+
]),
|
|
12052
|
+
/** What a `value` publish does when nobody is included. Counts ignore this. */
|
|
12053
|
+
empty: _enum([
|
|
12054
|
+
"null",
|
|
12055
|
+
"omit",
|
|
12056
|
+
"offline"
|
|
12057
|
+
])
|
|
12058
|
+
})
|
|
11969
12059
|
]);
|
|
11970
12060
|
var CompositionCommandTargetSchema = discriminatedUnion("kind", [object({
|
|
11971
12061
|
kind: literal("forward"),
|
|
@@ -12011,7 +12101,13 @@ var CompositionSchema = object({
|
|
|
12011
12101
|
kind: literal("existing"),
|
|
12012
12102
|
device: CompositionSourceRefSchema
|
|
12013
12103
|
})]),
|
|
12014
|
-
features: array(CompositionFeatureSchema).min(1).max(16)
|
|
12104
|
+
features: array(CompositionFeatureSchema).min(1).max(16),
|
|
12105
|
+
/**
|
|
12106
|
+
* Present when the block is a helper template. Absent on a free
|
|
12107
|
+
* composition (the room example, device 4603). The editor reads this,
|
|
12108
|
+
* never the compiled features.
|
|
12109
|
+
*/
|
|
12110
|
+
helper: HelperSpecSchema.optional()
|
|
12015
12111
|
}).superRefine((composition, ctx) => {
|
|
12016
12112
|
const seen = /* @__PURE__ */ new Set();
|
|
12017
12113
|
composition.features.forEach((feature, index) => {
|
|
@@ -18269,7 +18365,11 @@ var CompositionProblemSchema = object({
|
|
|
18269
18365
|
"item-field-reserved",
|
|
18270
18366
|
"target-missing",
|
|
18271
18367
|
"target-unreadable",
|
|
18272
|
-
"not-replaceable"
|
|
18368
|
+
"not-replaceable",
|
|
18369
|
+
"native-capability-replace",
|
|
18370
|
+
"mixed-quantity",
|
|
18371
|
+
"helper-mismatch",
|
|
18372
|
+
"member-constraint"
|
|
18273
18373
|
]),
|
|
18274
18374
|
path: string(),
|
|
18275
18375
|
message: string()
|
|
@@ -18290,7 +18390,8 @@ var CompositionUnavailableModeSchema = _enum([
|
|
|
18290
18390
|
"null",
|
|
18291
18391
|
"offline",
|
|
18292
18392
|
"unknown",
|
|
18293
|
-
"release"
|
|
18393
|
+
"release",
|
|
18394
|
+
"omit"
|
|
18294
18395
|
]);
|
|
18295
18396
|
/**
|
|
18296
18397
|
* `derived` reads a source · `clock` reads only `now`, recomputed when a sibling
|
|
@@ -18327,9 +18428,11 @@ var CompositionFieldPlanSchema = object({
|
|
|
18327
18428
|
reads: array(CompositionFieldReadSchema)
|
|
18328
18429
|
});
|
|
18329
18430
|
/**
|
|
18330
|
-
* What a feature does to its target (D663): `new` builds a capability on a
|
|
18331
|
-
* device; on an existing device it `add`s a capability the device lacks
|
|
18332
|
-
*
|
|
18431
|
+
* What a feature does to its target (D663, D944): `new` builds a capability on a
|
|
18432
|
+
* new device; on an existing device it `add`s a capability the device lacks.
|
|
18433
|
+
* Replacing a capability the device already serves is refused
|
|
18434
|
+
* (`native-capability-replace`), not planned. `replace` remains on the claim
|
|
18435
|
+
* wire for a claim the hub already holds.
|
|
18333
18436
|
*/
|
|
18334
18437
|
var CompositionFeatureModeSchema = _enum([
|
|
18335
18438
|
"new",
|
|
@@ -18502,6 +18605,235 @@ Object.freeze({
|
|
|
18502
18605
|
result: ["number", "null"]
|
|
18503
18606
|
}
|
|
18504
18607
|
});
|
|
18608
|
+
/**
|
|
18609
|
+
* One catalog row per base reading a group helper can build (D944 §3).
|
|
18610
|
+
* Data, not a form default written into the block.
|
|
18611
|
+
*/
|
|
18612
|
+
var NOW = {
|
|
18613
|
+
fieldPath: "lastFetchedAt",
|
|
18614
|
+
expr: "now"
|
|
18615
|
+
};
|
|
18616
|
+
var CHANGED = {
|
|
18617
|
+
fieldPath: "lastChangedAt",
|
|
18618
|
+
expr: "now"
|
|
18619
|
+
};
|
|
18620
|
+
function numeric(input) {
|
|
18621
|
+
return {
|
|
18622
|
+
...input,
|
|
18623
|
+
family: "numeric",
|
|
18624
|
+
deviceType: DeviceType.Sensor,
|
|
18625
|
+
memberDeviceType: DeviceType.Sensor,
|
|
18626
|
+
baseUnit: baseUnitOf(input.quantity),
|
|
18627
|
+
aggregates: NUMERIC_AGGREGATES,
|
|
18628
|
+
accept: [{
|
|
18629
|
+
cap: input.outputCap,
|
|
18630
|
+
fieldPath: input.outputField
|
|
18631
|
+
}]
|
|
18632
|
+
};
|
|
18633
|
+
}
|
|
18634
|
+
function binary(input) {
|
|
18635
|
+
return {
|
|
18636
|
+
...input,
|
|
18637
|
+
family: "binary",
|
|
18638
|
+
deviceType: DeviceType.Sensor,
|
|
18639
|
+
memberDeviceType: DeviceType.Sensor,
|
|
18640
|
+
quantity: "none",
|
|
18641
|
+
baseUnit: void 0,
|
|
18642
|
+
aggregates: BINARY_AGGREGATES,
|
|
18643
|
+
empty: "offline"
|
|
18644
|
+
};
|
|
18645
|
+
}
|
|
18646
|
+
var GROUP_TEMPLATES = [
|
|
18647
|
+
numeric({
|
|
18648
|
+
id: "temperature",
|
|
18649
|
+
summary: "Mean, median, min, max or sum of temperatures. Offline and unknown members are left out, never read as 0 °C.",
|
|
18650
|
+
role: DeviceRole.TemperatureSensor,
|
|
18651
|
+
outputCap: "temperature-sensor",
|
|
18652
|
+
outputField: "celsius",
|
|
18653
|
+
quantity: "temperature",
|
|
18654
|
+
defaultAggregate: "mean",
|
|
18655
|
+
empty: "null",
|
|
18656
|
+
companions: [NOW]
|
|
18657
|
+
}),
|
|
18658
|
+
numeric({
|
|
18659
|
+
id: "humidity",
|
|
18660
|
+
summary: "Humidity in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
18661
|
+
role: DeviceRole.HumiditySensor,
|
|
18662
|
+
outputCap: "humidity-sensor",
|
|
18663
|
+
outputField: "percent",
|
|
18664
|
+
quantity: "humidity",
|
|
18665
|
+
defaultAggregate: "mean",
|
|
18666
|
+
empty: "null",
|
|
18667
|
+
companions: [NOW]
|
|
18668
|
+
}),
|
|
18669
|
+
numeric({
|
|
18670
|
+
id: "pressure",
|
|
18671
|
+
summary: "Pressure in hectopascals. Offline and unknown members are left out, never read as 0 hPa.",
|
|
18672
|
+
role: DeviceRole.PressureSensor,
|
|
18673
|
+
outputCap: "pressure-sensor",
|
|
18674
|
+
outputField: "hpa",
|
|
18675
|
+
quantity: "pressure",
|
|
18676
|
+
defaultAggregate: "mean",
|
|
18677
|
+
empty: "null",
|
|
18678
|
+
companions: [NOW]
|
|
18679
|
+
}),
|
|
18680
|
+
numeric({
|
|
18681
|
+
id: "illuminance",
|
|
18682
|
+
summary: "Illuminance in lux. Offline and unknown members are left out, never read as 0 lx.",
|
|
18683
|
+
role: DeviceRole.AmbientLightSensor,
|
|
18684
|
+
outputCap: "ambient-light-sensor",
|
|
18685
|
+
outputField: "lux",
|
|
18686
|
+
quantity: "illuminance",
|
|
18687
|
+
defaultAggregate: "mean",
|
|
18688
|
+
empty: "null",
|
|
18689
|
+
companions: [NOW]
|
|
18690
|
+
}),
|
|
18691
|
+
numeric({
|
|
18692
|
+
id: "power",
|
|
18693
|
+
summary: "Power in watts, summed by default. Nobody reporting omits the key rather than writing 0 W.",
|
|
18694
|
+
role: DeviceRole.PowerSensor,
|
|
18695
|
+
outputCap: "power-meter",
|
|
18696
|
+
outputField: "watts",
|
|
18697
|
+
quantity: "power",
|
|
18698
|
+
defaultAggregate: "sum",
|
|
18699
|
+
empty: "omit",
|
|
18700
|
+
companions: [NOW]
|
|
18701
|
+
}),
|
|
18702
|
+
numeric({
|
|
18703
|
+
id: "energy",
|
|
18704
|
+
summary: "Energy in kilowatt-hours, summed by default. Nobody reporting omits the key rather than writing 0 kWh.",
|
|
18705
|
+
role: DeviceRole.EnergySensor,
|
|
18706
|
+
outputCap: "power-meter",
|
|
18707
|
+
outputField: "kwhTotal",
|
|
18708
|
+
quantity: "energy",
|
|
18709
|
+
defaultAggregate: "sum",
|
|
18710
|
+
empty: "omit",
|
|
18711
|
+
companions: [NOW]
|
|
18712
|
+
}),
|
|
18713
|
+
numeric({
|
|
18714
|
+
id: "battery",
|
|
18715
|
+
summary: "Battery charge in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
18716
|
+
role: DeviceRole.BatterySensor,
|
|
18717
|
+
outputCap: "battery",
|
|
18718
|
+
outputField: "percentage",
|
|
18719
|
+
quantity: "percentage",
|
|
18720
|
+
defaultAggregate: "mean",
|
|
18721
|
+
empty: "null",
|
|
18722
|
+
companions: [
|
|
18723
|
+
{
|
|
18724
|
+
fieldPath: "charging",
|
|
18725
|
+
expr: "\"unknown\""
|
|
18726
|
+
},
|
|
18727
|
+
{
|
|
18728
|
+
fieldPath: "sleeping",
|
|
18729
|
+
expr: "false"
|
|
18730
|
+
},
|
|
18731
|
+
{
|
|
18732
|
+
fieldPath: "lastUpdated",
|
|
18733
|
+
expr: "now"
|
|
18734
|
+
}
|
|
18735
|
+
]
|
|
18736
|
+
}),
|
|
18737
|
+
numeric({
|
|
18738
|
+
id: "numeric",
|
|
18739
|
+
summary: "A numeric reading in the members’ shared quantity. Mixed quantities are refused. Nobody reporting publishes null, not 0.",
|
|
18740
|
+
role: DeviceRole.NumericSensor,
|
|
18741
|
+
outputCap: "numeric-sensor",
|
|
18742
|
+
outputField: "value",
|
|
18743
|
+
quantity: "device",
|
|
18744
|
+
defaultAggregate: "mean",
|
|
18745
|
+
empty: "null",
|
|
18746
|
+
companions: [NOW]
|
|
18747
|
+
}),
|
|
18748
|
+
binary({
|
|
18749
|
+
id: "motion",
|
|
18750
|
+
summary: "Any or all motion. Offline and unknown members are left out, never read as off. Nobody reporting takes the device offline.",
|
|
18751
|
+
role: DeviceRole.MotionSensor,
|
|
18752
|
+
outputCap: "motion",
|
|
18753
|
+
outputField: "detected",
|
|
18754
|
+
defaultAggregate: "any",
|
|
18755
|
+
accept: [{
|
|
18756
|
+
cap: "motion",
|
|
18757
|
+
fieldPath: "detected"
|
|
18758
|
+
}],
|
|
18759
|
+
companions: [{
|
|
18760
|
+
fieldPath: "lastDetectedAt",
|
|
18761
|
+
expr: "null"
|
|
18762
|
+
}, {
|
|
18763
|
+
fieldPath: "autoClearAfterMs",
|
|
18764
|
+
expr: "null"
|
|
18765
|
+
}]
|
|
18766
|
+
}),
|
|
18767
|
+
binary({
|
|
18768
|
+
id: "contact",
|
|
18769
|
+
summary: "Any or all open contacts. Offline and unknown members are left out, never read as closed.",
|
|
18770
|
+
role: DeviceRole.ContactSensor,
|
|
18771
|
+
outputCap: "contact",
|
|
18772
|
+
outputField: "entryOpen",
|
|
18773
|
+
defaultAggregate: "any",
|
|
18774
|
+
accept: [{
|
|
18775
|
+
cap: "contact",
|
|
18776
|
+
fieldPath: "entryOpen"
|
|
18777
|
+
}],
|
|
18778
|
+
companions: [CHANGED]
|
|
18779
|
+
}),
|
|
18780
|
+
binary({
|
|
18781
|
+
id: "leak",
|
|
18782
|
+
summary: "Any or all leak detections. Offline and unknown members are left out, never read as dry.",
|
|
18783
|
+
role: DeviceRole.LeakSensor,
|
|
18784
|
+
outputCap: "flood",
|
|
18785
|
+
outputField: "flooded",
|
|
18786
|
+
defaultAggregate: "any",
|
|
18787
|
+
accept: [{
|
|
18788
|
+
cap: "flood",
|
|
18789
|
+
fieldPath: "flooded"
|
|
18790
|
+
}],
|
|
18791
|
+
companions: [CHANGED]
|
|
18792
|
+
}),
|
|
18793
|
+
binary({
|
|
18794
|
+
id: "smoke",
|
|
18795
|
+
summary: "Any or all smoke detections. Offline and unknown members are left out, never read as clear.",
|
|
18796
|
+
role: DeviceRole.SmokeSensor,
|
|
18797
|
+
outputCap: "smoke",
|
|
18798
|
+
outputField: "detected",
|
|
18799
|
+
defaultAggregate: "any",
|
|
18800
|
+
accept: [{
|
|
18801
|
+
cap: "smoke",
|
|
18802
|
+
fieldPath: "detected"
|
|
18803
|
+
}],
|
|
18804
|
+
companions: [CHANGED]
|
|
18805
|
+
}),
|
|
18806
|
+
binary({
|
|
18807
|
+
id: "occupancy",
|
|
18808
|
+
summary: "Any or all of motion or binary sensors, published as a binary. Presence zones are not aggregated. Nobody reporting is offline, not off.",
|
|
18809
|
+
role: DeviceRole.BinarySensor,
|
|
18810
|
+
outputCap: "binary",
|
|
18811
|
+
outputField: "on",
|
|
18812
|
+
defaultAggregate: "any",
|
|
18813
|
+
accept: [{
|
|
18814
|
+
cap: "motion",
|
|
18815
|
+
fieldPath: "detected"
|
|
18816
|
+
}, {
|
|
18817
|
+
cap: "binary",
|
|
18818
|
+
fieldPath: "on"
|
|
18819
|
+
}],
|
|
18820
|
+
companions: [CHANGED]
|
|
18821
|
+
}),
|
|
18822
|
+
binary({
|
|
18823
|
+
id: "binary",
|
|
18824
|
+
summary: "Any or all generic binary sensors. Offline and unknown members are left out, never read as off.",
|
|
18825
|
+
role: DeviceRole.BinarySensor,
|
|
18826
|
+
outputCap: "binary",
|
|
18827
|
+
outputField: "on",
|
|
18828
|
+
defaultAggregate: "any",
|
|
18829
|
+
accept: [{
|
|
18830
|
+
cap: "binary",
|
|
18831
|
+
fieldPath: "on"
|
|
18832
|
+
}],
|
|
18833
|
+
companions: [CHANGED]
|
|
18834
|
+
})
|
|
18835
|
+
];
|
|
18836
|
+
new Map(GROUP_TEMPLATES.map((template) => [template.id, template]));
|
|
18505
18837
|
`${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
|
|
18506
18838
|
/**
|
|
18507
18839
|
* What a composition may BUILD on a device type (G2, D676): the caps a new
|
|
@@ -20243,12 +20575,12 @@ method(object({ deviceId: number().int().nonnegative() }), DeviceAdminLinkSchema
|
|
|
20243
20575
|
* providers detect renames by matching `uniqueId` and patch `id`
|
|
20244
20576
|
* in-place so dispatch keeps working.
|
|
20245
20577
|
*
|
|
20246
|
-
* **
|
|
20247
|
-
*
|
|
20248
|
-
*
|
|
20249
|
-
*
|
|
20250
|
-
* (`ha-domain-mapping`)
|
|
20251
|
-
* stored after that point.
|
|
20578
|
+
* **Display unit and precision are NOT stored here.** They are a read-time
|
|
20579
|
+
* preference (D944). A polymorphic reading stores its `quantity` here once,
|
|
20580
|
+
* at adopt, and a date/time value stores `dateTimeShape` the same way —
|
|
20581
|
+
* neither is repeated on each sample. The `device_class` tag is an
|
|
20582
|
+
* HA-specific input consumed at the discovery boundary (`ha-domain-mapping`)
|
|
20583
|
+
* to derive the CamStack `DeviceRole`; it is never stored after that point.
|
|
20252
20584
|
*
|
|
20253
20585
|
* The `raw` escape hatch carries provider-specific attributes that don't
|
|
20254
20586
|
* fit the structured slots (HA `attributes` whitelist, Reolink `deviceCache`
|
|
@@ -20262,6 +20594,14 @@ var SourceInfoSchema = object({
|
|
|
20262
20594
|
/** Immutable upstream identifier when available (HA `unique_id`, … ).
|
|
20263
20595
|
* Used to detect rename when `id` changes. */
|
|
20264
20596
|
uniqueId: string().optional(),
|
|
20597
|
+
/** Quantity of a polymorphic reading, written once at adopt (D944). */
|
|
20598
|
+
quantity: ReadingQuantitySchema.optional(),
|
|
20599
|
+
/** Date / time / datetime shape of a string reading, written once at adopt. */
|
|
20600
|
+
dateTimeShape: _enum([
|
|
20601
|
+
"date",
|
|
20602
|
+
"time",
|
|
20603
|
+
"datetime"
|
|
20604
|
+
]).optional(),
|
|
20265
20605
|
/** Provider-specific extras that don't fit the structured slots.
|
|
20266
20606
|
* Whitelist what goes here per provider — do NOT dump entire HA
|
|
20267
20607
|
* attribute blobs (would explode the meta JSON column). */
|
|
@@ -41174,7 +41514,8 @@ method(object({
|
|
|
41174
41514
|
"enum"
|
|
41175
41515
|
]),
|
|
41176
41516
|
enumValues: array(string()).optional(),
|
|
41177
|
-
item: boolean().optional()
|
|
41517
|
+
item: boolean().optional(),
|
|
41518
|
+
quantity: ReadingQuantitySchema.optional()
|
|
41178
41519
|
})).readonly(),
|
|
41179
41520
|
itemArray: object({
|
|
41180
41521
|
path: string(),
|
|
@@ -44980,8 +45321,8 @@ var MaskPolygonShapeSchema = object({
|
|
|
44980
45321
|
/** Boolean cell grid — row-major, length === gridWidth*gridHeight. */
|
|
44981
45322
|
var MaskGridShapeSchema = object({
|
|
44982
45323
|
kind: literal("grid"),
|
|
44983
|
-
gridWidth: number(),
|
|
44984
|
-
gridHeight: number(),
|
|
45324
|
+
gridWidth: number().meta(readingMeta("none")),
|
|
45325
|
+
gridHeight: number().meta(readingMeta("none")),
|
|
44985
45326
|
cells: array(boolean())
|
|
44986
45327
|
});
|
|
44987
45328
|
discriminatedUnion("kind", [
|
|
@@ -56375,46 +56716,27 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
|
|
|
56375
56716
|
}), LogStreamEntrySchema, { kind: "subscription" });
|
|
56376
56717
|
object({
|
|
56377
56718
|
/** Carbon dioxide concentration in ppm. */
|
|
56378
|
-
co2Ppm: number().min(0).optional(),
|
|
56719
|
+
co2Ppm: number().min(0).optional().meta(readingMeta("concentration-volume")),
|
|
56379
56720
|
/** Total volatile organic compounds in ppb. */
|
|
56380
|
-
vocPpb: number().min(0).optional(),
|
|
56721
|
+
vocPpb: number().min(0).optional().meta(readingMeta("concentration-ppb")),
|
|
56381
56722
|
/** Particulate matter ≤ 2.5 μm in µg/m³. */
|
|
56382
|
-
pm25: number().min(0).optional(),
|
|
56723
|
+
pm25: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
56383
56724
|
/** Particulate matter ≤ 10 μm in µg/m³. */
|
|
56384
|
-
pm10: number().min(0).optional(),
|
|
56725
|
+
pm10: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
56385
56726
|
/** Composite AQI value (typically 0..500). */
|
|
56386
|
-
aqi: number().optional(),
|
|
56727
|
+
aqi: number().optional().meta(readingMeta("index")),
|
|
56387
56728
|
/** Ms epoch when the slice was last updated. */
|
|
56388
|
-
lastFetchedAt: number()
|
|
56389
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
56390
|
-
* `attributes.unit_of_measurement` → 'ppm' / 'ppb' / 'µg/m³'). Each
|
|
56391
|
-
* upstream `sensor.*` entity surfaces ONE device_class, so one unit
|
|
56392
|
-
* per slice is unambiguous. */
|
|
56393
|
-
unit: string().optional(),
|
|
56394
|
-
/** Suggested decimal places for numeric display.
|
|
56395
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
56396
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
56397
|
-
* auto-formatting when absent. */
|
|
56398
|
-
precision: number().int().min(0).max(10).optional()
|
|
56729
|
+
lastFetchedAt: number()
|
|
56399
56730
|
});
|
|
56400
56731
|
DeviceType.Sensor;
|
|
56401
56732
|
object({
|
|
56402
|
-
/** Current illuminance in lux (lx). */
|
|
56403
|
-
lux: number().min(0).meta({
|
|
56404
|
-
|
|
56733
|
+
/** Current illuminance in lux (lx). `null` when the sample was refused (D393). */
|
|
56734
|
+
lux: number().min(0).nullable().meta(readingMeta("illuminance", {
|
|
56735
|
+
precision: 0,
|
|
56405
56736
|
label: "Illuminance"
|
|
56406
|
-
}),
|
|
56737
|
+
})),
|
|
56407
56738
|
/** Ms epoch when the slice was last updated. */
|
|
56408
|
-
lastFetchedAt: number()
|
|
56409
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
56410
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
56411
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
56412
|
-
unit: string().optional(),
|
|
56413
|
-
/** Suggested decimal places for numeric display.
|
|
56414
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
56415
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
56416
|
-
* auto-formatting when absent. */
|
|
56417
|
-
precision: number().int().min(0).max(10).optional()
|
|
56739
|
+
lastFetchedAt: number()
|
|
56418
56740
|
});
|
|
56419
56741
|
DeviceType.Sensor;
|
|
56420
56742
|
/**
|
|
@@ -56559,10 +56881,7 @@ var BatteryStatusSchema = object({
|
|
|
56559
56881
|
* Consumers must SKIP a null rather than coerce it — `battery-band` already
|
|
56560
56882
|
* declines to band a non-finite reading, which is the correct shape.
|
|
56561
56883
|
*/
|
|
56562
|
-
percentage: number().min(0).max(100).nullable().meta({
|
|
56563
|
-
unit: "%",
|
|
56564
|
-
label: "Charge"
|
|
56565
|
-
}),
|
|
56884
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage", { label: "Charge" })),
|
|
56566
56885
|
/**
|
|
56567
56886
|
* Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
|
|
56568
56887
|
* Reolink-specific for the Solar Panel 2 accessory (will become
|
|
@@ -56589,7 +56908,14 @@ var BatteryStatusSchema = object({
|
|
|
56589
56908
|
*/
|
|
56590
56909
|
sleeping: boolean().meta({ label: "Sleeping" }),
|
|
56591
56910
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
56592
|
-
lastUpdated: number(),
|
|
56911
|
+
lastUpdated: number().meta(readingMeta("none")),
|
|
56912
|
+
/**
|
|
56913
|
+
* Battery voltage in volts, for a cell the firmware reports as voltage
|
|
56914
|
+
* rather than a percentage (Ecowitt capacitor packs). Absent on cameras
|
|
56915
|
+
* that only report charge. A second reading on this cap, not a second
|
|
56916
|
+
* `numeric-sensor` on the same device.
|
|
56917
|
+
*/
|
|
56918
|
+
volts: number().nullable().optional().meta(readingMeta("voltage", { label: "Voltage" })),
|
|
56593
56919
|
/**
|
|
56594
56920
|
* Ms epoch of the last time the device PROVED it was reachable — a
|
|
56595
56921
|
* completed firmware round-trip, an observed wake, or an inbound push
|
|
@@ -56649,7 +56975,7 @@ object({
|
|
|
56649
56975
|
DeviceType.Sensor;
|
|
56650
56976
|
object({
|
|
56651
56977
|
/** Current level as 0..100 inclusive. Firmware-reported. */
|
|
56652
|
-
percentage: number().min(0).max(100),
|
|
56978
|
+
percentage: number().min(0).max(100).meta(readingMeta("percentage")),
|
|
56653
56979
|
/** Ms epoch of the last operator-driven change. Useful for UI freshness. */
|
|
56654
56980
|
lastChangedAt: number()
|
|
56655
56981
|
});
|
|
@@ -57034,21 +57360,21 @@ object({
|
|
|
57034
57360
|
/** Single setpoint in Celsius. Used by single-target modes
|
|
57035
57361
|
* (heat / cool / dry). Null when the device is in a range mode
|
|
57036
57362
|
* (`heat_cool`) or has no setpoint at all (`fan_only`/`off`). */
|
|
57037
|
-
target: number().nullable(),
|
|
57363
|
+
target: number().nullable().meta(readingMeta("temperature")),
|
|
57038
57364
|
/** Upper bound of the dual setpoint in Celsius. Populated only
|
|
57039
57365
|
* in `heat_cool` mode. */
|
|
57040
|
-
targetHigh: number().nullable(),
|
|
57366
|
+
targetHigh: number().nullable().meta(readingMeta("temperature")),
|
|
57041
57367
|
/** Lower bound of the dual setpoint in Celsius. Populated only
|
|
57042
57368
|
* in `heat_cool` mode. */
|
|
57043
|
-
targetLow: number().nullable(),
|
|
57369
|
+
targetLow: number().nullable().meta(readingMeta("temperature")),
|
|
57044
57370
|
/** Target relative humidity (0..100). Null when the device has no
|
|
57045
57371
|
* humidity control. */
|
|
57046
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
57372
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
57047
57373
|
/** Current measured temperature in Celsius. Read-only — pushed by
|
|
57048
57374
|
* the device's internal sensor. */
|
|
57049
|
-
currentTemp: number().nullable(),
|
|
57375
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
57050
57376
|
/** Current measured relative humidity (0..100). Read-only. */
|
|
57051
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
57377
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
57052
57378
|
/** Vertical louver swing on/off. Null when the device has no vertical
|
|
57053
57379
|
* swing surface (gate with `DeviceFeature.ClimateSwingVertical`). */
|
|
57054
57380
|
swingVertical: boolean().nullable(),
|
|
@@ -57056,11 +57382,11 @@ object({
|
|
|
57056
57382
|
* horizontal swing surface (gate with `DeviceFeature.ClimateSwingHorizontal`). */
|
|
57057
57383
|
swingHorizontal: boolean().nullable(),
|
|
57058
57384
|
/** Lowest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
57059
|
-
minTemp: number().nullable().optional(),
|
|
57385
|
+
minTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
57060
57386
|
/** Highest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
57061
|
-
maxTemp: number().nullable().optional(),
|
|
57387
|
+
maxTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
57062
57388
|
/** Setpoint granularity, Celsius (0.5, 1). Absent / null = not reported. */
|
|
57063
|
-
tempStep: number().positive().nullable().optional(),
|
|
57389
|
+
tempStep: number().positive().nullable().optional().meta(readingMeta("temperature")),
|
|
57064
57390
|
/** Ms epoch when the slice was last updated (push or command). */
|
|
57065
57391
|
lastFetchedAt: number()
|
|
57066
57392
|
});
|
|
@@ -57139,17 +57465,17 @@ DeviceType.Thermostat, DeviceType.Climate, method(object({
|
|
|
57139
57465
|
* modes to expose in the picker without a slice fetch.
|
|
57140
57466
|
*/
|
|
57141
57467
|
var RgbTripletSchema = object({
|
|
57142
|
-
r: number().int().min(0).max(255),
|
|
57143
|
-
g: number().int().min(0).max(255),
|
|
57144
|
-
b: number().int().min(0).max(255)
|
|
57468
|
+
r: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
57469
|
+
g: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
57470
|
+
b: number().int().min(0).max(255).meta(readingMeta("none"))
|
|
57145
57471
|
});
|
|
57146
57472
|
var HsvTripletSchema = object({
|
|
57147
57473
|
/** Hue in degrees, 0..360. */
|
|
57148
|
-
h: number().min(0).max(360),
|
|
57474
|
+
h: number().min(0).max(360).meta(readingMeta("none")),
|
|
57149
57475
|
/** Saturation as 0..100 inclusive. */
|
|
57150
|
-
s: number().min(0).max(100),
|
|
57476
|
+
s: number().min(0).max(100).meta(readingMeta("none")),
|
|
57151
57477
|
/** Value/brightness as 0..100 inclusive. */
|
|
57152
|
-
v: number().min(0).max(100)
|
|
57478
|
+
v: number().min(0).max(100).meta(readingMeta("none"))
|
|
57153
57479
|
});
|
|
57154
57480
|
var ColorInputSchema = discriminatedUnion("mode", [
|
|
57155
57481
|
object({
|
|
@@ -57178,7 +57504,7 @@ object({
|
|
|
57178
57504
|
/** Populated when `mode === 'hsv'`. */
|
|
57179
57505
|
hsv: HsvTripletSchema.optional(),
|
|
57180
57506
|
/** Populated when `mode === 'mired'`. */
|
|
57181
|
-
mireds: number().int().optional(),
|
|
57507
|
+
mireds: number().int().optional().meta(readingMeta("colour-temperature")),
|
|
57182
57508
|
/** Ms epoch of the last operator-driven change. */
|
|
57183
57509
|
lastChangedAt: number()
|
|
57184
57510
|
});
|
|
@@ -57302,18 +57628,12 @@ _enum([
|
|
|
57302
57628
|
"empty",
|
|
57303
57629
|
"full"
|
|
57304
57630
|
]);
|
|
57305
|
-
/**
|
|
57306
|
-
|
|
57307
|
-
|
|
57308
|
-
"days",
|
|
57309
|
-
"hours",
|
|
57310
|
-
"cycles"
|
|
57311
|
-
]);
|
|
57312
|
-
/** Remaining life as a COUNT, not a percentage (the PetKit desiccant reports
|
|
57313
|
-
* days). `value` null = unknown (D393). */
|
|
57631
|
+
/** Whether `remaining.value` is a duration in seconds or a dimensionless count. */
|
|
57632
|
+
var ConsumableRemainingKindSchema = _enum(["duration", "count"]);
|
|
57633
|
+
/** Remaining life. `value` null = unknown (D393). Duration is seconds. */
|
|
57314
57634
|
var ConsumableRemainingSchema = object({
|
|
57315
|
-
value: number().min(0).nullable(),
|
|
57316
|
-
|
|
57635
|
+
value: number().min(0).nullable().meta(readingMeta("device")),
|
|
57636
|
+
kind: ConsumableRemainingKindSchema
|
|
57317
57637
|
});
|
|
57318
57638
|
var ConsumablesStatusSchema = object({
|
|
57319
57639
|
items: array(object({
|
|
@@ -57322,7 +57642,7 @@ var ConsumablesStatusSchema = object({
|
|
|
57322
57642
|
/** Display name. */
|
|
57323
57643
|
label: string().min(1),
|
|
57324
57644
|
/** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
|
|
57325
|
-
level: number().min(0).max(100).nullable(),
|
|
57645
|
+
level: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
57326
57646
|
/** The provider's discrete verdict when known (binary mode). */
|
|
57327
57647
|
status: ConsumableStatusSchema.nullable(),
|
|
57328
57648
|
/** What the item is — decides whether low or full is bad. Absent = `wear`. */
|
|
@@ -57339,7 +57659,7 @@ var ConsumablesStatusSchema = object({
|
|
|
57339
57659
|
})),
|
|
57340
57660
|
lastChangedAt: number()
|
|
57341
57661
|
});
|
|
57342
|
-
Object.values(DeviceType), [...
|
|
57662
|
+
Object.values(DeviceType), [...ConsumableRemainingKindSchema.options], [...ConsumableStatusSchema.options], [...ConsumableKindSchema.options], [...ConsumableFormSchema.options];
|
|
57343
57663
|
Object.values(DeviceType), method(object({
|
|
57344
57664
|
deviceId: number().int().nonnegative(),
|
|
57345
57665
|
key: string().min(1)
|
|
@@ -57364,39 +57684,17 @@ object({
|
|
|
57364
57684
|
/** Current value. Numeric kind → number; select/text/datetime → string.
|
|
57365
57685
|
* Datetime values are ISO 8601 strings (full timestamp, date-only,
|
|
57366
57686
|
* or time-only — HA accepts all three forms). */
|
|
57367
|
-
value: union([number(), string()]),
|
|
57687
|
+
value: union([number().meta(readingMeta("device")), string()]),
|
|
57368
57688
|
/** Acceptable values when `kind === 'select'`. Empty for other kinds. */
|
|
57369
57689
|
options: array(string()),
|
|
57370
57690
|
/** Ms epoch when the slice was last updated. */
|
|
57371
57691
|
lastChangedAt: number(),
|
|
57372
|
-
/**
|
|
57373
|
-
|
|
57374
|
-
|
|
57375
|
-
|
|
57376
|
-
/**
|
|
57377
|
-
|
|
57378
|
-
min: number().optional(),
|
|
57379
|
-
/** Maximum allowed value. Populated live from HA `attributes.max`.
|
|
57380
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
57381
|
-
max: number().optional(),
|
|
57382
|
-
/** Step increment. Populated live from HA `attributes.step`.
|
|
57383
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
57384
|
-
step: number().optional(),
|
|
57385
|
-
/** Suggested decimal places for numeric display. Populated live from HA
|
|
57386
|
-
* `attributes.suggested_display_precision`, or derived from `step` when the
|
|
57387
|
-
* HA attribute is absent. Meaningful for `kind === 'numeric'`; absent for
|
|
57388
|
-
* other kinds. Falls back to auto-formatting when absent. */
|
|
57389
|
-
precision: number().int().min(0).max(10).optional(),
|
|
57390
|
-
/** Date-picker granularity for `kind === 'datetime'`. 'date' → date-only,
|
|
57391
|
-
* 'time' → time-only, 'datetime' → full timestamp. Absent for other kinds
|
|
57392
|
-
* (UI defaults to 'datetime'). Derived live from the device's HA domain
|
|
57393
|
-
* (date.* / time.* / datetime.*) or, for input_datetime, from the entity's
|
|
57394
|
-
* `has_date`/`has_time` attributes on each push. */
|
|
57395
|
-
format: _enum([
|
|
57396
|
-
"date",
|
|
57397
|
-
"time",
|
|
57398
|
-
"datetime"
|
|
57399
|
-
]).optional()
|
|
57692
|
+
/** Minimum allowed value, in the device quantity's base unit. */
|
|
57693
|
+
min: number().optional().meta(readingMeta("device")),
|
|
57694
|
+
/** Maximum allowed value, in the device quantity's base unit. */
|
|
57695
|
+
max: number().optional().meta(readingMeta("device")),
|
|
57696
|
+
/** Step increment, in the device quantity's base unit. */
|
|
57697
|
+
step: number().optional().meta(readingMeta("device"))
|
|
57400
57698
|
});
|
|
57401
57699
|
var ControlSetValueInputSchema = discriminatedUnion("kind", [
|
|
57402
57700
|
object({
|
|
@@ -57434,9 +57732,9 @@ object({
|
|
|
57434
57732
|
]),
|
|
57435
57733
|
/** 0 = fully closed, 100 = fully open. Null when the device has
|
|
57436
57734
|
* no intermediate position surface. */
|
|
57437
|
-
position: number().min(0).max(100).nullable(),
|
|
57735
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
57438
57736
|
/** 0 = closed slats, 100 = open slats. Null when no tilt support. */
|
|
57439
|
-
tiltPosition: number().min(0).max(100).nullable(),
|
|
57737
|
+
tiltPosition: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
57440
57738
|
/** Ms epoch when the slice was last updated. */
|
|
57441
57739
|
lastChangedAt: number()
|
|
57442
57740
|
});
|
|
@@ -57494,9 +57792,9 @@ var NormalizedRangeSchema$1 = object({
|
|
|
57494
57792
|
object({
|
|
57495
57793
|
mode: DayNightModeSchema,
|
|
57496
57794
|
/** IR-cut trigger sensitivity, NORMALIZED 0–100 (higher = switches to night sooner). */
|
|
57497
|
-
sensitivity: number().optional(),
|
|
57795
|
+
sensitivity: number().optional().meta(readingMeta("none")),
|
|
57498
57796
|
/** Delay before the IR-cut filter flips, in seconds. */
|
|
57499
|
-
switchDelaySec: number().optional(),
|
|
57797
|
+
switchDelaySec: number().optional().meta(readingMeta("duration")),
|
|
57500
57798
|
lastFetchedAt: number()
|
|
57501
57799
|
});
|
|
57502
57800
|
/**
|
|
@@ -57651,11 +57949,11 @@ object({
|
|
|
57651
57949
|
/** Feature keys of the programs the appliance currently offers — drives the UI selector. */
|
|
57652
57950
|
availablePrograms: array(string()),
|
|
57653
57951
|
/** Seconds remaining on the active cycle, or null when not running / not known. */
|
|
57654
|
-
remainingSeconds: number().int().nonnegative().nullable(),
|
|
57952
|
+
remainingSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
57655
57953
|
/** Seconds the delayed start is set to (time until the cycle starts), or null. */
|
|
57656
|
-
delayedStartSeconds: number().int().nonnegative().nullable(),
|
|
57954
|
+
delayedStartSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
57657
57955
|
/** Cycle completion 0..100, or null when not applicable. */
|
|
57658
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
57956
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
57659
57957
|
/** True when the door is reported open; null when the door state is not known. */
|
|
57660
57958
|
doorOpen: boolean().nullable(),
|
|
57661
57959
|
/** True when the door is latched (locked) during a cycle; null when not reported. */
|
|
@@ -57679,7 +57977,7 @@ object({
|
|
|
57679
57977
|
/** True while the machine-care (descaling / cleaning-program) reminder is raised; false when clear; null when not reported. */
|
|
57680
57978
|
machineCareDue: boolean().nullable(),
|
|
57681
57979
|
/** Program runs left before the machine-care reminder is due; null when the appliance does not say. */
|
|
57682
|
-
machineCareRemainingRuns: number().int().nonnegative().nullable(),
|
|
57980
|
+
machineCareRemainingRuns: number().int().nonnegative().nullable().meta(readingMeta("count")),
|
|
57683
57981
|
/** Option states: null when the appliance does not expose the option or has not said. */
|
|
57684
57982
|
halfLoad: boolean().nullable(),
|
|
57685
57983
|
hygienePlus: boolean().nullable(),
|
|
@@ -57694,7 +57992,7 @@ object({
|
|
|
57694
57992
|
/** Feature keys of the events currently raised (salt low, rinse aid low, program finished, …). */
|
|
57695
57993
|
activeEvents: array(string()),
|
|
57696
57994
|
/** Numeric error code when the appliance reports one; null otherwise. */
|
|
57697
|
-
errorCode: number().nullable(),
|
|
57995
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
57698
57996
|
/** Name of the raised alert-level event while the appliance is in error; null otherwise. */
|
|
57699
57997
|
errorLabel: string().nullable(),
|
|
57700
57998
|
/** Ms epoch of the last value received from the appliance; 0 = never. */
|
|
@@ -57840,24 +58138,14 @@ object({
|
|
|
57840
58138
|
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
57841
58139
|
lastPressedAt: number().nullable(),
|
|
57842
58140
|
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
57843
|
-
pressCountSinceStart: number()
|
|
58141
|
+
pressCountSinceStart: number().meta(readingMeta("count"))
|
|
57844
58142
|
});
|
|
57845
58143
|
object({
|
|
57846
58144
|
deviceId: number(),
|
|
57847
58145
|
timestamp: number()
|
|
57848
58146
|
});
|
|
57849
58147
|
DeviceType.Button, DeviceType.Camera;
|
|
57850
|
-
|
|
57851
|
-
* Enum-state sensor — a string value picked from a finite option set.
|
|
57852
|
-
* Drives HA `sensor` entries with `state_class: enum` (HVAC action
|
|
57853
|
-
* states, weather conditions, contact-source channels, mode strings).
|
|
57854
|
-
* The option set is stable across observations; it is persisted in the
|
|
57855
|
-
* device config blob (via the control slice at adoption) and is NOT
|
|
57856
|
-
* stored in `sourceInfo`.
|
|
57857
|
-
*/
|
|
57858
|
-
/** Locale-render shape for an ISO `value` carried by a `DateTimeSensor`-role
|
|
57859
|
-
* enum sensor: `date` (date-only), `time` (time-only), `datetime` (both). */
|
|
57860
|
-
var EnumSensorDateTimeFormatSchema = _enum([
|
|
58148
|
+
_enum([
|
|
57861
58149
|
"date",
|
|
57862
58150
|
"time",
|
|
57863
58151
|
"datetime"
|
|
@@ -57865,12 +58153,11 @@ var EnumSensorDateTimeFormatSchema = _enum([
|
|
|
57865
58153
|
object({
|
|
57866
58154
|
value: string(),
|
|
57867
58155
|
/**
|
|
57868
|
-
* Set
|
|
57869
|
-
* as
|
|
57870
|
-
*
|
|
57871
|
-
* a time-only sensor → `'time'`.
|
|
58156
|
+
* Set when `value` is a timestamp rather than an enum state, so history
|
|
58157
|
+
* does not learn ISO strings as states. The display shape (date / time /
|
|
58158
|
+
* datetime) lives on `SourceInfo.dateTimeShape`, written once at adopt.
|
|
57872
58159
|
*/
|
|
57873
|
-
|
|
58160
|
+
timestamp: boolean().optional(),
|
|
57874
58161
|
/** Ms epoch when the slice was last updated. */
|
|
57875
58162
|
lastFetchedAt: number()
|
|
57876
58163
|
});
|
|
@@ -57889,13 +58176,13 @@ var EventFireSchema = object({
|
|
|
57889
58176
|
deviceId: number(),
|
|
57890
58177
|
eventType: string(),
|
|
57891
58178
|
data: record(string(), unknown()).nullable(),
|
|
57892
|
-
timestamp: number(),
|
|
57893
|
-
seq: number()
|
|
58179
|
+
timestamp: number().meta(readingMeta("none")),
|
|
58180
|
+
seq: number().meta(readingMeta("count"))
|
|
57894
58181
|
});
|
|
57895
58182
|
object({
|
|
57896
58183
|
eventTypes: array(string()),
|
|
57897
58184
|
lastEvent: EventFireSchema.nullable(),
|
|
57898
|
-
eventCountSinceStart: number()
|
|
58185
|
+
eventCountSinceStart: number().meta(readingMeta("count"))
|
|
57899
58186
|
});
|
|
57900
58187
|
DeviceType.EventEmitter;
|
|
57901
58188
|
var IdentitySchema = object({
|
|
@@ -58284,10 +58571,10 @@ var FanDirectionSchema = _enum(["forward", "reverse"]);
|
|
|
58284
58571
|
object({
|
|
58285
58572
|
/** Active speed as 0..100 inclusive. Null when the device has no
|
|
58286
58573
|
* speed surface (single-speed fan). */
|
|
58287
|
-
percentage: number().min(0).max(100).nullable(),
|
|
58574
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58288
58575
|
/** Speed granularity the device accepts (HA `percentage_step`, e.g. 25 for
|
|
58289
58576
|
* a 4-speed fan). Absent when unknown — the UI then falls back to step 1. */
|
|
58290
|
-
percentageStep: number().positive().optional(),
|
|
58577
|
+
percentageStep: number().positive().optional().meta(readingMeta("percentage")),
|
|
58291
58578
|
/** Active preset mode (`auto` / `quiet` / `turbo` / vendor-specific)
|
|
58292
58579
|
* — empty string when no preset is active or supported. */
|
|
58293
58580
|
preset: string(),
|
|
@@ -58369,7 +58656,7 @@ var FeatureProbeStatusSchema = object({
|
|
|
58369
58656
|
/** Camera/firmware model string. `null` when the firmware doesn't expose it. */
|
|
58370
58657
|
model: string().nullable(),
|
|
58371
58658
|
/** Channel count for NVR/Hub devices; `1` for standalone cameras; `null` pre-probe. */
|
|
58372
|
-
channelCount: number().nullable(),
|
|
58659
|
+
channelCount: number().nullable().meta(readingMeta("count")),
|
|
58373
58660
|
/**
|
|
58374
58661
|
* Ms epoch of the last SUCCESSFUL probe. `0` before the first probe
|
|
58375
58662
|
* completes — drivers' `getAccessoryChildren()` should treat zero as
|
|
@@ -58401,9 +58688,27 @@ object({
|
|
|
58401
58688
|
lastChangedAt: number()
|
|
58402
58689
|
});
|
|
58403
58690
|
DeviceType.Sensor;
|
|
58691
|
+
object({
|
|
58692
|
+
/** Members whose current value entered the aggregate. */
|
|
58693
|
+
included: number().int().nonnegative().meta(readingMeta("count", {
|
|
58694
|
+
precision: 0,
|
|
58695
|
+
label: "Reporting"
|
|
58696
|
+
})),
|
|
58697
|
+
/** Members left out: offline, unknown, or not a finite reading (D393). */
|
|
58698
|
+
excluded: number().int().nonnegative().meta(readingMeta("count", {
|
|
58699
|
+
precision: 0,
|
|
58700
|
+
label: "Excluded"
|
|
58701
|
+
})),
|
|
58702
|
+
/** `included` + `excluded`. */
|
|
58703
|
+
total: number().int().nonnegative().meta(readingMeta("count", {
|
|
58704
|
+
precision: 0,
|
|
58705
|
+
label: "Members"
|
|
58706
|
+
}))
|
|
58707
|
+
});
|
|
58708
|
+
DeviceType.Sensor;
|
|
58404
58709
|
object({
|
|
58405
58710
|
/** Radiator valve opening 0 (closed) .. 100 (open). Null = not yet known. */
|
|
58406
|
-
position: number().min(0).max(100).nullable(),
|
|
58711
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58407
58712
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
58408
58713
|
lastFetchedAt: number()
|
|
58409
58714
|
});
|
|
@@ -58412,9 +58717,9 @@ object({
|
|
|
58412
58717
|
/** Whether the humidifier is currently on. */
|
|
58413
58718
|
on: boolean(),
|
|
58414
58719
|
/** Current measured relative humidity (0..100). Null when not reported. */
|
|
58415
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
58720
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
58416
58721
|
/** Target relative humidity (0..100). Null when no setpoint surface. */
|
|
58417
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
58722
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
58418
58723
|
/** Active mode (`auto` / `normal` / `baby` / vendor). Null when the
|
|
58419
58724
|
* device has no mode surface. */
|
|
58420
58725
|
mode: string().nullable(),
|
|
@@ -58424,9 +58729,9 @@ object({
|
|
|
58424
58729
|
* `idle` / `off`). Null when the device doesn't report it. */
|
|
58425
58730
|
action: string().nullable(),
|
|
58426
58731
|
/** HA `min_humidity` attribute. Null → UI uses 0. */
|
|
58427
|
-
minHumidity: number().nullable(),
|
|
58732
|
+
minHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
58428
58733
|
/** HA `max_humidity` attribute. Null → UI uses 100. */
|
|
58429
|
-
maxHumidity: number().nullable(),
|
|
58734
|
+
maxHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
58430
58735
|
/** Ms epoch when the slice was last updated. */
|
|
58431
58736
|
lastChangedAt: number()
|
|
58432
58737
|
});
|
|
@@ -58450,22 +58755,13 @@ DeviceType.Humidifier, method(object({
|
|
|
58450
58755
|
auth: "protected"
|
|
58451
58756
|
});
|
|
58452
58757
|
object({
|
|
58453
|
-
/** Current relative humidity, 0..100. */
|
|
58454
|
-
percent: number().min(0).max(100).meta({
|
|
58455
|
-
|
|
58758
|
+
/** Current relative humidity, 0..100. `null` when the sample was refused (D393). */
|
|
58759
|
+
percent: number().min(0).max(100).nullable().meta(readingMeta("humidity", {
|
|
58760
|
+
precision: 0,
|
|
58456
58761
|
label: "Humidity"
|
|
58457
|
-
}),
|
|
58762
|
+
})),
|
|
58458
58763
|
/** Ms epoch when the slice was last updated. */
|
|
58459
|
-
lastFetchedAt: number()
|
|
58460
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
58461
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
58462
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
58463
|
-
unit: string().optional(),
|
|
58464
|
-
/** Suggested decimal places for numeric display.
|
|
58465
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
58466
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
58467
|
-
* auto-formatting when absent. */
|
|
58468
|
-
precision: number().int().min(0).max(10).optional()
|
|
58764
|
+
lastFetchedAt: number()
|
|
58469
58765
|
});
|
|
58470
58766
|
DeviceType.Sensor, DeviceType.Thermostat;
|
|
58471
58767
|
object({
|
|
@@ -58473,7 +58769,7 @@ object({
|
|
|
58473
58769
|
* entity exposes no `entity_picture` (yet). */
|
|
58474
58770
|
url: string().nullable(),
|
|
58475
58771
|
/** Ms epoch of the upstream last-updated timestamp. Null at cold-start. */
|
|
58476
|
-
lastUpdated: number().nullable()
|
|
58772
|
+
lastUpdated: number().nullable().meta(readingMeta("none"))
|
|
58477
58773
|
});
|
|
58478
58774
|
DeviceType.Image;
|
|
58479
58775
|
/**
|
|
@@ -58529,19 +58825,19 @@ var NormalizedRangeSchema = object({
|
|
|
58529
58825
|
});
|
|
58530
58826
|
object({
|
|
58531
58827
|
/** Normalized 0–100. */
|
|
58532
|
-
brightness: number().optional(),
|
|
58828
|
+
brightness: number().optional().meta(readingMeta("none")),
|
|
58533
58829
|
/** Normalized 0–100. */
|
|
58534
|
-
contrast: number().optional(),
|
|
58830
|
+
contrast: number().optional().meta(readingMeta("none")),
|
|
58535
58831
|
/** Normalized 0–100. */
|
|
58536
|
-
saturation: number().optional(),
|
|
58832
|
+
saturation: number().optional().meta(readingMeta("none")),
|
|
58537
58833
|
/** Normalized 0–100. */
|
|
58538
|
-
sharpness: number().optional(),
|
|
58834
|
+
sharpness: number().optional().meta(readingMeta("none")),
|
|
58539
58835
|
mirror: boolean().optional(),
|
|
58540
58836
|
flip: boolean().optional(),
|
|
58541
58837
|
rotate: ImageRotateSchema.optional(),
|
|
58542
58838
|
whiteBalance: WhiteBalanceModeSchema.optional(),
|
|
58543
58839
|
/** Manual white-balance warmth, NORMALIZED 0–100. Meaningful only when `whiteBalance === 'manual'`. */
|
|
58544
|
-
warmth: number().optional(),
|
|
58840
|
+
warmth: number().optional().meta(readingMeta("none")),
|
|
58545
58841
|
exposureMode: ExposureModeSchema.optional(),
|
|
58546
58842
|
backlightMode: BacklightModeSchema.optional(),
|
|
58547
58843
|
lastFetchedAt: number()
|
|
@@ -58786,10 +59082,10 @@ var IntercomAbilitySchema = object({
|
|
|
58786
59082
|
/** Codecs accepted by firmware, in preference order. Driver-authored strings. */
|
|
58787
59083
|
codecs: array(string()),
|
|
58788
59084
|
/** Sample rate (Hz) the firmware expects. Reolink typical: 16000. */
|
|
58789
|
-
sampleRate: number(),
|
|
59085
|
+
sampleRate: number().meta(readingMeta("none")),
|
|
58790
59086
|
duplex: _enum(["half", "full"]),
|
|
58791
59087
|
/** Max in-flight audio backlog before drop (ms). Server uses this to bound latency. */
|
|
58792
|
-
maxBacklogMs: number()
|
|
59088
|
+
maxBacklogMs: number().meta(readingMeta("duration-ms"))
|
|
58793
59089
|
});
|
|
58794
59090
|
var IntercomStatusSchema = object({
|
|
58795
59091
|
/** True while a talk session is open. */
|
|
@@ -58900,13 +59196,13 @@ object({
|
|
|
58900
59196
|
activity: LawnMowerActivitySchema,
|
|
58901
59197
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
58902
59198
|
* reading. */
|
|
58903
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
59199
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58904
59200
|
/** 0..100 mowing-completion percentage of the current task, or null when no
|
|
58905
59201
|
* task is active / progress is unavailable. */
|
|
58906
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
59202
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58907
59203
|
/** Current device/event code (dynamic — mostly status, sometimes an error),
|
|
58908
59204
|
* or null when unknown. */
|
|
58909
|
-
currentCode: number().nullable(),
|
|
59205
|
+
currentCode: number().nullable().meta(readingMeta("none")),
|
|
58910
59206
|
/** Human label for {@link currentCode}, or null when undecodable. */
|
|
58911
59207
|
currentCodeLabel: string().nullable(),
|
|
58912
59208
|
/** Severity of {@link currentCode}. `error` (and often `warning`) warrants UI
|
|
@@ -59368,7 +59664,7 @@ object({
|
|
|
59368
59664
|
state: MediaPlayerStateSchema,
|
|
59369
59665
|
/** Volume as 0..100 inclusive. Null when the device has no volume
|
|
59370
59666
|
* surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
|
|
59371
|
-
volumeLevel: number().min(0).max(100).nullable(),
|
|
59667
|
+
volumeLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59372
59668
|
/** Mute toggle distinct from volume=0. Null when no mute surface.
|
|
59373
59669
|
* Pair with `DeviceFeature.MediaPlayerMute`. */
|
|
59374
59670
|
isMuted: boolean().nullable(),
|
|
@@ -59381,10 +59677,10 @@ object({
|
|
|
59381
59677
|
currentMedia: MediaInfoSchema.nullable(),
|
|
59382
59678
|
/** Current playback position in ms. Null when not seekable or
|
|
59383
59679
|
* nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
|
|
59384
|
-
positionMs: number().int().nonnegative().nullable(),
|
|
59680
|
+
positionMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
59385
59681
|
/** Total duration of the current media in ms. Null when unknown
|
|
59386
59682
|
* (live stream) or nothing is playing. */
|
|
59387
|
-
durationMs: number().int().nonnegative().nullable(),
|
|
59683
|
+
durationMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
59388
59684
|
/** Shuffle toggle. Null when no shuffle surface.
|
|
59389
59685
|
* Pair with `DeviceFeature.MediaPlayerShuffle`. */
|
|
59390
59686
|
shuffle: boolean().nullable(),
|
|
@@ -59684,7 +59980,7 @@ object({
|
|
|
59684
59980
|
* it, every provider seeded it at boot, and every session left it
|
|
59685
59981
|
* `detected: true` after its detach.
|
|
59686
59982
|
*/
|
|
59687
|
-
autoClearAfterMs: number().nullable()
|
|
59983
|
+
autoClearAfterMs: number().nullable().meta(readingMeta("duration-ms"))
|
|
59688
59984
|
});
|
|
59689
59985
|
/**
|
|
59690
59986
|
* Payload of `motion.onMotionChanged` event + the corresponding bus
|
|
@@ -59734,7 +60030,7 @@ var MotionZoneRegionSchema = object({
|
|
|
59734
60030
|
});
|
|
59735
60031
|
object({
|
|
59736
60032
|
enabled: boolean(),
|
|
59737
|
-
sensitivity: number(),
|
|
60033
|
+
sensitivity: number().meta(readingMeta("none")),
|
|
59738
60034
|
/** Grid region(s). Today exactly one `grid` shape. */
|
|
59739
60035
|
regions: array(MotionZoneRegionSchema),
|
|
59740
60036
|
lastFetchedAt: number()
|
|
@@ -60038,7 +60334,7 @@ var NavigationStatusSchema = object({
|
|
|
60038
60334
|
following: boolean(),
|
|
60039
60335
|
flash: boolean(),
|
|
60040
60336
|
lightMode: NavigationLightModeSchema,
|
|
60041
|
-
lightLevel: number().min(40).max(100),
|
|
60337
|
+
lightLevel: number().min(40).max(100).meta(readingMeta("none")),
|
|
60042
60338
|
/** Ms epoch when the slice was last updated. */
|
|
60043
60339
|
lastChangedAt: number()
|
|
60044
60340
|
});
|
|
@@ -60084,13 +60380,13 @@ var NetworkLinkStatusSchema = object({
|
|
|
60084
60380
|
* one whose reading has not landed must not be drawn at 0 %. Consumers
|
|
60085
60381
|
* SKIP a null rather than coerce it.
|
|
60086
60382
|
*/
|
|
60087
|
-
signalPercent: number().min(0).max(100).nullable(),
|
|
60383
|
+
signalPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
60088
60384
|
/** Raw received signal strength in dBm, when the firmware reports one. */
|
|
60089
|
-
rssiDbm: number().optional(),
|
|
60385
|
+
rssiDbm: number().optional().meta(readingMeta("signal-level")),
|
|
60090
60386
|
/** Network name of a wireless link, when the firmware reports it. */
|
|
60091
60387
|
ssid: string().optional(),
|
|
60092
60388
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
60093
|
-
lastUpdated: number()
|
|
60389
|
+
lastUpdated: number().meta(readingMeta("none"))
|
|
60094
60390
|
});
|
|
60095
60391
|
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.Light, DeviceType.Lock, DeviceType.Siren, object({
|
|
60096
60392
|
deviceId: number(),
|
|
@@ -60409,7 +60705,7 @@ object({
|
|
|
60409
60705
|
lastError: string().nullable(),
|
|
60410
60706
|
/** Number of deliveries currently buffered server-side (rate-limited
|
|
60411
60707
|
* notifiers may queue). 0 when the provider sends synchronously. */
|
|
60412
|
-
queueDepth: number().int().nonnegative(),
|
|
60708
|
+
queueDepth: number().int().nonnegative().meta(readingMeta("count")),
|
|
60413
60709
|
/** Per-feature capability matrix — authoritative source for the
|
|
60414
60710
|
* compose-form field gating. */
|
|
60415
60711
|
supports: NotifierSupportsSchema
|
|
@@ -60459,15 +60755,8 @@ DeviceType.Notifier, method(NotifierSendInputSchema, NotifierSendResultSchema, {
|
|
|
60459
60755
|
acceptedAt: number()
|
|
60460
60756
|
});
|
|
60461
60757
|
object({
|
|
60462
|
-
|
|
60463
|
-
|
|
60464
|
-
* Populated live from the upstream source on each state push.
|
|
60465
|
-
* Absent for unitless sensors. */
|
|
60466
|
-
unit: string().optional(),
|
|
60467
|
-
/** Suggested decimal places for numeric display.
|
|
60468
|
-
* Populated live from the upstream source when provided.
|
|
60469
|
-
* Falls back to auto-formatting when absent. */
|
|
60470
|
-
precision: number().int().min(0).max(10).optional(),
|
|
60758
|
+
/** Reading in the device quantity's base unit. `null` when refused (D393). */
|
|
60759
|
+
value: number().nullable().meta(readingMeta("device")),
|
|
60471
60760
|
/** Ms epoch when the slice was last updated. */
|
|
60472
60761
|
lastFetchedAt: number()
|
|
60473
60762
|
});
|
|
@@ -60757,23 +61046,26 @@ object({
|
|
|
60757
61046
|
/** Food currently in the bowl (grams). Null when the device has not
|
|
60758
61047
|
* reported a reading yet. On dual-hopper models this is the combined
|
|
60759
61048
|
* bowl reading; per-hopper levels live in `food1`/`food2`. */
|
|
60760
|
-
foodLevel: number().nullable(),
|
|
61049
|
+
foodLevel: number().nullable().meta(readingMeta("none")),
|
|
60761
61050
|
/** Hopper-1 food level (grams) on dual-hopper feeders; null on
|
|
60762
61051
|
* single-hopper models. */
|
|
60763
|
-
food1: number().nullable(),
|
|
61052
|
+
food1: number().nullable().meta(readingMeta("none")),
|
|
60764
61053
|
/** Hopper-2 food level (grams) on dual-hopper feeders; null on
|
|
60765
61054
|
* single-hopper models. */
|
|
60766
|
-
food2: number().nullable(),
|
|
61055
|
+
food2: number().nullable().meta(readingMeta("none")),
|
|
60767
61056
|
/** Derived low-food flag — mirrors the HA `food_level` binary_sensor
|
|
60768
61057
|
* (`device_class: problem`, on = low). True when the bowl is empty /
|
|
60769
61058
|
* below the feeder's low threshold. */
|
|
60770
61059
|
lowFood: boolean(),
|
|
60771
61060
|
/** Battery charge 0..100 (%). Null on mains-powered models or when the
|
|
60772
61061
|
* device has no battery reading. */
|
|
60773
|
-
batteryPower: number().min(0).max(100).nullable(),
|
|
60774
|
-
/**
|
|
60775
|
-
*
|
|
60776
|
-
|
|
61062
|
+
batteryPower: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61063
|
+
/**
|
|
61064
|
+
* Desiccant life remaining, stored in seconds (duration base, D944).
|
|
61065
|
+
* Providers convert from the days the feeder reports. Null when the
|
|
61066
|
+
* model has no desiccant sensor.
|
|
61067
|
+
*/
|
|
61068
|
+
desiccantLeftDays: number().nullable().meta(readingMeta("duration")),
|
|
60777
61069
|
/** True while a feed is in progress. */
|
|
60778
61070
|
feeding: boolean(),
|
|
60779
61071
|
/** Decoded connectivity / power status (HA petkit device-status enum).
|
|
@@ -60784,7 +61076,7 @@ object({
|
|
|
60784
61076
|
* with `errorCode` for consumers that want the raw integer. */
|
|
60785
61077
|
error: string().nullable(),
|
|
60786
61078
|
/** Raw device error code (0 / null = no error). */
|
|
60787
|
-
errorCode: number().nullable(),
|
|
61079
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
60788
61080
|
/** True for D4S/D4SH dual-hopper hardware — gates the per-hopper UI. */
|
|
60789
61081
|
isDualHopper: boolean(),
|
|
60790
61082
|
/** Child-lock (manual-lock) setting — buttons on the unit are disabled. */
|
|
@@ -60794,7 +61086,7 @@ object({
|
|
|
60794
61086
|
/** Play a chime when dispensing. */
|
|
60795
61087
|
feedSound: boolean(),
|
|
60796
61088
|
/** Speaker / prompt volume level (device-scaled integer). */
|
|
60797
|
-
volume: number(),
|
|
61089
|
+
volume: number().meta(readingMeta("none")),
|
|
60798
61090
|
/** Ms epoch when the slice was last refreshed from the cloud. */
|
|
60799
61091
|
lastFetchedAt: number()
|
|
60800
61092
|
});
|
|
@@ -61231,36 +61523,19 @@ method(_void(), PlatformCapabilitiesSchema), method(_void(), HardwareInfoSchema)
|
|
|
61231
61523
|
});
|
|
61232
61524
|
object({
|
|
61233
61525
|
/** Instantaneous power draw in watts. */
|
|
61234
|
-
watts: number().optional().meta({
|
|
61235
|
-
unit: "W",
|
|
61236
|
-
label: "Power"
|
|
61237
|
-
}),
|
|
61526
|
+
watts: number().optional().meta(readingMeta("power", { label: "Power" })),
|
|
61238
61527
|
/** Cumulative energy in kilowatt-hours since the meter was reset. */
|
|
61239
|
-
kwhTotal: number().optional().meta({
|
|
61240
|
-
unit: "kWh",
|
|
61241
|
-
label: "Energy"
|
|
61242
|
-
}),
|
|
61528
|
+
kwhTotal: number().optional().meta(readingMeta("energy", { label: "Energy" })),
|
|
61243
61529
|
/** Voltage in volts. */
|
|
61244
|
-
volts: number().optional(),
|
|
61530
|
+
volts: number().optional().meta(readingMeta("voltage")),
|
|
61245
61531
|
/** Current in amperes. */
|
|
61246
|
-
amps: number().optional(),
|
|
61247
|
-
/** Apparent power in volt-amperes
|
|
61248
|
-
va: number().optional(),
|
|
61532
|
+
amps: number().optional().meta(readingMeta("current")),
|
|
61533
|
+
/** Apparent power in volt-amperes. */
|
|
61534
|
+
va: number().optional().meta(readingMeta("apparent-power")),
|
|
61249
61535
|
/** Power factor (0..1) if reported. */
|
|
61250
|
-
powerFactor: number().min(0).max(1).optional(),
|
|
61536
|
+
powerFactor: number().min(0).max(1).optional().meta(readingMeta("ratio")),
|
|
61251
61537
|
/** Ms epoch when the slice was last updated. */
|
|
61252
|
-
lastFetchedAt: number()
|
|
61253
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
61254
|
-
* `attributes.unit_of_measurement` → 'V' / 'A' / 'W' / 'kW' / 'kWh').
|
|
61255
|
-
* Each upstream `sensor.*` entity surfaces ONE device_class, so one
|
|
61256
|
-
* unit per slice is unambiguous. The UI prefers this over the role's
|
|
61257
|
-
* canonical unit so a 'kW' / 'Wh' feed renders verbatim. */
|
|
61258
|
-
unit: string().optional(),
|
|
61259
|
-
/** Suggested decimal places for numeric display.
|
|
61260
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
61261
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
61262
|
-
* auto-formatting when absent. */
|
|
61263
|
-
precision: number().int().min(0).max(10).optional()
|
|
61538
|
+
lastFetchedAt: number()
|
|
61264
61539
|
});
|
|
61265
61540
|
DeviceType.Sensor;
|
|
61266
61541
|
/**
|
|
@@ -61281,11 +61556,11 @@ DeviceType.Sensor;
|
|
|
61281
61556
|
*/
|
|
61282
61557
|
var GpsLocationSchema = object({
|
|
61283
61558
|
/** Latitude in decimal degrees, -90..90. */
|
|
61284
|
-
latitude: number().min(-90).max(90),
|
|
61559
|
+
latitude: number().min(-90).max(90).meta(readingMeta("angle")),
|
|
61285
61560
|
/** Longitude in decimal degrees, -180..180. */
|
|
61286
|
-
longitude: number().min(-180).max(180),
|
|
61561
|
+
longitude: number().min(-180).max(180).meta(readingMeta("angle")),
|
|
61287
61562
|
/** Reported accuracy in meters (lower = better). */
|
|
61288
|
-
accuracyMeters: number().nonnegative()
|
|
61563
|
+
accuracyMeters: number().nonnegative().meta(readingMeta("length"))
|
|
61289
61564
|
});
|
|
61290
61565
|
object({
|
|
61291
61566
|
/** `home` / `not_home` / any user-defined zone name. */
|
|
@@ -61297,25 +61572,16 @@ object({
|
|
|
61297
61572
|
gps: GpsLocationSchema.nullable(),
|
|
61298
61573
|
/** Optional battery level of the tracking device (0..100). Null
|
|
61299
61574
|
* when not reported. */
|
|
61300
|
-
batteryPercent: number().min(0).max(100).nullable(),
|
|
61575
|
+
batteryPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61301
61576
|
/** Ms epoch when the slice was last updated. */
|
|
61302
61577
|
lastChangedAt: number()
|
|
61303
61578
|
});
|
|
61304
61579
|
DeviceType.Presence;
|
|
61305
61580
|
object({
|
|
61306
|
-
/** Current pressure in hPa. */
|
|
61307
|
-
hpa: number(),
|
|
61581
|
+
/** Current pressure in hPa. `null` when the sample was refused (D393). */
|
|
61582
|
+
hpa: number().nullable().meta(readingMeta("pressure", { precision: 0 })),
|
|
61308
61583
|
/** Ms epoch when the slice was last updated. */
|
|
61309
|
-
lastFetchedAt: number()
|
|
61310
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
61311
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
61312
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
61313
|
-
unit: string().optional(),
|
|
61314
|
-
/** Suggested decimal places for numeric display.
|
|
61315
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
61316
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
61317
|
-
* auto-formatting when absent. */
|
|
61318
|
-
precision: number().int().min(0).max(10).optional()
|
|
61584
|
+
lastFetchedAt: number()
|
|
61319
61585
|
});
|
|
61320
61586
|
DeviceType.Sensor;
|
|
61321
61587
|
/**
|
|
@@ -61648,8 +61914,8 @@ DeviceType.Camera, method(PtzMoveCommandSchema.extend({ deviceId: number() }), _
|
|
|
61648
61914
|
}), _void(), { kind: "mutation" });
|
|
61649
61915
|
var PtzAutotrackSettingsSchema = object({
|
|
61650
61916
|
targetType: string().describe("Vendor target string (people/vehicle/pet); empty = camera default"),
|
|
61651
|
-
stopDelaySeconds: number().int().min(0).max(300),
|
|
61652
|
-
disappearDelaySeconds: number().int().min(0).max(300)
|
|
61917
|
+
stopDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration")),
|
|
61918
|
+
disappearDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration"))
|
|
61653
61919
|
});
|
|
61654
61920
|
/**
|
|
61655
61921
|
* One option the camera advertises as a valid `targetType`. Drivers
|
|
@@ -61706,7 +61972,7 @@ object({
|
|
|
61706
61972
|
/** null = unknown — never coerced to false (D393). */
|
|
61707
61973
|
running: boolean().nullable(),
|
|
61708
61974
|
/** Epoch ms the current boolean began; null while `running` is null. */
|
|
61709
|
-
since: number().nullable(),
|
|
61975
|
+
since: number().nullable().meta(readingMeta("none")),
|
|
61710
61976
|
source: RunningStateSourceSchema.meta({ label: "Source" }),
|
|
61711
61977
|
phase: string().nullable(),
|
|
61712
61978
|
/** null until a reading has been published (D393). */
|
|
@@ -62904,9 +63170,9 @@ var RecordTriggerSchema = _enum([
|
|
|
62904
63170
|
*/
|
|
62905
63171
|
var RecordWindowSchema = object({
|
|
62906
63172
|
trigger: RecordTriggerSchema,
|
|
62907
|
-
day: number().int().min(0).max(6),
|
|
62908
|
-
startMinute: number().int().min(0).max(1439),
|
|
62909
|
-
endMinute: number().int().min(1).max(1440)
|
|
63173
|
+
day: number().int().min(0).max(6).meta(readingMeta("none")),
|
|
63174
|
+
startMinute: number().int().min(0).max(1439).meta(readingMeta("none")),
|
|
63175
|
+
endMinute: number().int().min(1).max(1440).meta(readingMeta("none"))
|
|
62910
63176
|
});
|
|
62911
63177
|
/** Status of one physical volume, as the camera itself describes it. */
|
|
62912
63178
|
var OnboardStorageVolumeSchema = object({
|
|
@@ -62975,10 +63241,10 @@ object({
|
|
|
62975
63241
|
/** Master "record to the card at all" switch. */
|
|
62976
63242
|
enabled: boolean().nullable(),
|
|
62977
63243
|
overwriteWhenFull: boolean().nullable(),
|
|
62978
|
-
preRecordSec: number().nullable(),
|
|
62979
|
-
postRecordSec: number().nullable(),
|
|
63244
|
+
preRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
63245
|
+
postRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
62980
63246
|
/** Length of one recorded file, in minutes. */
|
|
62981
|
-
segmentMinutes: number().nullable(),
|
|
63247
|
+
segmentMinutes: number().nullable().meta(readingMeta("none")),
|
|
62982
63248
|
/** The primary track's weekly windows, flattened. */
|
|
62983
63249
|
windows: array(RecordWindowSchema),
|
|
62984
63250
|
/**
|
|
@@ -62994,7 +63260,7 @@ object({
|
|
|
62994
63260
|
* provider reporting a non-zero count also reports the schedule as not
|
|
62995
63261
|
* writable.
|
|
62996
63262
|
*/
|
|
62997
|
-
unreadableWindows: number(),
|
|
63263
|
+
unreadableWindows: number().meta(readingMeta("count")),
|
|
62998
63264
|
/**
|
|
62999
63265
|
* The camera is scheduled to record and has NO usable storage.
|
|
63000
63266
|
*
|
|
@@ -63631,7 +63897,7 @@ var CamStreamDescriptorSchema = object({
|
|
|
63631
63897
|
url: string().optional(),
|
|
63632
63898
|
codec: string().optional(),
|
|
63633
63899
|
resolution: CamStreamResolutionSchema.optional(),
|
|
63634
|
-
fps: number().positive().optional(),
|
|
63900
|
+
fps: number().positive().optional().meta(readingMeta("rate")),
|
|
63635
63901
|
label: string().optional(),
|
|
63636
63902
|
/** Device-level features (e.g. `battery-operated`) — drives broker policy. */
|
|
63637
63903
|
deviceFeatures: array(string()).optional(),
|
|
@@ -63661,18 +63927,18 @@ var StreamProfileSchema = _enum([
|
|
|
63661
63927
|
]);
|
|
63662
63928
|
/** The current encoding config of one stream profile. */
|
|
63663
63929
|
var StreamProfileConfigSchema = object({
|
|
63664
|
-
width: number(),
|
|
63665
|
-
height: number(),
|
|
63930
|
+
width: number().meta(readingMeta("none")),
|
|
63931
|
+
height: number().meta(readingMeta("none")),
|
|
63666
63932
|
codec: _enum(["h264", "h265"]),
|
|
63667
|
-
framerate: number(),
|
|
63668
|
-
bitrate: number(),
|
|
63933
|
+
framerate: number().meta(readingMeta("rate")),
|
|
63934
|
+
bitrate: number().meta(readingMeta("bitrate")),
|
|
63669
63935
|
bitrateMode: _enum(["vbr", "cbr"]).optional(),
|
|
63670
63936
|
encoderProfile: _enum([
|
|
63671
63937
|
"high",
|
|
63672
63938
|
"main",
|
|
63673
63939
|
"baseline"
|
|
63674
63940
|
]).optional(),
|
|
63675
|
-
gop: number().optional(),
|
|
63941
|
+
gop: number().optional().meta(readingMeta("none")),
|
|
63676
63942
|
/**
|
|
63677
63943
|
* Whether THIS profile currently carries an audio track. READ-ONLY here.
|
|
63678
63944
|
*
|
|
@@ -64315,23 +64581,13 @@ object({
|
|
|
64315
64581
|
});
|
|
64316
64582
|
DeviceType.Sensor;
|
|
64317
64583
|
object({
|
|
64318
|
-
/** Current temperature in Celsius. */
|
|
64319
|
-
celsius: number().meta({
|
|
64320
|
-
|
|
64584
|
+
/** Current temperature in Celsius. `null` when the sample was refused (D393). */
|
|
64585
|
+
celsius: number().nullable().meta(readingMeta("temperature", {
|
|
64586
|
+
precision: 1,
|
|
64321
64587
|
label: "Temperature"
|
|
64322
|
-
}),
|
|
64588
|
+
})),
|
|
64323
64589
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
64324
|
-
lastFetchedAt: number()
|
|
64325
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
64326
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
64327
|
-
* role's canonical unit, so a Fahrenheit feed renders '°F' not '°C'.
|
|
64328
|
-
* Absent → the UI falls back to the role's canonical unit. */
|
|
64329
|
-
unit: string().optional(),
|
|
64330
|
-
/** Suggested decimal places for numeric display.
|
|
64331
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
64332
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
64333
|
-
* auto-formatting when absent. */
|
|
64334
|
-
precision: number().int().min(0).max(10).optional()
|
|
64590
|
+
lastFetchedAt: number()
|
|
64335
64591
|
});
|
|
64336
64592
|
DeviceType.Sensor, DeviceType.Thermostat;
|
|
64337
64593
|
/**
|
|
@@ -64583,16 +64839,16 @@ object({
|
|
|
64583
64839
|
]),
|
|
64584
64840
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
64585
64841
|
* reading. */
|
|
64586
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
64842
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
64587
64843
|
/** Current fan-speed token (provider-verbatim). Null when unknown or
|
|
64588
64844
|
* the vacuum has no speed control. */
|
|
64589
64845
|
fanSpeed: string().nullable(),
|
|
64590
64846
|
/** Speed tokens the hardware accepts — drives the UI selector. */
|
|
64591
64847
|
availableFanSpeeds: array(string()),
|
|
64592
64848
|
/** 0..100 cleaning-completion percentage of the current task, or null. */
|
|
64593
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
64849
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
64594
64850
|
/** Current error code (0 / null = no error). */
|
|
64595
|
-
errorCode: number().nullable(),
|
|
64851
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
64596
64852
|
/** Human label for {@link errorCode}, or null when none / undecodable. */
|
|
64597
64853
|
errorLabel: string().nullable(),
|
|
64598
64854
|
/** Ms epoch when the slice was last updated. */
|
|
@@ -64631,7 +64887,7 @@ object({
|
|
|
64631
64887
|
]),
|
|
64632
64888
|
/** 0 = fully closed, 100 = fully open. Null when the device has no
|
|
64633
64889
|
* intermediate position surface. */
|
|
64634
|
-
position: number().min(0).max(100).nullable(),
|
|
64890
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
64635
64891
|
/** Ms epoch when the slice was last updated. */
|
|
64636
64892
|
lastChangedAt: number()
|
|
64637
64893
|
});
|
|
@@ -64659,9 +64915,9 @@ object({
|
|
|
64659
64915
|
DeviceType.Sensor;
|
|
64660
64916
|
object({
|
|
64661
64917
|
/** Current measured temperature. Null when not reported. */
|
|
64662
|
-
currentTemp: number().nullable(),
|
|
64918
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
64663
64919
|
/** Target temperature setpoint. Null when no setpoint surface. */
|
|
64664
|
-
targetTemp: number().nullable(),
|
|
64920
|
+
targetTemp: number().nullable().meta(readingMeta("temperature")),
|
|
64665
64921
|
/** Active operation mode = HA `state` (`eco` / `electric` / `gas` /
|
|
64666
64922
|
* `heat_pump` / `high_demand` / `performance` / `off`). Null when the
|
|
64667
64923
|
* device reports an unknown state. */
|
|
@@ -64672,9 +64928,9 @@ object({
|
|
|
64672
64928
|
* has no away surface. */
|
|
64673
64929
|
away: boolean().nullable(),
|
|
64674
64930
|
/** HA `min_temp` attribute. Null when not reported. */
|
|
64675
|
-
minTemp: number().nullable(),
|
|
64931
|
+
minTemp: number().nullable().meta(readingMeta("temperature")),
|
|
64676
64932
|
/** HA `max_temp` attribute. Null when not reported. */
|
|
64677
|
-
maxTemp: number().nullable(),
|
|
64933
|
+
maxTemp: number().nullable().meta(readingMeta("temperature")),
|
|
64678
64934
|
/** Ms epoch when the slice was last updated. */
|
|
64679
64935
|
lastChangedAt: number()
|
|
64680
64936
|
});
|
|
@@ -64698,25 +64954,18 @@ DeviceType.WaterHeater, method(object({
|
|
|
64698
64954
|
auth: "protected"
|
|
64699
64955
|
});
|
|
64700
64956
|
object({
|
|
64701
|
-
/** Verbatim
|
|
64702
|
-
* when no condition has been reported yet. */
|
|
64957
|
+
/** Verbatim condition state (`sunny`, `cloudy`, `rainy`, …). Null when none yet. */
|
|
64703
64958
|
condition: string().nullable(),
|
|
64704
|
-
/** Current temperature in
|
|
64705
|
-
temperature: number().nullable(),
|
|
64706
|
-
/** Temperature unit string (e.g. `°C` / `°F`). Null when not provided. */
|
|
64707
|
-
temperatureUnit: string().nullable(),
|
|
64959
|
+
/** Current temperature in Celsius. Null when not provided or refused. */
|
|
64960
|
+
temperature: number().nullable().meta(readingMeta("temperature", { precision: 1 })),
|
|
64708
64961
|
/** Relative humidity (0..100). Null when not provided. */
|
|
64709
|
-
humidity: number().min(0).max(100).nullable(),
|
|
64710
|
-
/** Barometric pressure in
|
|
64711
|
-
pressure: number().nullable(),
|
|
64712
|
-
/**
|
|
64713
|
-
|
|
64714
|
-
/** Wind speed in the reported unit. Null when not provided. */
|
|
64715
|
-
windSpeed: number().nullable(),
|
|
64716
|
-
/** Wind-speed unit string (e.g. `km/h` / `mph`). Null when not provided. */
|
|
64717
|
-
windSpeedUnit: string().nullable(),
|
|
64962
|
+
humidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
64963
|
+
/** Barometric pressure in hPa. Null when not provided or refused. */
|
|
64964
|
+
pressure: number().nullable().meta(readingMeta("pressure")),
|
|
64965
|
+
/** Wind speed in metres per second. Null when not provided or refused. */
|
|
64966
|
+
windSpeed: number().nullable().meta(readingMeta("speed")),
|
|
64718
64967
|
/** Wind bearing in degrees (0..360, meteorological). Null when not provided. */
|
|
64719
|
-
windBearing: number().nullable(),
|
|
64968
|
+
windBearing: number().nullable().meta(readingMeta("angle")),
|
|
64720
64969
|
/** Ms epoch when the slice was last updated. */
|
|
64721
64970
|
lastFetchedAt: number()
|
|
64722
64971
|
});
|
|
@@ -68834,6 +69083,13 @@ Object.freeze({
|
|
|
68834
69083
|
access: "view",
|
|
68835
69084
|
role: "viewer"
|
|
68836
69085
|
},
|
|
69086
|
+
"groupStatus.getStatus": {
|
|
69087
|
+
capName: "group-status",
|
|
69088
|
+
capScope: "device",
|
|
69089
|
+
addonId: null,
|
|
69090
|
+
access: "view",
|
|
69091
|
+
role: "viewer"
|
|
69092
|
+
},
|
|
68837
69093
|
"heatingValve.getStatus": {
|
|
68838
69094
|
capName: "heating-valve",
|
|
68839
69095
|
capScope: "device",
|
|
@@ -78656,6 +78912,33 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78656
78912
|
icon: "flame"
|
|
78657
78913
|
}]
|
|
78658
78914
|
},
|
|
78915
|
+
"group-status": {
|
|
78916
|
+
scope: "device",
|
|
78917
|
+
noun: t("Group", "Gruppo"),
|
|
78918
|
+
state: [
|
|
78919
|
+
{
|
|
78920
|
+
kind: "numeric",
|
|
78921
|
+
field: "included",
|
|
78922
|
+
quantity: t("the members reporting", "i membri che rispondono"),
|
|
78923
|
+
label: t("Reporting", "Rispondono"),
|
|
78924
|
+
icon: "users"
|
|
78925
|
+
},
|
|
78926
|
+
{
|
|
78927
|
+
kind: "numeric",
|
|
78928
|
+
field: "excluded",
|
|
78929
|
+
quantity: t("the members left out", "i membri esclusi"),
|
|
78930
|
+
label: t("Excluded", "Esclusi"),
|
|
78931
|
+
icon: "users"
|
|
78932
|
+
},
|
|
78933
|
+
{
|
|
78934
|
+
kind: "numeric",
|
|
78935
|
+
field: "total",
|
|
78936
|
+
quantity: t("the member count", "il numero di membri"),
|
|
78937
|
+
label: t("Members", "Membri"),
|
|
78938
|
+
icon: "sigma"
|
|
78939
|
+
}
|
|
78940
|
+
]
|
|
78941
|
+
},
|
|
78659
78942
|
"humidity-sensor": {
|
|
78660
78943
|
scope: "device",
|
|
78661
78944
|
noun: t("Humidity", "Umidità"),
|
|
@@ -78689,7 +78972,6 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78689
78972
|
field: "value",
|
|
78690
78973
|
quantity: t("the reading", "il valore"),
|
|
78691
78974
|
label: t("Reading", "Valore"),
|
|
78692
|
-
unitField: "unit",
|
|
78693
78975
|
icon: "gauge"
|
|
78694
78976
|
}]
|
|
78695
78977
|
},
|
|
@@ -78825,7 +79107,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78825
79107
|
field: "temperature",
|
|
78826
79108
|
quantity: t("the outdoor temperature", "la temperatura esterna"),
|
|
78827
79109
|
label: t("Temperature", "Temperatura"),
|
|
78828
|
-
|
|
79110
|
+
unit: "°C",
|
|
78829
79111
|
icon: "thermometer"
|
|
78830
79112
|
},
|
|
78831
79113
|
{
|
|
@@ -78841,7 +79123,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78841
79123
|
field: "windSpeed",
|
|
78842
79124
|
quantity: t("the wind speed", "la velocità del vento"),
|
|
78843
79125
|
label: t("Wind", "Vento"),
|
|
78844
|
-
|
|
79126
|
+
unit: "m/s",
|
|
78845
79127
|
icon: "wind"
|
|
78846
79128
|
},
|
|
78847
79129
|
{
|
|
@@ -78849,7 +79131,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78849
79131
|
field: "pressure",
|
|
78850
79132
|
quantity: t("the air pressure", "la pressione atmosferica"),
|
|
78851
79133
|
label: t("Pressure", "Pressione"),
|
|
78852
|
-
|
|
79134
|
+
unit: "hPa",
|
|
78853
79135
|
icon: "gauge"
|
|
78854
79136
|
}
|
|
78855
79137
|
]
|
|
@@ -80122,6 +80404,11 @@ Object.freeze({
|
|
|
80122
80404
|
form: "single",
|
|
80123
80405
|
optional: false
|
|
80124
80406
|
}],
|
|
80407
|
+
"groupStatus.getStatus": [{
|
|
80408
|
+
name: "deviceId",
|
|
80409
|
+
form: "single",
|
|
80410
|
+
optional: false
|
|
80411
|
+
}],
|
|
80125
80412
|
"heatingValve.getStatus": [{
|
|
80126
80413
|
name: "deviceId",
|
|
80127
80414
|
form: "single",
|