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