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