@camstack/addon-provider-bosch 0.1.23 → 0.1.25
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/{account-integration-offline-BaRX_382.js → account-integration-offline-BPV9TTp1.js} +1 -1
- package/dist/{account-integration-offline-D_Vc_igI.mjs → account-integration-offline-BcUPRaQD.mjs} +1 -1
- package/dist/{dist-BMDfX7xM.js → dist-Csx3t_1B.js} +925 -495
- package/dist/{dist-D4l9YngQ.mjs → dist-DPDLG8_g.mjs} +914 -496
- package/dist/home-connect/addon.js +17 -5
- package/dist/home-connect/addon.mjs +17 -5
- package/dist/homecom/addon.js +2 -2
- package/dist/homecom/addon.mjs +2 -2
- package/dist/shc/addon.js +1 -1
- package/dist/shc/addon.mjs +1 -1
- package/package.json +7 -2
|
@@ -5434,7 +5434,7 @@ var ZodIssueCode = {
|
|
|
5434
5434
|
var ZodFirstPartyTypeKind;
|
|
5435
5435
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5436
5436
|
//#endregion
|
|
5437
|
-
//#region ../types/dist/sleep-
|
|
5437
|
+
//#region ../types/dist/sleep-CARd6wZF.mjs
|
|
5438
5438
|
/**
|
|
5439
5439
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5440
5440
|
* window to float samples (D455).
|
|
@@ -7992,6 +7992,99 @@ var RecordKindDeclarationSchema = object({
|
|
|
7992
7992
|
}).strict();
|
|
7993
7993
|
/** The kind names: lower-case, dash separated, short enough for an index name. */
|
|
7994
7994
|
var RecordKindNameSchema = string().regex(/^[a-z][a-z0-9-]{0,47}$/);
|
|
7995
|
+
var READING_QUANTITIES = [
|
|
7996
|
+
"temperature",
|
|
7997
|
+
"pressure",
|
|
7998
|
+
"speed",
|
|
7999
|
+
"precipitation",
|
|
8000
|
+
"precipitation-rate",
|
|
8001
|
+
"length",
|
|
8002
|
+
"area",
|
|
8003
|
+
"illuminance",
|
|
8004
|
+
"irradiance",
|
|
8005
|
+
"power",
|
|
8006
|
+
"energy",
|
|
8007
|
+
"voltage",
|
|
8008
|
+
"current",
|
|
8009
|
+
"apparent-power",
|
|
8010
|
+
"humidity",
|
|
8011
|
+
"percentage",
|
|
8012
|
+
"concentration-volume",
|
|
8013
|
+
"concentration-mass",
|
|
8014
|
+
"concentration-ppb",
|
|
8015
|
+
"volume",
|
|
8016
|
+
"duration",
|
|
8017
|
+
"duration-ms",
|
|
8018
|
+
"information",
|
|
8019
|
+
"sound-level",
|
|
8020
|
+
"signal-level",
|
|
8021
|
+
"colour-temperature",
|
|
8022
|
+
"angle",
|
|
8023
|
+
"bitrate",
|
|
8024
|
+
"rate",
|
|
8025
|
+
"mass",
|
|
8026
|
+
"index",
|
|
8027
|
+
"ratio",
|
|
8028
|
+
"count",
|
|
8029
|
+
"none",
|
|
8030
|
+
"device"
|
|
8031
|
+
];
|
|
8032
|
+
var ReadingQuantitySchema = _enum(READING_QUANTITIES);
|
|
8033
|
+
new Set(READING_QUANTITIES);
|
|
8034
|
+
/**
|
|
8035
|
+
* Stored unit symbol for a quantity. `none` means the number is dimensionless
|
|
8036
|
+
* (or an index / ratio / count). `device` means the cap has no single unit.
|
|
8037
|
+
*/
|
|
8038
|
+
var QUANTITY_BASE = {
|
|
8039
|
+
temperature: "°C",
|
|
8040
|
+
pressure: "hPa",
|
|
8041
|
+
speed: "m/s",
|
|
8042
|
+
precipitation: "mm",
|
|
8043
|
+
"precipitation-rate": "mm/h",
|
|
8044
|
+
length: "m",
|
|
8045
|
+
area: "m²",
|
|
8046
|
+
illuminance: "lx",
|
|
8047
|
+
irradiance: "W/m²",
|
|
8048
|
+
power: "W",
|
|
8049
|
+
energy: "kWh",
|
|
8050
|
+
voltage: "V",
|
|
8051
|
+
current: "A",
|
|
8052
|
+
"apparent-power": "VA",
|
|
8053
|
+
humidity: "%",
|
|
8054
|
+
percentage: "%",
|
|
8055
|
+
"concentration-volume": "ppm",
|
|
8056
|
+
"concentration-mass": "µg/m³",
|
|
8057
|
+
"concentration-ppb": "ppb",
|
|
8058
|
+
volume: "L",
|
|
8059
|
+
duration: "s",
|
|
8060
|
+
"duration-ms": "ms",
|
|
8061
|
+
information: "B",
|
|
8062
|
+
"sound-level": "dBFS",
|
|
8063
|
+
"signal-level": "dBm",
|
|
8064
|
+
"colour-temperature": "mired",
|
|
8065
|
+
angle: "°",
|
|
8066
|
+
bitrate: "kbps",
|
|
8067
|
+
rate: "fps",
|
|
8068
|
+
mass: "kg",
|
|
8069
|
+
index: "none",
|
|
8070
|
+
ratio: "none",
|
|
8071
|
+
count: "none",
|
|
8072
|
+
none: "none",
|
|
8073
|
+
device: "device"
|
|
8074
|
+
};
|
|
8075
|
+
/** The stored unit, or `undefined` when the quantity has no unit symbol. */
|
|
8076
|
+
function baseUnitOf(quantity) {
|
|
8077
|
+
const symbol = QUANTITY_BASE[quantity];
|
|
8078
|
+
if (symbol === "none" || symbol === "device") return void 0;
|
|
8079
|
+
return symbol;
|
|
8080
|
+
}
|
|
8081
|
+
function readingMeta(quantity, extras) {
|
|
8082
|
+
return {
|
|
8083
|
+
quantity,
|
|
8084
|
+
...extras?.precision !== void 0 ? { precision: extras.precision } : {},
|
|
8085
|
+
...extras?.label !== void 0 ? { label: extras.label } : {}
|
|
8086
|
+
};
|
|
8087
|
+
}
|
|
7995
8088
|
/** Shared Zod schemas used across streaming capabilities. */
|
|
7996
8089
|
var CamProfileSchema = _enum([
|
|
7997
8090
|
"high",
|
|
@@ -8019,8 +8112,8 @@ var CamStreamKindSchema = _enum([
|
|
|
8019
8112
|
"derived"
|
|
8020
8113
|
]);
|
|
8021
8114
|
var CamStreamResolutionSchema = object({
|
|
8022
|
-
width: number().int().positive(),
|
|
8023
|
-
height: number().int().positive()
|
|
8115
|
+
width: number().int().positive().meta(readingMeta("none")),
|
|
8116
|
+
height: number().int().positive().meta(readingMeta("none"))
|
|
8024
8117
|
});
|
|
8025
8118
|
var CameraStreamSchema = object({
|
|
8026
8119
|
/** Stable, provider-assigned id unique within the (deviceId) scope. */
|
|
@@ -8689,14 +8782,6 @@ Object.freeze({
|
|
|
8689
8782
|
{
|
|
8690
8783
|
"path": "aqi",
|
|
8691
8784
|
"valueType": "number"
|
|
8692
|
-
},
|
|
8693
|
-
{
|
|
8694
|
-
"path": "unit",
|
|
8695
|
-
"valueType": "string"
|
|
8696
|
-
},
|
|
8697
|
-
{
|
|
8698
|
-
"path": "precision",
|
|
8699
|
-
"valueType": "number"
|
|
8700
8785
|
}
|
|
8701
8786
|
],
|
|
8702
8787
|
"alarm-panel": [
|
|
@@ -8732,20 +8817,10 @@ Object.freeze({
|
|
|
8732
8817
|
"valueType": "boolean"
|
|
8733
8818
|
}
|
|
8734
8819
|
],
|
|
8735
|
-
"ambient-light-sensor": [
|
|
8736
|
-
|
|
8737
|
-
|
|
8738
|
-
|
|
8739
|
-
},
|
|
8740
|
-
{
|
|
8741
|
-
"path": "unit",
|
|
8742
|
-
"valueType": "string"
|
|
8743
|
-
},
|
|
8744
|
-
{
|
|
8745
|
-
"path": "precision",
|
|
8746
|
-
"valueType": "number"
|
|
8747
|
-
}
|
|
8748
|
-
],
|
|
8820
|
+
"ambient-light-sensor": [{
|
|
8821
|
+
"path": "lux",
|
|
8822
|
+
"valueType": "number"
|
|
8823
|
+
}],
|
|
8749
8824
|
"audio-metrics": [
|
|
8750
8825
|
{
|
|
8751
8826
|
"path": "ts",
|
|
@@ -8825,6 +8900,10 @@ Object.freeze({
|
|
|
8825
8900
|
"path": "lastUpdated",
|
|
8826
8901
|
"valueType": "number"
|
|
8827
8902
|
},
|
|
8903
|
+
{
|
|
8904
|
+
"path": "volts",
|
|
8905
|
+
"valueType": "number"
|
|
8906
|
+
},
|
|
8828
8907
|
{
|
|
8829
8908
|
"path": "lastContactAt",
|
|
8830
8909
|
"valueType": "number"
|
|
@@ -9067,10 +9146,6 @@ Object.freeze({
|
|
|
9067
9146
|
"datetime"
|
|
9068
9147
|
]
|
|
9069
9148
|
},
|
|
9070
|
-
{
|
|
9071
|
-
"path": "unit",
|
|
9072
|
-
"valueType": "string"
|
|
9073
|
-
},
|
|
9074
9149
|
{
|
|
9075
9150
|
"path": "min",
|
|
9076
9151
|
"valueType": "number"
|
|
@@ -9082,19 +9157,6 @@ Object.freeze({
|
|
|
9082
9157
|
{
|
|
9083
9158
|
"path": "step",
|
|
9084
9159
|
"valueType": "number"
|
|
9085
|
-
},
|
|
9086
|
-
{
|
|
9087
|
-
"path": "precision",
|
|
9088
|
-
"valueType": "number"
|
|
9089
|
-
},
|
|
9090
|
-
{
|
|
9091
|
-
"path": "format",
|
|
9092
|
-
"valueType": "enum",
|
|
9093
|
-
"enumValues": [
|
|
9094
|
-
"date",
|
|
9095
|
-
"time",
|
|
9096
|
-
"datetime"
|
|
9097
|
-
]
|
|
9098
9160
|
}
|
|
9099
9161
|
],
|
|
9100
9162
|
"cover": [
|
|
@@ -9335,13 +9397,8 @@ Object.freeze({
|
|
|
9335
9397
|
"path": "value",
|
|
9336
9398
|
"valueType": "string"
|
|
9337
9399
|
}, {
|
|
9338
|
-
"path": "
|
|
9339
|
-
"valueType": "
|
|
9340
|
-
"enumValues": [
|
|
9341
|
-
"date",
|
|
9342
|
-
"time",
|
|
9343
|
-
"datetime"
|
|
9344
|
-
]
|
|
9400
|
+
"path": "timestamp",
|
|
9401
|
+
"valueType": "boolean"
|
|
9345
9402
|
}],
|
|
9346
9403
|
"event-emitter": [
|
|
9347
9404
|
{
|
|
@@ -9448,20 +9505,10 @@ Object.freeze({
|
|
|
9448
9505
|
"valueType": "number"
|
|
9449
9506
|
}
|
|
9450
9507
|
],
|
|
9451
|
-
"humidity-sensor": [
|
|
9452
|
-
|
|
9453
|
-
|
|
9454
|
-
|
|
9455
|
-
},
|
|
9456
|
-
{
|
|
9457
|
-
"path": "unit",
|
|
9458
|
-
"valueType": "string"
|
|
9459
|
-
},
|
|
9460
|
-
{
|
|
9461
|
-
"path": "precision",
|
|
9462
|
-
"valueType": "number"
|
|
9463
|
-
}
|
|
9464
|
-
],
|
|
9508
|
+
"humidity-sensor": [{
|
|
9509
|
+
"path": "percent",
|
|
9510
|
+
"valueType": "number"
|
|
9511
|
+
}],
|
|
9465
9512
|
"image": [{
|
|
9466
9513
|
"path": "url",
|
|
9467
9514
|
"valueType": "string"
|
|
@@ -9800,20 +9847,10 @@ Object.freeze({
|
|
|
9800
9847
|
"valueType": "boolean"
|
|
9801
9848
|
}
|
|
9802
9849
|
],
|
|
9803
|
-
"numeric-sensor": [
|
|
9804
|
-
|
|
9805
|
-
|
|
9806
|
-
|
|
9807
|
-
},
|
|
9808
|
-
{
|
|
9809
|
-
"path": "unit",
|
|
9810
|
-
"valueType": "string"
|
|
9811
|
-
},
|
|
9812
|
-
{
|
|
9813
|
-
"path": "precision",
|
|
9814
|
-
"valueType": "number"
|
|
9815
|
-
}
|
|
9816
|
-
],
|
|
9850
|
+
"numeric-sensor": [{
|
|
9851
|
+
"path": "value",
|
|
9852
|
+
"valueType": "number"
|
|
9853
|
+
}],
|
|
9817
9854
|
"pet-feeder": [
|
|
9818
9855
|
{
|
|
9819
9856
|
"path": "foodLevel",
|
|
@@ -9905,14 +9942,6 @@ Object.freeze({
|
|
|
9905
9942
|
{
|
|
9906
9943
|
"path": "powerFactor",
|
|
9907
9944
|
"valueType": "number"
|
|
9908
|
-
},
|
|
9909
|
-
{
|
|
9910
|
-
"path": "unit",
|
|
9911
|
-
"valueType": "string"
|
|
9912
|
-
},
|
|
9913
|
-
{
|
|
9914
|
-
"path": "precision",
|
|
9915
|
-
"valueType": "number"
|
|
9916
9945
|
}
|
|
9917
9946
|
],
|
|
9918
9947
|
"presence": [
|
|
@@ -9941,20 +9970,10 @@ Object.freeze({
|
|
|
9941
9970
|
"valueType": "number"
|
|
9942
9971
|
}
|
|
9943
9972
|
],
|
|
9944
|
-
"pressure-sensor": [
|
|
9945
|
-
|
|
9946
|
-
|
|
9947
|
-
|
|
9948
|
-
},
|
|
9949
|
-
{
|
|
9950
|
-
"path": "unit",
|
|
9951
|
-
"valueType": "string"
|
|
9952
|
-
},
|
|
9953
|
-
{
|
|
9954
|
-
"path": "precision",
|
|
9955
|
-
"valueType": "number"
|
|
9956
|
-
}
|
|
9957
|
-
],
|
|
9973
|
+
"pressure-sensor": [{
|
|
9974
|
+
"path": "hpa",
|
|
9975
|
+
"valueType": "number"
|
|
9976
|
+
}],
|
|
9958
9977
|
"privacy-mask": [{
|
|
9959
9978
|
"path": "enabled",
|
|
9960
9979
|
"valueType": "boolean"
|
|
@@ -10265,20 +10284,10 @@ Object.freeze({
|
|
|
10265
10284
|
"path": "tampered",
|
|
10266
10285
|
"valueType": "boolean"
|
|
10267
10286
|
}],
|
|
10268
|
-
"temperature-sensor": [
|
|
10269
|
-
|
|
10270
|
-
|
|
10271
|
-
|
|
10272
|
-
},
|
|
10273
|
-
{
|
|
10274
|
-
"path": "unit",
|
|
10275
|
-
"valueType": "string"
|
|
10276
|
-
},
|
|
10277
|
-
{
|
|
10278
|
-
"path": "precision",
|
|
10279
|
-
"valueType": "number"
|
|
10280
|
-
}
|
|
10281
|
-
],
|
|
10287
|
+
"temperature-sensor": [{
|
|
10288
|
+
"path": "celsius",
|
|
10289
|
+
"valueType": "number"
|
|
10290
|
+
}],
|
|
10282
10291
|
"update": [
|
|
10283
10292
|
{
|
|
10284
10293
|
"path": "currentVersion",
|
|
@@ -10389,10 +10398,6 @@ Object.freeze({
|
|
|
10389
10398
|
"path": "temperature",
|
|
10390
10399
|
"valueType": "number"
|
|
10391
10400
|
},
|
|
10392
|
-
{
|
|
10393
|
-
"path": "temperatureUnit",
|
|
10394
|
-
"valueType": "string"
|
|
10395
|
-
},
|
|
10396
10401
|
{
|
|
10397
10402
|
"path": "humidity",
|
|
10398
10403
|
"valueType": "number"
|
|
@@ -10401,18 +10406,10 @@ Object.freeze({
|
|
|
10401
10406
|
"path": "pressure",
|
|
10402
10407
|
"valueType": "number"
|
|
10403
10408
|
},
|
|
10404
|
-
{
|
|
10405
|
-
"path": "pressureUnit",
|
|
10406
|
-
"valueType": "string"
|
|
10407
|
-
},
|
|
10408
10409
|
{
|
|
10409
10410
|
"path": "windSpeed",
|
|
10410
10411
|
"valueType": "number"
|
|
10411
10412
|
},
|
|
10412
|
-
{
|
|
10413
|
-
"path": "windSpeedUnit",
|
|
10414
|
-
"valueType": "string"
|
|
10415
|
-
},
|
|
10416
10413
|
{
|
|
10417
10414
|
"path": "windBearing",
|
|
10418
10415
|
"valueType": "number"
|
|
@@ -17876,7 +17873,8 @@ var CompositionProblemSchema = object({
|
|
|
17876
17873
|
"item-field-reserved",
|
|
17877
17874
|
"target-missing",
|
|
17878
17875
|
"target-unreadable",
|
|
17879
|
-
"not-replaceable"
|
|
17876
|
+
"not-replaceable",
|
|
17877
|
+
"native-capability-replace"
|
|
17880
17878
|
]),
|
|
17881
17879
|
path: string(),
|
|
17882
17880
|
message: string()
|
|
@@ -17934,9 +17932,11 @@ var CompositionFieldPlanSchema = object({
|
|
|
17934
17932
|
reads: array(CompositionFieldReadSchema)
|
|
17935
17933
|
});
|
|
17936
17934
|
/**
|
|
17937
|
-
* What a feature does to its target (D663): `new` builds a capability on a
|
|
17938
|
-
* device; on an existing device it `add`s a capability the device lacks
|
|
17939
|
-
*
|
|
17935
|
+
* What a feature does to its target (D663, D944): `new` builds a capability on a
|
|
17936
|
+
* new device; on an existing device it `add`s a capability the device lacks.
|
|
17937
|
+
* Replacing a capability the device already serves is refused
|
|
17938
|
+
* (`native-capability-replace`), not planned. `replace` remains on the claim
|
|
17939
|
+
* wire for a claim the hub already holds.
|
|
17940
17940
|
*/
|
|
17941
17941
|
var CompositionFeatureModeSchema = _enum([
|
|
17942
17942
|
"new",
|
|
@@ -19822,12 +19822,12 @@ method(object({ deviceId: number().int().nonnegative() }), DeviceAdminLinkSchema
|
|
|
19822
19822
|
* providers detect renames by matching `uniqueId` and patch `id`
|
|
19823
19823
|
* in-place so dispatch keeps working.
|
|
19824
19824
|
*
|
|
19825
|
-
* **
|
|
19826
|
-
*
|
|
19827
|
-
*
|
|
19828
|
-
*
|
|
19829
|
-
* (`ha-domain-mapping`)
|
|
19830
|
-
* stored after that point.
|
|
19825
|
+
* **Display unit and precision are NOT stored here.** They are a read-time
|
|
19826
|
+
* preference (D944). A polymorphic reading stores its `quantity` here once,
|
|
19827
|
+
* at adopt, and a date/time value stores `dateTimeShape` the same way —
|
|
19828
|
+
* neither is repeated on each sample. The `device_class` tag is an
|
|
19829
|
+
* HA-specific input consumed at the discovery boundary (`ha-domain-mapping`)
|
|
19830
|
+
* to derive the CamStack `DeviceRole`; it is never stored after that point.
|
|
19831
19831
|
*
|
|
19832
19832
|
* The `raw` escape hatch carries provider-specific attributes that don't
|
|
19833
19833
|
* fit the structured slots (HA `attributes` whitelist, Reolink `deviceCache`
|
|
@@ -19841,6 +19841,14 @@ var SourceInfoSchema = object({
|
|
|
19841
19841
|
/** Immutable upstream identifier when available (HA `unique_id`, … ).
|
|
19842
19842
|
* Used to detect rename when `id` changes. */
|
|
19843
19843
|
uniqueId: string().optional(),
|
|
19844
|
+
/** Quantity of a polymorphic reading, written once at adopt (D944). */
|
|
19845
|
+
quantity: ReadingQuantitySchema.optional(),
|
|
19846
|
+
/** Date / time / datetime shape of a string reading, written once at adopt. */
|
|
19847
|
+
dateTimeShape: _enum([
|
|
19848
|
+
"date",
|
|
19849
|
+
"time",
|
|
19850
|
+
"datetime"
|
|
19851
|
+
]).optional(),
|
|
19844
19852
|
/** Provider-specific extras that don't fit the structured slots.
|
|
19845
19853
|
* Whitelist what goes here per provider — do NOT dump entire HA
|
|
19846
19854
|
* attribute blobs (would explode the meta JSON column). */
|
|
@@ -19886,6 +19894,80 @@ function mergeSourceInfo(prev, patch) {
|
|
|
19886
19894
|
return next;
|
|
19887
19895
|
}
|
|
19888
19896
|
/**
|
|
19897
|
+
* Coerce common unit-of-measurement string variants to a canonical form
|
|
19898
|
+
* so the UI's display templates can rely on stable strings. Pure
|
|
19899
|
+
* passthrough for unknown units — kept conservative on purpose, the goal
|
|
19900
|
+
* is to normalise the long tail of HA `unit_of_measurement` values that
|
|
19901
|
+
* have multiple historical spellings (`'°C'` vs `'C'` vs `'celsius'`).
|
|
19902
|
+
*
|
|
19903
|
+
* Extend the map as we encounter real-world data. Returning the raw
|
|
19904
|
+
* input for unknown values is intentional: providers should never
|
|
19905
|
+
* lose information silently here.
|
|
19906
|
+
*/
|
|
19907
|
+
function normalizeUnit(raw) {
|
|
19908
|
+
if (raw == null) return void 0;
|
|
19909
|
+
const trimmed = raw.trim();
|
|
19910
|
+
if (trimmed === "") return void 0;
|
|
19911
|
+
const lower = trimmed.toLowerCase();
|
|
19912
|
+
if (lower === "°c" || lower === "c" || lower === "celsius") return "°C";
|
|
19913
|
+
if (lower === "°f" || lower === "f" || lower === "fahrenheit") return "°F";
|
|
19914
|
+
if (lower === "k" || lower === "kelvin") return "K";
|
|
19915
|
+
if (lower === "%" || lower === "percent" || lower === "percentage") return "%";
|
|
19916
|
+
if (lower === "lx" || lower === "lux") return "lx";
|
|
19917
|
+
if (lower === "hpa" || lower === "hectopascal") return "hPa";
|
|
19918
|
+
if (lower === "kpa") return "kPa";
|
|
19919
|
+
if (lower === "pa") return "Pa";
|
|
19920
|
+
if (lower === "mbar" || lower === "millibar") return "mbar";
|
|
19921
|
+
if (lower === "w" || lower === "watt") return "W";
|
|
19922
|
+
if (lower === "kw" || lower === "kilowatt") return "kW";
|
|
19923
|
+
if (lower === "wh" || lower === "watt-hour") return "Wh";
|
|
19924
|
+
if (lower === "kwh" || lower === "kilowatt-hour") return "kWh";
|
|
19925
|
+
if (lower === "v" || lower === "volt") return "V";
|
|
19926
|
+
if (lower === "a" || lower === "amp" || lower === "ampere") return "A";
|
|
19927
|
+
if (lower === "ma" || lower === "milliampere") return "mA";
|
|
19928
|
+
if (lower === "va") return "VA";
|
|
19929
|
+
if (lower === "ppm") return "ppm";
|
|
19930
|
+
if (lower === "ppb") return "ppb";
|
|
19931
|
+
if (lower === "µg/m³" || lower === "ug/m3" || lower === "µg/m3") return "µg/m³";
|
|
19932
|
+
if (lower === "km/h" || lower === "kph") return "km/h";
|
|
19933
|
+
if (lower === "mph") return "mph";
|
|
19934
|
+
if (lower === "m/s") return "m/s";
|
|
19935
|
+
if (lower === "m") return "m";
|
|
19936
|
+
if (lower === "m²" || lower === "m2") return "m²";
|
|
19937
|
+
if (lower === "mm") return "mm";
|
|
19938
|
+
if (lower === "cm") return "cm";
|
|
19939
|
+
if (lower === "km") return "km";
|
|
19940
|
+
if (lower === "in" || lower === "inch" || lower === "inches") return "in";
|
|
19941
|
+
if (lower === "ft" || lower === "foot" || lower === "feet") return "ft";
|
|
19942
|
+
if (lower === "kg") return "kg";
|
|
19943
|
+
if (lower === "g") return "g";
|
|
19944
|
+
if (lower === "l" || lower === "liter" || lower === "litre" || lower === "liters" || lower === "litres") return "L";
|
|
19945
|
+
if (lower === "ml") return "mL";
|
|
19946
|
+
if (lower === "gal" || lower === "gallon" || lower === "gallons") return "gal";
|
|
19947
|
+
if (lower === "s" || lower === "sec" || lower === "second" || lower === "seconds") return "s";
|
|
19948
|
+
if (lower === "ms") return "ms";
|
|
19949
|
+
if (lower === "min" || lower === "minute" || lower === "minutes") return "min";
|
|
19950
|
+
if (lower === "h" || lower === "hr" || lower === "hour" || lower === "hours") return "h";
|
|
19951
|
+
if (lower === "d" || lower === "day" || lower === "days") return "d";
|
|
19952
|
+
if (lower === "b" || lower === "byte" || lower === "bytes") return "B";
|
|
19953
|
+
if (lower === "kib") return "KiB";
|
|
19954
|
+
if (lower === "mib") return "MiB";
|
|
19955
|
+
if (lower === "gib") return "GiB";
|
|
19956
|
+
if (lower === "tib") return "TiB";
|
|
19957
|
+
if (lower === "kb") return "kB";
|
|
19958
|
+
if (lower === "mb") return "MB";
|
|
19959
|
+
if (lower === "gb") return "GB";
|
|
19960
|
+
if (lower === "dbm") return "dBm";
|
|
19961
|
+
if (lower === "dbfs") return "dBFS";
|
|
19962
|
+
if (lower === "inhg") return "inHg";
|
|
19963
|
+
if (lower === "mm/h") return "mm/h";
|
|
19964
|
+
if (lower === "w/m²" || lower === "w/m2") return "W/m²";
|
|
19965
|
+
if (lower === "°" || lower === "deg" || lower === "degree" || lower === "degrees") return "°";
|
|
19966
|
+
if (lower === "kbps") return "kbps";
|
|
19967
|
+
if (lower === "fps") return "fps";
|
|
19968
|
+
return trimmed;
|
|
19969
|
+
}
|
|
19970
|
+
/**
|
|
19889
19971
|
* Key under which `SourceInfo` lives inside `DeviceMeta.metadata`. The
|
|
19890
19972
|
* blob is a free-form `Record<string, unknown>` shared with hardware-
|
|
19891
19973
|
* identity fields (`manufacturer`, `model`, `firmware`, …); SourceInfo
|
|
@@ -40962,7 +41044,8 @@ method(object({
|
|
|
40962
41044
|
"enum"
|
|
40963
41045
|
]),
|
|
40964
41046
|
enumValues: array(string()).optional(),
|
|
40965
|
-
item: boolean().optional()
|
|
41047
|
+
item: boolean().optional(),
|
|
41048
|
+
quantity: ReadingQuantitySchema.optional()
|
|
40966
41049
|
})).readonly(),
|
|
40967
41050
|
itemArray: object({
|
|
40968
41051
|
path: string(),
|
|
@@ -44806,8 +44889,8 @@ var MaskPolygonShapeSchema = object({
|
|
|
44806
44889
|
/** Boolean cell grid — row-major, length === gridWidth*gridHeight. */
|
|
44807
44890
|
var MaskGridShapeSchema = object({
|
|
44808
44891
|
kind: literal("grid"),
|
|
44809
|
-
gridWidth: number(),
|
|
44810
|
-
gridHeight: number(),
|
|
44892
|
+
gridWidth: number().meta(readingMeta("none")),
|
|
44893
|
+
gridHeight: number().meta(readingMeta("none")),
|
|
44811
44894
|
cells: array(boolean())
|
|
44812
44895
|
});
|
|
44813
44896
|
discriminatedUnion("kind", [
|
|
@@ -56287,27 +56370,17 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
|
|
|
56287
56370
|
*/
|
|
56288
56371
|
var AirQualitySensorStatusSchema = object({
|
|
56289
56372
|
/** Carbon dioxide concentration in ppm. */
|
|
56290
|
-
co2Ppm: number().min(0).optional(),
|
|
56373
|
+
co2Ppm: number().min(0).optional().meta(readingMeta("concentration-volume")),
|
|
56291
56374
|
/** Total volatile organic compounds in ppb. */
|
|
56292
|
-
vocPpb: number().min(0).optional(),
|
|
56375
|
+
vocPpb: number().min(0).optional().meta(readingMeta("concentration-ppb")),
|
|
56293
56376
|
/** Particulate matter ≤ 2.5 μm in µg/m³. */
|
|
56294
|
-
pm25: number().min(0).optional(),
|
|
56377
|
+
pm25: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
56295
56378
|
/** Particulate matter ≤ 10 μm in µg/m³. */
|
|
56296
|
-
pm10: number().min(0).optional(),
|
|
56379
|
+
pm10: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
56297
56380
|
/** Composite AQI value (typically 0..500). */
|
|
56298
|
-
aqi: number().optional(),
|
|
56381
|
+
aqi: number().optional().meta(readingMeta("index")),
|
|
56299
56382
|
/** Ms epoch when the slice was last updated. */
|
|
56300
|
-
lastFetchedAt: number()
|
|
56301
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
56302
|
-
* `attributes.unit_of_measurement` → 'ppm' / 'ppb' / 'µg/m³'). Each
|
|
56303
|
-
* upstream `sensor.*` entity surfaces ONE device_class, so one unit
|
|
56304
|
-
* per slice is unambiguous. */
|
|
56305
|
-
unit: string().optional(),
|
|
56306
|
-
/** Suggested decimal places for numeric display.
|
|
56307
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
56308
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
56309
|
-
* auto-formatting when absent. */
|
|
56310
|
-
precision: number().int().min(0).max(10).optional()
|
|
56383
|
+
lastFetchedAt: number()
|
|
56311
56384
|
});
|
|
56312
56385
|
var airQualitySensorCapability = {
|
|
56313
56386
|
name: "air-quality-sensor",
|
|
@@ -56344,12 +56417,12 @@ var airQualitySensorCapability = {
|
|
|
56344
56417
|
},
|
|
56345
56418
|
pm25: {
|
|
56346
56419
|
kind: "gauge",
|
|
56347
|
-
unit: "
|
|
56420
|
+
unit: "µg/m³",
|
|
56348
56421
|
deadband: 1
|
|
56349
56422
|
},
|
|
56350
56423
|
pm10: {
|
|
56351
56424
|
kind: "gauge",
|
|
56352
|
-
unit: "
|
|
56425
|
+
unit: "µg/m³",
|
|
56353
56426
|
deadband: 1
|
|
56354
56427
|
},
|
|
56355
56428
|
aqi: {
|
|
@@ -56367,22 +56440,13 @@ var airQualitySensorCapability = {
|
|
|
56367
56440
|
* entries with `device_class: illuminance`.
|
|
56368
56441
|
*/
|
|
56369
56442
|
var AmbientLightSensorStatusSchema = object({
|
|
56370
|
-
/** Current illuminance in lux (lx). */
|
|
56371
|
-
lux: number().min(0).meta({
|
|
56372
|
-
|
|
56443
|
+
/** Current illuminance in lux (lx). `null` when the sample was refused (D393). */
|
|
56444
|
+
lux: number().min(0).nullable().meta(readingMeta("illuminance", {
|
|
56445
|
+
precision: 0,
|
|
56373
56446
|
label: "Illuminance"
|
|
56374
|
-
}),
|
|
56447
|
+
})),
|
|
56375
56448
|
/** Ms epoch when the slice was last updated. */
|
|
56376
|
-
lastFetchedAt: number()
|
|
56377
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
56378
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
56379
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
56380
|
-
unit: string().optional(),
|
|
56381
|
-
/** Suggested decimal places for numeric display.
|
|
56382
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
56383
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
56384
|
-
* auto-formatting when absent. */
|
|
56385
|
-
precision: number().int().min(0).max(10).optional()
|
|
56449
|
+
lastFetchedAt: number()
|
|
56386
56450
|
});
|
|
56387
56451
|
var ambientLightSensorCapability = {
|
|
56388
56452
|
name: "ambient-light-sensor",
|
|
@@ -56414,12 +56478,7 @@ var ambientLightSensorCapability = {
|
|
|
56414
56478
|
} } },
|
|
56415
56479
|
/** Clock fields: written, but excluded from the compare that decides
|
|
56416
56480
|
* whether persisting is worth a SQLite commit. */
|
|
56417
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
56418
|
-
customize: {
|
|
56419
|
-
version: 1,
|
|
56420
|
-
advanced: "derive",
|
|
56421
|
-
targets: []
|
|
56422
|
-
}
|
|
56481
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
56423
56482
|
};
|
|
56424
56483
|
/**
|
|
56425
56484
|
* Per-class audio metrics aggregated over a sliding window.
|
|
@@ -56646,10 +56705,7 @@ var BatteryStatusSchema = object({
|
|
|
56646
56705
|
* Consumers must SKIP a null rather than coerce it — `battery-band` already
|
|
56647
56706
|
* declines to band a non-finite reading, which is the correct shape.
|
|
56648
56707
|
*/
|
|
56649
|
-
percentage: number().min(0).max(100).nullable().meta({
|
|
56650
|
-
unit: "%",
|
|
56651
|
-
label: "Charge"
|
|
56652
|
-
}),
|
|
56708
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage", { label: "Charge" })),
|
|
56653
56709
|
/**
|
|
56654
56710
|
* Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
|
|
56655
56711
|
* Reolink-specific for the Solar Panel 2 accessory (will become
|
|
@@ -56676,7 +56732,14 @@ var BatteryStatusSchema = object({
|
|
|
56676
56732
|
*/
|
|
56677
56733
|
sleeping: boolean().meta({ label: "Sleeping" }),
|
|
56678
56734
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
56679
|
-
lastUpdated: number(),
|
|
56735
|
+
lastUpdated: number().meta(readingMeta("none")),
|
|
56736
|
+
/**
|
|
56737
|
+
* Battery voltage in volts, for a cell the firmware reports as voltage
|
|
56738
|
+
* rather than a percentage (Ecowitt capacitor packs). Absent on cameras
|
|
56739
|
+
* that only report charge. A second reading on this cap, not a second
|
|
56740
|
+
* `numeric-sensor` on the same device.
|
|
56741
|
+
*/
|
|
56742
|
+
volts: number().nullable().optional().meta(readingMeta("voltage", { label: "Voltage" })),
|
|
56680
56743
|
/**
|
|
56681
56744
|
* Ms epoch of the last time the device PROVED it was reachable — a
|
|
56682
56745
|
* completed firmware round-trip, an observed wake, or an inbound push
|
|
@@ -56728,7 +56791,6 @@ var BATTERY_DEVICE_TYPES = [
|
|
|
56728
56791
|
/** Generic Customize target for the percentage reading (D936). */
|
|
56729
56792
|
var batteryCustomize = {
|
|
56730
56793
|
version: 1,
|
|
56731
|
-
advanced: "derive",
|
|
56732
56794
|
targets: [{
|
|
56733
56795
|
id: "percentage",
|
|
56734
56796
|
cardinality: "scalar",
|
|
@@ -56737,7 +56799,7 @@ var batteryCustomize = {
|
|
|
56737
56799
|
stateField: "percentage"
|
|
56738
56800
|
},
|
|
56739
56801
|
deviceTypes: BATTERY_DEVICE_TYPES,
|
|
56740
|
-
apply: "add
|
|
56802
|
+
apply: "add",
|
|
56741
56803
|
path: "percentage",
|
|
56742
56804
|
sources: [{
|
|
56743
56805
|
kind: "field",
|
|
@@ -56858,10 +56920,16 @@ onStatusChanged: { data: object({
|
|
|
56858
56920
|
/**
|
|
56859
56921
|
* History (D850): recorded series. The generic capture replaces the `battery` series of `pipeline-analytics:stats-5m`.
|
|
56860
56922
|
*/
|
|
56861
|
-
history: { fields: {
|
|
56862
|
-
|
|
56863
|
-
|
|
56864
|
-
|
|
56923
|
+
history: { fields: {
|
|
56924
|
+
percentage: {
|
|
56925
|
+
kind: "gauge",
|
|
56926
|
+
unit: "%"
|
|
56927
|
+
},
|
|
56928
|
+
volts: {
|
|
56929
|
+
kind: "gauge",
|
|
56930
|
+
unit: "V"
|
|
56931
|
+
}
|
|
56932
|
+
} },
|
|
56865
56933
|
customize: batteryCustomize,
|
|
56866
56934
|
/** Clock fields: written, but excluded from the compare that decides
|
|
56867
56935
|
* whether persisting is worth a SQLite commit. */
|
|
@@ -56908,12 +56976,7 @@ var binaryCapability = {
|
|
|
56908
56976
|
history: { fields: { on: { kind: "boolean" } } },
|
|
56909
56977
|
/** Clock fields: written, but excluded from the compare that decides
|
|
56910
56978
|
* whether persisting is worth a SQLite commit. */
|
|
56911
|
-
volatileStateFields: ["lastChangedAt"]
|
|
56912
|
-
customize: {
|
|
56913
|
-
version: 1,
|
|
56914
|
-
advanced: "derive",
|
|
56915
|
-
targets: []
|
|
56916
|
-
}
|
|
56979
|
+
volatileStateFields: ["lastChangedAt"]
|
|
56917
56980
|
};
|
|
56918
56981
|
/**
|
|
56919
56982
|
* Dimmable-light brightness control. Co-exists with `switch` on the
|
|
@@ -56929,7 +56992,7 @@ var binaryCapability = {
|
|
|
56929
56992
|
*/
|
|
56930
56993
|
var BrightnessStatusSchema = object({
|
|
56931
56994
|
/** Current level as 0..100 inclusive. Firmware-reported. */
|
|
56932
|
-
percentage: number().min(0).max(100),
|
|
56995
|
+
percentage: number().min(0).max(100).meta(readingMeta("percentage")),
|
|
56933
56996
|
/** Ms epoch of the last operator-driven change. Useful for UI freshness. */
|
|
56934
56997
|
lastChangedAt: number()
|
|
56935
56998
|
});
|
|
@@ -57383,21 +57446,21 @@ var ClimateControlStatusSchema = object({
|
|
|
57383
57446
|
/** Single setpoint in Celsius. Used by single-target modes
|
|
57384
57447
|
* (heat / cool / dry). Null when the device is in a range mode
|
|
57385
57448
|
* (`heat_cool`) or has no setpoint at all (`fan_only`/`off`). */
|
|
57386
|
-
target: number().nullable(),
|
|
57449
|
+
target: number().nullable().meta(readingMeta("temperature")),
|
|
57387
57450
|
/** Upper bound of the dual setpoint in Celsius. Populated only
|
|
57388
57451
|
* in `heat_cool` mode. */
|
|
57389
|
-
targetHigh: number().nullable(),
|
|
57452
|
+
targetHigh: number().nullable().meta(readingMeta("temperature")),
|
|
57390
57453
|
/** Lower bound of the dual setpoint in Celsius. Populated only
|
|
57391
57454
|
* in `heat_cool` mode. */
|
|
57392
|
-
targetLow: number().nullable(),
|
|
57455
|
+
targetLow: number().nullable().meta(readingMeta("temperature")),
|
|
57393
57456
|
/** Target relative humidity (0..100). Null when the device has no
|
|
57394
57457
|
* humidity control. */
|
|
57395
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
57458
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
57396
57459
|
/** Current measured temperature in Celsius. Read-only — pushed by
|
|
57397
57460
|
* the device's internal sensor. */
|
|
57398
|
-
currentTemp: number().nullable(),
|
|
57461
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
57399
57462
|
/** Current measured relative humidity (0..100). Read-only. */
|
|
57400
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
57463
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
57401
57464
|
/** Vertical louver swing on/off. Null when the device has no vertical
|
|
57402
57465
|
* swing surface (gate with `DeviceFeature.ClimateSwingVertical`). */
|
|
57403
57466
|
swingVertical: boolean().nullable(),
|
|
@@ -57405,11 +57468,11 @@ var ClimateControlStatusSchema = object({
|
|
|
57405
57468
|
* horizontal swing surface (gate with `DeviceFeature.ClimateSwingHorizontal`). */
|
|
57406
57469
|
swingHorizontal: boolean().nullable(),
|
|
57407
57470
|
/** Lowest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
57408
|
-
minTemp: number().nullable().optional(),
|
|
57471
|
+
minTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
57409
57472
|
/** Highest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
57410
|
-
maxTemp: number().nullable().optional(),
|
|
57473
|
+
maxTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
57411
57474
|
/** Setpoint granularity, Celsius (0.5, 1). Absent / null = not reported. */
|
|
57412
|
-
tempStep: number().positive().nullable().optional(),
|
|
57475
|
+
tempStep: number().positive().nullable().optional().meta(readingMeta("temperature")),
|
|
57413
57476
|
/** Ms epoch when the slice was last updated (push or command). */
|
|
57414
57477
|
lastFetchedAt: number()
|
|
57415
57478
|
});
|
|
@@ -57551,17 +57614,17 @@ var climateControlCapability = {
|
|
|
57551
57614
|
* modes to expose in the picker without a slice fetch.
|
|
57552
57615
|
*/
|
|
57553
57616
|
var RgbTripletSchema = object({
|
|
57554
|
-
r: number().int().min(0).max(255),
|
|
57555
|
-
g: number().int().min(0).max(255),
|
|
57556
|
-
b: number().int().min(0).max(255)
|
|
57617
|
+
r: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
57618
|
+
g: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
57619
|
+
b: number().int().min(0).max(255).meta(readingMeta("none"))
|
|
57557
57620
|
});
|
|
57558
57621
|
var HsvTripletSchema = object({
|
|
57559
57622
|
/** Hue in degrees, 0..360. */
|
|
57560
|
-
h: number().min(0).max(360),
|
|
57623
|
+
h: number().min(0).max(360).meta(readingMeta("none")),
|
|
57561
57624
|
/** Saturation as 0..100 inclusive. */
|
|
57562
|
-
s: number().min(0).max(100),
|
|
57625
|
+
s: number().min(0).max(100).meta(readingMeta("none")),
|
|
57563
57626
|
/** Value/brightness as 0..100 inclusive. */
|
|
57564
|
-
v: number().min(0).max(100)
|
|
57627
|
+
v: number().min(0).max(100).meta(readingMeta("none"))
|
|
57565
57628
|
});
|
|
57566
57629
|
var ColorInputSchema = discriminatedUnion("mode", [
|
|
57567
57630
|
object({
|
|
@@ -57590,7 +57653,7 @@ var ColorStatusSchema = object({
|
|
|
57590
57653
|
/** Populated when `mode === 'hsv'`. */
|
|
57591
57654
|
hsv: HsvTripletSchema.optional(),
|
|
57592
57655
|
/** Populated when `mode === 'mired'`. */
|
|
57593
|
-
mireds: number().int().optional(),
|
|
57656
|
+
mireds: number().int().optional().meta(readingMeta("colour-temperature")),
|
|
57594
57657
|
/** Ms epoch of the last operator-driven change. */
|
|
57595
57658
|
lastChangedAt: number()
|
|
57596
57659
|
});
|
|
@@ -57793,18 +57856,12 @@ _enum([
|
|
|
57793
57856
|
"empty",
|
|
57794
57857
|
"full"
|
|
57795
57858
|
]);
|
|
57796
|
-
/**
|
|
57797
|
-
|
|
57798
|
-
|
|
57799
|
-
"days",
|
|
57800
|
-
"hours",
|
|
57801
|
-
"cycles"
|
|
57802
|
-
]);
|
|
57803
|
-
/** Remaining life as a COUNT, not a percentage (the PetKit desiccant reports
|
|
57804
|
-
* days). `value` null = unknown (D393). */
|
|
57859
|
+
/** Whether `remaining.value` is a duration in seconds or a dimensionless count. */
|
|
57860
|
+
var ConsumableRemainingKindSchema = _enum(["duration", "count"]);
|
|
57861
|
+
/** Remaining life. `value` null = unknown (D393). Duration is seconds. */
|
|
57805
57862
|
var ConsumableRemainingSchema = object({
|
|
57806
|
-
value: number().min(0).nullable(),
|
|
57807
|
-
|
|
57863
|
+
value: number().min(0).nullable().meta(readingMeta("device")),
|
|
57864
|
+
kind: ConsumableRemainingKindSchema
|
|
57808
57865
|
});
|
|
57809
57866
|
/** A single consumable item. Either a continuous `level` (remaining
|
|
57810
57867
|
* life %, or fill % for a `supply` / `waste` item) or a discrete `status`
|
|
@@ -57817,7 +57874,7 @@ var ConsumableItemSchema = object({
|
|
|
57817
57874
|
/** Display name. */
|
|
57818
57875
|
label: string().min(1),
|
|
57819
57876
|
/** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
|
|
57820
|
-
level: number().min(0).max(100).nullable(),
|
|
57877
|
+
level: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
57821
57878
|
/** The provider's discrete verdict when known (binary mode). */
|
|
57822
57879
|
status: ConsumableStatusSchema.nullable(),
|
|
57823
57880
|
/** What the item is — decides whether low or full is bad. Absent = `wear`. */
|
|
@@ -57899,8 +57956,8 @@ var consumablesCustomize = {
|
|
|
57899
57956
|
transforms: [{ kind: "identity" }]
|
|
57900
57957
|
}],
|
|
57901
57958
|
literals: [{
|
|
57902
|
-
path: "remaining.
|
|
57903
|
-
values: [...
|
|
57959
|
+
path: "remaining.kind",
|
|
57960
|
+
values: [...ConsumableRemainingKindSchema.options]
|
|
57904
57961
|
}]
|
|
57905
57962
|
},
|
|
57906
57963
|
{
|
|
@@ -58029,7 +58086,6 @@ reset: method(object({
|
|
|
58029
58086
|
},
|
|
58030
58087
|
"remaining.value": {
|
|
58031
58088
|
kind: "gauge",
|
|
58032
|
-
unitFrom: "remaining.unit",
|
|
58033
58089
|
deadband: 1,
|
|
58034
58090
|
displayName: "Remaining"
|
|
58035
58091
|
}
|
|
@@ -58099,10 +58155,9 @@ var contactCapability = {
|
|
|
58099
58155
|
* (empty array for the other kinds). It lives in the slice because
|
|
58100
58156
|
* HA `select.*` entities may update their options at runtime.
|
|
58101
58157
|
*
|
|
58102
|
-
*
|
|
58103
|
-
*
|
|
58104
|
-
*
|
|
58105
|
-
* push — consistent with `options` and the sensor-unit approach.
|
|
58158
|
+
* Numeric `min` / `max` / `step` live in the slice and share the device
|
|
58159
|
+
* quantity (`SourceInfo.quantity`, D944). Display precision is a read-time
|
|
58160
|
+
* preference. A datetime control's shape is `SourceInfo.dateTimeShape`.
|
|
58106
58161
|
*/
|
|
58107
58162
|
var ControlStatusSchema = object({
|
|
58108
58163
|
kind: _enum([
|
|
@@ -58114,39 +58169,17 @@ var ControlStatusSchema = object({
|
|
|
58114
58169
|
/** Current value. Numeric kind → number; select/text/datetime → string.
|
|
58115
58170
|
* Datetime values are ISO 8601 strings (full timestamp, date-only,
|
|
58116
58171
|
* or time-only — HA accepts all three forms). */
|
|
58117
|
-
value: union([number(), string()]),
|
|
58172
|
+
value: union([number().meta(readingMeta("device")), string()]),
|
|
58118
58173
|
/** Acceptable values when `kind === 'select'`. Empty for other kinds. */
|
|
58119
58174
|
options: array(string()),
|
|
58120
58175
|
/** Ms epoch when the slice was last updated. */
|
|
58121
58176
|
lastChangedAt: number(),
|
|
58122
|
-
/**
|
|
58123
|
-
|
|
58124
|
-
|
|
58125
|
-
|
|
58126
|
-
/**
|
|
58127
|
-
|
|
58128
|
-
min: number().optional(),
|
|
58129
|
-
/** Maximum allowed value. Populated live from HA `attributes.max`.
|
|
58130
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
58131
|
-
max: number().optional(),
|
|
58132
|
-
/** Step increment. Populated live from HA `attributes.step`.
|
|
58133
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
58134
|
-
step: number().optional(),
|
|
58135
|
-
/** Suggested decimal places for numeric display. Populated live from HA
|
|
58136
|
-
* `attributes.suggested_display_precision`, or derived from `step` when the
|
|
58137
|
-
* HA attribute is absent. Meaningful for `kind === 'numeric'`; absent for
|
|
58138
|
-
* other kinds. Falls back to auto-formatting when absent. */
|
|
58139
|
-
precision: number().int().min(0).max(10).optional(),
|
|
58140
|
-
/** Date-picker granularity for `kind === 'datetime'`. 'date' → date-only,
|
|
58141
|
-
* 'time' → time-only, 'datetime' → full timestamp. Absent for other kinds
|
|
58142
|
-
* (UI defaults to 'datetime'). Derived live from the device's HA domain
|
|
58143
|
-
* (date.* / time.* / datetime.*) or, for input_datetime, from the entity's
|
|
58144
|
-
* `has_date`/`has_time` attributes on each push. */
|
|
58145
|
-
format: _enum([
|
|
58146
|
-
"date",
|
|
58147
|
-
"time",
|
|
58148
|
-
"datetime"
|
|
58149
|
-
]).optional()
|
|
58177
|
+
/** Minimum allowed value, in the device quantity's base unit. */
|
|
58178
|
+
min: number().optional().meta(readingMeta("device")),
|
|
58179
|
+
/** Maximum allowed value, in the device quantity's base unit. */
|
|
58180
|
+
max: number().optional().meta(readingMeta("device")),
|
|
58181
|
+
/** Step increment, in the device quantity's base unit. */
|
|
58182
|
+
step: number().optional().meta(readingMeta("device"))
|
|
58150
58183
|
});
|
|
58151
58184
|
var ControlSetValueInputSchema = discriminatedUnion("kind", [
|
|
58152
58185
|
object({
|
|
@@ -58212,9 +58245,9 @@ var CoverStatusSchema = object({
|
|
|
58212
58245
|
]),
|
|
58213
58246
|
/** 0 = fully closed, 100 = fully open. Null when the device has
|
|
58214
58247
|
* no intermediate position surface. */
|
|
58215
|
-
position: number().min(0).max(100).nullable(),
|
|
58248
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58216
58249
|
/** 0 = closed slats, 100 = open slats. Null when no tilt support. */
|
|
58217
|
-
tiltPosition: number().min(0).max(100).nullable(),
|
|
58250
|
+
tiltPosition: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58218
58251
|
/** Ms epoch when the slice was last updated. */
|
|
58219
58252
|
lastChangedAt: number()
|
|
58220
58253
|
});
|
|
@@ -58317,9 +58350,9 @@ var NormalizedRangeSchema$1 = object({
|
|
|
58317
58350
|
var DayNightStatusSchema = object({
|
|
58318
58351
|
mode: DayNightModeSchema,
|
|
58319
58352
|
/** IR-cut trigger sensitivity, NORMALIZED 0–100 (higher = switches to night sooner). */
|
|
58320
|
-
sensitivity: number().optional(),
|
|
58353
|
+
sensitivity: number().optional().meta(readingMeta("none")),
|
|
58321
58354
|
/** Delay before the IR-cut filter flips, in seconds. */
|
|
58322
|
-
switchDelaySec: number().optional(),
|
|
58355
|
+
switchDelaySec: number().optional().meta(readingMeta("duration")),
|
|
58323
58356
|
lastFetchedAt: number()
|
|
58324
58357
|
});
|
|
58325
58358
|
/**
|
|
@@ -58537,11 +58570,11 @@ var DishwasherStatusSchema = object({
|
|
|
58537
58570
|
/** Feature keys of the programs the appliance currently offers — drives the UI selector. */
|
|
58538
58571
|
availablePrograms: array(string()),
|
|
58539
58572
|
/** Seconds remaining on the active cycle, or null when not running / not known. */
|
|
58540
|
-
remainingSeconds: number().int().nonnegative().nullable(),
|
|
58573
|
+
remainingSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
58541
58574
|
/** Seconds the delayed start is set to (time until the cycle starts), or null. */
|
|
58542
|
-
delayedStartSeconds: number().int().nonnegative().nullable(),
|
|
58575
|
+
delayedStartSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
58543
58576
|
/** Cycle completion 0..100, or null when not applicable. */
|
|
58544
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
58577
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58545
58578
|
/** True when the door is reported open; null when the door state is not known. */
|
|
58546
58579
|
doorOpen: boolean().nullable(),
|
|
58547
58580
|
/** True when the door is latched (locked) during a cycle; null when not reported. */
|
|
@@ -58565,7 +58598,7 @@ var DishwasherStatusSchema = object({
|
|
|
58565
58598
|
/** True while the machine-care (descaling / cleaning-program) reminder is raised; false when clear; null when not reported. */
|
|
58566
58599
|
machineCareDue: boolean().nullable(),
|
|
58567
58600
|
/** Program runs left before the machine-care reminder is due; null when the appliance does not say. */
|
|
58568
|
-
machineCareRemainingRuns: number().int().nonnegative().nullable(),
|
|
58601
|
+
machineCareRemainingRuns: number().int().nonnegative().nullable().meta(readingMeta("count")),
|
|
58569
58602
|
/** Option states: null when the appliance does not expose the option or has not said. */
|
|
58570
58603
|
halfLoad: boolean().nullable(),
|
|
58571
58604
|
hygienePlus: boolean().nullable(),
|
|
@@ -58580,7 +58613,7 @@ var DishwasherStatusSchema = object({
|
|
|
58580
58613
|
/** Feature keys of the events currently raised (salt low, rinse aid low, program finished, …). */
|
|
58581
58614
|
activeEvents: array(string()),
|
|
58582
58615
|
/** Numeric error code when the appliance reports one; null otherwise. */
|
|
58583
|
-
errorCode: number().nullable(),
|
|
58616
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
58584
58617
|
/** Name of the raised alert-level event while the appliance is in error; null otherwise. */
|
|
58585
58618
|
errorLabel: string().nullable(),
|
|
58586
58619
|
/** Ms epoch of the last value received from the appliance; 0 = never. */
|
|
@@ -58792,6 +58825,7 @@ var doorbellCustomize = {
|
|
|
58792
58825
|
applyAuthority: { kind: "composition-claim" },
|
|
58793
58826
|
eventName: "onPressed",
|
|
58794
58827
|
edges: ["rising"],
|
|
58828
|
+
defaultEdge: "rising",
|
|
58795
58829
|
timestampPath: "lastPressedAt",
|
|
58796
58830
|
counterPath: "pressCountSinceStart",
|
|
58797
58831
|
highWater: "composer-advance",
|
|
@@ -58810,7 +58844,7 @@ var DoorbellStatusSchema = object({
|
|
|
58810
58844
|
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
58811
58845
|
lastPressedAt: number().nullable(),
|
|
58812
58846
|
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
58813
|
-
pressCountSinceStart: number()
|
|
58847
|
+
pressCountSinceStart: number().meta(readingMeta("count"))
|
|
58814
58848
|
});
|
|
58815
58849
|
var DoorbellPressEventSchema = object({
|
|
58816
58850
|
deviceId: number(),
|
|
@@ -58875,17 +58909,7 @@ onPressed: {
|
|
|
58875
58909
|
history: "none",
|
|
58876
58910
|
customize: doorbellCustomize
|
|
58877
58911
|
};
|
|
58878
|
-
|
|
58879
|
-
* Enum-state sensor — a string value picked from a finite option set.
|
|
58880
|
-
* Drives HA `sensor` entries with `state_class: enum` (HVAC action
|
|
58881
|
-
* states, weather conditions, contact-source channels, mode strings).
|
|
58882
|
-
* The option set is stable across observations; it is persisted in the
|
|
58883
|
-
* device config blob (via the control slice at adoption) and is NOT
|
|
58884
|
-
* stored in `sourceInfo`.
|
|
58885
|
-
*/
|
|
58886
|
-
/** Locale-render shape for an ISO `value` carried by a `DateTimeSensor`-role
|
|
58887
|
-
* enum sensor: `date` (date-only), `time` (time-only), `datetime` (both). */
|
|
58888
|
-
var EnumSensorDateTimeFormatSchema = _enum([
|
|
58912
|
+
_enum([
|
|
58889
58913
|
"date",
|
|
58890
58914
|
"time",
|
|
58891
58915
|
"datetime"
|
|
@@ -58893,12 +58917,11 @@ var EnumSensorDateTimeFormatSchema = _enum([
|
|
|
58893
58917
|
var EnumSensorStatusSchema = object({
|
|
58894
58918
|
value: string(),
|
|
58895
58919
|
/**
|
|
58896
|
-
* Set
|
|
58897
|
-
* as
|
|
58898
|
-
*
|
|
58899
|
-
* a time-only sensor → `'time'`.
|
|
58920
|
+
* Set when `value` is a timestamp rather than an enum state, so history
|
|
58921
|
+
* does not learn ISO strings as states. The display shape (date / time /
|
|
58922
|
+
* datetime) lives on `SourceInfo.dateTimeShape`, written once at adopt.
|
|
58900
58923
|
*/
|
|
58901
|
-
|
|
58924
|
+
timestamp: boolean().optional(),
|
|
58902
58925
|
/** Ms epoch when the slice was last updated. */
|
|
58903
58926
|
lastFetchedAt: number()
|
|
58904
58927
|
});
|
|
@@ -58925,11 +58948,11 @@ var enumSensorCapability = {
|
|
|
58925
58948
|
* History (D850): the value as an `enum` series (an appliance's program or
|
|
58926
58949
|
* operation state, an HVAC action). The option set is per device, so the
|
|
58927
58950
|
* value list is LEARNED as values are first seen (bounded). A sensor with a
|
|
58928
|
-
* `
|
|
58951
|
+
* `timestamp` carries a clock, not a state, and is not recorded.
|
|
58929
58952
|
*/
|
|
58930
58953
|
history: { fields: { value: {
|
|
58931
58954
|
kind: "enum",
|
|
58932
|
-
skipWhenSet: "
|
|
58955
|
+
skipWhenSet: "timestamp"
|
|
58933
58956
|
} } },
|
|
58934
58957
|
/** Clock fields: written, but excluded from the compare that decides
|
|
58935
58958
|
* whether persisting is worth a SQLite commit. */
|
|
@@ -58949,13 +58972,13 @@ var EventFireSchema = object({
|
|
|
58949
58972
|
deviceId: number(),
|
|
58950
58973
|
eventType: string(),
|
|
58951
58974
|
data: record(string(), unknown()).nullable(),
|
|
58952
|
-
timestamp: number(),
|
|
58953
|
-
seq: number()
|
|
58975
|
+
timestamp: number().meta(readingMeta("none")),
|
|
58976
|
+
seq: number().meta(readingMeta("count"))
|
|
58954
58977
|
});
|
|
58955
58978
|
var EventEmitterStatusSchema = object({
|
|
58956
58979
|
eventTypes: array(string()),
|
|
58957
58980
|
lastEvent: EventFireSchema.nullable(),
|
|
58958
|
-
eventCountSinceStart: number()
|
|
58981
|
+
eventCountSinceStart: number().meta(readingMeta("count"))
|
|
58959
58982
|
});
|
|
58960
58983
|
var eventEmitterCapability = {
|
|
58961
58984
|
name: "event-emitter",
|
|
@@ -59368,10 +59391,10 @@ var FanDirectionSchema = _enum(["forward", "reverse"]);
|
|
|
59368
59391
|
var FanControlStatusSchema = object({
|
|
59369
59392
|
/** Active speed as 0..100 inclusive. Null when the device has no
|
|
59370
59393
|
* speed surface (single-speed fan). */
|
|
59371
|
-
percentage: number().min(0).max(100).nullable(),
|
|
59394
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59372
59395
|
/** Speed granularity the device accepts (HA `percentage_step`, e.g. 25 for
|
|
59373
59396
|
* a 4-speed fan). Absent when unknown — the UI then falls back to step 1. */
|
|
59374
|
-
percentageStep: number().positive().optional(),
|
|
59397
|
+
percentageStep: number().positive().optional().meta(readingMeta("percentage")),
|
|
59375
59398
|
/** Active preset mode (`auto` / `quiet` / `turbo` / vendor-specific)
|
|
59376
59399
|
* — empty string when no preset is active or supported. */
|
|
59377
59400
|
preset: string(),
|
|
@@ -59492,7 +59515,7 @@ var FeatureProbeStatusSchema = object({
|
|
|
59492
59515
|
/** Camera/firmware model string. `null` when the firmware doesn't expose it. */
|
|
59493
59516
|
model: string().nullable(),
|
|
59494
59517
|
/** Channel count for NVR/Hub devices; `1` for standalone cameras; `null` pre-probe. */
|
|
59495
|
-
channelCount: number().nullable(),
|
|
59518
|
+
channelCount: number().nullable().meta(readingMeta("count")),
|
|
59496
59519
|
/**
|
|
59497
59520
|
* Ms epoch of the last SUCCESSFUL probe. `0` before the first probe
|
|
59498
59521
|
* completes — drivers' `getAccessoryChildren()` should treat zero as
|
|
@@ -59617,7 +59640,7 @@ var gasCapability = {
|
|
|
59617
59640
|
};
|
|
59618
59641
|
var HeatingValveStatusSchema = object({
|
|
59619
59642
|
/** Radiator valve opening 0 (closed) .. 100 (open). Null = not yet known. */
|
|
59620
|
-
position: number().min(0).max(100).nullable(),
|
|
59643
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59621
59644
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
59622
59645
|
lastFetchedAt: number()
|
|
59623
59646
|
});
|
|
@@ -59660,9 +59683,9 @@ var HumidifierStatusSchema = object({
|
|
|
59660
59683
|
/** Whether the humidifier is currently on. */
|
|
59661
59684
|
on: boolean(),
|
|
59662
59685
|
/** Current measured relative humidity (0..100). Null when not reported. */
|
|
59663
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
59686
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
59664
59687
|
/** Target relative humidity (0..100). Null when no setpoint surface. */
|
|
59665
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
59688
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
59666
59689
|
/** Active mode (`auto` / `normal` / `baby` / vendor). Null when the
|
|
59667
59690
|
* device has no mode surface. */
|
|
59668
59691
|
mode: string().nullable(),
|
|
@@ -59672,9 +59695,9 @@ var HumidifierStatusSchema = object({
|
|
|
59672
59695
|
* `idle` / `off`). Null when the device doesn't report it. */
|
|
59673
59696
|
action: string().nullable(),
|
|
59674
59697
|
/** HA `min_humidity` attribute. Null → UI uses 0. */
|
|
59675
|
-
minHumidity: number().nullable(),
|
|
59698
|
+
minHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
59676
59699
|
/** HA `max_humidity` attribute. Null → UI uses 100. */
|
|
59677
|
-
maxHumidity: number().nullable(),
|
|
59700
|
+
maxHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
59678
59701
|
/** Ms epoch when the slice was last updated. */
|
|
59679
59702
|
lastChangedAt: number()
|
|
59680
59703
|
});
|
|
@@ -59744,22 +59767,13 @@ var humidifierCapability = {
|
|
|
59744
59767
|
* `sourceInfo`.
|
|
59745
59768
|
*/
|
|
59746
59769
|
var HumiditySensorStatusSchema = object({
|
|
59747
|
-
/** Current relative humidity, 0..100. */
|
|
59748
|
-
percent: number().min(0).max(100).meta({
|
|
59749
|
-
|
|
59770
|
+
/** Current relative humidity, 0..100. `null` when the sample was refused (D393). */
|
|
59771
|
+
percent: number().min(0).max(100).nullable().meta(readingMeta("humidity", {
|
|
59772
|
+
precision: 0,
|
|
59750
59773
|
label: "Humidity"
|
|
59751
|
-
}),
|
|
59774
|
+
})),
|
|
59752
59775
|
/** Ms epoch when the slice was last updated. */
|
|
59753
|
-
lastFetchedAt: number()
|
|
59754
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
59755
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
59756
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
59757
|
-
unit: string().optional(),
|
|
59758
|
-
/** Suggested decimal places for numeric display.
|
|
59759
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
59760
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
59761
|
-
* auto-formatting when absent. */
|
|
59762
|
-
precision: number().int().min(0).max(10).optional()
|
|
59776
|
+
lastFetchedAt: number()
|
|
59763
59777
|
});
|
|
59764
59778
|
var humiditySensorCapability = {
|
|
59765
59779
|
name: "humidity-sensor",
|
|
@@ -59790,12 +59804,7 @@ var humiditySensorCapability = {
|
|
|
59790
59804
|
} } },
|
|
59791
59805
|
/** Clock fields: written, but excluded from the compare that decides
|
|
59792
59806
|
* whether persisting is worth a SQLite commit. */
|
|
59793
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
59794
|
-
customize: {
|
|
59795
|
-
version: 1,
|
|
59796
|
-
advanced: "derive",
|
|
59797
|
-
targets: []
|
|
59798
|
-
}
|
|
59807
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
59799
59808
|
};
|
|
59800
59809
|
/**
|
|
59801
59810
|
* Image display cap. Models a single still image exposed by an integration —
|
|
@@ -59816,7 +59825,7 @@ var ImageStatusSchema = object({
|
|
|
59816
59825
|
* entity exposes no `entity_picture` (yet). */
|
|
59817
59826
|
url: string().nullable(),
|
|
59818
59827
|
/** Ms epoch of the upstream last-updated timestamp. Null at cold-start. */
|
|
59819
|
-
lastUpdated: number().nullable()
|
|
59828
|
+
lastUpdated: number().nullable().meta(readingMeta("none"))
|
|
59820
59829
|
});
|
|
59821
59830
|
var imageCapability = {
|
|
59822
59831
|
name: "image",
|
|
@@ -59904,19 +59913,19 @@ var NormalizedRangeSchema = object({
|
|
|
59904
59913
|
*/
|
|
59905
59914
|
var ImageSettingsStatusSchema = object({
|
|
59906
59915
|
/** Normalized 0–100. */
|
|
59907
|
-
brightness: number().optional(),
|
|
59916
|
+
brightness: number().optional().meta(readingMeta("none")),
|
|
59908
59917
|
/** Normalized 0–100. */
|
|
59909
|
-
contrast: number().optional(),
|
|
59918
|
+
contrast: number().optional().meta(readingMeta("none")),
|
|
59910
59919
|
/** Normalized 0–100. */
|
|
59911
|
-
saturation: number().optional(),
|
|
59920
|
+
saturation: number().optional().meta(readingMeta("none")),
|
|
59912
59921
|
/** Normalized 0–100. */
|
|
59913
|
-
sharpness: number().optional(),
|
|
59922
|
+
sharpness: number().optional().meta(readingMeta("none")),
|
|
59914
59923
|
mirror: boolean().optional(),
|
|
59915
59924
|
flip: boolean().optional(),
|
|
59916
59925
|
rotate: ImageRotateSchema.optional(),
|
|
59917
59926
|
whiteBalance: WhiteBalanceModeSchema.optional(),
|
|
59918
59927
|
/** Manual white-balance warmth, NORMALIZED 0–100. Meaningful only when `whiteBalance === 'manual'`. */
|
|
59919
|
-
warmth: number().optional(),
|
|
59928
|
+
warmth: number().optional().meta(readingMeta("none")),
|
|
59920
59929
|
exposureMode: ExposureModeSchema.optional(),
|
|
59921
59930
|
backlightMode: BacklightModeSchema.optional(),
|
|
59922
59931
|
lastFetchedAt: number()
|
|
@@ -60195,10 +60204,10 @@ var IntercomAbilitySchema = object({
|
|
|
60195
60204
|
/** Codecs accepted by firmware, in preference order. Driver-authored strings. */
|
|
60196
60205
|
codecs: array(string()),
|
|
60197
60206
|
/** Sample rate (Hz) the firmware expects. Reolink typical: 16000. */
|
|
60198
|
-
sampleRate: number(),
|
|
60207
|
+
sampleRate: number().meta(readingMeta("none")),
|
|
60199
60208
|
duplex: _enum(["half", "full"]),
|
|
60200
60209
|
/** Max in-flight audio backlog before drop (ms). Server uses this to bound latency. */
|
|
60201
|
-
maxBacklogMs: number()
|
|
60210
|
+
maxBacklogMs: number().meta(readingMeta("duration-ms"))
|
|
60202
60211
|
});
|
|
60203
60212
|
var IntercomStatusSchema = object({
|
|
60204
60213
|
/** True while a talk session is open. */
|
|
@@ -60425,13 +60434,13 @@ var LawnMowerControlStatusSchema = object({
|
|
|
60425
60434
|
activity: LawnMowerActivitySchema,
|
|
60426
60435
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
60427
60436
|
* reading. */
|
|
60428
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
60437
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
60429
60438
|
/** 0..100 mowing-completion percentage of the current task, or null when no
|
|
60430
60439
|
* task is active / progress is unavailable. */
|
|
60431
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
60440
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
60432
60441
|
/** Current device/event code (dynamic — mostly status, sometimes an error),
|
|
60433
60442
|
* or null when unknown. */
|
|
60434
|
-
currentCode: number().nullable(),
|
|
60443
|
+
currentCode: number().nullable().meta(readingMeta("none")),
|
|
60435
60444
|
/** Human label for {@link currentCode}, or null when undecodable. */
|
|
60436
60445
|
currentCodeLabel: string().nullable(),
|
|
60437
60446
|
/** Severity of {@link currentCode}. `error` (and often `warning`) warrants UI
|
|
@@ -60964,7 +60973,7 @@ var MediaPlayerStatusSchema = object({
|
|
|
60964
60973
|
state: MediaPlayerStateSchema,
|
|
60965
60974
|
/** Volume as 0..100 inclusive. Null when the device has no volume
|
|
60966
60975
|
* surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
|
|
60967
|
-
volumeLevel: number().min(0).max(100).nullable(),
|
|
60976
|
+
volumeLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
60968
60977
|
/** Mute toggle distinct from volume=0. Null when no mute surface.
|
|
60969
60978
|
* Pair with `DeviceFeature.MediaPlayerMute`. */
|
|
60970
60979
|
isMuted: boolean().nullable(),
|
|
@@ -60977,10 +60986,10 @@ var MediaPlayerStatusSchema = object({
|
|
|
60977
60986
|
currentMedia: MediaInfoSchema.nullable(),
|
|
60978
60987
|
/** Current playback position in ms. Null when not seekable or
|
|
60979
60988
|
* nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
|
|
60980
|
-
positionMs: number().int().nonnegative().nullable(),
|
|
60989
|
+
positionMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
60981
60990
|
/** Total duration of the current media in ms. Null when unknown
|
|
60982
60991
|
* (live stream) or nothing is playing. */
|
|
60983
|
-
durationMs: number().int().nonnegative().nullable(),
|
|
60992
|
+
durationMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
60984
60993
|
/** Shuffle toggle. Null when no shuffle surface.
|
|
60985
60994
|
* Pair with `DeviceFeature.MediaPlayerShuffle`. */
|
|
60986
60995
|
shuffle: boolean().nullable(),
|
|
@@ -61289,7 +61298,7 @@ var motionCustomize = {
|
|
|
61289
61298
|
eventName: "onMotionChanged"
|
|
61290
61299
|
},
|
|
61291
61300
|
deviceTypes: [DeviceType.Camera],
|
|
61292
|
-
apply: "
|
|
61301
|
+
apply: "add",
|
|
61293
61302
|
applyAuthority: {
|
|
61294
61303
|
kind: "camera-sensors",
|
|
61295
61304
|
timeoutField: "motionCooldownMs"
|
|
@@ -61361,7 +61370,7 @@ var MotionStatusSchema = object({
|
|
|
61361
61370
|
* it, every provider seeded it at boot, and every session left it
|
|
61362
61371
|
* `detected: true` after its detach.
|
|
61363
61372
|
*/
|
|
61364
|
-
autoClearAfterMs: number().nullable()
|
|
61373
|
+
autoClearAfterMs: number().nullable().meta(readingMeta("duration-ms"))
|
|
61365
61374
|
});
|
|
61366
61375
|
/**
|
|
61367
61376
|
* Payload of `motion.onMotionChanged` event + the corresponding bus
|
|
@@ -61543,7 +61552,7 @@ var MotionZoneRegionSchema = object({
|
|
|
61543
61552
|
* the grid region(s). */
|
|
61544
61553
|
var MotionZoneStatusSchema = object({
|
|
61545
61554
|
enabled: boolean(),
|
|
61546
|
-
sensitivity: number(),
|
|
61555
|
+
sensitivity: number().meta(readingMeta("none")),
|
|
61547
61556
|
/** Grid region(s). Today exactly one `grid` shape. */
|
|
61548
61557
|
regions: array(MotionZoneRegionSchema),
|
|
61549
61558
|
lastFetchedAt: number()
|
|
@@ -61913,7 +61922,7 @@ var NavigationStatusSchema = object({
|
|
|
61913
61922
|
following: boolean(),
|
|
61914
61923
|
flash: boolean(),
|
|
61915
61924
|
lightMode: NavigationLightModeSchema,
|
|
61916
|
-
lightLevel: number().min(40).max(100),
|
|
61925
|
+
lightLevel: number().min(40).max(100).meta(readingMeta("none")),
|
|
61917
61926
|
/** Ms epoch when the slice was last updated. */
|
|
61918
61927
|
lastChangedAt: number()
|
|
61919
61928
|
});
|
|
@@ -62047,13 +62056,13 @@ var NetworkLinkStatusSchema = object({
|
|
|
62047
62056
|
* one whose reading has not landed must not be drawn at 0 %. Consumers
|
|
62048
62057
|
* SKIP a null rather than coerce it.
|
|
62049
62058
|
*/
|
|
62050
|
-
signalPercent: number().min(0).max(100).nullable(),
|
|
62059
|
+
signalPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
62051
62060
|
/** Raw received signal strength in dBm, when the firmware reports one. */
|
|
62052
|
-
rssiDbm: number().optional(),
|
|
62061
|
+
rssiDbm: number().optional().meta(readingMeta("signal-level")),
|
|
62053
62062
|
/** Network name of a wireless link, when the firmware reports it. */
|
|
62054
62063
|
ssid: string().optional(),
|
|
62055
62064
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
62056
|
-
lastUpdated: number()
|
|
62065
|
+
lastUpdated: number().meta(readingMeta("none"))
|
|
62057
62066
|
});
|
|
62058
62067
|
var networkLinkCapability = {
|
|
62059
62068
|
name: "network-link",
|
|
@@ -62438,7 +62447,7 @@ var NotifierStatusSchema = object({
|
|
|
62438
62447
|
lastError: string().nullable(),
|
|
62439
62448
|
/** Number of deliveries currently buffered server-side (rate-limited
|
|
62440
62449
|
* notifiers may queue). 0 when the provider sends synchronously. */
|
|
62441
|
-
queueDepth: number().int().nonnegative(),
|
|
62450
|
+
queueDepth: number().int().nonnegative().meta(readingMeta("count")),
|
|
62442
62451
|
/** Per-feature capability matrix — authoritative source for the
|
|
62443
62452
|
* compose-form field gating. */
|
|
62444
62453
|
supports: NotifierSupportsSchema
|
|
@@ -62530,11 +62539,9 @@ onSent: { data: object({
|
|
|
62530
62539
|
* cap fits (HA `sensor` whose `device_class` we don't have a typed cap
|
|
62531
62540
|
* for: water flow, distance, weight, frequency, signal strength, …).
|
|
62532
62541
|
*
|
|
62533
|
-
* The
|
|
62534
|
-
*
|
|
62535
|
-
*
|
|
62536
|
-
* The UI reads them directly from the slice — they are the single source
|
|
62537
|
-
* of truth for generic numeric rendering and do NOT live on `sourceInfo`.
|
|
62542
|
+
* The quantity is not on this slice. It is chosen when the device is
|
|
62543
|
+
* adopted and stored once on `SourceInfo.quantity` (D944). `value` is in
|
|
62544
|
+
* that quantity's base unit. `null` is a refused sample (D393).
|
|
62538
62545
|
*
|
|
62539
62546
|
* Prefer the typed alternatives (`temperature-sensor`, `humidity-sensor`,
|
|
62540
62547
|
* `ambient-light-sensor`, `pressure-sensor`, `power-meter`,
|
|
@@ -62543,15 +62550,8 @@ onSent: { data: object({
|
|
|
62543
62550
|
* numeric values land here.
|
|
62544
62551
|
*/
|
|
62545
62552
|
var NumericSensorStatusSchema = object({
|
|
62546
|
-
|
|
62547
|
-
|
|
62548
|
-
* Populated live from the upstream source on each state push.
|
|
62549
|
-
* Absent for unitless sensors. */
|
|
62550
|
-
unit: string().optional(),
|
|
62551
|
-
/** Suggested decimal places for numeric display.
|
|
62552
|
-
* Populated live from the upstream source when provided.
|
|
62553
|
-
* Falls back to auto-formatting when absent. */
|
|
62554
|
-
precision: number().int().min(0).max(10).optional(),
|
|
62553
|
+
/** Reading in the device quantity's base unit. `null` when refused (D393). */
|
|
62554
|
+
value: number().nullable().meta(readingMeta("device")),
|
|
62555
62555
|
/** Ms epoch when the slice was last updated. */
|
|
62556
62556
|
lastFetchedAt: number()
|
|
62557
62557
|
});
|
|
@@ -62575,11 +62575,11 @@ var numericSensorCapability = {
|
|
|
62575
62575
|
*/
|
|
62576
62576
|
durability: "restored",
|
|
62577
62577
|
/**
|
|
62578
|
-
* History (D850): recorded series. The unit is
|
|
62578
|
+
* History (D850): recorded series. The unit is the device quantity's base,
|
|
62579
|
+
* resolved when the series is read — the cap has no single unit.
|
|
62579
62580
|
*/
|
|
62580
62581
|
history: { fields: { value: {
|
|
62581
62582
|
kind: "gauge",
|
|
62582
|
-
unitFrom: "unit",
|
|
62583
62583
|
minIntervalMs: 3e4
|
|
62584
62584
|
} } },
|
|
62585
62585
|
/** Clock fields: written, but excluded from the compare that decides
|
|
@@ -62871,23 +62871,26 @@ var PetFeederStatusSchema = object({
|
|
|
62871
62871
|
/** Food currently in the bowl (grams). Null when the device has not
|
|
62872
62872
|
* reported a reading yet. On dual-hopper models this is the combined
|
|
62873
62873
|
* bowl reading; per-hopper levels live in `food1`/`food2`. */
|
|
62874
|
-
foodLevel: number().nullable(),
|
|
62874
|
+
foodLevel: number().nullable().meta(readingMeta("none")),
|
|
62875
62875
|
/** Hopper-1 food level (grams) on dual-hopper feeders; null on
|
|
62876
62876
|
* single-hopper models. */
|
|
62877
|
-
food1: number().nullable(),
|
|
62877
|
+
food1: number().nullable().meta(readingMeta("none")),
|
|
62878
62878
|
/** Hopper-2 food level (grams) on dual-hopper feeders; null on
|
|
62879
62879
|
* single-hopper models. */
|
|
62880
|
-
food2: number().nullable(),
|
|
62880
|
+
food2: number().nullable().meta(readingMeta("none")),
|
|
62881
62881
|
/** Derived low-food flag — mirrors the HA `food_level` binary_sensor
|
|
62882
62882
|
* (`device_class: problem`, on = low). True when the bowl is empty /
|
|
62883
62883
|
* below the feeder's low threshold. */
|
|
62884
62884
|
lowFood: boolean(),
|
|
62885
62885
|
/** Battery charge 0..100 (%). Null on mains-powered models or when the
|
|
62886
62886
|
* device has no battery reading. */
|
|
62887
|
-
batteryPower: number().min(0).max(100).nullable(),
|
|
62888
|
-
/**
|
|
62889
|
-
*
|
|
62890
|
-
|
|
62887
|
+
batteryPower: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
62888
|
+
/**
|
|
62889
|
+
* Desiccant life remaining, stored in seconds (duration base, D944).
|
|
62890
|
+
* Providers convert from the days the feeder reports. Null when the
|
|
62891
|
+
* model has no desiccant sensor.
|
|
62892
|
+
*/
|
|
62893
|
+
desiccantLeftDays: number().nullable().meta(readingMeta("duration")),
|
|
62891
62894
|
/** True while a feed is in progress. */
|
|
62892
62895
|
feeding: boolean(),
|
|
62893
62896
|
/** Decoded connectivity / power status (HA petkit device-status enum).
|
|
@@ -62898,7 +62901,7 @@ var PetFeederStatusSchema = object({
|
|
|
62898
62901
|
* with `errorCode` for consumers that want the raw integer. */
|
|
62899
62902
|
error: string().nullable(),
|
|
62900
62903
|
/** Raw device error code (0 / null = no error). */
|
|
62901
|
-
errorCode: number().nullable(),
|
|
62904
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
62902
62905
|
/** True for D4S/D4SH dual-hopper hardware — gates the per-hopper UI. */
|
|
62903
62906
|
isDualHopper: boolean(),
|
|
62904
62907
|
/** Child-lock (manual-lock) setting — buttons on the unit are disabled. */
|
|
@@ -62908,7 +62911,7 @@ var PetFeederStatusSchema = object({
|
|
|
62908
62911
|
/** Play a chime when dispensing. */
|
|
62909
62912
|
feedSound: boolean(),
|
|
62910
62913
|
/** Speaker / prompt volume level (device-scaled integer). */
|
|
62911
|
-
volume: number(),
|
|
62914
|
+
volume: number().meta(readingMeta("none")),
|
|
62912
62915
|
/** Ms epoch when the slice was last refreshed from the cloud. */
|
|
62913
62916
|
lastFetchedAt: number()
|
|
62914
62917
|
});
|
|
@@ -63027,7 +63030,7 @@ var petFeederCapability = {
|
|
|
63027
63030
|
},
|
|
63028
63031
|
desiccantLeftDays: {
|
|
63029
63032
|
kind: "gauge",
|
|
63030
|
-
unit: "
|
|
63033
|
+
unit: "s"
|
|
63031
63034
|
}
|
|
63032
63035
|
} }
|
|
63033
63036
|
};
|
|
@@ -63428,36 +63431,19 @@ method(_void(), PlatformCapabilitiesSchema), method(_void(), HardwareInfoSchema)
|
|
|
63428
63431
|
*/
|
|
63429
63432
|
var PowerMeterStatusSchema = object({
|
|
63430
63433
|
/** Instantaneous power draw in watts. */
|
|
63431
|
-
watts: number().optional().meta({
|
|
63432
|
-
unit: "W",
|
|
63433
|
-
label: "Power"
|
|
63434
|
-
}),
|
|
63434
|
+
watts: number().optional().meta(readingMeta("power", { label: "Power" })),
|
|
63435
63435
|
/** Cumulative energy in kilowatt-hours since the meter was reset. */
|
|
63436
|
-
kwhTotal: number().optional().meta({
|
|
63437
|
-
unit: "kWh",
|
|
63438
|
-
label: "Energy"
|
|
63439
|
-
}),
|
|
63436
|
+
kwhTotal: number().optional().meta(readingMeta("energy", { label: "Energy" })),
|
|
63440
63437
|
/** Voltage in volts. */
|
|
63441
|
-
volts: number().optional(),
|
|
63438
|
+
volts: number().optional().meta(readingMeta("voltage")),
|
|
63442
63439
|
/** Current in amperes. */
|
|
63443
|
-
amps: number().optional(),
|
|
63444
|
-
/** Apparent power in volt-amperes
|
|
63445
|
-
va: number().optional(),
|
|
63440
|
+
amps: number().optional().meta(readingMeta("current")),
|
|
63441
|
+
/** Apparent power in volt-amperes. */
|
|
63442
|
+
va: number().optional().meta(readingMeta("apparent-power")),
|
|
63446
63443
|
/** Power factor (0..1) if reported. */
|
|
63447
|
-
powerFactor: number().min(0).max(1).optional(),
|
|
63444
|
+
powerFactor: number().min(0).max(1).optional().meta(readingMeta("ratio")),
|
|
63448
63445
|
/** Ms epoch when the slice was last updated. */
|
|
63449
|
-
lastFetchedAt: number()
|
|
63450
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
63451
|
-
* `attributes.unit_of_measurement` → 'V' / 'A' / 'W' / 'kW' / 'kWh').
|
|
63452
|
-
* Each upstream `sensor.*` entity surfaces ONE device_class, so one
|
|
63453
|
-
* unit per slice is unambiguous. The UI prefers this over the role's
|
|
63454
|
-
* canonical unit so a 'kW' / 'Wh' feed renders verbatim. */
|
|
63455
|
-
unit: string().optional(),
|
|
63456
|
-
/** Suggested decimal places for numeric display.
|
|
63457
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
63458
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
63459
|
-
* auto-formatting when absent. */
|
|
63460
|
-
precision: number().int().min(0).max(10).optional()
|
|
63446
|
+
lastFetchedAt: number()
|
|
63461
63447
|
});
|
|
63462
63448
|
var powerMeterCapability = {
|
|
63463
63449
|
name: "power-meter",
|
|
@@ -63521,12 +63507,7 @@ var powerMeterCapability = {
|
|
|
63521
63507
|
} },
|
|
63522
63508
|
/** Clock fields: written, but excluded from the compare that decides
|
|
63523
63509
|
* whether persisting is worth a SQLite commit. */
|
|
63524
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
63525
|
-
customize: {
|
|
63526
|
-
version: 1,
|
|
63527
|
-
advanced: "derive",
|
|
63528
|
-
targets: []
|
|
63529
|
-
}
|
|
63510
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
63530
63511
|
};
|
|
63531
63512
|
/**
|
|
63532
63513
|
* Presence cap. Models HA `person.*` and `device_tracker.*` entities
|
|
@@ -63546,11 +63527,11 @@ var powerMeterCapability = {
|
|
|
63546
63527
|
*/
|
|
63547
63528
|
var GpsLocationSchema = object({
|
|
63548
63529
|
/** Latitude in decimal degrees, -90..90. */
|
|
63549
|
-
latitude: number().min(-90).max(90),
|
|
63530
|
+
latitude: number().min(-90).max(90).meta(readingMeta("angle")),
|
|
63550
63531
|
/** Longitude in decimal degrees, -180..180. */
|
|
63551
|
-
longitude: number().min(-180).max(180),
|
|
63532
|
+
longitude: number().min(-180).max(180).meta(readingMeta("angle")),
|
|
63552
63533
|
/** Reported accuracy in meters (lower = better). */
|
|
63553
|
-
accuracyMeters: number().nonnegative()
|
|
63534
|
+
accuracyMeters: number().nonnegative().meta(readingMeta("length"))
|
|
63554
63535
|
});
|
|
63555
63536
|
var PresenceStatusSchema = object({
|
|
63556
63537
|
/** `home` / `not_home` / any user-defined zone name. */
|
|
@@ -63562,7 +63543,7 @@ var PresenceStatusSchema = object({
|
|
|
63562
63543
|
gps: GpsLocationSchema.nullable(),
|
|
63563
63544
|
/** Optional battery level of the tracking device (0..100). Null
|
|
63564
63545
|
* when not reported. */
|
|
63565
|
-
batteryPercent: number().min(0).max(100).nullable(),
|
|
63546
|
+
batteryPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
63566
63547
|
/** Ms epoch when the slice was last updated. */
|
|
63567
63548
|
lastChangedAt: number()
|
|
63568
63549
|
});
|
|
@@ -63612,19 +63593,10 @@ var presenceCapability = {
|
|
|
63612
63593
|
* `sourceInfo`.
|
|
63613
63594
|
*/
|
|
63614
63595
|
var PressureSensorStatusSchema = object({
|
|
63615
|
-
/** Current pressure in hPa. */
|
|
63616
|
-
hpa: number(),
|
|
63596
|
+
/** Current pressure in hPa. `null` when the sample was refused (D393). */
|
|
63597
|
+
hpa: number().nullable().meta(readingMeta("pressure", { precision: 0 })),
|
|
63617
63598
|
/** Ms epoch when the slice was last updated. */
|
|
63618
|
-
lastFetchedAt: number()
|
|
63619
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
63620
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
63621
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
63622
|
-
unit: string().optional(),
|
|
63623
|
-
/** Suggested decimal places for numeric display.
|
|
63624
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
63625
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
63626
|
-
* auto-formatting when absent. */
|
|
63627
|
-
precision: number().int().min(0).max(10).optional()
|
|
63599
|
+
lastFetchedAt: number()
|
|
63628
63600
|
});
|
|
63629
63601
|
var pressureSensorCapability = {
|
|
63630
63602
|
name: "pressure-sensor",
|
|
@@ -64038,8 +64010,8 @@ DeviceType.Camera, method(PtzMoveCommandSchema.extend({ deviceId: number() }), _
|
|
|
64038
64010
|
}), _void(), { kind: "mutation" });
|
|
64039
64011
|
var PtzAutotrackSettingsSchema = object({
|
|
64040
64012
|
targetType: string().describe("Vendor target string (people/vehicle/pet); empty = camera default"),
|
|
64041
|
-
stopDelaySeconds: number().int().min(0).max(300),
|
|
64042
|
-
disappearDelaySeconds: number().int().min(0).max(300)
|
|
64013
|
+
stopDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration")),
|
|
64014
|
+
disappearDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration"))
|
|
64043
64015
|
});
|
|
64044
64016
|
/**
|
|
64045
64017
|
* One option the camera advertises as a valid `targetType`. Drivers
|
|
@@ -64201,7 +64173,7 @@ var RunningStateStatusSchema = object({
|
|
|
64201
64173
|
/** null = unknown — never coerced to false (D393). */
|
|
64202
64174
|
running: boolean().nullable(),
|
|
64203
64175
|
/** Epoch ms the current boolean began; null while `running` is null. */
|
|
64204
|
-
since: number().nullable(),
|
|
64176
|
+
since: number().nullable().meta(readingMeta("none")),
|
|
64205
64177
|
source: RunningStateSourceSchema.meta({ label: "Source" }),
|
|
64206
64178
|
phase: string().nullable(),
|
|
64207
64179
|
/** null until a reading has been published (D393). */
|
|
@@ -64216,7 +64188,6 @@ var RUNNING_DEVICE_TYPES = Object.values(DeviceType);
|
|
|
64216
64188
|
/** Generic Customize target for the running boolean (D936). */
|
|
64217
64189
|
var runningCustomize = {
|
|
64218
64190
|
version: 1,
|
|
64219
|
-
advanced: "derive",
|
|
64220
64191
|
targets: [{
|
|
64221
64192
|
id: "running",
|
|
64222
64193
|
cardinality: "scalar",
|
|
@@ -64236,7 +64207,7 @@ var runningCustomize = {
|
|
|
64236
64207
|
DeviceType.Thermostat,
|
|
64237
64208
|
DeviceType.PetFeeder
|
|
64238
64209
|
],
|
|
64239
|
-
apply: "add
|
|
64210
|
+
apply: "add",
|
|
64240
64211
|
path: "running",
|
|
64241
64212
|
sources: [
|
|
64242
64213
|
{
|
|
@@ -64252,6 +64223,7 @@ var runningCustomize = {
|
|
|
64252
64223
|
requiredUnit: "W",
|
|
64253
64224
|
transforms: [{
|
|
64254
64225
|
kind: "threshold",
|
|
64226
|
+
comparisons: ["gte", "lte"],
|
|
64255
64227
|
comparison: "gte",
|
|
64256
64228
|
defaultThreshold: 5,
|
|
64257
64229
|
defaultStartDwellMs: RUNNING_POWER_START_DELAY_MS,
|
|
@@ -65499,9 +65471,9 @@ var RecordTriggerSchema = _enum([
|
|
|
65499
65471
|
*/
|
|
65500
65472
|
var RecordWindowSchema = object({
|
|
65501
65473
|
trigger: RecordTriggerSchema,
|
|
65502
|
-
day: number().int().min(0).max(6),
|
|
65503
|
-
startMinute: number().int().min(0).max(1439),
|
|
65504
|
-
endMinute: number().int().min(1).max(1440)
|
|
65474
|
+
day: number().int().min(0).max(6).meta(readingMeta("none")),
|
|
65475
|
+
startMinute: number().int().min(0).max(1439).meta(readingMeta("none")),
|
|
65476
|
+
endMinute: number().int().min(1).max(1440).meta(readingMeta("none"))
|
|
65505
65477
|
});
|
|
65506
65478
|
/** Status of one physical volume, as the camera itself describes it. */
|
|
65507
65479
|
var OnboardStorageVolumeSchema = object({
|
|
@@ -65577,10 +65549,10 @@ var RecordingOnboardStatusSchema = object({
|
|
|
65577
65549
|
/** Master "record to the card at all" switch. */
|
|
65578
65550
|
enabled: boolean().nullable(),
|
|
65579
65551
|
overwriteWhenFull: boolean().nullable(),
|
|
65580
|
-
preRecordSec: number().nullable(),
|
|
65581
|
-
postRecordSec: number().nullable(),
|
|
65552
|
+
preRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
65553
|
+
postRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
65582
65554
|
/** Length of one recorded file, in minutes. */
|
|
65583
|
-
segmentMinutes: number().nullable(),
|
|
65555
|
+
segmentMinutes: number().nullable().meta(readingMeta("none")),
|
|
65584
65556
|
/** The primary track's weekly windows, flattened. */
|
|
65585
65557
|
windows: array(RecordWindowSchema),
|
|
65586
65558
|
/**
|
|
@@ -65596,7 +65568,7 @@ var RecordingOnboardStatusSchema = object({
|
|
|
65596
65568
|
* provider reporting a non-zero count also reports the schedule as not
|
|
65597
65569
|
* writable.
|
|
65598
65570
|
*/
|
|
65599
|
-
unreadableWindows: number(),
|
|
65571
|
+
unreadableWindows: number().meta(readingMeta("count")),
|
|
65600
65572
|
/**
|
|
65601
65573
|
* The camera is scheduled to record and has NO usable storage.
|
|
65602
65574
|
*
|
|
@@ -66441,7 +66413,7 @@ var CamStreamDescriptorSchema = object({
|
|
|
66441
66413
|
url: string().optional(),
|
|
66442
66414
|
codec: string().optional(),
|
|
66443
66415
|
resolution: CamStreamResolutionSchema.optional(),
|
|
66444
|
-
fps: number().positive().optional(),
|
|
66416
|
+
fps: number().positive().optional().meta(readingMeta("rate")),
|
|
66445
66417
|
label: string().optional(),
|
|
66446
66418
|
/** Device-level features (e.g. `battery-operated`) — drives broker policy. */
|
|
66447
66419
|
deviceFeatures: array(string()).optional(),
|
|
@@ -66528,18 +66500,18 @@ var StreamProfileSchema = _enum([
|
|
|
66528
66500
|
]);
|
|
66529
66501
|
/** The current encoding config of one stream profile. */
|
|
66530
66502
|
var StreamProfileConfigSchema = object({
|
|
66531
|
-
width: number(),
|
|
66532
|
-
height: number(),
|
|
66503
|
+
width: number().meta(readingMeta("none")),
|
|
66504
|
+
height: number().meta(readingMeta("none")),
|
|
66533
66505
|
codec: _enum(["h264", "h265"]),
|
|
66534
|
-
framerate: number(),
|
|
66535
|
-
bitrate: number(),
|
|
66506
|
+
framerate: number().meta(readingMeta("rate")),
|
|
66507
|
+
bitrate: number().meta(readingMeta("bitrate")),
|
|
66536
66508
|
bitrateMode: _enum(["vbr", "cbr"]).optional(),
|
|
66537
66509
|
encoderProfile: _enum([
|
|
66538
66510
|
"high",
|
|
66539
66511
|
"main",
|
|
66540
66512
|
"baseline"
|
|
66541
66513
|
]).optional(),
|
|
66542
|
-
gop: number().optional(),
|
|
66514
|
+
gop: number().optional().meta(readingMeta("none")),
|
|
66543
66515
|
/**
|
|
66544
66516
|
* Whether THIS profile currently carries an audio track. READ-ONLY here.
|
|
66545
66517
|
*
|
|
@@ -66760,12 +66732,7 @@ var switchCapability = {
|
|
|
66760
66732
|
label: "On",
|
|
66761
66733
|
kind: "boolean"
|
|
66762
66734
|
}
|
|
66763
|
-
}] }
|
|
66764
|
-
customize: {
|
|
66765
|
-
version: 1,
|
|
66766
|
-
advanced: "derive",
|
|
66767
|
-
targets: []
|
|
66768
|
-
}
|
|
66735
|
+
}] }
|
|
66769
66736
|
};
|
|
66770
66737
|
/** C0 controls, DEL and the C1 range: none of them belongs in a name. */
|
|
66771
66738
|
function hasControlCharacter(value) {
|
|
@@ -67348,35 +67315,21 @@ var tamperCapability = {
|
|
|
67348
67315
|
* entries with `device_class: temperature` and any future native
|
|
67349
67316
|
* thermometer.
|
|
67350
67317
|
*
|
|
67351
|
-
*
|
|
67352
|
-
*
|
|
67353
|
-
* (climate-control's `currentTemp`, energy analytics) can compose
|
|
67354
|
-
* without per-source unit fixups. The canonical display unit (`°C`) is
|
|
67355
|
-
* a descriptor constant in the UI (ROLE_DESCRIPTOR), not stored in
|
|
67356
|
-
* `sourceInfo`.
|
|
67318
|
+
* The number is Celsius (D944). Providers convert on ingest. A failed
|
|
67319
|
+
* conversion is `null`, never a guess. Display unit is a read-time preference.
|
|
67357
67320
|
*
|
|
67358
67321
|
* Status `lastFetchedAt` lets staleness-aware consumers detect a
|
|
67359
67322
|
* frozen feed (provider hung) distinct from a "temperature hasn't
|
|
67360
67323
|
* changed" steady state.
|
|
67361
67324
|
*/
|
|
67362
67325
|
var TemperatureSensorStatusSchema = object({
|
|
67363
|
-
/** Current temperature in Celsius. */
|
|
67364
|
-
celsius: number().meta({
|
|
67365
|
-
|
|
67326
|
+
/** Current temperature in Celsius. `null` when the sample was refused (D393). */
|
|
67327
|
+
celsius: number().nullable().meta(readingMeta("temperature", {
|
|
67328
|
+
precision: 1,
|
|
67366
67329
|
label: "Temperature"
|
|
67367
|
-
}),
|
|
67330
|
+
})),
|
|
67368
67331
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
67369
|
-
lastFetchedAt: number()
|
|
67370
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
67371
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
67372
|
-
* role's canonical unit, so a Fahrenheit feed renders '°F' not '°C'.
|
|
67373
|
-
* Absent → the UI falls back to the role's canonical unit. */
|
|
67374
|
-
unit: string().optional(),
|
|
67375
|
-
/** Suggested decimal places for numeric display.
|
|
67376
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
67377
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
67378
|
-
* auto-formatting when absent. */
|
|
67379
|
-
precision: number().int().min(0).max(10).optional()
|
|
67332
|
+
lastFetchedAt: number()
|
|
67380
67333
|
});
|
|
67381
67334
|
var temperatureSensorCapability = {
|
|
67382
67335
|
name: "temperature-sensor",
|
|
@@ -67407,12 +67360,7 @@ var temperatureSensorCapability = {
|
|
|
67407
67360
|
} } },
|
|
67408
67361
|
/** Clock fields: written, but excluded from the compare that decides
|
|
67409
67362
|
* whether persisting is worth a SQLite commit. */
|
|
67410
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
67411
|
-
customize: {
|
|
67412
|
-
version: 1,
|
|
67413
|
-
advanced: "derive",
|
|
67414
|
-
targets: []
|
|
67415
|
-
}
|
|
67363
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
67416
67364
|
};
|
|
67417
67365
|
/**
|
|
67418
67366
|
* toast — system-scoped singleton capability that streams toast
|
|
@@ -67695,16 +67643,16 @@ var VacuumControlStatusSchema = object({
|
|
|
67695
67643
|
]),
|
|
67696
67644
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
67697
67645
|
* reading. */
|
|
67698
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
67646
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
67699
67647
|
/** Current fan-speed token (provider-verbatim). Null when unknown or
|
|
67700
67648
|
* the vacuum has no speed control. */
|
|
67701
67649
|
fanSpeed: string().nullable(),
|
|
67702
67650
|
/** Speed tokens the hardware accepts — drives the UI selector. */
|
|
67703
67651
|
availableFanSpeeds: array(string()),
|
|
67704
67652
|
/** 0..100 cleaning-completion percentage of the current task, or null. */
|
|
67705
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
67653
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
67706
67654
|
/** Current error code (0 / null = no error). */
|
|
67707
|
-
errorCode: number().nullable(),
|
|
67655
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
67708
67656
|
/** Human label for {@link errorCode}, or null when none / undecodable. */
|
|
67709
67657
|
errorLabel: string().nullable(),
|
|
67710
67658
|
/** Ms epoch when the slice was last updated. */
|
|
@@ -67782,7 +67730,7 @@ var ValveStatusSchema = object({
|
|
|
67782
67730
|
]),
|
|
67783
67731
|
/** 0 = fully closed, 100 = fully open. Null when the device has no
|
|
67784
67732
|
* intermediate position surface. */
|
|
67785
|
-
position: number().min(0).max(100).nullable(),
|
|
67733
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
67786
67734
|
/** Ms epoch when the slice was last updated. */
|
|
67787
67735
|
lastChangedAt: number()
|
|
67788
67736
|
});
|
|
@@ -67890,9 +67838,9 @@ var vibrationCapability = {
|
|
|
67890
67838
|
*/
|
|
67891
67839
|
var WaterHeaterStatusSchema = object({
|
|
67892
67840
|
/** Current measured temperature. Null when not reported. */
|
|
67893
|
-
currentTemp: number().nullable(),
|
|
67841
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
67894
67842
|
/** Target temperature setpoint. Null when no setpoint surface. */
|
|
67895
|
-
targetTemp: number().nullable(),
|
|
67843
|
+
targetTemp: number().nullable().meta(readingMeta("temperature")),
|
|
67896
67844
|
/** Active operation mode = HA `state` (`eco` / `electric` / `gas` /
|
|
67897
67845
|
* `heat_pump` / `high_demand` / `performance` / `off`). Null when the
|
|
67898
67846
|
* device reports an unknown state. */
|
|
@@ -67903,9 +67851,9 @@ var WaterHeaterStatusSchema = object({
|
|
|
67903
67851
|
* has no away surface. */
|
|
67904
67852
|
away: boolean().nullable(),
|
|
67905
67853
|
/** HA `min_temp` attribute. Null when not reported. */
|
|
67906
|
-
minTemp: number().nullable(),
|
|
67854
|
+
minTemp: number().nullable().meta(readingMeta("temperature")),
|
|
67907
67855
|
/** HA `max_temp` attribute. Null when not reported. */
|
|
67908
|
-
maxTemp: number().nullable(),
|
|
67856
|
+
maxTemp: number().nullable().meta(readingMeta("temperature")),
|
|
67909
67857
|
/** Ms epoch when the slice was last updated. */
|
|
67910
67858
|
lastChangedAt: number()
|
|
67911
67859
|
});
|
|
@@ -67990,25 +67938,18 @@ var waterHeaterCapability = {
|
|
|
67990
67938
|
* Forecast deferred — current conditions only for v1.
|
|
67991
67939
|
*/
|
|
67992
67940
|
var WeatherStatusSchema = object({
|
|
67993
|
-
/** Verbatim
|
|
67994
|
-
* when no condition has been reported yet. */
|
|
67941
|
+
/** Verbatim condition state (`sunny`, `cloudy`, `rainy`, …). Null when none yet. */
|
|
67995
67942
|
condition: string().nullable(),
|
|
67996
|
-
/** Current temperature in
|
|
67997
|
-
temperature: number().nullable(),
|
|
67998
|
-
/** Temperature unit string (e.g. `°C` / `°F`). Null when not provided. */
|
|
67999
|
-
temperatureUnit: string().nullable(),
|
|
67943
|
+
/** Current temperature in Celsius. Null when not provided or refused. */
|
|
67944
|
+
temperature: number().nullable().meta(readingMeta("temperature", { precision: 1 })),
|
|
68000
67945
|
/** Relative humidity (0..100). Null when not provided. */
|
|
68001
|
-
humidity: number().min(0).max(100).nullable(),
|
|
68002
|
-
/** Barometric pressure in
|
|
68003
|
-
pressure: number().nullable(),
|
|
68004
|
-
/**
|
|
68005
|
-
|
|
68006
|
-
/** Wind speed in the reported unit. Null when not provided. */
|
|
68007
|
-
windSpeed: number().nullable(),
|
|
68008
|
-
/** Wind-speed unit string (e.g. `km/h` / `mph`). Null when not provided. */
|
|
68009
|
-
windSpeedUnit: string().nullable(),
|
|
67946
|
+
humidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
67947
|
+
/** Barometric pressure in hPa. Null when not provided or refused. */
|
|
67948
|
+
pressure: number().nullable().meta(readingMeta("pressure")),
|
|
67949
|
+
/** Wind speed in metres per second. Null when not provided or refused. */
|
|
67950
|
+
windSpeed: number().nullable().meta(readingMeta("speed")),
|
|
68010
67951
|
/** Wind bearing in degrees (0..360, meteorological). Null when not provided. */
|
|
68011
|
-
windBearing: number().nullable(),
|
|
67952
|
+
windBearing: number().nullable().meta(readingMeta("angle")),
|
|
68012
67953
|
/** Ms epoch when the slice was last updated. */
|
|
68013
67954
|
lastFetchedAt: number()
|
|
68014
67955
|
});
|
|
@@ -68036,12 +67977,12 @@ var weatherCapability = {
|
|
|
68036
67977
|
*/
|
|
68037
67978
|
durability: "session",
|
|
68038
67979
|
/**
|
|
68039
|
-
* History (D850): recorded series.
|
|
67980
|
+
* History (D850): recorded series. Numbers are the quantity base (D944).
|
|
68040
67981
|
*/
|
|
68041
67982
|
history: { fields: {
|
|
68042
67983
|
temperature: {
|
|
68043
67984
|
kind: "gauge",
|
|
68044
|
-
|
|
67985
|
+
unit: "°C",
|
|
68045
67986
|
deadband: .2
|
|
68046
67987
|
},
|
|
68047
67988
|
humidity: {
|
|
@@ -68051,12 +67992,12 @@ var weatherCapability = {
|
|
|
68051
67992
|
},
|
|
68052
67993
|
pressure: {
|
|
68053
67994
|
kind: "gauge",
|
|
68054
|
-
|
|
67995
|
+
unit: "hPa",
|
|
68055
67996
|
deadband: .5
|
|
68056
67997
|
},
|
|
68057
67998
|
windSpeed: {
|
|
68058
67999
|
kind: "gauge",
|
|
68059
|
-
|
|
68000
|
+
unit: "m/s",
|
|
68060
68001
|
deadband: .5
|
|
68061
68002
|
}
|
|
68062
68003
|
} }
|
|
@@ -68988,6 +68929,389 @@ function runningFromDishwasherOperation(operation, program, previous, fetchedAt,
|
|
|
68988
68929
|
if (operation === "Pause") return nativeSlice(false, "Pause", previous, transitionAtMs, fetchedAt, null);
|
|
68989
68930
|
return nativeSlice(false, operation, previous, transitionAtMs, fetchedAt, null);
|
|
68990
68931
|
}
|
|
68932
|
+
/**
|
|
68933
|
+
* Frozen unit → spec table. `•` in the doc marks each dimension's canonical
|
|
68934
|
+
* unit (`factor: 1, offset: 0`). °F derives from `°C = (°F − 32) × 5/9` ⇒
|
|
68935
|
+
* `factor = 5/9`, `offset = -160/9` (kept as exact expressions, not rounded
|
|
68936
|
+
* decimals). K derives from `°C = K − 273.15`.
|
|
68937
|
+
*/
|
|
68938
|
+
var UNIT_TABLE = {
|
|
68939
|
+
"°C": {
|
|
68940
|
+
dimension: "temperature",
|
|
68941
|
+
factor: 1,
|
|
68942
|
+
offset: 0
|
|
68943
|
+
},
|
|
68944
|
+
"°F": {
|
|
68945
|
+
dimension: "temperature",
|
|
68946
|
+
factor: 5 / 9,
|
|
68947
|
+
offset: -160 / 9
|
|
68948
|
+
},
|
|
68949
|
+
K: {
|
|
68950
|
+
dimension: "temperature",
|
|
68951
|
+
factor: 1,
|
|
68952
|
+
offset: -273.15
|
|
68953
|
+
},
|
|
68954
|
+
hPa: {
|
|
68955
|
+
dimension: "pressure",
|
|
68956
|
+
factor: 1,
|
|
68957
|
+
offset: 0
|
|
68958
|
+
},
|
|
68959
|
+
kPa: {
|
|
68960
|
+
dimension: "pressure",
|
|
68961
|
+
factor: 10,
|
|
68962
|
+
offset: 0
|
|
68963
|
+
},
|
|
68964
|
+
Pa: {
|
|
68965
|
+
dimension: "pressure",
|
|
68966
|
+
factor: .01,
|
|
68967
|
+
offset: 0
|
|
68968
|
+
},
|
|
68969
|
+
mbar: {
|
|
68970
|
+
dimension: "pressure",
|
|
68971
|
+
factor: 1,
|
|
68972
|
+
offset: 0
|
|
68973
|
+
},
|
|
68974
|
+
bar: {
|
|
68975
|
+
dimension: "pressure",
|
|
68976
|
+
factor: 1e3,
|
|
68977
|
+
offset: 0
|
|
68978
|
+
},
|
|
68979
|
+
inHg: {
|
|
68980
|
+
dimension: "pressure",
|
|
68981
|
+
factor: 33.8639,
|
|
68982
|
+
offset: 0
|
|
68983
|
+
},
|
|
68984
|
+
mmHg: {
|
|
68985
|
+
dimension: "pressure",
|
|
68986
|
+
factor: 1.33322,
|
|
68987
|
+
offset: 0
|
|
68988
|
+
},
|
|
68989
|
+
psi: {
|
|
68990
|
+
dimension: "pressure",
|
|
68991
|
+
factor: 68.9476,
|
|
68992
|
+
offset: 0
|
|
68993
|
+
},
|
|
68994
|
+
"m/s": {
|
|
68995
|
+
dimension: "speed",
|
|
68996
|
+
factor: 1,
|
|
68997
|
+
offset: 0
|
|
68998
|
+
},
|
|
68999
|
+
"km/h": {
|
|
69000
|
+
dimension: "speed",
|
|
69001
|
+
factor: 1 / 3.6,
|
|
69002
|
+
offset: 0
|
|
69003
|
+
},
|
|
69004
|
+
mph: {
|
|
69005
|
+
dimension: "speed",
|
|
69006
|
+
factor: .44704,
|
|
69007
|
+
offset: 0
|
|
69008
|
+
},
|
|
69009
|
+
kn: {
|
|
69010
|
+
dimension: "speed",
|
|
69011
|
+
factor: .514444,
|
|
69012
|
+
offset: 0
|
|
69013
|
+
},
|
|
69014
|
+
"mm/h": {
|
|
69015
|
+
dimension: "precipitation-rate",
|
|
69016
|
+
factor: 1,
|
|
69017
|
+
offset: 0
|
|
69018
|
+
},
|
|
69019
|
+
"in/h": {
|
|
69020
|
+
dimension: "precipitation-rate",
|
|
69021
|
+
factor: 25.4,
|
|
69022
|
+
offset: 0
|
|
69023
|
+
},
|
|
69024
|
+
m: {
|
|
69025
|
+
dimension: "length",
|
|
69026
|
+
factor: 1,
|
|
69027
|
+
offset: 0
|
|
69028
|
+
},
|
|
69029
|
+
mm: {
|
|
69030
|
+
dimension: "length",
|
|
69031
|
+
factor: .001,
|
|
69032
|
+
offset: 0
|
|
69033
|
+
},
|
|
69034
|
+
cm: {
|
|
69035
|
+
dimension: "length",
|
|
69036
|
+
factor: .01,
|
|
69037
|
+
offset: 0
|
|
69038
|
+
},
|
|
69039
|
+
km: {
|
|
69040
|
+
dimension: "length",
|
|
69041
|
+
factor: 1e3,
|
|
69042
|
+
offset: 0
|
|
69043
|
+
},
|
|
69044
|
+
in: {
|
|
69045
|
+
dimension: "length",
|
|
69046
|
+
factor: .0254,
|
|
69047
|
+
offset: 0
|
|
69048
|
+
},
|
|
69049
|
+
ft: {
|
|
69050
|
+
dimension: "length",
|
|
69051
|
+
factor: .3048,
|
|
69052
|
+
offset: 0
|
|
69053
|
+
},
|
|
69054
|
+
mi: {
|
|
69055
|
+
dimension: "length",
|
|
69056
|
+
factor: 1609.344,
|
|
69057
|
+
offset: 0
|
|
69058
|
+
},
|
|
69059
|
+
"m²": {
|
|
69060
|
+
dimension: "area",
|
|
69061
|
+
factor: 1,
|
|
69062
|
+
offset: 0
|
|
69063
|
+
},
|
|
69064
|
+
lx: {
|
|
69065
|
+
dimension: "illuminance",
|
|
69066
|
+
factor: 1,
|
|
69067
|
+
offset: 0
|
|
69068
|
+
},
|
|
69069
|
+
"W/m²": {
|
|
69070
|
+
dimension: "irradiance",
|
|
69071
|
+
factor: 1,
|
|
69072
|
+
offset: 0
|
|
69073
|
+
},
|
|
69074
|
+
W: {
|
|
69075
|
+
dimension: "power",
|
|
69076
|
+
factor: 1,
|
|
69077
|
+
offset: 0
|
|
69078
|
+
},
|
|
69079
|
+
kW: {
|
|
69080
|
+
dimension: "power",
|
|
69081
|
+
factor: 1e3,
|
|
69082
|
+
offset: 0
|
|
69083
|
+
},
|
|
69084
|
+
VA: {
|
|
69085
|
+
dimension: "apparent-power",
|
|
69086
|
+
factor: 1,
|
|
69087
|
+
offset: 0
|
|
69088
|
+
},
|
|
69089
|
+
Wh: {
|
|
69090
|
+
dimension: "energy",
|
|
69091
|
+
factor: 1,
|
|
69092
|
+
offset: 0
|
|
69093
|
+
},
|
|
69094
|
+
kWh: {
|
|
69095
|
+
dimension: "energy",
|
|
69096
|
+
factor: 1e3,
|
|
69097
|
+
offset: 0
|
|
69098
|
+
},
|
|
69099
|
+
MWh: {
|
|
69100
|
+
dimension: "energy",
|
|
69101
|
+
factor: 1e6,
|
|
69102
|
+
offset: 0
|
|
69103
|
+
},
|
|
69104
|
+
V: {
|
|
69105
|
+
dimension: "voltage",
|
|
69106
|
+
factor: 1,
|
|
69107
|
+
offset: 0
|
|
69108
|
+
},
|
|
69109
|
+
mV: {
|
|
69110
|
+
dimension: "voltage",
|
|
69111
|
+
factor: .001,
|
|
69112
|
+
offset: 0
|
|
69113
|
+
},
|
|
69114
|
+
A: {
|
|
69115
|
+
dimension: "current",
|
|
69116
|
+
factor: 1,
|
|
69117
|
+
offset: 0
|
|
69118
|
+
},
|
|
69119
|
+
mA: {
|
|
69120
|
+
dimension: "current",
|
|
69121
|
+
factor: .001,
|
|
69122
|
+
offset: 0
|
|
69123
|
+
},
|
|
69124
|
+
ppm: {
|
|
69125
|
+
dimension: "concentration-volume",
|
|
69126
|
+
factor: 1,
|
|
69127
|
+
offset: 0
|
|
69128
|
+
},
|
|
69129
|
+
ppb: {
|
|
69130
|
+
dimension: "concentration-volume",
|
|
69131
|
+
factor: .001,
|
|
69132
|
+
offset: 0
|
|
69133
|
+
},
|
|
69134
|
+
"µg/m³": {
|
|
69135
|
+
dimension: "concentration-mass",
|
|
69136
|
+
factor: 1,
|
|
69137
|
+
offset: 0
|
|
69138
|
+
},
|
|
69139
|
+
"mg/m³": {
|
|
69140
|
+
dimension: "concentration-mass",
|
|
69141
|
+
factor: 1e3,
|
|
69142
|
+
offset: 0
|
|
69143
|
+
},
|
|
69144
|
+
kg: {
|
|
69145
|
+
dimension: "mass",
|
|
69146
|
+
factor: 1,
|
|
69147
|
+
offset: 0
|
|
69148
|
+
},
|
|
69149
|
+
g: {
|
|
69150
|
+
dimension: "mass",
|
|
69151
|
+
factor: .001,
|
|
69152
|
+
offset: 0
|
|
69153
|
+
},
|
|
69154
|
+
lb: {
|
|
69155
|
+
dimension: "mass",
|
|
69156
|
+
factor: .453592,
|
|
69157
|
+
offset: 0
|
|
69158
|
+
},
|
|
69159
|
+
oz: {
|
|
69160
|
+
dimension: "mass",
|
|
69161
|
+
factor: .0283495,
|
|
69162
|
+
offset: 0
|
|
69163
|
+
},
|
|
69164
|
+
"%": {
|
|
69165
|
+
dimension: "percentage",
|
|
69166
|
+
factor: 1,
|
|
69167
|
+
offset: 0
|
|
69168
|
+
},
|
|
69169
|
+
L: {
|
|
69170
|
+
dimension: "volume",
|
|
69171
|
+
factor: 1,
|
|
69172
|
+
offset: 0
|
|
69173
|
+
},
|
|
69174
|
+
mL: {
|
|
69175
|
+
dimension: "volume",
|
|
69176
|
+
factor: .001,
|
|
69177
|
+
offset: 0
|
|
69178
|
+
},
|
|
69179
|
+
gal: {
|
|
69180
|
+
dimension: "volume",
|
|
69181
|
+
factor: 3.785411784,
|
|
69182
|
+
offset: 0
|
|
69183
|
+
},
|
|
69184
|
+
s: {
|
|
69185
|
+
dimension: "duration",
|
|
69186
|
+
factor: 1,
|
|
69187
|
+
offset: 0
|
|
69188
|
+
},
|
|
69189
|
+
ms: {
|
|
69190
|
+
dimension: "duration",
|
|
69191
|
+
factor: .001,
|
|
69192
|
+
offset: 0
|
|
69193
|
+
},
|
|
69194
|
+
min: {
|
|
69195
|
+
dimension: "duration",
|
|
69196
|
+
factor: 60,
|
|
69197
|
+
offset: 0
|
|
69198
|
+
},
|
|
69199
|
+
h: {
|
|
69200
|
+
dimension: "duration",
|
|
69201
|
+
factor: 3600,
|
|
69202
|
+
offset: 0
|
|
69203
|
+
},
|
|
69204
|
+
d: {
|
|
69205
|
+
dimension: "duration",
|
|
69206
|
+
factor: 86400,
|
|
69207
|
+
offset: 0
|
|
69208
|
+
},
|
|
69209
|
+
B: {
|
|
69210
|
+
dimension: "information",
|
|
69211
|
+
factor: 1,
|
|
69212
|
+
offset: 0
|
|
69213
|
+
},
|
|
69214
|
+
KiB: {
|
|
69215
|
+
dimension: "information",
|
|
69216
|
+
factor: 1024,
|
|
69217
|
+
offset: 0
|
|
69218
|
+
},
|
|
69219
|
+
MiB: {
|
|
69220
|
+
dimension: "information",
|
|
69221
|
+
factor: 1024 ** 2,
|
|
69222
|
+
offset: 0
|
|
69223
|
+
},
|
|
69224
|
+
GiB: {
|
|
69225
|
+
dimension: "information",
|
|
69226
|
+
factor: 1024 ** 3,
|
|
69227
|
+
offset: 0
|
|
69228
|
+
},
|
|
69229
|
+
TiB: {
|
|
69230
|
+
dimension: "information",
|
|
69231
|
+
factor: 1024 ** 4,
|
|
69232
|
+
offset: 0
|
|
69233
|
+
},
|
|
69234
|
+
kB: {
|
|
69235
|
+
dimension: "information",
|
|
69236
|
+
factor: 1e3,
|
|
69237
|
+
offset: 0
|
|
69238
|
+
},
|
|
69239
|
+
MB: {
|
|
69240
|
+
dimension: "information",
|
|
69241
|
+
factor: 1e6,
|
|
69242
|
+
offset: 0
|
|
69243
|
+
},
|
|
69244
|
+
GB: {
|
|
69245
|
+
dimension: "information",
|
|
69246
|
+
factor: 1e9,
|
|
69247
|
+
offset: 0
|
|
69248
|
+
},
|
|
69249
|
+
"°": {
|
|
69250
|
+
dimension: "angle",
|
|
69251
|
+
factor: 1,
|
|
69252
|
+
offset: 0
|
|
69253
|
+
},
|
|
69254
|
+
dBFS: {
|
|
69255
|
+
dimension: "sound-level",
|
|
69256
|
+
factor: 1,
|
|
69257
|
+
offset: 0
|
|
69258
|
+
},
|
|
69259
|
+
dBm: {
|
|
69260
|
+
dimension: "signal-level",
|
|
69261
|
+
factor: 1,
|
|
69262
|
+
offset: 0
|
|
69263
|
+
},
|
|
69264
|
+
mired: {
|
|
69265
|
+
dimension: "colour-temperature",
|
|
69266
|
+
factor: 1,
|
|
69267
|
+
offset: 0
|
|
69268
|
+
},
|
|
69269
|
+
kbps: {
|
|
69270
|
+
dimension: "bitrate",
|
|
69271
|
+
factor: 1,
|
|
69272
|
+
offset: 0
|
|
69273
|
+
},
|
|
69274
|
+
Mbps: {
|
|
69275
|
+
dimension: "bitrate",
|
|
69276
|
+
factor: 1e3,
|
|
69277
|
+
offset: 0
|
|
69278
|
+
},
|
|
69279
|
+
fps: {
|
|
69280
|
+
dimension: "rate",
|
|
69281
|
+
factor: 1,
|
|
69282
|
+
offset: 0
|
|
69283
|
+
}
|
|
69284
|
+
};
|
|
69285
|
+
/** Resolve a unit's `UnitSpec`, or `undefined` when the spelling is unknown. */
|
|
69286
|
+
function specFor(unit) {
|
|
69287
|
+
return Object.hasOwn(UNIT_TABLE, unit) ? UNIT_TABLE[unit] : void 0;
|
|
69288
|
+
}
|
|
69289
|
+
/** The dimension a unit belongs to, or `undefined` for an unknown unit. */
|
|
69290
|
+
function unitDimension(unit) {
|
|
69291
|
+
return specFor(unit)?.dimension;
|
|
69292
|
+
}
|
|
69293
|
+
/** Value in `spec`'s unit → its dimension's canonical unit. */
|
|
69294
|
+
function toCanonical(value, spec) {
|
|
69295
|
+
return value * spec.factor + spec.offset;
|
|
69296
|
+
}
|
|
69297
|
+
/** Canonical-unit value → the unit described by `spec`. */
|
|
69298
|
+
function fromCanonical(canonical, spec) {
|
|
69299
|
+
return (canonical - spec.offset) / spec.factor;
|
|
69300
|
+
}
|
|
69301
|
+
/**
|
|
69302
|
+
* Graceful variant for the render path: returns the converted value, or
|
|
69303
|
+
* `undefined` when the conversion is refused (unknown unit / cross-dimension).
|
|
69304
|
+
* Never throws — a render caller falls back to the raw value + source unit.
|
|
69305
|
+
*/
|
|
69306
|
+
function tryConvertUnit(value, from, to) {
|
|
69307
|
+
if (from === to) return value;
|
|
69308
|
+
const fromSpec = specFor(from);
|
|
69309
|
+
if (!fromSpec) return void 0;
|
|
69310
|
+
const toSpec = specFor(to);
|
|
69311
|
+
if (!toSpec) return void 0;
|
|
69312
|
+
if (fromSpec.dimension !== toSpec.dimension) return void 0;
|
|
69313
|
+
return fromCanonical(toCanonical(value, fromSpec), toSpec);
|
|
69314
|
+
}
|
|
68991
69315
|
SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
|
|
68992
69316
|
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;
|
|
68993
69317
|
String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
|
|
@@ -83657,7 +83981,6 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83657
83981
|
field: "value",
|
|
83658
83982
|
quantity: t("the reading", "il valore"),
|
|
83659
83983
|
label: t("Reading", "Valore"),
|
|
83660
|
-
unitField: "unit",
|
|
83661
83984
|
icon: "gauge"
|
|
83662
83985
|
}]
|
|
83663
83986
|
},
|
|
@@ -83793,7 +84116,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83793
84116
|
field: "temperature",
|
|
83794
84117
|
quantity: t("the outdoor temperature", "la temperatura esterna"),
|
|
83795
84118
|
label: t("Temperature", "Temperatura"),
|
|
83796
|
-
|
|
84119
|
+
unit: "°C",
|
|
83797
84120
|
icon: "thermometer"
|
|
83798
84121
|
},
|
|
83799
84122
|
{
|
|
@@ -83809,7 +84132,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83809
84132
|
field: "windSpeed",
|
|
83810
84133
|
quantity: t("the wind speed", "la velocità del vento"),
|
|
83811
84134
|
label: t("Wind", "Vento"),
|
|
83812
|
-
|
|
84135
|
+
unit: "m/s",
|
|
83813
84136
|
icon: "wind"
|
|
83814
84137
|
},
|
|
83815
84138
|
{
|
|
@@ -83817,7 +84140,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83817
84140
|
field: "pressure",
|
|
83818
84141
|
quantity: t("the air pressure", "la pressione atmosferica"),
|
|
83819
84142
|
label: t("Pressure", "Pressione"),
|
|
83820
|
-
|
|
84143
|
+
unit: "hPa",
|
|
83821
84144
|
icon: "gauge"
|
|
83822
84145
|
}
|
|
83823
84146
|
]
|
|
@@ -86954,6 +87277,11 @@ var PulseOverrideDraftSchema = object({
|
|
|
86954
87277
|
targetId: string().min(1),
|
|
86955
87278
|
enabled: boolean(),
|
|
86956
87279
|
debounceMs: number().nonnegative(),
|
|
87280
|
+
edges: array(_enum([
|
|
87281
|
+
"rising",
|
|
87282
|
+
"button",
|
|
87283
|
+
"native-event"
|
|
87284
|
+
])).min(1).optional(),
|
|
86957
87285
|
sources: array(OverrideSourceSchema).min(1)
|
|
86958
87286
|
});
|
|
86959
87287
|
var SpanSourceDraftSchema = OverrideSourceSchema.extend({ mode: _enum([
|
|
@@ -88177,6 +88505,96 @@ DEFAULT_NATIVE_LEASE_SETTINGS.activityMs;
|
|
|
88177
88505
|
DEFAULT_NATIVE_LEASE_SETTINGS.tileBudgetMb;
|
|
88178
88506
|
DEFAULT_NATIVE_LEASE_SETTINGS.sceneBudgetMb;
|
|
88179
88507
|
DEFAULT_NATIVE_LEASE_SETTINGS.admission;
|
|
88508
|
+
/**
|
|
88509
|
+
* Convert an upstream number into the stored base of its quantity (D944 §4).
|
|
88510
|
+
* An unknown unit or a unit from another dimension is a refusal: the caller
|
|
88511
|
+
* logs it and publishes null (D393). This function never guesses.
|
|
88512
|
+
*/
|
|
88513
|
+
var DIMENSION_QUANTITY = {
|
|
88514
|
+
temperature: "temperature",
|
|
88515
|
+
pressure: "pressure",
|
|
88516
|
+
speed: "speed",
|
|
88517
|
+
"precipitation-rate": "precipitation-rate",
|
|
88518
|
+
length: "length",
|
|
88519
|
+
area: "area",
|
|
88520
|
+
illuminance: "illuminance",
|
|
88521
|
+
irradiance: "irradiance",
|
|
88522
|
+
power: "power",
|
|
88523
|
+
"apparent-power": "apparent-power",
|
|
88524
|
+
energy: "energy",
|
|
88525
|
+
voltage: "voltage",
|
|
88526
|
+
current: "current",
|
|
88527
|
+
"concentration-volume": "concentration-volume",
|
|
88528
|
+
"concentration-mass": "concentration-mass",
|
|
88529
|
+
mass: "mass",
|
|
88530
|
+
percentage: "percentage",
|
|
88531
|
+
volume: "volume",
|
|
88532
|
+
duration: "duration",
|
|
88533
|
+
information: "information",
|
|
88534
|
+
angle: "angle",
|
|
88535
|
+
"sound-level": "sound-level",
|
|
88536
|
+
"signal-level": "signal-level",
|
|
88537
|
+
"colour-temperature": "colour-temperature",
|
|
88538
|
+
bitrate: "bitrate",
|
|
88539
|
+
rate: "rate"
|
|
88540
|
+
};
|
|
88541
|
+
/**
|
|
88542
|
+
* Quantity implied by a unit symbol. `ppb` and `ms` are the two symbols
|
|
88543
|
+
* whose stored base is not the dimension's canonical unit. `mm` is length;
|
|
88544
|
+
* precipitation is chosen by the caller (a device class), not by the symbol.
|
|
88545
|
+
*/
|
|
88546
|
+
function quantityFromUnit(rawUnit) {
|
|
88547
|
+
const unit = normalizeUnit(rawUnit);
|
|
88548
|
+
if (unit === void 0) return void 0;
|
|
88549
|
+
if (unit === "ppb") return "concentration-ppb";
|
|
88550
|
+
if (unit === "ms") return "duration-ms";
|
|
88551
|
+
const dimension = unitDimension(unit);
|
|
88552
|
+
if (dimension === void 0) return void 0;
|
|
88553
|
+
return DIMENSION_QUANTITY[dimension];
|
|
88554
|
+
}
|
|
88555
|
+
function ingestReading(input) {
|
|
88556
|
+
if (!Number.isFinite(input.value)) return {
|
|
88557
|
+
ok: false,
|
|
88558
|
+
reason: "non-finite"
|
|
88559
|
+
};
|
|
88560
|
+
if (input.quantity === "device") return {
|
|
88561
|
+
ok: false,
|
|
88562
|
+
reason: "unknown-unit"
|
|
88563
|
+
};
|
|
88564
|
+
const raw = input.rawUnit?.trim();
|
|
88565
|
+
if (raw === void 0 || raw.length === 0) return {
|
|
88566
|
+
ok: true,
|
|
88567
|
+
value: input.value
|
|
88568
|
+
};
|
|
88569
|
+
const unit = normalizeUnit(raw);
|
|
88570
|
+
if (unit === void 0) return {
|
|
88571
|
+
ok: false,
|
|
88572
|
+
reason: "unknown-unit"
|
|
88573
|
+
};
|
|
88574
|
+
const base = baseUnitOf(input.quantity);
|
|
88575
|
+
if (base === void 0) {
|
|
88576
|
+
if (unitDimension(unit) !== void 0) return {
|
|
88577
|
+
ok: false,
|
|
88578
|
+
reason: "cross-dimension"
|
|
88579
|
+
};
|
|
88580
|
+
return {
|
|
88581
|
+
ok: false,
|
|
88582
|
+
reason: "unknown-unit"
|
|
88583
|
+
};
|
|
88584
|
+
}
|
|
88585
|
+
const converted = tryConvertUnit(input.value, unit, base);
|
|
88586
|
+
if (converted === void 0) return unitDimension(unit) === void 0 ? {
|
|
88587
|
+
ok: false,
|
|
88588
|
+
reason: "unknown-unit"
|
|
88589
|
+
} : {
|
|
88590
|
+
ok: false,
|
|
88591
|
+
reason: "cross-dimension"
|
|
88592
|
+
};
|
|
88593
|
+
return {
|
|
88594
|
+
ok: true,
|
|
88595
|
+
value: converted
|
|
88596
|
+
};
|
|
88597
|
+
}
|
|
88180
88598
|
var MB = 1024 * 1024;
|
|
88181
88599
|
1024 * MB, 3072 * MB;
|
|
88182
88600
|
//#endregion
|
|
@@ -88318,6 +88736,12 @@ Object.defineProperty(exports, "heatingValveCapability", {
|
|
|
88318
88736
|
return heatingValveCapability;
|
|
88319
88737
|
}
|
|
88320
88738
|
});
|
|
88739
|
+
Object.defineProperty(exports, "ingestReading", {
|
|
88740
|
+
enumerable: true,
|
|
88741
|
+
get: function() {
|
|
88742
|
+
return ingestReading;
|
|
88743
|
+
}
|
|
88744
|
+
});
|
|
88321
88745
|
Object.defineProperty(exports, "isSecretMarker", {
|
|
88322
88746
|
enumerable: true,
|
|
88323
88747
|
get: function() {
|
|
@@ -88360,6 +88784,12 @@ Object.defineProperty(exports, "powerMeterCapability", {
|
|
|
88360
88784
|
return powerMeterCapability;
|
|
88361
88785
|
}
|
|
88362
88786
|
});
|
|
88787
|
+
Object.defineProperty(exports, "quantityFromUnit", {
|
|
88788
|
+
enumerable: true,
|
|
88789
|
+
get: function() {
|
|
88790
|
+
return quantityFromUnit;
|
|
88791
|
+
}
|
|
88792
|
+
});
|
|
88363
88793
|
Object.defineProperty(exports, "record", {
|
|
88364
88794
|
enumerable: true,
|
|
88365
88795
|
get: function() {
|