@camstack/addon-provider-homeassistant 1.2.625 → 1.2.627
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/addon.js +268 -119
- package/dist/addon.mjs +268 -119
- package/dist/{dist-DvZEnx9C.mjs → dist-BFnk4bwH.mjs} +1314 -497
- package/dist/{dist-oNUlRdur.js → dist-CRwUHjY7.js} +1349 -496
- package/dist/ha-export/ha-export.addon.js +30 -19
- package/dist/ha-export/ha-export.addon.mjs +30 -19
- package/package.json +1 -1
|
@@ -5566,7 +5566,7 @@ var ZodIssueCode = {
|
|
|
5566
5566
|
var ZodFirstPartyTypeKind;
|
|
5567
5567
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5568
5568
|
//#endregion
|
|
5569
|
-
//#region ../types/dist/sleep-
|
|
5569
|
+
//#region ../types/dist/sleep-B81gwQuR.mjs
|
|
5570
5570
|
/**
|
|
5571
5571
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5572
5572
|
* window to float samples (D455).
|
|
@@ -8308,6 +8308,102 @@ function defineEntryKind(name, spec) {
|
|
|
8308
8308
|
if (defined === void 0) throw new DeclarationRefusedError(`entry kind "${name}" was not built`);
|
|
8309
8309
|
return defined;
|
|
8310
8310
|
}
|
|
8311
|
+
var READING_QUANTITIES = [
|
|
8312
|
+
"temperature",
|
|
8313
|
+
"pressure",
|
|
8314
|
+
"speed",
|
|
8315
|
+
"precipitation",
|
|
8316
|
+
"precipitation-rate",
|
|
8317
|
+
"length",
|
|
8318
|
+
"area",
|
|
8319
|
+
"illuminance",
|
|
8320
|
+
"irradiance",
|
|
8321
|
+
"power",
|
|
8322
|
+
"energy",
|
|
8323
|
+
"voltage",
|
|
8324
|
+
"current",
|
|
8325
|
+
"apparent-power",
|
|
8326
|
+
"humidity",
|
|
8327
|
+
"percentage",
|
|
8328
|
+
"concentration-volume",
|
|
8329
|
+
"concentration-mass",
|
|
8330
|
+
"concentration-ppb",
|
|
8331
|
+
"volume",
|
|
8332
|
+
"duration",
|
|
8333
|
+
"duration-ms",
|
|
8334
|
+
"information",
|
|
8335
|
+
"sound-level",
|
|
8336
|
+
"signal-level",
|
|
8337
|
+
"colour-temperature",
|
|
8338
|
+
"angle",
|
|
8339
|
+
"bitrate",
|
|
8340
|
+
"rate",
|
|
8341
|
+
"mass",
|
|
8342
|
+
"index",
|
|
8343
|
+
"ratio",
|
|
8344
|
+
"count",
|
|
8345
|
+
"none",
|
|
8346
|
+
"device"
|
|
8347
|
+
];
|
|
8348
|
+
var ReadingQuantitySchema = _enum(READING_QUANTITIES);
|
|
8349
|
+
var QUANTITY_SET = new Set(READING_QUANTITIES);
|
|
8350
|
+
function isReadingQuantity(value) {
|
|
8351
|
+
return typeof value === "string" && QUANTITY_SET.has(value);
|
|
8352
|
+
}
|
|
8353
|
+
/**
|
|
8354
|
+
* Stored unit symbol for a quantity. `none` means the number is dimensionless
|
|
8355
|
+
* (or an index / ratio / count). `device` means the cap has no single unit.
|
|
8356
|
+
*/
|
|
8357
|
+
var QUANTITY_BASE = {
|
|
8358
|
+
temperature: "°C",
|
|
8359
|
+
pressure: "hPa",
|
|
8360
|
+
speed: "m/s",
|
|
8361
|
+
precipitation: "mm",
|
|
8362
|
+
"precipitation-rate": "mm/h",
|
|
8363
|
+
length: "m",
|
|
8364
|
+
area: "m²",
|
|
8365
|
+
illuminance: "lx",
|
|
8366
|
+
irradiance: "W/m²",
|
|
8367
|
+
power: "W",
|
|
8368
|
+
energy: "kWh",
|
|
8369
|
+
voltage: "V",
|
|
8370
|
+
current: "A",
|
|
8371
|
+
"apparent-power": "VA",
|
|
8372
|
+
humidity: "%",
|
|
8373
|
+
percentage: "%",
|
|
8374
|
+
"concentration-volume": "ppm",
|
|
8375
|
+
"concentration-mass": "µg/m³",
|
|
8376
|
+
"concentration-ppb": "ppb",
|
|
8377
|
+
volume: "L",
|
|
8378
|
+
duration: "s",
|
|
8379
|
+
"duration-ms": "ms",
|
|
8380
|
+
information: "B",
|
|
8381
|
+
"sound-level": "dBFS",
|
|
8382
|
+
"signal-level": "dBm",
|
|
8383
|
+
"colour-temperature": "mired",
|
|
8384
|
+
angle: "°",
|
|
8385
|
+
bitrate: "kbps",
|
|
8386
|
+
rate: "fps",
|
|
8387
|
+
mass: "kg",
|
|
8388
|
+
index: "none",
|
|
8389
|
+
ratio: "none",
|
|
8390
|
+
count: "none",
|
|
8391
|
+
none: "none",
|
|
8392
|
+
device: "device"
|
|
8393
|
+
};
|
|
8394
|
+
/** The stored unit, or `undefined` when the quantity has no unit symbol. */
|
|
8395
|
+
function baseUnitOf(quantity) {
|
|
8396
|
+
const symbol = QUANTITY_BASE[quantity];
|
|
8397
|
+
if (symbol === "none" || symbol === "device") return void 0;
|
|
8398
|
+
return symbol;
|
|
8399
|
+
}
|
|
8400
|
+
function readingMeta(quantity, extras) {
|
|
8401
|
+
return {
|
|
8402
|
+
quantity,
|
|
8403
|
+
...extras?.precision !== void 0 ? { precision: extras.precision } : {},
|
|
8404
|
+
...extras?.label !== void 0 ? { label: extras.label } : {}
|
|
8405
|
+
};
|
|
8406
|
+
}
|
|
8311
8407
|
/** Shared Zod schemas used across streaming capabilities. */
|
|
8312
8408
|
var CamProfileSchema = _enum([
|
|
8313
8409
|
"high",
|
|
@@ -8335,8 +8431,8 @@ var CamStreamKindSchema = _enum([
|
|
|
8335
8431
|
"derived"
|
|
8336
8432
|
]);
|
|
8337
8433
|
var CamStreamResolutionSchema = object({
|
|
8338
|
-
width: number().int().positive(),
|
|
8339
|
-
height: number().int().positive()
|
|
8434
|
+
width: number().int().positive().meta(readingMeta("none")),
|
|
8435
|
+
height: number().int().positive().meta(readingMeta("none"))
|
|
8340
8436
|
});
|
|
8341
8437
|
var CameraStreamSchema = object({
|
|
8342
8438
|
/** Stable, provider-assigned id unique within the (deviceId) scope. */
|
|
@@ -8913,6 +9009,7 @@ var CAP_NAMES = Object.freeze([
|
|
|
8913
9009
|
"filesystem-browse",
|
|
8914
9010
|
"flood",
|
|
8915
9011
|
"gas",
|
|
9012
|
+
"group-status",
|
|
8916
9013
|
"heating-valve",
|
|
8917
9014
|
"humidifier",
|
|
8918
9015
|
"humidity-sensor",
|
|
@@ -9042,14 +9139,6 @@ Object.freeze({
|
|
|
9042
9139
|
{
|
|
9043
9140
|
"path": "aqi",
|
|
9044
9141
|
"valueType": "number"
|
|
9045
|
-
},
|
|
9046
|
-
{
|
|
9047
|
-
"path": "unit",
|
|
9048
|
-
"valueType": "string"
|
|
9049
|
-
},
|
|
9050
|
-
{
|
|
9051
|
-
"path": "precision",
|
|
9052
|
-
"valueType": "number"
|
|
9053
9142
|
}
|
|
9054
9143
|
],
|
|
9055
9144
|
"alarm-panel": [
|
|
@@ -9085,20 +9174,10 @@ Object.freeze({
|
|
|
9085
9174
|
"valueType": "boolean"
|
|
9086
9175
|
}
|
|
9087
9176
|
],
|
|
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
|
-
],
|
|
9177
|
+
"ambient-light-sensor": [{
|
|
9178
|
+
"path": "lux",
|
|
9179
|
+
"valueType": "number"
|
|
9180
|
+
}],
|
|
9102
9181
|
"audio-metrics": [
|
|
9103
9182
|
{
|
|
9104
9183
|
"path": "ts",
|
|
@@ -9178,6 +9257,10 @@ Object.freeze({
|
|
|
9178
9257
|
"path": "lastUpdated",
|
|
9179
9258
|
"valueType": "number"
|
|
9180
9259
|
},
|
|
9260
|
+
{
|
|
9261
|
+
"path": "volts",
|
|
9262
|
+
"valueType": "number"
|
|
9263
|
+
},
|
|
9181
9264
|
{
|
|
9182
9265
|
"path": "lastContactAt",
|
|
9183
9266
|
"valueType": "number"
|
|
@@ -9420,10 +9503,6 @@ Object.freeze({
|
|
|
9420
9503
|
"datetime"
|
|
9421
9504
|
]
|
|
9422
9505
|
},
|
|
9423
|
-
{
|
|
9424
|
-
"path": "unit",
|
|
9425
|
-
"valueType": "string"
|
|
9426
|
-
},
|
|
9427
9506
|
{
|
|
9428
9507
|
"path": "min",
|
|
9429
9508
|
"valueType": "number"
|
|
@@ -9435,19 +9514,6 @@ Object.freeze({
|
|
|
9435
9514
|
{
|
|
9436
9515
|
"path": "step",
|
|
9437
9516
|
"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
9517
|
}
|
|
9452
9518
|
],
|
|
9453
9519
|
"cover": [
|
|
@@ -9688,13 +9754,8 @@ Object.freeze({
|
|
|
9688
9754
|
"path": "value",
|
|
9689
9755
|
"valueType": "string"
|
|
9690
9756
|
}, {
|
|
9691
|
-
"path": "
|
|
9692
|
-
"valueType": "
|
|
9693
|
-
"enumValues": [
|
|
9694
|
-
"date",
|
|
9695
|
-
"time",
|
|
9696
|
-
"datetime"
|
|
9697
|
-
]
|
|
9757
|
+
"path": "timestamp",
|
|
9758
|
+
"valueType": "boolean"
|
|
9698
9759
|
}],
|
|
9699
9760
|
"event-emitter": [
|
|
9700
9761
|
{
|
|
@@ -9767,6 +9828,20 @@ Object.freeze({
|
|
|
9767
9828
|
"path": "detected",
|
|
9768
9829
|
"valueType": "boolean"
|
|
9769
9830
|
}],
|
|
9831
|
+
"group-status": [
|
|
9832
|
+
{
|
|
9833
|
+
"path": "included",
|
|
9834
|
+
"valueType": "number"
|
|
9835
|
+
},
|
|
9836
|
+
{
|
|
9837
|
+
"path": "excluded",
|
|
9838
|
+
"valueType": "number"
|
|
9839
|
+
},
|
|
9840
|
+
{
|
|
9841
|
+
"path": "total",
|
|
9842
|
+
"valueType": "number"
|
|
9843
|
+
}
|
|
9844
|
+
],
|
|
9770
9845
|
"heating-valve": [{
|
|
9771
9846
|
"path": "position",
|
|
9772
9847
|
"valueType": "number"
|
|
@@ -9801,20 +9876,10 @@ Object.freeze({
|
|
|
9801
9876
|
"valueType": "number"
|
|
9802
9877
|
}
|
|
9803
9878
|
],
|
|
9804
|
-
"humidity-sensor": [
|
|
9805
|
-
|
|
9806
|
-
|
|
9807
|
-
|
|
9808
|
-
},
|
|
9809
|
-
{
|
|
9810
|
-
"path": "unit",
|
|
9811
|
-
"valueType": "string"
|
|
9812
|
-
},
|
|
9813
|
-
{
|
|
9814
|
-
"path": "precision",
|
|
9815
|
-
"valueType": "number"
|
|
9816
|
-
}
|
|
9817
|
-
],
|
|
9879
|
+
"humidity-sensor": [{
|
|
9880
|
+
"path": "percent",
|
|
9881
|
+
"valueType": "number"
|
|
9882
|
+
}],
|
|
9818
9883
|
"image": [{
|
|
9819
9884
|
"path": "url",
|
|
9820
9885
|
"valueType": "string"
|
|
@@ -10153,20 +10218,10 @@ Object.freeze({
|
|
|
10153
10218
|
"valueType": "boolean"
|
|
10154
10219
|
}
|
|
10155
10220
|
],
|
|
10156
|
-
"numeric-sensor": [
|
|
10157
|
-
|
|
10158
|
-
|
|
10159
|
-
|
|
10160
|
-
},
|
|
10161
|
-
{
|
|
10162
|
-
"path": "unit",
|
|
10163
|
-
"valueType": "string"
|
|
10164
|
-
},
|
|
10165
|
-
{
|
|
10166
|
-
"path": "precision",
|
|
10167
|
-
"valueType": "number"
|
|
10168
|
-
}
|
|
10169
|
-
],
|
|
10221
|
+
"numeric-sensor": [{
|
|
10222
|
+
"path": "value",
|
|
10223
|
+
"valueType": "number"
|
|
10224
|
+
}],
|
|
10170
10225
|
"pet-feeder": [
|
|
10171
10226
|
{
|
|
10172
10227
|
"path": "foodLevel",
|
|
@@ -10258,14 +10313,6 @@ Object.freeze({
|
|
|
10258
10313
|
{
|
|
10259
10314
|
"path": "powerFactor",
|
|
10260
10315
|
"valueType": "number"
|
|
10261
|
-
},
|
|
10262
|
-
{
|
|
10263
|
-
"path": "unit",
|
|
10264
|
-
"valueType": "string"
|
|
10265
|
-
},
|
|
10266
|
-
{
|
|
10267
|
-
"path": "precision",
|
|
10268
|
-
"valueType": "number"
|
|
10269
10316
|
}
|
|
10270
10317
|
],
|
|
10271
10318
|
"presence": [
|
|
@@ -10294,20 +10341,10 @@ Object.freeze({
|
|
|
10294
10341
|
"valueType": "number"
|
|
10295
10342
|
}
|
|
10296
10343
|
],
|
|
10297
|
-
"pressure-sensor": [
|
|
10298
|
-
|
|
10299
|
-
|
|
10300
|
-
|
|
10301
|
-
},
|
|
10302
|
-
{
|
|
10303
|
-
"path": "unit",
|
|
10304
|
-
"valueType": "string"
|
|
10305
|
-
},
|
|
10306
|
-
{
|
|
10307
|
-
"path": "precision",
|
|
10308
|
-
"valueType": "number"
|
|
10309
|
-
}
|
|
10310
|
-
],
|
|
10344
|
+
"pressure-sensor": [{
|
|
10345
|
+
"path": "hpa",
|
|
10346
|
+
"valueType": "number"
|
|
10347
|
+
}],
|
|
10311
10348
|
"privacy-mask": [{
|
|
10312
10349
|
"path": "enabled",
|
|
10313
10350
|
"valueType": "boolean"
|
|
@@ -10618,20 +10655,10 @@ Object.freeze({
|
|
|
10618
10655
|
"path": "tampered",
|
|
10619
10656
|
"valueType": "boolean"
|
|
10620
10657
|
}],
|
|
10621
|
-
"temperature-sensor": [
|
|
10622
|
-
|
|
10623
|
-
|
|
10624
|
-
|
|
10625
|
-
},
|
|
10626
|
-
{
|
|
10627
|
-
"path": "unit",
|
|
10628
|
-
"valueType": "string"
|
|
10629
|
-
},
|
|
10630
|
-
{
|
|
10631
|
-
"path": "precision",
|
|
10632
|
-
"valueType": "number"
|
|
10633
|
-
}
|
|
10634
|
-
],
|
|
10658
|
+
"temperature-sensor": [{
|
|
10659
|
+
"path": "celsius",
|
|
10660
|
+
"valueType": "number"
|
|
10661
|
+
}],
|
|
10635
10662
|
"update": [
|
|
10636
10663
|
{
|
|
10637
10664
|
"path": "currentVersion",
|
|
@@ -10742,10 +10769,6 @@ Object.freeze({
|
|
|
10742
10769
|
"path": "temperature",
|
|
10743
10770
|
"valueType": "number"
|
|
10744
10771
|
},
|
|
10745
|
-
{
|
|
10746
|
-
"path": "temperatureUnit",
|
|
10747
|
-
"valueType": "string"
|
|
10748
|
-
},
|
|
10749
10772
|
{
|
|
10750
10773
|
"path": "humidity",
|
|
10751
10774
|
"valueType": "number"
|
|
@@ -10754,18 +10777,10 @@ Object.freeze({
|
|
|
10754
10777
|
"path": "pressure",
|
|
10755
10778
|
"valueType": "number"
|
|
10756
10779
|
},
|
|
10757
|
-
{
|
|
10758
|
-
"path": "pressureUnit",
|
|
10759
|
-
"valueType": "string"
|
|
10760
|
-
},
|
|
10761
10780
|
{
|
|
10762
10781
|
"path": "windSpeed",
|
|
10763
10782
|
"valueType": "number"
|
|
10764
10783
|
},
|
|
10765
|
-
{
|
|
10766
|
-
"path": "windSpeedUnit",
|
|
10767
|
-
"valueType": "string"
|
|
10768
|
-
},
|
|
10769
10784
|
{
|
|
10770
10785
|
"path": "windBearing",
|
|
10771
10786
|
"valueType": "number"
|
|
@@ -11168,7 +11183,7 @@ function errMsg(err) {
|
|
|
11168
11183
|
return String(err);
|
|
11169
11184
|
}
|
|
11170
11185
|
//#endregion
|
|
11171
|
-
//#region ../types/dist/composition-
|
|
11186
|
+
//#region ../types/dist/composition-B85l9j1M.mjs
|
|
11172
11187
|
/**
|
|
11173
11188
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
11174
11189
|
*
|
|
@@ -11923,15 +11938,67 @@ function validateExpressionSource(src) {
|
|
|
11923
11938
|
}
|
|
11924
11939
|
return null;
|
|
11925
11940
|
}
|
|
11926
|
-
/**
|
|
11927
|
-
|
|
11928
|
-
|
|
11929
|
-
|
|
11941
|
+
/**
|
|
11942
|
+
* A composition source identity: `(addonId, stableId)`, never a numeric device
|
|
11943
|
+
* id. Split out so helper schemas can name it without a cycle through
|
|
11944
|
+
* `composition.ts` (D659).
|
|
11945
|
+
*/
|
|
11930
11946
|
var CompositionSourceRefSchema = object({
|
|
11931
11947
|
/** The owning addon; `stableId` is unique only within it. */
|
|
11932
11948
|
addonId: string().min(1),
|
|
11933
11949
|
stableId: string().min(1)
|
|
11934
11950
|
});
|
|
11951
|
+
var GROUP_TEMPLATE_IDS = [
|
|
11952
|
+
"temperature",
|
|
11953
|
+
"humidity",
|
|
11954
|
+
"pressure",
|
|
11955
|
+
"illuminance",
|
|
11956
|
+
"power",
|
|
11957
|
+
"energy",
|
|
11958
|
+
"battery",
|
|
11959
|
+
"numeric",
|
|
11960
|
+
"motion",
|
|
11961
|
+
"contact",
|
|
11962
|
+
"leak",
|
|
11963
|
+
"smoke",
|
|
11964
|
+
"occupancy",
|
|
11965
|
+
"binary"
|
|
11966
|
+
];
|
|
11967
|
+
var NUMERIC_AGGREGATES = [
|
|
11968
|
+
"mean",
|
|
11969
|
+
"median",
|
|
11970
|
+
"min",
|
|
11971
|
+
"max",
|
|
11972
|
+
"sum"
|
|
11973
|
+
];
|
|
11974
|
+
var BINARY_AGGREGATES = ["any", "all"];
|
|
11975
|
+
var AGGREGATE_REDUCERS = [
|
|
11976
|
+
"mean",
|
|
11977
|
+
"median",
|
|
11978
|
+
"min",
|
|
11979
|
+
"max",
|
|
11980
|
+
"sum",
|
|
11981
|
+
"any",
|
|
11982
|
+
"all"
|
|
11983
|
+
];
|
|
11984
|
+
var GroupTemplateIdSchema = _enum(GROUP_TEMPLATE_IDS);
|
|
11985
|
+
var AggregateReducerSchema = _enum(AGGREGATE_REDUCERS);
|
|
11986
|
+
/** One member. The field is stored so occupancy can name motion or binary. */
|
|
11987
|
+
var HelperMemberSchema = object({
|
|
11988
|
+
source: CompositionSourceRefSchema,
|
|
11989
|
+
cap: string().min(1),
|
|
11990
|
+
fieldPath: string().min(1)
|
|
11991
|
+
});
|
|
11992
|
+
var HelperSpecSchema = discriminatedUnion("kind", [object({
|
|
11993
|
+
kind: literal("group"),
|
|
11994
|
+
templateId: GroupTemplateIdSchema,
|
|
11995
|
+
aggregate: AggregateReducerSchema,
|
|
11996
|
+
members: array(HelperMemberSchema).min(1).max(64)
|
|
11997
|
+
})]);
|
|
11998
|
+
/** A composed device's stableId is this prefix plus the block id. */
|
|
11999
|
+
var COMPOSED_DEVICE_STABLE_ID_PREFIX = "composed-";
|
|
12000
|
+
/** Longest snippet a `code` source may carry (slice 4). */
|
|
12001
|
+
var MAX_COMPOSITION_CODE_LENGTH = 2e4;
|
|
11935
12002
|
/** One field of one capability of one source device. */
|
|
11936
12003
|
var CompositionFieldReadSchema = object({
|
|
11937
12004
|
source: CompositionSourceRefSchema,
|
|
@@ -11975,7 +12042,33 @@ var CompositionCodeSourceSchema = object({
|
|
|
11975
12042
|
var CompositionFieldSourceSchema = discriminatedUnion("kind", [
|
|
11976
12043
|
CompositionFromSourceSchema,
|
|
11977
12044
|
CompositionExpressionSourceSchema,
|
|
11978
|
-
CompositionCodeSourceSchema
|
|
12045
|
+
CompositionCodeSourceSchema,
|
|
12046
|
+
object({
|
|
12047
|
+
kind: literal("aggregate"),
|
|
12048
|
+
reducer: _enum([
|
|
12049
|
+
"mean",
|
|
12050
|
+
"median",
|
|
12051
|
+
"min",
|
|
12052
|
+
"max",
|
|
12053
|
+
"sum",
|
|
12054
|
+
"any",
|
|
12055
|
+
"all"
|
|
12056
|
+
]),
|
|
12057
|
+
reads: array(CompositionFieldReadSchema).min(1).max(64),
|
|
12058
|
+
/** `value` is the reading; the others are the member counts. */
|
|
12059
|
+
publish: _enum([
|
|
12060
|
+
"value",
|
|
12061
|
+
"included",
|
|
12062
|
+
"excluded",
|
|
12063
|
+
"total"
|
|
12064
|
+
]),
|
|
12065
|
+
/** What a `value` publish does when nobody is included. Counts ignore this. */
|
|
12066
|
+
empty: _enum([
|
|
12067
|
+
"null",
|
|
12068
|
+
"omit",
|
|
12069
|
+
"offline"
|
|
12070
|
+
])
|
|
12071
|
+
})
|
|
11979
12072
|
]);
|
|
11980
12073
|
var CompositionCommandTargetSchema = discriminatedUnion("kind", [object({
|
|
11981
12074
|
kind: literal("forward"),
|
|
@@ -12021,7 +12114,13 @@ var CompositionSchema = object({
|
|
|
12021
12114
|
kind: literal("existing"),
|
|
12022
12115
|
device: CompositionSourceRefSchema
|
|
12023
12116
|
})]),
|
|
12024
|
-
features: array(CompositionFeatureSchema).min(1).max(16)
|
|
12117
|
+
features: array(CompositionFeatureSchema).min(1).max(16),
|
|
12118
|
+
/**
|
|
12119
|
+
* Present when the block is a helper template. Absent on a free
|
|
12120
|
+
* composition (the room example, device 4603). The editor reads this,
|
|
12121
|
+
* never the compiled features.
|
|
12122
|
+
*/
|
|
12123
|
+
helper: HelperSpecSchema.optional()
|
|
12025
12124
|
}).superRefine((composition, ctx) => {
|
|
12026
12125
|
const seen = /* @__PURE__ */ new Set();
|
|
12027
12126
|
composition.features.forEach((feature, index) => {
|
|
@@ -18441,7 +18540,11 @@ var CompositionProblemSchema = object({
|
|
|
18441
18540
|
"item-field-reserved",
|
|
18442
18541
|
"target-missing",
|
|
18443
18542
|
"target-unreadable",
|
|
18444
|
-
"not-replaceable"
|
|
18543
|
+
"not-replaceable",
|
|
18544
|
+
"native-capability-replace",
|
|
18545
|
+
"mixed-quantity",
|
|
18546
|
+
"helper-mismatch",
|
|
18547
|
+
"member-constraint"
|
|
18445
18548
|
]),
|
|
18446
18549
|
path: string(),
|
|
18447
18550
|
message: string()
|
|
@@ -18462,7 +18565,8 @@ var CompositionUnavailableModeSchema = _enum([
|
|
|
18462
18565
|
"null",
|
|
18463
18566
|
"offline",
|
|
18464
18567
|
"unknown",
|
|
18465
|
-
"release"
|
|
18568
|
+
"release",
|
|
18569
|
+
"omit"
|
|
18466
18570
|
]);
|
|
18467
18571
|
/**
|
|
18468
18572
|
* `derived` reads a source · `clock` reads only `now`, recomputed when a sibling
|
|
@@ -18499,9 +18603,11 @@ var CompositionFieldPlanSchema = object({
|
|
|
18499
18603
|
reads: array(CompositionFieldReadSchema)
|
|
18500
18604
|
});
|
|
18501
18605
|
/**
|
|
18502
|
-
* What a feature does to its target (D663): `new` builds a capability on a
|
|
18503
|
-
* device; on an existing device it `add`s a capability the device lacks
|
|
18504
|
-
*
|
|
18606
|
+
* What a feature does to its target (D663, D944): `new` builds a capability on a
|
|
18607
|
+
* new device; on an existing device it `add`s a capability the device lacks.
|
|
18608
|
+
* Replacing a capability the device already serves is refused
|
|
18609
|
+
* (`native-capability-replace`), not planned. `replace` remains on the claim
|
|
18610
|
+
* wire for a claim the hub already holds.
|
|
18505
18611
|
*/
|
|
18506
18612
|
var CompositionFeatureModeSchema = _enum([
|
|
18507
18613
|
"new",
|
|
@@ -18674,6 +18780,235 @@ Object.freeze({
|
|
|
18674
18780
|
result: ["number", "null"]
|
|
18675
18781
|
}
|
|
18676
18782
|
});
|
|
18783
|
+
/**
|
|
18784
|
+
* One catalog row per base reading a group helper can build (D944 §3).
|
|
18785
|
+
* Data, not a form default written into the block.
|
|
18786
|
+
*/
|
|
18787
|
+
var NOW = {
|
|
18788
|
+
fieldPath: "lastFetchedAt",
|
|
18789
|
+
expr: "now"
|
|
18790
|
+
};
|
|
18791
|
+
var CHANGED = {
|
|
18792
|
+
fieldPath: "lastChangedAt",
|
|
18793
|
+
expr: "now"
|
|
18794
|
+
};
|
|
18795
|
+
function numeric(input) {
|
|
18796
|
+
return {
|
|
18797
|
+
...input,
|
|
18798
|
+
family: "numeric",
|
|
18799
|
+
deviceType: DeviceType.Sensor,
|
|
18800
|
+
memberDeviceType: DeviceType.Sensor,
|
|
18801
|
+
baseUnit: baseUnitOf(input.quantity),
|
|
18802
|
+
aggregates: NUMERIC_AGGREGATES,
|
|
18803
|
+
accept: [{
|
|
18804
|
+
cap: input.outputCap,
|
|
18805
|
+
fieldPath: input.outputField
|
|
18806
|
+
}]
|
|
18807
|
+
};
|
|
18808
|
+
}
|
|
18809
|
+
function binary(input) {
|
|
18810
|
+
return {
|
|
18811
|
+
...input,
|
|
18812
|
+
family: "binary",
|
|
18813
|
+
deviceType: DeviceType.Sensor,
|
|
18814
|
+
memberDeviceType: DeviceType.Sensor,
|
|
18815
|
+
quantity: "none",
|
|
18816
|
+
baseUnit: void 0,
|
|
18817
|
+
aggregates: BINARY_AGGREGATES,
|
|
18818
|
+
empty: "offline"
|
|
18819
|
+
};
|
|
18820
|
+
}
|
|
18821
|
+
var GROUP_TEMPLATES = [
|
|
18822
|
+
numeric({
|
|
18823
|
+
id: "temperature",
|
|
18824
|
+
summary: "Mean, median, min, max or sum of temperatures. Offline and unknown members are left out, never read as 0 °C.",
|
|
18825
|
+
role: DeviceRole.TemperatureSensor,
|
|
18826
|
+
outputCap: "temperature-sensor",
|
|
18827
|
+
outputField: "celsius",
|
|
18828
|
+
quantity: "temperature",
|
|
18829
|
+
defaultAggregate: "mean",
|
|
18830
|
+
empty: "null",
|
|
18831
|
+
companions: [NOW]
|
|
18832
|
+
}),
|
|
18833
|
+
numeric({
|
|
18834
|
+
id: "humidity",
|
|
18835
|
+
summary: "Humidity in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
18836
|
+
role: DeviceRole.HumiditySensor,
|
|
18837
|
+
outputCap: "humidity-sensor",
|
|
18838
|
+
outputField: "percent",
|
|
18839
|
+
quantity: "humidity",
|
|
18840
|
+
defaultAggregate: "mean",
|
|
18841
|
+
empty: "null",
|
|
18842
|
+
companions: [NOW]
|
|
18843
|
+
}),
|
|
18844
|
+
numeric({
|
|
18845
|
+
id: "pressure",
|
|
18846
|
+
summary: "Pressure in hectopascals. Offline and unknown members are left out, never read as 0 hPa.",
|
|
18847
|
+
role: DeviceRole.PressureSensor,
|
|
18848
|
+
outputCap: "pressure-sensor",
|
|
18849
|
+
outputField: "hpa",
|
|
18850
|
+
quantity: "pressure",
|
|
18851
|
+
defaultAggregate: "mean",
|
|
18852
|
+
empty: "null",
|
|
18853
|
+
companions: [NOW]
|
|
18854
|
+
}),
|
|
18855
|
+
numeric({
|
|
18856
|
+
id: "illuminance",
|
|
18857
|
+
summary: "Illuminance in lux. Offline and unknown members are left out, never read as 0 lx.",
|
|
18858
|
+
role: DeviceRole.AmbientLightSensor,
|
|
18859
|
+
outputCap: "ambient-light-sensor",
|
|
18860
|
+
outputField: "lux",
|
|
18861
|
+
quantity: "illuminance",
|
|
18862
|
+
defaultAggregate: "mean",
|
|
18863
|
+
empty: "null",
|
|
18864
|
+
companions: [NOW]
|
|
18865
|
+
}),
|
|
18866
|
+
numeric({
|
|
18867
|
+
id: "power",
|
|
18868
|
+
summary: "Power in watts, summed by default. Nobody reporting omits the key rather than writing 0 W.",
|
|
18869
|
+
role: DeviceRole.PowerSensor,
|
|
18870
|
+
outputCap: "power-meter",
|
|
18871
|
+
outputField: "watts",
|
|
18872
|
+
quantity: "power",
|
|
18873
|
+
defaultAggregate: "sum",
|
|
18874
|
+
empty: "omit",
|
|
18875
|
+
companions: [NOW]
|
|
18876
|
+
}),
|
|
18877
|
+
numeric({
|
|
18878
|
+
id: "energy",
|
|
18879
|
+
summary: "Energy in kilowatt-hours, summed by default. Nobody reporting omits the key rather than writing 0 kWh.",
|
|
18880
|
+
role: DeviceRole.EnergySensor,
|
|
18881
|
+
outputCap: "power-meter",
|
|
18882
|
+
outputField: "kwhTotal",
|
|
18883
|
+
quantity: "energy",
|
|
18884
|
+
defaultAggregate: "sum",
|
|
18885
|
+
empty: "omit",
|
|
18886
|
+
companions: [NOW]
|
|
18887
|
+
}),
|
|
18888
|
+
numeric({
|
|
18889
|
+
id: "battery",
|
|
18890
|
+
summary: "Battery charge in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
18891
|
+
role: DeviceRole.BatterySensor,
|
|
18892
|
+
outputCap: "battery",
|
|
18893
|
+
outputField: "percentage",
|
|
18894
|
+
quantity: "percentage",
|
|
18895
|
+
defaultAggregate: "mean",
|
|
18896
|
+
empty: "null",
|
|
18897
|
+
companions: [
|
|
18898
|
+
{
|
|
18899
|
+
fieldPath: "charging",
|
|
18900
|
+
expr: "\"unknown\""
|
|
18901
|
+
},
|
|
18902
|
+
{
|
|
18903
|
+
fieldPath: "sleeping",
|
|
18904
|
+
expr: "false"
|
|
18905
|
+
},
|
|
18906
|
+
{
|
|
18907
|
+
fieldPath: "lastUpdated",
|
|
18908
|
+
expr: "now"
|
|
18909
|
+
}
|
|
18910
|
+
]
|
|
18911
|
+
}),
|
|
18912
|
+
numeric({
|
|
18913
|
+
id: "numeric",
|
|
18914
|
+
summary: "A numeric reading in the members’ shared quantity. Mixed quantities are refused. Nobody reporting publishes null, not 0.",
|
|
18915
|
+
role: DeviceRole.NumericSensor,
|
|
18916
|
+
outputCap: "numeric-sensor",
|
|
18917
|
+
outputField: "value",
|
|
18918
|
+
quantity: "device",
|
|
18919
|
+
defaultAggregate: "mean",
|
|
18920
|
+
empty: "null",
|
|
18921
|
+
companions: [NOW]
|
|
18922
|
+
}),
|
|
18923
|
+
binary({
|
|
18924
|
+
id: "motion",
|
|
18925
|
+
summary: "Any or all motion. Offline and unknown members are left out, never read as off. Nobody reporting takes the device offline.",
|
|
18926
|
+
role: DeviceRole.MotionSensor,
|
|
18927
|
+
outputCap: "motion",
|
|
18928
|
+
outputField: "detected",
|
|
18929
|
+
defaultAggregate: "any",
|
|
18930
|
+
accept: [{
|
|
18931
|
+
cap: "motion",
|
|
18932
|
+
fieldPath: "detected"
|
|
18933
|
+
}],
|
|
18934
|
+
companions: [{
|
|
18935
|
+
fieldPath: "lastDetectedAt",
|
|
18936
|
+
expr: "null"
|
|
18937
|
+
}, {
|
|
18938
|
+
fieldPath: "autoClearAfterMs",
|
|
18939
|
+
expr: "null"
|
|
18940
|
+
}]
|
|
18941
|
+
}),
|
|
18942
|
+
binary({
|
|
18943
|
+
id: "contact",
|
|
18944
|
+
summary: "Any or all open contacts. Offline and unknown members are left out, never read as closed.",
|
|
18945
|
+
role: DeviceRole.ContactSensor,
|
|
18946
|
+
outputCap: "contact",
|
|
18947
|
+
outputField: "entryOpen",
|
|
18948
|
+
defaultAggregate: "any",
|
|
18949
|
+
accept: [{
|
|
18950
|
+
cap: "contact",
|
|
18951
|
+
fieldPath: "entryOpen"
|
|
18952
|
+
}],
|
|
18953
|
+
companions: [CHANGED]
|
|
18954
|
+
}),
|
|
18955
|
+
binary({
|
|
18956
|
+
id: "leak",
|
|
18957
|
+
summary: "Any or all leak detections. Offline and unknown members are left out, never read as dry.",
|
|
18958
|
+
role: DeviceRole.LeakSensor,
|
|
18959
|
+
outputCap: "flood",
|
|
18960
|
+
outputField: "flooded",
|
|
18961
|
+
defaultAggregate: "any",
|
|
18962
|
+
accept: [{
|
|
18963
|
+
cap: "flood",
|
|
18964
|
+
fieldPath: "flooded"
|
|
18965
|
+
}],
|
|
18966
|
+
companions: [CHANGED]
|
|
18967
|
+
}),
|
|
18968
|
+
binary({
|
|
18969
|
+
id: "smoke",
|
|
18970
|
+
summary: "Any or all smoke detections. Offline and unknown members are left out, never read as clear.",
|
|
18971
|
+
role: DeviceRole.SmokeSensor,
|
|
18972
|
+
outputCap: "smoke",
|
|
18973
|
+
outputField: "detected",
|
|
18974
|
+
defaultAggregate: "any",
|
|
18975
|
+
accept: [{
|
|
18976
|
+
cap: "smoke",
|
|
18977
|
+
fieldPath: "detected"
|
|
18978
|
+
}],
|
|
18979
|
+
companions: [CHANGED]
|
|
18980
|
+
}),
|
|
18981
|
+
binary({
|
|
18982
|
+
id: "occupancy",
|
|
18983
|
+
summary: "Any or all of motion or binary sensors, published as a binary. Presence zones are not aggregated. Nobody reporting is offline, not off.",
|
|
18984
|
+
role: DeviceRole.BinarySensor,
|
|
18985
|
+
outputCap: "binary",
|
|
18986
|
+
outputField: "on",
|
|
18987
|
+
defaultAggregate: "any",
|
|
18988
|
+
accept: [{
|
|
18989
|
+
cap: "motion",
|
|
18990
|
+
fieldPath: "detected"
|
|
18991
|
+
}, {
|
|
18992
|
+
cap: "binary",
|
|
18993
|
+
fieldPath: "on"
|
|
18994
|
+
}],
|
|
18995
|
+
companions: [CHANGED]
|
|
18996
|
+
}),
|
|
18997
|
+
binary({
|
|
18998
|
+
id: "binary",
|
|
18999
|
+
summary: "Any or all generic binary sensors. Offline and unknown members are left out, never read as off.",
|
|
19000
|
+
role: DeviceRole.BinarySensor,
|
|
19001
|
+
outputCap: "binary",
|
|
19002
|
+
outputField: "on",
|
|
19003
|
+
defaultAggregate: "any",
|
|
19004
|
+
accept: [{
|
|
19005
|
+
cap: "binary",
|
|
19006
|
+
fieldPath: "on"
|
|
19007
|
+
}],
|
|
19008
|
+
companions: [CHANGED]
|
|
19009
|
+
})
|
|
19010
|
+
];
|
|
19011
|
+
new Map(GROUP_TEMPLATES.map((template) => [template.id, template]));
|
|
18677
19012
|
`${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
|
|
18678
19013
|
/**
|
|
18679
19014
|
* What a composition may BUILD on a device type (G2, D676): the caps a new
|
|
@@ -20534,12 +20869,12 @@ function parseAdminBase(baseUrl) {
|
|
|
20534
20869
|
* providers detect renames by matching `uniqueId` and patch `id`
|
|
20535
20870
|
* in-place so dispatch keeps working.
|
|
20536
20871
|
*
|
|
20537
|
-
* **
|
|
20538
|
-
*
|
|
20539
|
-
*
|
|
20540
|
-
*
|
|
20541
|
-
* (`ha-domain-mapping`)
|
|
20542
|
-
* stored after that point.
|
|
20872
|
+
* **Display unit and precision are NOT stored here.** They are a read-time
|
|
20873
|
+
* preference (D944). A polymorphic reading stores its `quantity` here once,
|
|
20874
|
+
* at adopt, and a date/time value stores `dateTimeShape` the same way —
|
|
20875
|
+
* neither is repeated on each sample. The `device_class` tag is an
|
|
20876
|
+
* HA-specific input consumed at the discovery boundary (`ha-domain-mapping`)
|
|
20877
|
+
* to derive the CamStack `DeviceRole`; it is never stored after that point.
|
|
20543
20878
|
*
|
|
20544
20879
|
* The `raw` escape hatch carries provider-specific attributes that don't
|
|
20545
20880
|
* fit the structured slots (HA `attributes` whitelist, Reolink `deviceCache`
|
|
@@ -20553,6 +20888,14 @@ var SourceInfoSchema = object({
|
|
|
20553
20888
|
/** Immutable upstream identifier when available (HA `unique_id`, … ).
|
|
20554
20889
|
* Used to detect rename when `id` changes. */
|
|
20555
20890
|
uniqueId: string().optional(),
|
|
20891
|
+
/** Quantity of a polymorphic reading, written once at adopt (D944). */
|
|
20892
|
+
quantity: ReadingQuantitySchema.optional(),
|
|
20893
|
+
/** Date / time / datetime shape of a string reading, written once at adopt. */
|
|
20894
|
+
dateTimeShape: _enum([
|
|
20895
|
+
"date",
|
|
20896
|
+
"time",
|
|
20897
|
+
"datetime"
|
|
20898
|
+
]).optional(),
|
|
20556
20899
|
/** Provider-specific extras that don't fit the structured slots.
|
|
20557
20900
|
* Whitelist what goes here per provider — do NOT dump entire HA
|
|
20558
20901
|
* attribute blobs (would explode the meta JSON column). */
|
|
@@ -20637,9 +20980,38 @@ function normalizeUnit(raw) {
|
|
|
20637
20980
|
if (lower === "mph") return "mph";
|
|
20638
20981
|
if (lower === "m/s") return "m/s";
|
|
20639
20982
|
if (lower === "m") return "m";
|
|
20983
|
+
if (lower === "m²" || lower === "m2") return "m²";
|
|
20984
|
+
if (lower === "mm") return "mm";
|
|
20985
|
+
if (lower === "cm") return "cm";
|
|
20640
20986
|
if (lower === "km") return "km";
|
|
20987
|
+
if (lower === "in" || lower === "inch" || lower === "inches") return "in";
|
|
20988
|
+
if (lower === "ft" || lower === "foot" || lower === "feet") return "ft";
|
|
20641
20989
|
if (lower === "kg") return "kg";
|
|
20642
20990
|
if (lower === "g") return "g";
|
|
20991
|
+
if (lower === "l" || lower === "liter" || lower === "litre" || lower === "liters" || lower === "litres") return "L";
|
|
20992
|
+
if (lower === "ml") return "mL";
|
|
20993
|
+
if (lower === "gal" || lower === "gallon" || lower === "gallons") return "gal";
|
|
20994
|
+
if (lower === "s" || lower === "sec" || lower === "second" || lower === "seconds") return "s";
|
|
20995
|
+
if (lower === "ms") return "ms";
|
|
20996
|
+
if (lower === "min" || lower === "minute" || lower === "minutes") return "min";
|
|
20997
|
+
if (lower === "h" || lower === "hr" || lower === "hour" || lower === "hours") return "h";
|
|
20998
|
+
if (lower === "d" || lower === "day" || lower === "days") return "d";
|
|
20999
|
+
if (lower === "b" || lower === "byte" || lower === "bytes") return "B";
|
|
21000
|
+
if (lower === "kib") return "KiB";
|
|
21001
|
+
if (lower === "mib") return "MiB";
|
|
21002
|
+
if (lower === "gib") return "GiB";
|
|
21003
|
+
if (lower === "tib") return "TiB";
|
|
21004
|
+
if (lower === "kb") return "kB";
|
|
21005
|
+
if (lower === "mb") return "MB";
|
|
21006
|
+
if (lower === "gb") return "GB";
|
|
21007
|
+
if (lower === "dbm") return "dBm";
|
|
21008
|
+
if (lower === "dbfs") return "dBFS";
|
|
21009
|
+
if (lower === "inhg") return "inHg";
|
|
21010
|
+
if (lower === "mm/h") return "mm/h";
|
|
21011
|
+
if (lower === "w/m²" || lower === "w/m2") return "W/m²";
|
|
21012
|
+
if (lower === "°" || lower === "deg" || lower === "degree" || lower === "degrees") return "°";
|
|
21013
|
+
if (lower === "kbps") return "kbps";
|
|
21014
|
+
if (lower === "fps") return "fps";
|
|
20643
21015
|
return trimmed;
|
|
20644
21016
|
}
|
|
20645
21017
|
/**
|
|
@@ -41744,7 +42116,8 @@ method(object({
|
|
|
41744
42116
|
"enum"
|
|
41745
42117
|
]),
|
|
41746
42118
|
enumValues: array(string()).optional(),
|
|
41747
|
-
item: boolean().optional()
|
|
42119
|
+
item: boolean().optional(),
|
|
42120
|
+
quantity: ReadingQuantitySchema.optional()
|
|
41748
42121
|
})).readonly(),
|
|
41749
42122
|
itemArray: object({
|
|
41750
42123
|
path: string(),
|
|
@@ -45610,8 +45983,8 @@ var MaskPolygonShapeSchema = object({
|
|
|
45610
45983
|
/** Boolean cell grid — row-major, length === gridWidth*gridHeight. */
|
|
45611
45984
|
var MaskGridShapeSchema = object({
|
|
45612
45985
|
kind: literal("grid"),
|
|
45613
|
-
gridWidth: number(),
|
|
45614
|
-
gridHeight: number(),
|
|
45986
|
+
gridWidth: number().meta(readingMeta("none")),
|
|
45987
|
+
gridHeight: number().meta(readingMeta("none")),
|
|
45615
45988
|
cells: array(boolean())
|
|
45616
45989
|
});
|
|
45617
45990
|
discriminatedUnion("kind", [
|
|
@@ -57179,27 +57552,17 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
|
|
|
57179
57552
|
*/
|
|
57180
57553
|
var AirQualitySensorStatusSchema = object({
|
|
57181
57554
|
/** Carbon dioxide concentration in ppm. */
|
|
57182
|
-
co2Ppm: number().min(0).optional(),
|
|
57555
|
+
co2Ppm: number().min(0).optional().meta(readingMeta("concentration-volume")),
|
|
57183
57556
|
/** Total volatile organic compounds in ppb. */
|
|
57184
|
-
vocPpb: number().min(0).optional(),
|
|
57557
|
+
vocPpb: number().min(0).optional().meta(readingMeta("concentration-ppb")),
|
|
57185
57558
|
/** Particulate matter ≤ 2.5 μm in µg/m³. */
|
|
57186
|
-
pm25: number().min(0).optional(),
|
|
57559
|
+
pm25: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
57187
57560
|
/** Particulate matter ≤ 10 μm in µg/m³. */
|
|
57188
|
-
pm10: number().min(0).optional(),
|
|
57561
|
+
pm10: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
57189
57562
|
/** Composite AQI value (typically 0..500). */
|
|
57190
|
-
aqi: number().optional(),
|
|
57563
|
+
aqi: number().optional().meta(readingMeta("index")),
|
|
57191
57564
|
/** Ms epoch when the slice was last updated. */
|
|
57192
|
-
lastFetchedAt: number()
|
|
57193
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
57194
|
-
* `attributes.unit_of_measurement` → 'ppm' / 'ppb' / 'µg/m³'). Each
|
|
57195
|
-
* upstream `sensor.*` entity surfaces ONE device_class, so one unit
|
|
57196
|
-
* per slice is unambiguous. */
|
|
57197
|
-
unit: string().optional(),
|
|
57198
|
-
/** Suggested decimal places for numeric display.
|
|
57199
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
57200
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
57201
|
-
* auto-formatting when absent. */
|
|
57202
|
-
precision: number().int().min(0).max(10).optional()
|
|
57565
|
+
lastFetchedAt: number()
|
|
57203
57566
|
});
|
|
57204
57567
|
var airQualitySensorCapability = {
|
|
57205
57568
|
name: "air-quality-sensor",
|
|
@@ -57236,12 +57599,12 @@ var airQualitySensorCapability = {
|
|
|
57236
57599
|
},
|
|
57237
57600
|
pm25: {
|
|
57238
57601
|
kind: "gauge",
|
|
57239
|
-
unit: "
|
|
57602
|
+
unit: "µg/m³",
|
|
57240
57603
|
deadband: 1
|
|
57241
57604
|
},
|
|
57242
57605
|
pm10: {
|
|
57243
57606
|
kind: "gauge",
|
|
57244
|
-
unit: "
|
|
57607
|
+
unit: "µg/m³",
|
|
57245
57608
|
deadband: 1
|
|
57246
57609
|
},
|
|
57247
57610
|
aqi: {
|
|
@@ -57259,22 +57622,13 @@ var airQualitySensorCapability = {
|
|
|
57259
57622
|
* entries with `device_class: illuminance`.
|
|
57260
57623
|
*/
|
|
57261
57624
|
var AmbientLightSensorStatusSchema = object({
|
|
57262
|
-
/** Current illuminance in lux (lx). */
|
|
57263
|
-
lux: number().min(0).meta({
|
|
57264
|
-
|
|
57625
|
+
/** Current illuminance in lux (lx). `null` when the sample was refused (D393). */
|
|
57626
|
+
lux: number().min(0).nullable().meta(readingMeta("illuminance", {
|
|
57627
|
+
precision: 0,
|
|
57265
57628
|
label: "Illuminance"
|
|
57266
|
-
}),
|
|
57629
|
+
})),
|
|
57267
57630
|
/** Ms epoch when the slice was last updated. */
|
|
57268
|
-
lastFetchedAt: number()
|
|
57269
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
57270
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
57271
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
57272
|
-
unit: string().optional(),
|
|
57273
|
-
/** Suggested decimal places for numeric display.
|
|
57274
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
57275
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
57276
|
-
* auto-formatting when absent. */
|
|
57277
|
-
precision: number().int().min(0).max(10).optional()
|
|
57631
|
+
lastFetchedAt: number()
|
|
57278
57632
|
});
|
|
57279
57633
|
var ambientLightSensorCapability = {
|
|
57280
57634
|
name: "ambient-light-sensor",
|
|
@@ -57306,12 +57660,7 @@ var ambientLightSensorCapability = {
|
|
|
57306
57660
|
} } },
|
|
57307
57661
|
/** Clock fields: written, but excluded from the compare that decides
|
|
57308
57662
|
* whether persisting is worth a SQLite commit. */
|
|
57309
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
57310
|
-
customize: {
|
|
57311
|
-
version: 1,
|
|
57312
|
-
advanced: "derive",
|
|
57313
|
-
targets: []
|
|
57314
|
-
}
|
|
57663
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
57315
57664
|
};
|
|
57316
57665
|
/**
|
|
57317
57666
|
* Per-class audio metrics aggregated over a sliding window.
|
|
@@ -57538,10 +57887,7 @@ var BatteryStatusSchema = object({
|
|
|
57538
57887
|
* Consumers must SKIP a null rather than coerce it — `battery-band` already
|
|
57539
57888
|
* declines to band a non-finite reading, which is the correct shape.
|
|
57540
57889
|
*/
|
|
57541
|
-
percentage: number().min(0).max(100).nullable().meta({
|
|
57542
|
-
unit: "%",
|
|
57543
|
-
label: "Charge"
|
|
57544
|
-
}),
|
|
57890
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage", { label: "Charge" })),
|
|
57545
57891
|
/**
|
|
57546
57892
|
* Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
|
|
57547
57893
|
* Reolink-specific for the Solar Panel 2 accessory (will become
|
|
@@ -57568,7 +57914,14 @@ var BatteryStatusSchema = object({
|
|
|
57568
57914
|
*/
|
|
57569
57915
|
sleeping: boolean().meta({ label: "Sleeping" }),
|
|
57570
57916
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
57571
|
-
lastUpdated: number(),
|
|
57917
|
+
lastUpdated: number().meta(readingMeta("none")),
|
|
57918
|
+
/**
|
|
57919
|
+
* Battery voltage in volts, for a cell the firmware reports as voltage
|
|
57920
|
+
* rather than a percentage (Ecowitt capacitor packs). Absent on cameras
|
|
57921
|
+
* that only report charge. A second reading on this cap, not a second
|
|
57922
|
+
* `numeric-sensor` on the same device.
|
|
57923
|
+
*/
|
|
57924
|
+
volts: number().nullable().optional().meta(readingMeta("voltage", { label: "Voltage" })),
|
|
57572
57925
|
/**
|
|
57573
57926
|
* Ms epoch of the last time the device PROVED it was reachable — a
|
|
57574
57927
|
* completed firmware round-trip, an observed wake, or an inbound push
|
|
@@ -57620,7 +57973,6 @@ var BATTERY_DEVICE_TYPES = [
|
|
|
57620
57973
|
/** Generic Customize target for the percentage reading (D936). */
|
|
57621
57974
|
var batteryCustomize = {
|
|
57622
57975
|
version: 1,
|
|
57623
|
-
advanced: "derive",
|
|
57624
57976
|
targets: [{
|
|
57625
57977
|
id: "percentage",
|
|
57626
57978
|
cardinality: "scalar",
|
|
@@ -57629,7 +57981,7 @@ var batteryCustomize = {
|
|
|
57629
57981
|
stateField: "percentage"
|
|
57630
57982
|
},
|
|
57631
57983
|
deviceTypes: BATTERY_DEVICE_TYPES,
|
|
57632
|
-
apply: "add
|
|
57984
|
+
apply: "add",
|
|
57633
57985
|
path: "percentage",
|
|
57634
57986
|
sources: [{
|
|
57635
57987
|
kind: "field",
|
|
@@ -57750,10 +58102,16 @@ onStatusChanged: { data: object({
|
|
|
57750
58102
|
/**
|
|
57751
58103
|
* History (D850): recorded series. The generic capture replaces the `battery` series of `pipeline-analytics:stats-5m`.
|
|
57752
58104
|
*/
|
|
57753
|
-
history: { fields: {
|
|
57754
|
-
|
|
57755
|
-
|
|
57756
|
-
|
|
58105
|
+
history: { fields: {
|
|
58106
|
+
percentage: {
|
|
58107
|
+
kind: "gauge",
|
|
58108
|
+
unit: "%"
|
|
58109
|
+
},
|
|
58110
|
+
volts: {
|
|
58111
|
+
kind: "gauge",
|
|
58112
|
+
unit: "V"
|
|
58113
|
+
}
|
|
58114
|
+
} },
|
|
57757
58115
|
customize: batteryCustomize,
|
|
57758
58116
|
/** Clock fields: written, but excluded from the compare that decides
|
|
57759
58117
|
* whether persisting is worth a SQLite commit. */
|
|
@@ -57800,12 +58158,7 @@ var binaryCapability = {
|
|
|
57800
58158
|
history: { fields: { on: { kind: "boolean" } } },
|
|
57801
58159
|
/** Clock fields: written, but excluded from the compare that decides
|
|
57802
58160
|
* whether persisting is worth a SQLite commit. */
|
|
57803
|
-
volatileStateFields: ["lastChangedAt"]
|
|
57804
|
-
customize: {
|
|
57805
|
-
version: 1,
|
|
57806
|
-
advanced: "derive",
|
|
57807
|
-
targets: []
|
|
57808
|
-
}
|
|
58161
|
+
volatileStateFields: ["lastChangedAt"]
|
|
57809
58162
|
};
|
|
57810
58163
|
/**
|
|
57811
58164
|
* Dimmable-light brightness control. Co-exists with `switch` on the
|
|
@@ -57821,7 +58174,7 @@ var binaryCapability = {
|
|
|
57821
58174
|
*/
|
|
57822
58175
|
var BrightnessStatusSchema = object({
|
|
57823
58176
|
/** Current level as 0..100 inclusive. Firmware-reported. */
|
|
57824
|
-
percentage: number().min(0).max(100),
|
|
58177
|
+
percentage: number().min(0).max(100).meta(readingMeta("percentage")),
|
|
57825
58178
|
/** Ms epoch of the last operator-driven change. Useful for UI freshness. */
|
|
57826
58179
|
lastChangedAt: number()
|
|
57827
58180
|
});
|
|
@@ -58302,21 +58655,21 @@ var ClimateControlStatusSchema = object({
|
|
|
58302
58655
|
/** Single setpoint in Celsius. Used by single-target modes
|
|
58303
58656
|
* (heat / cool / dry). Null when the device is in a range mode
|
|
58304
58657
|
* (`heat_cool`) or has no setpoint at all (`fan_only`/`off`). */
|
|
58305
|
-
target: number().nullable(),
|
|
58658
|
+
target: number().nullable().meta(readingMeta("temperature")),
|
|
58306
58659
|
/** Upper bound of the dual setpoint in Celsius. Populated only
|
|
58307
58660
|
* in `heat_cool` mode. */
|
|
58308
|
-
targetHigh: number().nullable(),
|
|
58661
|
+
targetHigh: number().nullable().meta(readingMeta("temperature")),
|
|
58309
58662
|
/** Lower bound of the dual setpoint in Celsius. Populated only
|
|
58310
58663
|
* in `heat_cool` mode. */
|
|
58311
|
-
targetLow: number().nullable(),
|
|
58664
|
+
targetLow: number().nullable().meta(readingMeta("temperature")),
|
|
58312
58665
|
/** Target relative humidity (0..100). Null when the device has no
|
|
58313
58666
|
* humidity control. */
|
|
58314
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
58667
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
58315
58668
|
/** Current measured temperature in Celsius. Read-only — pushed by
|
|
58316
58669
|
* the device's internal sensor. */
|
|
58317
|
-
currentTemp: number().nullable(),
|
|
58670
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
58318
58671
|
/** Current measured relative humidity (0..100). Read-only. */
|
|
58319
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
58672
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
58320
58673
|
/** Vertical louver swing on/off. Null when the device has no vertical
|
|
58321
58674
|
* swing surface (gate with `DeviceFeature.ClimateSwingVertical`). */
|
|
58322
58675
|
swingVertical: boolean().nullable(),
|
|
@@ -58324,11 +58677,11 @@ var ClimateControlStatusSchema = object({
|
|
|
58324
58677
|
* horizontal swing surface (gate with `DeviceFeature.ClimateSwingHorizontal`). */
|
|
58325
58678
|
swingHorizontal: boolean().nullable(),
|
|
58326
58679
|
/** Lowest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
58327
|
-
minTemp: number().nullable().optional(),
|
|
58680
|
+
minTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
58328
58681
|
/** Highest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
58329
|
-
maxTemp: number().nullable().optional(),
|
|
58682
|
+
maxTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
58330
58683
|
/** Setpoint granularity, Celsius (0.5, 1). Absent / null = not reported. */
|
|
58331
|
-
tempStep: number().positive().nullable().optional(),
|
|
58684
|
+
tempStep: number().positive().nullable().optional().meta(readingMeta("temperature")),
|
|
58332
58685
|
/** Ms epoch when the slice was last updated (push or command). */
|
|
58333
58686
|
lastFetchedAt: number()
|
|
58334
58687
|
});
|
|
@@ -58470,17 +58823,17 @@ var climateControlCapability = {
|
|
|
58470
58823
|
* modes to expose in the picker without a slice fetch.
|
|
58471
58824
|
*/
|
|
58472
58825
|
var RgbTripletSchema = object({
|
|
58473
|
-
r: number().int().min(0).max(255),
|
|
58474
|
-
g: number().int().min(0).max(255),
|
|
58475
|
-
b: number().int().min(0).max(255)
|
|
58826
|
+
r: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
58827
|
+
g: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
58828
|
+
b: number().int().min(0).max(255).meta(readingMeta("none"))
|
|
58476
58829
|
});
|
|
58477
58830
|
var HsvTripletSchema = object({
|
|
58478
58831
|
/** Hue in degrees, 0..360. */
|
|
58479
|
-
h: number().min(0).max(360),
|
|
58832
|
+
h: number().min(0).max(360).meta(readingMeta("none")),
|
|
58480
58833
|
/** Saturation as 0..100 inclusive. */
|
|
58481
|
-
s: number().min(0).max(100),
|
|
58834
|
+
s: number().min(0).max(100).meta(readingMeta("none")),
|
|
58482
58835
|
/** Value/brightness as 0..100 inclusive. */
|
|
58483
|
-
v: number().min(0).max(100)
|
|
58836
|
+
v: number().min(0).max(100).meta(readingMeta("none"))
|
|
58484
58837
|
});
|
|
58485
58838
|
var ColorInputSchema = discriminatedUnion("mode", [
|
|
58486
58839
|
object({
|
|
@@ -58509,7 +58862,7 @@ var ColorStatusSchema = object({
|
|
|
58509
58862
|
/** Populated when `mode === 'hsv'`. */
|
|
58510
58863
|
hsv: HsvTripletSchema.optional(),
|
|
58511
58864
|
/** Populated when `mode === 'mired'`. */
|
|
58512
|
-
mireds: number().int().optional(),
|
|
58865
|
+
mireds: number().int().optional().meta(readingMeta("colour-temperature")),
|
|
58513
58866
|
/** Ms epoch of the last operator-driven change. */
|
|
58514
58867
|
lastChangedAt: number()
|
|
58515
58868
|
});
|
|
@@ -58718,18 +59071,12 @@ var FORM_OF_KIND = {
|
|
|
58718
59071
|
function consumableFormOf(item) {
|
|
58719
59072
|
return item.form ?? FORM_OF_KIND[consumableKindOf(item)];
|
|
58720
59073
|
}
|
|
58721
|
-
/**
|
|
58722
|
-
|
|
58723
|
-
|
|
58724
|
-
"days",
|
|
58725
|
-
"hours",
|
|
58726
|
-
"cycles"
|
|
58727
|
-
]);
|
|
58728
|
-
/** Remaining life as a COUNT, not a percentage (the PetKit desiccant reports
|
|
58729
|
-
* days). `value` null = unknown (D393). */
|
|
59074
|
+
/** Whether `remaining.value` is a duration in seconds or a dimensionless count. */
|
|
59075
|
+
var ConsumableRemainingKindSchema = _enum(["duration", "count"]);
|
|
59076
|
+
/** Remaining life. `value` null = unknown (D393). Duration is seconds. */
|
|
58730
59077
|
var ConsumableRemainingSchema = object({
|
|
58731
|
-
value: number().min(0).nullable(),
|
|
58732
|
-
|
|
59078
|
+
value: number().min(0).nullable().meta(readingMeta("device")),
|
|
59079
|
+
kind: ConsumableRemainingKindSchema
|
|
58733
59080
|
});
|
|
58734
59081
|
/** A single consumable item. Either a continuous `level` (remaining
|
|
58735
59082
|
* life %, or fill % for a `supply` / `waste` item) or a discrete `status`
|
|
@@ -58742,7 +59089,7 @@ var ConsumableItemSchema = object({
|
|
|
58742
59089
|
/** Display name. */
|
|
58743
59090
|
label: string().min(1),
|
|
58744
59091
|
/** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
|
|
58745
|
-
level: number().min(0).max(100).nullable(),
|
|
59092
|
+
level: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58746
59093
|
/** The provider's discrete verdict when known (binary mode). */
|
|
58747
59094
|
status: ConsumableStatusSchema.nullable(),
|
|
58748
59095
|
/** What the item is — decides whether low or full is bad. Absent = `wear`. */
|
|
@@ -58824,8 +59171,8 @@ var consumablesCustomize = {
|
|
|
58824
59171
|
transforms: [{ kind: "identity" }]
|
|
58825
59172
|
}],
|
|
58826
59173
|
literals: [{
|
|
58827
|
-
path: "remaining.
|
|
58828
|
-
values: [...
|
|
59174
|
+
path: "remaining.kind",
|
|
59175
|
+
values: [...ConsumableRemainingKindSchema.options]
|
|
58829
59176
|
}]
|
|
58830
59177
|
},
|
|
58831
59178
|
{
|
|
@@ -58954,7 +59301,6 @@ reset: method(object({
|
|
|
58954
59301
|
},
|
|
58955
59302
|
"remaining.value": {
|
|
58956
59303
|
kind: "gauge",
|
|
58957
|
-
unitFrom: "remaining.unit",
|
|
58958
59304
|
deadband: 1,
|
|
58959
59305
|
displayName: "Remaining"
|
|
58960
59306
|
}
|
|
@@ -59024,10 +59370,9 @@ var contactCapability = {
|
|
|
59024
59370
|
* (empty array for the other kinds). It lives in the slice because
|
|
59025
59371
|
* HA `select.*` entities may update their options at runtime.
|
|
59026
59372
|
*
|
|
59027
|
-
*
|
|
59028
|
-
*
|
|
59029
|
-
*
|
|
59030
|
-
* push — consistent with `options` and the sensor-unit approach.
|
|
59373
|
+
* Numeric `min` / `max` / `step` live in the slice and share the device
|
|
59374
|
+
* quantity (`SourceInfo.quantity`, D944). Display precision is a read-time
|
|
59375
|
+
* preference. A datetime control's shape is `SourceInfo.dateTimeShape`.
|
|
59031
59376
|
*/
|
|
59032
59377
|
var ControlStatusSchema = object({
|
|
59033
59378
|
kind: _enum([
|
|
@@ -59039,39 +59384,17 @@ var ControlStatusSchema = object({
|
|
|
59039
59384
|
/** Current value. Numeric kind → number; select/text/datetime → string.
|
|
59040
59385
|
* Datetime values are ISO 8601 strings (full timestamp, date-only,
|
|
59041
59386
|
* or time-only — HA accepts all three forms). */
|
|
59042
|
-
value: union([number(), string()]),
|
|
59387
|
+
value: union([number().meta(readingMeta("device")), string()]),
|
|
59043
59388
|
/** Acceptable values when `kind === 'select'`. Empty for other kinds. */
|
|
59044
59389
|
options: array(string()),
|
|
59045
59390
|
/** Ms epoch when the slice was last updated. */
|
|
59046
59391
|
lastChangedAt: number(),
|
|
59047
|
-
/**
|
|
59048
|
-
|
|
59049
|
-
|
|
59050
|
-
|
|
59051
|
-
/**
|
|
59052
|
-
|
|
59053
|
-
min: number().optional(),
|
|
59054
|
-
/** Maximum allowed value. Populated live from HA `attributes.max`.
|
|
59055
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
59056
|
-
max: number().optional(),
|
|
59057
|
-
/** Step increment. Populated live from HA `attributes.step`.
|
|
59058
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
59059
|
-
step: number().optional(),
|
|
59060
|
-
/** Suggested decimal places for numeric display. Populated live from HA
|
|
59061
|
-
* `attributes.suggested_display_precision`, or derived from `step` when the
|
|
59062
|
-
* HA attribute is absent. Meaningful for `kind === 'numeric'`; absent for
|
|
59063
|
-
* other kinds. Falls back to auto-formatting when absent. */
|
|
59064
|
-
precision: number().int().min(0).max(10).optional(),
|
|
59065
|
-
/** Date-picker granularity for `kind === 'datetime'`. 'date' → date-only,
|
|
59066
|
-
* 'time' → time-only, 'datetime' → full timestamp. Absent for other kinds
|
|
59067
|
-
* (UI defaults to 'datetime'). Derived live from the device's HA domain
|
|
59068
|
-
* (date.* / time.* / datetime.*) or, for input_datetime, from the entity's
|
|
59069
|
-
* `has_date`/`has_time` attributes on each push. */
|
|
59070
|
-
format: _enum([
|
|
59071
|
-
"date",
|
|
59072
|
-
"time",
|
|
59073
|
-
"datetime"
|
|
59074
|
-
]).optional()
|
|
59392
|
+
/** Minimum allowed value, in the device quantity's base unit. */
|
|
59393
|
+
min: number().optional().meta(readingMeta("device")),
|
|
59394
|
+
/** Maximum allowed value, in the device quantity's base unit. */
|
|
59395
|
+
max: number().optional().meta(readingMeta("device")),
|
|
59396
|
+
/** Step increment, in the device quantity's base unit. */
|
|
59397
|
+
step: number().optional().meta(readingMeta("device"))
|
|
59075
59398
|
});
|
|
59076
59399
|
var ControlSetValueInputSchema = discriminatedUnion("kind", [
|
|
59077
59400
|
object({
|
|
@@ -59137,9 +59460,9 @@ var CoverStatusSchema = object({
|
|
|
59137
59460
|
]),
|
|
59138
59461
|
/** 0 = fully closed, 100 = fully open. Null when the device has
|
|
59139
59462
|
* no intermediate position surface. */
|
|
59140
|
-
position: number().min(0).max(100).nullable(),
|
|
59463
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59141
59464
|
/** 0 = closed slats, 100 = open slats. Null when no tilt support. */
|
|
59142
|
-
tiltPosition: number().min(0).max(100).nullable(),
|
|
59465
|
+
tiltPosition: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59143
59466
|
/** Ms epoch when the slice was last updated. */
|
|
59144
59467
|
lastChangedAt: number()
|
|
59145
59468
|
});
|
|
@@ -59242,9 +59565,9 @@ var NormalizedRangeSchema$1 = object({
|
|
|
59242
59565
|
var DayNightStatusSchema = object({
|
|
59243
59566
|
mode: DayNightModeSchema,
|
|
59244
59567
|
/** IR-cut trigger sensitivity, NORMALIZED 0–100 (higher = switches to night sooner). */
|
|
59245
|
-
sensitivity: number().optional(),
|
|
59568
|
+
sensitivity: number().optional().meta(readingMeta("none")),
|
|
59246
59569
|
/** Delay before the IR-cut filter flips, in seconds. */
|
|
59247
|
-
switchDelaySec: number().optional(),
|
|
59570
|
+
switchDelaySec: number().optional().meta(readingMeta("duration")),
|
|
59248
59571
|
lastFetchedAt: number()
|
|
59249
59572
|
});
|
|
59250
59573
|
/**
|
|
@@ -59462,11 +59785,11 @@ var DishwasherStatusSchema = object({
|
|
|
59462
59785
|
/** Feature keys of the programs the appliance currently offers — drives the UI selector. */
|
|
59463
59786
|
availablePrograms: array(string()),
|
|
59464
59787
|
/** Seconds remaining on the active cycle, or null when not running / not known. */
|
|
59465
|
-
remainingSeconds: number().int().nonnegative().nullable(),
|
|
59788
|
+
remainingSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
59466
59789
|
/** Seconds the delayed start is set to (time until the cycle starts), or null. */
|
|
59467
|
-
delayedStartSeconds: number().int().nonnegative().nullable(),
|
|
59790
|
+
delayedStartSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
59468
59791
|
/** Cycle completion 0..100, or null when not applicable. */
|
|
59469
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
59792
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59470
59793
|
/** True when the door is reported open; null when the door state is not known. */
|
|
59471
59794
|
doorOpen: boolean().nullable(),
|
|
59472
59795
|
/** True when the door is latched (locked) during a cycle; null when not reported. */
|
|
@@ -59490,7 +59813,7 @@ var DishwasherStatusSchema = object({
|
|
|
59490
59813
|
/** True while the machine-care (descaling / cleaning-program) reminder is raised; false when clear; null when not reported. */
|
|
59491
59814
|
machineCareDue: boolean().nullable(),
|
|
59492
59815
|
/** Program runs left before the machine-care reminder is due; null when the appliance does not say. */
|
|
59493
|
-
machineCareRemainingRuns: number().int().nonnegative().nullable(),
|
|
59816
|
+
machineCareRemainingRuns: number().int().nonnegative().nullable().meta(readingMeta("count")),
|
|
59494
59817
|
/** Option states: null when the appliance does not expose the option or has not said. */
|
|
59495
59818
|
halfLoad: boolean().nullable(),
|
|
59496
59819
|
hygienePlus: boolean().nullable(),
|
|
@@ -59505,7 +59828,7 @@ var DishwasherStatusSchema = object({
|
|
|
59505
59828
|
/** Feature keys of the events currently raised (salt low, rinse aid low, program finished, …). */
|
|
59506
59829
|
activeEvents: array(string()),
|
|
59507
59830
|
/** Numeric error code when the appliance reports one; null otherwise. */
|
|
59508
|
-
errorCode: number().nullable(),
|
|
59831
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
59509
59832
|
/** Name of the raised alert-level event while the appliance is in error; null otherwise. */
|
|
59510
59833
|
errorLabel: string().nullable(),
|
|
59511
59834
|
/** Ms epoch of the last value received from the appliance; 0 = never. */
|
|
@@ -59736,7 +60059,7 @@ var DoorbellStatusSchema = object({
|
|
|
59736
60059
|
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
59737
60060
|
lastPressedAt: number().nullable(),
|
|
59738
60061
|
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
59739
|
-
pressCountSinceStart: number()
|
|
60062
|
+
pressCountSinceStart: number().meta(readingMeta("count"))
|
|
59740
60063
|
});
|
|
59741
60064
|
var DoorbellPressEventSchema = object({
|
|
59742
60065
|
deviceId: number(),
|
|
@@ -59819,12 +60142,11 @@ var EnumSensorDateTimeFormatSchema = _enum([
|
|
|
59819
60142
|
var EnumSensorStatusSchema = object({
|
|
59820
60143
|
value: string(),
|
|
59821
60144
|
/**
|
|
59822
|
-
* Set
|
|
59823
|
-
* as
|
|
59824
|
-
*
|
|
59825
|
-
* a time-only sensor → `'time'`.
|
|
60145
|
+
* Set when `value` is a timestamp rather than an enum state, so history
|
|
60146
|
+
* does not learn ISO strings as states. The display shape (date / time /
|
|
60147
|
+
* datetime) lives on `SourceInfo.dateTimeShape`, written once at adopt.
|
|
59826
60148
|
*/
|
|
59827
|
-
|
|
60149
|
+
timestamp: boolean().optional(),
|
|
59828
60150
|
/** Ms epoch when the slice was last updated. */
|
|
59829
60151
|
lastFetchedAt: number()
|
|
59830
60152
|
});
|
|
@@ -59851,11 +60173,11 @@ var enumSensorCapability = {
|
|
|
59851
60173
|
* History (D850): the value as an `enum` series (an appliance's program or
|
|
59852
60174
|
* operation state, an HVAC action). The option set is per device, so the
|
|
59853
60175
|
* value list is LEARNED as values are first seen (bounded). A sensor with a
|
|
59854
|
-
* `
|
|
60176
|
+
* `timestamp` carries a clock, not a state, and is not recorded.
|
|
59855
60177
|
*/
|
|
59856
60178
|
history: { fields: { value: {
|
|
59857
60179
|
kind: "enum",
|
|
59858
|
-
skipWhenSet: "
|
|
60180
|
+
skipWhenSet: "timestamp"
|
|
59859
60181
|
} } },
|
|
59860
60182
|
/** Clock fields: written, but excluded from the compare that decides
|
|
59861
60183
|
* whether persisting is worth a SQLite commit. */
|
|
@@ -59875,13 +60197,13 @@ var EventFireSchema = object({
|
|
|
59875
60197
|
deviceId: number(),
|
|
59876
60198
|
eventType: string(),
|
|
59877
60199
|
data: record(string(), unknown()).nullable(),
|
|
59878
|
-
timestamp: number(),
|
|
59879
|
-
seq: number()
|
|
60200
|
+
timestamp: number().meta(readingMeta("none")),
|
|
60201
|
+
seq: number().meta(readingMeta("count"))
|
|
59880
60202
|
});
|
|
59881
60203
|
var EventEmitterStatusSchema = object({
|
|
59882
60204
|
eventTypes: array(string()),
|
|
59883
60205
|
lastEvent: EventFireSchema.nullable(),
|
|
59884
|
-
eventCountSinceStart: number()
|
|
60206
|
+
eventCountSinceStart: number().meta(readingMeta("count"))
|
|
59885
60207
|
});
|
|
59886
60208
|
var eventEmitterCapability = {
|
|
59887
60209
|
name: "event-emitter",
|
|
@@ -60294,10 +60616,10 @@ var FanDirectionSchema = _enum(["forward", "reverse"]);
|
|
|
60294
60616
|
var FanControlStatusSchema = object({
|
|
60295
60617
|
/** Active speed as 0..100 inclusive. Null when the device has no
|
|
60296
60618
|
* speed surface (single-speed fan). */
|
|
60297
|
-
percentage: number().min(0).max(100).nullable(),
|
|
60619
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
60298
60620
|
/** Speed granularity the device accepts (HA `percentage_step`, e.g. 25 for
|
|
60299
60621
|
* a 4-speed fan). Absent when unknown — the UI then falls back to step 1. */
|
|
60300
|
-
percentageStep: number().positive().optional(),
|
|
60622
|
+
percentageStep: number().positive().optional().meta(readingMeta("percentage")),
|
|
60301
60623
|
/** Active preset mode (`auto` / `quiet` / `turbo` / vendor-specific)
|
|
60302
60624
|
* — empty string when no preset is active or supported. */
|
|
60303
60625
|
preset: string(),
|
|
@@ -60418,7 +60740,7 @@ var FeatureProbeStatusSchema = object({
|
|
|
60418
60740
|
/** Camera/firmware model string. `null` when the firmware doesn't expose it. */
|
|
60419
60741
|
model: string().nullable(),
|
|
60420
60742
|
/** Channel count for NVR/Hub devices; `1` for standalone cameras; `null` pre-probe. */
|
|
60421
|
-
channelCount: number().nullable(),
|
|
60743
|
+
channelCount: number().nullable().meta(readingMeta("count")),
|
|
60422
60744
|
/**
|
|
60423
60745
|
* Ms epoch of the last SUCCESSFUL probe. `0` before the first probe
|
|
60424
60746
|
* completes — drivers' `getAccessoryChildren()` should treat zero as
|
|
@@ -60541,9 +60863,54 @@ var gasCapability = {
|
|
|
60541
60863
|
* whether persisting is worth a SQLite commit. */
|
|
60542
60864
|
volatileStateFields: ["lastChangedAt"]
|
|
60543
60865
|
};
|
|
60866
|
+
/**
|
|
60867
|
+
* How many members of a helper group answered (D944). Counts are integers,
|
|
60868
|
+
* not measurements: zero included is a real count, never a stand-in reading.
|
|
60869
|
+
* The reading itself stays on the output capability. History is none — the
|
|
60870
|
+
* series that later statistics read is the output cap's own history block.
|
|
60871
|
+
*/
|
|
60872
|
+
var GroupStatusSchema = object({
|
|
60873
|
+
/** Members whose current value entered the aggregate. */
|
|
60874
|
+
included: number().int().nonnegative().meta(readingMeta("count", {
|
|
60875
|
+
precision: 0,
|
|
60876
|
+
label: "Reporting"
|
|
60877
|
+
})),
|
|
60878
|
+
/** Members left out: offline, unknown, or not a finite reading (D393). */
|
|
60879
|
+
excluded: number().int().nonnegative().meta(readingMeta("count", {
|
|
60880
|
+
precision: 0,
|
|
60881
|
+
label: "Excluded"
|
|
60882
|
+
})),
|
|
60883
|
+
/** `included` + `excluded`. */
|
|
60884
|
+
total: number().int().nonnegative().meta(readingMeta("count", {
|
|
60885
|
+
precision: 0,
|
|
60886
|
+
label: "Members"
|
|
60887
|
+
}))
|
|
60888
|
+
});
|
|
60889
|
+
var groupStatusCapability = {
|
|
60890
|
+
name: "group-status",
|
|
60891
|
+
scope: "device",
|
|
60892
|
+
deviceNative: true,
|
|
60893
|
+
mode: "singleton",
|
|
60894
|
+
deviceTypes: [DeviceType.Sensor],
|
|
60895
|
+
methods: {},
|
|
60896
|
+
status: {
|
|
60897
|
+
schema: GroupStatusSchema,
|
|
60898
|
+
kind: "push"
|
|
60899
|
+
},
|
|
60900
|
+
runtimeState: GroupStatusSchema,
|
|
60901
|
+
/**
|
|
60902
|
+
* Runtime-state durability: **session** — recomputed from members on the
|
|
60903
|
+
* next source event; a restored count would outlive the readings it named.
|
|
60904
|
+
*
|
|
60905
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
60906
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
60907
|
+
*/
|
|
60908
|
+
durability: "session",
|
|
60909
|
+
history: "none"
|
|
60910
|
+
};
|
|
60544
60911
|
var HeatingValveStatusSchema = object({
|
|
60545
60912
|
/** Radiator valve opening 0 (closed) .. 100 (open). Null = not yet known. */
|
|
60546
|
-
position: number().min(0).max(100).nullable(),
|
|
60913
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
60547
60914
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
60548
60915
|
lastFetchedAt: number()
|
|
60549
60916
|
});
|
|
@@ -60586,9 +60953,9 @@ var HumidifierStatusSchema = object({
|
|
|
60586
60953
|
/** Whether the humidifier is currently on. */
|
|
60587
60954
|
on: boolean(),
|
|
60588
60955
|
/** Current measured relative humidity (0..100). Null when not reported. */
|
|
60589
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
60956
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
60590
60957
|
/** Target relative humidity (0..100). Null when no setpoint surface. */
|
|
60591
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
60958
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
60592
60959
|
/** Active mode (`auto` / `normal` / `baby` / vendor). Null when the
|
|
60593
60960
|
* device has no mode surface. */
|
|
60594
60961
|
mode: string().nullable(),
|
|
@@ -60598,9 +60965,9 @@ var HumidifierStatusSchema = object({
|
|
|
60598
60965
|
* `idle` / `off`). Null when the device doesn't report it. */
|
|
60599
60966
|
action: string().nullable(),
|
|
60600
60967
|
/** HA `min_humidity` attribute. Null → UI uses 0. */
|
|
60601
|
-
minHumidity: number().nullable(),
|
|
60968
|
+
minHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
60602
60969
|
/** HA `max_humidity` attribute. Null → UI uses 100. */
|
|
60603
|
-
maxHumidity: number().nullable(),
|
|
60970
|
+
maxHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
60604
60971
|
/** Ms epoch when the slice was last updated. */
|
|
60605
60972
|
lastChangedAt: number()
|
|
60606
60973
|
});
|
|
@@ -60670,22 +61037,13 @@ var humidifierCapability = {
|
|
|
60670
61037
|
* `sourceInfo`.
|
|
60671
61038
|
*/
|
|
60672
61039
|
var HumiditySensorStatusSchema = object({
|
|
60673
|
-
/** Current relative humidity, 0..100. */
|
|
60674
|
-
percent: number().min(0).max(100).meta({
|
|
60675
|
-
|
|
61040
|
+
/** Current relative humidity, 0..100. `null` when the sample was refused (D393). */
|
|
61041
|
+
percent: number().min(0).max(100).nullable().meta(readingMeta("humidity", {
|
|
61042
|
+
precision: 0,
|
|
60676
61043
|
label: "Humidity"
|
|
60677
|
-
}),
|
|
61044
|
+
})),
|
|
60678
61045
|
/** Ms epoch when the slice was last updated. */
|
|
60679
|
-
lastFetchedAt: number()
|
|
60680
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
60681
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
60682
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
60683
|
-
unit: string().optional(),
|
|
60684
|
-
/** Suggested decimal places for numeric display.
|
|
60685
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
60686
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
60687
|
-
* auto-formatting when absent. */
|
|
60688
|
-
precision: number().int().min(0).max(10).optional()
|
|
61046
|
+
lastFetchedAt: number()
|
|
60689
61047
|
});
|
|
60690
61048
|
var humiditySensorCapability = {
|
|
60691
61049
|
name: "humidity-sensor",
|
|
@@ -60716,12 +61074,7 @@ var humiditySensorCapability = {
|
|
|
60716
61074
|
} } },
|
|
60717
61075
|
/** Clock fields: written, but excluded from the compare that decides
|
|
60718
61076
|
* whether persisting is worth a SQLite commit. */
|
|
60719
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
60720
|
-
customize: {
|
|
60721
|
-
version: 1,
|
|
60722
|
-
advanced: "derive",
|
|
60723
|
-
targets: []
|
|
60724
|
-
}
|
|
61077
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
60725
61078
|
};
|
|
60726
61079
|
/**
|
|
60727
61080
|
* Image display cap. Models a single still image exposed by an integration —
|
|
@@ -60742,7 +61095,7 @@ var ImageStatusSchema = object({
|
|
|
60742
61095
|
* entity exposes no `entity_picture` (yet). */
|
|
60743
61096
|
url: string().nullable(),
|
|
60744
61097
|
/** Ms epoch of the upstream last-updated timestamp. Null at cold-start. */
|
|
60745
|
-
lastUpdated: number().nullable()
|
|
61098
|
+
lastUpdated: number().nullable().meta(readingMeta("none"))
|
|
60746
61099
|
});
|
|
60747
61100
|
var imageCapability = {
|
|
60748
61101
|
name: "image",
|
|
@@ -60830,19 +61183,19 @@ var NormalizedRangeSchema = object({
|
|
|
60830
61183
|
*/
|
|
60831
61184
|
var ImageSettingsStatusSchema = object({
|
|
60832
61185
|
/** Normalized 0–100. */
|
|
60833
|
-
brightness: number().optional(),
|
|
61186
|
+
brightness: number().optional().meta(readingMeta("none")),
|
|
60834
61187
|
/** Normalized 0–100. */
|
|
60835
|
-
contrast: number().optional(),
|
|
61188
|
+
contrast: number().optional().meta(readingMeta("none")),
|
|
60836
61189
|
/** Normalized 0–100. */
|
|
60837
|
-
saturation: number().optional(),
|
|
61190
|
+
saturation: number().optional().meta(readingMeta("none")),
|
|
60838
61191
|
/** Normalized 0–100. */
|
|
60839
|
-
sharpness: number().optional(),
|
|
61192
|
+
sharpness: number().optional().meta(readingMeta("none")),
|
|
60840
61193
|
mirror: boolean().optional(),
|
|
60841
61194
|
flip: boolean().optional(),
|
|
60842
61195
|
rotate: ImageRotateSchema.optional(),
|
|
60843
61196
|
whiteBalance: WhiteBalanceModeSchema.optional(),
|
|
60844
61197
|
/** Manual white-balance warmth, NORMALIZED 0–100. Meaningful only when `whiteBalance === 'manual'`. */
|
|
60845
|
-
warmth: number().optional(),
|
|
61198
|
+
warmth: number().optional().meta(readingMeta("none")),
|
|
60846
61199
|
exposureMode: ExposureModeSchema.optional(),
|
|
60847
61200
|
backlightMode: BacklightModeSchema.optional(),
|
|
60848
61201
|
lastFetchedAt: number()
|
|
@@ -61121,10 +61474,10 @@ var IntercomAbilitySchema = object({
|
|
|
61121
61474
|
/** Codecs accepted by firmware, in preference order. Driver-authored strings. */
|
|
61122
61475
|
codecs: array(string()),
|
|
61123
61476
|
/** Sample rate (Hz) the firmware expects. Reolink typical: 16000. */
|
|
61124
|
-
sampleRate: number(),
|
|
61477
|
+
sampleRate: number().meta(readingMeta("none")),
|
|
61125
61478
|
duplex: _enum(["half", "full"]),
|
|
61126
61479
|
/** Max in-flight audio backlog before drop (ms). Server uses this to bound latency. */
|
|
61127
|
-
maxBacklogMs: number()
|
|
61480
|
+
maxBacklogMs: number().meta(readingMeta("duration-ms"))
|
|
61128
61481
|
});
|
|
61129
61482
|
var IntercomStatusSchema = object({
|
|
61130
61483
|
/** True while a talk session is open. */
|
|
@@ -61351,13 +61704,13 @@ var LawnMowerControlStatusSchema = object({
|
|
|
61351
61704
|
activity: LawnMowerActivitySchema,
|
|
61352
61705
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
61353
61706
|
* reading. */
|
|
61354
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
61707
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61355
61708
|
/** 0..100 mowing-completion percentage of the current task, or null when no
|
|
61356
61709
|
* task is active / progress is unavailable. */
|
|
61357
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
61710
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61358
61711
|
/** Current device/event code (dynamic — mostly status, sometimes an error),
|
|
61359
61712
|
* or null when unknown. */
|
|
61360
|
-
currentCode: number().nullable(),
|
|
61713
|
+
currentCode: number().nullable().meta(readingMeta("none")),
|
|
61361
61714
|
/** Human label for {@link currentCode}, or null when undecodable. */
|
|
61362
61715
|
currentCodeLabel: string().nullable(),
|
|
61363
61716
|
/** Severity of {@link currentCode}. `error` (and often `warning`) warrants UI
|
|
@@ -61890,7 +62243,7 @@ var MediaPlayerStatusSchema = object({
|
|
|
61890
62243
|
state: MediaPlayerStateSchema,
|
|
61891
62244
|
/** Volume as 0..100 inclusive. Null when the device has no volume
|
|
61892
62245
|
* surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
|
|
61893
|
-
volumeLevel: number().min(0).max(100).nullable(),
|
|
62246
|
+
volumeLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61894
62247
|
/** Mute toggle distinct from volume=0. Null when no mute surface.
|
|
61895
62248
|
* Pair with `DeviceFeature.MediaPlayerMute`. */
|
|
61896
62249
|
isMuted: boolean().nullable(),
|
|
@@ -61903,10 +62256,10 @@ var MediaPlayerStatusSchema = object({
|
|
|
61903
62256
|
currentMedia: MediaInfoSchema.nullable(),
|
|
61904
62257
|
/** Current playback position in ms. Null when not seekable or
|
|
61905
62258
|
* nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
|
|
61906
|
-
positionMs: number().int().nonnegative().nullable(),
|
|
62259
|
+
positionMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
61907
62260
|
/** Total duration of the current media in ms. Null when unknown
|
|
61908
62261
|
* (live stream) or nothing is playing. */
|
|
61909
|
-
durationMs: number().int().nonnegative().nullable(),
|
|
62262
|
+
durationMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
61910
62263
|
/** Shuffle toggle. Null when no shuffle surface.
|
|
61911
62264
|
* Pair with `DeviceFeature.MediaPlayerShuffle`. */
|
|
61912
62265
|
shuffle: boolean().nullable(),
|
|
@@ -62215,7 +62568,7 @@ var motionCustomize = {
|
|
|
62215
62568
|
eventName: "onMotionChanged"
|
|
62216
62569
|
},
|
|
62217
62570
|
deviceTypes: [DeviceType.Camera],
|
|
62218
|
-
apply: "
|
|
62571
|
+
apply: "add",
|
|
62219
62572
|
applyAuthority: {
|
|
62220
62573
|
kind: "camera-sensors",
|
|
62221
62574
|
timeoutField: "motionCooldownMs"
|
|
@@ -62287,7 +62640,7 @@ var MotionStatusSchema = object({
|
|
|
62287
62640
|
* it, every provider seeded it at boot, and every session left it
|
|
62288
62641
|
* `detected: true` after its detach.
|
|
62289
62642
|
*/
|
|
62290
|
-
autoClearAfterMs: number().nullable()
|
|
62643
|
+
autoClearAfterMs: number().nullable().meta(readingMeta("duration-ms"))
|
|
62291
62644
|
});
|
|
62292
62645
|
/**
|
|
62293
62646
|
* Payload of `motion.onMotionChanged` event + the corresponding bus
|
|
@@ -62324,12 +62677,18 @@ var motionCapability = {
|
|
|
62324
62677
|
methods: {
|
|
62325
62678
|
/**
|
|
62326
62679
|
* Pull the current motion state synchronously. Convenience shortcut
|
|
62327
|
-
* for consumers that don't need the full status object
|
|
62328
|
-
*
|
|
62329
|
-
* `getStatus` once the auto-injected status surface lands in every
|
|
62330
|
-
* consumer.
|
|
62680
|
+
* for consumers that don't need the full status object. A composed
|
|
62681
|
+
* group answers from its slice (D944): unknown throws, it is not off.
|
|
62331
62682
|
*/
|
|
62332
62683
|
isDetected: method(object({ deviceId: number() }), boolean()) },
|
|
62684
|
+
/**
|
|
62685
|
+
* A composed motion group serves `isDetected` from `detected` (D944).
|
|
62686
|
+
* Without this the cap stays uncomposable (`has-commands`).
|
|
62687
|
+
*/
|
|
62688
|
+
composedMethods: { isDetected: {
|
|
62689
|
+
kind: "slice",
|
|
62690
|
+
field: "detected"
|
|
62691
|
+
} },
|
|
62333
62692
|
events: {
|
|
62334
62693
|
/**
|
|
62335
62694
|
* Fires every time the runner transitions a camera between
|
|
@@ -62469,7 +62828,7 @@ var MotionZoneRegionSchema = object({
|
|
|
62469
62828
|
* the grid region(s). */
|
|
62470
62829
|
var MotionZoneStatusSchema = object({
|
|
62471
62830
|
enabled: boolean(),
|
|
62472
|
-
sensitivity: number(),
|
|
62831
|
+
sensitivity: number().meta(readingMeta("none")),
|
|
62473
62832
|
/** Grid region(s). Today exactly one `grid` shape. */
|
|
62474
62833
|
regions: array(MotionZoneRegionSchema),
|
|
62475
62834
|
lastFetchedAt: number()
|
|
@@ -62839,7 +63198,7 @@ var NavigationStatusSchema = object({
|
|
|
62839
63198
|
following: boolean(),
|
|
62840
63199
|
flash: boolean(),
|
|
62841
63200
|
lightMode: NavigationLightModeSchema,
|
|
62842
|
-
lightLevel: number().min(40).max(100),
|
|
63201
|
+
lightLevel: number().min(40).max(100).meta(readingMeta("none")),
|
|
62843
63202
|
/** Ms epoch when the slice was last updated. */
|
|
62844
63203
|
lastChangedAt: number()
|
|
62845
63204
|
});
|
|
@@ -62973,13 +63332,13 @@ var NetworkLinkStatusSchema = object({
|
|
|
62973
63332
|
* one whose reading has not landed must not be drawn at 0 %. Consumers
|
|
62974
63333
|
* SKIP a null rather than coerce it.
|
|
62975
63334
|
*/
|
|
62976
|
-
signalPercent: number().min(0).max(100).nullable(),
|
|
63335
|
+
signalPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
62977
63336
|
/** Raw received signal strength in dBm, when the firmware reports one. */
|
|
62978
|
-
rssiDbm: number().optional(),
|
|
63337
|
+
rssiDbm: number().optional().meta(readingMeta("signal-level")),
|
|
62979
63338
|
/** Network name of a wireless link, when the firmware reports it. */
|
|
62980
63339
|
ssid: string().optional(),
|
|
62981
63340
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
62982
|
-
lastUpdated: number()
|
|
63341
|
+
lastUpdated: number().meta(readingMeta("none"))
|
|
62983
63342
|
});
|
|
62984
63343
|
var networkLinkCapability = {
|
|
62985
63344
|
name: "network-link",
|
|
@@ -63364,7 +63723,7 @@ var NotifierStatusSchema = object({
|
|
|
63364
63723
|
lastError: string().nullable(),
|
|
63365
63724
|
/** Number of deliveries currently buffered server-side (rate-limited
|
|
63366
63725
|
* notifiers may queue). 0 when the provider sends synchronously. */
|
|
63367
|
-
queueDepth: number().int().nonnegative(),
|
|
63726
|
+
queueDepth: number().int().nonnegative().meta(readingMeta("count")),
|
|
63368
63727
|
/** Per-feature capability matrix — authoritative source for the
|
|
63369
63728
|
* compose-form field gating. */
|
|
63370
63729
|
supports: NotifierSupportsSchema
|
|
@@ -63456,11 +63815,9 @@ onSent: { data: object({
|
|
|
63456
63815
|
* cap fits (HA `sensor` whose `device_class` we don't have a typed cap
|
|
63457
63816
|
* for: water flow, distance, weight, frequency, signal strength, …).
|
|
63458
63817
|
*
|
|
63459
|
-
* The
|
|
63460
|
-
*
|
|
63461
|
-
*
|
|
63462
|
-
* The UI reads them directly from the slice — they are the single source
|
|
63463
|
-
* of truth for generic numeric rendering and do NOT live on `sourceInfo`.
|
|
63818
|
+
* The quantity is not on this slice. It is chosen when the device is
|
|
63819
|
+
* adopted and stored once on `SourceInfo.quantity` (D944). `value` is in
|
|
63820
|
+
* that quantity's base unit. `null` is a refused sample (D393).
|
|
63464
63821
|
*
|
|
63465
63822
|
* Prefer the typed alternatives (`temperature-sensor`, `humidity-sensor`,
|
|
63466
63823
|
* `ambient-light-sensor`, `pressure-sensor`, `power-meter`,
|
|
@@ -63469,15 +63826,8 @@ onSent: { data: object({
|
|
|
63469
63826
|
* numeric values land here.
|
|
63470
63827
|
*/
|
|
63471
63828
|
var NumericSensorStatusSchema = object({
|
|
63472
|
-
|
|
63473
|
-
|
|
63474
|
-
* Populated live from the upstream source on each state push.
|
|
63475
|
-
* Absent for unitless sensors. */
|
|
63476
|
-
unit: string().optional(),
|
|
63477
|
-
/** Suggested decimal places for numeric display.
|
|
63478
|
-
* Populated live from the upstream source when provided.
|
|
63479
|
-
* Falls back to auto-formatting when absent. */
|
|
63480
|
-
precision: number().int().min(0).max(10).optional(),
|
|
63829
|
+
/** Reading in the device quantity's base unit. `null` when refused (D393). */
|
|
63830
|
+
value: number().nullable().meta(readingMeta("device")),
|
|
63481
63831
|
/** Ms epoch when the slice was last updated. */
|
|
63482
63832
|
lastFetchedAt: number()
|
|
63483
63833
|
});
|
|
@@ -63501,11 +63851,11 @@ var numericSensorCapability = {
|
|
|
63501
63851
|
*/
|
|
63502
63852
|
durability: "restored",
|
|
63503
63853
|
/**
|
|
63504
|
-
* History (D850): recorded series. The unit is
|
|
63854
|
+
* History (D850): recorded series. The unit is the device quantity's base,
|
|
63855
|
+
* resolved when the series is read — the cap has no single unit.
|
|
63505
63856
|
*/
|
|
63506
63857
|
history: { fields: { value: {
|
|
63507
63858
|
kind: "gauge",
|
|
63508
|
-
unitFrom: "unit",
|
|
63509
63859
|
minIntervalMs: 3e4
|
|
63510
63860
|
} } },
|
|
63511
63861
|
/** Clock fields: written, but excluded from the compare that decides
|
|
@@ -63797,23 +64147,26 @@ var PetFeederStatusSchema = object({
|
|
|
63797
64147
|
/** Food currently in the bowl (grams). Null when the device has not
|
|
63798
64148
|
* reported a reading yet. On dual-hopper models this is the combined
|
|
63799
64149
|
* bowl reading; per-hopper levels live in `food1`/`food2`. */
|
|
63800
|
-
foodLevel: number().nullable(),
|
|
64150
|
+
foodLevel: number().nullable().meta(readingMeta("none")),
|
|
63801
64151
|
/** Hopper-1 food level (grams) on dual-hopper feeders; null on
|
|
63802
64152
|
* single-hopper models. */
|
|
63803
|
-
food1: number().nullable(),
|
|
64153
|
+
food1: number().nullable().meta(readingMeta("none")),
|
|
63804
64154
|
/** Hopper-2 food level (grams) on dual-hopper feeders; null on
|
|
63805
64155
|
* single-hopper models. */
|
|
63806
|
-
food2: number().nullable(),
|
|
64156
|
+
food2: number().nullable().meta(readingMeta("none")),
|
|
63807
64157
|
/** Derived low-food flag — mirrors the HA `food_level` binary_sensor
|
|
63808
64158
|
* (`device_class: problem`, on = low). True when the bowl is empty /
|
|
63809
64159
|
* below the feeder's low threshold. */
|
|
63810
64160
|
lowFood: boolean(),
|
|
63811
64161
|
/** Battery charge 0..100 (%). Null on mains-powered models or when the
|
|
63812
64162
|
* device has no battery reading. */
|
|
63813
|
-
batteryPower: number().min(0).max(100).nullable(),
|
|
63814
|
-
/**
|
|
63815
|
-
*
|
|
63816
|
-
|
|
64163
|
+
batteryPower: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
64164
|
+
/**
|
|
64165
|
+
* Desiccant life remaining, stored in seconds (duration base, D944).
|
|
64166
|
+
* Providers convert from the days the feeder reports. Null when the
|
|
64167
|
+
* model has no desiccant sensor.
|
|
64168
|
+
*/
|
|
64169
|
+
desiccantLeftDays: number().nullable().meta(readingMeta("duration")),
|
|
63817
64170
|
/** True while a feed is in progress. */
|
|
63818
64171
|
feeding: boolean(),
|
|
63819
64172
|
/** Decoded connectivity / power status (HA petkit device-status enum).
|
|
@@ -63824,7 +64177,7 @@ var PetFeederStatusSchema = object({
|
|
|
63824
64177
|
* with `errorCode` for consumers that want the raw integer. */
|
|
63825
64178
|
error: string().nullable(),
|
|
63826
64179
|
/** Raw device error code (0 / null = no error). */
|
|
63827
|
-
errorCode: number().nullable(),
|
|
64180
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
63828
64181
|
/** True for D4S/D4SH dual-hopper hardware — gates the per-hopper UI. */
|
|
63829
64182
|
isDualHopper: boolean(),
|
|
63830
64183
|
/** Child-lock (manual-lock) setting — buttons on the unit are disabled. */
|
|
@@ -63834,7 +64187,7 @@ var PetFeederStatusSchema = object({
|
|
|
63834
64187
|
/** Play a chime when dispensing. */
|
|
63835
64188
|
feedSound: boolean(),
|
|
63836
64189
|
/** Speaker / prompt volume level (device-scaled integer). */
|
|
63837
|
-
volume: number(),
|
|
64190
|
+
volume: number().meta(readingMeta("none")),
|
|
63838
64191
|
/** Ms epoch when the slice was last refreshed from the cloud. */
|
|
63839
64192
|
lastFetchedAt: number()
|
|
63840
64193
|
});
|
|
@@ -63953,7 +64306,7 @@ var petFeederCapability = {
|
|
|
63953
64306
|
},
|
|
63954
64307
|
desiccantLeftDays: {
|
|
63955
64308
|
kind: "gauge",
|
|
63956
|
-
unit: "
|
|
64309
|
+
unit: "s"
|
|
63957
64310
|
}
|
|
63958
64311
|
} }
|
|
63959
64312
|
};
|
|
@@ -64354,36 +64707,19 @@ method(_void(), PlatformCapabilitiesSchema), method(_void(), HardwareInfoSchema)
|
|
|
64354
64707
|
*/
|
|
64355
64708
|
var PowerMeterStatusSchema = object({
|
|
64356
64709
|
/** Instantaneous power draw in watts. */
|
|
64357
|
-
watts: number().optional().meta({
|
|
64358
|
-
unit: "W",
|
|
64359
|
-
label: "Power"
|
|
64360
|
-
}),
|
|
64710
|
+
watts: number().optional().meta(readingMeta("power", { label: "Power" })),
|
|
64361
64711
|
/** Cumulative energy in kilowatt-hours since the meter was reset. */
|
|
64362
|
-
kwhTotal: number().optional().meta({
|
|
64363
|
-
unit: "kWh",
|
|
64364
|
-
label: "Energy"
|
|
64365
|
-
}),
|
|
64712
|
+
kwhTotal: number().optional().meta(readingMeta("energy", { label: "Energy" })),
|
|
64366
64713
|
/** Voltage in volts. */
|
|
64367
|
-
volts: number().optional(),
|
|
64714
|
+
volts: number().optional().meta(readingMeta("voltage")),
|
|
64368
64715
|
/** Current in amperes. */
|
|
64369
|
-
amps: number().optional(),
|
|
64370
|
-
/** Apparent power in volt-amperes
|
|
64371
|
-
va: number().optional(),
|
|
64716
|
+
amps: number().optional().meta(readingMeta("current")),
|
|
64717
|
+
/** Apparent power in volt-amperes. */
|
|
64718
|
+
va: number().optional().meta(readingMeta("apparent-power")),
|
|
64372
64719
|
/** Power factor (0..1) if reported. */
|
|
64373
|
-
powerFactor: number().min(0).max(1).optional(),
|
|
64720
|
+
powerFactor: number().min(0).max(1).optional().meta(readingMeta("ratio")),
|
|
64374
64721
|
/** Ms epoch when the slice was last updated. */
|
|
64375
|
-
lastFetchedAt: number()
|
|
64376
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
64377
|
-
* `attributes.unit_of_measurement` → 'V' / 'A' / 'W' / 'kW' / 'kWh').
|
|
64378
|
-
* Each upstream `sensor.*` entity surfaces ONE device_class, so one
|
|
64379
|
-
* unit per slice is unambiguous. The UI prefers this over the role's
|
|
64380
|
-
* canonical unit so a 'kW' / 'Wh' feed renders verbatim. */
|
|
64381
|
-
unit: string().optional(),
|
|
64382
|
-
/** Suggested decimal places for numeric display.
|
|
64383
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
64384
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
64385
|
-
* auto-formatting when absent. */
|
|
64386
|
-
precision: number().int().min(0).max(10).optional()
|
|
64722
|
+
lastFetchedAt: number()
|
|
64387
64723
|
});
|
|
64388
64724
|
var powerMeterCapability = {
|
|
64389
64725
|
name: "power-meter",
|
|
@@ -64447,12 +64783,7 @@ var powerMeterCapability = {
|
|
|
64447
64783
|
} },
|
|
64448
64784
|
/** Clock fields: written, but excluded from the compare that decides
|
|
64449
64785
|
* whether persisting is worth a SQLite commit. */
|
|
64450
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
64451
|
-
customize: {
|
|
64452
|
-
version: 1,
|
|
64453
|
-
advanced: "derive",
|
|
64454
|
-
targets: []
|
|
64455
|
-
}
|
|
64786
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
64456
64787
|
};
|
|
64457
64788
|
/**
|
|
64458
64789
|
* Presence cap. Models HA `person.*` and `device_tracker.*` entities
|
|
@@ -64472,11 +64803,11 @@ var powerMeterCapability = {
|
|
|
64472
64803
|
*/
|
|
64473
64804
|
var GpsLocationSchema = object({
|
|
64474
64805
|
/** Latitude in decimal degrees, -90..90. */
|
|
64475
|
-
latitude: number().min(-90).max(90),
|
|
64806
|
+
latitude: number().min(-90).max(90).meta(readingMeta("angle")),
|
|
64476
64807
|
/** Longitude in decimal degrees, -180..180. */
|
|
64477
|
-
longitude: number().min(-180).max(180),
|
|
64808
|
+
longitude: number().min(-180).max(180).meta(readingMeta("angle")),
|
|
64478
64809
|
/** Reported accuracy in meters (lower = better). */
|
|
64479
|
-
accuracyMeters: number().nonnegative()
|
|
64810
|
+
accuracyMeters: number().nonnegative().meta(readingMeta("length"))
|
|
64480
64811
|
});
|
|
64481
64812
|
var PresenceStatusSchema = object({
|
|
64482
64813
|
/** `home` / `not_home` / any user-defined zone name. */
|
|
@@ -64488,7 +64819,7 @@ var PresenceStatusSchema = object({
|
|
|
64488
64819
|
gps: GpsLocationSchema.nullable(),
|
|
64489
64820
|
/** Optional battery level of the tracking device (0..100). Null
|
|
64490
64821
|
* when not reported. */
|
|
64491
|
-
batteryPercent: number().min(0).max(100).nullable(),
|
|
64822
|
+
batteryPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
64492
64823
|
/** Ms epoch when the slice was last updated. */
|
|
64493
64824
|
lastChangedAt: number()
|
|
64494
64825
|
});
|
|
@@ -64538,19 +64869,10 @@ var presenceCapability = {
|
|
|
64538
64869
|
* `sourceInfo`.
|
|
64539
64870
|
*/
|
|
64540
64871
|
var PressureSensorStatusSchema = object({
|
|
64541
|
-
/** Current pressure in hPa. */
|
|
64542
|
-
hpa: number(),
|
|
64872
|
+
/** Current pressure in hPa. `null` when the sample was refused (D393). */
|
|
64873
|
+
hpa: number().nullable().meta(readingMeta("pressure", { precision: 0 })),
|
|
64543
64874
|
/** Ms epoch when the slice was last updated. */
|
|
64544
|
-
lastFetchedAt: number()
|
|
64545
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
64546
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
64547
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
64548
|
-
unit: string().optional(),
|
|
64549
|
-
/** Suggested decimal places for numeric display.
|
|
64550
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
64551
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
64552
|
-
* auto-formatting when absent. */
|
|
64553
|
-
precision: number().int().min(0).max(10).optional()
|
|
64875
|
+
lastFetchedAt: number()
|
|
64554
64876
|
});
|
|
64555
64877
|
var pressureSensorCapability = {
|
|
64556
64878
|
name: "pressure-sensor",
|
|
@@ -64964,8 +65286,8 @@ DeviceType.Camera, method(PtzMoveCommandSchema.extend({ deviceId: number() }), _
|
|
|
64964
65286
|
}), _void(), { kind: "mutation" });
|
|
64965
65287
|
var PtzAutotrackSettingsSchema = object({
|
|
64966
65288
|
targetType: string().describe("Vendor target string (people/vehicle/pet); empty = camera default"),
|
|
64967
|
-
stopDelaySeconds: number().int().min(0).max(300),
|
|
64968
|
-
disappearDelaySeconds: number().int().min(0).max(300)
|
|
65289
|
+
stopDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration")),
|
|
65290
|
+
disappearDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration"))
|
|
64969
65291
|
});
|
|
64970
65292
|
/**
|
|
64971
65293
|
* One option the camera advertises as a valid `targetType`. Drivers
|
|
@@ -65127,7 +65449,7 @@ var RunningStateStatusSchema = object({
|
|
|
65127
65449
|
/** null = unknown — never coerced to false (D393). */
|
|
65128
65450
|
running: boolean().nullable(),
|
|
65129
65451
|
/** Epoch ms the current boolean began; null while `running` is null. */
|
|
65130
|
-
since: number().nullable(),
|
|
65452
|
+
since: number().nullable().meta(readingMeta("none")),
|
|
65131
65453
|
source: RunningStateSourceSchema.meta({ label: "Source" }),
|
|
65132
65454
|
phase: string().nullable(),
|
|
65133
65455
|
/** null until a reading has been published (D393). */
|
|
@@ -65142,7 +65464,6 @@ var RUNNING_DEVICE_TYPES = Object.values(DeviceType);
|
|
|
65142
65464
|
/** Generic Customize target for the running boolean (D936). */
|
|
65143
65465
|
var runningCustomize = {
|
|
65144
65466
|
version: 1,
|
|
65145
|
-
advanced: "derive",
|
|
65146
65467
|
targets: [{
|
|
65147
65468
|
id: "running",
|
|
65148
65469
|
cardinality: "scalar",
|
|
@@ -65162,7 +65483,7 @@ var runningCustomize = {
|
|
|
65162
65483
|
DeviceType.Thermostat,
|
|
65163
65484
|
DeviceType.PetFeeder
|
|
65164
65485
|
],
|
|
65165
|
-
apply: "add
|
|
65486
|
+
apply: "add",
|
|
65166
65487
|
path: "running",
|
|
65167
65488
|
sources: [
|
|
65168
65489
|
{
|
|
@@ -66426,9 +66747,9 @@ var RecordTriggerSchema = _enum([
|
|
|
66426
66747
|
*/
|
|
66427
66748
|
var RecordWindowSchema = object({
|
|
66428
66749
|
trigger: RecordTriggerSchema,
|
|
66429
|
-
day: number().int().min(0).max(6),
|
|
66430
|
-
startMinute: number().int().min(0).max(1439),
|
|
66431
|
-
endMinute: number().int().min(1).max(1440)
|
|
66750
|
+
day: number().int().min(0).max(6).meta(readingMeta("none")),
|
|
66751
|
+
startMinute: number().int().min(0).max(1439).meta(readingMeta("none")),
|
|
66752
|
+
endMinute: number().int().min(1).max(1440).meta(readingMeta("none"))
|
|
66432
66753
|
});
|
|
66433
66754
|
/** Status of one physical volume, as the camera itself describes it. */
|
|
66434
66755
|
var OnboardStorageVolumeSchema = object({
|
|
@@ -66504,10 +66825,10 @@ var RecordingOnboardStatusSchema = object({
|
|
|
66504
66825
|
/** Master "record to the card at all" switch. */
|
|
66505
66826
|
enabled: boolean().nullable(),
|
|
66506
66827
|
overwriteWhenFull: boolean().nullable(),
|
|
66507
|
-
preRecordSec: number().nullable(),
|
|
66508
|
-
postRecordSec: number().nullable(),
|
|
66828
|
+
preRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
66829
|
+
postRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
66509
66830
|
/** Length of one recorded file, in minutes. */
|
|
66510
|
-
segmentMinutes: number().nullable(),
|
|
66831
|
+
segmentMinutes: number().nullable().meta(readingMeta("none")),
|
|
66511
66832
|
/** The primary track's weekly windows, flattened. */
|
|
66512
66833
|
windows: array(RecordWindowSchema),
|
|
66513
66834
|
/**
|
|
@@ -66523,7 +66844,7 @@ var RecordingOnboardStatusSchema = object({
|
|
|
66523
66844
|
* provider reporting a non-zero count also reports the schedule as not
|
|
66524
66845
|
* writable.
|
|
66525
66846
|
*/
|
|
66526
|
-
unreadableWindows: number(),
|
|
66847
|
+
unreadableWindows: number().meta(readingMeta("count")),
|
|
66527
66848
|
/**
|
|
66528
66849
|
* The camera is scheduled to record and has NO usable storage.
|
|
66529
66850
|
*
|
|
@@ -67368,7 +67689,7 @@ var CamStreamDescriptorSchema = object({
|
|
|
67368
67689
|
url: string().optional(),
|
|
67369
67690
|
codec: string().optional(),
|
|
67370
67691
|
resolution: CamStreamResolutionSchema.optional(),
|
|
67371
|
-
fps: number().positive().optional(),
|
|
67692
|
+
fps: number().positive().optional().meta(readingMeta("rate")),
|
|
67372
67693
|
label: string().optional(),
|
|
67373
67694
|
/** Device-level features (e.g. `battery-operated`) — drives broker policy. */
|
|
67374
67695
|
deviceFeatures: array(string()).optional(),
|
|
@@ -67455,18 +67776,18 @@ var StreamProfileSchema = _enum([
|
|
|
67455
67776
|
]);
|
|
67456
67777
|
/** The current encoding config of one stream profile. */
|
|
67457
67778
|
var StreamProfileConfigSchema = object({
|
|
67458
|
-
width: number(),
|
|
67459
|
-
height: number(),
|
|
67779
|
+
width: number().meta(readingMeta("none")),
|
|
67780
|
+
height: number().meta(readingMeta("none")),
|
|
67460
67781
|
codec: _enum(["h264", "h265"]),
|
|
67461
|
-
framerate: number(),
|
|
67462
|
-
bitrate: number(),
|
|
67782
|
+
framerate: number().meta(readingMeta("rate")),
|
|
67783
|
+
bitrate: number().meta(readingMeta("bitrate")),
|
|
67463
67784
|
bitrateMode: _enum(["vbr", "cbr"]).optional(),
|
|
67464
67785
|
encoderProfile: _enum([
|
|
67465
67786
|
"high",
|
|
67466
67787
|
"main",
|
|
67467
67788
|
"baseline"
|
|
67468
67789
|
]).optional(),
|
|
67469
|
-
gop: number().optional(),
|
|
67790
|
+
gop: number().optional().meta(readingMeta("none")),
|
|
67470
67791
|
/**
|
|
67471
67792
|
* Whether THIS profile currently carries an audio track. READ-ONLY here.
|
|
67472
67793
|
*
|
|
@@ -67687,12 +68008,7 @@ var switchCapability = {
|
|
|
67687
68008
|
label: "On",
|
|
67688
68009
|
kind: "boolean"
|
|
67689
68010
|
}
|
|
67690
|
-
}] }
|
|
67691
|
-
customize: {
|
|
67692
|
-
version: 1,
|
|
67693
|
-
advanced: "derive",
|
|
67694
|
-
targets: []
|
|
67695
|
-
}
|
|
68011
|
+
}] }
|
|
67696
68012
|
};
|
|
67697
68013
|
/** C0 controls, DEL and the C1 range: none of them belongs in a name. */
|
|
67698
68014
|
function hasControlCharacter(value) {
|
|
@@ -68275,35 +68591,21 @@ var tamperCapability = {
|
|
|
68275
68591
|
* entries with `device_class: temperature` and any future native
|
|
68276
68592
|
* thermometer.
|
|
68277
68593
|
*
|
|
68278
|
-
*
|
|
68279
|
-
*
|
|
68280
|
-
* (climate-control's `currentTemp`, energy analytics) can compose
|
|
68281
|
-
* without per-source unit fixups. The canonical display unit (`°C`) is
|
|
68282
|
-
* a descriptor constant in the UI (ROLE_DESCRIPTOR), not stored in
|
|
68283
|
-
* `sourceInfo`.
|
|
68594
|
+
* The number is Celsius (D944). Providers convert on ingest. A failed
|
|
68595
|
+
* conversion is `null`, never a guess. Display unit is a read-time preference.
|
|
68284
68596
|
*
|
|
68285
68597
|
* Status `lastFetchedAt` lets staleness-aware consumers detect a
|
|
68286
68598
|
* frozen feed (provider hung) distinct from a "temperature hasn't
|
|
68287
68599
|
* changed" steady state.
|
|
68288
68600
|
*/
|
|
68289
68601
|
var TemperatureSensorStatusSchema = object({
|
|
68290
|
-
/** Current temperature in Celsius. */
|
|
68291
|
-
celsius: number().meta({
|
|
68292
|
-
|
|
68602
|
+
/** Current temperature in Celsius. `null` when the sample was refused (D393). */
|
|
68603
|
+
celsius: number().nullable().meta(readingMeta("temperature", {
|
|
68604
|
+
precision: 1,
|
|
68293
68605
|
label: "Temperature"
|
|
68294
|
-
}),
|
|
68606
|
+
})),
|
|
68295
68607
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
68296
|
-
lastFetchedAt: number()
|
|
68297
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
68298
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
68299
|
-
* role's canonical unit, so a Fahrenheit feed renders '°F' not '°C'.
|
|
68300
|
-
* Absent → the UI falls back to the role's canonical unit. */
|
|
68301
|
-
unit: string().optional(),
|
|
68302
|
-
/** Suggested decimal places for numeric display.
|
|
68303
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
68304
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
68305
|
-
* auto-formatting when absent. */
|
|
68306
|
-
precision: number().int().min(0).max(10).optional()
|
|
68608
|
+
lastFetchedAt: number()
|
|
68307
68609
|
});
|
|
68308
68610
|
var temperatureSensorCapability = {
|
|
68309
68611
|
name: "temperature-sensor",
|
|
@@ -68334,12 +68636,7 @@ var temperatureSensorCapability = {
|
|
|
68334
68636
|
} } },
|
|
68335
68637
|
/** Clock fields: written, but excluded from the compare that decides
|
|
68336
68638
|
* whether persisting is worth a SQLite commit. */
|
|
68337
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
68338
|
-
customize: {
|
|
68339
|
-
version: 1,
|
|
68340
|
-
advanced: "derive",
|
|
68341
|
-
targets: []
|
|
68342
|
-
}
|
|
68639
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
68343
68640
|
};
|
|
68344
68641
|
/**
|
|
68345
68642
|
* toast — system-scoped singleton capability that streams toast
|
|
@@ -68622,16 +68919,16 @@ var VacuumControlStatusSchema = object({
|
|
|
68622
68919
|
]),
|
|
68623
68920
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
68624
68921
|
* reading. */
|
|
68625
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
68922
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
68626
68923
|
/** Current fan-speed token (provider-verbatim). Null when unknown or
|
|
68627
68924
|
* the vacuum has no speed control. */
|
|
68628
68925
|
fanSpeed: string().nullable(),
|
|
68629
68926
|
/** Speed tokens the hardware accepts — drives the UI selector. */
|
|
68630
68927
|
availableFanSpeeds: array(string()),
|
|
68631
68928
|
/** 0..100 cleaning-completion percentage of the current task, or null. */
|
|
68632
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
68929
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
68633
68930
|
/** Current error code (0 / null = no error). */
|
|
68634
|
-
errorCode: number().nullable(),
|
|
68931
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
68635
68932
|
/** Human label for {@link errorCode}, or null when none / undecodable. */
|
|
68636
68933
|
errorLabel: string().nullable(),
|
|
68637
68934
|
/** Ms epoch when the slice was last updated. */
|
|
@@ -68709,7 +69006,7 @@ var ValveStatusSchema = object({
|
|
|
68709
69006
|
]),
|
|
68710
69007
|
/** 0 = fully closed, 100 = fully open. Null when the device has no
|
|
68711
69008
|
* intermediate position surface. */
|
|
68712
|
-
position: number().min(0).max(100).nullable(),
|
|
69009
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
68713
69010
|
/** Ms epoch when the slice was last updated. */
|
|
68714
69011
|
lastChangedAt: number()
|
|
68715
69012
|
});
|
|
@@ -68817,9 +69114,9 @@ var vibrationCapability = {
|
|
|
68817
69114
|
*/
|
|
68818
69115
|
var WaterHeaterStatusSchema = object({
|
|
68819
69116
|
/** Current measured temperature. Null when not reported. */
|
|
68820
|
-
currentTemp: number().nullable(),
|
|
69117
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
68821
69118
|
/** Target temperature setpoint. Null when no setpoint surface. */
|
|
68822
|
-
targetTemp: number().nullable(),
|
|
69119
|
+
targetTemp: number().nullable().meta(readingMeta("temperature")),
|
|
68823
69120
|
/** Active operation mode = HA `state` (`eco` / `electric` / `gas` /
|
|
68824
69121
|
* `heat_pump` / `high_demand` / `performance` / `off`). Null when the
|
|
68825
69122
|
* device reports an unknown state. */
|
|
@@ -68830,9 +69127,9 @@ var WaterHeaterStatusSchema = object({
|
|
|
68830
69127
|
* has no away surface. */
|
|
68831
69128
|
away: boolean().nullable(),
|
|
68832
69129
|
/** HA `min_temp` attribute. Null when not reported. */
|
|
68833
|
-
minTemp: number().nullable(),
|
|
69130
|
+
minTemp: number().nullable().meta(readingMeta("temperature")),
|
|
68834
69131
|
/** HA `max_temp` attribute. Null when not reported. */
|
|
68835
|
-
maxTemp: number().nullable(),
|
|
69132
|
+
maxTemp: number().nullable().meta(readingMeta("temperature")),
|
|
68836
69133
|
/** Ms epoch when the slice was last updated. */
|
|
68837
69134
|
lastChangedAt: number()
|
|
68838
69135
|
});
|
|
@@ -68917,25 +69214,18 @@ var waterHeaterCapability = {
|
|
|
68917
69214
|
* Forecast deferred — current conditions only for v1.
|
|
68918
69215
|
*/
|
|
68919
69216
|
var WeatherStatusSchema = object({
|
|
68920
|
-
/** Verbatim
|
|
68921
|
-
* when no condition has been reported yet. */
|
|
69217
|
+
/** Verbatim condition state (`sunny`, `cloudy`, `rainy`, …). Null when none yet. */
|
|
68922
69218
|
condition: string().nullable(),
|
|
68923
|
-
/** Current temperature in
|
|
68924
|
-
temperature: number().nullable(),
|
|
68925
|
-
/** Temperature unit string (e.g. `°C` / `°F`). Null when not provided. */
|
|
68926
|
-
temperatureUnit: string().nullable(),
|
|
69219
|
+
/** Current temperature in Celsius. Null when not provided or refused. */
|
|
69220
|
+
temperature: number().nullable().meta(readingMeta("temperature", { precision: 1 })),
|
|
68927
69221
|
/** Relative humidity (0..100). Null when not provided. */
|
|
68928
|
-
humidity: number().min(0).max(100).nullable(),
|
|
68929
|
-
/** Barometric pressure in
|
|
68930
|
-
pressure: number().nullable(),
|
|
68931
|
-
/**
|
|
68932
|
-
|
|
68933
|
-
/** Wind speed in the reported unit. Null when not provided. */
|
|
68934
|
-
windSpeed: number().nullable(),
|
|
68935
|
-
/** Wind-speed unit string (e.g. `km/h` / `mph`). Null when not provided. */
|
|
68936
|
-
windSpeedUnit: string().nullable(),
|
|
69222
|
+
humidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
69223
|
+
/** Barometric pressure in hPa. Null when not provided or refused. */
|
|
69224
|
+
pressure: number().nullable().meta(readingMeta("pressure")),
|
|
69225
|
+
/** Wind speed in metres per second. Null when not provided or refused. */
|
|
69226
|
+
windSpeed: number().nullable().meta(readingMeta("speed")),
|
|
68937
69227
|
/** Wind bearing in degrees (0..360, meteorological). Null when not provided. */
|
|
68938
|
-
windBearing: number().nullable(),
|
|
69228
|
+
windBearing: number().nullable().meta(readingMeta("angle")),
|
|
68939
69229
|
/** Ms epoch when the slice was last updated. */
|
|
68940
69230
|
lastFetchedAt: number()
|
|
68941
69231
|
});
|
|
@@ -68963,12 +69253,12 @@ var weatherCapability = {
|
|
|
68963
69253
|
*/
|
|
68964
69254
|
durability: "session",
|
|
68965
69255
|
/**
|
|
68966
|
-
* History (D850): recorded series.
|
|
69256
|
+
* History (D850): recorded series. Numbers are the quantity base (D944).
|
|
68967
69257
|
*/
|
|
68968
69258
|
history: { fields: {
|
|
68969
69259
|
temperature: {
|
|
68970
69260
|
kind: "gauge",
|
|
68971
|
-
|
|
69261
|
+
unit: "°C",
|
|
68972
69262
|
deadband: .2
|
|
68973
69263
|
},
|
|
68974
69264
|
humidity: {
|
|
@@ -68978,12 +69268,12 @@ var weatherCapability = {
|
|
|
68978
69268
|
},
|
|
68979
69269
|
pressure: {
|
|
68980
69270
|
kind: "gauge",
|
|
68981
|
-
|
|
69271
|
+
unit: "hPa",
|
|
68982
69272
|
deadband: .5
|
|
68983
69273
|
},
|
|
68984
69274
|
windSpeed: {
|
|
68985
69275
|
kind: "gauge",
|
|
68986
|
-
|
|
69276
|
+
unit: "m/s",
|
|
68987
69277
|
deadband: .5
|
|
68988
69278
|
}
|
|
68989
69279
|
} }
|
|
@@ -69921,6 +70211,404 @@ function runningFromMediaPlayer(state, previous, fetchedAt, transitionAt) {
|
|
|
69921
70211
|
if (state === "paused") return nativeSlice(false, "paused", previous, transitionAtMs, fetchedAt, null);
|
|
69922
70212
|
return nativeSlice(false, state, previous, transitionAtMs, fetchedAt, null);
|
|
69923
70213
|
}
|
|
70214
|
+
/**
|
|
70215
|
+
* Frozen unit → spec table. `•` in the doc marks each dimension's canonical
|
|
70216
|
+
* unit (`factor: 1, offset: 0`). °F derives from `°C = (°F − 32) × 5/9` ⇒
|
|
70217
|
+
* `factor = 5/9`, `offset = -160/9` (kept as exact expressions, not rounded
|
|
70218
|
+
* decimals). K derives from `°C = K − 273.15`.
|
|
70219
|
+
*/
|
|
70220
|
+
var UNIT_TABLE = {
|
|
70221
|
+
"°C": {
|
|
70222
|
+
dimension: "temperature",
|
|
70223
|
+
factor: 1,
|
|
70224
|
+
offset: 0
|
|
70225
|
+
},
|
|
70226
|
+
"°F": {
|
|
70227
|
+
dimension: "temperature",
|
|
70228
|
+
factor: 5 / 9,
|
|
70229
|
+
offset: -160 / 9
|
|
70230
|
+
},
|
|
70231
|
+
K: {
|
|
70232
|
+
dimension: "temperature",
|
|
70233
|
+
factor: 1,
|
|
70234
|
+
offset: -273.15
|
|
70235
|
+
},
|
|
70236
|
+
hPa: {
|
|
70237
|
+
dimension: "pressure",
|
|
70238
|
+
factor: 1,
|
|
70239
|
+
offset: 0
|
|
70240
|
+
},
|
|
70241
|
+
kPa: {
|
|
70242
|
+
dimension: "pressure",
|
|
70243
|
+
factor: 10,
|
|
70244
|
+
offset: 0
|
|
70245
|
+
},
|
|
70246
|
+
Pa: {
|
|
70247
|
+
dimension: "pressure",
|
|
70248
|
+
factor: .01,
|
|
70249
|
+
offset: 0
|
|
70250
|
+
},
|
|
70251
|
+
mbar: {
|
|
70252
|
+
dimension: "pressure",
|
|
70253
|
+
factor: 1,
|
|
70254
|
+
offset: 0
|
|
70255
|
+
},
|
|
70256
|
+
bar: {
|
|
70257
|
+
dimension: "pressure",
|
|
70258
|
+
factor: 1e3,
|
|
70259
|
+
offset: 0
|
|
70260
|
+
},
|
|
70261
|
+
inHg: {
|
|
70262
|
+
dimension: "pressure",
|
|
70263
|
+
factor: 33.8639,
|
|
70264
|
+
offset: 0
|
|
70265
|
+
},
|
|
70266
|
+
mmHg: {
|
|
70267
|
+
dimension: "pressure",
|
|
70268
|
+
factor: 1.33322,
|
|
70269
|
+
offset: 0
|
|
70270
|
+
},
|
|
70271
|
+
psi: {
|
|
70272
|
+
dimension: "pressure",
|
|
70273
|
+
factor: 68.9476,
|
|
70274
|
+
offset: 0
|
|
70275
|
+
},
|
|
70276
|
+
"m/s": {
|
|
70277
|
+
dimension: "speed",
|
|
70278
|
+
factor: 1,
|
|
70279
|
+
offset: 0
|
|
70280
|
+
},
|
|
70281
|
+
"km/h": {
|
|
70282
|
+
dimension: "speed",
|
|
70283
|
+
factor: 1 / 3.6,
|
|
70284
|
+
offset: 0
|
|
70285
|
+
},
|
|
70286
|
+
mph: {
|
|
70287
|
+
dimension: "speed",
|
|
70288
|
+
factor: .44704,
|
|
70289
|
+
offset: 0
|
|
70290
|
+
},
|
|
70291
|
+
kn: {
|
|
70292
|
+
dimension: "speed",
|
|
70293
|
+
factor: .514444,
|
|
70294
|
+
offset: 0
|
|
70295
|
+
},
|
|
70296
|
+
"mm/h": {
|
|
70297
|
+
dimension: "precipitation-rate",
|
|
70298
|
+
factor: 1,
|
|
70299
|
+
offset: 0
|
|
70300
|
+
},
|
|
70301
|
+
"in/h": {
|
|
70302
|
+
dimension: "precipitation-rate",
|
|
70303
|
+
factor: 25.4,
|
|
70304
|
+
offset: 0
|
|
70305
|
+
},
|
|
70306
|
+
m: {
|
|
70307
|
+
dimension: "length",
|
|
70308
|
+
factor: 1,
|
|
70309
|
+
offset: 0
|
|
70310
|
+
},
|
|
70311
|
+
mm: {
|
|
70312
|
+
dimension: "length",
|
|
70313
|
+
factor: .001,
|
|
70314
|
+
offset: 0
|
|
70315
|
+
},
|
|
70316
|
+
cm: {
|
|
70317
|
+
dimension: "length",
|
|
70318
|
+
factor: .01,
|
|
70319
|
+
offset: 0
|
|
70320
|
+
},
|
|
70321
|
+
km: {
|
|
70322
|
+
dimension: "length",
|
|
70323
|
+
factor: 1e3,
|
|
70324
|
+
offset: 0
|
|
70325
|
+
},
|
|
70326
|
+
in: {
|
|
70327
|
+
dimension: "length",
|
|
70328
|
+
factor: .0254,
|
|
70329
|
+
offset: 0
|
|
70330
|
+
},
|
|
70331
|
+
ft: {
|
|
70332
|
+
dimension: "length",
|
|
70333
|
+
factor: .3048,
|
|
70334
|
+
offset: 0
|
|
70335
|
+
},
|
|
70336
|
+
mi: {
|
|
70337
|
+
dimension: "length",
|
|
70338
|
+
factor: 1609.344,
|
|
70339
|
+
offset: 0
|
|
70340
|
+
},
|
|
70341
|
+
"m²": {
|
|
70342
|
+
dimension: "area",
|
|
70343
|
+
factor: 1,
|
|
70344
|
+
offset: 0
|
|
70345
|
+
},
|
|
70346
|
+
lx: {
|
|
70347
|
+
dimension: "illuminance",
|
|
70348
|
+
factor: 1,
|
|
70349
|
+
offset: 0
|
|
70350
|
+
},
|
|
70351
|
+
"W/m²": {
|
|
70352
|
+
dimension: "irradiance",
|
|
70353
|
+
factor: 1,
|
|
70354
|
+
offset: 0
|
|
70355
|
+
},
|
|
70356
|
+
W: {
|
|
70357
|
+
dimension: "power",
|
|
70358
|
+
factor: 1,
|
|
70359
|
+
offset: 0
|
|
70360
|
+
},
|
|
70361
|
+
kW: {
|
|
70362
|
+
dimension: "power",
|
|
70363
|
+
factor: 1e3,
|
|
70364
|
+
offset: 0
|
|
70365
|
+
},
|
|
70366
|
+
VA: {
|
|
70367
|
+
dimension: "apparent-power",
|
|
70368
|
+
factor: 1,
|
|
70369
|
+
offset: 0
|
|
70370
|
+
},
|
|
70371
|
+
Wh: {
|
|
70372
|
+
dimension: "energy",
|
|
70373
|
+
factor: 1,
|
|
70374
|
+
offset: 0
|
|
70375
|
+
},
|
|
70376
|
+
kWh: {
|
|
70377
|
+
dimension: "energy",
|
|
70378
|
+
factor: 1e3,
|
|
70379
|
+
offset: 0
|
|
70380
|
+
},
|
|
70381
|
+
MWh: {
|
|
70382
|
+
dimension: "energy",
|
|
70383
|
+
factor: 1e6,
|
|
70384
|
+
offset: 0
|
|
70385
|
+
},
|
|
70386
|
+
V: {
|
|
70387
|
+
dimension: "voltage",
|
|
70388
|
+
factor: 1,
|
|
70389
|
+
offset: 0
|
|
70390
|
+
},
|
|
70391
|
+
mV: {
|
|
70392
|
+
dimension: "voltage",
|
|
70393
|
+
factor: .001,
|
|
70394
|
+
offset: 0
|
|
70395
|
+
},
|
|
70396
|
+
A: {
|
|
70397
|
+
dimension: "current",
|
|
70398
|
+
factor: 1,
|
|
70399
|
+
offset: 0
|
|
70400
|
+
},
|
|
70401
|
+
mA: {
|
|
70402
|
+
dimension: "current",
|
|
70403
|
+
factor: .001,
|
|
70404
|
+
offset: 0
|
|
70405
|
+
},
|
|
70406
|
+
ppm: {
|
|
70407
|
+
dimension: "concentration-volume",
|
|
70408
|
+
factor: 1,
|
|
70409
|
+
offset: 0
|
|
70410
|
+
},
|
|
70411
|
+
ppb: {
|
|
70412
|
+
dimension: "concentration-volume",
|
|
70413
|
+
factor: .001,
|
|
70414
|
+
offset: 0
|
|
70415
|
+
},
|
|
70416
|
+
"µg/m³": {
|
|
70417
|
+
dimension: "concentration-mass",
|
|
70418
|
+
factor: 1,
|
|
70419
|
+
offset: 0
|
|
70420
|
+
},
|
|
70421
|
+
"mg/m³": {
|
|
70422
|
+
dimension: "concentration-mass",
|
|
70423
|
+
factor: 1e3,
|
|
70424
|
+
offset: 0
|
|
70425
|
+
},
|
|
70426
|
+
kg: {
|
|
70427
|
+
dimension: "mass",
|
|
70428
|
+
factor: 1,
|
|
70429
|
+
offset: 0
|
|
70430
|
+
},
|
|
70431
|
+
g: {
|
|
70432
|
+
dimension: "mass",
|
|
70433
|
+
factor: .001,
|
|
70434
|
+
offset: 0
|
|
70435
|
+
},
|
|
70436
|
+
lb: {
|
|
70437
|
+
dimension: "mass",
|
|
70438
|
+
factor: .453592,
|
|
70439
|
+
offset: 0
|
|
70440
|
+
},
|
|
70441
|
+
oz: {
|
|
70442
|
+
dimension: "mass",
|
|
70443
|
+
factor: .0283495,
|
|
70444
|
+
offset: 0
|
|
70445
|
+
},
|
|
70446
|
+
"%": {
|
|
70447
|
+
dimension: "percentage",
|
|
70448
|
+
factor: 1,
|
|
70449
|
+
offset: 0
|
|
70450
|
+
},
|
|
70451
|
+
L: {
|
|
70452
|
+
dimension: "volume",
|
|
70453
|
+
factor: 1,
|
|
70454
|
+
offset: 0
|
|
70455
|
+
},
|
|
70456
|
+
mL: {
|
|
70457
|
+
dimension: "volume",
|
|
70458
|
+
factor: .001,
|
|
70459
|
+
offset: 0
|
|
70460
|
+
},
|
|
70461
|
+
gal: {
|
|
70462
|
+
dimension: "volume",
|
|
70463
|
+
factor: 3.785411784,
|
|
70464
|
+
offset: 0
|
|
70465
|
+
},
|
|
70466
|
+
s: {
|
|
70467
|
+
dimension: "duration",
|
|
70468
|
+
factor: 1,
|
|
70469
|
+
offset: 0
|
|
70470
|
+
},
|
|
70471
|
+
ms: {
|
|
70472
|
+
dimension: "duration",
|
|
70473
|
+
factor: .001,
|
|
70474
|
+
offset: 0
|
|
70475
|
+
},
|
|
70476
|
+
min: {
|
|
70477
|
+
dimension: "duration",
|
|
70478
|
+
factor: 60,
|
|
70479
|
+
offset: 0
|
|
70480
|
+
},
|
|
70481
|
+
h: {
|
|
70482
|
+
dimension: "duration",
|
|
70483
|
+
factor: 3600,
|
|
70484
|
+
offset: 0
|
|
70485
|
+
},
|
|
70486
|
+
d: {
|
|
70487
|
+
dimension: "duration",
|
|
70488
|
+
factor: 86400,
|
|
70489
|
+
offset: 0
|
|
70490
|
+
},
|
|
70491
|
+
B: {
|
|
70492
|
+
dimension: "information",
|
|
70493
|
+
factor: 1,
|
|
70494
|
+
offset: 0
|
|
70495
|
+
},
|
|
70496
|
+
KiB: {
|
|
70497
|
+
dimension: "information",
|
|
70498
|
+
factor: 1024,
|
|
70499
|
+
offset: 0
|
|
70500
|
+
},
|
|
70501
|
+
MiB: {
|
|
70502
|
+
dimension: "information",
|
|
70503
|
+
factor: 1024 ** 2,
|
|
70504
|
+
offset: 0
|
|
70505
|
+
},
|
|
70506
|
+
GiB: {
|
|
70507
|
+
dimension: "information",
|
|
70508
|
+
factor: 1024 ** 3,
|
|
70509
|
+
offset: 0
|
|
70510
|
+
},
|
|
70511
|
+
TiB: {
|
|
70512
|
+
dimension: "information",
|
|
70513
|
+
factor: 1024 ** 4,
|
|
70514
|
+
offset: 0
|
|
70515
|
+
},
|
|
70516
|
+
kB: {
|
|
70517
|
+
dimension: "information",
|
|
70518
|
+
factor: 1e3,
|
|
70519
|
+
offset: 0
|
|
70520
|
+
},
|
|
70521
|
+
MB: {
|
|
70522
|
+
dimension: "information",
|
|
70523
|
+
factor: 1e6,
|
|
70524
|
+
offset: 0
|
|
70525
|
+
},
|
|
70526
|
+
GB: {
|
|
70527
|
+
dimension: "information",
|
|
70528
|
+
factor: 1e9,
|
|
70529
|
+
offset: 0
|
|
70530
|
+
},
|
|
70531
|
+
"°": {
|
|
70532
|
+
dimension: "angle",
|
|
70533
|
+
factor: 1,
|
|
70534
|
+
offset: 0
|
|
70535
|
+
},
|
|
70536
|
+
dBFS: {
|
|
70537
|
+
dimension: "sound-level",
|
|
70538
|
+
factor: 1,
|
|
70539
|
+
offset: 0
|
|
70540
|
+
},
|
|
70541
|
+
dBm: {
|
|
70542
|
+
dimension: "signal-level",
|
|
70543
|
+
factor: 1,
|
|
70544
|
+
offset: 0
|
|
70545
|
+
},
|
|
70546
|
+
mired: {
|
|
70547
|
+
dimension: "colour-temperature",
|
|
70548
|
+
factor: 1,
|
|
70549
|
+
offset: 0
|
|
70550
|
+
},
|
|
70551
|
+
kbps: {
|
|
70552
|
+
dimension: "bitrate",
|
|
70553
|
+
factor: 1,
|
|
70554
|
+
offset: 0
|
|
70555
|
+
},
|
|
70556
|
+
Mbps: {
|
|
70557
|
+
dimension: "bitrate",
|
|
70558
|
+
factor: 1e3,
|
|
70559
|
+
offset: 0
|
|
70560
|
+
},
|
|
70561
|
+
fps: {
|
|
70562
|
+
dimension: "rate",
|
|
70563
|
+
factor: 1,
|
|
70564
|
+
offset: 0
|
|
70565
|
+
}
|
|
70566
|
+
};
|
|
70567
|
+
/** Resolve a unit's `UnitSpec`, or `undefined` when the spelling is unknown. */
|
|
70568
|
+
function specFor(unit) {
|
|
70569
|
+
return Object.hasOwn(UNIT_TABLE, unit) ? UNIT_TABLE[unit] : void 0;
|
|
70570
|
+
}
|
|
70571
|
+
/** The dimension a unit belongs to, or `undefined` for an unknown unit. */
|
|
70572
|
+
function unitDimension(unit) {
|
|
70573
|
+
return specFor(unit)?.dimension;
|
|
70574
|
+
}
|
|
70575
|
+
/** Value in `spec`'s unit → its dimension's canonical unit. */
|
|
70576
|
+
function toCanonical(value, spec) {
|
|
70577
|
+
return value * spec.factor + spec.offset;
|
|
70578
|
+
}
|
|
70579
|
+
/** Canonical-unit value → the unit described by `spec`. */
|
|
70580
|
+
function fromCanonical(canonical, spec) {
|
|
70581
|
+
return (canonical - spec.offset) / spec.factor;
|
|
70582
|
+
}
|
|
70583
|
+
/**
|
|
70584
|
+
* Graceful variant for the render path: returns the converted value, or
|
|
70585
|
+
* `undefined` when the conversion is refused (unknown unit / cross-dimension).
|
|
70586
|
+
* Never throws — a render caller falls back to the raw value + source unit.
|
|
70587
|
+
*/
|
|
70588
|
+
function tryConvertUnit(value, from, to) {
|
|
70589
|
+
if (from === to) return value;
|
|
70590
|
+
const fromSpec = specFor(from);
|
|
70591
|
+
if (!fromSpec) return void 0;
|
|
70592
|
+
const toSpec = specFor(to);
|
|
70593
|
+
if (!toSpec) return void 0;
|
|
70594
|
+
if (fromSpec.dimension !== toSpec.dimension) return void 0;
|
|
70595
|
+
return fromCanonical(toCanonical(value, fromSpec), toSpec);
|
|
70596
|
+
}
|
|
70597
|
+
/**
|
|
70598
|
+
* Every known unit spelling in a dimension (table insertion order — canonical
|
|
70599
|
+
* unit first). Powers the UI's same-dimension unit picker.
|
|
70600
|
+
*/
|
|
70601
|
+
/**
|
|
70602
|
+
* Convert a difference, not a reading. Affine units (°F) shift an absolute
|
|
70603
|
+
* value by their offset; a step of 1°F is 5/9°C, so the offset is cancelled.
|
|
70604
|
+
*/
|
|
70605
|
+
function tryConvertDelta(value, from, to) {
|
|
70606
|
+
if (from === to) return value;
|
|
70607
|
+
const origin = tryConvertUnit(0, from, to);
|
|
70608
|
+
const shifted = tryConvertUnit(value, from, to);
|
|
70609
|
+
if (origin === void 0 || shifted === void 0) return void 0;
|
|
70610
|
+
return shifted - origin;
|
|
70611
|
+
}
|
|
69924
70612
|
SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
|
|
69925
70613
|
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.Dishwasher, DeviceType.Camera, DeviceType.Camera, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
|
|
69926
70614
|
String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
|
|
@@ -70251,6 +70939,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
70251
70939
|
featureProbe: featureProbeCapability,
|
|
70252
70940
|
flood: floodCapability,
|
|
70253
70941
|
gas: gasCapability,
|
|
70942
|
+
groupStatus: groupStatusCapability,
|
|
70254
70943
|
heatingValve: heatingValveCapability,
|
|
70255
70944
|
humidifier: humidifierCapability,
|
|
70256
70945
|
humiditySensor: humiditySensorCapability,
|
|
@@ -74735,6 +75424,13 @@ Object.freeze({
|
|
|
74735
75424
|
access: "view",
|
|
74736
75425
|
role: "viewer"
|
|
74737
75426
|
},
|
|
75427
|
+
"groupStatus.getStatus": {
|
|
75428
|
+
capName: "group-status",
|
|
75429
|
+
capScope: "device",
|
|
75430
|
+
addonId: null,
|
|
75431
|
+
access: "view",
|
|
75432
|
+
role: "viewer"
|
|
75433
|
+
},
|
|
74738
75434
|
"heatingValve.getStatus": {
|
|
74739
75435
|
capName: "heating-valve",
|
|
74740
75436
|
capScope: "device",
|
|
@@ -84557,6 +85253,33 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84557
85253
|
icon: "flame"
|
|
84558
85254
|
}]
|
|
84559
85255
|
},
|
|
85256
|
+
"group-status": {
|
|
85257
|
+
scope: "device",
|
|
85258
|
+
noun: t("Group", "Gruppo"),
|
|
85259
|
+
state: [
|
|
85260
|
+
{
|
|
85261
|
+
kind: "numeric",
|
|
85262
|
+
field: "included",
|
|
85263
|
+
quantity: t("the members reporting", "i membri che rispondono"),
|
|
85264
|
+
label: t("Reporting", "Rispondono"),
|
|
85265
|
+
icon: "users"
|
|
85266
|
+
},
|
|
85267
|
+
{
|
|
85268
|
+
kind: "numeric",
|
|
85269
|
+
field: "excluded",
|
|
85270
|
+
quantity: t("the members left out", "i membri esclusi"),
|
|
85271
|
+
label: t("Excluded", "Esclusi"),
|
|
85272
|
+
icon: "users"
|
|
85273
|
+
},
|
|
85274
|
+
{
|
|
85275
|
+
kind: "numeric",
|
|
85276
|
+
field: "total",
|
|
85277
|
+
quantity: t("the member count", "il numero di membri"),
|
|
85278
|
+
label: t("Members", "Membri"),
|
|
85279
|
+
icon: "sigma"
|
|
85280
|
+
}
|
|
85281
|
+
]
|
|
85282
|
+
},
|
|
84560
85283
|
"humidity-sensor": {
|
|
84561
85284
|
scope: "device",
|
|
84562
85285
|
noun: t("Humidity", "Umidità"),
|
|
@@ -84590,7 +85313,6 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84590
85313
|
field: "value",
|
|
84591
85314
|
quantity: t("the reading", "il valore"),
|
|
84592
85315
|
label: t("Reading", "Valore"),
|
|
84593
|
-
unitField: "unit",
|
|
84594
85316
|
icon: "gauge"
|
|
84595
85317
|
}]
|
|
84596
85318
|
},
|
|
@@ -84726,7 +85448,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84726
85448
|
field: "temperature",
|
|
84727
85449
|
quantity: t("the outdoor temperature", "la temperatura esterna"),
|
|
84728
85450
|
label: t("Temperature", "Temperatura"),
|
|
84729
|
-
|
|
85451
|
+
unit: "°C",
|
|
84730
85452
|
icon: "thermometer"
|
|
84731
85453
|
},
|
|
84732
85454
|
{
|
|
@@ -84742,7 +85464,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84742
85464
|
field: "windSpeed",
|
|
84743
85465
|
quantity: t("the wind speed", "la velocità del vento"),
|
|
84744
85466
|
label: t("Wind", "Vento"),
|
|
84745
|
-
|
|
85467
|
+
unit: "m/s",
|
|
84746
85468
|
icon: "wind"
|
|
84747
85469
|
},
|
|
84748
85470
|
{
|
|
@@ -84750,7 +85472,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84750
85472
|
field: "pressure",
|
|
84751
85473
|
quantity: t("the air pressure", "la pressione atmosferica"),
|
|
84752
85474
|
label: t("Pressure", "Pressione"),
|
|
84753
|
-
|
|
85475
|
+
unit: "hPa",
|
|
84754
85476
|
icon: "gauge"
|
|
84755
85477
|
}
|
|
84756
85478
|
]
|
|
@@ -86023,6 +86745,11 @@ Object.freeze({
|
|
|
86023
86745
|
form: "single",
|
|
86024
86746
|
optional: false
|
|
86025
86747
|
}],
|
|
86748
|
+
"groupStatus.getStatus": [{
|
|
86749
|
+
name: "deviceId",
|
|
86750
|
+
form: "single",
|
|
86751
|
+
optional: false
|
|
86752
|
+
}],
|
|
86026
86753
|
"heatingValve.getStatus": [{
|
|
86027
86754
|
name: "deviceId",
|
|
86028
86755
|
form: "single",
|
|
@@ -89323,6 +90050,96 @@ DEFAULT_NATIVE_LEASE_SETTINGS.tileBudgetMb;
|
|
|
89323
90050
|
DEFAULT_NATIVE_LEASE_SETTINGS.sceneBudgetMb;
|
|
89324
90051
|
DEFAULT_NATIVE_LEASE_SETTINGS.admission;
|
|
89325
90052
|
/**
|
|
90053
|
+
* Convert an upstream number into the stored base of its quantity (D944 §4).
|
|
90054
|
+
* An unknown unit or a unit from another dimension is a refusal: the caller
|
|
90055
|
+
* logs it and publishes null (D393). This function never guesses.
|
|
90056
|
+
*/
|
|
90057
|
+
var DIMENSION_QUANTITY = {
|
|
90058
|
+
temperature: "temperature",
|
|
90059
|
+
pressure: "pressure",
|
|
90060
|
+
speed: "speed",
|
|
90061
|
+
"precipitation-rate": "precipitation-rate",
|
|
90062
|
+
length: "length",
|
|
90063
|
+
area: "area",
|
|
90064
|
+
illuminance: "illuminance",
|
|
90065
|
+
irradiance: "irradiance",
|
|
90066
|
+
power: "power",
|
|
90067
|
+
"apparent-power": "apparent-power",
|
|
90068
|
+
energy: "energy",
|
|
90069
|
+
voltage: "voltage",
|
|
90070
|
+
current: "current",
|
|
90071
|
+
"concentration-volume": "concentration-volume",
|
|
90072
|
+
"concentration-mass": "concentration-mass",
|
|
90073
|
+
mass: "mass",
|
|
90074
|
+
percentage: "percentage",
|
|
90075
|
+
volume: "volume",
|
|
90076
|
+
duration: "duration",
|
|
90077
|
+
information: "information",
|
|
90078
|
+
angle: "angle",
|
|
90079
|
+
"sound-level": "sound-level",
|
|
90080
|
+
"signal-level": "signal-level",
|
|
90081
|
+
"colour-temperature": "colour-temperature",
|
|
90082
|
+
bitrate: "bitrate",
|
|
90083
|
+
rate: "rate"
|
|
90084
|
+
};
|
|
90085
|
+
/**
|
|
90086
|
+
* Quantity implied by a unit symbol. `ppb` and `ms` are the two symbols
|
|
90087
|
+
* whose stored base is not the dimension's canonical unit. `mm` is length;
|
|
90088
|
+
* precipitation is chosen by the caller (a device class), not by the symbol.
|
|
90089
|
+
*/
|
|
90090
|
+
function quantityFromUnit(rawUnit) {
|
|
90091
|
+
const unit = normalizeUnit(rawUnit);
|
|
90092
|
+
if (unit === void 0) return void 0;
|
|
90093
|
+
if (unit === "ppb") return "concentration-ppb";
|
|
90094
|
+
if (unit === "ms") return "duration-ms";
|
|
90095
|
+
const dimension = unitDimension(unit);
|
|
90096
|
+
if (dimension === void 0) return void 0;
|
|
90097
|
+
return DIMENSION_QUANTITY[dimension];
|
|
90098
|
+
}
|
|
90099
|
+
function ingestReading(input) {
|
|
90100
|
+
if (!Number.isFinite(input.value)) return {
|
|
90101
|
+
ok: false,
|
|
90102
|
+
reason: "non-finite"
|
|
90103
|
+
};
|
|
90104
|
+
if (input.quantity === "device") return {
|
|
90105
|
+
ok: false,
|
|
90106
|
+
reason: "unknown-unit"
|
|
90107
|
+
};
|
|
90108
|
+
const raw = input.rawUnit?.trim();
|
|
90109
|
+
if (raw === void 0 || raw.length === 0) return {
|
|
90110
|
+
ok: true,
|
|
90111
|
+
value: input.value
|
|
90112
|
+
};
|
|
90113
|
+
const unit = normalizeUnit(raw);
|
|
90114
|
+
if (unit === void 0) return {
|
|
90115
|
+
ok: false,
|
|
90116
|
+
reason: "unknown-unit"
|
|
90117
|
+
};
|
|
90118
|
+
const base = baseUnitOf(input.quantity);
|
|
90119
|
+
if (base === void 0) {
|
|
90120
|
+
if (unitDimension(unit) !== void 0) return {
|
|
90121
|
+
ok: false,
|
|
90122
|
+
reason: "cross-dimension"
|
|
90123
|
+
};
|
|
90124
|
+
return {
|
|
90125
|
+
ok: false,
|
|
90126
|
+
reason: "unknown-unit"
|
|
90127
|
+
};
|
|
90128
|
+
}
|
|
90129
|
+
const converted = tryConvertUnit(input.value, unit, base);
|
|
90130
|
+
if (converted === void 0) return unitDimension(unit) === void 0 ? {
|
|
90131
|
+
ok: false,
|
|
90132
|
+
reason: "unknown-unit"
|
|
90133
|
+
} : {
|
|
90134
|
+
ok: false,
|
|
90135
|
+
reason: "cross-dimension"
|
|
90136
|
+
};
|
|
90137
|
+
return {
|
|
90138
|
+
ok: true,
|
|
90139
|
+
value: converted
|
|
90140
|
+
};
|
|
90141
|
+
}
|
|
90142
|
+
/**
|
|
89326
90143
|
* Pure fuzzy matcher for adoption location import. Normalized
|
|
89327
90144
|
* case-insensitive Levenshtein similarity, used to reuse an existing
|
|
89328
90145
|
* CamStack location when an imported source location (e.g. an HA area) is
|
|
@@ -89377,4 +90194,4 @@ function bestLocationMatch(externalName, existing, threshold = .8) {
|
|
|
89377
90194
|
var MB = 1024 * 1024;
|
|
89378
90195
|
1024 * MB, 3072 * MB;
|
|
89379
90196
|
//#endregion
|
|
89380
|
-
export {
|
|
90197
|
+
export { lockControlCapability as $, unknown as $t, calendarSourceCapability as A, DeviceFeature as At, deviceAdminLinkCapability as B, entryBody as Bt, bestLocationMatch as C, tryConvertUnit as Ct, buildAddonRouteProvider as D, vibrationCapability as Dt, brokerCapability as E, valveCapability as Et, consumableFormOf as F, RecordSecretUnavailableError as Ft, fanControlCapability as G, boolean as Gt, deviceExportCapability as H, nodePin as Ht, consumableKindOf as I, baseUnitOf as It, humidifierCapability as J, number as Jt, floodCapability as K, discriminatedUnion as Kt, contactCapability as L, createEvent as Lt, climateControlCapability as M, DeviceType as Mt, colorCapability as N, errMsg as Nt, buildDeviceAdminUrl as O, waterHeaterCapability as Ot, connectivityCapability as P, BaseAddon as Pt, lawnMowerControlCapability as Q, union as Qt, controlCapability as R, defineEntryKind as Rt, batteryCapability as S, tryConvertDelta as St, brightnessCapability as T, vacuumControlCapability as Tt, enumSensorCapability as U, _enum as Ut, deviceAdoptionCapability as V, isReadingQuantity as Vt, eventEmitterCapability as W, array as Wt, imageCapability as X, record as Xt, humiditySensorCapability as Y, object as Yt, ingestReading as Z, string as Zt, addonRoutesCapability as _, scriptRunnerCapability as _t, COCO_TO_MACRO as a, numericSensorCapability as at, ambientLightSensorCapability as b, tamperCapability as bt, ConsumableItemSchema as c, powerMeterCapability as ct, FanDirectionSchema as d, pressureSensorCapability as dt, url as en, mediaPlayerCapability as et, HvacModeSchema as f, quantityFromUnit as ft, accessoriesCapability as g, runningStateCapability as gt, TargetSchema as h, runningFromVacuumState as ht, CAMERA_SWITCH_ORDER as i, notifierCapability as it, carbonMonoxideCapability as j, DeviceRole as jt, buttonCapability as k, weatherCapability as kt, ConsumableStatusSchema as l, prepareNotification as lt, RUNNING_STATE_COLD as m, runningFromMediaPlayer as mt, BaseDevice as n, normalizeUnit as nt, CameraSwitchIdSchema as o, oauthIntegrationCapability as ot, MediaPlayerRepeatSchema as p, runningFromLawnMower as pt, gasCapability as q, literal as qt, BaseDeviceProvider as r, notificationOutputCapability as rt, ConsumableFormSchema as s, parseAdminBase as st, AlarmArmModeSchema as t, EventCategory as tn, motionCapability as tt, EnumSensorDateTimeFormatSchema as u, presenceCapability as ut, airQualitySensorCapability as v, smokeCapability as vt, binaryCapability as w, updateCapability as wt, automationControlCapability as x, temperatureSensorCapability as xt, alarmPanelCapability as y, switchCapability as yt, coverCapability as z, defineRecordKinds as zt };
|