@camstack/addon-provider-homeassistant 1.2.624 → 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-_Yi49Ixo.js → dist-1tLY30OG.js} +921 -484
- package/dist/{dist-BJRmTD1G.mjs → dist-B7nW5y58.mjs} +886 -485
- package/dist/ha-export/ha-export.addon.js +26 -19
- package/dist/ha-export/ha-export.addon.mjs +26 -19
- package/package.json +7 -2
|
@@ -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. */
|
|
@@ -59718,6 +59709,7 @@ var doorbellCustomize = {
|
|
|
59718
59709
|
applyAuthority: { kind: "composition-claim" },
|
|
59719
59710
|
eventName: "onPressed",
|
|
59720
59711
|
edges: ["rising"],
|
|
59712
|
+
defaultEdge: "rising",
|
|
59721
59713
|
timestampPath: "lastPressedAt",
|
|
59722
59714
|
counterPath: "pressCountSinceStart",
|
|
59723
59715
|
highWater: "composer-advance",
|
|
@@ -59736,7 +59728,7 @@ var DoorbellStatusSchema = object({
|
|
|
59736
59728
|
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
59737
59729
|
lastPressedAt: number().nullable(),
|
|
59738
59730
|
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
59739
|
-
pressCountSinceStart: number()
|
|
59731
|
+
pressCountSinceStart: number().meta(readingMeta("count"))
|
|
59740
59732
|
});
|
|
59741
59733
|
var DoorbellPressEventSchema = object({
|
|
59742
59734
|
deviceId: number(),
|
|
@@ -59819,12 +59811,11 @@ var EnumSensorDateTimeFormatSchema = _enum([
|
|
|
59819
59811
|
var EnumSensorStatusSchema = object({
|
|
59820
59812
|
value: string(),
|
|
59821
59813
|
/**
|
|
59822
|
-
* Set
|
|
59823
|
-
* as
|
|
59824
|
-
*
|
|
59825
|
-
* 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.
|
|
59826
59817
|
*/
|
|
59827
|
-
|
|
59818
|
+
timestamp: boolean().optional(),
|
|
59828
59819
|
/** Ms epoch when the slice was last updated. */
|
|
59829
59820
|
lastFetchedAt: number()
|
|
59830
59821
|
});
|
|
@@ -59851,11 +59842,11 @@ var enumSensorCapability = {
|
|
|
59851
59842
|
* History (D850): the value as an `enum` series (an appliance's program or
|
|
59852
59843
|
* operation state, an HVAC action). The option set is per device, so the
|
|
59853
59844
|
* value list is LEARNED as values are first seen (bounded). A sensor with a
|
|
59854
|
-
* `
|
|
59845
|
+
* `timestamp` carries a clock, not a state, and is not recorded.
|
|
59855
59846
|
*/
|
|
59856
59847
|
history: { fields: { value: {
|
|
59857
59848
|
kind: "enum",
|
|
59858
|
-
skipWhenSet: "
|
|
59849
|
+
skipWhenSet: "timestamp"
|
|
59859
59850
|
} } },
|
|
59860
59851
|
/** Clock fields: written, but excluded from the compare that decides
|
|
59861
59852
|
* whether persisting is worth a SQLite commit. */
|
|
@@ -59875,13 +59866,13 @@ var EventFireSchema = object({
|
|
|
59875
59866
|
deviceId: number(),
|
|
59876
59867
|
eventType: string(),
|
|
59877
59868
|
data: record(string(), unknown()).nullable(),
|
|
59878
|
-
timestamp: number(),
|
|
59879
|
-
seq: number()
|
|
59869
|
+
timestamp: number().meta(readingMeta("none")),
|
|
59870
|
+
seq: number().meta(readingMeta("count"))
|
|
59880
59871
|
});
|
|
59881
59872
|
var EventEmitterStatusSchema = object({
|
|
59882
59873
|
eventTypes: array(string()),
|
|
59883
59874
|
lastEvent: EventFireSchema.nullable(),
|
|
59884
|
-
eventCountSinceStart: number()
|
|
59875
|
+
eventCountSinceStart: number().meta(readingMeta("count"))
|
|
59885
59876
|
});
|
|
59886
59877
|
var eventEmitterCapability = {
|
|
59887
59878
|
name: "event-emitter",
|
|
@@ -60294,10 +60285,10 @@ var FanDirectionSchema = _enum(["forward", "reverse"]);
|
|
|
60294
60285
|
var FanControlStatusSchema = object({
|
|
60295
60286
|
/** Active speed as 0..100 inclusive. Null when the device has no
|
|
60296
60287
|
* speed surface (single-speed fan). */
|
|
60297
|
-
percentage: number().min(0).max(100).nullable(),
|
|
60288
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
60298
60289
|
/** Speed granularity the device accepts (HA `percentage_step`, e.g. 25 for
|
|
60299
60290
|
* a 4-speed fan). Absent when unknown — the UI then falls back to step 1. */
|
|
60300
|
-
percentageStep: number().positive().optional(),
|
|
60291
|
+
percentageStep: number().positive().optional().meta(readingMeta("percentage")),
|
|
60301
60292
|
/** Active preset mode (`auto` / `quiet` / `turbo` / vendor-specific)
|
|
60302
60293
|
* — empty string when no preset is active or supported. */
|
|
60303
60294
|
preset: string(),
|
|
@@ -60418,7 +60409,7 @@ var FeatureProbeStatusSchema = object({
|
|
|
60418
60409
|
/** Camera/firmware model string. `null` when the firmware doesn't expose it. */
|
|
60419
60410
|
model: string().nullable(),
|
|
60420
60411
|
/** Channel count for NVR/Hub devices; `1` for standalone cameras; `null` pre-probe. */
|
|
60421
|
-
channelCount: number().nullable(),
|
|
60412
|
+
channelCount: number().nullable().meta(readingMeta("count")),
|
|
60422
60413
|
/**
|
|
60423
60414
|
* Ms epoch of the last SUCCESSFUL probe. `0` before the first probe
|
|
60424
60415
|
* completes — drivers' `getAccessoryChildren()` should treat zero as
|
|
@@ -60543,7 +60534,7 @@ var gasCapability = {
|
|
|
60543
60534
|
};
|
|
60544
60535
|
var HeatingValveStatusSchema = object({
|
|
60545
60536
|
/** Radiator valve opening 0 (closed) .. 100 (open). Null = not yet known. */
|
|
60546
|
-
position: number().min(0).max(100).nullable(),
|
|
60537
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
60547
60538
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
60548
60539
|
lastFetchedAt: number()
|
|
60549
60540
|
});
|
|
@@ -60586,9 +60577,9 @@ var HumidifierStatusSchema = object({
|
|
|
60586
60577
|
/** Whether the humidifier is currently on. */
|
|
60587
60578
|
on: boolean(),
|
|
60588
60579
|
/** Current measured relative humidity (0..100). Null when not reported. */
|
|
60589
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
60580
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
60590
60581
|
/** Target relative humidity (0..100). Null when no setpoint surface. */
|
|
60591
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
60582
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
60592
60583
|
/** Active mode (`auto` / `normal` / `baby` / vendor). Null when the
|
|
60593
60584
|
* device has no mode surface. */
|
|
60594
60585
|
mode: string().nullable(),
|
|
@@ -60598,9 +60589,9 @@ var HumidifierStatusSchema = object({
|
|
|
60598
60589
|
* `idle` / `off`). Null when the device doesn't report it. */
|
|
60599
60590
|
action: string().nullable(),
|
|
60600
60591
|
/** HA `min_humidity` attribute. Null → UI uses 0. */
|
|
60601
|
-
minHumidity: number().nullable(),
|
|
60592
|
+
minHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
60602
60593
|
/** HA `max_humidity` attribute. Null → UI uses 100. */
|
|
60603
|
-
maxHumidity: number().nullable(),
|
|
60594
|
+
maxHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
60604
60595
|
/** Ms epoch when the slice was last updated. */
|
|
60605
60596
|
lastChangedAt: number()
|
|
60606
60597
|
});
|
|
@@ -60670,22 +60661,13 @@ var humidifierCapability = {
|
|
|
60670
60661
|
* `sourceInfo`.
|
|
60671
60662
|
*/
|
|
60672
60663
|
var HumiditySensorStatusSchema = object({
|
|
60673
|
-
/** Current relative humidity, 0..100. */
|
|
60674
|
-
percent: number().min(0).max(100).meta({
|
|
60675
|
-
|
|
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,
|
|
60676
60667
|
label: "Humidity"
|
|
60677
|
-
}),
|
|
60668
|
+
})),
|
|
60678
60669
|
/** Ms epoch when the slice was last updated. */
|
|
60679
|
-
lastFetchedAt: number()
|
|
60680
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
60681
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
60682
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
60683
|
-
unit: string().optional(),
|
|
60684
|
-
/** Suggested decimal places for numeric display.
|
|
60685
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
60686
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
60687
|
-
* auto-formatting when absent. */
|
|
60688
|
-
precision: number().int().min(0).max(10).optional()
|
|
60670
|
+
lastFetchedAt: number()
|
|
60689
60671
|
});
|
|
60690
60672
|
var humiditySensorCapability = {
|
|
60691
60673
|
name: "humidity-sensor",
|
|
@@ -60716,12 +60698,7 @@ var humiditySensorCapability = {
|
|
|
60716
60698
|
} } },
|
|
60717
60699
|
/** Clock fields: written, but excluded from the compare that decides
|
|
60718
60700
|
* whether persisting is worth a SQLite commit. */
|
|
60719
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
60720
|
-
customize: {
|
|
60721
|
-
version: 1,
|
|
60722
|
-
advanced: "derive",
|
|
60723
|
-
targets: []
|
|
60724
|
-
}
|
|
60701
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
60725
60702
|
};
|
|
60726
60703
|
/**
|
|
60727
60704
|
* Image display cap. Models a single still image exposed by an integration —
|
|
@@ -60742,7 +60719,7 @@ var ImageStatusSchema = object({
|
|
|
60742
60719
|
* entity exposes no `entity_picture` (yet). */
|
|
60743
60720
|
url: string().nullable(),
|
|
60744
60721
|
/** Ms epoch of the upstream last-updated timestamp. Null at cold-start. */
|
|
60745
|
-
lastUpdated: number().nullable()
|
|
60722
|
+
lastUpdated: number().nullable().meta(readingMeta("none"))
|
|
60746
60723
|
});
|
|
60747
60724
|
var imageCapability = {
|
|
60748
60725
|
name: "image",
|
|
@@ -60830,19 +60807,19 @@ var NormalizedRangeSchema = object({
|
|
|
60830
60807
|
*/
|
|
60831
60808
|
var ImageSettingsStatusSchema = object({
|
|
60832
60809
|
/** Normalized 0–100. */
|
|
60833
|
-
brightness: number().optional(),
|
|
60810
|
+
brightness: number().optional().meta(readingMeta("none")),
|
|
60834
60811
|
/** Normalized 0–100. */
|
|
60835
|
-
contrast: number().optional(),
|
|
60812
|
+
contrast: number().optional().meta(readingMeta("none")),
|
|
60836
60813
|
/** Normalized 0–100. */
|
|
60837
|
-
saturation: number().optional(),
|
|
60814
|
+
saturation: number().optional().meta(readingMeta("none")),
|
|
60838
60815
|
/** Normalized 0–100. */
|
|
60839
|
-
sharpness: number().optional(),
|
|
60816
|
+
sharpness: number().optional().meta(readingMeta("none")),
|
|
60840
60817
|
mirror: boolean().optional(),
|
|
60841
60818
|
flip: boolean().optional(),
|
|
60842
60819
|
rotate: ImageRotateSchema.optional(),
|
|
60843
60820
|
whiteBalance: WhiteBalanceModeSchema.optional(),
|
|
60844
60821
|
/** Manual white-balance warmth, NORMALIZED 0–100. Meaningful only when `whiteBalance === 'manual'`. */
|
|
60845
|
-
warmth: number().optional(),
|
|
60822
|
+
warmth: number().optional().meta(readingMeta("none")),
|
|
60846
60823
|
exposureMode: ExposureModeSchema.optional(),
|
|
60847
60824
|
backlightMode: BacklightModeSchema.optional(),
|
|
60848
60825
|
lastFetchedAt: number()
|
|
@@ -61121,10 +61098,10 @@ var IntercomAbilitySchema = object({
|
|
|
61121
61098
|
/** Codecs accepted by firmware, in preference order. Driver-authored strings. */
|
|
61122
61099
|
codecs: array(string()),
|
|
61123
61100
|
/** Sample rate (Hz) the firmware expects. Reolink typical: 16000. */
|
|
61124
|
-
sampleRate: number(),
|
|
61101
|
+
sampleRate: number().meta(readingMeta("none")),
|
|
61125
61102
|
duplex: _enum(["half", "full"]),
|
|
61126
61103
|
/** Max in-flight audio backlog before drop (ms). Server uses this to bound latency. */
|
|
61127
|
-
maxBacklogMs: number()
|
|
61104
|
+
maxBacklogMs: number().meta(readingMeta("duration-ms"))
|
|
61128
61105
|
});
|
|
61129
61106
|
var IntercomStatusSchema = object({
|
|
61130
61107
|
/** True while a talk session is open. */
|
|
@@ -61351,13 +61328,13 @@ var LawnMowerControlStatusSchema = object({
|
|
|
61351
61328
|
activity: LawnMowerActivitySchema,
|
|
61352
61329
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
61353
61330
|
* reading. */
|
|
61354
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
61331
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61355
61332
|
/** 0..100 mowing-completion percentage of the current task, or null when no
|
|
61356
61333
|
* task is active / progress is unavailable. */
|
|
61357
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
61334
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61358
61335
|
/** Current device/event code (dynamic — mostly status, sometimes an error),
|
|
61359
61336
|
* or null when unknown. */
|
|
61360
|
-
currentCode: number().nullable(),
|
|
61337
|
+
currentCode: number().nullable().meta(readingMeta("none")),
|
|
61361
61338
|
/** Human label for {@link currentCode}, or null when undecodable. */
|
|
61362
61339
|
currentCodeLabel: string().nullable(),
|
|
61363
61340
|
/** Severity of {@link currentCode}. `error` (and often `warning`) warrants UI
|
|
@@ -61890,7 +61867,7 @@ var MediaPlayerStatusSchema = object({
|
|
|
61890
61867
|
state: MediaPlayerStateSchema,
|
|
61891
61868
|
/** Volume as 0..100 inclusive. Null when the device has no volume
|
|
61892
61869
|
* surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
|
|
61893
|
-
volumeLevel: number().min(0).max(100).nullable(),
|
|
61870
|
+
volumeLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61894
61871
|
/** Mute toggle distinct from volume=0. Null when no mute surface.
|
|
61895
61872
|
* Pair with `DeviceFeature.MediaPlayerMute`. */
|
|
61896
61873
|
isMuted: boolean().nullable(),
|
|
@@ -61903,10 +61880,10 @@ var MediaPlayerStatusSchema = object({
|
|
|
61903
61880
|
currentMedia: MediaInfoSchema.nullable(),
|
|
61904
61881
|
/** Current playback position in ms. Null when not seekable or
|
|
61905
61882
|
* nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
|
|
61906
|
-
positionMs: number().int().nonnegative().nullable(),
|
|
61883
|
+
positionMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
61907
61884
|
/** Total duration of the current media in ms. Null when unknown
|
|
61908
61885
|
* (live stream) or nothing is playing. */
|
|
61909
|
-
durationMs: number().int().nonnegative().nullable(),
|
|
61886
|
+
durationMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
61910
61887
|
/** Shuffle toggle. Null when no shuffle surface.
|
|
61911
61888
|
* Pair with `DeviceFeature.MediaPlayerShuffle`. */
|
|
61912
61889
|
shuffle: boolean().nullable(),
|
|
@@ -62215,7 +62192,7 @@ var motionCustomize = {
|
|
|
62215
62192
|
eventName: "onMotionChanged"
|
|
62216
62193
|
},
|
|
62217
62194
|
deviceTypes: [DeviceType.Camera],
|
|
62218
|
-
apply: "
|
|
62195
|
+
apply: "add",
|
|
62219
62196
|
applyAuthority: {
|
|
62220
62197
|
kind: "camera-sensors",
|
|
62221
62198
|
timeoutField: "motionCooldownMs"
|
|
@@ -62287,7 +62264,7 @@ var MotionStatusSchema = object({
|
|
|
62287
62264
|
* it, every provider seeded it at boot, and every session left it
|
|
62288
62265
|
* `detected: true` after its detach.
|
|
62289
62266
|
*/
|
|
62290
|
-
autoClearAfterMs: number().nullable()
|
|
62267
|
+
autoClearAfterMs: number().nullable().meta(readingMeta("duration-ms"))
|
|
62291
62268
|
});
|
|
62292
62269
|
/**
|
|
62293
62270
|
* Payload of `motion.onMotionChanged` event + the corresponding bus
|
|
@@ -62469,7 +62446,7 @@ var MotionZoneRegionSchema = object({
|
|
|
62469
62446
|
* the grid region(s). */
|
|
62470
62447
|
var MotionZoneStatusSchema = object({
|
|
62471
62448
|
enabled: boolean(),
|
|
62472
|
-
sensitivity: number(),
|
|
62449
|
+
sensitivity: number().meta(readingMeta("none")),
|
|
62473
62450
|
/** Grid region(s). Today exactly one `grid` shape. */
|
|
62474
62451
|
regions: array(MotionZoneRegionSchema),
|
|
62475
62452
|
lastFetchedAt: number()
|
|
@@ -62839,7 +62816,7 @@ var NavigationStatusSchema = object({
|
|
|
62839
62816
|
following: boolean(),
|
|
62840
62817
|
flash: boolean(),
|
|
62841
62818
|
lightMode: NavigationLightModeSchema,
|
|
62842
|
-
lightLevel: number().min(40).max(100),
|
|
62819
|
+
lightLevel: number().min(40).max(100).meta(readingMeta("none")),
|
|
62843
62820
|
/** Ms epoch when the slice was last updated. */
|
|
62844
62821
|
lastChangedAt: number()
|
|
62845
62822
|
});
|
|
@@ -62973,13 +62950,13 @@ var NetworkLinkStatusSchema = object({
|
|
|
62973
62950
|
* one whose reading has not landed must not be drawn at 0 %. Consumers
|
|
62974
62951
|
* SKIP a null rather than coerce it.
|
|
62975
62952
|
*/
|
|
62976
|
-
signalPercent: number().min(0).max(100).nullable(),
|
|
62953
|
+
signalPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
62977
62954
|
/** Raw received signal strength in dBm, when the firmware reports one. */
|
|
62978
|
-
rssiDbm: number().optional(),
|
|
62955
|
+
rssiDbm: number().optional().meta(readingMeta("signal-level")),
|
|
62979
62956
|
/** Network name of a wireless link, when the firmware reports it. */
|
|
62980
62957
|
ssid: string().optional(),
|
|
62981
62958
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
62982
|
-
lastUpdated: number()
|
|
62959
|
+
lastUpdated: number().meta(readingMeta("none"))
|
|
62983
62960
|
});
|
|
62984
62961
|
var networkLinkCapability = {
|
|
62985
62962
|
name: "network-link",
|
|
@@ -63364,7 +63341,7 @@ var NotifierStatusSchema = object({
|
|
|
63364
63341
|
lastError: string().nullable(),
|
|
63365
63342
|
/** Number of deliveries currently buffered server-side (rate-limited
|
|
63366
63343
|
* notifiers may queue). 0 when the provider sends synchronously. */
|
|
63367
|
-
queueDepth: number().int().nonnegative(),
|
|
63344
|
+
queueDepth: number().int().nonnegative().meta(readingMeta("count")),
|
|
63368
63345
|
/** Per-feature capability matrix — authoritative source for the
|
|
63369
63346
|
* compose-form field gating. */
|
|
63370
63347
|
supports: NotifierSupportsSchema
|
|
@@ -63456,11 +63433,9 @@ onSent: { data: object({
|
|
|
63456
63433
|
* cap fits (HA `sensor` whose `device_class` we don't have a typed cap
|
|
63457
63434
|
* for: water flow, distance, weight, frequency, signal strength, …).
|
|
63458
63435
|
*
|
|
63459
|
-
* The
|
|
63460
|
-
*
|
|
63461
|
-
*
|
|
63462
|
-
* The UI reads them directly from the slice — they are the single source
|
|
63463
|
-
* of truth for generic numeric rendering and do NOT live on `sourceInfo`.
|
|
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).
|
|
63464
63439
|
*
|
|
63465
63440
|
* Prefer the typed alternatives (`temperature-sensor`, `humidity-sensor`,
|
|
63466
63441
|
* `ambient-light-sensor`, `pressure-sensor`, `power-meter`,
|
|
@@ -63469,15 +63444,8 @@ onSent: { data: object({
|
|
|
63469
63444
|
* numeric values land here.
|
|
63470
63445
|
*/
|
|
63471
63446
|
var NumericSensorStatusSchema = object({
|
|
63472
|
-
|
|
63473
|
-
|
|
63474
|
-
* Populated live from the upstream source on each state push.
|
|
63475
|
-
* Absent for unitless sensors. */
|
|
63476
|
-
unit: string().optional(),
|
|
63477
|
-
/** Suggested decimal places for numeric display.
|
|
63478
|
-
* Populated live from the upstream source when provided.
|
|
63479
|
-
* Falls back to auto-formatting when absent. */
|
|
63480
|
-
precision: number().int().min(0).max(10).optional(),
|
|
63447
|
+
/** Reading in the device quantity's base unit. `null` when refused (D393). */
|
|
63448
|
+
value: number().nullable().meta(readingMeta("device")),
|
|
63481
63449
|
/** Ms epoch when the slice was last updated. */
|
|
63482
63450
|
lastFetchedAt: number()
|
|
63483
63451
|
});
|
|
@@ -63501,11 +63469,11 @@ var numericSensorCapability = {
|
|
|
63501
63469
|
*/
|
|
63502
63470
|
durability: "restored",
|
|
63503
63471
|
/**
|
|
63504
|
-
* 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.
|
|
63505
63474
|
*/
|
|
63506
63475
|
history: { fields: { value: {
|
|
63507
63476
|
kind: "gauge",
|
|
63508
|
-
unitFrom: "unit",
|
|
63509
63477
|
minIntervalMs: 3e4
|
|
63510
63478
|
} } },
|
|
63511
63479
|
/** Clock fields: written, but excluded from the compare that decides
|
|
@@ -63797,23 +63765,26 @@ var PetFeederStatusSchema = object({
|
|
|
63797
63765
|
/** Food currently in the bowl (grams). Null when the device has not
|
|
63798
63766
|
* reported a reading yet. On dual-hopper models this is the combined
|
|
63799
63767
|
* bowl reading; per-hopper levels live in `food1`/`food2`. */
|
|
63800
|
-
foodLevel: number().nullable(),
|
|
63768
|
+
foodLevel: number().nullable().meta(readingMeta("none")),
|
|
63801
63769
|
/** Hopper-1 food level (grams) on dual-hopper feeders; null on
|
|
63802
63770
|
* single-hopper models. */
|
|
63803
|
-
food1: number().nullable(),
|
|
63771
|
+
food1: number().nullable().meta(readingMeta("none")),
|
|
63804
63772
|
/** Hopper-2 food level (grams) on dual-hopper feeders; null on
|
|
63805
63773
|
* single-hopper models. */
|
|
63806
|
-
food2: number().nullable(),
|
|
63774
|
+
food2: number().nullable().meta(readingMeta("none")),
|
|
63807
63775
|
/** Derived low-food flag — mirrors the HA `food_level` binary_sensor
|
|
63808
63776
|
* (`device_class: problem`, on = low). True when the bowl is empty /
|
|
63809
63777
|
* below the feeder's low threshold. */
|
|
63810
63778
|
lowFood: boolean(),
|
|
63811
63779
|
/** Battery charge 0..100 (%). Null on mains-powered models or when the
|
|
63812
63780
|
* device has no battery reading. */
|
|
63813
|
-
batteryPower: number().min(0).max(100).nullable(),
|
|
63814
|
-
/**
|
|
63815
|
-
*
|
|
63816
|
-
|
|
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")),
|
|
63817
63788
|
/** True while a feed is in progress. */
|
|
63818
63789
|
feeding: boolean(),
|
|
63819
63790
|
/** Decoded connectivity / power status (HA petkit device-status enum).
|
|
@@ -63824,7 +63795,7 @@ var PetFeederStatusSchema = object({
|
|
|
63824
63795
|
* with `errorCode` for consumers that want the raw integer. */
|
|
63825
63796
|
error: string().nullable(),
|
|
63826
63797
|
/** Raw device error code (0 / null = no error). */
|
|
63827
|
-
errorCode: number().nullable(),
|
|
63798
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
63828
63799
|
/** True for D4S/D4SH dual-hopper hardware — gates the per-hopper UI. */
|
|
63829
63800
|
isDualHopper: boolean(),
|
|
63830
63801
|
/** Child-lock (manual-lock) setting — buttons on the unit are disabled. */
|
|
@@ -63834,7 +63805,7 @@ var PetFeederStatusSchema = object({
|
|
|
63834
63805
|
/** Play a chime when dispensing. */
|
|
63835
63806
|
feedSound: boolean(),
|
|
63836
63807
|
/** Speaker / prompt volume level (device-scaled integer). */
|
|
63837
|
-
volume: number(),
|
|
63808
|
+
volume: number().meta(readingMeta("none")),
|
|
63838
63809
|
/** Ms epoch when the slice was last refreshed from the cloud. */
|
|
63839
63810
|
lastFetchedAt: number()
|
|
63840
63811
|
});
|
|
@@ -63953,7 +63924,7 @@ var petFeederCapability = {
|
|
|
63953
63924
|
},
|
|
63954
63925
|
desiccantLeftDays: {
|
|
63955
63926
|
kind: "gauge",
|
|
63956
|
-
unit: "
|
|
63927
|
+
unit: "s"
|
|
63957
63928
|
}
|
|
63958
63929
|
} }
|
|
63959
63930
|
};
|
|
@@ -64354,36 +64325,19 @@ method(_void(), PlatformCapabilitiesSchema), method(_void(), HardwareInfoSchema)
|
|
|
64354
64325
|
*/
|
|
64355
64326
|
var PowerMeterStatusSchema = object({
|
|
64356
64327
|
/** Instantaneous power draw in watts. */
|
|
64357
|
-
watts: number().optional().meta({
|
|
64358
|
-
unit: "W",
|
|
64359
|
-
label: "Power"
|
|
64360
|
-
}),
|
|
64328
|
+
watts: number().optional().meta(readingMeta("power", { label: "Power" })),
|
|
64361
64329
|
/** Cumulative energy in kilowatt-hours since the meter was reset. */
|
|
64362
|
-
kwhTotal: number().optional().meta({
|
|
64363
|
-
unit: "kWh",
|
|
64364
|
-
label: "Energy"
|
|
64365
|
-
}),
|
|
64330
|
+
kwhTotal: number().optional().meta(readingMeta("energy", { label: "Energy" })),
|
|
64366
64331
|
/** Voltage in volts. */
|
|
64367
|
-
volts: number().optional(),
|
|
64332
|
+
volts: number().optional().meta(readingMeta("voltage")),
|
|
64368
64333
|
/** Current in amperes. */
|
|
64369
|
-
amps: number().optional(),
|
|
64370
|
-
/** Apparent power in volt-amperes
|
|
64371
|
-
va: number().optional(),
|
|
64334
|
+
amps: number().optional().meta(readingMeta("current")),
|
|
64335
|
+
/** Apparent power in volt-amperes. */
|
|
64336
|
+
va: number().optional().meta(readingMeta("apparent-power")),
|
|
64372
64337
|
/** Power factor (0..1) if reported. */
|
|
64373
|
-
powerFactor: number().min(0).max(1).optional(),
|
|
64338
|
+
powerFactor: number().min(0).max(1).optional().meta(readingMeta("ratio")),
|
|
64374
64339
|
/** Ms epoch when the slice was last updated. */
|
|
64375
|
-
lastFetchedAt: number()
|
|
64376
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
64377
|
-
* `attributes.unit_of_measurement` → 'V' / 'A' / 'W' / 'kW' / 'kWh').
|
|
64378
|
-
* Each upstream `sensor.*` entity surfaces ONE device_class, so one
|
|
64379
|
-
* unit per slice is unambiguous. The UI prefers this over the role's
|
|
64380
|
-
* canonical unit so a 'kW' / 'Wh' feed renders verbatim. */
|
|
64381
|
-
unit: string().optional(),
|
|
64382
|
-
/** Suggested decimal places for numeric display.
|
|
64383
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
64384
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
64385
|
-
* auto-formatting when absent. */
|
|
64386
|
-
precision: number().int().min(0).max(10).optional()
|
|
64340
|
+
lastFetchedAt: number()
|
|
64387
64341
|
});
|
|
64388
64342
|
var powerMeterCapability = {
|
|
64389
64343
|
name: "power-meter",
|
|
@@ -64447,12 +64401,7 @@ var powerMeterCapability = {
|
|
|
64447
64401
|
} },
|
|
64448
64402
|
/** Clock fields: written, but excluded from the compare that decides
|
|
64449
64403
|
* whether persisting is worth a SQLite commit. */
|
|
64450
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
64451
|
-
customize: {
|
|
64452
|
-
version: 1,
|
|
64453
|
-
advanced: "derive",
|
|
64454
|
-
targets: []
|
|
64455
|
-
}
|
|
64404
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
64456
64405
|
};
|
|
64457
64406
|
/**
|
|
64458
64407
|
* Presence cap. Models HA `person.*` and `device_tracker.*` entities
|
|
@@ -64472,11 +64421,11 @@ var powerMeterCapability = {
|
|
|
64472
64421
|
*/
|
|
64473
64422
|
var GpsLocationSchema = object({
|
|
64474
64423
|
/** Latitude in decimal degrees, -90..90. */
|
|
64475
|
-
latitude: number().min(-90).max(90),
|
|
64424
|
+
latitude: number().min(-90).max(90).meta(readingMeta("angle")),
|
|
64476
64425
|
/** Longitude in decimal degrees, -180..180. */
|
|
64477
|
-
longitude: number().min(-180).max(180),
|
|
64426
|
+
longitude: number().min(-180).max(180).meta(readingMeta("angle")),
|
|
64478
64427
|
/** Reported accuracy in meters (lower = better). */
|
|
64479
|
-
accuracyMeters: number().nonnegative()
|
|
64428
|
+
accuracyMeters: number().nonnegative().meta(readingMeta("length"))
|
|
64480
64429
|
});
|
|
64481
64430
|
var PresenceStatusSchema = object({
|
|
64482
64431
|
/** `home` / `not_home` / any user-defined zone name. */
|
|
@@ -64488,7 +64437,7 @@ var PresenceStatusSchema = object({
|
|
|
64488
64437
|
gps: GpsLocationSchema.nullable(),
|
|
64489
64438
|
/** Optional battery level of the tracking device (0..100). Null
|
|
64490
64439
|
* when not reported. */
|
|
64491
|
-
batteryPercent: number().min(0).max(100).nullable(),
|
|
64440
|
+
batteryPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
64492
64441
|
/** Ms epoch when the slice was last updated. */
|
|
64493
64442
|
lastChangedAt: number()
|
|
64494
64443
|
});
|
|
@@ -64538,19 +64487,10 @@ var presenceCapability = {
|
|
|
64538
64487
|
* `sourceInfo`.
|
|
64539
64488
|
*/
|
|
64540
64489
|
var PressureSensorStatusSchema = object({
|
|
64541
|
-
/** Current pressure in hPa. */
|
|
64542
|
-
hpa: number(),
|
|
64490
|
+
/** Current pressure in hPa. `null` when the sample was refused (D393). */
|
|
64491
|
+
hpa: number().nullable().meta(readingMeta("pressure", { precision: 0 })),
|
|
64543
64492
|
/** Ms epoch when the slice was last updated. */
|
|
64544
|
-
lastFetchedAt: number()
|
|
64545
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
64546
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
64547
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
64548
|
-
unit: string().optional(),
|
|
64549
|
-
/** Suggested decimal places for numeric display.
|
|
64550
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
64551
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
64552
|
-
* auto-formatting when absent. */
|
|
64553
|
-
precision: number().int().min(0).max(10).optional()
|
|
64493
|
+
lastFetchedAt: number()
|
|
64554
64494
|
});
|
|
64555
64495
|
var pressureSensorCapability = {
|
|
64556
64496
|
name: "pressure-sensor",
|
|
@@ -64964,8 +64904,8 @@ DeviceType.Camera, method(PtzMoveCommandSchema.extend({ deviceId: number() }), _
|
|
|
64964
64904
|
}), _void(), { kind: "mutation" });
|
|
64965
64905
|
var PtzAutotrackSettingsSchema = object({
|
|
64966
64906
|
targetType: string().describe("Vendor target string (people/vehicle/pet); empty = camera default"),
|
|
64967
|
-
stopDelaySeconds: number().int().min(0).max(300),
|
|
64968
|
-
disappearDelaySeconds: number().int().min(0).max(300)
|
|
64907
|
+
stopDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration")),
|
|
64908
|
+
disappearDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration"))
|
|
64969
64909
|
});
|
|
64970
64910
|
/**
|
|
64971
64911
|
* One option the camera advertises as a valid `targetType`. Drivers
|
|
@@ -65127,7 +65067,7 @@ var RunningStateStatusSchema = object({
|
|
|
65127
65067
|
/** null = unknown — never coerced to false (D393). */
|
|
65128
65068
|
running: boolean().nullable(),
|
|
65129
65069
|
/** Epoch ms the current boolean began; null while `running` is null. */
|
|
65130
|
-
since: number().nullable(),
|
|
65070
|
+
since: number().nullable().meta(readingMeta("none")),
|
|
65131
65071
|
source: RunningStateSourceSchema.meta({ label: "Source" }),
|
|
65132
65072
|
phase: string().nullable(),
|
|
65133
65073
|
/** null until a reading has been published (D393). */
|
|
@@ -65142,7 +65082,6 @@ var RUNNING_DEVICE_TYPES = Object.values(DeviceType);
|
|
|
65142
65082
|
/** Generic Customize target for the running boolean (D936). */
|
|
65143
65083
|
var runningCustomize = {
|
|
65144
65084
|
version: 1,
|
|
65145
|
-
advanced: "derive",
|
|
65146
65085
|
targets: [{
|
|
65147
65086
|
id: "running",
|
|
65148
65087
|
cardinality: "scalar",
|
|
@@ -65162,7 +65101,7 @@ var runningCustomize = {
|
|
|
65162
65101
|
DeviceType.Thermostat,
|
|
65163
65102
|
DeviceType.PetFeeder
|
|
65164
65103
|
],
|
|
65165
|
-
apply: "add
|
|
65104
|
+
apply: "add",
|
|
65166
65105
|
path: "running",
|
|
65167
65106
|
sources: [
|
|
65168
65107
|
{
|
|
@@ -65178,6 +65117,7 @@ var runningCustomize = {
|
|
|
65178
65117
|
requiredUnit: "W",
|
|
65179
65118
|
transforms: [{
|
|
65180
65119
|
kind: "threshold",
|
|
65120
|
+
comparisons: ["gte", "lte"],
|
|
65181
65121
|
comparison: "gte",
|
|
65182
65122
|
defaultThreshold: 5,
|
|
65183
65123
|
defaultStartDwellMs: RUNNING_POWER_START_DELAY_MS,
|
|
@@ -66425,9 +66365,9 @@ var RecordTriggerSchema = _enum([
|
|
|
66425
66365
|
*/
|
|
66426
66366
|
var RecordWindowSchema = object({
|
|
66427
66367
|
trigger: RecordTriggerSchema,
|
|
66428
|
-
day: number().int().min(0).max(6),
|
|
66429
|
-
startMinute: number().int().min(0).max(1439),
|
|
66430
|
-
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"))
|
|
66431
66371
|
});
|
|
66432
66372
|
/** Status of one physical volume, as the camera itself describes it. */
|
|
66433
66373
|
var OnboardStorageVolumeSchema = object({
|
|
@@ -66503,10 +66443,10 @@ var RecordingOnboardStatusSchema = object({
|
|
|
66503
66443
|
/** Master "record to the card at all" switch. */
|
|
66504
66444
|
enabled: boolean().nullable(),
|
|
66505
66445
|
overwriteWhenFull: boolean().nullable(),
|
|
66506
|
-
preRecordSec: number().nullable(),
|
|
66507
|
-
postRecordSec: number().nullable(),
|
|
66446
|
+
preRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
66447
|
+
postRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
66508
66448
|
/** Length of one recorded file, in minutes. */
|
|
66509
|
-
segmentMinutes: number().nullable(),
|
|
66449
|
+
segmentMinutes: number().nullable().meta(readingMeta("none")),
|
|
66510
66450
|
/** The primary track's weekly windows, flattened. */
|
|
66511
66451
|
windows: array(RecordWindowSchema),
|
|
66512
66452
|
/**
|
|
@@ -66522,7 +66462,7 @@ var RecordingOnboardStatusSchema = object({
|
|
|
66522
66462
|
* provider reporting a non-zero count also reports the schedule as not
|
|
66523
66463
|
* writable.
|
|
66524
66464
|
*/
|
|
66525
|
-
unreadableWindows: number(),
|
|
66465
|
+
unreadableWindows: number().meta(readingMeta("count")),
|
|
66526
66466
|
/**
|
|
66527
66467
|
* The camera is scheduled to record and has NO usable storage.
|
|
66528
66468
|
*
|
|
@@ -67367,7 +67307,7 @@ var CamStreamDescriptorSchema = object({
|
|
|
67367
67307
|
url: string().optional(),
|
|
67368
67308
|
codec: string().optional(),
|
|
67369
67309
|
resolution: CamStreamResolutionSchema.optional(),
|
|
67370
|
-
fps: number().positive().optional(),
|
|
67310
|
+
fps: number().positive().optional().meta(readingMeta("rate")),
|
|
67371
67311
|
label: string().optional(),
|
|
67372
67312
|
/** Device-level features (e.g. `battery-operated`) — drives broker policy. */
|
|
67373
67313
|
deviceFeatures: array(string()).optional(),
|
|
@@ -67454,18 +67394,18 @@ var StreamProfileSchema = _enum([
|
|
|
67454
67394
|
]);
|
|
67455
67395
|
/** The current encoding config of one stream profile. */
|
|
67456
67396
|
var StreamProfileConfigSchema = object({
|
|
67457
|
-
width: number(),
|
|
67458
|
-
height: number(),
|
|
67397
|
+
width: number().meta(readingMeta("none")),
|
|
67398
|
+
height: number().meta(readingMeta("none")),
|
|
67459
67399
|
codec: _enum(["h264", "h265"]),
|
|
67460
|
-
framerate: number(),
|
|
67461
|
-
bitrate: number(),
|
|
67400
|
+
framerate: number().meta(readingMeta("rate")),
|
|
67401
|
+
bitrate: number().meta(readingMeta("bitrate")),
|
|
67462
67402
|
bitrateMode: _enum(["vbr", "cbr"]).optional(),
|
|
67463
67403
|
encoderProfile: _enum([
|
|
67464
67404
|
"high",
|
|
67465
67405
|
"main",
|
|
67466
67406
|
"baseline"
|
|
67467
67407
|
]).optional(),
|
|
67468
|
-
gop: number().optional(),
|
|
67408
|
+
gop: number().optional().meta(readingMeta("none")),
|
|
67469
67409
|
/**
|
|
67470
67410
|
* Whether THIS profile currently carries an audio track. READ-ONLY here.
|
|
67471
67411
|
*
|
|
@@ -67686,12 +67626,7 @@ var switchCapability = {
|
|
|
67686
67626
|
label: "On",
|
|
67687
67627
|
kind: "boolean"
|
|
67688
67628
|
}
|
|
67689
|
-
}] }
|
|
67690
|
-
customize: {
|
|
67691
|
-
version: 1,
|
|
67692
|
-
advanced: "derive",
|
|
67693
|
-
targets: []
|
|
67694
|
-
}
|
|
67629
|
+
}] }
|
|
67695
67630
|
};
|
|
67696
67631
|
/** C0 controls, DEL and the C1 range: none of them belongs in a name. */
|
|
67697
67632
|
function hasControlCharacter(value) {
|
|
@@ -68274,35 +68209,21 @@ var tamperCapability = {
|
|
|
68274
68209
|
* entries with `device_class: temperature` and any future native
|
|
68275
68210
|
* thermometer.
|
|
68276
68211
|
*
|
|
68277
|
-
*
|
|
68278
|
-
*
|
|
68279
|
-
* (climate-control's `currentTemp`, energy analytics) can compose
|
|
68280
|
-
* without per-source unit fixups. The canonical display unit (`°C`) is
|
|
68281
|
-
* a descriptor constant in the UI (ROLE_DESCRIPTOR), not stored in
|
|
68282
|
-
* `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.
|
|
68283
68214
|
*
|
|
68284
68215
|
* Status `lastFetchedAt` lets staleness-aware consumers detect a
|
|
68285
68216
|
* frozen feed (provider hung) distinct from a "temperature hasn't
|
|
68286
68217
|
* changed" steady state.
|
|
68287
68218
|
*/
|
|
68288
68219
|
var TemperatureSensorStatusSchema = object({
|
|
68289
|
-
/** Current temperature in Celsius. */
|
|
68290
|
-
celsius: number().meta({
|
|
68291
|
-
|
|
68220
|
+
/** Current temperature in Celsius. `null` when the sample was refused (D393). */
|
|
68221
|
+
celsius: number().nullable().meta(readingMeta("temperature", {
|
|
68222
|
+
precision: 1,
|
|
68292
68223
|
label: "Temperature"
|
|
68293
|
-
}),
|
|
68224
|
+
})),
|
|
68294
68225
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
68295
|
-
lastFetchedAt: number()
|
|
68296
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
68297
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
68298
|
-
* role's canonical unit, so a Fahrenheit feed renders '°F' not '°C'.
|
|
68299
|
-
* Absent → the UI falls back to the role's canonical unit. */
|
|
68300
|
-
unit: string().optional(),
|
|
68301
|
-
/** Suggested decimal places for numeric display.
|
|
68302
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
68303
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
68304
|
-
* auto-formatting when absent. */
|
|
68305
|
-
precision: number().int().min(0).max(10).optional()
|
|
68226
|
+
lastFetchedAt: number()
|
|
68306
68227
|
});
|
|
68307
68228
|
var temperatureSensorCapability = {
|
|
68308
68229
|
name: "temperature-sensor",
|
|
@@ -68333,12 +68254,7 @@ var temperatureSensorCapability = {
|
|
|
68333
68254
|
} } },
|
|
68334
68255
|
/** Clock fields: written, but excluded from the compare that decides
|
|
68335
68256
|
* whether persisting is worth a SQLite commit. */
|
|
68336
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
68337
|
-
customize: {
|
|
68338
|
-
version: 1,
|
|
68339
|
-
advanced: "derive",
|
|
68340
|
-
targets: []
|
|
68341
|
-
}
|
|
68257
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
68342
68258
|
};
|
|
68343
68259
|
/**
|
|
68344
68260
|
* toast — system-scoped singleton capability that streams toast
|
|
@@ -68621,16 +68537,16 @@ var VacuumControlStatusSchema = object({
|
|
|
68621
68537
|
]),
|
|
68622
68538
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
68623
68539
|
* reading. */
|
|
68624
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
68540
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
68625
68541
|
/** Current fan-speed token (provider-verbatim). Null when unknown or
|
|
68626
68542
|
* the vacuum has no speed control. */
|
|
68627
68543
|
fanSpeed: string().nullable(),
|
|
68628
68544
|
/** Speed tokens the hardware accepts — drives the UI selector. */
|
|
68629
68545
|
availableFanSpeeds: array(string()),
|
|
68630
68546
|
/** 0..100 cleaning-completion percentage of the current task, or null. */
|
|
68631
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
68547
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
68632
68548
|
/** Current error code (0 / null = no error). */
|
|
68633
|
-
errorCode: number().nullable(),
|
|
68549
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
68634
68550
|
/** Human label for {@link errorCode}, or null when none / undecodable. */
|
|
68635
68551
|
errorLabel: string().nullable(),
|
|
68636
68552
|
/** Ms epoch when the slice was last updated. */
|
|
@@ -68708,7 +68624,7 @@ var ValveStatusSchema = object({
|
|
|
68708
68624
|
]),
|
|
68709
68625
|
/** 0 = fully closed, 100 = fully open. Null when the device has no
|
|
68710
68626
|
* intermediate position surface. */
|
|
68711
|
-
position: number().min(0).max(100).nullable(),
|
|
68627
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
68712
68628
|
/** Ms epoch when the slice was last updated. */
|
|
68713
68629
|
lastChangedAt: number()
|
|
68714
68630
|
});
|
|
@@ -68816,9 +68732,9 @@ var vibrationCapability = {
|
|
|
68816
68732
|
*/
|
|
68817
68733
|
var WaterHeaterStatusSchema = object({
|
|
68818
68734
|
/** Current measured temperature. Null when not reported. */
|
|
68819
|
-
currentTemp: number().nullable(),
|
|
68735
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
68820
68736
|
/** Target temperature setpoint. Null when no setpoint surface. */
|
|
68821
|
-
targetTemp: number().nullable(),
|
|
68737
|
+
targetTemp: number().nullable().meta(readingMeta("temperature")),
|
|
68822
68738
|
/** Active operation mode = HA `state` (`eco` / `electric` / `gas` /
|
|
68823
68739
|
* `heat_pump` / `high_demand` / `performance` / `off`). Null when the
|
|
68824
68740
|
* device reports an unknown state. */
|
|
@@ -68829,9 +68745,9 @@ var WaterHeaterStatusSchema = object({
|
|
|
68829
68745
|
* has no away surface. */
|
|
68830
68746
|
away: boolean().nullable(),
|
|
68831
68747
|
/** HA `min_temp` attribute. Null when not reported. */
|
|
68832
|
-
minTemp: number().nullable(),
|
|
68748
|
+
minTemp: number().nullable().meta(readingMeta("temperature")),
|
|
68833
68749
|
/** HA `max_temp` attribute. Null when not reported. */
|
|
68834
|
-
maxTemp: number().nullable(),
|
|
68750
|
+
maxTemp: number().nullable().meta(readingMeta("temperature")),
|
|
68835
68751
|
/** Ms epoch when the slice was last updated. */
|
|
68836
68752
|
lastChangedAt: number()
|
|
68837
68753
|
});
|
|
@@ -68916,25 +68832,18 @@ var waterHeaterCapability = {
|
|
|
68916
68832
|
* Forecast deferred — current conditions only for v1.
|
|
68917
68833
|
*/
|
|
68918
68834
|
var WeatherStatusSchema = object({
|
|
68919
|
-
/** Verbatim
|
|
68920
|
-
* when no condition has been reported yet. */
|
|
68835
|
+
/** Verbatim condition state (`sunny`, `cloudy`, `rainy`, …). Null when none yet. */
|
|
68921
68836
|
condition: string().nullable(),
|
|
68922
|
-
/** Current temperature in
|
|
68923
|
-
temperature: number().nullable(),
|
|
68924
|
-
/** Temperature unit string (e.g. `°C` / `°F`). Null when not provided. */
|
|
68925
|
-
temperatureUnit: string().nullable(),
|
|
68837
|
+
/** Current temperature in Celsius. Null when not provided or refused. */
|
|
68838
|
+
temperature: number().nullable().meta(readingMeta("temperature", { precision: 1 })),
|
|
68926
68839
|
/** Relative humidity (0..100). Null when not provided. */
|
|
68927
|
-
humidity: number().min(0).max(100).nullable(),
|
|
68928
|
-
/** Barometric pressure in
|
|
68929
|
-
pressure: number().nullable(),
|
|
68930
|
-
/**
|
|
68931
|
-
|
|
68932
|
-
/** Wind speed in the reported unit. Null when not provided. */
|
|
68933
|
-
windSpeed: number().nullable(),
|
|
68934
|
-
/** Wind-speed unit string (e.g. `km/h` / `mph`). Null when not provided. */
|
|
68935
|
-
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")),
|
|
68936
68845
|
/** Wind bearing in degrees (0..360, meteorological). Null when not provided. */
|
|
68937
|
-
windBearing: number().nullable(),
|
|
68846
|
+
windBearing: number().nullable().meta(readingMeta("angle")),
|
|
68938
68847
|
/** Ms epoch when the slice was last updated. */
|
|
68939
68848
|
lastFetchedAt: number()
|
|
68940
68849
|
});
|
|
@@ -68962,12 +68871,12 @@ var weatherCapability = {
|
|
|
68962
68871
|
*/
|
|
68963
68872
|
durability: "session",
|
|
68964
68873
|
/**
|
|
68965
|
-
* History (D850): recorded series.
|
|
68874
|
+
* History (D850): recorded series. Numbers are the quantity base (D944).
|
|
68966
68875
|
*/
|
|
68967
68876
|
history: { fields: {
|
|
68968
68877
|
temperature: {
|
|
68969
68878
|
kind: "gauge",
|
|
68970
|
-
|
|
68879
|
+
unit: "°C",
|
|
68971
68880
|
deadband: .2
|
|
68972
68881
|
},
|
|
68973
68882
|
humidity: {
|
|
@@ -68977,12 +68886,12 @@ var weatherCapability = {
|
|
|
68977
68886
|
},
|
|
68978
68887
|
pressure: {
|
|
68979
68888
|
kind: "gauge",
|
|
68980
|
-
|
|
68889
|
+
unit: "hPa",
|
|
68981
68890
|
deadband: .5
|
|
68982
68891
|
},
|
|
68983
68892
|
windSpeed: {
|
|
68984
68893
|
kind: "gauge",
|
|
68985
|
-
|
|
68894
|
+
unit: "m/s",
|
|
68986
68895
|
deadband: .5
|
|
68987
68896
|
}
|
|
68988
68897
|
} }
|
|
@@ -69920,6 +69829,404 @@ function runningFromMediaPlayer(state, previous, fetchedAt, transitionAt) {
|
|
|
69920
69829
|
if (state === "paused") return nativeSlice(false, "paused", previous, transitionAtMs, fetchedAt, null);
|
|
69921
69830
|
return nativeSlice(false, state, previous, transitionAtMs, fetchedAt, null);
|
|
69922
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
|
+
}
|
|
69923
70230
|
SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
|
|
69924
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;
|
|
69925
70232
|
String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
|
|
@@ -84589,7 +84896,6 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84589
84896
|
field: "value",
|
|
84590
84897
|
quantity: t("the reading", "il valore"),
|
|
84591
84898
|
label: t("Reading", "Valore"),
|
|
84592
|
-
unitField: "unit",
|
|
84593
84899
|
icon: "gauge"
|
|
84594
84900
|
}]
|
|
84595
84901
|
},
|
|
@@ -84725,7 +85031,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84725
85031
|
field: "temperature",
|
|
84726
85032
|
quantity: t("the outdoor temperature", "la temperatura esterna"),
|
|
84727
85033
|
label: t("Temperature", "Temperatura"),
|
|
84728
|
-
|
|
85034
|
+
unit: "°C",
|
|
84729
85035
|
icon: "thermometer"
|
|
84730
85036
|
},
|
|
84731
85037
|
{
|
|
@@ -84741,7 +85047,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84741
85047
|
field: "windSpeed",
|
|
84742
85048
|
quantity: t("the wind speed", "la velocità del vento"),
|
|
84743
85049
|
label: t("Wind", "Vento"),
|
|
84744
|
-
|
|
85050
|
+
unit: "m/s",
|
|
84745
85051
|
icon: "wind"
|
|
84746
85052
|
},
|
|
84747
85053
|
{
|
|
@@ -84749,7 +85055,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84749
85055
|
field: "pressure",
|
|
84750
85056
|
quantity: t("the air pressure", "la pressione atmosferica"),
|
|
84751
85057
|
label: t("Pressure", "Pressione"),
|
|
84752
|
-
|
|
85058
|
+
unit: "hPa",
|
|
84753
85059
|
icon: "gauge"
|
|
84754
85060
|
}
|
|
84755
85061
|
]
|
|
@@ -87886,6 +88192,11 @@ var PulseOverrideDraftSchema = object({
|
|
|
87886
88192
|
targetId: string().min(1),
|
|
87887
88193
|
enabled: boolean(),
|
|
87888
88194
|
debounceMs: number().nonnegative(),
|
|
88195
|
+
edges: array(_enum([
|
|
88196
|
+
"rising",
|
|
88197
|
+
"button",
|
|
88198
|
+
"native-event"
|
|
88199
|
+
])).min(1).optional(),
|
|
87889
88200
|
sources: array(OverrideSourceSchema).min(1)
|
|
87890
88201
|
});
|
|
87891
88202
|
var SpanSourceDraftSchema = OverrideSourceSchema.extend({ mode: _enum([
|
|
@@ -89317,6 +89628,96 @@ DEFAULT_NATIVE_LEASE_SETTINGS.tileBudgetMb;
|
|
|
89317
89628
|
DEFAULT_NATIVE_LEASE_SETTINGS.sceneBudgetMb;
|
|
89318
89629
|
DEFAULT_NATIVE_LEASE_SETTINGS.admission;
|
|
89319
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
|
+
/**
|
|
89320
89721
|
* Pure fuzzy matcher for adoption location import. Normalized
|
|
89321
89722
|
* case-insensitive Levenshtein similarity, used to reuse an existing
|
|
89322
89723
|
* CamStack location when an imported source location (e.g. an HA area) is
|
|
@@ -89545,6 +89946,12 @@ Object.defineProperty(exports, "automationControlCapability", {
|
|
|
89545
89946
|
return automationControlCapability;
|
|
89546
89947
|
}
|
|
89547
89948
|
});
|
|
89949
|
+
Object.defineProperty(exports, "baseUnitOf", {
|
|
89950
|
+
enumerable: true,
|
|
89951
|
+
get: function() {
|
|
89952
|
+
return baseUnitOf;
|
|
89953
|
+
}
|
|
89954
|
+
});
|
|
89548
89955
|
Object.defineProperty(exports, "batteryCapability", {
|
|
89549
89956
|
enumerable: true,
|
|
89550
89957
|
get: function() {
|
|
@@ -89761,6 +90168,18 @@ Object.defineProperty(exports, "imageCapability", {
|
|
|
89761
90168
|
return imageCapability;
|
|
89762
90169
|
}
|
|
89763
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
|
+
});
|
|
89764
90183
|
Object.defineProperty(exports, "lawnMowerControlCapability", {
|
|
89765
90184
|
enumerable: true,
|
|
89766
90185
|
get: function() {
|
|
@@ -89869,6 +90288,12 @@ Object.defineProperty(exports, "pressureSensorCapability", {
|
|
|
89869
90288
|
return pressureSensorCapability;
|
|
89870
90289
|
}
|
|
89871
90290
|
});
|
|
90291
|
+
Object.defineProperty(exports, "quantityFromUnit", {
|
|
90292
|
+
enumerable: true,
|
|
90293
|
+
get: function() {
|
|
90294
|
+
return quantityFromUnit;
|
|
90295
|
+
}
|
|
90296
|
+
});
|
|
89872
90297
|
Object.defineProperty(exports, "record", {
|
|
89873
90298
|
enumerable: true,
|
|
89874
90299
|
get: function() {
|
|
@@ -89935,6 +90360,18 @@ Object.defineProperty(exports, "temperatureSensorCapability", {
|
|
|
89935
90360
|
return temperatureSensorCapability;
|
|
89936
90361
|
}
|
|
89937
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
|
+
});
|
|
89938
90375
|
Object.defineProperty(exports, "union", {
|
|
89939
90376
|
enumerable: true,
|
|
89940
90377
|
get: function() {
|