@camstack/addon-provider-tuya 0.2.145 → 0.2.146
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/CHANGELOG.md +12 -0
- package/README.md +18 -0
- package/dist/addon.js +959 -509
- package/dist/addon.mjs +959 -509
- package/package.json +4 -2
package/dist/addon.js
CHANGED
|
@@ -819,7 +819,7 @@ async function discoverDevices(options = {}, binder = createDgramBinder()) {
|
|
|
819
819
|
return [...byId.values()];
|
|
820
820
|
}
|
|
821
821
|
//#endregion
|
|
822
|
-
//#region ../types/dist/event-category-
|
|
822
|
+
//#region ../types/dist/event-category-CT-hz5Rb.mjs
|
|
823
823
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
824
824
|
EventCategory["SystemBoot"] = "system.boot";
|
|
825
825
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -1145,6 +1145,14 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
1145
1145
|
/** The recovery edge of {@link PipelineMotionNoisy}: the motion fell back, or a detection arrived. */
|
|
1146
1146
|
EventCategory["PipelineMotionCalm"] = "pipeline.motion-calm";
|
|
1147
1147
|
/**
|
|
1148
|
+
* A camera's package LLM confirm has failed closed three times in a row
|
|
1149
|
+
* (D931, 2026-10-26). One edge per camera until
|
|
1150
|
+
* {@link PipelinePackageLlmAnswered}.
|
|
1151
|
+
*/
|
|
1152
|
+
EventCategory["PipelinePackageLlmSilent"] = "pipeline.package-llm-silent";
|
|
1153
|
+
/** The recovery edge of {@link PipelinePackageLlmSilent}: a confirm returned yes or no. */
|
|
1154
|
+
EventCategory["PipelinePackageLlmAnswered"] = "pipeline.package-llm-answered";
|
|
1155
|
+
/**
|
|
1148
1156
|
* Per-camera pipeline config was mutated by the orchestrator
|
|
1149
1157
|
* (a settings change via `setAgentInferenceDevices` /
|
|
1150
1158
|
* `setCameraStepToggle` / `setCameraStepSettings`). Orchestrator
|
|
@@ -6254,7 +6262,7 @@ var ZodIssueCode = {
|
|
|
6254
6262
|
var ZodFirstPartyTypeKind;
|
|
6255
6263
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
6256
6264
|
//#endregion
|
|
6257
|
-
//#region ../types/dist/sleep-
|
|
6265
|
+
//#region ../types/dist/sleep-bykKrTgu.mjs
|
|
6258
6266
|
/**
|
|
6259
6267
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
6260
6268
|
* window to float samples (D455).
|
|
@@ -8808,6 +8816,99 @@ var RecordKindDeclarationSchema = object({
|
|
|
8808
8816
|
}).strict();
|
|
8809
8817
|
/** The kind names: lower-case, dash separated, short enough for an index name. */
|
|
8810
8818
|
var RecordKindNameSchema = string().regex(/^[a-z][a-z0-9-]{0,47}$/);
|
|
8819
|
+
var READING_QUANTITIES = [
|
|
8820
|
+
"temperature",
|
|
8821
|
+
"pressure",
|
|
8822
|
+
"speed",
|
|
8823
|
+
"precipitation",
|
|
8824
|
+
"precipitation-rate",
|
|
8825
|
+
"length",
|
|
8826
|
+
"area",
|
|
8827
|
+
"illuminance",
|
|
8828
|
+
"irradiance",
|
|
8829
|
+
"power",
|
|
8830
|
+
"energy",
|
|
8831
|
+
"voltage",
|
|
8832
|
+
"current",
|
|
8833
|
+
"apparent-power",
|
|
8834
|
+
"humidity",
|
|
8835
|
+
"percentage",
|
|
8836
|
+
"concentration-volume",
|
|
8837
|
+
"concentration-mass",
|
|
8838
|
+
"concentration-ppb",
|
|
8839
|
+
"volume",
|
|
8840
|
+
"duration",
|
|
8841
|
+
"duration-ms",
|
|
8842
|
+
"information",
|
|
8843
|
+
"sound-level",
|
|
8844
|
+
"signal-level",
|
|
8845
|
+
"colour-temperature",
|
|
8846
|
+
"angle",
|
|
8847
|
+
"bitrate",
|
|
8848
|
+
"rate",
|
|
8849
|
+
"mass",
|
|
8850
|
+
"index",
|
|
8851
|
+
"ratio",
|
|
8852
|
+
"count",
|
|
8853
|
+
"none",
|
|
8854
|
+
"device"
|
|
8855
|
+
];
|
|
8856
|
+
var ReadingQuantitySchema = _enum(READING_QUANTITIES);
|
|
8857
|
+
new Set(READING_QUANTITIES);
|
|
8858
|
+
/**
|
|
8859
|
+
* Stored unit symbol for a quantity. `none` means the number is dimensionless
|
|
8860
|
+
* (or an index / ratio / count). `device` means the cap has no single unit.
|
|
8861
|
+
*/
|
|
8862
|
+
var QUANTITY_BASE = {
|
|
8863
|
+
temperature: "°C",
|
|
8864
|
+
pressure: "hPa",
|
|
8865
|
+
speed: "m/s",
|
|
8866
|
+
precipitation: "mm",
|
|
8867
|
+
"precipitation-rate": "mm/h",
|
|
8868
|
+
length: "m",
|
|
8869
|
+
area: "m²",
|
|
8870
|
+
illuminance: "lx",
|
|
8871
|
+
irradiance: "W/m²",
|
|
8872
|
+
power: "W",
|
|
8873
|
+
energy: "kWh",
|
|
8874
|
+
voltage: "V",
|
|
8875
|
+
current: "A",
|
|
8876
|
+
"apparent-power": "VA",
|
|
8877
|
+
humidity: "%",
|
|
8878
|
+
percentage: "%",
|
|
8879
|
+
"concentration-volume": "ppm",
|
|
8880
|
+
"concentration-mass": "µg/m³",
|
|
8881
|
+
"concentration-ppb": "ppb",
|
|
8882
|
+
volume: "L",
|
|
8883
|
+
duration: "s",
|
|
8884
|
+
"duration-ms": "ms",
|
|
8885
|
+
information: "B",
|
|
8886
|
+
"sound-level": "dBFS",
|
|
8887
|
+
"signal-level": "dBm",
|
|
8888
|
+
"colour-temperature": "mired",
|
|
8889
|
+
angle: "°",
|
|
8890
|
+
bitrate: "kbps",
|
|
8891
|
+
rate: "fps",
|
|
8892
|
+
mass: "kg",
|
|
8893
|
+
index: "none",
|
|
8894
|
+
ratio: "none",
|
|
8895
|
+
count: "none",
|
|
8896
|
+
none: "none",
|
|
8897
|
+
device: "device"
|
|
8898
|
+
};
|
|
8899
|
+
/** The stored unit, or `undefined` when the quantity has no unit symbol. */
|
|
8900
|
+
function baseUnitOf(quantity) {
|
|
8901
|
+
const symbol = QUANTITY_BASE[quantity];
|
|
8902
|
+
if (symbol === "none" || symbol === "device") return void 0;
|
|
8903
|
+
return symbol;
|
|
8904
|
+
}
|
|
8905
|
+
function readingMeta(quantity, extras) {
|
|
8906
|
+
return {
|
|
8907
|
+
quantity,
|
|
8908
|
+
...extras?.precision !== void 0 ? { precision: extras.precision } : {},
|
|
8909
|
+
...extras?.label !== void 0 ? { label: extras.label } : {}
|
|
8910
|
+
};
|
|
8911
|
+
}
|
|
8811
8912
|
/** Shared Zod schemas used across streaming capabilities. */
|
|
8812
8913
|
var CamProfileSchema = _enum([
|
|
8813
8914
|
"high",
|
|
@@ -8835,8 +8936,8 @@ var CamStreamKindSchema = _enum([
|
|
|
8835
8936
|
"derived"
|
|
8836
8937
|
]);
|
|
8837
8938
|
var CamStreamResolutionSchema = object({
|
|
8838
|
-
width: number().int().positive(),
|
|
8839
|
-
height: number().int().positive()
|
|
8939
|
+
width: number().int().positive().meta(readingMeta("none")),
|
|
8940
|
+
height: number().int().positive().meta(readingMeta("none"))
|
|
8840
8941
|
});
|
|
8841
8942
|
var CameraStreamSchema = object({
|
|
8842
8943
|
/** Stable, provider-assigned id unique within the (deviceId) scope. */
|
|
@@ -9354,6 +9455,8 @@ var CAP_NAMES = Object.freeze([
|
|
|
9354
9455
|
"filesystem-browse",
|
|
9355
9456
|
"flood",
|
|
9356
9457
|
"gas",
|
|
9458
|
+
"group-commands",
|
|
9459
|
+
"group-status",
|
|
9357
9460
|
"heating-valve",
|
|
9358
9461
|
"humidifier",
|
|
9359
9462
|
"humidity-sensor",
|
|
@@ -9483,14 +9586,6 @@ Object.freeze({
|
|
|
9483
9586
|
{
|
|
9484
9587
|
"path": "aqi",
|
|
9485
9588
|
"valueType": "number"
|
|
9486
|
-
},
|
|
9487
|
-
{
|
|
9488
|
-
"path": "unit",
|
|
9489
|
-
"valueType": "string"
|
|
9490
|
-
},
|
|
9491
|
-
{
|
|
9492
|
-
"path": "precision",
|
|
9493
|
-
"valueType": "number"
|
|
9494
9589
|
}
|
|
9495
9590
|
],
|
|
9496
9591
|
"alarm-panel": [
|
|
@@ -9526,20 +9621,10 @@ Object.freeze({
|
|
|
9526
9621
|
"valueType": "boolean"
|
|
9527
9622
|
}
|
|
9528
9623
|
],
|
|
9529
|
-
"ambient-light-sensor": [
|
|
9530
|
-
|
|
9531
|
-
|
|
9532
|
-
|
|
9533
|
-
},
|
|
9534
|
-
{
|
|
9535
|
-
"path": "unit",
|
|
9536
|
-
"valueType": "string"
|
|
9537
|
-
},
|
|
9538
|
-
{
|
|
9539
|
-
"path": "precision",
|
|
9540
|
-
"valueType": "number"
|
|
9541
|
-
}
|
|
9542
|
-
],
|
|
9624
|
+
"ambient-light-sensor": [{
|
|
9625
|
+
"path": "lux",
|
|
9626
|
+
"valueType": "number"
|
|
9627
|
+
}],
|
|
9543
9628
|
"audio-metrics": [
|
|
9544
9629
|
{
|
|
9545
9630
|
"path": "ts",
|
|
@@ -9619,6 +9704,10 @@ Object.freeze({
|
|
|
9619
9704
|
"path": "lastUpdated",
|
|
9620
9705
|
"valueType": "number"
|
|
9621
9706
|
},
|
|
9707
|
+
{
|
|
9708
|
+
"path": "volts",
|
|
9709
|
+
"valueType": "number"
|
|
9710
|
+
},
|
|
9622
9711
|
{
|
|
9623
9712
|
"path": "lastContactAt",
|
|
9624
9713
|
"valueType": "number"
|
|
@@ -9861,10 +9950,6 @@ Object.freeze({
|
|
|
9861
9950
|
"datetime"
|
|
9862
9951
|
]
|
|
9863
9952
|
},
|
|
9864
|
-
{
|
|
9865
|
-
"path": "unit",
|
|
9866
|
-
"valueType": "string"
|
|
9867
|
-
},
|
|
9868
9953
|
{
|
|
9869
9954
|
"path": "min",
|
|
9870
9955
|
"valueType": "number"
|
|
@@ -9876,19 +9961,6 @@ Object.freeze({
|
|
|
9876
9961
|
{
|
|
9877
9962
|
"path": "step",
|
|
9878
9963
|
"valueType": "number"
|
|
9879
|
-
},
|
|
9880
|
-
{
|
|
9881
|
-
"path": "precision",
|
|
9882
|
-
"valueType": "number"
|
|
9883
|
-
},
|
|
9884
|
-
{
|
|
9885
|
-
"path": "format",
|
|
9886
|
-
"valueType": "enum",
|
|
9887
|
-
"enumValues": [
|
|
9888
|
-
"date",
|
|
9889
|
-
"time",
|
|
9890
|
-
"datetime"
|
|
9891
|
-
]
|
|
9892
9964
|
}
|
|
9893
9965
|
],
|
|
9894
9966
|
"cover": [
|
|
@@ -10129,13 +10201,8 @@ Object.freeze({
|
|
|
10129
10201
|
"path": "value",
|
|
10130
10202
|
"valueType": "string"
|
|
10131
10203
|
}, {
|
|
10132
|
-
"path": "
|
|
10133
|
-
"valueType": "
|
|
10134
|
-
"enumValues": [
|
|
10135
|
-
"date",
|
|
10136
|
-
"time",
|
|
10137
|
-
"datetime"
|
|
10138
|
-
]
|
|
10204
|
+
"path": "timestamp",
|
|
10205
|
+
"valueType": "boolean"
|
|
10139
10206
|
}],
|
|
10140
10207
|
"event-emitter": [
|
|
10141
10208
|
{
|
|
@@ -10208,6 +10275,20 @@ Object.freeze({
|
|
|
10208
10275
|
"path": "detected",
|
|
10209
10276
|
"valueType": "boolean"
|
|
10210
10277
|
}],
|
|
10278
|
+
"group-status": [
|
|
10279
|
+
{
|
|
10280
|
+
"path": "included",
|
|
10281
|
+
"valueType": "number"
|
|
10282
|
+
},
|
|
10283
|
+
{
|
|
10284
|
+
"path": "excluded",
|
|
10285
|
+
"valueType": "number"
|
|
10286
|
+
},
|
|
10287
|
+
{
|
|
10288
|
+
"path": "total",
|
|
10289
|
+
"valueType": "number"
|
|
10290
|
+
}
|
|
10291
|
+
],
|
|
10211
10292
|
"heating-valve": [{
|
|
10212
10293
|
"path": "position",
|
|
10213
10294
|
"valueType": "number"
|
|
@@ -10242,20 +10323,10 @@ Object.freeze({
|
|
|
10242
10323
|
"valueType": "number"
|
|
10243
10324
|
}
|
|
10244
10325
|
],
|
|
10245
|
-
"humidity-sensor": [
|
|
10246
|
-
|
|
10247
|
-
|
|
10248
|
-
|
|
10249
|
-
},
|
|
10250
|
-
{
|
|
10251
|
-
"path": "unit",
|
|
10252
|
-
"valueType": "string"
|
|
10253
|
-
},
|
|
10254
|
-
{
|
|
10255
|
-
"path": "precision",
|
|
10256
|
-
"valueType": "number"
|
|
10257
|
-
}
|
|
10258
|
-
],
|
|
10326
|
+
"humidity-sensor": [{
|
|
10327
|
+
"path": "percent",
|
|
10328
|
+
"valueType": "number"
|
|
10329
|
+
}],
|
|
10259
10330
|
"image": [{
|
|
10260
10331
|
"path": "url",
|
|
10261
10332
|
"valueType": "string"
|
|
@@ -10594,20 +10665,10 @@ Object.freeze({
|
|
|
10594
10665
|
"valueType": "boolean"
|
|
10595
10666
|
}
|
|
10596
10667
|
],
|
|
10597
|
-
"numeric-sensor": [
|
|
10598
|
-
|
|
10599
|
-
|
|
10600
|
-
|
|
10601
|
-
},
|
|
10602
|
-
{
|
|
10603
|
-
"path": "unit",
|
|
10604
|
-
"valueType": "string"
|
|
10605
|
-
},
|
|
10606
|
-
{
|
|
10607
|
-
"path": "precision",
|
|
10608
|
-
"valueType": "number"
|
|
10609
|
-
}
|
|
10610
|
-
],
|
|
10668
|
+
"numeric-sensor": [{
|
|
10669
|
+
"path": "value",
|
|
10670
|
+
"valueType": "number"
|
|
10671
|
+
}],
|
|
10611
10672
|
"pet-feeder": [
|
|
10612
10673
|
{
|
|
10613
10674
|
"path": "foodLevel",
|
|
@@ -10699,14 +10760,6 @@ Object.freeze({
|
|
|
10699
10760
|
{
|
|
10700
10761
|
"path": "powerFactor",
|
|
10701
10762
|
"valueType": "number"
|
|
10702
|
-
},
|
|
10703
|
-
{
|
|
10704
|
-
"path": "unit",
|
|
10705
|
-
"valueType": "string"
|
|
10706
|
-
},
|
|
10707
|
-
{
|
|
10708
|
-
"path": "precision",
|
|
10709
|
-
"valueType": "number"
|
|
10710
10763
|
}
|
|
10711
10764
|
],
|
|
10712
10765
|
"presence": [
|
|
@@ -10735,20 +10788,10 @@ Object.freeze({
|
|
|
10735
10788
|
"valueType": "number"
|
|
10736
10789
|
}
|
|
10737
10790
|
],
|
|
10738
|
-
"pressure-sensor": [
|
|
10739
|
-
|
|
10740
|
-
|
|
10741
|
-
|
|
10742
|
-
},
|
|
10743
|
-
{
|
|
10744
|
-
"path": "unit",
|
|
10745
|
-
"valueType": "string"
|
|
10746
|
-
},
|
|
10747
|
-
{
|
|
10748
|
-
"path": "precision",
|
|
10749
|
-
"valueType": "number"
|
|
10750
|
-
}
|
|
10751
|
-
],
|
|
10791
|
+
"pressure-sensor": [{
|
|
10792
|
+
"path": "hpa",
|
|
10793
|
+
"valueType": "number"
|
|
10794
|
+
}],
|
|
10752
10795
|
"privacy-mask": [{
|
|
10753
10796
|
"path": "enabled",
|
|
10754
10797
|
"valueType": "boolean"
|
|
@@ -11059,20 +11102,10 @@ Object.freeze({
|
|
|
11059
11102
|
"path": "tampered",
|
|
11060
11103
|
"valueType": "boolean"
|
|
11061
11104
|
}],
|
|
11062
|
-
"temperature-sensor": [
|
|
11063
|
-
|
|
11064
|
-
|
|
11065
|
-
|
|
11066
|
-
},
|
|
11067
|
-
{
|
|
11068
|
-
"path": "unit",
|
|
11069
|
-
"valueType": "string"
|
|
11070
|
-
},
|
|
11071
|
-
{
|
|
11072
|
-
"path": "precision",
|
|
11073
|
-
"valueType": "number"
|
|
11074
|
-
}
|
|
11075
|
-
],
|
|
11105
|
+
"temperature-sensor": [{
|
|
11106
|
+
"path": "celsius",
|
|
11107
|
+
"valueType": "number"
|
|
11108
|
+
}],
|
|
11076
11109
|
"update": [
|
|
11077
11110
|
{
|
|
11078
11111
|
"path": "currentVersion",
|
|
@@ -11183,10 +11216,6 @@ Object.freeze({
|
|
|
11183
11216
|
"path": "temperature",
|
|
11184
11217
|
"valueType": "number"
|
|
11185
11218
|
},
|
|
11186
|
-
{
|
|
11187
|
-
"path": "temperatureUnit",
|
|
11188
|
-
"valueType": "string"
|
|
11189
|
-
},
|
|
11190
11219
|
{
|
|
11191
11220
|
"path": "humidity",
|
|
11192
11221
|
"valueType": "number"
|
|
@@ -11195,18 +11224,10 @@ Object.freeze({
|
|
|
11195
11224
|
"path": "pressure",
|
|
11196
11225
|
"valueType": "number"
|
|
11197
11226
|
},
|
|
11198
|
-
{
|
|
11199
|
-
"path": "pressureUnit",
|
|
11200
|
-
"valueType": "string"
|
|
11201
|
-
},
|
|
11202
11227
|
{
|
|
11203
11228
|
"path": "windSpeed",
|
|
11204
11229
|
"valueType": "number"
|
|
11205
11230
|
},
|
|
11206
|
-
{
|
|
11207
|
-
"path": "windSpeedUnit",
|
|
11208
|
-
"valueType": "string"
|
|
11209
|
-
},
|
|
11210
11231
|
{
|
|
11211
11232
|
"path": "windBearing",
|
|
11212
11233
|
"valueType": "number"
|
|
@@ -11609,7 +11630,7 @@ function errMsg(err) {
|
|
|
11609
11630
|
return String(err);
|
|
11610
11631
|
}
|
|
11611
11632
|
//#endregion
|
|
11612
|
-
//#region ../types/dist/composition-
|
|
11633
|
+
//#region ../types/dist/composition-OhpuespA.mjs
|
|
11613
11634
|
/**
|
|
11614
11635
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
11615
11636
|
*
|
|
@@ -12364,15 +12385,74 @@ function validateExpressionSource(src) {
|
|
|
12364
12385
|
}
|
|
12365
12386
|
return null;
|
|
12366
12387
|
}
|
|
12367
|
-
/**
|
|
12368
|
-
|
|
12369
|
-
|
|
12370
|
-
|
|
12388
|
+
/**
|
|
12389
|
+
* A composition source identity: `(addonId, stableId)`, never a numeric device
|
|
12390
|
+
* id. Split out so helper schemas can name it without a cycle through
|
|
12391
|
+
* `composition.ts` (D659).
|
|
12392
|
+
*/
|
|
12371
12393
|
var CompositionSourceRefSchema = object({
|
|
12372
12394
|
/** The owning addon; `stableId` is unique only within it. */
|
|
12373
12395
|
addonId: string().min(1),
|
|
12374
12396
|
stableId: string().min(1)
|
|
12375
12397
|
});
|
|
12398
|
+
var GROUP_TEMPLATE_IDS = [
|
|
12399
|
+
"temperature",
|
|
12400
|
+
"humidity",
|
|
12401
|
+
"pressure",
|
|
12402
|
+
"illuminance",
|
|
12403
|
+
"power",
|
|
12404
|
+
"energy",
|
|
12405
|
+
"battery",
|
|
12406
|
+
"numeric",
|
|
12407
|
+
"motion",
|
|
12408
|
+
"contact",
|
|
12409
|
+
"leak",
|
|
12410
|
+
"smoke",
|
|
12411
|
+
"occupancy",
|
|
12412
|
+
"binary",
|
|
12413
|
+
"switch",
|
|
12414
|
+
"light"
|
|
12415
|
+
];
|
|
12416
|
+
var NUMERIC_AGGREGATES = [
|
|
12417
|
+
"mean",
|
|
12418
|
+
"median",
|
|
12419
|
+
"min",
|
|
12420
|
+
"max",
|
|
12421
|
+
"sum"
|
|
12422
|
+
];
|
|
12423
|
+
var BINARY_AGGREGATES = ["any", "all"];
|
|
12424
|
+
/** How an actuator group decides it is on. Unknown members never count as off. */
|
|
12425
|
+
var ACTIVE_CRITERIA = ["at-least-one", "all"];
|
|
12426
|
+
var AGGREGATE_REDUCERS = [
|
|
12427
|
+
"mean",
|
|
12428
|
+
"median",
|
|
12429
|
+
"min",
|
|
12430
|
+
"max",
|
|
12431
|
+
"sum",
|
|
12432
|
+
"any",
|
|
12433
|
+
"all"
|
|
12434
|
+
];
|
|
12435
|
+
var GroupTemplateIdSchema = _enum(GROUP_TEMPLATE_IDS);
|
|
12436
|
+
var AggregateReducerSchema = _enum(AGGREGATE_REDUCERS);
|
|
12437
|
+
var ActiveCriterionSchema = _enum(ACTIVE_CRITERIA);
|
|
12438
|
+
/** One member. The field is stored so occupancy can name motion or binary. */
|
|
12439
|
+
var HelperMemberSchema = object({
|
|
12440
|
+
source: CompositionSourceRefSchema,
|
|
12441
|
+
cap: string().min(1),
|
|
12442
|
+
fieldPath: string().min(1)
|
|
12443
|
+
});
|
|
12444
|
+
var HelperSpecSchema = discriminatedUnion("kind", [object({
|
|
12445
|
+
kind: literal("group"),
|
|
12446
|
+
templateId: GroupTemplateIdSchema,
|
|
12447
|
+
aggregate: AggregateReducerSchema,
|
|
12448
|
+
members: array(HelperMemberSchema).min(1).max(64),
|
|
12449
|
+
/** Actuator groups only. Readings leave this unset. */
|
|
12450
|
+
active: ActiveCriterionSchema.optional()
|
|
12451
|
+
})]);
|
|
12452
|
+
/** A composed device's stableId is this prefix plus the block id. */
|
|
12453
|
+
var COMPOSED_DEVICE_STABLE_ID_PREFIX = "composed-";
|
|
12454
|
+
/** Longest snippet a `code` source may carry (slice 4). */
|
|
12455
|
+
var MAX_COMPOSITION_CODE_LENGTH = 2e4;
|
|
12376
12456
|
/** One field of one capability of one source device. */
|
|
12377
12457
|
var CompositionFieldReadSchema = object({
|
|
12378
12458
|
source: CompositionSourceRefSchema,
|
|
@@ -12416,7 +12496,33 @@ var CompositionCodeSourceSchema = object({
|
|
|
12416
12496
|
var CompositionFieldSourceSchema = discriminatedUnion("kind", [
|
|
12417
12497
|
CompositionFromSourceSchema,
|
|
12418
12498
|
CompositionExpressionSourceSchema,
|
|
12419
|
-
CompositionCodeSourceSchema
|
|
12499
|
+
CompositionCodeSourceSchema,
|
|
12500
|
+
object({
|
|
12501
|
+
kind: literal("aggregate"),
|
|
12502
|
+
reducer: _enum([
|
|
12503
|
+
"mean",
|
|
12504
|
+
"median",
|
|
12505
|
+
"min",
|
|
12506
|
+
"max",
|
|
12507
|
+
"sum",
|
|
12508
|
+
"any",
|
|
12509
|
+
"all"
|
|
12510
|
+
]),
|
|
12511
|
+
reads: array(CompositionFieldReadSchema).min(1).max(64),
|
|
12512
|
+
/** `value` is the reading; the others are the member counts. */
|
|
12513
|
+
publish: _enum([
|
|
12514
|
+
"value",
|
|
12515
|
+
"included",
|
|
12516
|
+
"excluded",
|
|
12517
|
+
"total"
|
|
12518
|
+
]),
|
|
12519
|
+
/** What a `value` publish does when nobody is included. Counts ignore this. */
|
|
12520
|
+
empty: _enum([
|
|
12521
|
+
"null",
|
|
12522
|
+
"omit",
|
|
12523
|
+
"offline"
|
|
12524
|
+
])
|
|
12525
|
+
})
|
|
12420
12526
|
]);
|
|
12421
12527
|
var CompositionCommandTargetSchema = discriminatedUnion("kind", [object({
|
|
12422
12528
|
kind: literal("forward"),
|
|
@@ -12462,7 +12568,13 @@ var CompositionSchema = object({
|
|
|
12462
12568
|
kind: literal("existing"),
|
|
12463
12569
|
device: CompositionSourceRefSchema
|
|
12464
12570
|
})]),
|
|
12465
|
-
features: array(CompositionFeatureSchema).min(1).max(16)
|
|
12571
|
+
features: array(CompositionFeatureSchema).min(1).max(16),
|
|
12572
|
+
/**
|
|
12573
|
+
* Present when the block is a helper template. Absent on a free
|
|
12574
|
+
* composition (the room example, device 4603). The editor reads this,
|
|
12575
|
+
* never the compiled features.
|
|
12576
|
+
*/
|
|
12577
|
+
helper: HelperSpecSchema.optional()
|
|
12466
12578
|
}).superRefine((composition, ctx) => {
|
|
12467
12579
|
const seen = /* @__PURE__ */ new Set();
|
|
12468
12580
|
composition.features.forEach((feature, index) => {
|
|
@@ -18670,7 +18782,11 @@ var CompositionProblemSchema = object({
|
|
|
18670
18782
|
"item-field-reserved",
|
|
18671
18783
|
"target-missing",
|
|
18672
18784
|
"target-unreadable",
|
|
18673
|
-
"not-replaceable"
|
|
18785
|
+
"not-replaceable",
|
|
18786
|
+
"native-capability-replace",
|
|
18787
|
+
"mixed-quantity",
|
|
18788
|
+
"helper-mismatch",
|
|
18789
|
+
"member-constraint"
|
|
18674
18790
|
]),
|
|
18675
18791
|
path: string(),
|
|
18676
18792
|
message: string()
|
|
@@ -18691,7 +18807,8 @@ var CompositionUnavailableModeSchema = _enum([
|
|
|
18691
18807
|
"null",
|
|
18692
18808
|
"offline",
|
|
18693
18809
|
"unknown",
|
|
18694
|
-
"release"
|
|
18810
|
+
"release",
|
|
18811
|
+
"omit"
|
|
18695
18812
|
]);
|
|
18696
18813
|
/**
|
|
18697
18814
|
* `derived` reads a source · `clock` reads only `now`, recomputed when a sibling
|
|
@@ -18728,9 +18845,11 @@ var CompositionFieldPlanSchema = object({
|
|
|
18728
18845
|
reads: array(CompositionFieldReadSchema)
|
|
18729
18846
|
});
|
|
18730
18847
|
/**
|
|
18731
|
-
* What a feature does to its target (D663): `new` builds a capability on a
|
|
18732
|
-
* device; on an existing device it `add`s a capability the device lacks
|
|
18733
|
-
*
|
|
18848
|
+
* What a feature does to its target (D663, D944): `new` builds a capability on a
|
|
18849
|
+
* new device; on an existing device it `add`s a capability the device lacks.
|
|
18850
|
+
* Replacing a capability the device already serves is refused
|
|
18851
|
+
* (`native-capability-replace`), not planned. `replace` remains on the claim
|
|
18852
|
+
* wire for a claim the hub already holds.
|
|
18734
18853
|
*/
|
|
18735
18854
|
var CompositionFeatureModeSchema = _enum([
|
|
18736
18855
|
"new",
|
|
@@ -18903,6 +19022,275 @@ Object.freeze({
|
|
|
18903
19022
|
result: ["number", "null"]
|
|
18904
19023
|
}
|
|
18905
19024
|
});
|
|
19025
|
+
/**
|
|
19026
|
+
* One catalog row per base reading a group helper can build (D944 §3).
|
|
19027
|
+
* Data, not a form default written into the block.
|
|
19028
|
+
*/
|
|
19029
|
+
var NOW = {
|
|
19030
|
+
fieldPath: "lastFetchedAt",
|
|
19031
|
+
expr: "now"
|
|
19032
|
+
};
|
|
19033
|
+
var CHANGED = {
|
|
19034
|
+
fieldPath: "lastChangedAt",
|
|
19035
|
+
expr: "now"
|
|
19036
|
+
};
|
|
19037
|
+
function numeric(input) {
|
|
19038
|
+
return {
|
|
19039
|
+
...input,
|
|
19040
|
+
family: "numeric",
|
|
19041
|
+
deviceType: DeviceType.Sensor,
|
|
19042
|
+
memberDeviceType: DeviceType.Sensor,
|
|
19043
|
+
commandCaps: [],
|
|
19044
|
+
baseUnit: baseUnitOf(input.quantity),
|
|
19045
|
+
aggregates: NUMERIC_AGGREGATES,
|
|
19046
|
+
accept: [{
|
|
19047
|
+
cap: input.outputCap,
|
|
19048
|
+
fieldPath: input.outputField
|
|
19049
|
+
}]
|
|
19050
|
+
};
|
|
19051
|
+
}
|
|
19052
|
+
function binary(input) {
|
|
19053
|
+
return {
|
|
19054
|
+
...input,
|
|
19055
|
+
family: "binary",
|
|
19056
|
+
deviceType: DeviceType.Sensor,
|
|
19057
|
+
memberDeviceType: DeviceType.Sensor,
|
|
19058
|
+
commandCaps: [],
|
|
19059
|
+
quantity: "none",
|
|
19060
|
+
baseUnit: void 0,
|
|
19061
|
+
aggregates: BINARY_AGGREGATES,
|
|
19062
|
+
empty: "offline"
|
|
19063
|
+
};
|
|
19064
|
+
}
|
|
19065
|
+
var GROUP_TEMPLATES = [
|
|
19066
|
+
numeric({
|
|
19067
|
+
id: "temperature",
|
|
19068
|
+
summary: "Mean, median, min, max or sum of temperatures. Offline and unknown members are left out, never read as 0 °C.",
|
|
19069
|
+
role: DeviceRole.TemperatureSensor,
|
|
19070
|
+
outputCap: "temperature-sensor",
|
|
19071
|
+
outputField: "celsius",
|
|
19072
|
+
quantity: "temperature",
|
|
19073
|
+
defaultAggregate: "mean",
|
|
19074
|
+
empty: "null",
|
|
19075
|
+
companions: [NOW]
|
|
19076
|
+
}),
|
|
19077
|
+
numeric({
|
|
19078
|
+
id: "humidity",
|
|
19079
|
+
summary: "Humidity in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
19080
|
+
role: DeviceRole.HumiditySensor,
|
|
19081
|
+
outputCap: "humidity-sensor",
|
|
19082
|
+
outputField: "percent",
|
|
19083
|
+
quantity: "humidity",
|
|
19084
|
+
defaultAggregate: "mean",
|
|
19085
|
+
empty: "null",
|
|
19086
|
+
companions: [NOW]
|
|
19087
|
+
}),
|
|
19088
|
+
numeric({
|
|
19089
|
+
id: "pressure",
|
|
19090
|
+
summary: "Pressure in hectopascals. Offline and unknown members are left out, never read as 0 hPa.",
|
|
19091
|
+
role: DeviceRole.PressureSensor,
|
|
19092
|
+
outputCap: "pressure-sensor",
|
|
19093
|
+
outputField: "hpa",
|
|
19094
|
+
quantity: "pressure",
|
|
19095
|
+
defaultAggregate: "mean",
|
|
19096
|
+
empty: "null",
|
|
19097
|
+
companions: [NOW]
|
|
19098
|
+
}),
|
|
19099
|
+
numeric({
|
|
19100
|
+
id: "illuminance",
|
|
19101
|
+
summary: "Illuminance in lux. Offline and unknown members are left out, never read as 0 lx.",
|
|
19102
|
+
role: DeviceRole.AmbientLightSensor,
|
|
19103
|
+
outputCap: "ambient-light-sensor",
|
|
19104
|
+
outputField: "lux",
|
|
19105
|
+
quantity: "illuminance",
|
|
19106
|
+
defaultAggregate: "mean",
|
|
19107
|
+
empty: "null",
|
|
19108
|
+
companions: [NOW]
|
|
19109
|
+
}),
|
|
19110
|
+
numeric({
|
|
19111
|
+
id: "power",
|
|
19112
|
+
summary: "Power in watts, summed by default. Nobody reporting omits the key rather than writing 0 W.",
|
|
19113
|
+
role: DeviceRole.PowerSensor,
|
|
19114
|
+
outputCap: "power-meter",
|
|
19115
|
+
outputField: "watts",
|
|
19116
|
+
quantity: "power",
|
|
19117
|
+
defaultAggregate: "sum",
|
|
19118
|
+
empty: "omit",
|
|
19119
|
+
companions: [NOW]
|
|
19120
|
+
}),
|
|
19121
|
+
numeric({
|
|
19122
|
+
id: "energy",
|
|
19123
|
+
summary: "Energy in kilowatt-hours, summed by default. Nobody reporting omits the key rather than writing 0 kWh.",
|
|
19124
|
+
role: DeviceRole.EnergySensor,
|
|
19125
|
+
outputCap: "power-meter",
|
|
19126
|
+
outputField: "kwhTotal",
|
|
19127
|
+
quantity: "energy",
|
|
19128
|
+
defaultAggregate: "sum",
|
|
19129
|
+
empty: "omit",
|
|
19130
|
+
companions: [NOW]
|
|
19131
|
+
}),
|
|
19132
|
+
numeric({
|
|
19133
|
+
id: "battery",
|
|
19134
|
+
summary: "Battery charge in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
19135
|
+
role: DeviceRole.BatterySensor,
|
|
19136
|
+
outputCap: "battery",
|
|
19137
|
+
outputField: "percentage",
|
|
19138
|
+
quantity: "percentage",
|
|
19139
|
+
defaultAggregate: "mean",
|
|
19140
|
+
empty: "null",
|
|
19141
|
+
companions: [
|
|
19142
|
+
{
|
|
19143
|
+
fieldPath: "charging",
|
|
19144
|
+
expr: "\"unknown\""
|
|
19145
|
+
},
|
|
19146
|
+
{
|
|
19147
|
+
fieldPath: "sleeping",
|
|
19148
|
+
expr: "false"
|
|
19149
|
+
},
|
|
19150
|
+
{
|
|
19151
|
+
fieldPath: "lastUpdated",
|
|
19152
|
+
expr: "now"
|
|
19153
|
+
}
|
|
19154
|
+
]
|
|
19155
|
+
}),
|
|
19156
|
+
numeric({
|
|
19157
|
+
id: "numeric",
|
|
19158
|
+
summary: "A numeric reading in the members’ shared quantity. Mixed quantities are refused. Nobody reporting publishes null, not 0.",
|
|
19159
|
+
role: DeviceRole.NumericSensor,
|
|
19160
|
+
outputCap: "numeric-sensor",
|
|
19161
|
+
outputField: "value",
|
|
19162
|
+
quantity: "device",
|
|
19163
|
+
defaultAggregate: "mean",
|
|
19164
|
+
empty: "null",
|
|
19165
|
+
companions: [NOW]
|
|
19166
|
+
}),
|
|
19167
|
+
binary({
|
|
19168
|
+
id: "motion",
|
|
19169
|
+
summary: "Any or all motion. Offline and unknown members are left out, never read as off. Nobody reporting takes the device offline.",
|
|
19170
|
+
role: DeviceRole.MotionSensor,
|
|
19171
|
+
outputCap: "motion",
|
|
19172
|
+
outputField: "detected",
|
|
19173
|
+
defaultAggregate: "any",
|
|
19174
|
+
accept: [{
|
|
19175
|
+
cap: "motion",
|
|
19176
|
+
fieldPath: "detected"
|
|
19177
|
+
}],
|
|
19178
|
+
companions: [{
|
|
19179
|
+
fieldPath: "lastDetectedAt",
|
|
19180
|
+
expr: "null"
|
|
19181
|
+
}, {
|
|
19182
|
+
fieldPath: "autoClearAfterMs",
|
|
19183
|
+
expr: "null"
|
|
19184
|
+
}]
|
|
19185
|
+
}),
|
|
19186
|
+
binary({
|
|
19187
|
+
id: "contact",
|
|
19188
|
+
summary: "Any or all open contacts. Offline and unknown members are left out, never read as closed.",
|
|
19189
|
+
role: DeviceRole.ContactSensor,
|
|
19190
|
+
outputCap: "contact",
|
|
19191
|
+
outputField: "entryOpen",
|
|
19192
|
+
defaultAggregate: "any",
|
|
19193
|
+
accept: [{
|
|
19194
|
+
cap: "contact",
|
|
19195
|
+
fieldPath: "entryOpen"
|
|
19196
|
+
}],
|
|
19197
|
+
companions: [CHANGED]
|
|
19198
|
+
}),
|
|
19199
|
+
binary({
|
|
19200
|
+
id: "leak",
|
|
19201
|
+
summary: "Any or all leak detections. Offline and unknown members are left out, never read as dry.",
|
|
19202
|
+
role: DeviceRole.LeakSensor,
|
|
19203
|
+
outputCap: "flood",
|
|
19204
|
+
outputField: "flooded",
|
|
19205
|
+
defaultAggregate: "any",
|
|
19206
|
+
accept: [{
|
|
19207
|
+
cap: "flood",
|
|
19208
|
+
fieldPath: "flooded"
|
|
19209
|
+
}],
|
|
19210
|
+
companions: [CHANGED]
|
|
19211
|
+
}),
|
|
19212
|
+
binary({
|
|
19213
|
+
id: "smoke",
|
|
19214
|
+
summary: "Any or all smoke detections. Offline and unknown members are left out, never read as clear.",
|
|
19215
|
+
role: DeviceRole.SmokeSensor,
|
|
19216
|
+
outputCap: "smoke",
|
|
19217
|
+
outputField: "detected",
|
|
19218
|
+
defaultAggregate: "any",
|
|
19219
|
+
accept: [{
|
|
19220
|
+
cap: "smoke",
|
|
19221
|
+
fieldPath: "detected"
|
|
19222
|
+
}],
|
|
19223
|
+
companions: [CHANGED]
|
|
19224
|
+
}),
|
|
19225
|
+
binary({
|
|
19226
|
+
id: "occupancy",
|
|
19227
|
+
summary: "Any or all of motion or binary sensors, published as a binary. Presence zones are not aggregated. Nobody reporting is offline, not off.",
|
|
19228
|
+
role: DeviceRole.BinarySensor,
|
|
19229
|
+
outputCap: "binary",
|
|
19230
|
+
outputField: "on",
|
|
19231
|
+
defaultAggregate: "any",
|
|
19232
|
+
accept: [{
|
|
19233
|
+
cap: "motion",
|
|
19234
|
+
fieldPath: "detected"
|
|
19235
|
+
}, {
|
|
19236
|
+
cap: "binary",
|
|
19237
|
+
fieldPath: "on"
|
|
19238
|
+
}],
|
|
19239
|
+
companions: [CHANGED]
|
|
19240
|
+
}),
|
|
19241
|
+
binary({
|
|
19242
|
+
id: "binary",
|
|
19243
|
+
summary: "Any or all generic binary sensors. Offline and unknown members are left out, never read as off.",
|
|
19244
|
+
role: DeviceRole.BinarySensor,
|
|
19245
|
+
outputCap: "binary",
|
|
19246
|
+
outputField: "on",
|
|
19247
|
+
defaultAggregate: "any",
|
|
19248
|
+
accept: [{
|
|
19249
|
+
cap: "binary",
|
|
19250
|
+
fieldPath: "on"
|
|
19251
|
+
}],
|
|
19252
|
+
companions: [CHANGED]
|
|
19253
|
+
}),
|
|
19254
|
+
actuator({
|
|
19255
|
+
id: "switch",
|
|
19256
|
+
summary: "On when at least one switch is on, or when all of them are. Offline and unknown members are left out of that decision, never read as off, and still receive the command.",
|
|
19257
|
+
deviceType: DeviceType.Switch,
|
|
19258
|
+
outputCap: "switch",
|
|
19259
|
+
commandCaps: ["switch"]
|
|
19260
|
+
}),
|
|
19261
|
+
actuator({
|
|
19262
|
+
id: "light",
|
|
19263
|
+
summary: "On when at least one light is on, or when all of them are. Brightness and colour are offered only when every member has them. A command is not sent to a member that lacks it.",
|
|
19264
|
+
deviceType: DeviceType.Light,
|
|
19265
|
+
outputCap: "switch",
|
|
19266
|
+
commandCaps: [
|
|
19267
|
+
"switch",
|
|
19268
|
+
"brightness",
|
|
19269
|
+
"color"
|
|
19270
|
+
]
|
|
19271
|
+
})
|
|
19272
|
+
];
|
|
19273
|
+
function actuator(input) {
|
|
19274
|
+
return {
|
|
19275
|
+
...input,
|
|
19276
|
+
family: "actuator",
|
|
19277
|
+
role: void 0,
|
|
19278
|
+
memberDeviceType: input.deviceType,
|
|
19279
|
+
outputField: "on",
|
|
19280
|
+
quantity: "none",
|
|
19281
|
+
baseUnit: void 0,
|
|
19282
|
+
aggregates: BINARY_AGGREGATES,
|
|
19283
|
+
defaultAggregate: "any",
|
|
19284
|
+
empty: "offline",
|
|
19285
|
+
accept: [{
|
|
19286
|
+
cap: "switch",
|
|
19287
|
+
fieldPath: "on"
|
|
19288
|
+
}],
|
|
19289
|
+
companions: [CHANGED]
|
|
19290
|
+
};
|
|
19291
|
+
}
|
|
19292
|
+
new Map(GROUP_TEMPLATES.map((template) => [template.id, template]));
|
|
19293
|
+
DeviceFeature.LightColorRgb, DeviceFeature.LightColorHsv, DeviceFeature.LightColorMired;
|
|
18906
19294
|
`${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
|
|
18907
19295
|
/**
|
|
18908
19296
|
* What a composition may BUILD on a device type (G2, D676): the caps a new
|
|
@@ -20616,12 +21004,12 @@ method(object({ deviceId: number().int().nonnegative() }), DeviceAdminLinkSchema
|
|
|
20616
21004
|
* providers detect renames by matching `uniqueId` and patch `id`
|
|
20617
21005
|
* in-place so dispatch keeps working.
|
|
20618
21006
|
*
|
|
20619
|
-
* **
|
|
20620
|
-
*
|
|
20621
|
-
*
|
|
20622
|
-
*
|
|
20623
|
-
* (`ha-domain-mapping`)
|
|
20624
|
-
* stored after that point.
|
|
21007
|
+
* **Display unit and precision are NOT stored here.** They are a read-time
|
|
21008
|
+
* preference (D944). A polymorphic reading stores its `quantity` here once,
|
|
21009
|
+
* at adopt, and a date/time value stores `dateTimeShape` the same way —
|
|
21010
|
+
* neither is repeated on each sample. The `device_class` tag is an
|
|
21011
|
+
* HA-specific input consumed at the discovery boundary (`ha-domain-mapping`)
|
|
21012
|
+
* to derive the CamStack `DeviceRole`; it is never stored after that point.
|
|
20625
21013
|
*
|
|
20626
21014
|
* The `raw` escape hatch carries provider-specific attributes that don't
|
|
20627
21015
|
* fit the structured slots (HA `attributes` whitelist, Reolink `deviceCache`
|
|
@@ -20635,6 +21023,14 @@ var SourceInfoSchema = object({
|
|
|
20635
21023
|
/** Immutable upstream identifier when available (HA `unique_id`, … ).
|
|
20636
21024
|
* Used to detect rename when `id` changes. */
|
|
20637
21025
|
uniqueId: string().optional(),
|
|
21026
|
+
/** Quantity of a polymorphic reading, written once at adopt (D944). */
|
|
21027
|
+
quantity: ReadingQuantitySchema.optional(),
|
|
21028
|
+
/** Date / time / datetime shape of a string reading, written once at adopt. */
|
|
21029
|
+
dateTimeShape: _enum([
|
|
21030
|
+
"date",
|
|
21031
|
+
"time",
|
|
21032
|
+
"datetime"
|
|
21033
|
+
]).optional(),
|
|
20638
21034
|
/** Provider-specific extras that don't fit the structured slots.
|
|
20639
21035
|
* Whitelist what goes here per provider — do NOT dump entire HA
|
|
20640
21036
|
* attribute blobs (would explode the meta JSON column). */
|
|
@@ -41756,7 +42152,8 @@ method(object({
|
|
|
41756
42152
|
"enum"
|
|
41757
42153
|
]),
|
|
41758
42154
|
enumValues: array(string()).optional(),
|
|
41759
|
-
item: boolean().optional()
|
|
42155
|
+
item: boolean().optional(),
|
|
42156
|
+
quantity: ReadingQuantitySchema.optional()
|
|
41760
42157
|
})).readonly(),
|
|
41761
42158
|
itemArray: object({
|
|
41762
42159
|
path: string(),
|
|
@@ -45600,8 +45997,8 @@ var MaskPolygonShapeSchema = object({
|
|
|
45600
45997
|
/** Boolean cell grid — row-major, length === gridWidth*gridHeight. */
|
|
45601
45998
|
var MaskGridShapeSchema = object({
|
|
45602
45999
|
kind: literal("grid"),
|
|
45603
|
-
gridWidth: number(),
|
|
45604
|
-
gridHeight: number(),
|
|
46000
|
+
gridWidth: number().meta(readingMeta("none")),
|
|
46001
|
+
gridHeight: number().meta(readingMeta("none")),
|
|
45605
46002
|
cells: array(boolean())
|
|
45606
46003
|
});
|
|
45607
46004
|
discriminatedUnion("kind", [
|
|
@@ -45713,6 +46110,8 @@ var NcSystemEventKindSchema = _enum([
|
|
|
45713
46110
|
"detection-blind",
|
|
45714
46111
|
"motion-noisy",
|
|
45715
46112
|
"motion-calm",
|
|
46113
|
+
"package-llm-silent",
|
|
46114
|
+
"package-llm-answered",
|
|
45716
46115
|
"recording-stalled",
|
|
45717
46116
|
"recording-healthy",
|
|
45718
46117
|
"recording-degraded",
|
|
@@ -56804,6 +57203,28 @@ var PackageVersionInfoSchema = object({
|
|
|
56804
57203
|
deprecated: string().optional(),
|
|
56805
57204
|
distTags: array(string()).readonly()
|
|
56806
57205
|
});
|
|
57206
|
+
/**
|
|
57207
|
+
* One published document. `ok` is markdown from the registry. `missing` means
|
|
57208
|
+
* the registry answered and the file was not there. `error` is a registry or
|
|
57209
|
+
* tarball failure — never an empty string standing in for either.
|
|
57210
|
+
*/
|
|
57211
|
+
var PackageDocBodySchema = discriminatedUnion("status", [
|
|
57212
|
+
object({
|
|
57213
|
+
status: literal("ok"),
|
|
57214
|
+
markdown: string()
|
|
57215
|
+
}),
|
|
57216
|
+
object({ status: literal("missing") }),
|
|
57217
|
+
object({
|
|
57218
|
+
status: literal("error"),
|
|
57219
|
+
message: string()
|
|
57220
|
+
})
|
|
57221
|
+
]);
|
|
57222
|
+
var PackageDocsSchema = object({
|
|
57223
|
+
name: string(),
|
|
57224
|
+
version: string(),
|
|
57225
|
+
readme: PackageDocBodySchema,
|
|
57226
|
+
changelog: PackageDocBodySchema
|
|
57227
|
+
});
|
|
56807
57228
|
var SearchResultSchema = object({
|
|
56808
57229
|
name: string(),
|
|
56809
57230
|
version: string(),
|
|
@@ -57022,7 +57443,10 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
|
|
|
57022
57443
|
}), object({ success: literal(true) }), {
|
|
57023
57444
|
kind: "mutation",
|
|
57024
57445
|
auth: "admin"
|
|
57025
|
-
}), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({
|
|
57446
|
+
}), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({
|
|
57447
|
+
name: string().min(1),
|
|
57448
|
+
version: string().min(1).optional()
|
|
57449
|
+
}), PackageDocsSchema, { auth: "admin" }), method(object({ addonId: string() }), RestartAddonResultSchema, {
|
|
57026
57450
|
kind: "mutation",
|
|
57027
57451
|
auth: "admin"
|
|
57028
57452
|
}), method(object({ packageName: string() }), object({ success: literal(true) }), {
|
|
@@ -57081,27 +57505,17 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
|
|
|
57081
57505
|
*/
|
|
57082
57506
|
var AirQualitySensorStatusSchema = object({
|
|
57083
57507
|
/** Carbon dioxide concentration in ppm. */
|
|
57084
|
-
co2Ppm: number().min(0).optional(),
|
|
57508
|
+
co2Ppm: number().min(0).optional().meta(readingMeta("concentration-volume")),
|
|
57085
57509
|
/** Total volatile organic compounds in ppb. */
|
|
57086
|
-
vocPpb: number().min(0).optional(),
|
|
57510
|
+
vocPpb: number().min(0).optional().meta(readingMeta("concentration-ppb")),
|
|
57087
57511
|
/** Particulate matter ≤ 2.5 μm in µg/m³. */
|
|
57088
|
-
pm25: number().min(0).optional(),
|
|
57512
|
+
pm25: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
57089
57513
|
/** Particulate matter ≤ 10 μm in µg/m³. */
|
|
57090
|
-
pm10: number().min(0).optional(),
|
|
57514
|
+
pm10: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
57091
57515
|
/** Composite AQI value (typically 0..500). */
|
|
57092
|
-
aqi: number().optional(),
|
|
57516
|
+
aqi: number().optional().meta(readingMeta("index")),
|
|
57093
57517
|
/** Ms epoch when the slice was last updated. */
|
|
57094
|
-
lastFetchedAt: number()
|
|
57095
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
57096
|
-
* `attributes.unit_of_measurement` → 'ppm' / 'ppb' / 'µg/m³'). Each
|
|
57097
|
-
* upstream `sensor.*` entity surfaces ONE device_class, so one unit
|
|
57098
|
-
* per slice is unambiguous. */
|
|
57099
|
-
unit: string().optional(),
|
|
57100
|
-
/** Suggested decimal places for numeric display.
|
|
57101
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
57102
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
57103
|
-
* auto-formatting when absent. */
|
|
57104
|
-
precision: number().int().min(0).max(10).optional()
|
|
57518
|
+
lastFetchedAt: number()
|
|
57105
57519
|
});
|
|
57106
57520
|
var airQualitySensorCapability = {
|
|
57107
57521
|
name: "air-quality-sensor",
|
|
@@ -57138,12 +57552,12 @@ var airQualitySensorCapability = {
|
|
|
57138
57552
|
},
|
|
57139
57553
|
pm25: {
|
|
57140
57554
|
kind: "gauge",
|
|
57141
|
-
unit: "
|
|
57555
|
+
unit: "µg/m³",
|
|
57142
57556
|
deadband: 1
|
|
57143
57557
|
},
|
|
57144
57558
|
pm10: {
|
|
57145
57559
|
kind: "gauge",
|
|
57146
|
-
unit: "
|
|
57560
|
+
unit: "µg/m³",
|
|
57147
57561
|
deadband: 1
|
|
57148
57562
|
},
|
|
57149
57563
|
aqi: {
|
|
@@ -57161,22 +57575,13 @@ var airQualitySensorCapability = {
|
|
|
57161
57575
|
* entries with `device_class: illuminance`.
|
|
57162
57576
|
*/
|
|
57163
57577
|
var AmbientLightSensorStatusSchema = object({
|
|
57164
|
-
/** Current illuminance in lux (lx). */
|
|
57165
|
-
lux: number().min(0).meta({
|
|
57166
|
-
|
|
57578
|
+
/** Current illuminance in lux (lx). `null` when the sample was refused (D393). */
|
|
57579
|
+
lux: number().min(0).nullable().meta(readingMeta("illuminance", {
|
|
57580
|
+
precision: 0,
|
|
57167
57581
|
label: "Illuminance"
|
|
57168
|
-
}),
|
|
57582
|
+
})),
|
|
57169
57583
|
/** Ms epoch when the slice was last updated. */
|
|
57170
|
-
lastFetchedAt: number()
|
|
57171
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
57172
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
57173
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
57174
|
-
unit: string().optional(),
|
|
57175
|
-
/** Suggested decimal places for numeric display.
|
|
57176
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
57177
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
57178
|
-
* auto-formatting when absent. */
|
|
57179
|
-
precision: number().int().min(0).max(10).optional()
|
|
57584
|
+
lastFetchedAt: number()
|
|
57180
57585
|
});
|
|
57181
57586
|
var ambientLightSensorCapability = {
|
|
57182
57587
|
name: "ambient-light-sensor",
|
|
@@ -57208,12 +57613,7 @@ var ambientLightSensorCapability = {
|
|
|
57208
57613
|
} } },
|
|
57209
57614
|
/** Clock fields: written, but excluded from the compare that decides
|
|
57210
57615
|
* whether persisting is worth a SQLite commit. */
|
|
57211
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
57212
|
-
customize: {
|
|
57213
|
-
version: 1,
|
|
57214
|
-
advanced: "derive",
|
|
57215
|
-
targets: []
|
|
57216
|
-
}
|
|
57616
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
57217
57617
|
};
|
|
57218
57618
|
/**
|
|
57219
57619
|
* Per-class audio metrics aggregated over a sliding window.
|
|
@@ -57440,10 +57840,7 @@ var BatteryStatusSchema = object({
|
|
|
57440
57840
|
* Consumers must SKIP a null rather than coerce it — `battery-band` already
|
|
57441
57841
|
* declines to band a non-finite reading, which is the correct shape.
|
|
57442
57842
|
*/
|
|
57443
|
-
percentage: number().min(0).max(100).nullable().meta({
|
|
57444
|
-
unit: "%",
|
|
57445
|
-
label: "Charge"
|
|
57446
|
-
}),
|
|
57843
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage", { label: "Charge" })),
|
|
57447
57844
|
/**
|
|
57448
57845
|
* Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
|
|
57449
57846
|
* Reolink-specific for the Solar Panel 2 accessory (will become
|
|
@@ -57470,7 +57867,14 @@ var BatteryStatusSchema = object({
|
|
|
57470
57867
|
*/
|
|
57471
57868
|
sleeping: boolean().meta({ label: "Sleeping" }),
|
|
57472
57869
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
57473
|
-
lastUpdated: number(),
|
|
57870
|
+
lastUpdated: number().meta(readingMeta("none")),
|
|
57871
|
+
/**
|
|
57872
|
+
* Battery voltage in volts, for a cell the firmware reports as voltage
|
|
57873
|
+
* rather than a percentage (Ecowitt capacitor packs). Absent on cameras
|
|
57874
|
+
* that only report charge. A second reading on this cap, not a second
|
|
57875
|
+
* `numeric-sensor` on the same device.
|
|
57876
|
+
*/
|
|
57877
|
+
volts: number().nullable().optional().meta(readingMeta("voltage", { label: "Voltage" })),
|
|
57474
57878
|
/**
|
|
57475
57879
|
* Ms epoch of the last time the device PROVED it was reachable — a
|
|
57476
57880
|
* completed firmware round-trip, an observed wake, or an inbound push
|
|
@@ -57522,7 +57926,6 @@ var BATTERY_DEVICE_TYPES = [
|
|
|
57522
57926
|
/** Generic Customize target for the percentage reading (D936). */
|
|
57523
57927
|
var batteryCustomize = {
|
|
57524
57928
|
version: 1,
|
|
57525
|
-
advanced: "derive",
|
|
57526
57929
|
targets: [{
|
|
57527
57930
|
id: "percentage",
|
|
57528
57931
|
cardinality: "scalar",
|
|
@@ -57531,7 +57934,7 @@ var batteryCustomize = {
|
|
|
57531
57934
|
stateField: "percentage"
|
|
57532
57935
|
},
|
|
57533
57936
|
deviceTypes: BATTERY_DEVICE_TYPES,
|
|
57534
|
-
apply: "add
|
|
57937
|
+
apply: "add",
|
|
57535
57938
|
path: "percentage",
|
|
57536
57939
|
sources: [{
|
|
57537
57940
|
kind: "field",
|
|
@@ -57652,10 +58055,16 @@ onStatusChanged: { data: object({
|
|
|
57652
58055
|
/**
|
|
57653
58056
|
* History (D850): recorded series. The generic capture replaces the `battery` series of `pipeline-analytics:stats-5m`.
|
|
57654
58057
|
*/
|
|
57655
|
-
history: { fields: {
|
|
57656
|
-
|
|
57657
|
-
|
|
57658
|
-
|
|
58058
|
+
history: { fields: {
|
|
58059
|
+
percentage: {
|
|
58060
|
+
kind: "gauge",
|
|
58061
|
+
unit: "%"
|
|
58062
|
+
},
|
|
58063
|
+
volts: {
|
|
58064
|
+
kind: "gauge",
|
|
58065
|
+
unit: "V"
|
|
58066
|
+
}
|
|
58067
|
+
} },
|
|
57659
58068
|
customize: batteryCustomize,
|
|
57660
58069
|
/** Clock fields: written, but excluded from the compare that decides
|
|
57661
58070
|
* whether persisting is worth a SQLite commit. */
|
|
@@ -57702,12 +58111,7 @@ var binaryCapability = {
|
|
|
57702
58111
|
history: { fields: { on: { kind: "boolean" } } },
|
|
57703
58112
|
/** Clock fields: written, but excluded from the compare that decides
|
|
57704
58113
|
* whether persisting is worth a SQLite commit. */
|
|
57705
|
-
volatileStateFields: ["lastChangedAt"]
|
|
57706
|
-
customize: {
|
|
57707
|
-
version: 1,
|
|
57708
|
-
advanced: "derive",
|
|
57709
|
-
targets: []
|
|
57710
|
-
}
|
|
58114
|
+
volatileStateFields: ["lastChangedAt"]
|
|
57711
58115
|
};
|
|
57712
58116
|
/**
|
|
57713
58117
|
* Dimmable-light brightness control. Co-exists with `switch` on the
|
|
@@ -57723,7 +58127,7 @@ var binaryCapability = {
|
|
|
57723
58127
|
*/
|
|
57724
58128
|
var BrightnessStatusSchema = object({
|
|
57725
58129
|
/** Current level as 0..100 inclusive. Firmware-reported. */
|
|
57726
|
-
percentage: number().min(0).max(100),
|
|
58130
|
+
percentage: number().min(0).max(100).meta(readingMeta("percentage")),
|
|
57727
58131
|
/** Ms epoch of the last operator-driven change. Useful for UI freshness. */
|
|
57728
58132
|
lastChangedAt: number()
|
|
57729
58133
|
});
|
|
@@ -58177,21 +58581,21 @@ var ClimateControlStatusSchema = object({
|
|
|
58177
58581
|
/** Single setpoint in Celsius. Used by single-target modes
|
|
58178
58582
|
* (heat / cool / dry). Null when the device is in a range mode
|
|
58179
58583
|
* (`heat_cool`) or has no setpoint at all (`fan_only`/`off`). */
|
|
58180
|
-
target: number().nullable(),
|
|
58584
|
+
target: number().nullable().meta(readingMeta("temperature")),
|
|
58181
58585
|
/** Upper bound of the dual setpoint in Celsius. Populated only
|
|
58182
58586
|
* in `heat_cool` mode. */
|
|
58183
|
-
targetHigh: number().nullable(),
|
|
58587
|
+
targetHigh: number().nullable().meta(readingMeta("temperature")),
|
|
58184
58588
|
/** Lower bound of the dual setpoint in Celsius. Populated only
|
|
58185
58589
|
* in `heat_cool` mode. */
|
|
58186
|
-
targetLow: number().nullable(),
|
|
58590
|
+
targetLow: number().nullable().meta(readingMeta("temperature")),
|
|
58187
58591
|
/** Target relative humidity (0..100). Null when the device has no
|
|
58188
58592
|
* humidity control. */
|
|
58189
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
58593
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
58190
58594
|
/** Current measured temperature in Celsius. Read-only — pushed by
|
|
58191
58595
|
* the device's internal sensor. */
|
|
58192
|
-
currentTemp: number().nullable(),
|
|
58596
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
58193
58597
|
/** Current measured relative humidity (0..100). Read-only. */
|
|
58194
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
58598
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
58195
58599
|
/** Vertical louver swing on/off. Null when the device has no vertical
|
|
58196
58600
|
* swing surface (gate with `DeviceFeature.ClimateSwingVertical`). */
|
|
58197
58601
|
swingVertical: boolean().nullable(),
|
|
@@ -58199,11 +58603,11 @@ var ClimateControlStatusSchema = object({
|
|
|
58199
58603
|
* horizontal swing surface (gate with `DeviceFeature.ClimateSwingHorizontal`). */
|
|
58200
58604
|
swingHorizontal: boolean().nullable(),
|
|
58201
58605
|
/** Lowest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
58202
|
-
minTemp: number().nullable().optional(),
|
|
58606
|
+
minTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
58203
58607
|
/** Highest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
58204
|
-
maxTemp: number().nullable().optional(),
|
|
58608
|
+
maxTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
58205
58609
|
/** Setpoint granularity, Celsius (0.5, 1). Absent / null = not reported. */
|
|
58206
|
-
tempStep: number().positive().nullable().optional(),
|
|
58610
|
+
tempStep: number().positive().nullable().optional().meta(readingMeta("temperature")),
|
|
58207
58611
|
/** Ms epoch when the slice was last updated (push or command). */
|
|
58208
58612
|
lastFetchedAt: number()
|
|
58209
58613
|
});
|
|
@@ -58345,17 +58749,17 @@ var climateControlCapability = {
|
|
|
58345
58749
|
* modes to expose in the picker without a slice fetch.
|
|
58346
58750
|
*/
|
|
58347
58751
|
var RgbTripletSchema = object({
|
|
58348
|
-
r: number().int().min(0).max(255),
|
|
58349
|
-
g: number().int().min(0).max(255),
|
|
58350
|
-
b: number().int().min(0).max(255)
|
|
58752
|
+
r: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
58753
|
+
g: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
58754
|
+
b: number().int().min(0).max(255).meta(readingMeta("none"))
|
|
58351
58755
|
});
|
|
58352
58756
|
var HsvTripletSchema = object({
|
|
58353
58757
|
/** Hue in degrees, 0..360. */
|
|
58354
|
-
h: number().min(0).max(360),
|
|
58758
|
+
h: number().min(0).max(360).meta(readingMeta("none")),
|
|
58355
58759
|
/** Saturation as 0..100 inclusive. */
|
|
58356
|
-
s: number().min(0).max(100),
|
|
58760
|
+
s: number().min(0).max(100).meta(readingMeta("none")),
|
|
58357
58761
|
/** Value/brightness as 0..100 inclusive. */
|
|
58358
|
-
v: number().min(0).max(100)
|
|
58762
|
+
v: number().min(0).max(100).meta(readingMeta("none"))
|
|
58359
58763
|
});
|
|
58360
58764
|
var ColorInputSchema = discriminatedUnion("mode", [
|
|
58361
58765
|
object({
|
|
@@ -58384,7 +58788,7 @@ var ColorStatusSchema = object({
|
|
|
58384
58788
|
/** Populated when `mode === 'hsv'`. */
|
|
58385
58789
|
hsv: HsvTripletSchema.optional(),
|
|
58386
58790
|
/** Populated when `mode === 'mired'`. */
|
|
58387
|
-
mireds: number().int().optional(),
|
|
58791
|
+
mireds: number().int().optional().meta(readingMeta("colour-temperature")),
|
|
58388
58792
|
/** Ms epoch of the last operator-driven change. */
|
|
58389
58793
|
lastChangedAt: number()
|
|
58390
58794
|
});
|
|
@@ -58587,18 +58991,12 @@ _enum([
|
|
|
58587
58991
|
"empty",
|
|
58588
58992
|
"full"
|
|
58589
58993
|
]);
|
|
58590
|
-
/**
|
|
58591
|
-
|
|
58592
|
-
|
|
58593
|
-
"days",
|
|
58594
|
-
"hours",
|
|
58595
|
-
"cycles"
|
|
58596
|
-
]);
|
|
58597
|
-
/** Remaining life as a COUNT, not a percentage (the PetKit desiccant reports
|
|
58598
|
-
* days). `value` null = unknown (D393). */
|
|
58994
|
+
/** Whether `remaining.value` is a duration in seconds or a dimensionless count. */
|
|
58995
|
+
var ConsumableRemainingKindSchema = _enum(["duration", "count"]);
|
|
58996
|
+
/** Remaining life. `value` null = unknown (D393). Duration is seconds. */
|
|
58599
58997
|
var ConsumableRemainingSchema = object({
|
|
58600
|
-
value: number().min(0).nullable(),
|
|
58601
|
-
|
|
58998
|
+
value: number().min(0).nullable().meta(readingMeta("device")),
|
|
58999
|
+
kind: ConsumableRemainingKindSchema
|
|
58602
59000
|
});
|
|
58603
59001
|
/** A single consumable item. Either a continuous `level` (remaining
|
|
58604
59002
|
* life %, or fill % for a `supply` / `waste` item) or a discrete `status`
|
|
@@ -58611,7 +59009,7 @@ var ConsumableItemSchema = object({
|
|
|
58611
59009
|
/** Display name. */
|
|
58612
59010
|
label: string().min(1),
|
|
58613
59011
|
/** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
|
|
58614
|
-
level: number().min(0).max(100).nullable(),
|
|
59012
|
+
level: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58615
59013
|
/** The provider's discrete verdict when known (binary mode). */
|
|
58616
59014
|
status: ConsumableStatusSchema.nullable(),
|
|
58617
59015
|
/** What the item is — decides whether low or full is bad. Absent = `wear`. */
|
|
@@ -58693,8 +59091,8 @@ var consumablesCustomize = {
|
|
|
58693
59091
|
transforms: [{ kind: "identity" }]
|
|
58694
59092
|
}],
|
|
58695
59093
|
literals: [{
|
|
58696
|
-
path: "remaining.
|
|
58697
|
-
values: [...
|
|
59094
|
+
path: "remaining.kind",
|
|
59095
|
+
values: [...ConsumableRemainingKindSchema.options]
|
|
58698
59096
|
}]
|
|
58699
59097
|
},
|
|
58700
59098
|
{
|
|
@@ -58823,7 +59221,6 @@ reset: method(object({
|
|
|
58823
59221
|
},
|
|
58824
59222
|
"remaining.value": {
|
|
58825
59223
|
kind: "gauge",
|
|
58826
|
-
unitFrom: "remaining.unit",
|
|
58827
59224
|
deadband: 1,
|
|
58828
59225
|
displayName: "Remaining"
|
|
58829
59226
|
}
|
|
@@ -58893,10 +59290,9 @@ var contactCapability = {
|
|
|
58893
59290
|
* (empty array for the other kinds). It lives in the slice because
|
|
58894
59291
|
* HA `select.*` entities may update their options at runtime.
|
|
58895
59292
|
*
|
|
58896
|
-
*
|
|
58897
|
-
*
|
|
58898
|
-
*
|
|
58899
|
-
* push — consistent with `options` and the sensor-unit approach.
|
|
59293
|
+
* Numeric `min` / `max` / `step` live in the slice and share the device
|
|
59294
|
+
* quantity (`SourceInfo.quantity`, D944). Display precision is a read-time
|
|
59295
|
+
* preference. A datetime control's shape is `SourceInfo.dateTimeShape`.
|
|
58900
59296
|
*/
|
|
58901
59297
|
var ControlStatusSchema = object({
|
|
58902
59298
|
kind: _enum([
|
|
@@ -58908,39 +59304,17 @@ var ControlStatusSchema = object({
|
|
|
58908
59304
|
/** Current value. Numeric kind → number; select/text/datetime → string.
|
|
58909
59305
|
* Datetime values are ISO 8601 strings (full timestamp, date-only,
|
|
58910
59306
|
* or time-only — HA accepts all three forms). */
|
|
58911
|
-
value: union([number(), string()]),
|
|
59307
|
+
value: union([number().meta(readingMeta("device")), string()]),
|
|
58912
59308
|
/** Acceptable values when `kind === 'select'`. Empty for other kinds. */
|
|
58913
59309
|
options: array(string()),
|
|
58914
59310
|
/** Ms epoch when the slice was last updated. */
|
|
58915
59311
|
lastChangedAt: number(),
|
|
58916
|
-
/**
|
|
58917
|
-
|
|
58918
|
-
|
|
58919
|
-
|
|
58920
|
-
/**
|
|
58921
|
-
|
|
58922
|
-
min: number().optional(),
|
|
58923
|
-
/** Maximum allowed value. Populated live from HA `attributes.max`.
|
|
58924
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
58925
|
-
max: number().optional(),
|
|
58926
|
-
/** Step increment. Populated live from HA `attributes.step`.
|
|
58927
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
58928
|
-
step: number().optional(),
|
|
58929
|
-
/** Suggested decimal places for numeric display. Populated live from HA
|
|
58930
|
-
* `attributes.suggested_display_precision`, or derived from `step` when the
|
|
58931
|
-
* HA attribute is absent. Meaningful for `kind === 'numeric'`; absent for
|
|
58932
|
-
* other kinds. Falls back to auto-formatting when absent. */
|
|
58933
|
-
precision: number().int().min(0).max(10).optional(),
|
|
58934
|
-
/** Date-picker granularity for `kind === 'datetime'`. 'date' → date-only,
|
|
58935
|
-
* 'time' → time-only, 'datetime' → full timestamp. Absent for other kinds
|
|
58936
|
-
* (UI defaults to 'datetime'). Derived live from the device's HA domain
|
|
58937
|
-
* (date.* / time.* / datetime.*) or, for input_datetime, from the entity's
|
|
58938
|
-
* `has_date`/`has_time` attributes on each push. */
|
|
58939
|
-
format: _enum([
|
|
58940
|
-
"date",
|
|
58941
|
-
"time",
|
|
58942
|
-
"datetime"
|
|
58943
|
-
]).optional()
|
|
59312
|
+
/** Minimum allowed value, in the device quantity's base unit. */
|
|
59313
|
+
min: number().optional().meta(readingMeta("device")),
|
|
59314
|
+
/** Maximum allowed value, in the device quantity's base unit. */
|
|
59315
|
+
max: number().optional().meta(readingMeta("device")),
|
|
59316
|
+
/** Step increment, in the device quantity's base unit. */
|
|
59317
|
+
step: number().optional().meta(readingMeta("device"))
|
|
58944
59318
|
});
|
|
58945
59319
|
var ControlSetValueInputSchema = discriminatedUnion("kind", [
|
|
58946
59320
|
object({
|
|
@@ -59006,9 +59380,9 @@ var CoverStatusSchema = object({
|
|
|
59006
59380
|
]),
|
|
59007
59381
|
/** 0 = fully closed, 100 = fully open. Null when the device has
|
|
59008
59382
|
* no intermediate position surface. */
|
|
59009
|
-
position: number().min(0).max(100).nullable(),
|
|
59383
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59010
59384
|
/** 0 = closed slats, 100 = open slats. Null when no tilt support. */
|
|
59011
|
-
tiltPosition: number().min(0).max(100).nullable(),
|
|
59385
|
+
tiltPosition: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59012
59386
|
/** Ms epoch when the slice was last updated. */
|
|
59013
59387
|
lastChangedAt: number()
|
|
59014
59388
|
});
|
|
@@ -59111,9 +59485,9 @@ var NormalizedRangeSchema$1 = object({
|
|
|
59111
59485
|
var DayNightStatusSchema = object({
|
|
59112
59486
|
mode: DayNightModeSchema,
|
|
59113
59487
|
/** IR-cut trigger sensitivity, NORMALIZED 0–100 (higher = switches to night sooner). */
|
|
59114
|
-
sensitivity: number().optional(),
|
|
59488
|
+
sensitivity: number().optional().meta(readingMeta("none")),
|
|
59115
59489
|
/** Delay before the IR-cut filter flips, in seconds. */
|
|
59116
|
-
switchDelaySec: number().optional(),
|
|
59490
|
+
switchDelaySec: number().optional().meta(readingMeta("duration")),
|
|
59117
59491
|
lastFetchedAt: number()
|
|
59118
59492
|
});
|
|
59119
59493
|
/**
|
|
@@ -59331,11 +59705,11 @@ var DishwasherStatusSchema = object({
|
|
|
59331
59705
|
/** Feature keys of the programs the appliance currently offers — drives the UI selector. */
|
|
59332
59706
|
availablePrograms: array(string()),
|
|
59333
59707
|
/** Seconds remaining on the active cycle, or null when not running / not known. */
|
|
59334
|
-
remainingSeconds: number().int().nonnegative().nullable(),
|
|
59708
|
+
remainingSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
59335
59709
|
/** Seconds the delayed start is set to (time until the cycle starts), or null. */
|
|
59336
|
-
delayedStartSeconds: number().int().nonnegative().nullable(),
|
|
59710
|
+
delayedStartSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
59337
59711
|
/** Cycle completion 0..100, or null when not applicable. */
|
|
59338
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
59712
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59339
59713
|
/** True when the door is reported open; null when the door state is not known. */
|
|
59340
59714
|
doorOpen: boolean().nullable(),
|
|
59341
59715
|
/** True when the door is latched (locked) during a cycle; null when not reported. */
|
|
@@ -59359,7 +59733,7 @@ var DishwasherStatusSchema = object({
|
|
|
59359
59733
|
/** True while the machine-care (descaling / cleaning-program) reminder is raised; false when clear; null when not reported. */
|
|
59360
59734
|
machineCareDue: boolean().nullable(),
|
|
59361
59735
|
/** Program runs left before the machine-care reminder is due; null when the appliance does not say. */
|
|
59362
|
-
machineCareRemainingRuns: number().int().nonnegative().nullable(),
|
|
59736
|
+
machineCareRemainingRuns: number().int().nonnegative().nullable().meta(readingMeta("count")),
|
|
59363
59737
|
/** Option states: null when the appliance does not expose the option or has not said. */
|
|
59364
59738
|
halfLoad: boolean().nullable(),
|
|
59365
59739
|
hygienePlus: boolean().nullable(),
|
|
@@ -59374,7 +59748,7 @@ var DishwasherStatusSchema = object({
|
|
|
59374
59748
|
/** Feature keys of the events currently raised (salt low, rinse aid low, program finished, …). */
|
|
59375
59749
|
activeEvents: array(string()),
|
|
59376
59750
|
/** Numeric error code when the appliance reports one; null otherwise. */
|
|
59377
|
-
errorCode: number().nullable(),
|
|
59751
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
59378
59752
|
/** Name of the raised alert-level event while the appliance is in error; null otherwise. */
|
|
59379
59753
|
errorLabel: string().nullable(),
|
|
59380
59754
|
/** Ms epoch of the last value received from the appliance; 0 = never. */
|
|
@@ -59605,7 +59979,7 @@ var DoorbellStatusSchema = object({
|
|
|
59605
59979
|
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
59606
59980
|
lastPressedAt: number().nullable(),
|
|
59607
59981
|
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
59608
|
-
pressCountSinceStart: number()
|
|
59982
|
+
pressCountSinceStart: number().meta(readingMeta("count"))
|
|
59609
59983
|
});
|
|
59610
59984
|
var DoorbellPressEventSchema = object({
|
|
59611
59985
|
deviceId: number(),
|
|
@@ -59670,17 +60044,7 @@ onPressed: {
|
|
|
59670
60044
|
history: "none",
|
|
59671
60045
|
customize: doorbellCustomize
|
|
59672
60046
|
};
|
|
59673
|
-
|
|
59674
|
-
* Enum-state sensor — a string value picked from a finite option set.
|
|
59675
|
-
* Drives HA `sensor` entries with `state_class: enum` (HVAC action
|
|
59676
|
-
* states, weather conditions, contact-source channels, mode strings).
|
|
59677
|
-
* The option set is stable across observations; it is persisted in the
|
|
59678
|
-
* device config blob (via the control slice at adoption) and is NOT
|
|
59679
|
-
* stored in `sourceInfo`.
|
|
59680
|
-
*/
|
|
59681
|
-
/** Locale-render shape for an ISO `value` carried by a `DateTimeSensor`-role
|
|
59682
|
-
* enum sensor: `date` (date-only), `time` (time-only), `datetime` (both). */
|
|
59683
|
-
var EnumSensorDateTimeFormatSchema = _enum([
|
|
60047
|
+
_enum([
|
|
59684
60048
|
"date",
|
|
59685
60049
|
"time",
|
|
59686
60050
|
"datetime"
|
|
@@ -59688,12 +60052,11 @@ var EnumSensorDateTimeFormatSchema = _enum([
|
|
|
59688
60052
|
var EnumSensorStatusSchema = object({
|
|
59689
60053
|
value: string(),
|
|
59690
60054
|
/**
|
|
59691
|
-
* Set
|
|
59692
|
-
* as
|
|
59693
|
-
*
|
|
59694
|
-
* a time-only sensor → `'time'`.
|
|
60055
|
+
* Set when `value` is a timestamp rather than an enum state, so history
|
|
60056
|
+
* does not learn ISO strings as states. The display shape (date / time /
|
|
60057
|
+
* datetime) lives on `SourceInfo.dateTimeShape`, written once at adopt.
|
|
59695
60058
|
*/
|
|
59696
|
-
|
|
60059
|
+
timestamp: boolean().optional(),
|
|
59697
60060
|
/** Ms epoch when the slice was last updated. */
|
|
59698
60061
|
lastFetchedAt: number()
|
|
59699
60062
|
});
|
|
@@ -59720,11 +60083,11 @@ var enumSensorCapability = {
|
|
|
59720
60083
|
* History (D850): the value as an `enum` series (an appliance's program or
|
|
59721
60084
|
* operation state, an HVAC action). The option set is per device, so the
|
|
59722
60085
|
* value list is LEARNED as values are first seen (bounded). A sensor with a
|
|
59723
|
-
* `
|
|
60086
|
+
* `timestamp` carries a clock, not a state, and is not recorded.
|
|
59724
60087
|
*/
|
|
59725
60088
|
history: { fields: { value: {
|
|
59726
60089
|
kind: "enum",
|
|
59727
|
-
skipWhenSet: "
|
|
60090
|
+
skipWhenSet: "timestamp"
|
|
59728
60091
|
} } },
|
|
59729
60092
|
/** Clock fields: written, but excluded from the compare that decides
|
|
59730
60093
|
* whether persisting is worth a SQLite commit. */
|
|
@@ -59744,13 +60107,13 @@ var EventFireSchema = object({
|
|
|
59744
60107
|
deviceId: number(),
|
|
59745
60108
|
eventType: string(),
|
|
59746
60109
|
data: record(string(), unknown()).nullable(),
|
|
59747
|
-
timestamp: number(),
|
|
59748
|
-
seq: number()
|
|
60110
|
+
timestamp: number().meta(readingMeta("none")),
|
|
60111
|
+
seq: number().meta(readingMeta("count"))
|
|
59749
60112
|
});
|
|
59750
60113
|
var EventEmitterStatusSchema = object({
|
|
59751
60114
|
eventTypes: array(string()),
|
|
59752
60115
|
lastEvent: EventFireSchema.nullable(),
|
|
59753
|
-
eventCountSinceStart: number()
|
|
60116
|
+
eventCountSinceStart: number().meta(readingMeta("count"))
|
|
59754
60117
|
});
|
|
59755
60118
|
var eventEmitterCapability = {
|
|
59756
60119
|
name: "event-emitter",
|
|
@@ -60163,10 +60526,10 @@ var FanDirectionSchema = _enum(["forward", "reverse"]);
|
|
|
60163
60526
|
var FanControlStatusSchema = object({
|
|
60164
60527
|
/** Active speed as 0..100 inclusive. Null when the device has no
|
|
60165
60528
|
* speed surface (single-speed fan). */
|
|
60166
|
-
percentage: number().min(0).max(100).nullable(),
|
|
60529
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
60167
60530
|
/** Speed granularity the device accepts (HA `percentage_step`, e.g. 25 for
|
|
60168
60531
|
* a 4-speed fan). Absent when unknown — the UI then falls back to step 1. */
|
|
60169
|
-
percentageStep: number().positive().optional(),
|
|
60532
|
+
percentageStep: number().positive().optional().meta(readingMeta("percentage")),
|
|
60170
60533
|
/** Active preset mode (`auto` / `quiet` / `turbo` / vendor-specific)
|
|
60171
60534
|
* — empty string when no preset is active or supported. */
|
|
60172
60535
|
preset: string(),
|
|
@@ -60287,7 +60650,7 @@ var FeatureProbeStatusSchema = object({
|
|
|
60287
60650
|
/** Camera/firmware model string. `null` when the firmware doesn't expose it. */
|
|
60288
60651
|
model: string().nullable(),
|
|
60289
60652
|
/** Channel count for NVR/Hub devices; `1` for standalone cameras; `null` pre-probe. */
|
|
60290
|
-
channelCount: number().nullable(),
|
|
60653
|
+
channelCount: number().nullable().meta(readingMeta("count")),
|
|
60291
60654
|
/**
|
|
60292
60655
|
* Ms epoch of the last SUCCESSFUL probe. `0` before the first probe
|
|
60293
60656
|
* completes — drivers' `getAccessoryChildren()` should treat zero as
|
|
@@ -60410,9 +60773,91 @@ var gasCapability = {
|
|
|
60410
60773
|
* whether persisting is worth a SQLite commit. */
|
|
60411
60774
|
volatileStateFields: ["lastChangedAt"]
|
|
60412
60775
|
};
|
|
60776
|
+
var GroupCommandsSchema = object({
|
|
60777
|
+
/** One row per member that has been commanded. A later command replaces that member's row. */
|
|
60778
|
+
results: array(object({
|
|
60779
|
+
deviceId: number().int().nonnegative(),
|
|
60780
|
+
cap: string().min(1),
|
|
60781
|
+
method: string().min(1),
|
|
60782
|
+
ok: boolean(),
|
|
60783
|
+
error: string().optional(),
|
|
60784
|
+
/** Ms epoch of the attempt. */
|
|
60785
|
+
at: number()
|
|
60786
|
+
})) });
|
|
60787
|
+
var groupCommandsCapability = {
|
|
60788
|
+
name: "group-commands",
|
|
60789
|
+
scope: "device",
|
|
60790
|
+
deviceNative: true,
|
|
60791
|
+
mode: "singleton",
|
|
60792
|
+
deviceTypes: [DeviceType.Switch, DeviceType.Light],
|
|
60793
|
+
methods: {},
|
|
60794
|
+
status: {
|
|
60795
|
+
schema: GroupCommandsSchema,
|
|
60796
|
+
kind: "push"
|
|
60797
|
+
},
|
|
60798
|
+
runtimeState: GroupCommandsSchema,
|
|
60799
|
+
/**
|
|
60800
|
+
* Runtime-state durability: **session** — the last attempt. A restored
|
|
60801
|
+
* failure would outlive the command that caused it.
|
|
60802
|
+
*
|
|
60803
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
60804
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
60805
|
+
*/
|
|
60806
|
+
durability: "session",
|
|
60807
|
+
history: "none"
|
|
60808
|
+
};
|
|
60809
|
+
/**
|
|
60810
|
+
* How many members of a helper group answered (D944). Counts are integers,
|
|
60811
|
+
* not measurements: zero included is a real count, never a stand-in reading.
|
|
60812
|
+
* The reading itself stays on the output capability. History is none — the
|
|
60813
|
+
* series that later statistics read is the output cap's own history block.
|
|
60814
|
+
*/
|
|
60815
|
+
var GroupStatusSchema = object({
|
|
60816
|
+
/** Members whose current value entered the aggregate. */
|
|
60817
|
+
included: number().int().nonnegative().meta(readingMeta("count", {
|
|
60818
|
+
precision: 0,
|
|
60819
|
+
label: "Reporting"
|
|
60820
|
+
})),
|
|
60821
|
+
/** Members left out: offline, unknown, or not a finite reading (D393). */
|
|
60822
|
+
excluded: number().int().nonnegative().meta(readingMeta("count", {
|
|
60823
|
+
precision: 0,
|
|
60824
|
+
label: "Excluded"
|
|
60825
|
+
})),
|
|
60826
|
+
/** `included` + `excluded`. */
|
|
60827
|
+
total: number().int().nonnegative().meta(readingMeta("count", {
|
|
60828
|
+
precision: 0,
|
|
60829
|
+
label: "Members"
|
|
60830
|
+
}))
|
|
60831
|
+
});
|
|
60832
|
+
var groupStatusCapability = {
|
|
60833
|
+
name: "group-status",
|
|
60834
|
+
scope: "device",
|
|
60835
|
+
deviceNative: true,
|
|
60836
|
+
mode: "singleton",
|
|
60837
|
+
deviceTypes: [
|
|
60838
|
+
DeviceType.Sensor,
|
|
60839
|
+
DeviceType.Switch,
|
|
60840
|
+
DeviceType.Light
|
|
60841
|
+
],
|
|
60842
|
+
methods: {},
|
|
60843
|
+
status: {
|
|
60844
|
+
schema: GroupStatusSchema,
|
|
60845
|
+
kind: "push"
|
|
60846
|
+
},
|
|
60847
|
+
runtimeState: GroupStatusSchema,
|
|
60848
|
+
/**
|
|
60849
|
+
* Runtime-state durability: **session** — recomputed from members on the
|
|
60850
|
+
* next source event; a restored count would outlive the readings it named.
|
|
60851
|
+
*
|
|
60852
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
60853
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
60854
|
+
*/
|
|
60855
|
+
durability: "session",
|
|
60856
|
+
history: "none"
|
|
60857
|
+
};
|
|
60413
60858
|
var HeatingValveStatusSchema = object({
|
|
60414
60859
|
/** Radiator valve opening 0 (closed) .. 100 (open). Null = not yet known. */
|
|
60415
|
-
position: number().min(0).max(100).nullable(),
|
|
60860
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
60416
60861
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
60417
60862
|
lastFetchedAt: number()
|
|
60418
60863
|
});
|
|
@@ -60455,9 +60900,9 @@ var HumidifierStatusSchema = object({
|
|
|
60455
60900
|
/** Whether the humidifier is currently on. */
|
|
60456
60901
|
on: boolean(),
|
|
60457
60902
|
/** Current measured relative humidity (0..100). Null when not reported. */
|
|
60458
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
60903
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
60459
60904
|
/** Target relative humidity (0..100). Null when no setpoint surface. */
|
|
60460
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
60905
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
60461
60906
|
/** Active mode (`auto` / `normal` / `baby` / vendor). Null when the
|
|
60462
60907
|
* device has no mode surface. */
|
|
60463
60908
|
mode: string().nullable(),
|
|
@@ -60467,9 +60912,9 @@ var HumidifierStatusSchema = object({
|
|
|
60467
60912
|
* `idle` / `off`). Null when the device doesn't report it. */
|
|
60468
60913
|
action: string().nullable(),
|
|
60469
60914
|
/** HA `min_humidity` attribute. Null → UI uses 0. */
|
|
60470
|
-
minHumidity: number().nullable(),
|
|
60915
|
+
minHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
60471
60916
|
/** HA `max_humidity` attribute. Null → UI uses 100. */
|
|
60472
|
-
maxHumidity: number().nullable(),
|
|
60917
|
+
maxHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
60473
60918
|
/** Ms epoch when the slice was last updated. */
|
|
60474
60919
|
lastChangedAt: number()
|
|
60475
60920
|
});
|
|
@@ -60539,22 +60984,13 @@ var humidifierCapability = {
|
|
|
60539
60984
|
* `sourceInfo`.
|
|
60540
60985
|
*/
|
|
60541
60986
|
var HumiditySensorStatusSchema = object({
|
|
60542
|
-
/** Current relative humidity, 0..100. */
|
|
60543
|
-
percent: number().min(0).max(100).meta({
|
|
60544
|
-
|
|
60987
|
+
/** Current relative humidity, 0..100. `null` when the sample was refused (D393). */
|
|
60988
|
+
percent: number().min(0).max(100).nullable().meta(readingMeta("humidity", {
|
|
60989
|
+
precision: 0,
|
|
60545
60990
|
label: "Humidity"
|
|
60546
|
-
}),
|
|
60991
|
+
})),
|
|
60547
60992
|
/** Ms epoch when the slice was last updated. */
|
|
60548
|
-
lastFetchedAt: number()
|
|
60549
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
60550
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
60551
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
60552
|
-
unit: string().optional(),
|
|
60553
|
-
/** Suggested decimal places for numeric display.
|
|
60554
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
60555
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
60556
|
-
* auto-formatting when absent. */
|
|
60557
|
-
precision: number().int().min(0).max(10).optional()
|
|
60993
|
+
lastFetchedAt: number()
|
|
60558
60994
|
});
|
|
60559
60995
|
var humiditySensorCapability = {
|
|
60560
60996
|
name: "humidity-sensor",
|
|
@@ -60585,12 +61021,7 @@ var humiditySensorCapability = {
|
|
|
60585
61021
|
} } },
|
|
60586
61022
|
/** Clock fields: written, but excluded from the compare that decides
|
|
60587
61023
|
* whether persisting is worth a SQLite commit. */
|
|
60588
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
60589
|
-
customize: {
|
|
60590
|
-
version: 1,
|
|
60591
|
-
advanced: "derive",
|
|
60592
|
-
targets: []
|
|
60593
|
-
}
|
|
61024
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
60594
61025
|
};
|
|
60595
61026
|
/**
|
|
60596
61027
|
* Image display cap. Models a single still image exposed by an integration —
|
|
@@ -60611,7 +61042,7 @@ var ImageStatusSchema = object({
|
|
|
60611
61042
|
* entity exposes no `entity_picture` (yet). */
|
|
60612
61043
|
url: string().nullable(),
|
|
60613
61044
|
/** Ms epoch of the upstream last-updated timestamp. Null at cold-start. */
|
|
60614
|
-
lastUpdated: number().nullable()
|
|
61045
|
+
lastUpdated: number().nullable().meta(readingMeta("none"))
|
|
60615
61046
|
});
|
|
60616
61047
|
var imageCapability = {
|
|
60617
61048
|
name: "image",
|
|
@@ -60699,19 +61130,19 @@ var NormalizedRangeSchema = object({
|
|
|
60699
61130
|
*/
|
|
60700
61131
|
var ImageSettingsStatusSchema = object({
|
|
60701
61132
|
/** Normalized 0–100. */
|
|
60702
|
-
brightness: number().optional(),
|
|
61133
|
+
brightness: number().optional().meta(readingMeta("none")),
|
|
60703
61134
|
/** Normalized 0–100. */
|
|
60704
|
-
contrast: number().optional(),
|
|
61135
|
+
contrast: number().optional().meta(readingMeta("none")),
|
|
60705
61136
|
/** Normalized 0–100. */
|
|
60706
|
-
saturation: number().optional(),
|
|
61137
|
+
saturation: number().optional().meta(readingMeta("none")),
|
|
60707
61138
|
/** Normalized 0–100. */
|
|
60708
|
-
sharpness: number().optional(),
|
|
61139
|
+
sharpness: number().optional().meta(readingMeta("none")),
|
|
60709
61140
|
mirror: boolean().optional(),
|
|
60710
61141
|
flip: boolean().optional(),
|
|
60711
61142
|
rotate: ImageRotateSchema.optional(),
|
|
60712
61143
|
whiteBalance: WhiteBalanceModeSchema.optional(),
|
|
60713
61144
|
/** Manual white-balance warmth, NORMALIZED 0–100. Meaningful only when `whiteBalance === 'manual'`. */
|
|
60714
|
-
warmth: number().optional(),
|
|
61145
|
+
warmth: number().optional().meta(readingMeta("none")),
|
|
60715
61146
|
exposureMode: ExposureModeSchema.optional(),
|
|
60716
61147
|
backlightMode: BacklightModeSchema.optional(),
|
|
60717
61148
|
lastFetchedAt: number()
|
|
@@ -60990,10 +61421,10 @@ var IntercomAbilitySchema = object({
|
|
|
60990
61421
|
/** Codecs accepted by firmware, in preference order. Driver-authored strings. */
|
|
60991
61422
|
codecs: array(string()),
|
|
60992
61423
|
/** Sample rate (Hz) the firmware expects. Reolink typical: 16000. */
|
|
60993
|
-
sampleRate: number(),
|
|
61424
|
+
sampleRate: number().meta(readingMeta("none")),
|
|
60994
61425
|
duplex: _enum(["half", "full"]),
|
|
60995
61426
|
/** Max in-flight audio backlog before drop (ms). Server uses this to bound latency. */
|
|
60996
|
-
maxBacklogMs: number()
|
|
61427
|
+
maxBacklogMs: number().meta(readingMeta("duration-ms"))
|
|
60997
61428
|
});
|
|
60998
61429
|
var IntercomStatusSchema = object({
|
|
60999
61430
|
/** True while a talk session is open. */
|
|
@@ -61220,13 +61651,13 @@ var LawnMowerControlStatusSchema = object({
|
|
|
61220
61651
|
activity: LawnMowerActivitySchema,
|
|
61221
61652
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
61222
61653
|
* reading. */
|
|
61223
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
61654
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61224
61655
|
/** 0..100 mowing-completion percentage of the current task, or null when no
|
|
61225
61656
|
* task is active / progress is unavailable. */
|
|
61226
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
61657
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61227
61658
|
/** Current device/event code (dynamic — mostly status, sometimes an error),
|
|
61228
61659
|
* or null when unknown. */
|
|
61229
|
-
currentCode: number().nullable(),
|
|
61660
|
+
currentCode: number().nullable().meta(readingMeta("none")),
|
|
61230
61661
|
/** Human label for {@link currentCode}, or null when undecodable. */
|
|
61231
61662
|
currentCodeLabel: string().nullable(),
|
|
61232
61663
|
/** Severity of {@link currentCode}. `error` (and often `warning`) warrants UI
|
|
@@ -61759,7 +62190,7 @@ var MediaPlayerStatusSchema = object({
|
|
|
61759
62190
|
state: MediaPlayerStateSchema,
|
|
61760
62191
|
/** Volume as 0..100 inclusive. Null when the device has no volume
|
|
61761
62192
|
* surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
|
|
61762
|
-
volumeLevel: number().min(0).max(100).nullable(),
|
|
62193
|
+
volumeLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61763
62194
|
/** Mute toggle distinct from volume=0. Null when no mute surface.
|
|
61764
62195
|
* Pair with `DeviceFeature.MediaPlayerMute`. */
|
|
61765
62196
|
isMuted: boolean().nullable(),
|
|
@@ -61772,10 +62203,10 @@ var MediaPlayerStatusSchema = object({
|
|
|
61772
62203
|
currentMedia: MediaInfoSchema.nullable(),
|
|
61773
62204
|
/** Current playback position in ms. Null when not seekable or
|
|
61774
62205
|
* nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
|
|
61775
|
-
positionMs: number().int().nonnegative().nullable(),
|
|
62206
|
+
positionMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
61776
62207
|
/** Total duration of the current media in ms. Null when unknown
|
|
61777
62208
|
* (live stream) or nothing is playing. */
|
|
61778
|
-
durationMs: number().int().nonnegative().nullable(),
|
|
62209
|
+
durationMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
61779
62210
|
/** Shuffle toggle. Null when no shuffle surface.
|
|
61780
62211
|
* Pair with `DeviceFeature.MediaPlayerShuffle`. */
|
|
61781
62212
|
shuffle: boolean().nullable(),
|
|
@@ -62084,7 +62515,7 @@ var motionCustomize = {
|
|
|
62084
62515
|
eventName: "onMotionChanged"
|
|
62085
62516
|
},
|
|
62086
62517
|
deviceTypes: [DeviceType.Camera],
|
|
62087
|
-
apply: "
|
|
62518
|
+
apply: "add",
|
|
62088
62519
|
applyAuthority: {
|
|
62089
62520
|
kind: "camera-sensors",
|
|
62090
62521
|
timeoutField: "motionCooldownMs"
|
|
@@ -62156,7 +62587,7 @@ var MotionStatusSchema = object({
|
|
|
62156
62587
|
* it, every provider seeded it at boot, and every session left it
|
|
62157
62588
|
* `detected: true` after its detach.
|
|
62158
62589
|
*/
|
|
62159
|
-
autoClearAfterMs: number().nullable()
|
|
62590
|
+
autoClearAfterMs: number().nullable().meta(readingMeta("duration-ms"))
|
|
62160
62591
|
});
|
|
62161
62592
|
/**
|
|
62162
62593
|
* Payload of `motion.onMotionChanged` event + the corresponding bus
|
|
@@ -62193,12 +62624,18 @@ var motionCapability = {
|
|
|
62193
62624
|
methods: {
|
|
62194
62625
|
/**
|
|
62195
62626
|
* Pull the current motion state synchronously. Convenience shortcut
|
|
62196
|
-
* for consumers that don't need the full status object
|
|
62197
|
-
*
|
|
62198
|
-
* `getStatus` once the auto-injected status surface lands in every
|
|
62199
|
-
* consumer.
|
|
62627
|
+
* for consumers that don't need the full status object. A composed
|
|
62628
|
+
* group answers from its slice (D944): unknown throws, it is not off.
|
|
62200
62629
|
*/
|
|
62201
62630
|
isDetected: method(object({ deviceId: number() }), boolean()) },
|
|
62631
|
+
/**
|
|
62632
|
+
* A composed motion group serves `isDetected` from `detected` (D944).
|
|
62633
|
+
* Without this the cap stays uncomposable (`has-commands`).
|
|
62634
|
+
*/
|
|
62635
|
+
composedMethods: { isDetected: {
|
|
62636
|
+
kind: "slice",
|
|
62637
|
+
field: "detected"
|
|
62638
|
+
} },
|
|
62202
62639
|
events: {
|
|
62203
62640
|
/**
|
|
62204
62641
|
* Fires every time the runner transitions a camera between
|
|
@@ -62338,7 +62775,7 @@ var MotionZoneRegionSchema = object({
|
|
|
62338
62775
|
* the grid region(s). */
|
|
62339
62776
|
var MotionZoneStatusSchema = object({
|
|
62340
62777
|
enabled: boolean(),
|
|
62341
|
-
sensitivity: number(),
|
|
62778
|
+
sensitivity: number().meta(readingMeta("none")),
|
|
62342
62779
|
/** Grid region(s). Today exactly one `grid` shape. */
|
|
62343
62780
|
regions: array(MotionZoneRegionSchema),
|
|
62344
62781
|
lastFetchedAt: number()
|
|
@@ -62708,7 +63145,7 @@ var NavigationStatusSchema = object({
|
|
|
62708
63145
|
following: boolean(),
|
|
62709
63146
|
flash: boolean(),
|
|
62710
63147
|
lightMode: NavigationLightModeSchema,
|
|
62711
|
-
lightLevel: number().min(40).max(100),
|
|
63148
|
+
lightLevel: number().min(40).max(100).meta(readingMeta("none")),
|
|
62712
63149
|
/** Ms epoch when the slice was last updated. */
|
|
62713
63150
|
lastChangedAt: number()
|
|
62714
63151
|
});
|
|
@@ -62842,13 +63279,13 @@ var NetworkLinkStatusSchema = object({
|
|
|
62842
63279
|
* one whose reading has not landed must not be drawn at 0 %. Consumers
|
|
62843
63280
|
* SKIP a null rather than coerce it.
|
|
62844
63281
|
*/
|
|
62845
|
-
signalPercent: number().min(0).max(100).nullable(),
|
|
63282
|
+
signalPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
62846
63283
|
/** Raw received signal strength in dBm, when the firmware reports one. */
|
|
62847
|
-
rssiDbm: number().optional(),
|
|
63284
|
+
rssiDbm: number().optional().meta(readingMeta("signal-level")),
|
|
62848
63285
|
/** Network name of a wireless link, when the firmware reports it. */
|
|
62849
63286
|
ssid: string().optional(),
|
|
62850
63287
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
62851
|
-
lastUpdated: number()
|
|
63288
|
+
lastUpdated: number().meta(readingMeta("none"))
|
|
62852
63289
|
});
|
|
62853
63290
|
var networkLinkCapability = {
|
|
62854
63291
|
name: "network-link",
|
|
@@ -63233,7 +63670,7 @@ var NotifierStatusSchema = object({
|
|
|
63233
63670
|
lastError: string().nullable(),
|
|
63234
63671
|
/** Number of deliveries currently buffered server-side (rate-limited
|
|
63235
63672
|
* notifiers may queue). 0 when the provider sends synchronously. */
|
|
63236
|
-
queueDepth: number().int().nonnegative(),
|
|
63673
|
+
queueDepth: number().int().nonnegative().meta(readingMeta("count")),
|
|
63237
63674
|
/** Per-feature capability matrix — authoritative source for the
|
|
63238
63675
|
* compose-form field gating. */
|
|
63239
63676
|
supports: NotifierSupportsSchema
|
|
@@ -63325,11 +63762,9 @@ onSent: { data: object({
|
|
|
63325
63762
|
* cap fits (HA `sensor` whose `device_class` we don't have a typed cap
|
|
63326
63763
|
* for: water flow, distance, weight, frequency, signal strength, …).
|
|
63327
63764
|
*
|
|
63328
|
-
* The
|
|
63329
|
-
*
|
|
63330
|
-
*
|
|
63331
|
-
* The UI reads them directly from the slice — they are the single source
|
|
63332
|
-
* of truth for generic numeric rendering and do NOT live on `sourceInfo`.
|
|
63765
|
+
* The quantity is not on this slice. It is chosen when the device is
|
|
63766
|
+
* adopted and stored once on `SourceInfo.quantity` (D944). `value` is in
|
|
63767
|
+
* that quantity's base unit. `null` is a refused sample (D393).
|
|
63333
63768
|
*
|
|
63334
63769
|
* Prefer the typed alternatives (`temperature-sensor`, `humidity-sensor`,
|
|
63335
63770
|
* `ambient-light-sensor`, `pressure-sensor`, `power-meter`,
|
|
@@ -63338,15 +63773,8 @@ onSent: { data: object({
|
|
|
63338
63773
|
* numeric values land here.
|
|
63339
63774
|
*/
|
|
63340
63775
|
var NumericSensorStatusSchema = object({
|
|
63341
|
-
|
|
63342
|
-
|
|
63343
|
-
* Populated live from the upstream source on each state push.
|
|
63344
|
-
* Absent for unitless sensors. */
|
|
63345
|
-
unit: string().optional(),
|
|
63346
|
-
/** Suggested decimal places for numeric display.
|
|
63347
|
-
* Populated live from the upstream source when provided.
|
|
63348
|
-
* Falls back to auto-formatting when absent. */
|
|
63349
|
-
precision: number().int().min(0).max(10).optional(),
|
|
63776
|
+
/** Reading in the device quantity's base unit. `null` when refused (D393). */
|
|
63777
|
+
value: number().nullable().meta(readingMeta("device")),
|
|
63350
63778
|
/** Ms epoch when the slice was last updated. */
|
|
63351
63779
|
lastFetchedAt: number()
|
|
63352
63780
|
});
|
|
@@ -63370,11 +63798,11 @@ var numericSensorCapability = {
|
|
|
63370
63798
|
*/
|
|
63371
63799
|
durability: "restored",
|
|
63372
63800
|
/**
|
|
63373
|
-
* History (D850): recorded series. The unit is
|
|
63801
|
+
* History (D850): recorded series. The unit is the device quantity's base,
|
|
63802
|
+
* resolved when the series is read — the cap has no single unit.
|
|
63374
63803
|
*/
|
|
63375
63804
|
history: { fields: { value: {
|
|
63376
63805
|
kind: "gauge",
|
|
63377
|
-
unitFrom: "unit",
|
|
63378
63806
|
minIntervalMs: 3e4
|
|
63379
63807
|
} } },
|
|
63380
63808
|
/** Clock fields: written, but excluded from the compare that decides
|
|
@@ -63666,23 +64094,26 @@ var PetFeederStatusSchema = object({
|
|
|
63666
64094
|
/** Food currently in the bowl (grams). Null when the device has not
|
|
63667
64095
|
* reported a reading yet. On dual-hopper models this is the combined
|
|
63668
64096
|
* bowl reading; per-hopper levels live in `food1`/`food2`. */
|
|
63669
|
-
foodLevel: number().nullable(),
|
|
64097
|
+
foodLevel: number().nullable().meta(readingMeta("none")),
|
|
63670
64098
|
/** Hopper-1 food level (grams) on dual-hopper feeders; null on
|
|
63671
64099
|
* single-hopper models. */
|
|
63672
|
-
food1: number().nullable(),
|
|
64100
|
+
food1: number().nullable().meta(readingMeta("none")),
|
|
63673
64101
|
/** Hopper-2 food level (grams) on dual-hopper feeders; null on
|
|
63674
64102
|
* single-hopper models. */
|
|
63675
|
-
food2: number().nullable(),
|
|
64103
|
+
food2: number().nullable().meta(readingMeta("none")),
|
|
63676
64104
|
/** Derived low-food flag — mirrors the HA `food_level` binary_sensor
|
|
63677
64105
|
* (`device_class: problem`, on = low). True when the bowl is empty /
|
|
63678
64106
|
* below the feeder's low threshold. */
|
|
63679
64107
|
lowFood: boolean(),
|
|
63680
64108
|
/** Battery charge 0..100 (%). Null on mains-powered models or when the
|
|
63681
64109
|
* device has no battery reading. */
|
|
63682
|
-
batteryPower: number().min(0).max(100).nullable(),
|
|
63683
|
-
/**
|
|
63684
|
-
*
|
|
63685
|
-
|
|
64110
|
+
batteryPower: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
64111
|
+
/**
|
|
64112
|
+
* Desiccant life remaining, stored in seconds (duration base, D944).
|
|
64113
|
+
* Providers convert from the days the feeder reports. Null when the
|
|
64114
|
+
* model has no desiccant sensor.
|
|
64115
|
+
*/
|
|
64116
|
+
desiccantLeftDays: number().nullable().meta(readingMeta("duration")),
|
|
63686
64117
|
/** True while a feed is in progress. */
|
|
63687
64118
|
feeding: boolean(),
|
|
63688
64119
|
/** Decoded connectivity / power status (HA petkit device-status enum).
|
|
@@ -63693,7 +64124,7 @@ var PetFeederStatusSchema = object({
|
|
|
63693
64124
|
* with `errorCode` for consumers that want the raw integer. */
|
|
63694
64125
|
error: string().nullable(),
|
|
63695
64126
|
/** Raw device error code (0 / null = no error). */
|
|
63696
|
-
errorCode: number().nullable(),
|
|
64127
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
63697
64128
|
/** True for D4S/D4SH dual-hopper hardware — gates the per-hopper UI. */
|
|
63698
64129
|
isDualHopper: boolean(),
|
|
63699
64130
|
/** Child-lock (manual-lock) setting — buttons on the unit are disabled. */
|
|
@@ -63703,7 +64134,7 @@ var PetFeederStatusSchema = object({
|
|
|
63703
64134
|
/** Play a chime when dispensing. */
|
|
63704
64135
|
feedSound: boolean(),
|
|
63705
64136
|
/** Speaker / prompt volume level (device-scaled integer). */
|
|
63706
|
-
volume: number(),
|
|
64137
|
+
volume: number().meta(readingMeta("none")),
|
|
63707
64138
|
/** Ms epoch when the slice was last refreshed from the cloud. */
|
|
63708
64139
|
lastFetchedAt: number()
|
|
63709
64140
|
});
|
|
@@ -63822,7 +64253,7 @@ var petFeederCapability = {
|
|
|
63822
64253
|
},
|
|
63823
64254
|
desiccantLeftDays: {
|
|
63824
64255
|
kind: "gauge",
|
|
63825
|
-
unit: "
|
|
64256
|
+
unit: "s"
|
|
63826
64257
|
}
|
|
63827
64258
|
} }
|
|
63828
64259
|
};
|
|
@@ -64223,36 +64654,19 @@ method(_void(), PlatformCapabilitiesSchema), method(_void(), HardwareInfoSchema)
|
|
|
64223
64654
|
*/
|
|
64224
64655
|
var PowerMeterStatusSchema = object({
|
|
64225
64656
|
/** Instantaneous power draw in watts. */
|
|
64226
|
-
watts: number().optional().meta({
|
|
64227
|
-
unit: "W",
|
|
64228
|
-
label: "Power"
|
|
64229
|
-
}),
|
|
64657
|
+
watts: number().optional().meta(readingMeta("power", { label: "Power" })),
|
|
64230
64658
|
/** Cumulative energy in kilowatt-hours since the meter was reset. */
|
|
64231
|
-
kwhTotal: number().optional().meta({
|
|
64232
|
-
unit: "kWh",
|
|
64233
|
-
label: "Energy"
|
|
64234
|
-
}),
|
|
64659
|
+
kwhTotal: number().optional().meta(readingMeta("energy", { label: "Energy" })),
|
|
64235
64660
|
/** Voltage in volts. */
|
|
64236
|
-
volts: number().optional(),
|
|
64661
|
+
volts: number().optional().meta(readingMeta("voltage")),
|
|
64237
64662
|
/** Current in amperes. */
|
|
64238
|
-
amps: number().optional(),
|
|
64239
|
-
/** Apparent power in volt-amperes
|
|
64240
|
-
va: number().optional(),
|
|
64663
|
+
amps: number().optional().meta(readingMeta("current")),
|
|
64664
|
+
/** Apparent power in volt-amperes. */
|
|
64665
|
+
va: number().optional().meta(readingMeta("apparent-power")),
|
|
64241
64666
|
/** Power factor (0..1) if reported. */
|
|
64242
|
-
powerFactor: number().min(0).max(1).optional(),
|
|
64667
|
+
powerFactor: number().min(0).max(1).optional().meta(readingMeta("ratio")),
|
|
64243
64668
|
/** Ms epoch when the slice was last updated. */
|
|
64244
|
-
lastFetchedAt: number()
|
|
64245
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
64246
|
-
* `attributes.unit_of_measurement` → 'V' / 'A' / 'W' / 'kW' / 'kWh').
|
|
64247
|
-
* Each upstream `sensor.*` entity surfaces ONE device_class, so one
|
|
64248
|
-
* unit per slice is unambiguous. The UI prefers this over the role's
|
|
64249
|
-
* canonical unit so a 'kW' / 'Wh' feed renders verbatim. */
|
|
64250
|
-
unit: string().optional(),
|
|
64251
|
-
/** Suggested decimal places for numeric display.
|
|
64252
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
64253
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
64254
|
-
* auto-formatting when absent. */
|
|
64255
|
-
precision: number().int().min(0).max(10).optional()
|
|
64669
|
+
lastFetchedAt: number()
|
|
64256
64670
|
});
|
|
64257
64671
|
var powerMeterCapability = {
|
|
64258
64672
|
name: "power-meter",
|
|
@@ -64316,12 +64730,7 @@ var powerMeterCapability = {
|
|
|
64316
64730
|
} },
|
|
64317
64731
|
/** Clock fields: written, but excluded from the compare that decides
|
|
64318
64732
|
* whether persisting is worth a SQLite commit. */
|
|
64319
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
64320
|
-
customize: {
|
|
64321
|
-
version: 1,
|
|
64322
|
-
advanced: "derive",
|
|
64323
|
-
targets: []
|
|
64324
|
-
}
|
|
64733
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
64325
64734
|
};
|
|
64326
64735
|
/**
|
|
64327
64736
|
* Presence cap. Models HA `person.*` and `device_tracker.*` entities
|
|
@@ -64341,11 +64750,11 @@ var powerMeterCapability = {
|
|
|
64341
64750
|
*/
|
|
64342
64751
|
var GpsLocationSchema = object({
|
|
64343
64752
|
/** Latitude in decimal degrees, -90..90. */
|
|
64344
|
-
latitude: number().min(-90).max(90),
|
|
64753
|
+
latitude: number().min(-90).max(90).meta(readingMeta("angle")),
|
|
64345
64754
|
/** Longitude in decimal degrees, -180..180. */
|
|
64346
|
-
longitude: number().min(-180).max(180),
|
|
64755
|
+
longitude: number().min(-180).max(180).meta(readingMeta("angle")),
|
|
64347
64756
|
/** Reported accuracy in meters (lower = better). */
|
|
64348
|
-
accuracyMeters: number().nonnegative()
|
|
64757
|
+
accuracyMeters: number().nonnegative().meta(readingMeta("length"))
|
|
64349
64758
|
});
|
|
64350
64759
|
var PresenceStatusSchema = object({
|
|
64351
64760
|
/** `home` / `not_home` / any user-defined zone name. */
|
|
@@ -64357,7 +64766,7 @@ var PresenceStatusSchema = object({
|
|
|
64357
64766
|
gps: GpsLocationSchema.nullable(),
|
|
64358
64767
|
/** Optional battery level of the tracking device (0..100). Null
|
|
64359
64768
|
* when not reported. */
|
|
64360
|
-
batteryPercent: number().min(0).max(100).nullable(),
|
|
64769
|
+
batteryPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
64361
64770
|
/** Ms epoch when the slice was last updated. */
|
|
64362
64771
|
lastChangedAt: number()
|
|
64363
64772
|
});
|
|
@@ -64407,19 +64816,10 @@ var presenceCapability = {
|
|
|
64407
64816
|
* `sourceInfo`.
|
|
64408
64817
|
*/
|
|
64409
64818
|
var PressureSensorStatusSchema = object({
|
|
64410
|
-
/** Current pressure in hPa. */
|
|
64411
|
-
hpa: number(),
|
|
64819
|
+
/** Current pressure in hPa. `null` when the sample was refused (D393). */
|
|
64820
|
+
hpa: number().nullable().meta(readingMeta("pressure", { precision: 0 })),
|
|
64412
64821
|
/** Ms epoch when the slice was last updated. */
|
|
64413
|
-
lastFetchedAt: number()
|
|
64414
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
64415
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
64416
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
64417
|
-
unit: string().optional(),
|
|
64418
|
-
/** Suggested decimal places for numeric display.
|
|
64419
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
64420
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
64421
|
-
* auto-formatting when absent. */
|
|
64422
|
-
precision: number().int().min(0).max(10).optional()
|
|
64822
|
+
lastFetchedAt: number()
|
|
64423
64823
|
});
|
|
64424
64824
|
var pressureSensorCapability = {
|
|
64425
64825
|
name: "pressure-sensor",
|
|
@@ -64833,8 +65233,8 @@ DeviceType.Camera, method(PtzMoveCommandSchema.extend({ deviceId: number() }), _
|
|
|
64833
65233
|
}), _void(), { kind: "mutation" });
|
|
64834
65234
|
var PtzAutotrackSettingsSchema = object({
|
|
64835
65235
|
targetType: string().describe("Vendor target string (people/vehicle/pet); empty = camera default"),
|
|
64836
|
-
stopDelaySeconds: number().int().min(0).max(300),
|
|
64837
|
-
disappearDelaySeconds: number().int().min(0).max(300)
|
|
65236
|
+
stopDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration")),
|
|
65237
|
+
disappearDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration"))
|
|
64838
65238
|
});
|
|
64839
65239
|
/**
|
|
64840
65240
|
* One option the camera advertises as a valid `targetType`. Drivers
|
|
@@ -64988,7 +65388,7 @@ var RunningStateStatusSchema = object({
|
|
|
64988
65388
|
/** null = unknown — never coerced to false (D393). */
|
|
64989
65389
|
running: boolean().nullable(),
|
|
64990
65390
|
/** Epoch ms the current boolean began; null while `running` is null. */
|
|
64991
|
-
since: number().nullable(),
|
|
65391
|
+
since: number().nullable().meta(readingMeta("none")),
|
|
64992
65392
|
source: RunningStateSourceSchema.meta({ label: "Source" }),
|
|
64993
65393
|
phase: string().nullable(),
|
|
64994
65394
|
/** null until a reading has been published (D393). */
|
|
@@ -65003,7 +65403,6 @@ var RUNNING_DEVICE_TYPES = Object.values(DeviceType);
|
|
|
65003
65403
|
/** Generic Customize target for the running boolean (D936). */
|
|
65004
65404
|
var runningCustomize = {
|
|
65005
65405
|
version: 1,
|
|
65006
|
-
advanced: "derive",
|
|
65007
65406
|
targets: [{
|
|
65008
65407
|
id: "running",
|
|
65009
65408
|
cardinality: "scalar",
|
|
@@ -65023,7 +65422,7 @@ var runningCustomize = {
|
|
|
65023
65422
|
DeviceType.Thermostat,
|
|
65024
65423
|
DeviceType.PetFeeder
|
|
65025
65424
|
],
|
|
65026
|
-
apply: "add
|
|
65425
|
+
apply: "add",
|
|
65027
65426
|
path: "running",
|
|
65028
65427
|
sources: [
|
|
65029
65428
|
{
|
|
@@ -66287,9 +66686,9 @@ var RecordTriggerSchema = _enum([
|
|
|
66287
66686
|
*/
|
|
66288
66687
|
var RecordWindowSchema = object({
|
|
66289
66688
|
trigger: RecordTriggerSchema,
|
|
66290
|
-
day: number().int().min(0).max(6),
|
|
66291
|
-
startMinute: number().int().min(0).max(1439),
|
|
66292
|
-
endMinute: number().int().min(1).max(1440)
|
|
66689
|
+
day: number().int().min(0).max(6).meta(readingMeta("none")),
|
|
66690
|
+
startMinute: number().int().min(0).max(1439).meta(readingMeta("none")),
|
|
66691
|
+
endMinute: number().int().min(1).max(1440).meta(readingMeta("none"))
|
|
66293
66692
|
});
|
|
66294
66693
|
/** Status of one physical volume, as the camera itself describes it. */
|
|
66295
66694
|
var OnboardStorageVolumeSchema = object({
|
|
@@ -66365,10 +66764,10 @@ var RecordingOnboardStatusSchema = object({
|
|
|
66365
66764
|
/** Master "record to the card at all" switch. */
|
|
66366
66765
|
enabled: boolean().nullable(),
|
|
66367
66766
|
overwriteWhenFull: boolean().nullable(),
|
|
66368
|
-
preRecordSec: number().nullable(),
|
|
66369
|
-
postRecordSec: number().nullable(),
|
|
66767
|
+
preRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
66768
|
+
postRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
66370
66769
|
/** Length of one recorded file, in minutes. */
|
|
66371
|
-
segmentMinutes: number().nullable(),
|
|
66770
|
+
segmentMinutes: number().nullable().meta(readingMeta("none")),
|
|
66372
66771
|
/** The primary track's weekly windows, flattened. */
|
|
66373
66772
|
windows: array(RecordWindowSchema),
|
|
66374
66773
|
/**
|
|
@@ -66384,7 +66783,7 @@ var RecordingOnboardStatusSchema = object({
|
|
|
66384
66783
|
* provider reporting a non-zero count also reports the schedule as not
|
|
66385
66784
|
* writable.
|
|
66386
66785
|
*/
|
|
66387
|
-
unreadableWindows: number(),
|
|
66786
|
+
unreadableWindows: number().meta(readingMeta("count")),
|
|
66388
66787
|
/**
|
|
66389
66788
|
* The camera is scheduled to record and has NO usable storage.
|
|
66390
66789
|
*
|
|
@@ -67229,7 +67628,7 @@ var CamStreamDescriptorSchema = object({
|
|
|
67229
67628
|
url: string().optional(),
|
|
67230
67629
|
codec: string().optional(),
|
|
67231
67630
|
resolution: CamStreamResolutionSchema.optional(),
|
|
67232
|
-
fps: number().positive().optional(),
|
|
67631
|
+
fps: number().positive().optional().meta(readingMeta("rate")),
|
|
67233
67632
|
label: string().optional(),
|
|
67234
67633
|
/** Device-level features (e.g. `battery-operated`) — drives broker policy. */
|
|
67235
67634
|
deviceFeatures: array(string()).optional(),
|
|
@@ -67316,18 +67715,18 @@ var StreamProfileSchema = _enum([
|
|
|
67316
67715
|
]);
|
|
67317
67716
|
/** The current encoding config of one stream profile. */
|
|
67318
67717
|
var StreamProfileConfigSchema = object({
|
|
67319
|
-
width: number(),
|
|
67320
|
-
height: number(),
|
|
67718
|
+
width: number().meta(readingMeta("none")),
|
|
67719
|
+
height: number().meta(readingMeta("none")),
|
|
67321
67720
|
codec: _enum(["h264", "h265"]),
|
|
67322
|
-
framerate: number(),
|
|
67323
|
-
bitrate: number(),
|
|
67721
|
+
framerate: number().meta(readingMeta("rate")),
|
|
67722
|
+
bitrate: number().meta(readingMeta("bitrate")),
|
|
67324
67723
|
bitrateMode: _enum(["vbr", "cbr"]).optional(),
|
|
67325
67724
|
encoderProfile: _enum([
|
|
67326
67725
|
"high",
|
|
67327
67726
|
"main",
|
|
67328
67727
|
"baseline"
|
|
67329
67728
|
]).optional(),
|
|
67330
|
-
gop: number().optional(),
|
|
67729
|
+
gop: number().optional().meta(readingMeta("none")),
|
|
67331
67730
|
/**
|
|
67332
67731
|
* Whether THIS profile currently carries an audio track. READ-ONLY here.
|
|
67333
67732
|
*
|
|
@@ -67548,12 +67947,7 @@ var switchCapability = {
|
|
|
67548
67947
|
label: "On",
|
|
67549
67948
|
kind: "boolean"
|
|
67550
67949
|
}
|
|
67551
|
-
}] }
|
|
67552
|
-
customize: {
|
|
67553
|
-
version: 1,
|
|
67554
|
-
advanced: "derive",
|
|
67555
|
-
targets: []
|
|
67556
|
-
}
|
|
67950
|
+
}] }
|
|
67557
67951
|
};
|
|
67558
67952
|
/** C0 controls, DEL and the C1 range: none of them belongs in a name. */
|
|
67559
67953
|
function hasControlCharacter(value) {
|
|
@@ -68136,35 +68530,21 @@ var tamperCapability = {
|
|
|
68136
68530
|
* entries with `device_class: temperature` and any future native
|
|
68137
68531
|
* thermometer.
|
|
68138
68532
|
*
|
|
68139
|
-
*
|
|
68140
|
-
*
|
|
68141
|
-
* (climate-control's `currentTemp`, energy analytics) can compose
|
|
68142
|
-
* without per-source unit fixups. The canonical display unit (`°C`) is
|
|
68143
|
-
* a descriptor constant in the UI (ROLE_DESCRIPTOR), not stored in
|
|
68144
|
-
* `sourceInfo`.
|
|
68533
|
+
* The number is Celsius (D944). Providers convert on ingest. A failed
|
|
68534
|
+
* conversion is `null`, never a guess. Display unit is a read-time preference.
|
|
68145
68535
|
*
|
|
68146
68536
|
* Status `lastFetchedAt` lets staleness-aware consumers detect a
|
|
68147
68537
|
* frozen feed (provider hung) distinct from a "temperature hasn't
|
|
68148
68538
|
* changed" steady state.
|
|
68149
68539
|
*/
|
|
68150
68540
|
var TemperatureSensorStatusSchema = object({
|
|
68151
|
-
/** Current temperature in Celsius. */
|
|
68152
|
-
celsius: number().meta({
|
|
68153
|
-
|
|
68541
|
+
/** Current temperature in Celsius. `null` when the sample was refused (D393). */
|
|
68542
|
+
celsius: number().nullable().meta(readingMeta("temperature", {
|
|
68543
|
+
precision: 1,
|
|
68154
68544
|
label: "Temperature"
|
|
68155
|
-
}),
|
|
68545
|
+
})),
|
|
68156
68546
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
68157
|
-
lastFetchedAt: number()
|
|
68158
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
68159
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
68160
|
-
* role's canonical unit, so a Fahrenheit feed renders '°F' not '°C'.
|
|
68161
|
-
* Absent → the UI falls back to the role's canonical unit. */
|
|
68162
|
-
unit: string().optional(),
|
|
68163
|
-
/** Suggested decimal places for numeric display.
|
|
68164
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
68165
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
68166
|
-
* auto-formatting when absent. */
|
|
68167
|
-
precision: number().int().min(0).max(10).optional()
|
|
68547
|
+
lastFetchedAt: number()
|
|
68168
68548
|
});
|
|
68169
68549
|
var temperatureSensorCapability = {
|
|
68170
68550
|
name: "temperature-sensor",
|
|
@@ -68195,12 +68575,7 @@ var temperatureSensorCapability = {
|
|
|
68195
68575
|
} } },
|
|
68196
68576
|
/** Clock fields: written, but excluded from the compare that decides
|
|
68197
68577
|
* whether persisting is worth a SQLite commit. */
|
|
68198
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
68199
|
-
customize: {
|
|
68200
|
-
version: 1,
|
|
68201
|
-
advanced: "derive",
|
|
68202
|
-
targets: []
|
|
68203
|
-
}
|
|
68578
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
68204
68579
|
};
|
|
68205
68580
|
/**
|
|
68206
68581
|
* toast — system-scoped singleton capability that streams toast
|
|
@@ -68483,16 +68858,16 @@ var VacuumControlStatusSchema = object({
|
|
|
68483
68858
|
]),
|
|
68484
68859
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
68485
68860
|
* reading. */
|
|
68486
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
68861
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
68487
68862
|
/** Current fan-speed token (provider-verbatim). Null when unknown or
|
|
68488
68863
|
* the vacuum has no speed control. */
|
|
68489
68864
|
fanSpeed: string().nullable(),
|
|
68490
68865
|
/** Speed tokens the hardware accepts — drives the UI selector. */
|
|
68491
68866
|
availableFanSpeeds: array(string()),
|
|
68492
68867
|
/** 0..100 cleaning-completion percentage of the current task, or null. */
|
|
68493
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
68868
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
68494
68869
|
/** Current error code (0 / null = no error). */
|
|
68495
|
-
errorCode: number().nullable(),
|
|
68870
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
68496
68871
|
/** Human label for {@link errorCode}, or null when none / undecodable. */
|
|
68497
68872
|
errorLabel: string().nullable(),
|
|
68498
68873
|
/** Ms epoch when the slice was last updated. */
|
|
@@ -68570,7 +68945,7 @@ var ValveStatusSchema = object({
|
|
|
68570
68945
|
]),
|
|
68571
68946
|
/** 0 = fully closed, 100 = fully open. Null when the device has no
|
|
68572
68947
|
* intermediate position surface. */
|
|
68573
|
-
position: number().min(0).max(100).nullable(),
|
|
68948
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
68574
68949
|
/** Ms epoch when the slice was last updated. */
|
|
68575
68950
|
lastChangedAt: number()
|
|
68576
68951
|
});
|
|
@@ -68678,9 +69053,9 @@ var vibrationCapability = {
|
|
|
68678
69053
|
*/
|
|
68679
69054
|
var WaterHeaterStatusSchema = object({
|
|
68680
69055
|
/** Current measured temperature. Null when not reported. */
|
|
68681
|
-
currentTemp: number().nullable(),
|
|
69056
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
68682
69057
|
/** Target temperature setpoint. Null when no setpoint surface. */
|
|
68683
|
-
targetTemp: number().nullable(),
|
|
69058
|
+
targetTemp: number().nullable().meta(readingMeta("temperature")),
|
|
68684
69059
|
/** Active operation mode = HA `state` (`eco` / `electric` / `gas` /
|
|
68685
69060
|
* `heat_pump` / `high_demand` / `performance` / `off`). Null when the
|
|
68686
69061
|
* device reports an unknown state. */
|
|
@@ -68691,9 +69066,9 @@ var WaterHeaterStatusSchema = object({
|
|
|
68691
69066
|
* has no away surface. */
|
|
68692
69067
|
away: boolean().nullable(),
|
|
68693
69068
|
/** HA `min_temp` attribute. Null when not reported. */
|
|
68694
|
-
minTemp: number().nullable(),
|
|
69069
|
+
minTemp: number().nullable().meta(readingMeta("temperature")),
|
|
68695
69070
|
/** HA `max_temp` attribute. Null when not reported. */
|
|
68696
|
-
maxTemp: number().nullable(),
|
|
69071
|
+
maxTemp: number().nullable().meta(readingMeta("temperature")),
|
|
68697
69072
|
/** Ms epoch when the slice was last updated. */
|
|
68698
69073
|
lastChangedAt: number()
|
|
68699
69074
|
});
|
|
@@ -68778,25 +69153,18 @@ var waterHeaterCapability = {
|
|
|
68778
69153
|
* Forecast deferred — current conditions only for v1.
|
|
68779
69154
|
*/
|
|
68780
69155
|
var WeatherStatusSchema = object({
|
|
68781
|
-
/** Verbatim
|
|
68782
|
-
* when no condition has been reported yet. */
|
|
69156
|
+
/** Verbatim condition state (`sunny`, `cloudy`, `rainy`, …). Null when none yet. */
|
|
68783
69157
|
condition: string().nullable(),
|
|
68784
|
-
/** Current temperature in
|
|
68785
|
-
temperature: number().nullable(),
|
|
68786
|
-
/** Temperature unit string (e.g. `°C` / `°F`). Null when not provided. */
|
|
68787
|
-
temperatureUnit: string().nullable(),
|
|
69158
|
+
/** Current temperature in Celsius. Null when not provided or refused. */
|
|
69159
|
+
temperature: number().nullable().meta(readingMeta("temperature", { precision: 1 })),
|
|
68788
69160
|
/** Relative humidity (0..100). Null when not provided. */
|
|
68789
|
-
humidity: number().min(0).max(100).nullable(),
|
|
68790
|
-
/** Barometric pressure in
|
|
68791
|
-
pressure: number().nullable(),
|
|
68792
|
-
/**
|
|
68793
|
-
|
|
68794
|
-
/** Wind speed in the reported unit. Null when not provided. */
|
|
68795
|
-
windSpeed: number().nullable(),
|
|
68796
|
-
/** Wind-speed unit string (e.g. `km/h` / `mph`). Null when not provided. */
|
|
68797
|
-
windSpeedUnit: string().nullable(),
|
|
69161
|
+
humidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
69162
|
+
/** Barometric pressure in hPa. Null when not provided or refused. */
|
|
69163
|
+
pressure: number().nullable().meta(readingMeta("pressure")),
|
|
69164
|
+
/** Wind speed in metres per second. Null when not provided or refused. */
|
|
69165
|
+
windSpeed: number().nullable().meta(readingMeta("speed")),
|
|
68798
69166
|
/** Wind bearing in degrees (0..360, meteorological). Null when not provided. */
|
|
68799
|
-
windBearing: number().nullable(),
|
|
69167
|
+
windBearing: number().nullable().meta(readingMeta("angle")),
|
|
68800
69168
|
/** Ms epoch when the slice was last updated. */
|
|
68801
69169
|
lastFetchedAt: number()
|
|
68802
69170
|
});
|
|
@@ -68824,12 +69192,12 @@ var weatherCapability = {
|
|
|
68824
69192
|
*/
|
|
68825
69193
|
durability: "session",
|
|
68826
69194
|
/**
|
|
68827
|
-
* History (D850): recorded series.
|
|
69195
|
+
* History (D850): recorded series. Numbers are the quantity base (D944).
|
|
68828
69196
|
*/
|
|
68829
69197
|
history: { fields: {
|
|
68830
69198
|
temperature: {
|
|
68831
69199
|
kind: "gauge",
|
|
68832
|
-
|
|
69200
|
+
unit: "°C",
|
|
68833
69201
|
deadband: .2
|
|
68834
69202
|
},
|
|
68835
69203
|
humidity: {
|
|
@@ -68839,12 +69207,12 @@ var weatherCapability = {
|
|
|
68839
69207
|
},
|
|
68840
69208
|
pressure: {
|
|
68841
69209
|
kind: "gauge",
|
|
68842
|
-
|
|
69210
|
+
unit: "hPa",
|
|
68843
69211
|
deadband: .5
|
|
68844
69212
|
},
|
|
68845
69213
|
windSpeed: {
|
|
68846
69214
|
kind: "gauge",
|
|
68847
|
-
|
|
69215
|
+
unit: "m/s",
|
|
68848
69216
|
deadband: .5
|
|
68849
69217
|
}
|
|
68850
69218
|
} }
|
|
@@ -70075,6 +70443,8 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
70075
70443
|
featureProbe: featureProbeCapability,
|
|
70076
70444
|
flood: floodCapability,
|
|
70077
70445
|
gas: gasCapability,
|
|
70446
|
+
groupCommands: groupCommandsCapability,
|
|
70447
|
+
groupStatus: groupStatusCapability,
|
|
70078
70448
|
heatingValve: heatingValveCapability,
|
|
70079
70449
|
humidifier: humidifierCapability,
|
|
70080
70450
|
humiditySensor: humiditySensorCapability,
|
|
@@ -71451,6 +71821,13 @@ Object.freeze({
|
|
|
71451
71821
|
access: "view",
|
|
71452
71822
|
role: "admin"
|
|
71453
71823
|
},
|
|
71824
|
+
"addons.getPackageDocs": {
|
|
71825
|
+
capName: "addons",
|
|
71826
|
+
capScope: "system",
|
|
71827
|
+
addonId: null,
|
|
71828
|
+
access: "view",
|
|
71829
|
+
role: "admin"
|
|
71830
|
+
},
|
|
71454
71831
|
"addons.getVersions": {
|
|
71455
71832
|
capName: "addons",
|
|
71456
71833
|
capScope: "system",
|
|
@@ -74559,6 +74936,20 @@ Object.freeze({
|
|
|
74559
74936
|
access: "view",
|
|
74560
74937
|
role: "viewer"
|
|
74561
74938
|
},
|
|
74939
|
+
"groupCommands.getStatus": {
|
|
74940
|
+
capName: "group-commands",
|
|
74941
|
+
capScope: "device",
|
|
74942
|
+
addonId: null,
|
|
74943
|
+
access: "view",
|
|
74944
|
+
role: "viewer"
|
|
74945
|
+
},
|
|
74946
|
+
"groupStatus.getStatus": {
|
|
74947
|
+
capName: "group-status",
|
|
74948
|
+
capScope: "device",
|
|
74949
|
+
addonId: null,
|
|
74950
|
+
access: "view",
|
|
74951
|
+
role: "viewer"
|
|
74952
|
+
},
|
|
74562
74953
|
"heatingValve.getStatus": {
|
|
74563
74954
|
capName: "heating-valve",
|
|
74564
74955
|
capScope: "device",
|
|
@@ -84381,6 +84772,37 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84381
84772
|
icon: "flame"
|
|
84382
84773
|
}]
|
|
84383
84774
|
},
|
|
84775
|
+
"group-commands": {
|
|
84776
|
+
scope: "device",
|
|
84777
|
+
noun: t("Group command", "Comando di gruppo")
|
|
84778
|
+
},
|
|
84779
|
+
"group-status": {
|
|
84780
|
+
scope: "device",
|
|
84781
|
+
noun: t("Group", "Gruppo"),
|
|
84782
|
+
state: [
|
|
84783
|
+
{
|
|
84784
|
+
kind: "numeric",
|
|
84785
|
+
field: "included",
|
|
84786
|
+
quantity: t("the members reporting", "i membri che rispondono"),
|
|
84787
|
+
label: t("Reporting", "Rispondono"),
|
|
84788
|
+
icon: "users"
|
|
84789
|
+
},
|
|
84790
|
+
{
|
|
84791
|
+
kind: "numeric",
|
|
84792
|
+
field: "excluded",
|
|
84793
|
+
quantity: t("the members left out", "i membri esclusi"),
|
|
84794
|
+
label: t("Excluded", "Esclusi"),
|
|
84795
|
+
icon: "users"
|
|
84796
|
+
},
|
|
84797
|
+
{
|
|
84798
|
+
kind: "numeric",
|
|
84799
|
+
field: "total",
|
|
84800
|
+
quantity: t("the member count", "il numero di membri"),
|
|
84801
|
+
label: t("Members", "Membri"),
|
|
84802
|
+
icon: "sigma"
|
|
84803
|
+
}
|
|
84804
|
+
]
|
|
84805
|
+
},
|
|
84384
84806
|
"humidity-sensor": {
|
|
84385
84807
|
scope: "device",
|
|
84386
84808
|
noun: t("Humidity", "Umidità"),
|
|
@@ -84414,7 +84836,6 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84414
84836
|
field: "value",
|
|
84415
84837
|
quantity: t("the reading", "il valore"),
|
|
84416
84838
|
label: t("Reading", "Valore"),
|
|
84417
|
-
unitField: "unit",
|
|
84418
84839
|
icon: "gauge"
|
|
84419
84840
|
}]
|
|
84420
84841
|
},
|
|
@@ -84550,7 +84971,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84550
84971
|
field: "temperature",
|
|
84551
84972
|
quantity: t("the outdoor temperature", "la temperatura esterna"),
|
|
84552
84973
|
label: t("Temperature", "Temperatura"),
|
|
84553
|
-
|
|
84974
|
+
unit: "°C",
|
|
84554
84975
|
icon: "thermometer"
|
|
84555
84976
|
},
|
|
84556
84977
|
{
|
|
@@ -84566,7 +84987,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84566
84987
|
field: "windSpeed",
|
|
84567
84988
|
quantity: t("the wind speed", "la velocità del vento"),
|
|
84568
84989
|
label: t("Wind", "Vento"),
|
|
84569
|
-
|
|
84990
|
+
unit: "m/s",
|
|
84570
84991
|
icon: "wind"
|
|
84571
84992
|
},
|
|
84572
84993
|
{
|
|
@@ -84574,7 +84995,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84574
84995
|
field: "pressure",
|
|
84575
84996
|
quantity: t("the air pressure", "la pressione atmosferica"),
|
|
84576
84997
|
label: t("Pressure", "Pressione"),
|
|
84577
|
-
|
|
84998
|
+
unit: "hPa",
|
|
84578
84999
|
icon: "gauge"
|
|
84579
85000
|
}
|
|
84580
85001
|
]
|
|
@@ -85847,6 +86268,16 @@ Object.freeze({
|
|
|
85847
86268
|
form: "single",
|
|
85848
86269
|
optional: false
|
|
85849
86270
|
}],
|
|
86271
|
+
"groupCommands.getStatus": [{
|
|
86272
|
+
name: "deviceId",
|
|
86273
|
+
form: "single",
|
|
86274
|
+
optional: false
|
|
86275
|
+
}],
|
|
86276
|
+
"groupStatus.getStatus": [{
|
|
86277
|
+
name: "deviceId",
|
|
86278
|
+
form: "single",
|
|
86279
|
+
optional: false
|
|
86280
|
+
}],
|
|
85850
86281
|
"heatingValve.getStatus": [{
|
|
85851
86282
|
name: "deviceId",
|
|
85852
86283
|
form: "single",
|
|
@@ -87831,6 +88262,8 @@ new Map(Object.entries({
|
|
|
87831
88262
|
"detection-blind": "device-events",
|
|
87832
88263
|
"motion-noisy": "device-events",
|
|
87833
88264
|
"motion-calm": "device-events",
|
|
88265
|
+
"package-llm-silent": "device-events",
|
|
88266
|
+
"package-llm-answered": "device-events",
|
|
87834
88267
|
"recording-stalled": "device-events",
|
|
87835
88268
|
"recording-healthy": "device-events",
|
|
87836
88269
|
"recording-degraded": "device-events",
|
|
@@ -87914,6 +88347,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
|
|
|
87914
88347
|
label: "Motion without a subject",
|
|
87915
88348
|
kinds: ["motion-noisy", "motion-calm"]
|
|
87916
88349
|
},
|
|
88350
|
+
{
|
|
88351
|
+
id: "package-llm",
|
|
88352
|
+
family: "device-events",
|
|
88353
|
+
label: "Package confirm",
|
|
88354
|
+
kinds: ["package-llm-silent", "package-llm-answered"]
|
|
88355
|
+
},
|
|
87917
88356
|
{
|
|
87918
88357
|
id: "recording",
|
|
87919
88358
|
family: "device-events",
|
|
@@ -88095,6 +88534,8 @@ var DEVICE_EVENTS = [
|
|
|
88095
88534
|
"detection-blind",
|
|
88096
88535
|
"motion-noisy",
|
|
88097
88536
|
"motion-calm",
|
|
88537
|
+
"package-llm-silent",
|
|
88538
|
+
"package-llm-answered",
|
|
88098
88539
|
"recording-stalled",
|
|
88099
88540
|
"recording-healthy",
|
|
88100
88541
|
"recording-degraded",
|
|
@@ -88363,6 +88804,15 @@ new Map([
|
|
|
88363
88804
|
snapshotLabel: "Cameras with constant motion now",
|
|
88364
88805
|
snapshotSection: null
|
|
88365
88806
|
},
|
|
88807
|
+
{
|
|
88808
|
+
id: "package-llm-confirm",
|
|
88809
|
+
family: "device-events",
|
|
88810
|
+
label: "Package confirm (not answering / answering again)",
|
|
88811
|
+
bad: ["package-llm-silent"],
|
|
88812
|
+
recovery: ["package-llm-answered"],
|
|
88813
|
+
snapshotLabel: "Cameras whose package confirm is not answering",
|
|
88814
|
+
snapshotSection: null
|
|
88815
|
+
},
|
|
88366
88816
|
{
|
|
88367
88817
|
id: "recording-health",
|
|
88368
88818
|
family: "device-events",
|