@camstack/addon-provider-homeassistant 1.2.625 → 1.2.626
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-oNUlRdur.js → dist-1tLY30OG.js} +914 -484
- package/dist/{dist-DvZEnx9C.mjs → dist-B7nW5y58.mjs} +879 -485
- package/dist/ha-export/ha-export.addon.js +26 -19
- package/dist/ha-export/ha-export.addon.mjs +26 -19
- package/package.json +1 -1
|
@@ -5567,7 +5567,7 @@ var ZodIssueCode = {
|
|
|
5567
5567
|
var ZodFirstPartyTypeKind;
|
|
5568
5568
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5569
5569
|
//#endregion
|
|
5570
|
-
//#region ../types/dist/sleep-
|
|
5570
|
+
//#region ../types/dist/sleep-CARd6wZF.mjs
|
|
5571
5571
|
/**
|
|
5572
5572
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5573
5573
|
* window to float samples (D455).
|
|
@@ -8309,6 +8309,102 @@ function defineEntryKind(name, spec) {
|
|
|
8309
8309
|
if (defined === void 0) throw new DeclarationRefusedError(`entry kind "${name}" was not built`);
|
|
8310
8310
|
return defined;
|
|
8311
8311
|
}
|
|
8312
|
+
var READING_QUANTITIES = [
|
|
8313
|
+
"temperature",
|
|
8314
|
+
"pressure",
|
|
8315
|
+
"speed",
|
|
8316
|
+
"precipitation",
|
|
8317
|
+
"precipitation-rate",
|
|
8318
|
+
"length",
|
|
8319
|
+
"area",
|
|
8320
|
+
"illuminance",
|
|
8321
|
+
"irradiance",
|
|
8322
|
+
"power",
|
|
8323
|
+
"energy",
|
|
8324
|
+
"voltage",
|
|
8325
|
+
"current",
|
|
8326
|
+
"apparent-power",
|
|
8327
|
+
"humidity",
|
|
8328
|
+
"percentage",
|
|
8329
|
+
"concentration-volume",
|
|
8330
|
+
"concentration-mass",
|
|
8331
|
+
"concentration-ppb",
|
|
8332
|
+
"volume",
|
|
8333
|
+
"duration",
|
|
8334
|
+
"duration-ms",
|
|
8335
|
+
"information",
|
|
8336
|
+
"sound-level",
|
|
8337
|
+
"signal-level",
|
|
8338
|
+
"colour-temperature",
|
|
8339
|
+
"angle",
|
|
8340
|
+
"bitrate",
|
|
8341
|
+
"rate",
|
|
8342
|
+
"mass",
|
|
8343
|
+
"index",
|
|
8344
|
+
"ratio",
|
|
8345
|
+
"count",
|
|
8346
|
+
"none",
|
|
8347
|
+
"device"
|
|
8348
|
+
];
|
|
8349
|
+
var ReadingQuantitySchema = _enum(READING_QUANTITIES);
|
|
8350
|
+
var QUANTITY_SET = new Set(READING_QUANTITIES);
|
|
8351
|
+
function isReadingQuantity(value) {
|
|
8352
|
+
return typeof value === "string" && QUANTITY_SET.has(value);
|
|
8353
|
+
}
|
|
8354
|
+
/**
|
|
8355
|
+
* Stored unit symbol for a quantity. `none` means the number is dimensionless
|
|
8356
|
+
* (or an index / ratio / count). `device` means the cap has no single unit.
|
|
8357
|
+
*/
|
|
8358
|
+
var QUANTITY_BASE = {
|
|
8359
|
+
temperature: "°C",
|
|
8360
|
+
pressure: "hPa",
|
|
8361
|
+
speed: "m/s",
|
|
8362
|
+
precipitation: "mm",
|
|
8363
|
+
"precipitation-rate": "mm/h",
|
|
8364
|
+
length: "m",
|
|
8365
|
+
area: "m²",
|
|
8366
|
+
illuminance: "lx",
|
|
8367
|
+
irradiance: "W/m²",
|
|
8368
|
+
power: "W",
|
|
8369
|
+
energy: "kWh",
|
|
8370
|
+
voltage: "V",
|
|
8371
|
+
current: "A",
|
|
8372
|
+
"apparent-power": "VA",
|
|
8373
|
+
humidity: "%",
|
|
8374
|
+
percentage: "%",
|
|
8375
|
+
"concentration-volume": "ppm",
|
|
8376
|
+
"concentration-mass": "µg/m³",
|
|
8377
|
+
"concentration-ppb": "ppb",
|
|
8378
|
+
volume: "L",
|
|
8379
|
+
duration: "s",
|
|
8380
|
+
"duration-ms": "ms",
|
|
8381
|
+
information: "B",
|
|
8382
|
+
"sound-level": "dBFS",
|
|
8383
|
+
"signal-level": "dBm",
|
|
8384
|
+
"colour-temperature": "mired",
|
|
8385
|
+
angle: "°",
|
|
8386
|
+
bitrate: "kbps",
|
|
8387
|
+
rate: "fps",
|
|
8388
|
+
mass: "kg",
|
|
8389
|
+
index: "none",
|
|
8390
|
+
ratio: "none",
|
|
8391
|
+
count: "none",
|
|
8392
|
+
none: "none",
|
|
8393
|
+
device: "device"
|
|
8394
|
+
};
|
|
8395
|
+
/** The stored unit, or `undefined` when the quantity has no unit symbol. */
|
|
8396
|
+
function baseUnitOf(quantity) {
|
|
8397
|
+
const symbol = QUANTITY_BASE[quantity];
|
|
8398
|
+
if (symbol === "none" || symbol === "device") return void 0;
|
|
8399
|
+
return symbol;
|
|
8400
|
+
}
|
|
8401
|
+
function readingMeta(quantity, extras) {
|
|
8402
|
+
return {
|
|
8403
|
+
quantity,
|
|
8404
|
+
...extras?.precision !== void 0 ? { precision: extras.precision } : {},
|
|
8405
|
+
...extras?.label !== void 0 ? { label: extras.label } : {}
|
|
8406
|
+
};
|
|
8407
|
+
}
|
|
8312
8408
|
/** Shared Zod schemas used across streaming capabilities. */
|
|
8313
8409
|
var CamProfileSchema = _enum([
|
|
8314
8410
|
"high",
|
|
@@ -8336,8 +8432,8 @@ var CamStreamKindSchema = _enum([
|
|
|
8336
8432
|
"derived"
|
|
8337
8433
|
]);
|
|
8338
8434
|
var CamStreamResolutionSchema = object({
|
|
8339
|
-
width: number().int().positive(),
|
|
8340
|
-
height: number().int().positive()
|
|
8435
|
+
width: number().int().positive().meta(readingMeta("none")),
|
|
8436
|
+
height: number().int().positive().meta(readingMeta("none"))
|
|
8341
8437
|
});
|
|
8342
8438
|
var CameraStreamSchema = object({
|
|
8343
8439
|
/** Stable, provider-assigned id unique within the (deviceId) scope. */
|
|
@@ -9043,14 +9139,6 @@ Object.freeze({
|
|
|
9043
9139
|
{
|
|
9044
9140
|
"path": "aqi",
|
|
9045
9141
|
"valueType": "number"
|
|
9046
|
-
},
|
|
9047
|
-
{
|
|
9048
|
-
"path": "unit",
|
|
9049
|
-
"valueType": "string"
|
|
9050
|
-
},
|
|
9051
|
-
{
|
|
9052
|
-
"path": "precision",
|
|
9053
|
-
"valueType": "number"
|
|
9054
9142
|
}
|
|
9055
9143
|
],
|
|
9056
9144
|
"alarm-panel": [
|
|
@@ -9086,20 +9174,10 @@ Object.freeze({
|
|
|
9086
9174
|
"valueType": "boolean"
|
|
9087
9175
|
}
|
|
9088
9176
|
],
|
|
9089
|
-
"ambient-light-sensor": [
|
|
9090
|
-
|
|
9091
|
-
|
|
9092
|
-
|
|
9093
|
-
},
|
|
9094
|
-
{
|
|
9095
|
-
"path": "unit",
|
|
9096
|
-
"valueType": "string"
|
|
9097
|
-
},
|
|
9098
|
-
{
|
|
9099
|
-
"path": "precision",
|
|
9100
|
-
"valueType": "number"
|
|
9101
|
-
}
|
|
9102
|
-
],
|
|
9177
|
+
"ambient-light-sensor": [{
|
|
9178
|
+
"path": "lux",
|
|
9179
|
+
"valueType": "number"
|
|
9180
|
+
}],
|
|
9103
9181
|
"audio-metrics": [
|
|
9104
9182
|
{
|
|
9105
9183
|
"path": "ts",
|
|
@@ -9179,6 +9257,10 @@ Object.freeze({
|
|
|
9179
9257
|
"path": "lastUpdated",
|
|
9180
9258
|
"valueType": "number"
|
|
9181
9259
|
},
|
|
9260
|
+
{
|
|
9261
|
+
"path": "volts",
|
|
9262
|
+
"valueType": "number"
|
|
9263
|
+
},
|
|
9182
9264
|
{
|
|
9183
9265
|
"path": "lastContactAt",
|
|
9184
9266
|
"valueType": "number"
|
|
@@ -9421,10 +9503,6 @@ Object.freeze({
|
|
|
9421
9503
|
"datetime"
|
|
9422
9504
|
]
|
|
9423
9505
|
},
|
|
9424
|
-
{
|
|
9425
|
-
"path": "unit",
|
|
9426
|
-
"valueType": "string"
|
|
9427
|
-
},
|
|
9428
9506
|
{
|
|
9429
9507
|
"path": "min",
|
|
9430
9508
|
"valueType": "number"
|
|
@@ -9436,19 +9514,6 @@ Object.freeze({
|
|
|
9436
9514
|
{
|
|
9437
9515
|
"path": "step",
|
|
9438
9516
|
"valueType": "number"
|
|
9439
|
-
},
|
|
9440
|
-
{
|
|
9441
|
-
"path": "precision",
|
|
9442
|
-
"valueType": "number"
|
|
9443
|
-
},
|
|
9444
|
-
{
|
|
9445
|
-
"path": "format",
|
|
9446
|
-
"valueType": "enum",
|
|
9447
|
-
"enumValues": [
|
|
9448
|
-
"date",
|
|
9449
|
-
"time",
|
|
9450
|
-
"datetime"
|
|
9451
|
-
]
|
|
9452
9517
|
}
|
|
9453
9518
|
],
|
|
9454
9519
|
"cover": [
|
|
@@ -9689,13 +9754,8 @@ Object.freeze({
|
|
|
9689
9754
|
"path": "value",
|
|
9690
9755
|
"valueType": "string"
|
|
9691
9756
|
}, {
|
|
9692
|
-
"path": "
|
|
9693
|
-
"valueType": "
|
|
9694
|
-
"enumValues": [
|
|
9695
|
-
"date",
|
|
9696
|
-
"time",
|
|
9697
|
-
"datetime"
|
|
9698
|
-
]
|
|
9757
|
+
"path": "timestamp",
|
|
9758
|
+
"valueType": "boolean"
|
|
9699
9759
|
}],
|
|
9700
9760
|
"event-emitter": [
|
|
9701
9761
|
{
|
|
@@ -9802,20 +9862,10 @@ Object.freeze({
|
|
|
9802
9862
|
"valueType": "number"
|
|
9803
9863
|
}
|
|
9804
9864
|
],
|
|
9805
|
-
"humidity-sensor": [
|
|
9806
|
-
|
|
9807
|
-
|
|
9808
|
-
|
|
9809
|
-
},
|
|
9810
|
-
{
|
|
9811
|
-
"path": "unit",
|
|
9812
|
-
"valueType": "string"
|
|
9813
|
-
},
|
|
9814
|
-
{
|
|
9815
|
-
"path": "precision",
|
|
9816
|
-
"valueType": "number"
|
|
9817
|
-
}
|
|
9818
|
-
],
|
|
9865
|
+
"humidity-sensor": [{
|
|
9866
|
+
"path": "percent",
|
|
9867
|
+
"valueType": "number"
|
|
9868
|
+
}],
|
|
9819
9869
|
"image": [{
|
|
9820
9870
|
"path": "url",
|
|
9821
9871
|
"valueType": "string"
|
|
@@ -10154,20 +10204,10 @@ Object.freeze({
|
|
|
10154
10204
|
"valueType": "boolean"
|
|
10155
10205
|
}
|
|
10156
10206
|
],
|
|
10157
|
-
"numeric-sensor": [
|
|
10158
|
-
|
|
10159
|
-
|
|
10160
|
-
|
|
10161
|
-
},
|
|
10162
|
-
{
|
|
10163
|
-
"path": "unit",
|
|
10164
|
-
"valueType": "string"
|
|
10165
|
-
},
|
|
10166
|
-
{
|
|
10167
|
-
"path": "precision",
|
|
10168
|
-
"valueType": "number"
|
|
10169
|
-
}
|
|
10170
|
-
],
|
|
10207
|
+
"numeric-sensor": [{
|
|
10208
|
+
"path": "value",
|
|
10209
|
+
"valueType": "number"
|
|
10210
|
+
}],
|
|
10171
10211
|
"pet-feeder": [
|
|
10172
10212
|
{
|
|
10173
10213
|
"path": "foodLevel",
|
|
@@ -10259,14 +10299,6 @@ Object.freeze({
|
|
|
10259
10299
|
{
|
|
10260
10300
|
"path": "powerFactor",
|
|
10261
10301
|
"valueType": "number"
|
|
10262
|
-
},
|
|
10263
|
-
{
|
|
10264
|
-
"path": "unit",
|
|
10265
|
-
"valueType": "string"
|
|
10266
|
-
},
|
|
10267
|
-
{
|
|
10268
|
-
"path": "precision",
|
|
10269
|
-
"valueType": "number"
|
|
10270
10302
|
}
|
|
10271
10303
|
],
|
|
10272
10304
|
"presence": [
|
|
@@ -10295,20 +10327,10 @@ Object.freeze({
|
|
|
10295
10327
|
"valueType": "number"
|
|
10296
10328
|
}
|
|
10297
10329
|
],
|
|
10298
|
-
"pressure-sensor": [
|
|
10299
|
-
|
|
10300
|
-
|
|
10301
|
-
|
|
10302
|
-
},
|
|
10303
|
-
{
|
|
10304
|
-
"path": "unit",
|
|
10305
|
-
"valueType": "string"
|
|
10306
|
-
},
|
|
10307
|
-
{
|
|
10308
|
-
"path": "precision",
|
|
10309
|
-
"valueType": "number"
|
|
10310
|
-
}
|
|
10311
|
-
],
|
|
10330
|
+
"pressure-sensor": [{
|
|
10331
|
+
"path": "hpa",
|
|
10332
|
+
"valueType": "number"
|
|
10333
|
+
}],
|
|
10312
10334
|
"privacy-mask": [{
|
|
10313
10335
|
"path": "enabled",
|
|
10314
10336
|
"valueType": "boolean"
|
|
@@ -10619,20 +10641,10 @@ Object.freeze({
|
|
|
10619
10641
|
"path": "tampered",
|
|
10620
10642
|
"valueType": "boolean"
|
|
10621
10643
|
}],
|
|
10622
|
-
"temperature-sensor": [
|
|
10623
|
-
|
|
10624
|
-
|
|
10625
|
-
|
|
10626
|
-
},
|
|
10627
|
-
{
|
|
10628
|
-
"path": "unit",
|
|
10629
|
-
"valueType": "string"
|
|
10630
|
-
},
|
|
10631
|
-
{
|
|
10632
|
-
"path": "precision",
|
|
10633
|
-
"valueType": "number"
|
|
10634
|
-
}
|
|
10635
|
-
],
|
|
10644
|
+
"temperature-sensor": [{
|
|
10645
|
+
"path": "celsius",
|
|
10646
|
+
"valueType": "number"
|
|
10647
|
+
}],
|
|
10636
10648
|
"update": [
|
|
10637
10649
|
{
|
|
10638
10650
|
"path": "currentVersion",
|
|
@@ -10743,10 +10755,6 @@ Object.freeze({
|
|
|
10743
10755
|
"path": "temperature",
|
|
10744
10756
|
"valueType": "number"
|
|
10745
10757
|
},
|
|
10746
|
-
{
|
|
10747
|
-
"path": "temperatureUnit",
|
|
10748
|
-
"valueType": "string"
|
|
10749
|
-
},
|
|
10750
10758
|
{
|
|
10751
10759
|
"path": "humidity",
|
|
10752
10760
|
"valueType": "number"
|
|
@@ -10755,18 +10763,10 @@ Object.freeze({
|
|
|
10755
10763
|
"path": "pressure",
|
|
10756
10764
|
"valueType": "number"
|
|
10757
10765
|
},
|
|
10758
|
-
{
|
|
10759
|
-
"path": "pressureUnit",
|
|
10760
|
-
"valueType": "string"
|
|
10761
|
-
},
|
|
10762
10766
|
{
|
|
10763
10767
|
"path": "windSpeed",
|
|
10764
10768
|
"valueType": "number"
|
|
10765
10769
|
},
|
|
10766
|
-
{
|
|
10767
|
-
"path": "windSpeedUnit",
|
|
10768
|
-
"valueType": "string"
|
|
10769
|
-
},
|
|
10770
10770
|
{
|
|
10771
10771
|
"path": "windBearing",
|
|
10772
10772
|
"valueType": "number"
|
|
@@ -18442,7 +18442,8 @@ var CompositionProblemSchema = object({
|
|
|
18442
18442
|
"item-field-reserved",
|
|
18443
18443
|
"target-missing",
|
|
18444
18444
|
"target-unreadable",
|
|
18445
|
-
"not-replaceable"
|
|
18445
|
+
"not-replaceable",
|
|
18446
|
+
"native-capability-replace"
|
|
18446
18447
|
]),
|
|
18447
18448
|
path: string(),
|
|
18448
18449
|
message: string()
|
|
@@ -18500,9 +18501,11 @@ var CompositionFieldPlanSchema = object({
|
|
|
18500
18501
|
reads: array(CompositionFieldReadSchema)
|
|
18501
18502
|
});
|
|
18502
18503
|
/**
|
|
18503
|
-
* What a feature does to its target (D663): `new` builds a capability on a
|
|
18504
|
-
* device; on an existing device it `add`s a capability the device lacks
|
|
18505
|
-
*
|
|
18504
|
+
* What a feature does to its target (D663, D944): `new` builds a capability on a
|
|
18505
|
+
* new device; on an existing device it `add`s a capability the device lacks.
|
|
18506
|
+
* Replacing a capability the device already serves is refused
|
|
18507
|
+
* (`native-capability-replace`), not planned. `replace` remains on the claim
|
|
18508
|
+
* wire for a claim the hub already holds.
|
|
18506
18509
|
*/
|
|
18507
18510
|
var CompositionFeatureModeSchema = _enum([
|
|
18508
18511
|
"new",
|
|
@@ -20535,12 +20538,12 @@ function parseAdminBase(baseUrl) {
|
|
|
20535
20538
|
* providers detect renames by matching `uniqueId` and patch `id`
|
|
20536
20539
|
* in-place so dispatch keeps working.
|
|
20537
20540
|
*
|
|
20538
|
-
* **
|
|
20539
|
-
*
|
|
20540
|
-
*
|
|
20541
|
-
*
|
|
20542
|
-
* (`ha-domain-mapping`)
|
|
20543
|
-
* stored after that point.
|
|
20541
|
+
* **Display unit and precision are NOT stored here.** They are a read-time
|
|
20542
|
+
* preference (D944). A polymorphic reading stores its `quantity` here once,
|
|
20543
|
+
* at adopt, and a date/time value stores `dateTimeShape` the same way —
|
|
20544
|
+
* neither is repeated on each sample. The `device_class` tag is an
|
|
20545
|
+
* HA-specific input consumed at the discovery boundary (`ha-domain-mapping`)
|
|
20546
|
+
* to derive the CamStack `DeviceRole`; it is never stored after that point.
|
|
20544
20547
|
*
|
|
20545
20548
|
* The `raw` escape hatch carries provider-specific attributes that don't
|
|
20546
20549
|
* fit the structured slots (HA `attributes` whitelist, Reolink `deviceCache`
|
|
@@ -20554,6 +20557,14 @@ var SourceInfoSchema = object({
|
|
|
20554
20557
|
/** Immutable upstream identifier when available (HA `unique_id`, … ).
|
|
20555
20558
|
* Used to detect rename when `id` changes. */
|
|
20556
20559
|
uniqueId: string().optional(),
|
|
20560
|
+
/** Quantity of a polymorphic reading, written once at adopt (D944). */
|
|
20561
|
+
quantity: ReadingQuantitySchema.optional(),
|
|
20562
|
+
/** Date / time / datetime shape of a string reading, written once at adopt. */
|
|
20563
|
+
dateTimeShape: _enum([
|
|
20564
|
+
"date",
|
|
20565
|
+
"time",
|
|
20566
|
+
"datetime"
|
|
20567
|
+
]).optional(),
|
|
20557
20568
|
/** Provider-specific extras that don't fit the structured slots.
|
|
20558
20569
|
* Whitelist what goes here per provider — do NOT dump entire HA
|
|
20559
20570
|
* attribute blobs (would explode the meta JSON column). */
|
|
@@ -20638,9 +20649,38 @@ function normalizeUnit(raw) {
|
|
|
20638
20649
|
if (lower === "mph") return "mph";
|
|
20639
20650
|
if (lower === "m/s") return "m/s";
|
|
20640
20651
|
if (lower === "m") return "m";
|
|
20652
|
+
if (lower === "m²" || lower === "m2") return "m²";
|
|
20653
|
+
if (lower === "mm") return "mm";
|
|
20654
|
+
if (lower === "cm") return "cm";
|
|
20641
20655
|
if (lower === "km") return "km";
|
|
20656
|
+
if (lower === "in" || lower === "inch" || lower === "inches") return "in";
|
|
20657
|
+
if (lower === "ft" || lower === "foot" || lower === "feet") return "ft";
|
|
20642
20658
|
if (lower === "kg") return "kg";
|
|
20643
20659
|
if (lower === "g") return "g";
|
|
20660
|
+
if (lower === "l" || lower === "liter" || lower === "litre" || lower === "liters" || lower === "litres") return "L";
|
|
20661
|
+
if (lower === "ml") return "mL";
|
|
20662
|
+
if (lower === "gal" || lower === "gallon" || lower === "gallons") return "gal";
|
|
20663
|
+
if (lower === "s" || lower === "sec" || lower === "second" || lower === "seconds") return "s";
|
|
20664
|
+
if (lower === "ms") return "ms";
|
|
20665
|
+
if (lower === "min" || lower === "minute" || lower === "minutes") return "min";
|
|
20666
|
+
if (lower === "h" || lower === "hr" || lower === "hour" || lower === "hours") return "h";
|
|
20667
|
+
if (lower === "d" || lower === "day" || lower === "days") return "d";
|
|
20668
|
+
if (lower === "b" || lower === "byte" || lower === "bytes") return "B";
|
|
20669
|
+
if (lower === "kib") return "KiB";
|
|
20670
|
+
if (lower === "mib") return "MiB";
|
|
20671
|
+
if (lower === "gib") return "GiB";
|
|
20672
|
+
if (lower === "tib") return "TiB";
|
|
20673
|
+
if (lower === "kb") return "kB";
|
|
20674
|
+
if (lower === "mb") return "MB";
|
|
20675
|
+
if (lower === "gb") return "GB";
|
|
20676
|
+
if (lower === "dbm") return "dBm";
|
|
20677
|
+
if (lower === "dbfs") return "dBFS";
|
|
20678
|
+
if (lower === "inhg") return "inHg";
|
|
20679
|
+
if (lower === "mm/h") return "mm/h";
|
|
20680
|
+
if (lower === "w/m²" || lower === "w/m2") return "W/m²";
|
|
20681
|
+
if (lower === "°" || lower === "deg" || lower === "degree" || lower === "degrees") return "°";
|
|
20682
|
+
if (lower === "kbps") return "kbps";
|
|
20683
|
+
if (lower === "fps") return "fps";
|
|
20644
20684
|
return trimmed;
|
|
20645
20685
|
}
|
|
20646
20686
|
/**
|
|
@@ -41745,7 +41785,8 @@ method(object({
|
|
|
41745
41785
|
"enum"
|
|
41746
41786
|
]),
|
|
41747
41787
|
enumValues: array(string()).optional(),
|
|
41748
|
-
item: boolean().optional()
|
|
41788
|
+
item: boolean().optional(),
|
|
41789
|
+
quantity: ReadingQuantitySchema.optional()
|
|
41749
41790
|
})).readonly(),
|
|
41750
41791
|
itemArray: object({
|
|
41751
41792
|
path: string(),
|
|
@@ -45611,8 +45652,8 @@ var MaskPolygonShapeSchema = object({
|
|
|
45611
45652
|
/** Boolean cell grid — row-major, length === gridWidth*gridHeight. */
|
|
45612
45653
|
var MaskGridShapeSchema = object({
|
|
45613
45654
|
kind: literal("grid"),
|
|
45614
|
-
gridWidth: number(),
|
|
45615
|
-
gridHeight: number(),
|
|
45655
|
+
gridWidth: number().meta(readingMeta("none")),
|
|
45656
|
+
gridHeight: number().meta(readingMeta("none")),
|
|
45616
45657
|
cells: array(boolean())
|
|
45617
45658
|
});
|
|
45618
45659
|
discriminatedUnion("kind", [
|
|
@@ -57180,27 +57221,17 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
|
|
|
57180
57221
|
*/
|
|
57181
57222
|
var AirQualitySensorStatusSchema = object({
|
|
57182
57223
|
/** Carbon dioxide concentration in ppm. */
|
|
57183
|
-
co2Ppm: number().min(0).optional(),
|
|
57224
|
+
co2Ppm: number().min(0).optional().meta(readingMeta("concentration-volume")),
|
|
57184
57225
|
/** Total volatile organic compounds in ppb. */
|
|
57185
|
-
vocPpb: number().min(0).optional(),
|
|
57226
|
+
vocPpb: number().min(0).optional().meta(readingMeta("concentration-ppb")),
|
|
57186
57227
|
/** Particulate matter ≤ 2.5 μm in µg/m³. */
|
|
57187
|
-
pm25: number().min(0).optional(),
|
|
57228
|
+
pm25: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
57188
57229
|
/** Particulate matter ≤ 10 μm in µg/m³. */
|
|
57189
|
-
pm10: number().min(0).optional(),
|
|
57230
|
+
pm10: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
57190
57231
|
/** Composite AQI value (typically 0..500). */
|
|
57191
|
-
aqi: number().optional(),
|
|
57232
|
+
aqi: number().optional().meta(readingMeta("index")),
|
|
57192
57233
|
/** Ms epoch when the slice was last updated. */
|
|
57193
|
-
lastFetchedAt: number()
|
|
57194
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
57195
|
-
* `attributes.unit_of_measurement` → 'ppm' / 'ppb' / 'µg/m³'). Each
|
|
57196
|
-
* upstream `sensor.*` entity surfaces ONE device_class, so one unit
|
|
57197
|
-
* per slice is unambiguous. */
|
|
57198
|
-
unit: string().optional(),
|
|
57199
|
-
/** Suggested decimal places for numeric display.
|
|
57200
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
57201
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
57202
|
-
* auto-formatting when absent. */
|
|
57203
|
-
precision: number().int().min(0).max(10).optional()
|
|
57234
|
+
lastFetchedAt: number()
|
|
57204
57235
|
});
|
|
57205
57236
|
var airQualitySensorCapability = {
|
|
57206
57237
|
name: "air-quality-sensor",
|
|
@@ -57237,12 +57268,12 @@ var airQualitySensorCapability = {
|
|
|
57237
57268
|
},
|
|
57238
57269
|
pm25: {
|
|
57239
57270
|
kind: "gauge",
|
|
57240
|
-
unit: "
|
|
57271
|
+
unit: "µg/m³",
|
|
57241
57272
|
deadband: 1
|
|
57242
57273
|
},
|
|
57243
57274
|
pm10: {
|
|
57244
57275
|
kind: "gauge",
|
|
57245
|
-
unit: "
|
|
57276
|
+
unit: "µg/m³",
|
|
57246
57277
|
deadband: 1
|
|
57247
57278
|
},
|
|
57248
57279
|
aqi: {
|
|
@@ -57260,22 +57291,13 @@ var airQualitySensorCapability = {
|
|
|
57260
57291
|
* entries with `device_class: illuminance`.
|
|
57261
57292
|
*/
|
|
57262
57293
|
var AmbientLightSensorStatusSchema = object({
|
|
57263
|
-
/** Current illuminance in lux (lx). */
|
|
57264
|
-
lux: number().min(0).meta({
|
|
57265
|
-
|
|
57294
|
+
/** Current illuminance in lux (lx). `null` when the sample was refused (D393). */
|
|
57295
|
+
lux: number().min(0).nullable().meta(readingMeta("illuminance", {
|
|
57296
|
+
precision: 0,
|
|
57266
57297
|
label: "Illuminance"
|
|
57267
|
-
}),
|
|
57298
|
+
})),
|
|
57268
57299
|
/** Ms epoch when the slice was last updated. */
|
|
57269
|
-
lastFetchedAt: number()
|
|
57270
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
57271
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
57272
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
57273
|
-
unit: string().optional(),
|
|
57274
|
-
/** Suggested decimal places for numeric display.
|
|
57275
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
57276
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
57277
|
-
* auto-formatting when absent. */
|
|
57278
|
-
precision: number().int().min(0).max(10).optional()
|
|
57300
|
+
lastFetchedAt: number()
|
|
57279
57301
|
});
|
|
57280
57302
|
var ambientLightSensorCapability = {
|
|
57281
57303
|
name: "ambient-light-sensor",
|
|
@@ -57307,12 +57329,7 @@ var ambientLightSensorCapability = {
|
|
|
57307
57329
|
} } },
|
|
57308
57330
|
/** Clock fields: written, but excluded from the compare that decides
|
|
57309
57331
|
* whether persisting is worth a SQLite commit. */
|
|
57310
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
57311
|
-
customize: {
|
|
57312
|
-
version: 1,
|
|
57313
|
-
advanced: "derive",
|
|
57314
|
-
targets: []
|
|
57315
|
-
}
|
|
57332
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
57316
57333
|
};
|
|
57317
57334
|
/**
|
|
57318
57335
|
* Per-class audio metrics aggregated over a sliding window.
|
|
@@ -57539,10 +57556,7 @@ var BatteryStatusSchema = object({
|
|
|
57539
57556
|
* Consumers must SKIP a null rather than coerce it — `battery-band` already
|
|
57540
57557
|
* declines to band a non-finite reading, which is the correct shape.
|
|
57541
57558
|
*/
|
|
57542
|
-
percentage: number().min(0).max(100).nullable().meta({
|
|
57543
|
-
unit: "%",
|
|
57544
|
-
label: "Charge"
|
|
57545
|
-
}),
|
|
57559
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage", { label: "Charge" })),
|
|
57546
57560
|
/**
|
|
57547
57561
|
* Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
|
|
57548
57562
|
* Reolink-specific for the Solar Panel 2 accessory (will become
|
|
@@ -57569,7 +57583,14 @@ var BatteryStatusSchema = object({
|
|
|
57569
57583
|
*/
|
|
57570
57584
|
sleeping: boolean().meta({ label: "Sleeping" }),
|
|
57571
57585
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
57572
|
-
lastUpdated: number(),
|
|
57586
|
+
lastUpdated: number().meta(readingMeta("none")),
|
|
57587
|
+
/**
|
|
57588
|
+
* Battery voltage in volts, for a cell the firmware reports as voltage
|
|
57589
|
+
* rather than a percentage (Ecowitt capacitor packs). Absent on cameras
|
|
57590
|
+
* that only report charge. A second reading on this cap, not a second
|
|
57591
|
+
* `numeric-sensor` on the same device.
|
|
57592
|
+
*/
|
|
57593
|
+
volts: number().nullable().optional().meta(readingMeta("voltage", { label: "Voltage" })),
|
|
57573
57594
|
/**
|
|
57574
57595
|
* Ms epoch of the last time the device PROVED it was reachable — a
|
|
57575
57596
|
* completed firmware round-trip, an observed wake, or an inbound push
|
|
@@ -57621,7 +57642,6 @@ var BATTERY_DEVICE_TYPES = [
|
|
|
57621
57642
|
/** Generic Customize target for the percentage reading (D936). */
|
|
57622
57643
|
var batteryCustomize = {
|
|
57623
57644
|
version: 1,
|
|
57624
|
-
advanced: "derive",
|
|
57625
57645
|
targets: [{
|
|
57626
57646
|
id: "percentage",
|
|
57627
57647
|
cardinality: "scalar",
|
|
@@ -57630,7 +57650,7 @@ var batteryCustomize = {
|
|
|
57630
57650
|
stateField: "percentage"
|
|
57631
57651
|
},
|
|
57632
57652
|
deviceTypes: BATTERY_DEVICE_TYPES,
|
|
57633
|
-
apply: "add
|
|
57653
|
+
apply: "add",
|
|
57634
57654
|
path: "percentage",
|
|
57635
57655
|
sources: [{
|
|
57636
57656
|
kind: "field",
|
|
@@ -57751,10 +57771,16 @@ onStatusChanged: { data: object({
|
|
|
57751
57771
|
/**
|
|
57752
57772
|
* History (D850): recorded series. The generic capture replaces the `battery` series of `pipeline-analytics:stats-5m`.
|
|
57753
57773
|
*/
|
|
57754
|
-
history: { fields: {
|
|
57755
|
-
|
|
57756
|
-
|
|
57757
|
-
|
|
57774
|
+
history: { fields: {
|
|
57775
|
+
percentage: {
|
|
57776
|
+
kind: "gauge",
|
|
57777
|
+
unit: "%"
|
|
57778
|
+
},
|
|
57779
|
+
volts: {
|
|
57780
|
+
kind: "gauge",
|
|
57781
|
+
unit: "V"
|
|
57782
|
+
}
|
|
57783
|
+
} },
|
|
57758
57784
|
customize: batteryCustomize,
|
|
57759
57785
|
/** Clock fields: written, but excluded from the compare that decides
|
|
57760
57786
|
* whether persisting is worth a SQLite commit. */
|
|
@@ -57801,12 +57827,7 @@ var binaryCapability = {
|
|
|
57801
57827
|
history: { fields: { on: { kind: "boolean" } } },
|
|
57802
57828
|
/** Clock fields: written, but excluded from the compare that decides
|
|
57803
57829
|
* whether persisting is worth a SQLite commit. */
|
|
57804
|
-
volatileStateFields: ["lastChangedAt"]
|
|
57805
|
-
customize: {
|
|
57806
|
-
version: 1,
|
|
57807
|
-
advanced: "derive",
|
|
57808
|
-
targets: []
|
|
57809
|
-
}
|
|
57830
|
+
volatileStateFields: ["lastChangedAt"]
|
|
57810
57831
|
};
|
|
57811
57832
|
/**
|
|
57812
57833
|
* Dimmable-light brightness control. Co-exists with `switch` on the
|
|
@@ -57822,7 +57843,7 @@ var binaryCapability = {
|
|
|
57822
57843
|
*/
|
|
57823
57844
|
var BrightnessStatusSchema = object({
|
|
57824
57845
|
/** Current level as 0..100 inclusive. Firmware-reported. */
|
|
57825
|
-
percentage: number().min(0).max(100),
|
|
57846
|
+
percentage: number().min(0).max(100).meta(readingMeta("percentage")),
|
|
57826
57847
|
/** Ms epoch of the last operator-driven change. Useful for UI freshness. */
|
|
57827
57848
|
lastChangedAt: number()
|
|
57828
57849
|
});
|
|
@@ -58303,21 +58324,21 @@ var ClimateControlStatusSchema = object({
|
|
|
58303
58324
|
/** Single setpoint in Celsius. Used by single-target modes
|
|
58304
58325
|
* (heat / cool / dry). Null when the device is in a range mode
|
|
58305
58326
|
* (`heat_cool`) or has no setpoint at all (`fan_only`/`off`). */
|
|
58306
|
-
target: number().nullable(),
|
|
58327
|
+
target: number().nullable().meta(readingMeta("temperature")),
|
|
58307
58328
|
/** Upper bound of the dual setpoint in Celsius. Populated only
|
|
58308
58329
|
* in `heat_cool` mode. */
|
|
58309
|
-
targetHigh: number().nullable(),
|
|
58330
|
+
targetHigh: number().nullable().meta(readingMeta("temperature")),
|
|
58310
58331
|
/** Lower bound of the dual setpoint in Celsius. Populated only
|
|
58311
58332
|
* in `heat_cool` mode. */
|
|
58312
|
-
targetLow: number().nullable(),
|
|
58333
|
+
targetLow: number().nullable().meta(readingMeta("temperature")),
|
|
58313
58334
|
/** Target relative humidity (0..100). Null when the device has no
|
|
58314
58335
|
* humidity control. */
|
|
58315
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
58336
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
58316
58337
|
/** Current measured temperature in Celsius. Read-only — pushed by
|
|
58317
58338
|
* the device's internal sensor. */
|
|
58318
|
-
currentTemp: number().nullable(),
|
|
58339
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
58319
58340
|
/** Current measured relative humidity (0..100). Read-only. */
|
|
58320
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
58341
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
58321
58342
|
/** Vertical louver swing on/off. Null when the device has no vertical
|
|
58322
58343
|
* swing surface (gate with `DeviceFeature.ClimateSwingVertical`). */
|
|
58323
58344
|
swingVertical: boolean().nullable(),
|
|
@@ -58325,11 +58346,11 @@ var ClimateControlStatusSchema = object({
|
|
|
58325
58346
|
* horizontal swing surface (gate with `DeviceFeature.ClimateSwingHorizontal`). */
|
|
58326
58347
|
swingHorizontal: boolean().nullable(),
|
|
58327
58348
|
/** Lowest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
58328
|
-
minTemp: number().nullable().optional(),
|
|
58349
|
+
minTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
58329
58350
|
/** Highest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
58330
|
-
maxTemp: number().nullable().optional(),
|
|
58351
|
+
maxTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
58331
58352
|
/** Setpoint granularity, Celsius (0.5, 1). Absent / null = not reported. */
|
|
58332
|
-
tempStep: number().positive().nullable().optional(),
|
|
58353
|
+
tempStep: number().positive().nullable().optional().meta(readingMeta("temperature")),
|
|
58333
58354
|
/** Ms epoch when the slice was last updated (push or command). */
|
|
58334
58355
|
lastFetchedAt: number()
|
|
58335
58356
|
});
|
|
@@ -58471,17 +58492,17 @@ var climateControlCapability = {
|
|
|
58471
58492
|
* modes to expose in the picker without a slice fetch.
|
|
58472
58493
|
*/
|
|
58473
58494
|
var RgbTripletSchema = object({
|
|
58474
|
-
r: number().int().min(0).max(255),
|
|
58475
|
-
g: number().int().min(0).max(255),
|
|
58476
|
-
b: number().int().min(0).max(255)
|
|
58495
|
+
r: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
58496
|
+
g: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
58497
|
+
b: number().int().min(0).max(255).meta(readingMeta("none"))
|
|
58477
58498
|
});
|
|
58478
58499
|
var HsvTripletSchema = object({
|
|
58479
58500
|
/** Hue in degrees, 0..360. */
|
|
58480
|
-
h: number().min(0).max(360),
|
|
58501
|
+
h: number().min(0).max(360).meta(readingMeta("none")),
|
|
58481
58502
|
/** Saturation as 0..100 inclusive. */
|
|
58482
|
-
s: number().min(0).max(100),
|
|
58503
|
+
s: number().min(0).max(100).meta(readingMeta("none")),
|
|
58483
58504
|
/** Value/brightness as 0..100 inclusive. */
|
|
58484
|
-
v: number().min(0).max(100)
|
|
58505
|
+
v: number().min(0).max(100).meta(readingMeta("none"))
|
|
58485
58506
|
});
|
|
58486
58507
|
var ColorInputSchema = discriminatedUnion("mode", [
|
|
58487
58508
|
object({
|
|
@@ -58510,7 +58531,7 @@ var ColorStatusSchema = object({
|
|
|
58510
58531
|
/** Populated when `mode === 'hsv'`. */
|
|
58511
58532
|
hsv: HsvTripletSchema.optional(),
|
|
58512
58533
|
/** Populated when `mode === 'mired'`. */
|
|
58513
|
-
mireds: number().int().optional(),
|
|
58534
|
+
mireds: number().int().optional().meta(readingMeta("colour-temperature")),
|
|
58514
58535
|
/** Ms epoch of the last operator-driven change. */
|
|
58515
58536
|
lastChangedAt: number()
|
|
58516
58537
|
});
|
|
@@ -58719,18 +58740,12 @@ var FORM_OF_KIND = {
|
|
|
58719
58740
|
function consumableFormOf(item) {
|
|
58720
58741
|
return item.form ?? FORM_OF_KIND[consumableKindOf(item)];
|
|
58721
58742
|
}
|
|
58722
|
-
/**
|
|
58723
|
-
|
|
58724
|
-
|
|
58725
|
-
"days",
|
|
58726
|
-
"hours",
|
|
58727
|
-
"cycles"
|
|
58728
|
-
]);
|
|
58729
|
-
/** Remaining life as a COUNT, not a percentage (the PetKit desiccant reports
|
|
58730
|
-
* days). `value` null = unknown (D393). */
|
|
58743
|
+
/** Whether `remaining.value` is a duration in seconds or a dimensionless count. */
|
|
58744
|
+
var ConsumableRemainingKindSchema = _enum(["duration", "count"]);
|
|
58745
|
+
/** Remaining life. `value` null = unknown (D393). Duration is seconds. */
|
|
58731
58746
|
var ConsumableRemainingSchema = object({
|
|
58732
|
-
value: number().min(0).nullable(),
|
|
58733
|
-
|
|
58747
|
+
value: number().min(0).nullable().meta(readingMeta("device")),
|
|
58748
|
+
kind: ConsumableRemainingKindSchema
|
|
58734
58749
|
});
|
|
58735
58750
|
/** A single consumable item. Either a continuous `level` (remaining
|
|
58736
58751
|
* life %, or fill % for a `supply` / `waste` item) or a discrete `status`
|
|
@@ -58743,7 +58758,7 @@ var ConsumableItemSchema = object({
|
|
|
58743
58758
|
/** Display name. */
|
|
58744
58759
|
label: string().min(1),
|
|
58745
58760
|
/** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
|
|
58746
|
-
level: number().min(0).max(100).nullable(),
|
|
58761
|
+
level: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58747
58762
|
/** The provider's discrete verdict when known (binary mode). */
|
|
58748
58763
|
status: ConsumableStatusSchema.nullable(),
|
|
58749
58764
|
/** What the item is — decides whether low or full is bad. Absent = `wear`. */
|
|
@@ -58825,8 +58840,8 @@ var consumablesCustomize = {
|
|
|
58825
58840
|
transforms: [{ kind: "identity" }]
|
|
58826
58841
|
}],
|
|
58827
58842
|
literals: [{
|
|
58828
|
-
path: "remaining.
|
|
58829
|
-
values: [...
|
|
58843
|
+
path: "remaining.kind",
|
|
58844
|
+
values: [...ConsumableRemainingKindSchema.options]
|
|
58830
58845
|
}]
|
|
58831
58846
|
},
|
|
58832
58847
|
{
|
|
@@ -58955,7 +58970,6 @@ reset: method(object({
|
|
|
58955
58970
|
},
|
|
58956
58971
|
"remaining.value": {
|
|
58957
58972
|
kind: "gauge",
|
|
58958
|
-
unitFrom: "remaining.unit",
|
|
58959
58973
|
deadband: 1,
|
|
58960
58974
|
displayName: "Remaining"
|
|
58961
58975
|
}
|
|
@@ -59025,10 +59039,9 @@ var contactCapability = {
|
|
|
59025
59039
|
* (empty array for the other kinds). It lives in the slice because
|
|
59026
59040
|
* HA `select.*` entities may update their options at runtime.
|
|
59027
59041
|
*
|
|
59028
|
-
*
|
|
59029
|
-
*
|
|
59030
|
-
*
|
|
59031
|
-
* push — consistent with `options` and the sensor-unit approach.
|
|
59042
|
+
* Numeric `min` / `max` / `step` live in the slice and share the device
|
|
59043
|
+
* quantity (`SourceInfo.quantity`, D944). Display precision is a read-time
|
|
59044
|
+
* preference. A datetime control's shape is `SourceInfo.dateTimeShape`.
|
|
59032
59045
|
*/
|
|
59033
59046
|
var ControlStatusSchema = object({
|
|
59034
59047
|
kind: _enum([
|
|
@@ -59040,39 +59053,17 @@ var ControlStatusSchema = object({
|
|
|
59040
59053
|
/** Current value. Numeric kind → number; select/text/datetime → string.
|
|
59041
59054
|
* Datetime values are ISO 8601 strings (full timestamp, date-only,
|
|
59042
59055
|
* or time-only — HA accepts all three forms). */
|
|
59043
|
-
value: union([number(), string()]),
|
|
59056
|
+
value: union([number().meta(readingMeta("device")), string()]),
|
|
59044
59057
|
/** Acceptable values when `kind === 'select'`. Empty for other kinds. */
|
|
59045
59058
|
options: array(string()),
|
|
59046
59059
|
/** Ms epoch when the slice was last updated. */
|
|
59047
59060
|
lastChangedAt: number(),
|
|
59048
|
-
/**
|
|
59049
|
-
|
|
59050
|
-
|
|
59051
|
-
|
|
59052
|
-
/**
|
|
59053
|
-
|
|
59054
|
-
min: number().optional(),
|
|
59055
|
-
/** Maximum allowed value. Populated live from HA `attributes.max`.
|
|
59056
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
59057
|
-
max: number().optional(),
|
|
59058
|
-
/** Step increment. Populated live from HA `attributes.step`.
|
|
59059
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
59060
|
-
step: number().optional(),
|
|
59061
|
-
/** Suggested decimal places for numeric display. Populated live from HA
|
|
59062
|
-
* `attributes.suggested_display_precision`, or derived from `step` when the
|
|
59063
|
-
* HA attribute is absent. Meaningful for `kind === 'numeric'`; absent for
|
|
59064
|
-
* other kinds. Falls back to auto-formatting when absent. */
|
|
59065
|
-
precision: number().int().min(0).max(10).optional(),
|
|
59066
|
-
/** Date-picker granularity for `kind === 'datetime'`. 'date' → date-only,
|
|
59067
|
-
* 'time' → time-only, 'datetime' → full timestamp. Absent for other kinds
|
|
59068
|
-
* (UI defaults to 'datetime'). Derived live from the device's HA domain
|
|
59069
|
-
* (date.* / time.* / datetime.*) or, for input_datetime, from the entity's
|
|
59070
|
-
* `has_date`/`has_time` attributes on each push. */
|
|
59071
|
-
format: _enum([
|
|
59072
|
-
"date",
|
|
59073
|
-
"time",
|
|
59074
|
-
"datetime"
|
|
59075
|
-
]).optional()
|
|
59061
|
+
/** Minimum allowed value, in the device quantity's base unit. */
|
|
59062
|
+
min: number().optional().meta(readingMeta("device")),
|
|
59063
|
+
/** Maximum allowed value, in the device quantity's base unit. */
|
|
59064
|
+
max: number().optional().meta(readingMeta("device")),
|
|
59065
|
+
/** Step increment, in the device quantity's base unit. */
|
|
59066
|
+
step: number().optional().meta(readingMeta("device"))
|
|
59076
59067
|
});
|
|
59077
59068
|
var ControlSetValueInputSchema = discriminatedUnion("kind", [
|
|
59078
59069
|
object({
|
|
@@ -59138,9 +59129,9 @@ var CoverStatusSchema = object({
|
|
|
59138
59129
|
]),
|
|
59139
59130
|
/** 0 = fully closed, 100 = fully open. Null when the device has
|
|
59140
59131
|
* no intermediate position surface. */
|
|
59141
|
-
position: number().min(0).max(100).nullable(),
|
|
59132
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59142
59133
|
/** 0 = closed slats, 100 = open slats. Null when no tilt support. */
|
|
59143
|
-
tiltPosition: number().min(0).max(100).nullable(),
|
|
59134
|
+
tiltPosition: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59144
59135
|
/** Ms epoch when the slice was last updated. */
|
|
59145
59136
|
lastChangedAt: number()
|
|
59146
59137
|
});
|
|
@@ -59243,9 +59234,9 @@ var NormalizedRangeSchema$1 = object({
|
|
|
59243
59234
|
var DayNightStatusSchema = object({
|
|
59244
59235
|
mode: DayNightModeSchema,
|
|
59245
59236
|
/** IR-cut trigger sensitivity, NORMALIZED 0–100 (higher = switches to night sooner). */
|
|
59246
|
-
sensitivity: number().optional(),
|
|
59237
|
+
sensitivity: number().optional().meta(readingMeta("none")),
|
|
59247
59238
|
/** Delay before the IR-cut filter flips, in seconds. */
|
|
59248
|
-
switchDelaySec: number().optional(),
|
|
59239
|
+
switchDelaySec: number().optional().meta(readingMeta("duration")),
|
|
59249
59240
|
lastFetchedAt: number()
|
|
59250
59241
|
});
|
|
59251
59242
|
/**
|
|
@@ -59463,11 +59454,11 @@ var DishwasherStatusSchema = object({
|
|
|
59463
59454
|
/** Feature keys of the programs the appliance currently offers — drives the UI selector. */
|
|
59464
59455
|
availablePrograms: array(string()),
|
|
59465
59456
|
/** Seconds remaining on the active cycle, or null when not running / not known. */
|
|
59466
|
-
remainingSeconds: number().int().nonnegative().nullable(),
|
|
59457
|
+
remainingSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
59467
59458
|
/** Seconds the delayed start is set to (time until the cycle starts), or null. */
|
|
59468
|
-
delayedStartSeconds: number().int().nonnegative().nullable(),
|
|
59459
|
+
delayedStartSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
59469
59460
|
/** Cycle completion 0..100, or null when not applicable. */
|
|
59470
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
59461
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59471
59462
|
/** True when the door is reported open; null when the door state is not known. */
|
|
59472
59463
|
doorOpen: boolean().nullable(),
|
|
59473
59464
|
/** True when the door is latched (locked) during a cycle; null when not reported. */
|
|
@@ -59491,7 +59482,7 @@ var DishwasherStatusSchema = object({
|
|
|
59491
59482
|
/** True while the machine-care (descaling / cleaning-program) reminder is raised; false when clear; null when not reported. */
|
|
59492
59483
|
machineCareDue: boolean().nullable(),
|
|
59493
59484
|
/** Program runs left before the machine-care reminder is due; null when the appliance does not say. */
|
|
59494
|
-
machineCareRemainingRuns: number().int().nonnegative().nullable(),
|
|
59485
|
+
machineCareRemainingRuns: number().int().nonnegative().nullable().meta(readingMeta("count")),
|
|
59495
59486
|
/** Option states: null when the appliance does not expose the option or has not said. */
|
|
59496
59487
|
halfLoad: boolean().nullable(),
|
|
59497
59488
|
hygienePlus: boolean().nullable(),
|
|
@@ -59506,7 +59497,7 @@ var DishwasherStatusSchema = object({
|
|
|
59506
59497
|
/** Feature keys of the events currently raised (salt low, rinse aid low, program finished, …). */
|
|
59507
59498
|
activeEvents: array(string()),
|
|
59508
59499
|
/** Numeric error code when the appliance reports one; null otherwise. */
|
|
59509
|
-
errorCode: number().nullable(),
|
|
59500
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
59510
59501
|
/** Name of the raised alert-level event while the appliance is in error; null otherwise. */
|
|
59511
59502
|
errorLabel: string().nullable(),
|
|
59512
59503
|
/** Ms epoch of the last value received from the appliance; 0 = never. */
|
|
@@ -59737,7 +59728,7 @@ var DoorbellStatusSchema = object({
|
|
|
59737
59728
|
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
59738
59729
|
lastPressedAt: number().nullable(),
|
|
59739
59730
|
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
59740
|
-
pressCountSinceStart: number()
|
|
59731
|
+
pressCountSinceStart: number().meta(readingMeta("count"))
|
|
59741
59732
|
});
|
|
59742
59733
|
var DoorbellPressEventSchema = object({
|
|
59743
59734
|
deviceId: number(),
|
|
@@ -59820,12 +59811,11 @@ var EnumSensorDateTimeFormatSchema = _enum([
|
|
|
59820
59811
|
var EnumSensorStatusSchema = object({
|
|
59821
59812
|
value: string(),
|
|
59822
59813
|
/**
|
|
59823
|
-
* Set
|
|
59824
|
-
* as
|
|
59825
|
-
*
|
|
59826
|
-
* a time-only sensor → `'time'`.
|
|
59814
|
+
* Set when `value` is a timestamp rather than an enum state, so history
|
|
59815
|
+
* does not learn ISO strings as states. The display shape (date / time /
|
|
59816
|
+
* datetime) lives on `SourceInfo.dateTimeShape`, written once at adopt.
|
|
59827
59817
|
*/
|
|
59828
|
-
|
|
59818
|
+
timestamp: boolean().optional(),
|
|
59829
59819
|
/** Ms epoch when the slice was last updated. */
|
|
59830
59820
|
lastFetchedAt: number()
|
|
59831
59821
|
});
|
|
@@ -59852,11 +59842,11 @@ var enumSensorCapability = {
|
|
|
59852
59842
|
* History (D850): the value as an `enum` series (an appliance's program or
|
|
59853
59843
|
* operation state, an HVAC action). The option set is per device, so the
|
|
59854
59844
|
* value list is LEARNED as values are first seen (bounded). A sensor with a
|
|
59855
|
-
* `
|
|
59845
|
+
* `timestamp` carries a clock, not a state, and is not recorded.
|
|
59856
59846
|
*/
|
|
59857
59847
|
history: { fields: { value: {
|
|
59858
59848
|
kind: "enum",
|
|
59859
|
-
skipWhenSet: "
|
|
59849
|
+
skipWhenSet: "timestamp"
|
|
59860
59850
|
} } },
|
|
59861
59851
|
/** Clock fields: written, but excluded from the compare that decides
|
|
59862
59852
|
* whether persisting is worth a SQLite commit. */
|
|
@@ -59876,13 +59866,13 @@ var EventFireSchema = object({
|
|
|
59876
59866
|
deviceId: number(),
|
|
59877
59867
|
eventType: string(),
|
|
59878
59868
|
data: record(string(), unknown()).nullable(),
|
|
59879
|
-
timestamp: number(),
|
|
59880
|
-
seq: number()
|
|
59869
|
+
timestamp: number().meta(readingMeta("none")),
|
|
59870
|
+
seq: number().meta(readingMeta("count"))
|
|
59881
59871
|
});
|
|
59882
59872
|
var EventEmitterStatusSchema = object({
|
|
59883
59873
|
eventTypes: array(string()),
|
|
59884
59874
|
lastEvent: EventFireSchema.nullable(),
|
|
59885
|
-
eventCountSinceStart: number()
|
|
59875
|
+
eventCountSinceStart: number().meta(readingMeta("count"))
|
|
59886
59876
|
});
|
|
59887
59877
|
var eventEmitterCapability = {
|
|
59888
59878
|
name: "event-emitter",
|
|
@@ -60295,10 +60285,10 @@ var FanDirectionSchema = _enum(["forward", "reverse"]);
|
|
|
60295
60285
|
var FanControlStatusSchema = object({
|
|
60296
60286
|
/** Active speed as 0..100 inclusive. Null when the device has no
|
|
60297
60287
|
* speed surface (single-speed fan). */
|
|
60298
|
-
percentage: number().min(0).max(100).nullable(),
|
|
60288
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
60299
60289
|
/** Speed granularity the device accepts (HA `percentage_step`, e.g. 25 for
|
|
60300
60290
|
* a 4-speed fan). Absent when unknown — the UI then falls back to step 1. */
|
|
60301
|
-
percentageStep: number().positive().optional(),
|
|
60291
|
+
percentageStep: number().positive().optional().meta(readingMeta("percentage")),
|
|
60302
60292
|
/** Active preset mode (`auto` / `quiet` / `turbo` / vendor-specific)
|
|
60303
60293
|
* — empty string when no preset is active or supported. */
|
|
60304
60294
|
preset: string(),
|
|
@@ -60419,7 +60409,7 @@ var FeatureProbeStatusSchema = object({
|
|
|
60419
60409
|
/** Camera/firmware model string. `null` when the firmware doesn't expose it. */
|
|
60420
60410
|
model: string().nullable(),
|
|
60421
60411
|
/** Channel count for NVR/Hub devices; `1` for standalone cameras; `null` pre-probe. */
|
|
60422
|
-
channelCount: number().nullable(),
|
|
60412
|
+
channelCount: number().nullable().meta(readingMeta("count")),
|
|
60423
60413
|
/**
|
|
60424
60414
|
* Ms epoch of the last SUCCESSFUL probe. `0` before the first probe
|
|
60425
60415
|
* completes — drivers' `getAccessoryChildren()` should treat zero as
|
|
@@ -60544,7 +60534,7 @@ var gasCapability = {
|
|
|
60544
60534
|
};
|
|
60545
60535
|
var HeatingValveStatusSchema = object({
|
|
60546
60536
|
/** Radiator valve opening 0 (closed) .. 100 (open). Null = not yet known. */
|
|
60547
|
-
position: number().min(0).max(100).nullable(),
|
|
60537
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
60548
60538
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
60549
60539
|
lastFetchedAt: number()
|
|
60550
60540
|
});
|
|
@@ -60587,9 +60577,9 @@ var HumidifierStatusSchema = object({
|
|
|
60587
60577
|
/** Whether the humidifier is currently on. */
|
|
60588
60578
|
on: boolean(),
|
|
60589
60579
|
/** Current measured relative humidity (0..100). Null when not reported. */
|
|
60590
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
60580
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
60591
60581
|
/** Target relative humidity (0..100). Null when no setpoint surface. */
|
|
60592
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
60582
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
60593
60583
|
/** Active mode (`auto` / `normal` / `baby` / vendor). Null when the
|
|
60594
60584
|
* device has no mode surface. */
|
|
60595
60585
|
mode: string().nullable(),
|
|
@@ -60599,9 +60589,9 @@ var HumidifierStatusSchema = object({
|
|
|
60599
60589
|
* `idle` / `off`). Null when the device doesn't report it. */
|
|
60600
60590
|
action: string().nullable(),
|
|
60601
60591
|
/** HA `min_humidity` attribute. Null → UI uses 0. */
|
|
60602
|
-
minHumidity: number().nullable(),
|
|
60592
|
+
minHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
60603
60593
|
/** HA `max_humidity` attribute. Null → UI uses 100. */
|
|
60604
|
-
maxHumidity: number().nullable(),
|
|
60594
|
+
maxHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
60605
60595
|
/** Ms epoch when the slice was last updated. */
|
|
60606
60596
|
lastChangedAt: number()
|
|
60607
60597
|
});
|
|
@@ -60671,22 +60661,13 @@ var humidifierCapability = {
|
|
|
60671
60661
|
* `sourceInfo`.
|
|
60672
60662
|
*/
|
|
60673
60663
|
var HumiditySensorStatusSchema = object({
|
|
60674
|
-
/** Current relative humidity, 0..100. */
|
|
60675
|
-
percent: number().min(0).max(100).meta({
|
|
60676
|
-
|
|
60664
|
+
/** Current relative humidity, 0..100. `null` when the sample was refused (D393). */
|
|
60665
|
+
percent: number().min(0).max(100).nullable().meta(readingMeta("humidity", {
|
|
60666
|
+
precision: 0,
|
|
60677
60667
|
label: "Humidity"
|
|
60678
|
-
}),
|
|
60668
|
+
})),
|
|
60679
60669
|
/** Ms epoch when the slice was last updated. */
|
|
60680
|
-
lastFetchedAt: number()
|
|
60681
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
60682
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
60683
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
60684
|
-
unit: string().optional(),
|
|
60685
|
-
/** Suggested decimal places for numeric display.
|
|
60686
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
60687
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
60688
|
-
* auto-formatting when absent. */
|
|
60689
|
-
precision: number().int().min(0).max(10).optional()
|
|
60670
|
+
lastFetchedAt: number()
|
|
60690
60671
|
});
|
|
60691
60672
|
var humiditySensorCapability = {
|
|
60692
60673
|
name: "humidity-sensor",
|
|
@@ -60717,12 +60698,7 @@ var humiditySensorCapability = {
|
|
|
60717
60698
|
} } },
|
|
60718
60699
|
/** Clock fields: written, but excluded from the compare that decides
|
|
60719
60700
|
* whether persisting is worth a SQLite commit. */
|
|
60720
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
60721
|
-
customize: {
|
|
60722
|
-
version: 1,
|
|
60723
|
-
advanced: "derive",
|
|
60724
|
-
targets: []
|
|
60725
|
-
}
|
|
60701
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
60726
60702
|
};
|
|
60727
60703
|
/**
|
|
60728
60704
|
* Image display cap. Models a single still image exposed by an integration —
|
|
@@ -60743,7 +60719,7 @@ var ImageStatusSchema = object({
|
|
|
60743
60719
|
* entity exposes no `entity_picture` (yet). */
|
|
60744
60720
|
url: string().nullable(),
|
|
60745
60721
|
/** Ms epoch of the upstream last-updated timestamp. Null at cold-start. */
|
|
60746
|
-
lastUpdated: number().nullable()
|
|
60722
|
+
lastUpdated: number().nullable().meta(readingMeta("none"))
|
|
60747
60723
|
});
|
|
60748
60724
|
var imageCapability = {
|
|
60749
60725
|
name: "image",
|
|
@@ -60831,19 +60807,19 @@ var NormalizedRangeSchema = object({
|
|
|
60831
60807
|
*/
|
|
60832
60808
|
var ImageSettingsStatusSchema = object({
|
|
60833
60809
|
/** Normalized 0–100. */
|
|
60834
|
-
brightness: number().optional(),
|
|
60810
|
+
brightness: number().optional().meta(readingMeta("none")),
|
|
60835
60811
|
/** Normalized 0–100. */
|
|
60836
|
-
contrast: number().optional(),
|
|
60812
|
+
contrast: number().optional().meta(readingMeta("none")),
|
|
60837
60813
|
/** Normalized 0–100. */
|
|
60838
|
-
saturation: number().optional(),
|
|
60814
|
+
saturation: number().optional().meta(readingMeta("none")),
|
|
60839
60815
|
/** Normalized 0–100. */
|
|
60840
|
-
sharpness: number().optional(),
|
|
60816
|
+
sharpness: number().optional().meta(readingMeta("none")),
|
|
60841
60817
|
mirror: boolean().optional(),
|
|
60842
60818
|
flip: boolean().optional(),
|
|
60843
60819
|
rotate: ImageRotateSchema.optional(),
|
|
60844
60820
|
whiteBalance: WhiteBalanceModeSchema.optional(),
|
|
60845
60821
|
/** Manual white-balance warmth, NORMALIZED 0–100. Meaningful only when `whiteBalance === 'manual'`. */
|
|
60846
|
-
warmth: number().optional(),
|
|
60822
|
+
warmth: number().optional().meta(readingMeta("none")),
|
|
60847
60823
|
exposureMode: ExposureModeSchema.optional(),
|
|
60848
60824
|
backlightMode: BacklightModeSchema.optional(),
|
|
60849
60825
|
lastFetchedAt: number()
|
|
@@ -61122,10 +61098,10 @@ var IntercomAbilitySchema = object({
|
|
|
61122
61098
|
/** Codecs accepted by firmware, in preference order. Driver-authored strings. */
|
|
61123
61099
|
codecs: array(string()),
|
|
61124
61100
|
/** Sample rate (Hz) the firmware expects. Reolink typical: 16000. */
|
|
61125
|
-
sampleRate: number(),
|
|
61101
|
+
sampleRate: number().meta(readingMeta("none")),
|
|
61126
61102
|
duplex: _enum(["half", "full"]),
|
|
61127
61103
|
/** Max in-flight audio backlog before drop (ms). Server uses this to bound latency. */
|
|
61128
|
-
maxBacklogMs: number()
|
|
61104
|
+
maxBacklogMs: number().meta(readingMeta("duration-ms"))
|
|
61129
61105
|
});
|
|
61130
61106
|
var IntercomStatusSchema = object({
|
|
61131
61107
|
/** True while a talk session is open. */
|
|
@@ -61352,13 +61328,13 @@ var LawnMowerControlStatusSchema = object({
|
|
|
61352
61328
|
activity: LawnMowerActivitySchema,
|
|
61353
61329
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
61354
61330
|
* reading. */
|
|
61355
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
61331
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61356
61332
|
/** 0..100 mowing-completion percentage of the current task, or null when no
|
|
61357
61333
|
* task is active / progress is unavailable. */
|
|
61358
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
61334
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61359
61335
|
/** Current device/event code (dynamic — mostly status, sometimes an error),
|
|
61360
61336
|
* or null when unknown. */
|
|
61361
|
-
currentCode: number().nullable(),
|
|
61337
|
+
currentCode: number().nullable().meta(readingMeta("none")),
|
|
61362
61338
|
/** Human label for {@link currentCode}, or null when undecodable. */
|
|
61363
61339
|
currentCodeLabel: string().nullable(),
|
|
61364
61340
|
/** Severity of {@link currentCode}. `error` (and often `warning`) warrants UI
|
|
@@ -61891,7 +61867,7 @@ var MediaPlayerStatusSchema = object({
|
|
|
61891
61867
|
state: MediaPlayerStateSchema,
|
|
61892
61868
|
/** Volume as 0..100 inclusive. Null when the device has no volume
|
|
61893
61869
|
* surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
|
|
61894
|
-
volumeLevel: number().min(0).max(100).nullable(),
|
|
61870
|
+
volumeLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61895
61871
|
/** Mute toggle distinct from volume=0. Null when no mute surface.
|
|
61896
61872
|
* Pair with `DeviceFeature.MediaPlayerMute`. */
|
|
61897
61873
|
isMuted: boolean().nullable(),
|
|
@@ -61904,10 +61880,10 @@ var MediaPlayerStatusSchema = object({
|
|
|
61904
61880
|
currentMedia: MediaInfoSchema.nullable(),
|
|
61905
61881
|
/** Current playback position in ms. Null when not seekable or
|
|
61906
61882
|
* nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
|
|
61907
|
-
positionMs: number().int().nonnegative().nullable(),
|
|
61883
|
+
positionMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
61908
61884
|
/** Total duration of the current media in ms. Null when unknown
|
|
61909
61885
|
* (live stream) or nothing is playing. */
|
|
61910
|
-
durationMs: number().int().nonnegative().nullable(),
|
|
61886
|
+
durationMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
61911
61887
|
/** Shuffle toggle. Null when no shuffle surface.
|
|
61912
61888
|
* Pair with `DeviceFeature.MediaPlayerShuffle`. */
|
|
61913
61889
|
shuffle: boolean().nullable(),
|
|
@@ -62216,7 +62192,7 @@ var motionCustomize = {
|
|
|
62216
62192
|
eventName: "onMotionChanged"
|
|
62217
62193
|
},
|
|
62218
62194
|
deviceTypes: [DeviceType.Camera],
|
|
62219
|
-
apply: "
|
|
62195
|
+
apply: "add",
|
|
62220
62196
|
applyAuthority: {
|
|
62221
62197
|
kind: "camera-sensors",
|
|
62222
62198
|
timeoutField: "motionCooldownMs"
|
|
@@ -62288,7 +62264,7 @@ var MotionStatusSchema = object({
|
|
|
62288
62264
|
* it, every provider seeded it at boot, and every session left it
|
|
62289
62265
|
* `detected: true` after its detach.
|
|
62290
62266
|
*/
|
|
62291
|
-
autoClearAfterMs: number().nullable()
|
|
62267
|
+
autoClearAfterMs: number().nullable().meta(readingMeta("duration-ms"))
|
|
62292
62268
|
});
|
|
62293
62269
|
/**
|
|
62294
62270
|
* Payload of `motion.onMotionChanged` event + the corresponding bus
|
|
@@ -62470,7 +62446,7 @@ var MotionZoneRegionSchema = object({
|
|
|
62470
62446
|
* the grid region(s). */
|
|
62471
62447
|
var MotionZoneStatusSchema = object({
|
|
62472
62448
|
enabled: boolean(),
|
|
62473
|
-
sensitivity: number(),
|
|
62449
|
+
sensitivity: number().meta(readingMeta("none")),
|
|
62474
62450
|
/** Grid region(s). Today exactly one `grid` shape. */
|
|
62475
62451
|
regions: array(MotionZoneRegionSchema),
|
|
62476
62452
|
lastFetchedAt: number()
|
|
@@ -62840,7 +62816,7 @@ var NavigationStatusSchema = object({
|
|
|
62840
62816
|
following: boolean(),
|
|
62841
62817
|
flash: boolean(),
|
|
62842
62818
|
lightMode: NavigationLightModeSchema,
|
|
62843
|
-
lightLevel: number().min(40).max(100),
|
|
62819
|
+
lightLevel: number().min(40).max(100).meta(readingMeta("none")),
|
|
62844
62820
|
/** Ms epoch when the slice was last updated. */
|
|
62845
62821
|
lastChangedAt: number()
|
|
62846
62822
|
});
|
|
@@ -62974,13 +62950,13 @@ var NetworkLinkStatusSchema = object({
|
|
|
62974
62950
|
* one whose reading has not landed must not be drawn at 0 %. Consumers
|
|
62975
62951
|
* SKIP a null rather than coerce it.
|
|
62976
62952
|
*/
|
|
62977
|
-
signalPercent: number().min(0).max(100).nullable(),
|
|
62953
|
+
signalPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
62978
62954
|
/** Raw received signal strength in dBm, when the firmware reports one. */
|
|
62979
|
-
rssiDbm: number().optional(),
|
|
62955
|
+
rssiDbm: number().optional().meta(readingMeta("signal-level")),
|
|
62980
62956
|
/** Network name of a wireless link, when the firmware reports it. */
|
|
62981
62957
|
ssid: string().optional(),
|
|
62982
62958
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
62983
|
-
lastUpdated: number()
|
|
62959
|
+
lastUpdated: number().meta(readingMeta("none"))
|
|
62984
62960
|
});
|
|
62985
62961
|
var networkLinkCapability = {
|
|
62986
62962
|
name: "network-link",
|
|
@@ -63365,7 +63341,7 @@ var NotifierStatusSchema = object({
|
|
|
63365
63341
|
lastError: string().nullable(),
|
|
63366
63342
|
/** Number of deliveries currently buffered server-side (rate-limited
|
|
63367
63343
|
* notifiers may queue). 0 when the provider sends synchronously. */
|
|
63368
|
-
queueDepth: number().int().nonnegative(),
|
|
63344
|
+
queueDepth: number().int().nonnegative().meta(readingMeta("count")),
|
|
63369
63345
|
/** Per-feature capability matrix — authoritative source for the
|
|
63370
63346
|
* compose-form field gating. */
|
|
63371
63347
|
supports: NotifierSupportsSchema
|
|
@@ -63457,11 +63433,9 @@ onSent: { data: object({
|
|
|
63457
63433
|
* cap fits (HA `sensor` whose `device_class` we don't have a typed cap
|
|
63458
63434
|
* for: water flow, distance, weight, frequency, signal strength, …).
|
|
63459
63435
|
*
|
|
63460
|
-
* The
|
|
63461
|
-
*
|
|
63462
|
-
*
|
|
63463
|
-
* The UI reads them directly from the slice — they are the single source
|
|
63464
|
-
* of truth for generic numeric rendering and do NOT live on `sourceInfo`.
|
|
63436
|
+
* The quantity is not on this slice. It is chosen when the device is
|
|
63437
|
+
* adopted and stored once on `SourceInfo.quantity` (D944). `value` is in
|
|
63438
|
+
* that quantity's base unit. `null` is a refused sample (D393).
|
|
63465
63439
|
*
|
|
63466
63440
|
* Prefer the typed alternatives (`temperature-sensor`, `humidity-sensor`,
|
|
63467
63441
|
* `ambient-light-sensor`, `pressure-sensor`, `power-meter`,
|
|
@@ -63470,15 +63444,8 @@ onSent: { data: object({
|
|
|
63470
63444
|
* numeric values land here.
|
|
63471
63445
|
*/
|
|
63472
63446
|
var NumericSensorStatusSchema = object({
|
|
63473
|
-
|
|
63474
|
-
|
|
63475
|
-
* Populated live from the upstream source on each state push.
|
|
63476
|
-
* Absent for unitless sensors. */
|
|
63477
|
-
unit: string().optional(),
|
|
63478
|
-
/** Suggested decimal places for numeric display.
|
|
63479
|
-
* Populated live from the upstream source when provided.
|
|
63480
|
-
* Falls back to auto-formatting when absent. */
|
|
63481
|
-
precision: number().int().min(0).max(10).optional(),
|
|
63447
|
+
/** Reading in the device quantity's base unit. `null` when refused (D393). */
|
|
63448
|
+
value: number().nullable().meta(readingMeta("device")),
|
|
63482
63449
|
/** Ms epoch when the slice was last updated. */
|
|
63483
63450
|
lastFetchedAt: number()
|
|
63484
63451
|
});
|
|
@@ -63502,11 +63469,11 @@ var numericSensorCapability = {
|
|
|
63502
63469
|
*/
|
|
63503
63470
|
durability: "restored",
|
|
63504
63471
|
/**
|
|
63505
|
-
* History (D850): recorded series. The unit is
|
|
63472
|
+
* History (D850): recorded series. The unit is the device quantity's base,
|
|
63473
|
+
* resolved when the series is read — the cap has no single unit.
|
|
63506
63474
|
*/
|
|
63507
63475
|
history: { fields: { value: {
|
|
63508
63476
|
kind: "gauge",
|
|
63509
|
-
unitFrom: "unit",
|
|
63510
63477
|
minIntervalMs: 3e4
|
|
63511
63478
|
} } },
|
|
63512
63479
|
/** Clock fields: written, but excluded from the compare that decides
|
|
@@ -63798,23 +63765,26 @@ var PetFeederStatusSchema = object({
|
|
|
63798
63765
|
/** Food currently in the bowl (grams). Null when the device has not
|
|
63799
63766
|
* reported a reading yet. On dual-hopper models this is the combined
|
|
63800
63767
|
* bowl reading; per-hopper levels live in `food1`/`food2`. */
|
|
63801
|
-
foodLevel: number().nullable(),
|
|
63768
|
+
foodLevel: number().nullable().meta(readingMeta("none")),
|
|
63802
63769
|
/** Hopper-1 food level (grams) on dual-hopper feeders; null on
|
|
63803
63770
|
* single-hopper models. */
|
|
63804
|
-
food1: number().nullable(),
|
|
63771
|
+
food1: number().nullable().meta(readingMeta("none")),
|
|
63805
63772
|
/** Hopper-2 food level (grams) on dual-hopper feeders; null on
|
|
63806
63773
|
* single-hopper models. */
|
|
63807
|
-
food2: number().nullable(),
|
|
63774
|
+
food2: number().nullable().meta(readingMeta("none")),
|
|
63808
63775
|
/** Derived low-food flag — mirrors the HA `food_level` binary_sensor
|
|
63809
63776
|
* (`device_class: problem`, on = low). True when the bowl is empty /
|
|
63810
63777
|
* below the feeder's low threshold. */
|
|
63811
63778
|
lowFood: boolean(),
|
|
63812
63779
|
/** Battery charge 0..100 (%). Null on mains-powered models or when the
|
|
63813
63780
|
* device has no battery reading. */
|
|
63814
|
-
batteryPower: number().min(0).max(100).nullable(),
|
|
63815
|
-
/**
|
|
63816
|
-
*
|
|
63817
|
-
|
|
63781
|
+
batteryPower: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
63782
|
+
/**
|
|
63783
|
+
* Desiccant life remaining, stored in seconds (duration base, D944).
|
|
63784
|
+
* Providers convert from the days the feeder reports. Null when the
|
|
63785
|
+
* model has no desiccant sensor.
|
|
63786
|
+
*/
|
|
63787
|
+
desiccantLeftDays: number().nullable().meta(readingMeta("duration")),
|
|
63818
63788
|
/** True while a feed is in progress. */
|
|
63819
63789
|
feeding: boolean(),
|
|
63820
63790
|
/** Decoded connectivity / power status (HA petkit device-status enum).
|
|
@@ -63825,7 +63795,7 @@ var PetFeederStatusSchema = object({
|
|
|
63825
63795
|
* with `errorCode` for consumers that want the raw integer. */
|
|
63826
63796
|
error: string().nullable(),
|
|
63827
63797
|
/** Raw device error code (0 / null = no error). */
|
|
63828
|
-
errorCode: number().nullable(),
|
|
63798
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
63829
63799
|
/** True for D4S/D4SH dual-hopper hardware — gates the per-hopper UI. */
|
|
63830
63800
|
isDualHopper: boolean(),
|
|
63831
63801
|
/** Child-lock (manual-lock) setting — buttons on the unit are disabled. */
|
|
@@ -63835,7 +63805,7 @@ var PetFeederStatusSchema = object({
|
|
|
63835
63805
|
/** Play a chime when dispensing. */
|
|
63836
63806
|
feedSound: boolean(),
|
|
63837
63807
|
/** Speaker / prompt volume level (device-scaled integer). */
|
|
63838
|
-
volume: number(),
|
|
63808
|
+
volume: number().meta(readingMeta("none")),
|
|
63839
63809
|
/** Ms epoch when the slice was last refreshed from the cloud. */
|
|
63840
63810
|
lastFetchedAt: number()
|
|
63841
63811
|
});
|
|
@@ -63954,7 +63924,7 @@ var petFeederCapability = {
|
|
|
63954
63924
|
},
|
|
63955
63925
|
desiccantLeftDays: {
|
|
63956
63926
|
kind: "gauge",
|
|
63957
|
-
unit: "
|
|
63927
|
+
unit: "s"
|
|
63958
63928
|
}
|
|
63959
63929
|
} }
|
|
63960
63930
|
};
|
|
@@ -64355,36 +64325,19 @@ method(_void(), PlatformCapabilitiesSchema), method(_void(), HardwareInfoSchema)
|
|
|
64355
64325
|
*/
|
|
64356
64326
|
var PowerMeterStatusSchema = object({
|
|
64357
64327
|
/** Instantaneous power draw in watts. */
|
|
64358
|
-
watts: number().optional().meta({
|
|
64359
|
-
unit: "W",
|
|
64360
|
-
label: "Power"
|
|
64361
|
-
}),
|
|
64328
|
+
watts: number().optional().meta(readingMeta("power", { label: "Power" })),
|
|
64362
64329
|
/** Cumulative energy in kilowatt-hours since the meter was reset. */
|
|
64363
|
-
kwhTotal: number().optional().meta({
|
|
64364
|
-
unit: "kWh",
|
|
64365
|
-
label: "Energy"
|
|
64366
|
-
}),
|
|
64330
|
+
kwhTotal: number().optional().meta(readingMeta("energy", { label: "Energy" })),
|
|
64367
64331
|
/** Voltage in volts. */
|
|
64368
|
-
volts: number().optional(),
|
|
64332
|
+
volts: number().optional().meta(readingMeta("voltage")),
|
|
64369
64333
|
/** Current in amperes. */
|
|
64370
|
-
amps: number().optional(),
|
|
64371
|
-
/** Apparent power in volt-amperes
|
|
64372
|
-
va: number().optional(),
|
|
64334
|
+
amps: number().optional().meta(readingMeta("current")),
|
|
64335
|
+
/** Apparent power in volt-amperes. */
|
|
64336
|
+
va: number().optional().meta(readingMeta("apparent-power")),
|
|
64373
64337
|
/** Power factor (0..1) if reported. */
|
|
64374
|
-
powerFactor: number().min(0).max(1).optional(),
|
|
64338
|
+
powerFactor: number().min(0).max(1).optional().meta(readingMeta("ratio")),
|
|
64375
64339
|
/** Ms epoch when the slice was last updated. */
|
|
64376
|
-
lastFetchedAt: number()
|
|
64377
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
64378
|
-
* `attributes.unit_of_measurement` → 'V' / 'A' / 'W' / 'kW' / 'kWh').
|
|
64379
|
-
* Each upstream `sensor.*` entity surfaces ONE device_class, so one
|
|
64380
|
-
* unit per slice is unambiguous. The UI prefers this over the role's
|
|
64381
|
-
* canonical unit so a 'kW' / 'Wh' feed renders verbatim. */
|
|
64382
|
-
unit: string().optional(),
|
|
64383
|
-
/** Suggested decimal places for numeric display.
|
|
64384
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
64385
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
64386
|
-
* auto-formatting when absent. */
|
|
64387
|
-
precision: number().int().min(0).max(10).optional()
|
|
64340
|
+
lastFetchedAt: number()
|
|
64388
64341
|
});
|
|
64389
64342
|
var powerMeterCapability = {
|
|
64390
64343
|
name: "power-meter",
|
|
@@ -64448,12 +64401,7 @@ var powerMeterCapability = {
|
|
|
64448
64401
|
} },
|
|
64449
64402
|
/** Clock fields: written, but excluded from the compare that decides
|
|
64450
64403
|
* whether persisting is worth a SQLite commit. */
|
|
64451
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
64452
|
-
customize: {
|
|
64453
|
-
version: 1,
|
|
64454
|
-
advanced: "derive",
|
|
64455
|
-
targets: []
|
|
64456
|
-
}
|
|
64404
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
64457
64405
|
};
|
|
64458
64406
|
/**
|
|
64459
64407
|
* Presence cap. Models HA `person.*` and `device_tracker.*` entities
|
|
@@ -64473,11 +64421,11 @@ var powerMeterCapability = {
|
|
|
64473
64421
|
*/
|
|
64474
64422
|
var GpsLocationSchema = object({
|
|
64475
64423
|
/** Latitude in decimal degrees, -90..90. */
|
|
64476
|
-
latitude: number().min(-90).max(90),
|
|
64424
|
+
latitude: number().min(-90).max(90).meta(readingMeta("angle")),
|
|
64477
64425
|
/** Longitude in decimal degrees, -180..180. */
|
|
64478
|
-
longitude: number().min(-180).max(180),
|
|
64426
|
+
longitude: number().min(-180).max(180).meta(readingMeta("angle")),
|
|
64479
64427
|
/** Reported accuracy in meters (lower = better). */
|
|
64480
|
-
accuracyMeters: number().nonnegative()
|
|
64428
|
+
accuracyMeters: number().nonnegative().meta(readingMeta("length"))
|
|
64481
64429
|
});
|
|
64482
64430
|
var PresenceStatusSchema = object({
|
|
64483
64431
|
/** `home` / `not_home` / any user-defined zone name. */
|
|
@@ -64489,7 +64437,7 @@ var PresenceStatusSchema = object({
|
|
|
64489
64437
|
gps: GpsLocationSchema.nullable(),
|
|
64490
64438
|
/** Optional battery level of the tracking device (0..100). Null
|
|
64491
64439
|
* when not reported. */
|
|
64492
|
-
batteryPercent: number().min(0).max(100).nullable(),
|
|
64440
|
+
batteryPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
64493
64441
|
/** Ms epoch when the slice was last updated. */
|
|
64494
64442
|
lastChangedAt: number()
|
|
64495
64443
|
});
|
|
@@ -64539,19 +64487,10 @@ var presenceCapability = {
|
|
|
64539
64487
|
* `sourceInfo`.
|
|
64540
64488
|
*/
|
|
64541
64489
|
var PressureSensorStatusSchema = object({
|
|
64542
|
-
/** Current pressure in hPa. */
|
|
64543
|
-
hpa: number(),
|
|
64490
|
+
/** Current pressure in hPa. `null` when the sample was refused (D393). */
|
|
64491
|
+
hpa: number().nullable().meta(readingMeta("pressure", { precision: 0 })),
|
|
64544
64492
|
/** Ms epoch when the slice was last updated. */
|
|
64545
|
-
lastFetchedAt: number()
|
|
64546
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
64547
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
64548
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
64549
|
-
unit: string().optional(),
|
|
64550
|
-
/** Suggested decimal places for numeric display.
|
|
64551
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
64552
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
64553
|
-
* auto-formatting when absent. */
|
|
64554
|
-
precision: number().int().min(0).max(10).optional()
|
|
64493
|
+
lastFetchedAt: number()
|
|
64555
64494
|
});
|
|
64556
64495
|
var pressureSensorCapability = {
|
|
64557
64496
|
name: "pressure-sensor",
|
|
@@ -64965,8 +64904,8 @@ DeviceType.Camera, method(PtzMoveCommandSchema.extend({ deviceId: number() }), _
|
|
|
64965
64904
|
}), _void(), { kind: "mutation" });
|
|
64966
64905
|
var PtzAutotrackSettingsSchema = object({
|
|
64967
64906
|
targetType: string().describe("Vendor target string (people/vehicle/pet); empty = camera default"),
|
|
64968
|
-
stopDelaySeconds: number().int().min(0).max(300),
|
|
64969
|
-
disappearDelaySeconds: number().int().min(0).max(300)
|
|
64907
|
+
stopDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration")),
|
|
64908
|
+
disappearDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration"))
|
|
64970
64909
|
});
|
|
64971
64910
|
/**
|
|
64972
64911
|
* One option the camera advertises as a valid `targetType`. Drivers
|
|
@@ -65128,7 +65067,7 @@ var RunningStateStatusSchema = object({
|
|
|
65128
65067
|
/** null = unknown — never coerced to false (D393). */
|
|
65129
65068
|
running: boolean().nullable(),
|
|
65130
65069
|
/** Epoch ms the current boolean began; null while `running` is null. */
|
|
65131
|
-
since: number().nullable(),
|
|
65070
|
+
since: number().nullable().meta(readingMeta("none")),
|
|
65132
65071
|
source: RunningStateSourceSchema.meta({ label: "Source" }),
|
|
65133
65072
|
phase: string().nullable(),
|
|
65134
65073
|
/** null until a reading has been published (D393). */
|
|
@@ -65143,7 +65082,6 @@ var RUNNING_DEVICE_TYPES = Object.values(DeviceType);
|
|
|
65143
65082
|
/** Generic Customize target for the running boolean (D936). */
|
|
65144
65083
|
var runningCustomize = {
|
|
65145
65084
|
version: 1,
|
|
65146
|
-
advanced: "derive",
|
|
65147
65085
|
targets: [{
|
|
65148
65086
|
id: "running",
|
|
65149
65087
|
cardinality: "scalar",
|
|
@@ -65163,7 +65101,7 @@ var runningCustomize = {
|
|
|
65163
65101
|
DeviceType.Thermostat,
|
|
65164
65102
|
DeviceType.PetFeeder
|
|
65165
65103
|
],
|
|
65166
|
-
apply: "add
|
|
65104
|
+
apply: "add",
|
|
65167
65105
|
path: "running",
|
|
65168
65106
|
sources: [
|
|
65169
65107
|
{
|
|
@@ -66427,9 +66365,9 @@ var RecordTriggerSchema = _enum([
|
|
|
66427
66365
|
*/
|
|
66428
66366
|
var RecordWindowSchema = object({
|
|
66429
66367
|
trigger: RecordTriggerSchema,
|
|
66430
|
-
day: number().int().min(0).max(6),
|
|
66431
|
-
startMinute: number().int().min(0).max(1439),
|
|
66432
|
-
endMinute: number().int().min(1).max(1440)
|
|
66368
|
+
day: number().int().min(0).max(6).meta(readingMeta("none")),
|
|
66369
|
+
startMinute: number().int().min(0).max(1439).meta(readingMeta("none")),
|
|
66370
|
+
endMinute: number().int().min(1).max(1440).meta(readingMeta("none"))
|
|
66433
66371
|
});
|
|
66434
66372
|
/** Status of one physical volume, as the camera itself describes it. */
|
|
66435
66373
|
var OnboardStorageVolumeSchema = object({
|
|
@@ -66505,10 +66443,10 @@ var RecordingOnboardStatusSchema = object({
|
|
|
66505
66443
|
/** Master "record to the card at all" switch. */
|
|
66506
66444
|
enabled: boolean().nullable(),
|
|
66507
66445
|
overwriteWhenFull: boolean().nullable(),
|
|
66508
|
-
preRecordSec: number().nullable(),
|
|
66509
|
-
postRecordSec: number().nullable(),
|
|
66446
|
+
preRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
66447
|
+
postRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
66510
66448
|
/** Length of one recorded file, in minutes. */
|
|
66511
|
-
segmentMinutes: number().nullable(),
|
|
66449
|
+
segmentMinutes: number().nullable().meta(readingMeta("none")),
|
|
66512
66450
|
/** The primary track's weekly windows, flattened. */
|
|
66513
66451
|
windows: array(RecordWindowSchema),
|
|
66514
66452
|
/**
|
|
@@ -66524,7 +66462,7 @@ var RecordingOnboardStatusSchema = object({
|
|
|
66524
66462
|
* provider reporting a non-zero count also reports the schedule as not
|
|
66525
66463
|
* writable.
|
|
66526
66464
|
*/
|
|
66527
|
-
unreadableWindows: number(),
|
|
66465
|
+
unreadableWindows: number().meta(readingMeta("count")),
|
|
66528
66466
|
/**
|
|
66529
66467
|
* The camera is scheduled to record and has NO usable storage.
|
|
66530
66468
|
*
|
|
@@ -67369,7 +67307,7 @@ var CamStreamDescriptorSchema = object({
|
|
|
67369
67307
|
url: string().optional(),
|
|
67370
67308
|
codec: string().optional(),
|
|
67371
67309
|
resolution: CamStreamResolutionSchema.optional(),
|
|
67372
|
-
fps: number().positive().optional(),
|
|
67310
|
+
fps: number().positive().optional().meta(readingMeta("rate")),
|
|
67373
67311
|
label: string().optional(),
|
|
67374
67312
|
/** Device-level features (e.g. `battery-operated`) — drives broker policy. */
|
|
67375
67313
|
deviceFeatures: array(string()).optional(),
|
|
@@ -67456,18 +67394,18 @@ var StreamProfileSchema = _enum([
|
|
|
67456
67394
|
]);
|
|
67457
67395
|
/** The current encoding config of one stream profile. */
|
|
67458
67396
|
var StreamProfileConfigSchema = object({
|
|
67459
|
-
width: number(),
|
|
67460
|
-
height: number(),
|
|
67397
|
+
width: number().meta(readingMeta("none")),
|
|
67398
|
+
height: number().meta(readingMeta("none")),
|
|
67461
67399
|
codec: _enum(["h264", "h265"]),
|
|
67462
|
-
framerate: number(),
|
|
67463
|
-
bitrate: number(),
|
|
67400
|
+
framerate: number().meta(readingMeta("rate")),
|
|
67401
|
+
bitrate: number().meta(readingMeta("bitrate")),
|
|
67464
67402
|
bitrateMode: _enum(["vbr", "cbr"]).optional(),
|
|
67465
67403
|
encoderProfile: _enum([
|
|
67466
67404
|
"high",
|
|
67467
67405
|
"main",
|
|
67468
67406
|
"baseline"
|
|
67469
67407
|
]).optional(),
|
|
67470
|
-
gop: number().optional(),
|
|
67408
|
+
gop: number().optional().meta(readingMeta("none")),
|
|
67471
67409
|
/**
|
|
67472
67410
|
* Whether THIS profile currently carries an audio track. READ-ONLY here.
|
|
67473
67411
|
*
|
|
@@ -67688,12 +67626,7 @@ var switchCapability = {
|
|
|
67688
67626
|
label: "On",
|
|
67689
67627
|
kind: "boolean"
|
|
67690
67628
|
}
|
|
67691
|
-
}] }
|
|
67692
|
-
customize: {
|
|
67693
|
-
version: 1,
|
|
67694
|
-
advanced: "derive",
|
|
67695
|
-
targets: []
|
|
67696
|
-
}
|
|
67629
|
+
}] }
|
|
67697
67630
|
};
|
|
67698
67631
|
/** C0 controls, DEL and the C1 range: none of them belongs in a name. */
|
|
67699
67632
|
function hasControlCharacter(value) {
|
|
@@ -68276,35 +68209,21 @@ var tamperCapability = {
|
|
|
68276
68209
|
* entries with `device_class: temperature` and any future native
|
|
68277
68210
|
* thermometer.
|
|
68278
68211
|
*
|
|
68279
|
-
*
|
|
68280
|
-
*
|
|
68281
|
-
* (climate-control's `currentTemp`, energy analytics) can compose
|
|
68282
|
-
* without per-source unit fixups. The canonical display unit (`°C`) is
|
|
68283
|
-
* a descriptor constant in the UI (ROLE_DESCRIPTOR), not stored in
|
|
68284
|
-
* `sourceInfo`.
|
|
68212
|
+
* The number is Celsius (D944). Providers convert on ingest. A failed
|
|
68213
|
+
* conversion is `null`, never a guess. Display unit is a read-time preference.
|
|
68285
68214
|
*
|
|
68286
68215
|
* Status `lastFetchedAt` lets staleness-aware consumers detect a
|
|
68287
68216
|
* frozen feed (provider hung) distinct from a "temperature hasn't
|
|
68288
68217
|
* changed" steady state.
|
|
68289
68218
|
*/
|
|
68290
68219
|
var TemperatureSensorStatusSchema = object({
|
|
68291
|
-
/** Current temperature in Celsius. */
|
|
68292
|
-
celsius: number().meta({
|
|
68293
|
-
|
|
68220
|
+
/** Current temperature in Celsius. `null` when the sample was refused (D393). */
|
|
68221
|
+
celsius: number().nullable().meta(readingMeta("temperature", {
|
|
68222
|
+
precision: 1,
|
|
68294
68223
|
label: "Temperature"
|
|
68295
|
-
}),
|
|
68224
|
+
})),
|
|
68296
68225
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
68297
|
-
lastFetchedAt: number()
|
|
68298
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
68299
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
68300
|
-
* role's canonical unit, so a Fahrenheit feed renders '°F' not '°C'.
|
|
68301
|
-
* Absent → the UI falls back to the role's canonical unit. */
|
|
68302
|
-
unit: string().optional(),
|
|
68303
|
-
/** Suggested decimal places for numeric display.
|
|
68304
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
68305
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
68306
|
-
* auto-formatting when absent. */
|
|
68307
|
-
precision: number().int().min(0).max(10).optional()
|
|
68226
|
+
lastFetchedAt: number()
|
|
68308
68227
|
});
|
|
68309
68228
|
var temperatureSensorCapability = {
|
|
68310
68229
|
name: "temperature-sensor",
|
|
@@ -68335,12 +68254,7 @@ var temperatureSensorCapability = {
|
|
|
68335
68254
|
} } },
|
|
68336
68255
|
/** Clock fields: written, but excluded from the compare that decides
|
|
68337
68256
|
* whether persisting is worth a SQLite commit. */
|
|
68338
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
68339
|
-
customize: {
|
|
68340
|
-
version: 1,
|
|
68341
|
-
advanced: "derive",
|
|
68342
|
-
targets: []
|
|
68343
|
-
}
|
|
68257
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
68344
68258
|
};
|
|
68345
68259
|
/**
|
|
68346
68260
|
* toast — system-scoped singleton capability that streams toast
|
|
@@ -68623,16 +68537,16 @@ var VacuumControlStatusSchema = object({
|
|
|
68623
68537
|
]),
|
|
68624
68538
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
68625
68539
|
* reading. */
|
|
68626
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
68540
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
68627
68541
|
/** Current fan-speed token (provider-verbatim). Null when unknown or
|
|
68628
68542
|
* the vacuum has no speed control. */
|
|
68629
68543
|
fanSpeed: string().nullable(),
|
|
68630
68544
|
/** Speed tokens the hardware accepts — drives the UI selector. */
|
|
68631
68545
|
availableFanSpeeds: array(string()),
|
|
68632
68546
|
/** 0..100 cleaning-completion percentage of the current task, or null. */
|
|
68633
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
68547
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
68634
68548
|
/** Current error code (0 / null = no error). */
|
|
68635
|
-
errorCode: number().nullable(),
|
|
68549
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
68636
68550
|
/** Human label for {@link errorCode}, or null when none / undecodable. */
|
|
68637
68551
|
errorLabel: string().nullable(),
|
|
68638
68552
|
/** Ms epoch when the slice was last updated. */
|
|
@@ -68710,7 +68624,7 @@ var ValveStatusSchema = object({
|
|
|
68710
68624
|
]),
|
|
68711
68625
|
/** 0 = fully closed, 100 = fully open. Null when the device has no
|
|
68712
68626
|
* intermediate position surface. */
|
|
68713
|
-
position: number().min(0).max(100).nullable(),
|
|
68627
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
68714
68628
|
/** Ms epoch when the slice was last updated. */
|
|
68715
68629
|
lastChangedAt: number()
|
|
68716
68630
|
});
|
|
@@ -68818,9 +68732,9 @@ var vibrationCapability = {
|
|
|
68818
68732
|
*/
|
|
68819
68733
|
var WaterHeaterStatusSchema = object({
|
|
68820
68734
|
/** Current measured temperature. Null when not reported. */
|
|
68821
|
-
currentTemp: number().nullable(),
|
|
68735
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
68822
68736
|
/** Target temperature setpoint. Null when no setpoint surface. */
|
|
68823
|
-
targetTemp: number().nullable(),
|
|
68737
|
+
targetTemp: number().nullable().meta(readingMeta("temperature")),
|
|
68824
68738
|
/** Active operation mode = HA `state` (`eco` / `electric` / `gas` /
|
|
68825
68739
|
* `heat_pump` / `high_demand` / `performance` / `off`). Null when the
|
|
68826
68740
|
* device reports an unknown state. */
|
|
@@ -68831,9 +68745,9 @@ var WaterHeaterStatusSchema = object({
|
|
|
68831
68745
|
* has no away surface. */
|
|
68832
68746
|
away: boolean().nullable(),
|
|
68833
68747
|
/** HA `min_temp` attribute. Null when not reported. */
|
|
68834
|
-
minTemp: number().nullable(),
|
|
68748
|
+
minTemp: number().nullable().meta(readingMeta("temperature")),
|
|
68835
68749
|
/** HA `max_temp` attribute. Null when not reported. */
|
|
68836
|
-
maxTemp: number().nullable(),
|
|
68750
|
+
maxTemp: number().nullable().meta(readingMeta("temperature")),
|
|
68837
68751
|
/** Ms epoch when the slice was last updated. */
|
|
68838
68752
|
lastChangedAt: number()
|
|
68839
68753
|
});
|
|
@@ -68918,25 +68832,18 @@ var waterHeaterCapability = {
|
|
|
68918
68832
|
* Forecast deferred — current conditions only for v1.
|
|
68919
68833
|
*/
|
|
68920
68834
|
var WeatherStatusSchema = object({
|
|
68921
|
-
/** Verbatim
|
|
68922
|
-
* when no condition has been reported yet. */
|
|
68835
|
+
/** Verbatim condition state (`sunny`, `cloudy`, `rainy`, …). Null when none yet. */
|
|
68923
68836
|
condition: string().nullable(),
|
|
68924
|
-
/** Current temperature in
|
|
68925
|
-
temperature: number().nullable(),
|
|
68926
|
-
/** Temperature unit string (e.g. `°C` / `°F`). Null when not provided. */
|
|
68927
|
-
temperatureUnit: string().nullable(),
|
|
68837
|
+
/** Current temperature in Celsius. Null when not provided or refused. */
|
|
68838
|
+
temperature: number().nullable().meta(readingMeta("temperature", { precision: 1 })),
|
|
68928
68839
|
/** Relative humidity (0..100). Null when not provided. */
|
|
68929
|
-
humidity: number().min(0).max(100).nullable(),
|
|
68930
|
-
/** Barometric pressure in
|
|
68931
|
-
pressure: number().nullable(),
|
|
68932
|
-
/**
|
|
68933
|
-
|
|
68934
|
-
/** Wind speed in the reported unit. Null when not provided. */
|
|
68935
|
-
windSpeed: number().nullable(),
|
|
68936
|
-
/** Wind-speed unit string (e.g. `km/h` / `mph`). Null when not provided. */
|
|
68937
|
-
windSpeedUnit: string().nullable(),
|
|
68840
|
+
humidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
68841
|
+
/** Barometric pressure in hPa. Null when not provided or refused. */
|
|
68842
|
+
pressure: number().nullable().meta(readingMeta("pressure")),
|
|
68843
|
+
/** Wind speed in metres per second. Null when not provided or refused. */
|
|
68844
|
+
windSpeed: number().nullable().meta(readingMeta("speed")),
|
|
68938
68845
|
/** Wind bearing in degrees (0..360, meteorological). Null when not provided. */
|
|
68939
|
-
windBearing: number().nullable(),
|
|
68846
|
+
windBearing: number().nullable().meta(readingMeta("angle")),
|
|
68940
68847
|
/** Ms epoch when the slice was last updated. */
|
|
68941
68848
|
lastFetchedAt: number()
|
|
68942
68849
|
});
|
|
@@ -68964,12 +68871,12 @@ var weatherCapability = {
|
|
|
68964
68871
|
*/
|
|
68965
68872
|
durability: "session",
|
|
68966
68873
|
/**
|
|
68967
|
-
* History (D850): recorded series.
|
|
68874
|
+
* History (D850): recorded series. Numbers are the quantity base (D944).
|
|
68968
68875
|
*/
|
|
68969
68876
|
history: { fields: {
|
|
68970
68877
|
temperature: {
|
|
68971
68878
|
kind: "gauge",
|
|
68972
|
-
|
|
68879
|
+
unit: "°C",
|
|
68973
68880
|
deadband: .2
|
|
68974
68881
|
},
|
|
68975
68882
|
humidity: {
|
|
@@ -68979,12 +68886,12 @@ var weatherCapability = {
|
|
|
68979
68886
|
},
|
|
68980
68887
|
pressure: {
|
|
68981
68888
|
kind: "gauge",
|
|
68982
|
-
|
|
68889
|
+
unit: "hPa",
|
|
68983
68890
|
deadband: .5
|
|
68984
68891
|
},
|
|
68985
68892
|
windSpeed: {
|
|
68986
68893
|
kind: "gauge",
|
|
68987
|
-
|
|
68894
|
+
unit: "m/s",
|
|
68988
68895
|
deadband: .5
|
|
68989
68896
|
}
|
|
68990
68897
|
} }
|
|
@@ -69922,6 +69829,404 @@ function runningFromMediaPlayer(state, previous, fetchedAt, transitionAt) {
|
|
|
69922
69829
|
if (state === "paused") return nativeSlice(false, "paused", previous, transitionAtMs, fetchedAt, null);
|
|
69923
69830
|
return nativeSlice(false, state, previous, transitionAtMs, fetchedAt, null);
|
|
69924
69831
|
}
|
|
69832
|
+
/**
|
|
69833
|
+
* Frozen unit → spec table. `•` in the doc marks each dimension's canonical
|
|
69834
|
+
* unit (`factor: 1, offset: 0`). °F derives from `°C = (°F − 32) × 5/9` ⇒
|
|
69835
|
+
* `factor = 5/9`, `offset = -160/9` (kept as exact expressions, not rounded
|
|
69836
|
+
* decimals). K derives from `°C = K − 273.15`.
|
|
69837
|
+
*/
|
|
69838
|
+
var UNIT_TABLE = {
|
|
69839
|
+
"°C": {
|
|
69840
|
+
dimension: "temperature",
|
|
69841
|
+
factor: 1,
|
|
69842
|
+
offset: 0
|
|
69843
|
+
},
|
|
69844
|
+
"°F": {
|
|
69845
|
+
dimension: "temperature",
|
|
69846
|
+
factor: 5 / 9,
|
|
69847
|
+
offset: -160 / 9
|
|
69848
|
+
},
|
|
69849
|
+
K: {
|
|
69850
|
+
dimension: "temperature",
|
|
69851
|
+
factor: 1,
|
|
69852
|
+
offset: -273.15
|
|
69853
|
+
},
|
|
69854
|
+
hPa: {
|
|
69855
|
+
dimension: "pressure",
|
|
69856
|
+
factor: 1,
|
|
69857
|
+
offset: 0
|
|
69858
|
+
},
|
|
69859
|
+
kPa: {
|
|
69860
|
+
dimension: "pressure",
|
|
69861
|
+
factor: 10,
|
|
69862
|
+
offset: 0
|
|
69863
|
+
},
|
|
69864
|
+
Pa: {
|
|
69865
|
+
dimension: "pressure",
|
|
69866
|
+
factor: .01,
|
|
69867
|
+
offset: 0
|
|
69868
|
+
},
|
|
69869
|
+
mbar: {
|
|
69870
|
+
dimension: "pressure",
|
|
69871
|
+
factor: 1,
|
|
69872
|
+
offset: 0
|
|
69873
|
+
},
|
|
69874
|
+
bar: {
|
|
69875
|
+
dimension: "pressure",
|
|
69876
|
+
factor: 1e3,
|
|
69877
|
+
offset: 0
|
|
69878
|
+
},
|
|
69879
|
+
inHg: {
|
|
69880
|
+
dimension: "pressure",
|
|
69881
|
+
factor: 33.8639,
|
|
69882
|
+
offset: 0
|
|
69883
|
+
},
|
|
69884
|
+
mmHg: {
|
|
69885
|
+
dimension: "pressure",
|
|
69886
|
+
factor: 1.33322,
|
|
69887
|
+
offset: 0
|
|
69888
|
+
},
|
|
69889
|
+
psi: {
|
|
69890
|
+
dimension: "pressure",
|
|
69891
|
+
factor: 68.9476,
|
|
69892
|
+
offset: 0
|
|
69893
|
+
},
|
|
69894
|
+
"m/s": {
|
|
69895
|
+
dimension: "speed",
|
|
69896
|
+
factor: 1,
|
|
69897
|
+
offset: 0
|
|
69898
|
+
},
|
|
69899
|
+
"km/h": {
|
|
69900
|
+
dimension: "speed",
|
|
69901
|
+
factor: 1 / 3.6,
|
|
69902
|
+
offset: 0
|
|
69903
|
+
},
|
|
69904
|
+
mph: {
|
|
69905
|
+
dimension: "speed",
|
|
69906
|
+
factor: .44704,
|
|
69907
|
+
offset: 0
|
|
69908
|
+
},
|
|
69909
|
+
kn: {
|
|
69910
|
+
dimension: "speed",
|
|
69911
|
+
factor: .514444,
|
|
69912
|
+
offset: 0
|
|
69913
|
+
},
|
|
69914
|
+
"mm/h": {
|
|
69915
|
+
dimension: "precipitation-rate",
|
|
69916
|
+
factor: 1,
|
|
69917
|
+
offset: 0
|
|
69918
|
+
},
|
|
69919
|
+
"in/h": {
|
|
69920
|
+
dimension: "precipitation-rate",
|
|
69921
|
+
factor: 25.4,
|
|
69922
|
+
offset: 0
|
|
69923
|
+
},
|
|
69924
|
+
m: {
|
|
69925
|
+
dimension: "length",
|
|
69926
|
+
factor: 1,
|
|
69927
|
+
offset: 0
|
|
69928
|
+
},
|
|
69929
|
+
mm: {
|
|
69930
|
+
dimension: "length",
|
|
69931
|
+
factor: .001,
|
|
69932
|
+
offset: 0
|
|
69933
|
+
},
|
|
69934
|
+
cm: {
|
|
69935
|
+
dimension: "length",
|
|
69936
|
+
factor: .01,
|
|
69937
|
+
offset: 0
|
|
69938
|
+
},
|
|
69939
|
+
km: {
|
|
69940
|
+
dimension: "length",
|
|
69941
|
+
factor: 1e3,
|
|
69942
|
+
offset: 0
|
|
69943
|
+
},
|
|
69944
|
+
in: {
|
|
69945
|
+
dimension: "length",
|
|
69946
|
+
factor: .0254,
|
|
69947
|
+
offset: 0
|
|
69948
|
+
},
|
|
69949
|
+
ft: {
|
|
69950
|
+
dimension: "length",
|
|
69951
|
+
factor: .3048,
|
|
69952
|
+
offset: 0
|
|
69953
|
+
},
|
|
69954
|
+
mi: {
|
|
69955
|
+
dimension: "length",
|
|
69956
|
+
factor: 1609.344,
|
|
69957
|
+
offset: 0
|
|
69958
|
+
},
|
|
69959
|
+
"m²": {
|
|
69960
|
+
dimension: "area",
|
|
69961
|
+
factor: 1,
|
|
69962
|
+
offset: 0
|
|
69963
|
+
},
|
|
69964
|
+
lx: {
|
|
69965
|
+
dimension: "illuminance",
|
|
69966
|
+
factor: 1,
|
|
69967
|
+
offset: 0
|
|
69968
|
+
},
|
|
69969
|
+
"W/m²": {
|
|
69970
|
+
dimension: "irradiance",
|
|
69971
|
+
factor: 1,
|
|
69972
|
+
offset: 0
|
|
69973
|
+
},
|
|
69974
|
+
W: {
|
|
69975
|
+
dimension: "power",
|
|
69976
|
+
factor: 1,
|
|
69977
|
+
offset: 0
|
|
69978
|
+
},
|
|
69979
|
+
kW: {
|
|
69980
|
+
dimension: "power",
|
|
69981
|
+
factor: 1e3,
|
|
69982
|
+
offset: 0
|
|
69983
|
+
},
|
|
69984
|
+
VA: {
|
|
69985
|
+
dimension: "apparent-power",
|
|
69986
|
+
factor: 1,
|
|
69987
|
+
offset: 0
|
|
69988
|
+
},
|
|
69989
|
+
Wh: {
|
|
69990
|
+
dimension: "energy",
|
|
69991
|
+
factor: 1,
|
|
69992
|
+
offset: 0
|
|
69993
|
+
},
|
|
69994
|
+
kWh: {
|
|
69995
|
+
dimension: "energy",
|
|
69996
|
+
factor: 1e3,
|
|
69997
|
+
offset: 0
|
|
69998
|
+
},
|
|
69999
|
+
MWh: {
|
|
70000
|
+
dimension: "energy",
|
|
70001
|
+
factor: 1e6,
|
|
70002
|
+
offset: 0
|
|
70003
|
+
},
|
|
70004
|
+
V: {
|
|
70005
|
+
dimension: "voltage",
|
|
70006
|
+
factor: 1,
|
|
70007
|
+
offset: 0
|
|
70008
|
+
},
|
|
70009
|
+
mV: {
|
|
70010
|
+
dimension: "voltage",
|
|
70011
|
+
factor: .001,
|
|
70012
|
+
offset: 0
|
|
70013
|
+
},
|
|
70014
|
+
A: {
|
|
70015
|
+
dimension: "current",
|
|
70016
|
+
factor: 1,
|
|
70017
|
+
offset: 0
|
|
70018
|
+
},
|
|
70019
|
+
mA: {
|
|
70020
|
+
dimension: "current",
|
|
70021
|
+
factor: .001,
|
|
70022
|
+
offset: 0
|
|
70023
|
+
},
|
|
70024
|
+
ppm: {
|
|
70025
|
+
dimension: "concentration-volume",
|
|
70026
|
+
factor: 1,
|
|
70027
|
+
offset: 0
|
|
70028
|
+
},
|
|
70029
|
+
ppb: {
|
|
70030
|
+
dimension: "concentration-volume",
|
|
70031
|
+
factor: .001,
|
|
70032
|
+
offset: 0
|
|
70033
|
+
},
|
|
70034
|
+
"µg/m³": {
|
|
70035
|
+
dimension: "concentration-mass",
|
|
70036
|
+
factor: 1,
|
|
70037
|
+
offset: 0
|
|
70038
|
+
},
|
|
70039
|
+
"mg/m³": {
|
|
70040
|
+
dimension: "concentration-mass",
|
|
70041
|
+
factor: 1e3,
|
|
70042
|
+
offset: 0
|
|
70043
|
+
},
|
|
70044
|
+
kg: {
|
|
70045
|
+
dimension: "mass",
|
|
70046
|
+
factor: 1,
|
|
70047
|
+
offset: 0
|
|
70048
|
+
},
|
|
70049
|
+
g: {
|
|
70050
|
+
dimension: "mass",
|
|
70051
|
+
factor: .001,
|
|
70052
|
+
offset: 0
|
|
70053
|
+
},
|
|
70054
|
+
lb: {
|
|
70055
|
+
dimension: "mass",
|
|
70056
|
+
factor: .453592,
|
|
70057
|
+
offset: 0
|
|
70058
|
+
},
|
|
70059
|
+
oz: {
|
|
70060
|
+
dimension: "mass",
|
|
70061
|
+
factor: .0283495,
|
|
70062
|
+
offset: 0
|
|
70063
|
+
},
|
|
70064
|
+
"%": {
|
|
70065
|
+
dimension: "percentage",
|
|
70066
|
+
factor: 1,
|
|
70067
|
+
offset: 0
|
|
70068
|
+
},
|
|
70069
|
+
L: {
|
|
70070
|
+
dimension: "volume",
|
|
70071
|
+
factor: 1,
|
|
70072
|
+
offset: 0
|
|
70073
|
+
},
|
|
70074
|
+
mL: {
|
|
70075
|
+
dimension: "volume",
|
|
70076
|
+
factor: .001,
|
|
70077
|
+
offset: 0
|
|
70078
|
+
},
|
|
70079
|
+
gal: {
|
|
70080
|
+
dimension: "volume",
|
|
70081
|
+
factor: 3.785411784,
|
|
70082
|
+
offset: 0
|
|
70083
|
+
},
|
|
70084
|
+
s: {
|
|
70085
|
+
dimension: "duration",
|
|
70086
|
+
factor: 1,
|
|
70087
|
+
offset: 0
|
|
70088
|
+
},
|
|
70089
|
+
ms: {
|
|
70090
|
+
dimension: "duration",
|
|
70091
|
+
factor: .001,
|
|
70092
|
+
offset: 0
|
|
70093
|
+
},
|
|
70094
|
+
min: {
|
|
70095
|
+
dimension: "duration",
|
|
70096
|
+
factor: 60,
|
|
70097
|
+
offset: 0
|
|
70098
|
+
},
|
|
70099
|
+
h: {
|
|
70100
|
+
dimension: "duration",
|
|
70101
|
+
factor: 3600,
|
|
70102
|
+
offset: 0
|
|
70103
|
+
},
|
|
70104
|
+
d: {
|
|
70105
|
+
dimension: "duration",
|
|
70106
|
+
factor: 86400,
|
|
70107
|
+
offset: 0
|
|
70108
|
+
},
|
|
70109
|
+
B: {
|
|
70110
|
+
dimension: "information",
|
|
70111
|
+
factor: 1,
|
|
70112
|
+
offset: 0
|
|
70113
|
+
},
|
|
70114
|
+
KiB: {
|
|
70115
|
+
dimension: "information",
|
|
70116
|
+
factor: 1024,
|
|
70117
|
+
offset: 0
|
|
70118
|
+
},
|
|
70119
|
+
MiB: {
|
|
70120
|
+
dimension: "information",
|
|
70121
|
+
factor: 1024 ** 2,
|
|
70122
|
+
offset: 0
|
|
70123
|
+
},
|
|
70124
|
+
GiB: {
|
|
70125
|
+
dimension: "information",
|
|
70126
|
+
factor: 1024 ** 3,
|
|
70127
|
+
offset: 0
|
|
70128
|
+
},
|
|
70129
|
+
TiB: {
|
|
70130
|
+
dimension: "information",
|
|
70131
|
+
factor: 1024 ** 4,
|
|
70132
|
+
offset: 0
|
|
70133
|
+
},
|
|
70134
|
+
kB: {
|
|
70135
|
+
dimension: "information",
|
|
70136
|
+
factor: 1e3,
|
|
70137
|
+
offset: 0
|
|
70138
|
+
},
|
|
70139
|
+
MB: {
|
|
70140
|
+
dimension: "information",
|
|
70141
|
+
factor: 1e6,
|
|
70142
|
+
offset: 0
|
|
70143
|
+
},
|
|
70144
|
+
GB: {
|
|
70145
|
+
dimension: "information",
|
|
70146
|
+
factor: 1e9,
|
|
70147
|
+
offset: 0
|
|
70148
|
+
},
|
|
70149
|
+
"°": {
|
|
70150
|
+
dimension: "angle",
|
|
70151
|
+
factor: 1,
|
|
70152
|
+
offset: 0
|
|
70153
|
+
},
|
|
70154
|
+
dBFS: {
|
|
70155
|
+
dimension: "sound-level",
|
|
70156
|
+
factor: 1,
|
|
70157
|
+
offset: 0
|
|
70158
|
+
},
|
|
70159
|
+
dBm: {
|
|
70160
|
+
dimension: "signal-level",
|
|
70161
|
+
factor: 1,
|
|
70162
|
+
offset: 0
|
|
70163
|
+
},
|
|
70164
|
+
mired: {
|
|
70165
|
+
dimension: "colour-temperature",
|
|
70166
|
+
factor: 1,
|
|
70167
|
+
offset: 0
|
|
70168
|
+
},
|
|
70169
|
+
kbps: {
|
|
70170
|
+
dimension: "bitrate",
|
|
70171
|
+
factor: 1,
|
|
70172
|
+
offset: 0
|
|
70173
|
+
},
|
|
70174
|
+
Mbps: {
|
|
70175
|
+
dimension: "bitrate",
|
|
70176
|
+
factor: 1e3,
|
|
70177
|
+
offset: 0
|
|
70178
|
+
},
|
|
70179
|
+
fps: {
|
|
70180
|
+
dimension: "rate",
|
|
70181
|
+
factor: 1,
|
|
70182
|
+
offset: 0
|
|
70183
|
+
}
|
|
70184
|
+
};
|
|
70185
|
+
/** Resolve a unit's `UnitSpec`, or `undefined` when the spelling is unknown. */
|
|
70186
|
+
function specFor(unit) {
|
|
70187
|
+
return Object.hasOwn(UNIT_TABLE, unit) ? UNIT_TABLE[unit] : void 0;
|
|
70188
|
+
}
|
|
70189
|
+
/** The dimension a unit belongs to, or `undefined` for an unknown unit. */
|
|
70190
|
+
function unitDimension(unit) {
|
|
70191
|
+
return specFor(unit)?.dimension;
|
|
70192
|
+
}
|
|
70193
|
+
/** Value in `spec`'s unit → its dimension's canonical unit. */
|
|
70194
|
+
function toCanonical(value, spec) {
|
|
70195
|
+
return value * spec.factor + spec.offset;
|
|
70196
|
+
}
|
|
70197
|
+
/** Canonical-unit value → the unit described by `spec`. */
|
|
70198
|
+
function fromCanonical(canonical, spec) {
|
|
70199
|
+
return (canonical - spec.offset) / spec.factor;
|
|
70200
|
+
}
|
|
70201
|
+
/**
|
|
70202
|
+
* Graceful variant for the render path: returns the converted value, or
|
|
70203
|
+
* `undefined` when the conversion is refused (unknown unit / cross-dimension).
|
|
70204
|
+
* Never throws — a render caller falls back to the raw value + source unit.
|
|
70205
|
+
*/
|
|
70206
|
+
function tryConvertUnit(value, from, to) {
|
|
70207
|
+
if (from === to) return value;
|
|
70208
|
+
const fromSpec = specFor(from);
|
|
70209
|
+
if (!fromSpec) return void 0;
|
|
70210
|
+
const toSpec = specFor(to);
|
|
70211
|
+
if (!toSpec) return void 0;
|
|
70212
|
+
if (fromSpec.dimension !== toSpec.dimension) return void 0;
|
|
70213
|
+
return fromCanonical(toCanonical(value, fromSpec), toSpec);
|
|
70214
|
+
}
|
|
70215
|
+
/**
|
|
70216
|
+
* Every known unit spelling in a dimension (table insertion order — canonical
|
|
70217
|
+
* unit first). Powers the UI's same-dimension unit picker.
|
|
70218
|
+
*/
|
|
70219
|
+
/**
|
|
70220
|
+
* Convert a difference, not a reading. Affine units (°F) shift an absolute
|
|
70221
|
+
* value by their offset; a step of 1°F is 5/9°C, so the offset is cancelled.
|
|
70222
|
+
*/
|
|
70223
|
+
function tryConvertDelta(value, from, to) {
|
|
70224
|
+
if (from === to) return value;
|
|
70225
|
+
const origin = tryConvertUnit(0, from, to);
|
|
70226
|
+
const shifted = tryConvertUnit(value, from, to);
|
|
70227
|
+
if (origin === void 0 || shifted === void 0) return void 0;
|
|
70228
|
+
return shifted - origin;
|
|
70229
|
+
}
|
|
69925
70230
|
SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
|
|
69926
70231
|
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;
|
|
69927
70232
|
String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
|
|
@@ -84591,7 +84896,6 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84591
84896
|
field: "value",
|
|
84592
84897
|
quantity: t("the reading", "il valore"),
|
|
84593
84898
|
label: t("Reading", "Valore"),
|
|
84594
|
-
unitField: "unit",
|
|
84595
84899
|
icon: "gauge"
|
|
84596
84900
|
}]
|
|
84597
84901
|
},
|
|
@@ -84727,7 +85031,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84727
85031
|
field: "temperature",
|
|
84728
85032
|
quantity: t("the outdoor temperature", "la temperatura esterna"),
|
|
84729
85033
|
label: t("Temperature", "Temperatura"),
|
|
84730
|
-
|
|
85034
|
+
unit: "°C",
|
|
84731
85035
|
icon: "thermometer"
|
|
84732
85036
|
},
|
|
84733
85037
|
{
|
|
@@ -84743,7 +85047,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84743
85047
|
field: "windSpeed",
|
|
84744
85048
|
quantity: t("the wind speed", "la velocità del vento"),
|
|
84745
85049
|
label: t("Wind", "Vento"),
|
|
84746
|
-
|
|
85050
|
+
unit: "m/s",
|
|
84747
85051
|
icon: "wind"
|
|
84748
85052
|
},
|
|
84749
85053
|
{
|
|
@@ -84751,7 +85055,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84751
85055
|
field: "pressure",
|
|
84752
85056
|
quantity: t("the air pressure", "la pressione atmosferica"),
|
|
84753
85057
|
label: t("Pressure", "Pressione"),
|
|
84754
|
-
|
|
85058
|
+
unit: "hPa",
|
|
84755
85059
|
icon: "gauge"
|
|
84756
85060
|
}
|
|
84757
85061
|
]
|
|
@@ -89324,6 +89628,96 @@ DEFAULT_NATIVE_LEASE_SETTINGS.tileBudgetMb;
|
|
|
89324
89628
|
DEFAULT_NATIVE_LEASE_SETTINGS.sceneBudgetMb;
|
|
89325
89629
|
DEFAULT_NATIVE_LEASE_SETTINGS.admission;
|
|
89326
89630
|
/**
|
|
89631
|
+
* Convert an upstream number into the stored base of its quantity (D944 §4).
|
|
89632
|
+
* An unknown unit or a unit from another dimension is a refusal: the caller
|
|
89633
|
+
* logs it and publishes null (D393). This function never guesses.
|
|
89634
|
+
*/
|
|
89635
|
+
var DIMENSION_QUANTITY = {
|
|
89636
|
+
temperature: "temperature",
|
|
89637
|
+
pressure: "pressure",
|
|
89638
|
+
speed: "speed",
|
|
89639
|
+
"precipitation-rate": "precipitation-rate",
|
|
89640
|
+
length: "length",
|
|
89641
|
+
area: "area",
|
|
89642
|
+
illuminance: "illuminance",
|
|
89643
|
+
irradiance: "irradiance",
|
|
89644
|
+
power: "power",
|
|
89645
|
+
"apparent-power": "apparent-power",
|
|
89646
|
+
energy: "energy",
|
|
89647
|
+
voltage: "voltage",
|
|
89648
|
+
current: "current",
|
|
89649
|
+
"concentration-volume": "concentration-volume",
|
|
89650
|
+
"concentration-mass": "concentration-mass",
|
|
89651
|
+
mass: "mass",
|
|
89652
|
+
percentage: "percentage",
|
|
89653
|
+
volume: "volume",
|
|
89654
|
+
duration: "duration",
|
|
89655
|
+
information: "information",
|
|
89656
|
+
angle: "angle",
|
|
89657
|
+
"sound-level": "sound-level",
|
|
89658
|
+
"signal-level": "signal-level",
|
|
89659
|
+
"colour-temperature": "colour-temperature",
|
|
89660
|
+
bitrate: "bitrate",
|
|
89661
|
+
rate: "rate"
|
|
89662
|
+
};
|
|
89663
|
+
/**
|
|
89664
|
+
* Quantity implied by a unit symbol. `ppb` and `ms` are the two symbols
|
|
89665
|
+
* whose stored base is not the dimension's canonical unit. `mm` is length;
|
|
89666
|
+
* precipitation is chosen by the caller (a device class), not by the symbol.
|
|
89667
|
+
*/
|
|
89668
|
+
function quantityFromUnit(rawUnit) {
|
|
89669
|
+
const unit = normalizeUnit(rawUnit);
|
|
89670
|
+
if (unit === void 0) return void 0;
|
|
89671
|
+
if (unit === "ppb") return "concentration-ppb";
|
|
89672
|
+
if (unit === "ms") return "duration-ms";
|
|
89673
|
+
const dimension = unitDimension(unit);
|
|
89674
|
+
if (dimension === void 0) return void 0;
|
|
89675
|
+
return DIMENSION_QUANTITY[dimension];
|
|
89676
|
+
}
|
|
89677
|
+
function ingestReading(input) {
|
|
89678
|
+
if (!Number.isFinite(input.value)) return {
|
|
89679
|
+
ok: false,
|
|
89680
|
+
reason: "non-finite"
|
|
89681
|
+
};
|
|
89682
|
+
if (input.quantity === "device") return {
|
|
89683
|
+
ok: false,
|
|
89684
|
+
reason: "unknown-unit"
|
|
89685
|
+
};
|
|
89686
|
+
const raw = input.rawUnit?.trim();
|
|
89687
|
+
if (raw === void 0 || raw.length === 0) return {
|
|
89688
|
+
ok: true,
|
|
89689
|
+
value: input.value
|
|
89690
|
+
};
|
|
89691
|
+
const unit = normalizeUnit(raw);
|
|
89692
|
+
if (unit === void 0) return {
|
|
89693
|
+
ok: false,
|
|
89694
|
+
reason: "unknown-unit"
|
|
89695
|
+
};
|
|
89696
|
+
const base = baseUnitOf(input.quantity);
|
|
89697
|
+
if (base === void 0) {
|
|
89698
|
+
if (unitDimension(unit) !== void 0) return {
|
|
89699
|
+
ok: false,
|
|
89700
|
+
reason: "cross-dimension"
|
|
89701
|
+
};
|
|
89702
|
+
return {
|
|
89703
|
+
ok: false,
|
|
89704
|
+
reason: "unknown-unit"
|
|
89705
|
+
};
|
|
89706
|
+
}
|
|
89707
|
+
const converted = tryConvertUnit(input.value, unit, base);
|
|
89708
|
+
if (converted === void 0) return unitDimension(unit) === void 0 ? {
|
|
89709
|
+
ok: false,
|
|
89710
|
+
reason: "unknown-unit"
|
|
89711
|
+
} : {
|
|
89712
|
+
ok: false,
|
|
89713
|
+
reason: "cross-dimension"
|
|
89714
|
+
};
|
|
89715
|
+
return {
|
|
89716
|
+
ok: true,
|
|
89717
|
+
value: converted
|
|
89718
|
+
};
|
|
89719
|
+
}
|
|
89720
|
+
/**
|
|
89327
89721
|
* Pure fuzzy matcher for adoption location import. Normalized
|
|
89328
89722
|
* case-insensitive Levenshtein similarity, used to reuse an existing
|
|
89329
89723
|
* CamStack location when an imported source location (e.g. an HA area) is
|
|
@@ -89552,6 +89946,12 @@ Object.defineProperty(exports, "automationControlCapability", {
|
|
|
89552
89946
|
return automationControlCapability;
|
|
89553
89947
|
}
|
|
89554
89948
|
});
|
|
89949
|
+
Object.defineProperty(exports, "baseUnitOf", {
|
|
89950
|
+
enumerable: true,
|
|
89951
|
+
get: function() {
|
|
89952
|
+
return baseUnitOf;
|
|
89953
|
+
}
|
|
89954
|
+
});
|
|
89555
89955
|
Object.defineProperty(exports, "batteryCapability", {
|
|
89556
89956
|
enumerable: true,
|
|
89557
89957
|
get: function() {
|
|
@@ -89768,6 +90168,18 @@ Object.defineProperty(exports, "imageCapability", {
|
|
|
89768
90168
|
return imageCapability;
|
|
89769
90169
|
}
|
|
89770
90170
|
});
|
|
90171
|
+
Object.defineProperty(exports, "ingestReading", {
|
|
90172
|
+
enumerable: true,
|
|
90173
|
+
get: function() {
|
|
90174
|
+
return ingestReading;
|
|
90175
|
+
}
|
|
90176
|
+
});
|
|
90177
|
+
Object.defineProperty(exports, "isReadingQuantity", {
|
|
90178
|
+
enumerable: true,
|
|
90179
|
+
get: function() {
|
|
90180
|
+
return isReadingQuantity;
|
|
90181
|
+
}
|
|
90182
|
+
});
|
|
89771
90183
|
Object.defineProperty(exports, "lawnMowerControlCapability", {
|
|
89772
90184
|
enumerable: true,
|
|
89773
90185
|
get: function() {
|
|
@@ -89876,6 +90288,12 @@ Object.defineProperty(exports, "pressureSensorCapability", {
|
|
|
89876
90288
|
return pressureSensorCapability;
|
|
89877
90289
|
}
|
|
89878
90290
|
});
|
|
90291
|
+
Object.defineProperty(exports, "quantityFromUnit", {
|
|
90292
|
+
enumerable: true,
|
|
90293
|
+
get: function() {
|
|
90294
|
+
return quantityFromUnit;
|
|
90295
|
+
}
|
|
90296
|
+
});
|
|
89879
90297
|
Object.defineProperty(exports, "record", {
|
|
89880
90298
|
enumerable: true,
|
|
89881
90299
|
get: function() {
|
|
@@ -89942,6 +90360,18 @@ Object.defineProperty(exports, "temperatureSensorCapability", {
|
|
|
89942
90360
|
return temperatureSensorCapability;
|
|
89943
90361
|
}
|
|
89944
90362
|
});
|
|
90363
|
+
Object.defineProperty(exports, "tryConvertDelta", {
|
|
90364
|
+
enumerable: true,
|
|
90365
|
+
get: function() {
|
|
90366
|
+
return tryConvertDelta;
|
|
90367
|
+
}
|
|
90368
|
+
});
|
|
90369
|
+
Object.defineProperty(exports, "tryConvertUnit", {
|
|
90370
|
+
enumerable: true,
|
|
90371
|
+
get: function() {
|
|
90372
|
+
return tryConvertUnit;
|
|
90373
|
+
}
|
|
90374
|
+
});
|
|
89945
90375
|
Object.defineProperty(exports, "union", {
|
|
89946
90376
|
enumerable: true,
|
|
89947
90377
|
get: function() {
|