@camstack/addon-provider-rademacher 0.2.146 → 0.2.147
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
|
@@ -983,7 +983,7 @@ var Rademacher = class {
|
|
|
983
983
|
}
|
|
984
984
|
};
|
|
985
985
|
//#endregion
|
|
986
|
-
//#region ../types/dist/event-category-
|
|
986
|
+
//#region ../types/dist/event-category-CT-hz5Rb.mjs
|
|
987
987
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
988
988
|
EventCategory["SystemBoot"] = "system.boot";
|
|
989
989
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -1309,6 +1309,14 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
1309
1309
|
/** The recovery edge of {@link PipelineMotionNoisy}: the motion fell back, or a detection arrived. */
|
|
1310
1310
|
EventCategory["PipelineMotionCalm"] = "pipeline.motion-calm";
|
|
1311
1311
|
/**
|
|
1312
|
+
* A camera's package LLM confirm has failed closed three times in a row
|
|
1313
|
+
* (D931, 2026-10-26). One edge per camera until
|
|
1314
|
+
* {@link PipelinePackageLlmAnswered}.
|
|
1315
|
+
*/
|
|
1316
|
+
EventCategory["PipelinePackageLlmSilent"] = "pipeline.package-llm-silent";
|
|
1317
|
+
/** The recovery edge of {@link PipelinePackageLlmSilent}: a confirm returned yes or no. */
|
|
1318
|
+
EventCategory["PipelinePackageLlmAnswered"] = "pipeline.package-llm-answered";
|
|
1319
|
+
/**
|
|
1312
1320
|
* Per-camera pipeline config was mutated by the orchestrator
|
|
1313
1321
|
* (a settings change via `setAgentInferenceDevices` /
|
|
1314
1322
|
* `setCameraStepToggle` / `setCameraStepSettings`). Orchestrator
|
|
@@ -6418,7 +6426,7 @@ var ZodIssueCode = {
|
|
|
6418
6426
|
var ZodFirstPartyTypeKind;
|
|
6419
6427
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
6420
6428
|
//#endregion
|
|
6421
|
-
//#region ../types/dist/sleep-
|
|
6429
|
+
//#region ../types/dist/sleep-bykKrTgu.mjs
|
|
6422
6430
|
/**
|
|
6423
6431
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
6424
6432
|
* window to float samples (D455).
|
|
@@ -8972,6 +8980,99 @@ var RecordKindDeclarationSchema = object({
|
|
|
8972
8980
|
}).strict();
|
|
8973
8981
|
/** The kind names: lower-case, dash separated, short enough for an index name. */
|
|
8974
8982
|
var RecordKindNameSchema = string().regex(/^[a-z][a-z0-9-]{0,47}$/);
|
|
8983
|
+
var READING_QUANTITIES = [
|
|
8984
|
+
"temperature",
|
|
8985
|
+
"pressure",
|
|
8986
|
+
"speed",
|
|
8987
|
+
"precipitation",
|
|
8988
|
+
"precipitation-rate",
|
|
8989
|
+
"length",
|
|
8990
|
+
"area",
|
|
8991
|
+
"illuminance",
|
|
8992
|
+
"irradiance",
|
|
8993
|
+
"power",
|
|
8994
|
+
"energy",
|
|
8995
|
+
"voltage",
|
|
8996
|
+
"current",
|
|
8997
|
+
"apparent-power",
|
|
8998
|
+
"humidity",
|
|
8999
|
+
"percentage",
|
|
9000
|
+
"concentration-volume",
|
|
9001
|
+
"concentration-mass",
|
|
9002
|
+
"concentration-ppb",
|
|
9003
|
+
"volume",
|
|
9004
|
+
"duration",
|
|
9005
|
+
"duration-ms",
|
|
9006
|
+
"information",
|
|
9007
|
+
"sound-level",
|
|
9008
|
+
"signal-level",
|
|
9009
|
+
"colour-temperature",
|
|
9010
|
+
"angle",
|
|
9011
|
+
"bitrate",
|
|
9012
|
+
"rate",
|
|
9013
|
+
"mass",
|
|
9014
|
+
"index",
|
|
9015
|
+
"ratio",
|
|
9016
|
+
"count",
|
|
9017
|
+
"none",
|
|
9018
|
+
"device"
|
|
9019
|
+
];
|
|
9020
|
+
var ReadingQuantitySchema = _enum(READING_QUANTITIES);
|
|
9021
|
+
new Set(READING_QUANTITIES);
|
|
9022
|
+
/**
|
|
9023
|
+
* Stored unit symbol for a quantity. `none` means the number is dimensionless
|
|
9024
|
+
* (or an index / ratio / count). `device` means the cap has no single unit.
|
|
9025
|
+
*/
|
|
9026
|
+
var QUANTITY_BASE = {
|
|
9027
|
+
temperature: "°C",
|
|
9028
|
+
pressure: "hPa",
|
|
9029
|
+
speed: "m/s",
|
|
9030
|
+
precipitation: "mm",
|
|
9031
|
+
"precipitation-rate": "mm/h",
|
|
9032
|
+
length: "m",
|
|
9033
|
+
area: "m²",
|
|
9034
|
+
illuminance: "lx",
|
|
9035
|
+
irradiance: "W/m²",
|
|
9036
|
+
power: "W",
|
|
9037
|
+
energy: "kWh",
|
|
9038
|
+
voltage: "V",
|
|
9039
|
+
current: "A",
|
|
9040
|
+
"apparent-power": "VA",
|
|
9041
|
+
humidity: "%",
|
|
9042
|
+
percentage: "%",
|
|
9043
|
+
"concentration-volume": "ppm",
|
|
9044
|
+
"concentration-mass": "µg/m³",
|
|
9045
|
+
"concentration-ppb": "ppb",
|
|
9046
|
+
volume: "L",
|
|
9047
|
+
duration: "s",
|
|
9048
|
+
"duration-ms": "ms",
|
|
9049
|
+
information: "B",
|
|
9050
|
+
"sound-level": "dBFS",
|
|
9051
|
+
"signal-level": "dBm",
|
|
9052
|
+
"colour-temperature": "mired",
|
|
9053
|
+
angle: "°",
|
|
9054
|
+
bitrate: "kbps",
|
|
9055
|
+
rate: "fps",
|
|
9056
|
+
mass: "kg",
|
|
9057
|
+
index: "none",
|
|
9058
|
+
ratio: "none",
|
|
9059
|
+
count: "none",
|
|
9060
|
+
none: "none",
|
|
9061
|
+
device: "device"
|
|
9062
|
+
};
|
|
9063
|
+
/** The stored unit, or `undefined` when the quantity has no unit symbol. */
|
|
9064
|
+
function baseUnitOf(quantity) {
|
|
9065
|
+
const symbol = QUANTITY_BASE[quantity];
|
|
9066
|
+
if (symbol === "none" || symbol === "device") return void 0;
|
|
9067
|
+
return symbol;
|
|
9068
|
+
}
|
|
9069
|
+
function readingMeta(quantity, extras) {
|
|
9070
|
+
return {
|
|
9071
|
+
quantity,
|
|
9072
|
+
...extras?.precision !== void 0 ? { precision: extras.precision } : {},
|
|
9073
|
+
...extras?.label !== void 0 ? { label: extras.label } : {}
|
|
9074
|
+
};
|
|
9075
|
+
}
|
|
8975
9076
|
/** Shared Zod schemas used across streaming capabilities. */
|
|
8976
9077
|
var CamProfileSchema = _enum([
|
|
8977
9078
|
"high",
|
|
@@ -8999,8 +9100,8 @@ var CamStreamKindSchema = _enum([
|
|
|
8999
9100
|
"derived"
|
|
9000
9101
|
]);
|
|
9001
9102
|
var CamStreamResolutionSchema = object({
|
|
9002
|
-
width: number().int().positive(),
|
|
9003
|
-
height: number().int().positive()
|
|
9103
|
+
width: number().int().positive().meta(readingMeta("none")),
|
|
9104
|
+
height: number().int().positive().meta(readingMeta("none"))
|
|
9004
9105
|
});
|
|
9005
9106
|
var CameraStreamSchema = object({
|
|
9006
9107
|
/** Stable, provider-assigned id unique within the (deviceId) scope. */
|
|
@@ -9518,6 +9619,8 @@ var CAP_NAMES = Object.freeze([
|
|
|
9518
9619
|
"filesystem-browse",
|
|
9519
9620
|
"flood",
|
|
9520
9621
|
"gas",
|
|
9622
|
+
"group-commands",
|
|
9623
|
+
"group-status",
|
|
9521
9624
|
"heating-valve",
|
|
9522
9625
|
"humidifier",
|
|
9523
9626
|
"humidity-sensor",
|
|
@@ -9647,14 +9750,6 @@ Object.freeze({
|
|
|
9647
9750
|
{
|
|
9648
9751
|
"path": "aqi",
|
|
9649
9752
|
"valueType": "number"
|
|
9650
|
-
},
|
|
9651
|
-
{
|
|
9652
|
-
"path": "unit",
|
|
9653
|
-
"valueType": "string"
|
|
9654
|
-
},
|
|
9655
|
-
{
|
|
9656
|
-
"path": "precision",
|
|
9657
|
-
"valueType": "number"
|
|
9658
9753
|
}
|
|
9659
9754
|
],
|
|
9660
9755
|
"alarm-panel": [
|
|
@@ -9690,20 +9785,10 @@ Object.freeze({
|
|
|
9690
9785
|
"valueType": "boolean"
|
|
9691
9786
|
}
|
|
9692
9787
|
],
|
|
9693
|
-
"ambient-light-sensor": [
|
|
9694
|
-
|
|
9695
|
-
|
|
9696
|
-
|
|
9697
|
-
},
|
|
9698
|
-
{
|
|
9699
|
-
"path": "unit",
|
|
9700
|
-
"valueType": "string"
|
|
9701
|
-
},
|
|
9702
|
-
{
|
|
9703
|
-
"path": "precision",
|
|
9704
|
-
"valueType": "number"
|
|
9705
|
-
}
|
|
9706
|
-
],
|
|
9788
|
+
"ambient-light-sensor": [{
|
|
9789
|
+
"path": "lux",
|
|
9790
|
+
"valueType": "number"
|
|
9791
|
+
}],
|
|
9707
9792
|
"audio-metrics": [
|
|
9708
9793
|
{
|
|
9709
9794
|
"path": "ts",
|
|
@@ -9783,6 +9868,10 @@ Object.freeze({
|
|
|
9783
9868
|
"path": "lastUpdated",
|
|
9784
9869
|
"valueType": "number"
|
|
9785
9870
|
},
|
|
9871
|
+
{
|
|
9872
|
+
"path": "volts",
|
|
9873
|
+
"valueType": "number"
|
|
9874
|
+
},
|
|
9786
9875
|
{
|
|
9787
9876
|
"path": "lastContactAt",
|
|
9788
9877
|
"valueType": "number"
|
|
@@ -10025,10 +10114,6 @@ Object.freeze({
|
|
|
10025
10114
|
"datetime"
|
|
10026
10115
|
]
|
|
10027
10116
|
},
|
|
10028
|
-
{
|
|
10029
|
-
"path": "unit",
|
|
10030
|
-
"valueType": "string"
|
|
10031
|
-
},
|
|
10032
10117
|
{
|
|
10033
10118
|
"path": "min",
|
|
10034
10119
|
"valueType": "number"
|
|
@@ -10040,19 +10125,6 @@ Object.freeze({
|
|
|
10040
10125
|
{
|
|
10041
10126
|
"path": "step",
|
|
10042
10127
|
"valueType": "number"
|
|
10043
|
-
},
|
|
10044
|
-
{
|
|
10045
|
-
"path": "precision",
|
|
10046
|
-
"valueType": "number"
|
|
10047
|
-
},
|
|
10048
|
-
{
|
|
10049
|
-
"path": "format",
|
|
10050
|
-
"valueType": "enum",
|
|
10051
|
-
"enumValues": [
|
|
10052
|
-
"date",
|
|
10053
|
-
"time",
|
|
10054
|
-
"datetime"
|
|
10055
|
-
]
|
|
10056
10128
|
}
|
|
10057
10129
|
],
|
|
10058
10130
|
"cover": [
|
|
@@ -10293,13 +10365,8 @@ Object.freeze({
|
|
|
10293
10365
|
"path": "value",
|
|
10294
10366
|
"valueType": "string"
|
|
10295
10367
|
}, {
|
|
10296
|
-
"path": "
|
|
10297
|
-
"valueType": "
|
|
10298
|
-
"enumValues": [
|
|
10299
|
-
"date",
|
|
10300
|
-
"time",
|
|
10301
|
-
"datetime"
|
|
10302
|
-
]
|
|
10368
|
+
"path": "timestamp",
|
|
10369
|
+
"valueType": "boolean"
|
|
10303
10370
|
}],
|
|
10304
10371
|
"event-emitter": [
|
|
10305
10372
|
{
|
|
@@ -10372,6 +10439,20 @@ Object.freeze({
|
|
|
10372
10439
|
"path": "detected",
|
|
10373
10440
|
"valueType": "boolean"
|
|
10374
10441
|
}],
|
|
10442
|
+
"group-status": [
|
|
10443
|
+
{
|
|
10444
|
+
"path": "included",
|
|
10445
|
+
"valueType": "number"
|
|
10446
|
+
},
|
|
10447
|
+
{
|
|
10448
|
+
"path": "excluded",
|
|
10449
|
+
"valueType": "number"
|
|
10450
|
+
},
|
|
10451
|
+
{
|
|
10452
|
+
"path": "total",
|
|
10453
|
+
"valueType": "number"
|
|
10454
|
+
}
|
|
10455
|
+
],
|
|
10375
10456
|
"heating-valve": [{
|
|
10376
10457
|
"path": "position",
|
|
10377
10458
|
"valueType": "number"
|
|
@@ -10406,20 +10487,10 @@ Object.freeze({
|
|
|
10406
10487
|
"valueType": "number"
|
|
10407
10488
|
}
|
|
10408
10489
|
],
|
|
10409
|
-
"humidity-sensor": [
|
|
10410
|
-
|
|
10411
|
-
|
|
10412
|
-
|
|
10413
|
-
},
|
|
10414
|
-
{
|
|
10415
|
-
"path": "unit",
|
|
10416
|
-
"valueType": "string"
|
|
10417
|
-
},
|
|
10418
|
-
{
|
|
10419
|
-
"path": "precision",
|
|
10420
|
-
"valueType": "number"
|
|
10421
|
-
}
|
|
10422
|
-
],
|
|
10490
|
+
"humidity-sensor": [{
|
|
10491
|
+
"path": "percent",
|
|
10492
|
+
"valueType": "number"
|
|
10493
|
+
}],
|
|
10423
10494
|
"image": [{
|
|
10424
10495
|
"path": "url",
|
|
10425
10496
|
"valueType": "string"
|
|
@@ -10758,20 +10829,10 @@ Object.freeze({
|
|
|
10758
10829
|
"valueType": "boolean"
|
|
10759
10830
|
}
|
|
10760
10831
|
],
|
|
10761
|
-
"numeric-sensor": [
|
|
10762
|
-
|
|
10763
|
-
|
|
10764
|
-
|
|
10765
|
-
},
|
|
10766
|
-
{
|
|
10767
|
-
"path": "unit",
|
|
10768
|
-
"valueType": "string"
|
|
10769
|
-
},
|
|
10770
|
-
{
|
|
10771
|
-
"path": "precision",
|
|
10772
|
-
"valueType": "number"
|
|
10773
|
-
}
|
|
10774
|
-
],
|
|
10832
|
+
"numeric-sensor": [{
|
|
10833
|
+
"path": "value",
|
|
10834
|
+
"valueType": "number"
|
|
10835
|
+
}],
|
|
10775
10836
|
"pet-feeder": [
|
|
10776
10837
|
{
|
|
10777
10838
|
"path": "foodLevel",
|
|
@@ -10863,14 +10924,6 @@ Object.freeze({
|
|
|
10863
10924
|
{
|
|
10864
10925
|
"path": "powerFactor",
|
|
10865
10926
|
"valueType": "number"
|
|
10866
|
-
},
|
|
10867
|
-
{
|
|
10868
|
-
"path": "unit",
|
|
10869
|
-
"valueType": "string"
|
|
10870
|
-
},
|
|
10871
|
-
{
|
|
10872
|
-
"path": "precision",
|
|
10873
|
-
"valueType": "number"
|
|
10874
10927
|
}
|
|
10875
10928
|
],
|
|
10876
10929
|
"presence": [
|
|
@@ -10899,20 +10952,10 @@ Object.freeze({
|
|
|
10899
10952
|
"valueType": "number"
|
|
10900
10953
|
}
|
|
10901
10954
|
],
|
|
10902
|
-
"pressure-sensor": [
|
|
10903
|
-
|
|
10904
|
-
|
|
10905
|
-
|
|
10906
|
-
},
|
|
10907
|
-
{
|
|
10908
|
-
"path": "unit",
|
|
10909
|
-
"valueType": "string"
|
|
10910
|
-
},
|
|
10911
|
-
{
|
|
10912
|
-
"path": "precision",
|
|
10913
|
-
"valueType": "number"
|
|
10914
|
-
}
|
|
10915
|
-
],
|
|
10955
|
+
"pressure-sensor": [{
|
|
10956
|
+
"path": "hpa",
|
|
10957
|
+
"valueType": "number"
|
|
10958
|
+
}],
|
|
10916
10959
|
"privacy-mask": [{
|
|
10917
10960
|
"path": "enabled",
|
|
10918
10961
|
"valueType": "boolean"
|
|
@@ -11223,20 +11266,10 @@ Object.freeze({
|
|
|
11223
11266
|
"path": "tampered",
|
|
11224
11267
|
"valueType": "boolean"
|
|
11225
11268
|
}],
|
|
11226
|
-
"temperature-sensor": [
|
|
11227
|
-
|
|
11228
|
-
|
|
11229
|
-
|
|
11230
|
-
},
|
|
11231
|
-
{
|
|
11232
|
-
"path": "unit",
|
|
11233
|
-
"valueType": "string"
|
|
11234
|
-
},
|
|
11235
|
-
{
|
|
11236
|
-
"path": "precision",
|
|
11237
|
-
"valueType": "number"
|
|
11238
|
-
}
|
|
11239
|
-
],
|
|
11269
|
+
"temperature-sensor": [{
|
|
11270
|
+
"path": "celsius",
|
|
11271
|
+
"valueType": "number"
|
|
11272
|
+
}],
|
|
11240
11273
|
"update": [
|
|
11241
11274
|
{
|
|
11242
11275
|
"path": "currentVersion",
|
|
@@ -11347,10 +11380,6 @@ Object.freeze({
|
|
|
11347
11380
|
"path": "temperature",
|
|
11348
11381
|
"valueType": "number"
|
|
11349
11382
|
},
|
|
11350
|
-
{
|
|
11351
|
-
"path": "temperatureUnit",
|
|
11352
|
-
"valueType": "string"
|
|
11353
|
-
},
|
|
11354
11383
|
{
|
|
11355
11384
|
"path": "humidity",
|
|
11356
11385
|
"valueType": "number"
|
|
@@ -11359,18 +11388,10 @@ Object.freeze({
|
|
|
11359
11388
|
"path": "pressure",
|
|
11360
11389
|
"valueType": "number"
|
|
11361
11390
|
},
|
|
11362
|
-
{
|
|
11363
|
-
"path": "pressureUnit",
|
|
11364
|
-
"valueType": "string"
|
|
11365
|
-
},
|
|
11366
11391
|
{
|
|
11367
11392
|
"path": "windSpeed",
|
|
11368
11393
|
"valueType": "number"
|
|
11369
11394
|
},
|
|
11370
|
-
{
|
|
11371
|
-
"path": "windSpeedUnit",
|
|
11372
|
-
"valueType": "string"
|
|
11373
|
-
},
|
|
11374
11395
|
{
|
|
11375
11396
|
"path": "windBearing",
|
|
11376
11397
|
"valueType": "number"
|
|
@@ -11773,7 +11794,7 @@ function errMsg(err) {
|
|
|
11773
11794
|
return String(err);
|
|
11774
11795
|
}
|
|
11775
11796
|
//#endregion
|
|
11776
|
-
//#region ../types/dist/composition-
|
|
11797
|
+
//#region ../types/dist/composition-OhpuespA.mjs
|
|
11777
11798
|
/**
|
|
11778
11799
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
11779
11800
|
*
|
|
@@ -12528,15 +12549,74 @@ function validateExpressionSource(src) {
|
|
|
12528
12549
|
}
|
|
12529
12550
|
return null;
|
|
12530
12551
|
}
|
|
12531
|
-
/**
|
|
12532
|
-
|
|
12533
|
-
|
|
12534
|
-
|
|
12552
|
+
/**
|
|
12553
|
+
* A composition source identity: `(addonId, stableId)`, never a numeric device
|
|
12554
|
+
* id. Split out so helper schemas can name it without a cycle through
|
|
12555
|
+
* `composition.ts` (D659).
|
|
12556
|
+
*/
|
|
12535
12557
|
var CompositionSourceRefSchema = object({
|
|
12536
12558
|
/** The owning addon; `stableId` is unique only within it. */
|
|
12537
12559
|
addonId: string().min(1),
|
|
12538
12560
|
stableId: string().min(1)
|
|
12539
12561
|
});
|
|
12562
|
+
var GROUP_TEMPLATE_IDS = [
|
|
12563
|
+
"temperature",
|
|
12564
|
+
"humidity",
|
|
12565
|
+
"pressure",
|
|
12566
|
+
"illuminance",
|
|
12567
|
+
"power",
|
|
12568
|
+
"energy",
|
|
12569
|
+
"battery",
|
|
12570
|
+
"numeric",
|
|
12571
|
+
"motion",
|
|
12572
|
+
"contact",
|
|
12573
|
+
"leak",
|
|
12574
|
+
"smoke",
|
|
12575
|
+
"occupancy",
|
|
12576
|
+
"binary",
|
|
12577
|
+
"switch",
|
|
12578
|
+
"light"
|
|
12579
|
+
];
|
|
12580
|
+
var NUMERIC_AGGREGATES = [
|
|
12581
|
+
"mean",
|
|
12582
|
+
"median",
|
|
12583
|
+
"min",
|
|
12584
|
+
"max",
|
|
12585
|
+
"sum"
|
|
12586
|
+
];
|
|
12587
|
+
var BINARY_AGGREGATES = ["any", "all"];
|
|
12588
|
+
/** How an actuator group decides it is on. Unknown members never count as off. */
|
|
12589
|
+
var ACTIVE_CRITERIA = ["at-least-one", "all"];
|
|
12590
|
+
var AGGREGATE_REDUCERS = [
|
|
12591
|
+
"mean",
|
|
12592
|
+
"median",
|
|
12593
|
+
"min",
|
|
12594
|
+
"max",
|
|
12595
|
+
"sum",
|
|
12596
|
+
"any",
|
|
12597
|
+
"all"
|
|
12598
|
+
];
|
|
12599
|
+
var GroupTemplateIdSchema = _enum(GROUP_TEMPLATE_IDS);
|
|
12600
|
+
var AggregateReducerSchema = _enum(AGGREGATE_REDUCERS);
|
|
12601
|
+
var ActiveCriterionSchema = _enum(ACTIVE_CRITERIA);
|
|
12602
|
+
/** One member. The field is stored so occupancy can name motion or binary. */
|
|
12603
|
+
var HelperMemberSchema = object({
|
|
12604
|
+
source: CompositionSourceRefSchema,
|
|
12605
|
+
cap: string().min(1),
|
|
12606
|
+
fieldPath: string().min(1)
|
|
12607
|
+
});
|
|
12608
|
+
var HelperSpecSchema = discriminatedUnion("kind", [object({
|
|
12609
|
+
kind: literal("group"),
|
|
12610
|
+
templateId: GroupTemplateIdSchema,
|
|
12611
|
+
aggregate: AggregateReducerSchema,
|
|
12612
|
+
members: array(HelperMemberSchema).min(1).max(64),
|
|
12613
|
+
/** Actuator groups only. Readings leave this unset. */
|
|
12614
|
+
active: ActiveCriterionSchema.optional()
|
|
12615
|
+
})]);
|
|
12616
|
+
/** A composed device's stableId is this prefix plus the block id. */
|
|
12617
|
+
var COMPOSED_DEVICE_STABLE_ID_PREFIX = "composed-";
|
|
12618
|
+
/** Longest snippet a `code` source may carry (slice 4). */
|
|
12619
|
+
var MAX_COMPOSITION_CODE_LENGTH = 2e4;
|
|
12540
12620
|
/** One field of one capability of one source device. */
|
|
12541
12621
|
var CompositionFieldReadSchema = object({
|
|
12542
12622
|
source: CompositionSourceRefSchema,
|
|
@@ -12580,7 +12660,33 @@ var CompositionCodeSourceSchema = object({
|
|
|
12580
12660
|
var CompositionFieldSourceSchema = discriminatedUnion("kind", [
|
|
12581
12661
|
CompositionFromSourceSchema,
|
|
12582
12662
|
CompositionExpressionSourceSchema,
|
|
12583
|
-
CompositionCodeSourceSchema
|
|
12663
|
+
CompositionCodeSourceSchema,
|
|
12664
|
+
object({
|
|
12665
|
+
kind: literal("aggregate"),
|
|
12666
|
+
reducer: _enum([
|
|
12667
|
+
"mean",
|
|
12668
|
+
"median",
|
|
12669
|
+
"min",
|
|
12670
|
+
"max",
|
|
12671
|
+
"sum",
|
|
12672
|
+
"any",
|
|
12673
|
+
"all"
|
|
12674
|
+
]),
|
|
12675
|
+
reads: array(CompositionFieldReadSchema).min(1).max(64),
|
|
12676
|
+
/** `value` is the reading; the others are the member counts. */
|
|
12677
|
+
publish: _enum([
|
|
12678
|
+
"value",
|
|
12679
|
+
"included",
|
|
12680
|
+
"excluded",
|
|
12681
|
+
"total"
|
|
12682
|
+
]),
|
|
12683
|
+
/** What a `value` publish does when nobody is included. Counts ignore this. */
|
|
12684
|
+
empty: _enum([
|
|
12685
|
+
"null",
|
|
12686
|
+
"omit",
|
|
12687
|
+
"offline"
|
|
12688
|
+
])
|
|
12689
|
+
})
|
|
12584
12690
|
]);
|
|
12585
12691
|
var CompositionCommandTargetSchema = discriminatedUnion("kind", [object({
|
|
12586
12692
|
kind: literal("forward"),
|
|
@@ -12626,7 +12732,13 @@ var CompositionSchema = object({
|
|
|
12626
12732
|
kind: literal("existing"),
|
|
12627
12733
|
device: CompositionSourceRefSchema
|
|
12628
12734
|
})]),
|
|
12629
|
-
features: array(CompositionFeatureSchema).min(1).max(16)
|
|
12735
|
+
features: array(CompositionFeatureSchema).min(1).max(16),
|
|
12736
|
+
/**
|
|
12737
|
+
* Present when the block is a helper template. Absent on a free
|
|
12738
|
+
* composition (the room example, device 4603). The editor reads this,
|
|
12739
|
+
* never the compiled features.
|
|
12740
|
+
*/
|
|
12741
|
+
helper: HelperSpecSchema.optional()
|
|
12630
12742
|
}).superRefine((composition, ctx) => {
|
|
12631
12743
|
const seen = /* @__PURE__ */ new Set();
|
|
12632
12744
|
composition.features.forEach((feature, index) => {
|
|
@@ -18834,7 +18946,11 @@ var CompositionProblemSchema = object({
|
|
|
18834
18946
|
"item-field-reserved",
|
|
18835
18947
|
"target-missing",
|
|
18836
18948
|
"target-unreadable",
|
|
18837
|
-
"not-replaceable"
|
|
18949
|
+
"not-replaceable",
|
|
18950
|
+
"native-capability-replace",
|
|
18951
|
+
"mixed-quantity",
|
|
18952
|
+
"helper-mismatch",
|
|
18953
|
+
"member-constraint"
|
|
18838
18954
|
]),
|
|
18839
18955
|
path: string(),
|
|
18840
18956
|
message: string()
|
|
@@ -18855,7 +18971,8 @@ var CompositionUnavailableModeSchema = _enum([
|
|
|
18855
18971
|
"null",
|
|
18856
18972
|
"offline",
|
|
18857
18973
|
"unknown",
|
|
18858
|
-
"release"
|
|
18974
|
+
"release",
|
|
18975
|
+
"omit"
|
|
18859
18976
|
]);
|
|
18860
18977
|
/**
|
|
18861
18978
|
* `derived` reads a source · `clock` reads only `now`, recomputed when a sibling
|
|
@@ -18892,9 +19009,11 @@ var CompositionFieldPlanSchema = object({
|
|
|
18892
19009
|
reads: array(CompositionFieldReadSchema)
|
|
18893
19010
|
});
|
|
18894
19011
|
/**
|
|
18895
|
-
* What a feature does to its target (D663): `new` builds a capability on a
|
|
18896
|
-
* device; on an existing device it `add`s a capability the device lacks
|
|
18897
|
-
*
|
|
19012
|
+
* What a feature does to its target (D663, D944): `new` builds a capability on a
|
|
19013
|
+
* new device; on an existing device it `add`s a capability the device lacks.
|
|
19014
|
+
* Replacing a capability the device already serves is refused
|
|
19015
|
+
* (`native-capability-replace`), not planned. `replace` remains on the claim
|
|
19016
|
+
* wire for a claim the hub already holds.
|
|
18898
19017
|
*/
|
|
18899
19018
|
var CompositionFeatureModeSchema = _enum([
|
|
18900
19019
|
"new",
|
|
@@ -19067,6 +19186,275 @@ Object.freeze({
|
|
|
19067
19186
|
result: ["number", "null"]
|
|
19068
19187
|
}
|
|
19069
19188
|
});
|
|
19189
|
+
/**
|
|
19190
|
+
* One catalog row per base reading a group helper can build (D944 §3).
|
|
19191
|
+
* Data, not a form default written into the block.
|
|
19192
|
+
*/
|
|
19193
|
+
var NOW = {
|
|
19194
|
+
fieldPath: "lastFetchedAt",
|
|
19195
|
+
expr: "now"
|
|
19196
|
+
};
|
|
19197
|
+
var CHANGED = {
|
|
19198
|
+
fieldPath: "lastChangedAt",
|
|
19199
|
+
expr: "now"
|
|
19200
|
+
};
|
|
19201
|
+
function numeric(input) {
|
|
19202
|
+
return {
|
|
19203
|
+
...input,
|
|
19204
|
+
family: "numeric",
|
|
19205
|
+
deviceType: DeviceType.Sensor,
|
|
19206
|
+
memberDeviceType: DeviceType.Sensor,
|
|
19207
|
+
commandCaps: [],
|
|
19208
|
+
baseUnit: baseUnitOf(input.quantity),
|
|
19209
|
+
aggregates: NUMERIC_AGGREGATES,
|
|
19210
|
+
accept: [{
|
|
19211
|
+
cap: input.outputCap,
|
|
19212
|
+
fieldPath: input.outputField
|
|
19213
|
+
}]
|
|
19214
|
+
};
|
|
19215
|
+
}
|
|
19216
|
+
function binary(input) {
|
|
19217
|
+
return {
|
|
19218
|
+
...input,
|
|
19219
|
+
family: "binary",
|
|
19220
|
+
deviceType: DeviceType.Sensor,
|
|
19221
|
+
memberDeviceType: DeviceType.Sensor,
|
|
19222
|
+
commandCaps: [],
|
|
19223
|
+
quantity: "none",
|
|
19224
|
+
baseUnit: void 0,
|
|
19225
|
+
aggregates: BINARY_AGGREGATES,
|
|
19226
|
+
empty: "offline"
|
|
19227
|
+
};
|
|
19228
|
+
}
|
|
19229
|
+
var GROUP_TEMPLATES = [
|
|
19230
|
+
numeric({
|
|
19231
|
+
id: "temperature",
|
|
19232
|
+
summary: "Mean, median, min, max or sum of temperatures. Offline and unknown members are left out, never read as 0 °C.",
|
|
19233
|
+
role: DeviceRole.TemperatureSensor,
|
|
19234
|
+
outputCap: "temperature-sensor",
|
|
19235
|
+
outputField: "celsius",
|
|
19236
|
+
quantity: "temperature",
|
|
19237
|
+
defaultAggregate: "mean",
|
|
19238
|
+
empty: "null",
|
|
19239
|
+
companions: [NOW]
|
|
19240
|
+
}),
|
|
19241
|
+
numeric({
|
|
19242
|
+
id: "humidity",
|
|
19243
|
+
summary: "Humidity in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
19244
|
+
role: DeviceRole.HumiditySensor,
|
|
19245
|
+
outputCap: "humidity-sensor",
|
|
19246
|
+
outputField: "percent",
|
|
19247
|
+
quantity: "humidity",
|
|
19248
|
+
defaultAggregate: "mean",
|
|
19249
|
+
empty: "null",
|
|
19250
|
+
companions: [NOW]
|
|
19251
|
+
}),
|
|
19252
|
+
numeric({
|
|
19253
|
+
id: "pressure",
|
|
19254
|
+
summary: "Pressure in hectopascals. Offline and unknown members are left out, never read as 0 hPa.",
|
|
19255
|
+
role: DeviceRole.PressureSensor,
|
|
19256
|
+
outputCap: "pressure-sensor",
|
|
19257
|
+
outputField: "hpa",
|
|
19258
|
+
quantity: "pressure",
|
|
19259
|
+
defaultAggregate: "mean",
|
|
19260
|
+
empty: "null",
|
|
19261
|
+
companions: [NOW]
|
|
19262
|
+
}),
|
|
19263
|
+
numeric({
|
|
19264
|
+
id: "illuminance",
|
|
19265
|
+
summary: "Illuminance in lux. Offline and unknown members are left out, never read as 0 lx.",
|
|
19266
|
+
role: DeviceRole.AmbientLightSensor,
|
|
19267
|
+
outputCap: "ambient-light-sensor",
|
|
19268
|
+
outputField: "lux",
|
|
19269
|
+
quantity: "illuminance",
|
|
19270
|
+
defaultAggregate: "mean",
|
|
19271
|
+
empty: "null",
|
|
19272
|
+
companions: [NOW]
|
|
19273
|
+
}),
|
|
19274
|
+
numeric({
|
|
19275
|
+
id: "power",
|
|
19276
|
+
summary: "Power in watts, summed by default. Nobody reporting omits the key rather than writing 0 W.",
|
|
19277
|
+
role: DeviceRole.PowerSensor,
|
|
19278
|
+
outputCap: "power-meter",
|
|
19279
|
+
outputField: "watts",
|
|
19280
|
+
quantity: "power",
|
|
19281
|
+
defaultAggregate: "sum",
|
|
19282
|
+
empty: "omit",
|
|
19283
|
+
companions: [NOW]
|
|
19284
|
+
}),
|
|
19285
|
+
numeric({
|
|
19286
|
+
id: "energy",
|
|
19287
|
+
summary: "Energy in kilowatt-hours, summed by default. Nobody reporting omits the key rather than writing 0 kWh.",
|
|
19288
|
+
role: DeviceRole.EnergySensor,
|
|
19289
|
+
outputCap: "power-meter",
|
|
19290
|
+
outputField: "kwhTotal",
|
|
19291
|
+
quantity: "energy",
|
|
19292
|
+
defaultAggregate: "sum",
|
|
19293
|
+
empty: "omit",
|
|
19294
|
+
companions: [NOW]
|
|
19295
|
+
}),
|
|
19296
|
+
numeric({
|
|
19297
|
+
id: "battery",
|
|
19298
|
+
summary: "Battery charge in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
19299
|
+
role: DeviceRole.BatterySensor,
|
|
19300
|
+
outputCap: "battery",
|
|
19301
|
+
outputField: "percentage",
|
|
19302
|
+
quantity: "percentage",
|
|
19303
|
+
defaultAggregate: "mean",
|
|
19304
|
+
empty: "null",
|
|
19305
|
+
companions: [
|
|
19306
|
+
{
|
|
19307
|
+
fieldPath: "charging",
|
|
19308
|
+
expr: "\"unknown\""
|
|
19309
|
+
},
|
|
19310
|
+
{
|
|
19311
|
+
fieldPath: "sleeping",
|
|
19312
|
+
expr: "false"
|
|
19313
|
+
},
|
|
19314
|
+
{
|
|
19315
|
+
fieldPath: "lastUpdated",
|
|
19316
|
+
expr: "now"
|
|
19317
|
+
}
|
|
19318
|
+
]
|
|
19319
|
+
}),
|
|
19320
|
+
numeric({
|
|
19321
|
+
id: "numeric",
|
|
19322
|
+
summary: "A numeric reading in the members’ shared quantity. Mixed quantities are refused. Nobody reporting publishes null, not 0.",
|
|
19323
|
+
role: DeviceRole.NumericSensor,
|
|
19324
|
+
outputCap: "numeric-sensor",
|
|
19325
|
+
outputField: "value",
|
|
19326
|
+
quantity: "device",
|
|
19327
|
+
defaultAggregate: "mean",
|
|
19328
|
+
empty: "null",
|
|
19329
|
+
companions: [NOW]
|
|
19330
|
+
}),
|
|
19331
|
+
binary({
|
|
19332
|
+
id: "motion",
|
|
19333
|
+
summary: "Any or all motion. Offline and unknown members are left out, never read as off. Nobody reporting takes the device offline.",
|
|
19334
|
+
role: DeviceRole.MotionSensor,
|
|
19335
|
+
outputCap: "motion",
|
|
19336
|
+
outputField: "detected",
|
|
19337
|
+
defaultAggregate: "any",
|
|
19338
|
+
accept: [{
|
|
19339
|
+
cap: "motion",
|
|
19340
|
+
fieldPath: "detected"
|
|
19341
|
+
}],
|
|
19342
|
+
companions: [{
|
|
19343
|
+
fieldPath: "lastDetectedAt",
|
|
19344
|
+
expr: "null"
|
|
19345
|
+
}, {
|
|
19346
|
+
fieldPath: "autoClearAfterMs",
|
|
19347
|
+
expr: "null"
|
|
19348
|
+
}]
|
|
19349
|
+
}),
|
|
19350
|
+
binary({
|
|
19351
|
+
id: "contact",
|
|
19352
|
+
summary: "Any or all open contacts. Offline and unknown members are left out, never read as closed.",
|
|
19353
|
+
role: DeviceRole.ContactSensor,
|
|
19354
|
+
outputCap: "contact",
|
|
19355
|
+
outputField: "entryOpen",
|
|
19356
|
+
defaultAggregate: "any",
|
|
19357
|
+
accept: [{
|
|
19358
|
+
cap: "contact",
|
|
19359
|
+
fieldPath: "entryOpen"
|
|
19360
|
+
}],
|
|
19361
|
+
companions: [CHANGED]
|
|
19362
|
+
}),
|
|
19363
|
+
binary({
|
|
19364
|
+
id: "leak",
|
|
19365
|
+
summary: "Any or all leak detections. Offline and unknown members are left out, never read as dry.",
|
|
19366
|
+
role: DeviceRole.LeakSensor,
|
|
19367
|
+
outputCap: "flood",
|
|
19368
|
+
outputField: "flooded",
|
|
19369
|
+
defaultAggregate: "any",
|
|
19370
|
+
accept: [{
|
|
19371
|
+
cap: "flood",
|
|
19372
|
+
fieldPath: "flooded"
|
|
19373
|
+
}],
|
|
19374
|
+
companions: [CHANGED]
|
|
19375
|
+
}),
|
|
19376
|
+
binary({
|
|
19377
|
+
id: "smoke",
|
|
19378
|
+
summary: "Any or all smoke detections. Offline and unknown members are left out, never read as clear.",
|
|
19379
|
+
role: DeviceRole.SmokeSensor,
|
|
19380
|
+
outputCap: "smoke",
|
|
19381
|
+
outputField: "detected",
|
|
19382
|
+
defaultAggregate: "any",
|
|
19383
|
+
accept: [{
|
|
19384
|
+
cap: "smoke",
|
|
19385
|
+
fieldPath: "detected"
|
|
19386
|
+
}],
|
|
19387
|
+
companions: [CHANGED]
|
|
19388
|
+
}),
|
|
19389
|
+
binary({
|
|
19390
|
+
id: "occupancy",
|
|
19391
|
+
summary: "Any or all of motion or binary sensors, published as a binary. Presence zones are not aggregated. Nobody reporting is offline, not off.",
|
|
19392
|
+
role: DeviceRole.BinarySensor,
|
|
19393
|
+
outputCap: "binary",
|
|
19394
|
+
outputField: "on",
|
|
19395
|
+
defaultAggregate: "any",
|
|
19396
|
+
accept: [{
|
|
19397
|
+
cap: "motion",
|
|
19398
|
+
fieldPath: "detected"
|
|
19399
|
+
}, {
|
|
19400
|
+
cap: "binary",
|
|
19401
|
+
fieldPath: "on"
|
|
19402
|
+
}],
|
|
19403
|
+
companions: [CHANGED]
|
|
19404
|
+
}),
|
|
19405
|
+
binary({
|
|
19406
|
+
id: "binary",
|
|
19407
|
+
summary: "Any or all generic binary sensors. Offline and unknown members are left out, never read as off.",
|
|
19408
|
+
role: DeviceRole.BinarySensor,
|
|
19409
|
+
outputCap: "binary",
|
|
19410
|
+
outputField: "on",
|
|
19411
|
+
defaultAggregate: "any",
|
|
19412
|
+
accept: [{
|
|
19413
|
+
cap: "binary",
|
|
19414
|
+
fieldPath: "on"
|
|
19415
|
+
}],
|
|
19416
|
+
companions: [CHANGED]
|
|
19417
|
+
}),
|
|
19418
|
+
actuator({
|
|
19419
|
+
id: "switch",
|
|
19420
|
+
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.",
|
|
19421
|
+
deviceType: DeviceType.Switch,
|
|
19422
|
+
outputCap: "switch",
|
|
19423
|
+
commandCaps: ["switch"]
|
|
19424
|
+
}),
|
|
19425
|
+
actuator({
|
|
19426
|
+
id: "light",
|
|
19427
|
+
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.",
|
|
19428
|
+
deviceType: DeviceType.Light,
|
|
19429
|
+
outputCap: "switch",
|
|
19430
|
+
commandCaps: [
|
|
19431
|
+
"switch",
|
|
19432
|
+
"brightness",
|
|
19433
|
+
"color"
|
|
19434
|
+
]
|
|
19435
|
+
})
|
|
19436
|
+
];
|
|
19437
|
+
function actuator(input) {
|
|
19438
|
+
return {
|
|
19439
|
+
...input,
|
|
19440
|
+
family: "actuator",
|
|
19441
|
+
role: void 0,
|
|
19442
|
+
memberDeviceType: input.deviceType,
|
|
19443
|
+
outputField: "on",
|
|
19444
|
+
quantity: "none",
|
|
19445
|
+
baseUnit: void 0,
|
|
19446
|
+
aggregates: BINARY_AGGREGATES,
|
|
19447
|
+
defaultAggregate: "any",
|
|
19448
|
+
empty: "offline",
|
|
19449
|
+
accept: [{
|
|
19450
|
+
cap: "switch",
|
|
19451
|
+
fieldPath: "on"
|
|
19452
|
+
}],
|
|
19453
|
+
companions: [CHANGED]
|
|
19454
|
+
};
|
|
19455
|
+
}
|
|
19456
|
+
new Map(GROUP_TEMPLATES.map((template) => [template.id, template]));
|
|
19457
|
+
DeviceFeature.LightColorRgb, DeviceFeature.LightColorHsv, DeviceFeature.LightColorMired;
|
|
19070
19458
|
`${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
|
|
19071
19459
|
/**
|
|
19072
19460
|
* What a composition may BUILD on a device type (G2, D676): the caps a new
|
|
@@ -20893,12 +21281,12 @@ function buildDeviceAdminUrl(parts) {
|
|
|
20893
21281
|
* providers detect renames by matching `uniqueId` and patch `id`
|
|
20894
21282
|
* in-place so dispatch keeps working.
|
|
20895
21283
|
*
|
|
20896
|
-
* **
|
|
20897
|
-
*
|
|
20898
|
-
*
|
|
20899
|
-
*
|
|
20900
|
-
* (`ha-domain-mapping`)
|
|
20901
|
-
* stored after that point.
|
|
21284
|
+
* **Display unit and precision are NOT stored here.** They are a read-time
|
|
21285
|
+
* preference (D944). A polymorphic reading stores its `quantity` here once,
|
|
21286
|
+
* at adopt, and a date/time value stores `dateTimeShape` the same way —
|
|
21287
|
+
* neither is repeated on each sample. The `device_class` tag is an
|
|
21288
|
+
* HA-specific input consumed at the discovery boundary (`ha-domain-mapping`)
|
|
21289
|
+
* to derive the CamStack `DeviceRole`; it is never stored after that point.
|
|
20902
21290
|
*
|
|
20903
21291
|
* The `raw` escape hatch carries provider-specific attributes that don't
|
|
20904
21292
|
* fit the structured slots (HA `attributes` whitelist, Reolink `deviceCache`
|
|
@@ -20912,6 +21300,14 @@ var SourceInfoSchema = object({
|
|
|
20912
21300
|
/** Immutable upstream identifier when available (HA `unique_id`, … ).
|
|
20913
21301
|
* Used to detect rename when `id` changes. */
|
|
20914
21302
|
uniqueId: string().optional(),
|
|
21303
|
+
/** Quantity of a polymorphic reading, written once at adopt (D944). */
|
|
21304
|
+
quantity: ReadingQuantitySchema.optional(),
|
|
21305
|
+
/** Date / time / datetime shape of a string reading, written once at adopt. */
|
|
21306
|
+
dateTimeShape: _enum([
|
|
21307
|
+
"date",
|
|
21308
|
+
"time",
|
|
21309
|
+
"datetime"
|
|
21310
|
+
]).optional(),
|
|
20915
21311
|
/** Provider-specific extras that don't fit the structured slots.
|
|
20916
21312
|
* Whitelist what goes here per provider — do NOT dump entire HA
|
|
20917
21313
|
* attribute blobs (would explode the meta JSON column). */
|
|
@@ -42016,7 +42412,8 @@ method(object({
|
|
|
42016
42412
|
"enum"
|
|
42017
42413
|
]),
|
|
42018
42414
|
enumValues: array(string()).optional(),
|
|
42019
|
-
item: boolean().optional()
|
|
42415
|
+
item: boolean().optional(),
|
|
42416
|
+
quantity: ReadingQuantitySchema.optional()
|
|
42020
42417
|
})).readonly(),
|
|
42021
42418
|
itemArray: object({
|
|
42022
42419
|
path: string(),
|
|
@@ -45860,8 +46257,8 @@ var MaskPolygonShapeSchema = object({
|
|
|
45860
46257
|
/** Boolean cell grid — row-major, length === gridWidth*gridHeight. */
|
|
45861
46258
|
var MaskGridShapeSchema = object({
|
|
45862
46259
|
kind: literal("grid"),
|
|
45863
|
-
gridWidth: number(),
|
|
45864
|
-
gridHeight: number(),
|
|
46260
|
+
gridWidth: number().meta(readingMeta("none")),
|
|
46261
|
+
gridHeight: number().meta(readingMeta("none")),
|
|
45865
46262
|
cells: array(boolean())
|
|
45866
46263
|
});
|
|
45867
46264
|
discriminatedUnion("kind", [
|
|
@@ -45973,6 +46370,8 @@ var NcSystemEventKindSchema = _enum([
|
|
|
45973
46370
|
"detection-blind",
|
|
45974
46371
|
"motion-noisy",
|
|
45975
46372
|
"motion-calm",
|
|
46373
|
+
"package-llm-silent",
|
|
46374
|
+
"package-llm-answered",
|
|
45976
46375
|
"recording-stalled",
|
|
45977
46376
|
"recording-healthy",
|
|
45978
46377
|
"recording-degraded",
|
|
@@ -57064,6 +57463,28 @@ var PackageVersionInfoSchema = object({
|
|
|
57064
57463
|
deprecated: string().optional(),
|
|
57065
57464
|
distTags: array(string()).readonly()
|
|
57066
57465
|
});
|
|
57466
|
+
/**
|
|
57467
|
+
* One published document. `ok` is markdown from the registry. `missing` means
|
|
57468
|
+
* the registry answered and the file was not there. `error` is a registry or
|
|
57469
|
+
* tarball failure — never an empty string standing in for either.
|
|
57470
|
+
*/
|
|
57471
|
+
var PackageDocBodySchema = discriminatedUnion("status", [
|
|
57472
|
+
object({
|
|
57473
|
+
status: literal("ok"),
|
|
57474
|
+
markdown: string()
|
|
57475
|
+
}),
|
|
57476
|
+
object({ status: literal("missing") }),
|
|
57477
|
+
object({
|
|
57478
|
+
status: literal("error"),
|
|
57479
|
+
message: string()
|
|
57480
|
+
})
|
|
57481
|
+
]);
|
|
57482
|
+
var PackageDocsSchema = object({
|
|
57483
|
+
name: string(),
|
|
57484
|
+
version: string(),
|
|
57485
|
+
readme: PackageDocBodySchema,
|
|
57486
|
+
changelog: PackageDocBodySchema
|
|
57487
|
+
});
|
|
57067
57488
|
var SearchResultSchema = object({
|
|
57068
57489
|
name: string(),
|
|
57069
57490
|
version: string(),
|
|
@@ -57282,7 +57703,10 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
|
|
|
57282
57703
|
}), object({ success: literal(true) }), {
|
|
57283
57704
|
kind: "mutation",
|
|
57284
57705
|
auth: "admin"
|
|
57285
|
-
}), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({
|
|
57706
|
+
}), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({
|
|
57707
|
+
name: string().min(1),
|
|
57708
|
+
version: string().min(1).optional()
|
|
57709
|
+
}), PackageDocsSchema, { auth: "admin" }), method(object({ addonId: string() }), RestartAddonResultSchema, {
|
|
57286
57710
|
kind: "mutation",
|
|
57287
57711
|
auth: "admin"
|
|
57288
57712
|
}), method(object({ packageName: string() }), object({ success: literal(true) }), {
|
|
@@ -57341,27 +57765,17 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
|
|
|
57341
57765
|
*/
|
|
57342
57766
|
var AirQualitySensorStatusSchema = object({
|
|
57343
57767
|
/** Carbon dioxide concentration in ppm. */
|
|
57344
|
-
co2Ppm: number().min(0).optional(),
|
|
57768
|
+
co2Ppm: number().min(0).optional().meta(readingMeta("concentration-volume")),
|
|
57345
57769
|
/** Total volatile organic compounds in ppb. */
|
|
57346
|
-
vocPpb: number().min(0).optional(),
|
|
57770
|
+
vocPpb: number().min(0).optional().meta(readingMeta("concentration-ppb")),
|
|
57347
57771
|
/** Particulate matter ≤ 2.5 μm in µg/m³. */
|
|
57348
|
-
pm25: number().min(0).optional(),
|
|
57772
|
+
pm25: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
57349
57773
|
/** Particulate matter ≤ 10 μm in µg/m³. */
|
|
57350
|
-
pm10: number().min(0).optional(),
|
|
57774
|
+
pm10: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
57351
57775
|
/** Composite AQI value (typically 0..500). */
|
|
57352
|
-
aqi: number().optional(),
|
|
57776
|
+
aqi: number().optional().meta(readingMeta("index")),
|
|
57353
57777
|
/** Ms epoch when the slice was last updated. */
|
|
57354
|
-
lastFetchedAt: number()
|
|
57355
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
57356
|
-
* `attributes.unit_of_measurement` → 'ppm' / 'ppb' / 'µg/m³'). Each
|
|
57357
|
-
* upstream `sensor.*` entity surfaces ONE device_class, so one unit
|
|
57358
|
-
* per slice is unambiguous. */
|
|
57359
|
-
unit: string().optional(),
|
|
57360
|
-
/** Suggested decimal places for numeric display.
|
|
57361
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
57362
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
57363
|
-
* auto-formatting when absent. */
|
|
57364
|
-
precision: number().int().min(0).max(10).optional()
|
|
57778
|
+
lastFetchedAt: number()
|
|
57365
57779
|
});
|
|
57366
57780
|
var airQualitySensorCapability = {
|
|
57367
57781
|
name: "air-quality-sensor",
|
|
@@ -57398,12 +57812,12 @@ var airQualitySensorCapability = {
|
|
|
57398
57812
|
},
|
|
57399
57813
|
pm25: {
|
|
57400
57814
|
kind: "gauge",
|
|
57401
|
-
unit: "
|
|
57815
|
+
unit: "µg/m³",
|
|
57402
57816
|
deadband: 1
|
|
57403
57817
|
},
|
|
57404
57818
|
pm10: {
|
|
57405
57819
|
kind: "gauge",
|
|
57406
|
-
unit: "
|
|
57820
|
+
unit: "µg/m³",
|
|
57407
57821
|
deadband: 1
|
|
57408
57822
|
},
|
|
57409
57823
|
aqi: {
|
|
@@ -57421,22 +57835,13 @@ var airQualitySensorCapability = {
|
|
|
57421
57835
|
* entries with `device_class: illuminance`.
|
|
57422
57836
|
*/
|
|
57423
57837
|
var AmbientLightSensorStatusSchema = object({
|
|
57424
|
-
/** Current illuminance in lux (lx). */
|
|
57425
|
-
lux: number().min(0).meta({
|
|
57426
|
-
|
|
57838
|
+
/** Current illuminance in lux (lx). `null` when the sample was refused (D393). */
|
|
57839
|
+
lux: number().min(0).nullable().meta(readingMeta("illuminance", {
|
|
57840
|
+
precision: 0,
|
|
57427
57841
|
label: "Illuminance"
|
|
57428
|
-
}),
|
|
57842
|
+
})),
|
|
57429
57843
|
/** Ms epoch when the slice was last updated. */
|
|
57430
|
-
lastFetchedAt: number()
|
|
57431
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
57432
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
57433
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
57434
|
-
unit: string().optional(),
|
|
57435
|
-
/** Suggested decimal places for numeric display.
|
|
57436
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
57437
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
57438
|
-
* auto-formatting when absent. */
|
|
57439
|
-
precision: number().int().min(0).max(10).optional()
|
|
57844
|
+
lastFetchedAt: number()
|
|
57440
57845
|
});
|
|
57441
57846
|
var ambientLightSensorCapability = {
|
|
57442
57847
|
name: "ambient-light-sensor",
|
|
@@ -57468,12 +57873,7 @@ var ambientLightSensorCapability = {
|
|
|
57468
57873
|
} } },
|
|
57469
57874
|
/** Clock fields: written, but excluded from the compare that decides
|
|
57470
57875
|
* whether persisting is worth a SQLite commit. */
|
|
57471
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
57472
|
-
customize: {
|
|
57473
|
-
version: 1,
|
|
57474
|
-
advanced: "derive",
|
|
57475
|
-
targets: []
|
|
57476
|
-
}
|
|
57876
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
57477
57877
|
};
|
|
57478
57878
|
/**
|
|
57479
57879
|
* Per-class audio metrics aggregated over a sliding window.
|
|
@@ -57700,10 +58100,7 @@ var BatteryStatusSchema = object({
|
|
|
57700
58100
|
* Consumers must SKIP a null rather than coerce it — `battery-band` already
|
|
57701
58101
|
* declines to band a non-finite reading, which is the correct shape.
|
|
57702
58102
|
*/
|
|
57703
|
-
percentage: number().min(0).max(100).nullable().meta({
|
|
57704
|
-
unit: "%",
|
|
57705
|
-
label: "Charge"
|
|
57706
|
-
}),
|
|
58103
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage", { label: "Charge" })),
|
|
57707
58104
|
/**
|
|
57708
58105
|
* Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
|
|
57709
58106
|
* Reolink-specific for the Solar Panel 2 accessory (will become
|
|
@@ -57730,7 +58127,14 @@ var BatteryStatusSchema = object({
|
|
|
57730
58127
|
*/
|
|
57731
58128
|
sleeping: boolean().meta({ label: "Sleeping" }),
|
|
57732
58129
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
57733
|
-
lastUpdated: number(),
|
|
58130
|
+
lastUpdated: number().meta(readingMeta("none")),
|
|
58131
|
+
/**
|
|
58132
|
+
* Battery voltage in volts, for a cell the firmware reports as voltage
|
|
58133
|
+
* rather than a percentage (Ecowitt capacitor packs). Absent on cameras
|
|
58134
|
+
* that only report charge. A second reading on this cap, not a second
|
|
58135
|
+
* `numeric-sensor` on the same device.
|
|
58136
|
+
*/
|
|
58137
|
+
volts: number().nullable().optional().meta(readingMeta("voltage", { label: "Voltage" })),
|
|
57734
58138
|
/**
|
|
57735
58139
|
* Ms epoch of the last time the device PROVED it was reachable — a
|
|
57736
58140
|
* completed firmware round-trip, an observed wake, or an inbound push
|
|
@@ -57782,7 +58186,6 @@ var BATTERY_DEVICE_TYPES = [
|
|
|
57782
58186
|
/** Generic Customize target for the percentage reading (D936). */
|
|
57783
58187
|
var batteryCustomize = {
|
|
57784
58188
|
version: 1,
|
|
57785
|
-
advanced: "derive",
|
|
57786
58189
|
targets: [{
|
|
57787
58190
|
id: "percentage",
|
|
57788
58191
|
cardinality: "scalar",
|
|
@@ -57791,7 +58194,7 @@ var batteryCustomize = {
|
|
|
57791
58194
|
stateField: "percentage"
|
|
57792
58195
|
},
|
|
57793
58196
|
deviceTypes: BATTERY_DEVICE_TYPES,
|
|
57794
|
-
apply: "add
|
|
58197
|
+
apply: "add",
|
|
57795
58198
|
path: "percentage",
|
|
57796
58199
|
sources: [{
|
|
57797
58200
|
kind: "field",
|
|
@@ -57912,10 +58315,16 @@ onStatusChanged: { data: object({
|
|
|
57912
58315
|
/**
|
|
57913
58316
|
* History (D850): recorded series. The generic capture replaces the `battery` series of `pipeline-analytics:stats-5m`.
|
|
57914
58317
|
*/
|
|
57915
|
-
history: { fields: {
|
|
57916
|
-
|
|
57917
|
-
|
|
57918
|
-
|
|
58318
|
+
history: { fields: {
|
|
58319
|
+
percentage: {
|
|
58320
|
+
kind: "gauge",
|
|
58321
|
+
unit: "%"
|
|
58322
|
+
},
|
|
58323
|
+
volts: {
|
|
58324
|
+
kind: "gauge",
|
|
58325
|
+
unit: "V"
|
|
58326
|
+
}
|
|
58327
|
+
} },
|
|
57919
58328
|
customize: batteryCustomize,
|
|
57920
58329
|
/** Clock fields: written, but excluded from the compare that decides
|
|
57921
58330
|
* whether persisting is worth a SQLite commit. */
|
|
@@ -57962,12 +58371,7 @@ var binaryCapability = {
|
|
|
57962
58371
|
history: { fields: { on: { kind: "boolean" } } },
|
|
57963
58372
|
/** Clock fields: written, but excluded from the compare that decides
|
|
57964
58373
|
* whether persisting is worth a SQLite commit. */
|
|
57965
|
-
volatileStateFields: ["lastChangedAt"]
|
|
57966
|
-
customize: {
|
|
57967
|
-
version: 1,
|
|
57968
|
-
advanced: "derive",
|
|
57969
|
-
targets: []
|
|
57970
|
-
}
|
|
58374
|
+
volatileStateFields: ["lastChangedAt"]
|
|
57971
58375
|
};
|
|
57972
58376
|
/**
|
|
57973
58377
|
* Dimmable-light brightness control. Co-exists with `switch` on the
|
|
@@ -57983,7 +58387,7 @@ var binaryCapability = {
|
|
|
57983
58387
|
*/
|
|
57984
58388
|
var BrightnessStatusSchema = object({
|
|
57985
58389
|
/** Current level as 0..100 inclusive. Firmware-reported. */
|
|
57986
|
-
percentage: number().min(0).max(100),
|
|
58390
|
+
percentage: number().min(0).max(100).meta(readingMeta("percentage")),
|
|
57987
58391
|
/** Ms epoch of the last operator-driven change. Useful for UI freshness. */
|
|
57988
58392
|
lastChangedAt: number()
|
|
57989
58393
|
});
|
|
@@ -58437,21 +58841,21 @@ var ClimateControlStatusSchema = object({
|
|
|
58437
58841
|
/** Single setpoint in Celsius. Used by single-target modes
|
|
58438
58842
|
* (heat / cool / dry). Null when the device is in a range mode
|
|
58439
58843
|
* (`heat_cool`) or has no setpoint at all (`fan_only`/`off`). */
|
|
58440
|
-
target: number().nullable(),
|
|
58844
|
+
target: number().nullable().meta(readingMeta("temperature")),
|
|
58441
58845
|
/** Upper bound of the dual setpoint in Celsius. Populated only
|
|
58442
58846
|
* in `heat_cool` mode. */
|
|
58443
|
-
targetHigh: number().nullable(),
|
|
58847
|
+
targetHigh: number().nullable().meta(readingMeta("temperature")),
|
|
58444
58848
|
/** Lower bound of the dual setpoint in Celsius. Populated only
|
|
58445
58849
|
* in `heat_cool` mode. */
|
|
58446
|
-
targetLow: number().nullable(),
|
|
58850
|
+
targetLow: number().nullable().meta(readingMeta("temperature")),
|
|
58447
58851
|
/** Target relative humidity (0..100). Null when the device has no
|
|
58448
58852
|
* humidity control. */
|
|
58449
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
58853
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
58450
58854
|
/** Current measured temperature in Celsius. Read-only — pushed by
|
|
58451
58855
|
* the device's internal sensor. */
|
|
58452
|
-
currentTemp: number().nullable(),
|
|
58856
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
58453
58857
|
/** Current measured relative humidity (0..100). Read-only. */
|
|
58454
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
58858
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
58455
58859
|
/** Vertical louver swing on/off. Null when the device has no vertical
|
|
58456
58860
|
* swing surface (gate with `DeviceFeature.ClimateSwingVertical`). */
|
|
58457
58861
|
swingVertical: boolean().nullable(),
|
|
@@ -58459,11 +58863,11 @@ var ClimateControlStatusSchema = object({
|
|
|
58459
58863
|
* horizontal swing surface (gate with `DeviceFeature.ClimateSwingHorizontal`). */
|
|
58460
58864
|
swingHorizontal: boolean().nullable(),
|
|
58461
58865
|
/** Lowest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
58462
|
-
minTemp: number().nullable().optional(),
|
|
58866
|
+
minTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
58463
58867
|
/** Highest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
58464
|
-
maxTemp: number().nullable().optional(),
|
|
58868
|
+
maxTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
58465
58869
|
/** Setpoint granularity, Celsius (0.5, 1). Absent / null = not reported. */
|
|
58466
|
-
tempStep: number().positive().nullable().optional(),
|
|
58870
|
+
tempStep: number().positive().nullable().optional().meta(readingMeta("temperature")),
|
|
58467
58871
|
/** Ms epoch when the slice was last updated (push or command). */
|
|
58468
58872
|
lastFetchedAt: number()
|
|
58469
58873
|
});
|
|
@@ -58605,17 +59009,17 @@ var climateControlCapability = {
|
|
|
58605
59009
|
* modes to expose in the picker without a slice fetch.
|
|
58606
59010
|
*/
|
|
58607
59011
|
var RgbTripletSchema = object({
|
|
58608
|
-
r: number().int().min(0).max(255),
|
|
58609
|
-
g: number().int().min(0).max(255),
|
|
58610
|
-
b: number().int().min(0).max(255)
|
|
59012
|
+
r: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
59013
|
+
g: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
59014
|
+
b: number().int().min(0).max(255).meta(readingMeta("none"))
|
|
58611
59015
|
});
|
|
58612
59016
|
var HsvTripletSchema = object({
|
|
58613
59017
|
/** Hue in degrees, 0..360. */
|
|
58614
|
-
h: number().min(0).max(360),
|
|
59018
|
+
h: number().min(0).max(360).meta(readingMeta("none")),
|
|
58615
59019
|
/** Saturation as 0..100 inclusive. */
|
|
58616
|
-
s: number().min(0).max(100),
|
|
59020
|
+
s: number().min(0).max(100).meta(readingMeta("none")),
|
|
58617
59021
|
/** Value/brightness as 0..100 inclusive. */
|
|
58618
|
-
v: number().min(0).max(100)
|
|
59022
|
+
v: number().min(0).max(100).meta(readingMeta("none"))
|
|
58619
59023
|
});
|
|
58620
59024
|
var ColorInputSchema = discriminatedUnion("mode", [
|
|
58621
59025
|
object({
|
|
@@ -58644,7 +59048,7 @@ var ColorStatusSchema = object({
|
|
|
58644
59048
|
/** Populated when `mode === 'hsv'`. */
|
|
58645
59049
|
hsv: HsvTripletSchema.optional(),
|
|
58646
59050
|
/** Populated when `mode === 'mired'`. */
|
|
58647
|
-
mireds: number().int().optional(),
|
|
59051
|
+
mireds: number().int().optional().meta(readingMeta("colour-temperature")),
|
|
58648
59052
|
/** Ms epoch of the last operator-driven change. */
|
|
58649
59053
|
lastChangedAt: number()
|
|
58650
59054
|
});
|
|
@@ -58839,18 +59243,12 @@ _enum([
|
|
|
58839
59243
|
"empty",
|
|
58840
59244
|
"full"
|
|
58841
59245
|
]);
|
|
58842
|
-
/**
|
|
58843
|
-
|
|
58844
|
-
|
|
58845
|
-
"days",
|
|
58846
|
-
"hours",
|
|
58847
|
-
"cycles"
|
|
58848
|
-
]);
|
|
58849
|
-
/** Remaining life as a COUNT, not a percentage (the PetKit desiccant reports
|
|
58850
|
-
* days). `value` null = unknown (D393). */
|
|
59246
|
+
/** Whether `remaining.value` is a duration in seconds or a dimensionless count. */
|
|
59247
|
+
var ConsumableRemainingKindSchema = _enum(["duration", "count"]);
|
|
59248
|
+
/** Remaining life. `value` null = unknown (D393). Duration is seconds. */
|
|
58851
59249
|
var ConsumableRemainingSchema = object({
|
|
58852
|
-
value: number().min(0).nullable(),
|
|
58853
|
-
|
|
59250
|
+
value: number().min(0).nullable().meta(readingMeta("device")),
|
|
59251
|
+
kind: ConsumableRemainingKindSchema
|
|
58854
59252
|
});
|
|
58855
59253
|
/** A single consumable item. Either a continuous `level` (remaining
|
|
58856
59254
|
* life %, or fill % for a `supply` / `waste` item) or a discrete `status`
|
|
@@ -58863,7 +59261,7 @@ var ConsumableItemSchema = object({
|
|
|
58863
59261
|
/** Display name. */
|
|
58864
59262
|
label: string().min(1),
|
|
58865
59263
|
/** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
|
|
58866
|
-
level: number().min(0).max(100).nullable(),
|
|
59264
|
+
level: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58867
59265
|
/** The provider's discrete verdict when known (binary mode). */
|
|
58868
59266
|
status: ConsumableStatusSchema.nullable(),
|
|
58869
59267
|
/** What the item is — decides whether low or full is bad. Absent = `wear`. */
|
|
@@ -58945,8 +59343,8 @@ var consumablesCustomize = {
|
|
|
58945
59343
|
transforms: [{ kind: "identity" }]
|
|
58946
59344
|
}],
|
|
58947
59345
|
literals: [{
|
|
58948
|
-
path: "remaining.
|
|
58949
|
-
values: [...
|
|
59346
|
+
path: "remaining.kind",
|
|
59347
|
+
values: [...ConsumableRemainingKindSchema.options]
|
|
58950
59348
|
}]
|
|
58951
59349
|
},
|
|
58952
59350
|
{
|
|
@@ -59075,7 +59473,6 @@ reset: method(object({
|
|
|
59075
59473
|
},
|
|
59076
59474
|
"remaining.value": {
|
|
59077
59475
|
kind: "gauge",
|
|
59078
|
-
unitFrom: "remaining.unit",
|
|
59079
59476
|
deadband: 1,
|
|
59080
59477
|
displayName: "Remaining"
|
|
59081
59478
|
}
|
|
@@ -59145,10 +59542,9 @@ var contactCapability = {
|
|
|
59145
59542
|
* (empty array for the other kinds). It lives in the slice because
|
|
59146
59543
|
* HA `select.*` entities may update their options at runtime.
|
|
59147
59544
|
*
|
|
59148
|
-
*
|
|
59149
|
-
*
|
|
59150
|
-
*
|
|
59151
|
-
* push — consistent with `options` and the sensor-unit approach.
|
|
59545
|
+
* Numeric `min` / `max` / `step` live in the slice and share the device
|
|
59546
|
+
* quantity (`SourceInfo.quantity`, D944). Display precision is a read-time
|
|
59547
|
+
* preference. A datetime control's shape is `SourceInfo.dateTimeShape`.
|
|
59152
59548
|
*/
|
|
59153
59549
|
var ControlStatusSchema = object({
|
|
59154
59550
|
kind: _enum([
|
|
@@ -59160,39 +59556,17 @@ var ControlStatusSchema = object({
|
|
|
59160
59556
|
/** Current value. Numeric kind → number; select/text/datetime → string.
|
|
59161
59557
|
* Datetime values are ISO 8601 strings (full timestamp, date-only,
|
|
59162
59558
|
* or time-only — HA accepts all three forms). */
|
|
59163
|
-
value: union([number(), string()]),
|
|
59559
|
+
value: union([number().meta(readingMeta("device")), string()]),
|
|
59164
59560
|
/** Acceptable values when `kind === 'select'`. Empty for other kinds. */
|
|
59165
59561
|
options: array(string()),
|
|
59166
59562
|
/** Ms epoch when the slice was last updated. */
|
|
59167
59563
|
lastChangedAt: number(),
|
|
59168
|
-
/**
|
|
59169
|
-
|
|
59170
|
-
|
|
59171
|
-
|
|
59172
|
-
/**
|
|
59173
|
-
|
|
59174
|
-
min: number().optional(),
|
|
59175
|
-
/** Maximum allowed value. Populated live from HA `attributes.max`.
|
|
59176
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
59177
|
-
max: number().optional(),
|
|
59178
|
-
/** Step increment. Populated live from HA `attributes.step`.
|
|
59179
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
59180
|
-
step: number().optional(),
|
|
59181
|
-
/** Suggested decimal places for numeric display. Populated live from HA
|
|
59182
|
-
* `attributes.suggested_display_precision`, or derived from `step` when the
|
|
59183
|
-
* HA attribute is absent. Meaningful for `kind === 'numeric'`; absent for
|
|
59184
|
-
* other kinds. Falls back to auto-formatting when absent. */
|
|
59185
|
-
precision: number().int().min(0).max(10).optional(),
|
|
59186
|
-
/** Date-picker granularity for `kind === 'datetime'`. 'date' → date-only,
|
|
59187
|
-
* 'time' → time-only, 'datetime' → full timestamp. Absent for other kinds
|
|
59188
|
-
* (UI defaults to 'datetime'). Derived live from the device's HA domain
|
|
59189
|
-
* (date.* / time.* / datetime.*) or, for input_datetime, from the entity's
|
|
59190
|
-
* `has_date`/`has_time` attributes on each push. */
|
|
59191
|
-
format: _enum([
|
|
59192
|
-
"date",
|
|
59193
|
-
"time",
|
|
59194
|
-
"datetime"
|
|
59195
|
-
]).optional()
|
|
59564
|
+
/** Minimum allowed value, in the device quantity's base unit. */
|
|
59565
|
+
min: number().optional().meta(readingMeta("device")),
|
|
59566
|
+
/** Maximum allowed value, in the device quantity's base unit. */
|
|
59567
|
+
max: number().optional().meta(readingMeta("device")),
|
|
59568
|
+
/** Step increment, in the device quantity's base unit. */
|
|
59569
|
+
step: number().optional().meta(readingMeta("device"))
|
|
59196
59570
|
});
|
|
59197
59571
|
var ControlSetValueInputSchema = discriminatedUnion("kind", [
|
|
59198
59572
|
object({
|
|
@@ -59258,9 +59632,9 @@ var CoverStatusSchema = object({
|
|
|
59258
59632
|
]),
|
|
59259
59633
|
/** 0 = fully closed, 100 = fully open. Null when the device has
|
|
59260
59634
|
* no intermediate position surface. */
|
|
59261
|
-
position: number().min(0).max(100).nullable(),
|
|
59635
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59262
59636
|
/** 0 = closed slats, 100 = open slats. Null when no tilt support. */
|
|
59263
|
-
tiltPosition: number().min(0).max(100).nullable(),
|
|
59637
|
+
tiltPosition: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59264
59638
|
/** Ms epoch when the slice was last updated. */
|
|
59265
59639
|
lastChangedAt: number()
|
|
59266
59640
|
});
|
|
@@ -59363,9 +59737,9 @@ var NormalizedRangeSchema$1 = object({
|
|
|
59363
59737
|
var DayNightStatusSchema = object({
|
|
59364
59738
|
mode: DayNightModeSchema,
|
|
59365
59739
|
/** IR-cut trigger sensitivity, NORMALIZED 0–100 (higher = switches to night sooner). */
|
|
59366
|
-
sensitivity: number().optional(),
|
|
59740
|
+
sensitivity: number().optional().meta(readingMeta("none")),
|
|
59367
59741
|
/** Delay before the IR-cut filter flips, in seconds. */
|
|
59368
|
-
switchDelaySec: number().optional(),
|
|
59742
|
+
switchDelaySec: number().optional().meta(readingMeta("duration")),
|
|
59369
59743
|
lastFetchedAt: number()
|
|
59370
59744
|
});
|
|
59371
59745
|
/**
|
|
@@ -59583,11 +59957,11 @@ var DishwasherStatusSchema = object({
|
|
|
59583
59957
|
/** Feature keys of the programs the appliance currently offers — drives the UI selector. */
|
|
59584
59958
|
availablePrograms: array(string()),
|
|
59585
59959
|
/** Seconds remaining on the active cycle, or null when not running / not known. */
|
|
59586
|
-
remainingSeconds: number().int().nonnegative().nullable(),
|
|
59960
|
+
remainingSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
59587
59961
|
/** Seconds the delayed start is set to (time until the cycle starts), or null. */
|
|
59588
|
-
delayedStartSeconds: number().int().nonnegative().nullable(),
|
|
59962
|
+
delayedStartSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
59589
59963
|
/** Cycle completion 0..100, or null when not applicable. */
|
|
59590
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
59964
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59591
59965
|
/** True when the door is reported open; null when the door state is not known. */
|
|
59592
59966
|
doorOpen: boolean().nullable(),
|
|
59593
59967
|
/** True when the door is latched (locked) during a cycle; null when not reported. */
|
|
@@ -59611,7 +59985,7 @@ var DishwasherStatusSchema = object({
|
|
|
59611
59985
|
/** True while the machine-care (descaling / cleaning-program) reminder is raised; false when clear; null when not reported. */
|
|
59612
59986
|
machineCareDue: boolean().nullable(),
|
|
59613
59987
|
/** Program runs left before the machine-care reminder is due; null when the appliance does not say. */
|
|
59614
|
-
machineCareRemainingRuns: number().int().nonnegative().nullable(),
|
|
59988
|
+
machineCareRemainingRuns: number().int().nonnegative().nullable().meta(readingMeta("count")),
|
|
59615
59989
|
/** Option states: null when the appliance does not expose the option or has not said. */
|
|
59616
59990
|
halfLoad: boolean().nullable(),
|
|
59617
59991
|
hygienePlus: boolean().nullable(),
|
|
@@ -59626,7 +60000,7 @@ var DishwasherStatusSchema = object({
|
|
|
59626
60000
|
/** Feature keys of the events currently raised (salt low, rinse aid low, program finished, …). */
|
|
59627
60001
|
activeEvents: array(string()),
|
|
59628
60002
|
/** Numeric error code when the appliance reports one; null otherwise. */
|
|
59629
|
-
errorCode: number().nullable(),
|
|
60003
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
59630
60004
|
/** Name of the raised alert-level event while the appliance is in error; null otherwise. */
|
|
59631
60005
|
errorLabel: string().nullable(),
|
|
59632
60006
|
/** Ms epoch of the last value received from the appliance; 0 = never. */
|
|
@@ -59857,7 +60231,7 @@ var DoorbellStatusSchema = object({
|
|
|
59857
60231
|
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
59858
60232
|
lastPressedAt: number().nullable(),
|
|
59859
60233
|
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
59860
|
-
pressCountSinceStart: number()
|
|
60234
|
+
pressCountSinceStart: number().meta(readingMeta("count"))
|
|
59861
60235
|
});
|
|
59862
60236
|
var DoorbellPressEventSchema = object({
|
|
59863
60237
|
deviceId: number(),
|
|
@@ -59922,17 +60296,7 @@ onPressed: {
|
|
|
59922
60296
|
history: "none",
|
|
59923
60297
|
customize: doorbellCustomize
|
|
59924
60298
|
};
|
|
59925
|
-
|
|
59926
|
-
* Enum-state sensor — a string value picked from a finite option set.
|
|
59927
|
-
* Drives HA `sensor` entries with `state_class: enum` (HVAC action
|
|
59928
|
-
* states, weather conditions, contact-source channels, mode strings).
|
|
59929
|
-
* The option set is stable across observations; it is persisted in the
|
|
59930
|
-
* device config blob (via the control slice at adoption) and is NOT
|
|
59931
|
-
* stored in `sourceInfo`.
|
|
59932
|
-
*/
|
|
59933
|
-
/** Locale-render shape for an ISO `value` carried by a `DateTimeSensor`-role
|
|
59934
|
-
* enum sensor: `date` (date-only), `time` (time-only), `datetime` (both). */
|
|
59935
|
-
var EnumSensorDateTimeFormatSchema = _enum([
|
|
60299
|
+
_enum([
|
|
59936
60300
|
"date",
|
|
59937
60301
|
"time",
|
|
59938
60302
|
"datetime"
|
|
@@ -59940,12 +60304,11 @@ var EnumSensorDateTimeFormatSchema = _enum([
|
|
|
59940
60304
|
var EnumSensorStatusSchema = object({
|
|
59941
60305
|
value: string(),
|
|
59942
60306
|
/**
|
|
59943
|
-
* Set
|
|
59944
|
-
* as
|
|
59945
|
-
*
|
|
59946
|
-
* a time-only sensor → `'time'`.
|
|
60307
|
+
* Set when `value` is a timestamp rather than an enum state, so history
|
|
60308
|
+
* does not learn ISO strings as states. The display shape (date / time /
|
|
60309
|
+
* datetime) lives on `SourceInfo.dateTimeShape`, written once at adopt.
|
|
59947
60310
|
*/
|
|
59948
|
-
|
|
60311
|
+
timestamp: boolean().optional(),
|
|
59949
60312
|
/** Ms epoch when the slice was last updated. */
|
|
59950
60313
|
lastFetchedAt: number()
|
|
59951
60314
|
});
|
|
@@ -59972,11 +60335,11 @@ var enumSensorCapability = {
|
|
|
59972
60335
|
* History (D850): the value as an `enum` series (an appliance's program or
|
|
59973
60336
|
* operation state, an HVAC action). The option set is per device, so the
|
|
59974
60337
|
* value list is LEARNED as values are first seen (bounded). A sensor with a
|
|
59975
|
-
* `
|
|
60338
|
+
* `timestamp` carries a clock, not a state, and is not recorded.
|
|
59976
60339
|
*/
|
|
59977
60340
|
history: { fields: { value: {
|
|
59978
60341
|
kind: "enum",
|
|
59979
|
-
skipWhenSet: "
|
|
60342
|
+
skipWhenSet: "timestamp"
|
|
59980
60343
|
} } },
|
|
59981
60344
|
/** Clock fields: written, but excluded from the compare that decides
|
|
59982
60345
|
* whether persisting is worth a SQLite commit. */
|
|
@@ -59996,13 +60359,13 @@ var EventFireSchema = object({
|
|
|
59996
60359
|
deviceId: number(),
|
|
59997
60360
|
eventType: string(),
|
|
59998
60361
|
data: record(string(), unknown()).nullable(),
|
|
59999
|
-
timestamp: number(),
|
|
60000
|
-
seq: number()
|
|
60362
|
+
timestamp: number().meta(readingMeta("none")),
|
|
60363
|
+
seq: number().meta(readingMeta("count"))
|
|
60001
60364
|
});
|
|
60002
60365
|
var EventEmitterStatusSchema = object({
|
|
60003
60366
|
eventTypes: array(string()),
|
|
60004
60367
|
lastEvent: EventFireSchema.nullable(),
|
|
60005
|
-
eventCountSinceStart: number()
|
|
60368
|
+
eventCountSinceStart: number().meta(readingMeta("count"))
|
|
60006
60369
|
});
|
|
60007
60370
|
var eventEmitterCapability = {
|
|
60008
60371
|
name: "event-emitter",
|
|
@@ -60415,10 +60778,10 @@ var FanDirectionSchema = _enum(["forward", "reverse"]);
|
|
|
60415
60778
|
var FanControlStatusSchema = object({
|
|
60416
60779
|
/** Active speed as 0..100 inclusive. Null when the device has no
|
|
60417
60780
|
* speed surface (single-speed fan). */
|
|
60418
|
-
percentage: number().min(0).max(100).nullable(),
|
|
60781
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
60419
60782
|
/** Speed granularity the device accepts (HA `percentage_step`, e.g. 25 for
|
|
60420
60783
|
* a 4-speed fan). Absent when unknown — the UI then falls back to step 1. */
|
|
60421
|
-
percentageStep: number().positive().optional(),
|
|
60784
|
+
percentageStep: number().positive().optional().meta(readingMeta("percentage")),
|
|
60422
60785
|
/** Active preset mode (`auto` / `quiet` / `turbo` / vendor-specific)
|
|
60423
60786
|
* — empty string when no preset is active or supported. */
|
|
60424
60787
|
preset: string(),
|
|
@@ -60539,7 +60902,7 @@ var FeatureProbeStatusSchema = object({
|
|
|
60539
60902
|
/** Camera/firmware model string. `null` when the firmware doesn't expose it. */
|
|
60540
60903
|
model: string().nullable(),
|
|
60541
60904
|
/** Channel count for NVR/Hub devices; `1` for standalone cameras; `null` pre-probe. */
|
|
60542
|
-
channelCount: number().nullable(),
|
|
60905
|
+
channelCount: number().nullable().meta(readingMeta("count")),
|
|
60543
60906
|
/**
|
|
60544
60907
|
* Ms epoch of the last SUCCESSFUL probe. `0` before the first probe
|
|
60545
60908
|
* completes — drivers' `getAccessoryChildren()` should treat zero as
|
|
@@ -60662,9 +61025,91 @@ var gasCapability = {
|
|
|
60662
61025
|
* whether persisting is worth a SQLite commit. */
|
|
60663
61026
|
volatileStateFields: ["lastChangedAt"]
|
|
60664
61027
|
};
|
|
61028
|
+
var GroupCommandsSchema = object({
|
|
61029
|
+
/** One row per member that has been commanded. A later command replaces that member's row. */
|
|
61030
|
+
results: array(object({
|
|
61031
|
+
deviceId: number().int().nonnegative(),
|
|
61032
|
+
cap: string().min(1),
|
|
61033
|
+
method: string().min(1),
|
|
61034
|
+
ok: boolean(),
|
|
61035
|
+
error: string().optional(),
|
|
61036
|
+
/** Ms epoch of the attempt. */
|
|
61037
|
+
at: number()
|
|
61038
|
+
})) });
|
|
61039
|
+
var groupCommandsCapability = {
|
|
61040
|
+
name: "group-commands",
|
|
61041
|
+
scope: "device",
|
|
61042
|
+
deviceNative: true,
|
|
61043
|
+
mode: "singleton",
|
|
61044
|
+
deviceTypes: [DeviceType.Switch, DeviceType.Light],
|
|
61045
|
+
methods: {},
|
|
61046
|
+
status: {
|
|
61047
|
+
schema: GroupCommandsSchema,
|
|
61048
|
+
kind: "push"
|
|
61049
|
+
},
|
|
61050
|
+
runtimeState: GroupCommandsSchema,
|
|
61051
|
+
/**
|
|
61052
|
+
* Runtime-state durability: **session** — the last attempt. A restored
|
|
61053
|
+
* failure would outlive the command that caused it.
|
|
61054
|
+
*
|
|
61055
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
61056
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
61057
|
+
*/
|
|
61058
|
+
durability: "session",
|
|
61059
|
+
history: "none"
|
|
61060
|
+
};
|
|
61061
|
+
/**
|
|
61062
|
+
* How many members of a helper group answered (D944). Counts are integers,
|
|
61063
|
+
* not measurements: zero included is a real count, never a stand-in reading.
|
|
61064
|
+
* The reading itself stays on the output capability. History is none — the
|
|
61065
|
+
* series that later statistics read is the output cap's own history block.
|
|
61066
|
+
*/
|
|
61067
|
+
var GroupStatusSchema = object({
|
|
61068
|
+
/** Members whose current value entered the aggregate. */
|
|
61069
|
+
included: number().int().nonnegative().meta(readingMeta("count", {
|
|
61070
|
+
precision: 0,
|
|
61071
|
+
label: "Reporting"
|
|
61072
|
+
})),
|
|
61073
|
+
/** Members left out: offline, unknown, or not a finite reading (D393). */
|
|
61074
|
+
excluded: number().int().nonnegative().meta(readingMeta("count", {
|
|
61075
|
+
precision: 0,
|
|
61076
|
+
label: "Excluded"
|
|
61077
|
+
})),
|
|
61078
|
+
/** `included` + `excluded`. */
|
|
61079
|
+
total: number().int().nonnegative().meta(readingMeta("count", {
|
|
61080
|
+
precision: 0,
|
|
61081
|
+
label: "Members"
|
|
61082
|
+
}))
|
|
61083
|
+
});
|
|
61084
|
+
var groupStatusCapability = {
|
|
61085
|
+
name: "group-status",
|
|
61086
|
+
scope: "device",
|
|
61087
|
+
deviceNative: true,
|
|
61088
|
+
mode: "singleton",
|
|
61089
|
+
deviceTypes: [
|
|
61090
|
+
DeviceType.Sensor,
|
|
61091
|
+
DeviceType.Switch,
|
|
61092
|
+
DeviceType.Light
|
|
61093
|
+
],
|
|
61094
|
+
methods: {},
|
|
61095
|
+
status: {
|
|
61096
|
+
schema: GroupStatusSchema,
|
|
61097
|
+
kind: "push"
|
|
61098
|
+
},
|
|
61099
|
+
runtimeState: GroupStatusSchema,
|
|
61100
|
+
/**
|
|
61101
|
+
* Runtime-state durability: **session** — recomputed from members on the
|
|
61102
|
+
* next source event; a restored count would outlive the readings it named.
|
|
61103
|
+
*
|
|
61104
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
61105
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
61106
|
+
*/
|
|
61107
|
+
durability: "session",
|
|
61108
|
+
history: "none"
|
|
61109
|
+
};
|
|
60665
61110
|
var HeatingValveStatusSchema = object({
|
|
60666
61111
|
/** Radiator valve opening 0 (closed) .. 100 (open). Null = not yet known. */
|
|
60667
|
-
position: number().min(0).max(100).nullable(),
|
|
61112
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
60668
61113
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
60669
61114
|
lastFetchedAt: number()
|
|
60670
61115
|
});
|
|
@@ -60707,9 +61152,9 @@ var HumidifierStatusSchema = object({
|
|
|
60707
61152
|
/** Whether the humidifier is currently on. */
|
|
60708
61153
|
on: boolean(),
|
|
60709
61154
|
/** Current measured relative humidity (0..100). Null when not reported. */
|
|
60710
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
61155
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
60711
61156
|
/** Target relative humidity (0..100). Null when no setpoint surface. */
|
|
60712
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
61157
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
60713
61158
|
/** Active mode (`auto` / `normal` / `baby` / vendor). Null when the
|
|
60714
61159
|
* device has no mode surface. */
|
|
60715
61160
|
mode: string().nullable(),
|
|
@@ -60719,9 +61164,9 @@ var HumidifierStatusSchema = object({
|
|
|
60719
61164
|
* `idle` / `off`). Null when the device doesn't report it. */
|
|
60720
61165
|
action: string().nullable(),
|
|
60721
61166
|
/** HA `min_humidity` attribute. Null → UI uses 0. */
|
|
60722
|
-
minHumidity: number().nullable(),
|
|
61167
|
+
minHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
60723
61168
|
/** HA `max_humidity` attribute. Null → UI uses 100. */
|
|
60724
|
-
maxHumidity: number().nullable(),
|
|
61169
|
+
maxHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
60725
61170
|
/** Ms epoch when the slice was last updated. */
|
|
60726
61171
|
lastChangedAt: number()
|
|
60727
61172
|
});
|
|
@@ -60791,22 +61236,13 @@ var humidifierCapability = {
|
|
|
60791
61236
|
* `sourceInfo`.
|
|
60792
61237
|
*/
|
|
60793
61238
|
var HumiditySensorStatusSchema = object({
|
|
60794
|
-
/** Current relative humidity, 0..100. */
|
|
60795
|
-
percent: number().min(0).max(100).meta({
|
|
60796
|
-
|
|
61239
|
+
/** Current relative humidity, 0..100. `null` when the sample was refused (D393). */
|
|
61240
|
+
percent: number().min(0).max(100).nullable().meta(readingMeta("humidity", {
|
|
61241
|
+
precision: 0,
|
|
60797
61242
|
label: "Humidity"
|
|
60798
|
-
}),
|
|
61243
|
+
})),
|
|
60799
61244
|
/** Ms epoch when the slice was last updated. */
|
|
60800
|
-
lastFetchedAt: number()
|
|
60801
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
60802
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
60803
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
60804
|
-
unit: string().optional(),
|
|
60805
|
-
/** Suggested decimal places for numeric display.
|
|
60806
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
60807
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
60808
|
-
* auto-formatting when absent. */
|
|
60809
|
-
precision: number().int().min(0).max(10).optional()
|
|
61245
|
+
lastFetchedAt: number()
|
|
60810
61246
|
});
|
|
60811
61247
|
var humiditySensorCapability = {
|
|
60812
61248
|
name: "humidity-sensor",
|
|
@@ -60837,12 +61273,7 @@ var humiditySensorCapability = {
|
|
|
60837
61273
|
} } },
|
|
60838
61274
|
/** Clock fields: written, but excluded from the compare that decides
|
|
60839
61275
|
* whether persisting is worth a SQLite commit. */
|
|
60840
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
60841
|
-
customize: {
|
|
60842
|
-
version: 1,
|
|
60843
|
-
advanced: "derive",
|
|
60844
|
-
targets: []
|
|
60845
|
-
}
|
|
61276
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
60846
61277
|
};
|
|
60847
61278
|
/**
|
|
60848
61279
|
* Image display cap. Models a single still image exposed by an integration —
|
|
@@ -60863,7 +61294,7 @@ var ImageStatusSchema = object({
|
|
|
60863
61294
|
* entity exposes no `entity_picture` (yet). */
|
|
60864
61295
|
url: string().nullable(),
|
|
60865
61296
|
/** Ms epoch of the upstream last-updated timestamp. Null at cold-start. */
|
|
60866
|
-
lastUpdated: number().nullable()
|
|
61297
|
+
lastUpdated: number().nullable().meta(readingMeta("none"))
|
|
60867
61298
|
});
|
|
60868
61299
|
var imageCapability = {
|
|
60869
61300
|
name: "image",
|
|
@@ -60951,19 +61382,19 @@ var NormalizedRangeSchema = object({
|
|
|
60951
61382
|
*/
|
|
60952
61383
|
var ImageSettingsStatusSchema = object({
|
|
60953
61384
|
/** Normalized 0–100. */
|
|
60954
|
-
brightness: number().optional(),
|
|
61385
|
+
brightness: number().optional().meta(readingMeta("none")),
|
|
60955
61386
|
/** Normalized 0–100. */
|
|
60956
|
-
contrast: number().optional(),
|
|
61387
|
+
contrast: number().optional().meta(readingMeta("none")),
|
|
60957
61388
|
/** Normalized 0–100. */
|
|
60958
|
-
saturation: number().optional(),
|
|
61389
|
+
saturation: number().optional().meta(readingMeta("none")),
|
|
60959
61390
|
/** Normalized 0–100. */
|
|
60960
|
-
sharpness: number().optional(),
|
|
61391
|
+
sharpness: number().optional().meta(readingMeta("none")),
|
|
60961
61392
|
mirror: boolean().optional(),
|
|
60962
61393
|
flip: boolean().optional(),
|
|
60963
61394
|
rotate: ImageRotateSchema.optional(),
|
|
60964
61395
|
whiteBalance: WhiteBalanceModeSchema.optional(),
|
|
60965
61396
|
/** Manual white-balance warmth, NORMALIZED 0–100. Meaningful only when `whiteBalance === 'manual'`. */
|
|
60966
|
-
warmth: number().optional(),
|
|
61397
|
+
warmth: number().optional().meta(readingMeta("none")),
|
|
60967
61398
|
exposureMode: ExposureModeSchema.optional(),
|
|
60968
61399
|
backlightMode: BacklightModeSchema.optional(),
|
|
60969
61400
|
lastFetchedAt: number()
|
|
@@ -61242,10 +61673,10 @@ var IntercomAbilitySchema = object({
|
|
|
61242
61673
|
/** Codecs accepted by firmware, in preference order. Driver-authored strings. */
|
|
61243
61674
|
codecs: array(string()),
|
|
61244
61675
|
/** Sample rate (Hz) the firmware expects. Reolink typical: 16000. */
|
|
61245
|
-
sampleRate: number(),
|
|
61676
|
+
sampleRate: number().meta(readingMeta("none")),
|
|
61246
61677
|
duplex: _enum(["half", "full"]),
|
|
61247
61678
|
/** Max in-flight audio backlog before drop (ms). Server uses this to bound latency. */
|
|
61248
|
-
maxBacklogMs: number()
|
|
61679
|
+
maxBacklogMs: number().meta(readingMeta("duration-ms"))
|
|
61249
61680
|
});
|
|
61250
61681
|
var IntercomStatusSchema = object({
|
|
61251
61682
|
/** True while a talk session is open. */
|
|
@@ -61472,13 +61903,13 @@ var LawnMowerControlStatusSchema = object({
|
|
|
61472
61903
|
activity: LawnMowerActivitySchema,
|
|
61473
61904
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
61474
61905
|
* reading. */
|
|
61475
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
61906
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61476
61907
|
/** 0..100 mowing-completion percentage of the current task, or null when no
|
|
61477
61908
|
* task is active / progress is unavailable. */
|
|
61478
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
61909
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61479
61910
|
/** Current device/event code (dynamic — mostly status, sometimes an error),
|
|
61480
61911
|
* or null when unknown. */
|
|
61481
|
-
currentCode: number().nullable(),
|
|
61912
|
+
currentCode: number().nullable().meta(readingMeta("none")),
|
|
61482
61913
|
/** Human label for {@link currentCode}, or null when undecodable. */
|
|
61483
61914
|
currentCodeLabel: string().nullable(),
|
|
61484
61915
|
/** Severity of {@link currentCode}. `error` (and often `warning`) warrants UI
|
|
@@ -62011,7 +62442,7 @@ var MediaPlayerStatusSchema = object({
|
|
|
62011
62442
|
state: MediaPlayerStateSchema,
|
|
62012
62443
|
/** Volume as 0..100 inclusive. Null when the device has no volume
|
|
62013
62444
|
* surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
|
|
62014
|
-
volumeLevel: number().min(0).max(100).nullable(),
|
|
62445
|
+
volumeLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
62015
62446
|
/** Mute toggle distinct from volume=0. Null when no mute surface.
|
|
62016
62447
|
* Pair with `DeviceFeature.MediaPlayerMute`. */
|
|
62017
62448
|
isMuted: boolean().nullable(),
|
|
@@ -62024,10 +62455,10 @@ var MediaPlayerStatusSchema = object({
|
|
|
62024
62455
|
currentMedia: MediaInfoSchema.nullable(),
|
|
62025
62456
|
/** Current playback position in ms. Null when not seekable or
|
|
62026
62457
|
* nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
|
|
62027
|
-
positionMs: number().int().nonnegative().nullable(),
|
|
62458
|
+
positionMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
62028
62459
|
/** Total duration of the current media in ms. Null when unknown
|
|
62029
62460
|
* (live stream) or nothing is playing. */
|
|
62030
|
-
durationMs: number().int().nonnegative().nullable(),
|
|
62461
|
+
durationMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
62031
62462
|
/** Shuffle toggle. Null when no shuffle surface.
|
|
62032
62463
|
* Pair with `DeviceFeature.MediaPlayerShuffle`. */
|
|
62033
62464
|
shuffle: boolean().nullable(),
|
|
@@ -62336,7 +62767,7 @@ var motionCustomize = {
|
|
|
62336
62767
|
eventName: "onMotionChanged"
|
|
62337
62768
|
},
|
|
62338
62769
|
deviceTypes: [DeviceType.Camera],
|
|
62339
|
-
apply: "
|
|
62770
|
+
apply: "add",
|
|
62340
62771
|
applyAuthority: {
|
|
62341
62772
|
kind: "camera-sensors",
|
|
62342
62773
|
timeoutField: "motionCooldownMs"
|
|
@@ -62408,7 +62839,7 @@ var MotionStatusSchema = object({
|
|
|
62408
62839
|
* it, every provider seeded it at boot, and every session left it
|
|
62409
62840
|
* `detected: true` after its detach.
|
|
62410
62841
|
*/
|
|
62411
|
-
autoClearAfterMs: number().nullable()
|
|
62842
|
+
autoClearAfterMs: number().nullable().meta(readingMeta("duration-ms"))
|
|
62412
62843
|
});
|
|
62413
62844
|
/**
|
|
62414
62845
|
* Payload of `motion.onMotionChanged` event + the corresponding bus
|
|
@@ -62445,12 +62876,18 @@ var motionCapability = {
|
|
|
62445
62876
|
methods: {
|
|
62446
62877
|
/**
|
|
62447
62878
|
* Pull the current motion state synchronously. Convenience shortcut
|
|
62448
|
-
* for consumers that don't need the full status object
|
|
62449
|
-
*
|
|
62450
|
-
* `getStatus` once the auto-injected status surface lands in every
|
|
62451
|
-
* consumer.
|
|
62879
|
+
* for consumers that don't need the full status object. A composed
|
|
62880
|
+
* group answers from its slice (D944): unknown throws, it is not off.
|
|
62452
62881
|
*/
|
|
62453
62882
|
isDetected: method(object({ deviceId: number() }), boolean()) },
|
|
62883
|
+
/**
|
|
62884
|
+
* A composed motion group serves `isDetected` from `detected` (D944).
|
|
62885
|
+
* Without this the cap stays uncomposable (`has-commands`).
|
|
62886
|
+
*/
|
|
62887
|
+
composedMethods: { isDetected: {
|
|
62888
|
+
kind: "slice",
|
|
62889
|
+
field: "detected"
|
|
62890
|
+
} },
|
|
62454
62891
|
events: {
|
|
62455
62892
|
/**
|
|
62456
62893
|
* Fires every time the runner transitions a camera between
|
|
@@ -62590,7 +63027,7 @@ var MotionZoneRegionSchema = object({
|
|
|
62590
63027
|
* the grid region(s). */
|
|
62591
63028
|
var MotionZoneStatusSchema = object({
|
|
62592
63029
|
enabled: boolean(),
|
|
62593
|
-
sensitivity: number(),
|
|
63030
|
+
sensitivity: number().meta(readingMeta("none")),
|
|
62594
63031
|
/** Grid region(s). Today exactly one `grid` shape. */
|
|
62595
63032
|
regions: array(MotionZoneRegionSchema),
|
|
62596
63033
|
lastFetchedAt: number()
|
|
@@ -62960,7 +63397,7 @@ var NavigationStatusSchema = object({
|
|
|
62960
63397
|
following: boolean(),
|
|
62961
63398
|
flash: boolean(),
|
|
62962
63399
|
lightMode: NavigationLightModeSchema,
|
|
62963
|
-
lightLevel: number().min(40).max(100),
|
|
63400
|
+
lightLevel: number().min(40).max(100).meta(readingMeta("none")),
|
|
62964
63401
|
/** Ms epoch when the slice was last updated. */
|
|
62965
63402
|
lastChangedAt: number()
|
|
62966
63403
|
});
|
|
@@ -63094,13 +63531,13 @@ var NetworkLinkStatusSchema = object({
|
|
|
63094
63531
|
* one whose reading has not landed must not be drawn at 0 %. Consumers
|
|
63095
63532
|
* SKIP a null rather than coerce it.
|
|
63096
63533
|
*/
|
|
63097
|
-
signalPercent: number().min(0).max(100).nullable(),
|
|
63534
|
+
signalPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
63098
63535
|
/** Raw received signal strength in dBm, when the firmware reports one. */
|
|
63099
|
-
rssiDbm: number().optional(),
|
|
63536
|
+
rssiDbm: number().optional().meta(readingMeta("signal-level")),
|
|
63100
63537
|
/** Network name of a wireless link, when the firmware reports it. */
|
|
63101
63538
|
ssid: string().optional(),
|
|
63102
63539
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
63103
|
-
lastUpdated: number()
|
|
63540
|
+
lastUpdated: number().meta(readingMeta("none"))
|
|
63104
63541
|
});
|
|
63105
63542
|
var networkLinkCapability = {
|
|
63106
63543
|
name: "network-link",
|
|
@@ -63485,7 +63922,7 @@ var NotifierStatusSchema = object({
|
|
|
63485
63922
|
lastError: string().nullable(),
|
|
63486
63923
|
/** Number of deliveries currently buffered server-side (rate-limited
|
|
63487
63924
|
* notifiers may queue). 0 when the provider sends synchronously. */
|
|
63488
|
-
queueDepth: number().int().nonnegative(),
|
|
63925
|
+
queueDepth: number().int().nonnegative().meta(readingMeta("count")),
|
|
63489
63926
|
/** Per-feature capability matrix — authoritative source for the
|
|
63490
63927
|
* compose-form field gating. */
|
|
63491
63928
|
supports: NotifierSupportsSchema
|
|
@@ -63577,11 +64014,9 @@ onSent: { data: object({
|
|
|
63577
64014
|
* cap fits (HA `sensor` whose `device_class` we don't have a typed cap
|
|
63578
64015
|
* for: water flow, distance, weight, frequency, signal strength, …).
|
|
63579
64016
|
*
|
|
63580
|
-
* The
|
|
63581
|
-
*
|
|
63582
|
-
*
|
|
63583
|
-
* The UI reads them directly from the slice — they are the single source
|
|
63584
|
-
* of truth for generic numeric rendering and do NOT live on `sourceInfo`.
|
|
64017
|
+
* The quantity is not on this slice. It is chosen when the device is
|
|
64018
|
+
* adopted and stored once on `SourceInfo.quantity` (D944). `value` is in
|
|
64019
|
+
* that quantity's base unit. `null` is a refused sample (D393).
|
|
63585
64020
|
*
|
|
63586
64021
|
* Prefer the typed alternatives (`temperature-sensor`, `humidity-sensor`,
|
|
63587
64022
|
* `ambient-light-sensor`, `pressure-sensor`, `power-meter`,
|
|
@@ -63590,15 +64025,8 @@ onSent: { data: object({
|
|
|
63590
64025
|
* numeric values land here.
|
|
63591
64026
|
*/
|
|
63592
64027
|
var NumericSensorStatusSchema = object({
|
|
63593
|
-
|
|
63594
|
-
|
|
63595
|
-
* Populated live from the upstream source on each state push.
|
|
63596
|
-
* Absent for unitless sensors. */
|
|
63597
|
-
unit: string().optional(),
|
|
63598
|
-
/** Suggested decimal places for numeric display.
|
|
63599
|
-
* Populated live from the upstream source when provided.
|
|
63600
|
-
* Falls back to auto-formatting when absent. */
|
|
63601
|
-
precision: number().int().min(0).max(10).optional(),
|
|
64028
|
+
/** Reading in the device quantity's base unit. `null` when refused (D393). */
|
|
64029
|
+
value: number().nullable().meta(readingMeta("device")),
|
|
63602
64030
|
/** Ms epoch when the slice was last updated. */
|
|
63603
64031
|
lastFetchedAt: number()
|
|
63604
64032
|
});
|
|
@@ -63622,11 +64050,11 @@ var numericSensorCapability = {
|
|
|
63622
64050
|
*/
|
|
63623
64051
|
durability: "restored",
|
|
63624
64052
|
/**
|
|
63625
|
-
* History (D850): recorded series. The unit is
|
|
64053
|
+
* History (D850): recorded series. The unit is the device quantity's base,
|
|
64054
|
+
* resolved when the series is read — the cap has no single unit.
|
|
63626
64055
|
*/
|
|
63627
64056
|
history: { fields: { value: {
|
|
63628
64057
|
kind: "gauge",
|
|
63629
|
-
unitFrom: "unit",
|
|
63630
64058
|
minIntervalMs: 3e4
|
|
63631
64059
|
} } },
|
|
63632
64060
|
/** Clock fields: written, but excluded from the compare that decides
|
|
@@ -63918,23 +64346,26 @@ var PetFeederStatusSchema = object({
|
|
|
63918
64346
|
/** Food currently in the bowl (grams). Null when the device has not
|
|
63919
64347
|
* reported a reading yet. On dual-hopper models this is the combined
|
|
63920
64348
|
* bowl reading; per-hopper levels live in `food1`/`food2`. */
|
|
63921
|
-
foodLevel: number().nullable(),
|
|
64349
|
+
foodLevel: number().nullable().meta(readingMeta("none")),
|
|
63922
64350
|
/** Hopper-1 food level (grams) on dual-hopper feeders; null on
|
|
63923
64351
|
* single-hopper models. */
|
|
63924
|
-
food1: number().nullable(),
|
|
64352
|
+
food1: number().nullable().meta(readingMeta("none")),
|
|
63925
64353
|
/** Hopper-2 food level (grams) on dual-hopper feeders; null on
|
|
63926
64354
|
* single-hopper models. */
|
|
63927
|
-
food2: number().nullable(),
|
|
64355
|
+
food2: number().nullable().meta(readingMeta("none")),
|
|
63928
64356
|
/** Derived low-food flag — mirrors the HA `food_level` binary_sensor
|
|
63929
64357
|
* (`device_class: problem`, on = low). True when the bowl is empty /
|
|
63930
64358
|
* below the feeder's low threshold. */
|
|
63931
64359
|
lowFood: boolean(),
|
|
63932
64360
|
/** Battery charge 0..100 (%). Null on mains-powered models or when the
|
|
63933
64361
|
* device has no battery reading. */
|
|
63934
|
-
batteryPower: number().min(0).max(100).nullable(),
|
|
63935
|
-
/**
|
|
63936
|
-
*
|
|
63937
|
-
|
|
64362
|
+
batteryPower: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
64363
|
+
/**
|
|
64364
|
+
* Desiccant life remaining, stored in seconds (duration base, D944).
|
|
64365
|
+
* Providers convert from the days the feeder reports. Null when the
|
|
64366
|
+
* model has no desiccant sensor.
|
|
64367
|
+
*/
|
|
64368
|
+
desiccantLeftDays: number().nullable().meta(readingMeta("duration")),
|
|
63938
64369
|
/** True while a feed is in progress. */
|
|
63939
64370
|
feeding: boolean(),
|
|
63940
64371
|
/** Decoded connectivity / power status (HA petkit device-status enum).
|
|
@@ -63945,7 +64376,7 @@ var PetFeederStatusSchema = object({
|
|
|
63945
64376
|
* with `errorCode` for consumers that want the raw integer. */
|
|
63946
64377
|
error: string().nullable(),
|
|
63947
64378
|
/** Raw device error code (0 / null = no error). */
|
|
63948
|
-
errorCode: number().nullable(),
|
|
64379
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
63949
64380
|
/** True for D4S/D4SH dual-hopper hardware — gates the per-hopper UI. */
|
|
63950
64381
|
isDualHopper: boolean(),
|
|
63951
64382
|
/** Child-lock (manual-lock) setting — buttons on the unit are disabled. */
|
|
@@ -63955,7 +64386,7 @@ var PetFeederStatusSchema = object({
|
|
|
63955
64386
|
/** Play a chime when dispensing. */
|
|
63956
64387
|
feedSound: boolean(),
|
|
63957
64388
|
/** Speaker / prompt volume level (device-scaled integer). */
|
|
63958
|
-
volume: number(),
|
|
64389
|
+
volume: number().meta(readingMeta("none")),
|
|
63959
64390
|
/** Ms epoch when the slice was last refreshed from the cloud. */
|
|
63960
64391
|
lastFetchedAt: number()
|
|
63961
64392
|
});
|
|
@@ -64074,7 +64505,7 @@ var petFeederCapability = {
|
|
|
64074
64505
|
},
|
|
64075
64506
|
desiccantLeftDays: {
|
|
64076
64507
|
kind: "gauge",
|
|
64077
|
-
unit: "
|
|
64508
|
+
unit: "s"
|
|
64078
64509
|
}
|
|
64079
64510
|
} }
|
|
64080
64511
|
};
|
|
@@ -64475,36 +64906,19 @@ method(_void(), PlatformCapabilitiesSchema), method(_void(), HardwareInfoSchema)
|
|
|
64475
64906
|
*/
|
|
64476
64907
|
var PowerMeterStatusSchema = object({
|
|
64477
64908
|
/** Instantaneous power draw in watts. */
|
|
64478
|
-
watts: number().optional().meta({
|
|
64479
|
-
unit: "W",
|
|
64480
|
-
label: "Power"
|
|
64481
|
-
}),
|
|
64909
|
+
watts: number().optional().meta(readingMeta("power", { label: "Power" })),
|
|
64482
64910
|
/** Cumulative energy in kilowatt-hours since the meter was reset. */
|
|
64483
|
-
kwhTotal: number().optional().meta({
|
|
64484
|
-
unit: "kWh",
|
|
64485
|
-
label: "Energy"
|
|
64486
|
-
}),
|
|
64911
|
+
kwhTotal: number().optional().meta(readingMeta("energy", { label: "Energy" })),
|
|
64487
64912
|
/** Voltage in volts. */
|
|
64488
|
-
volts: number().optional(),
|
|
64913
|
+
volts: number().optional().meta(readingMeta("voltage")),
|
|
64489
64914
|
/** Current in amperes. */
|
|
64490
|
-
amps: number().optional(),
|
|
64491
|
-
/** Apparent power in volt-amperes
|
|
64492
|
-
va: number().optional(),
|
|
64915
|
+
amps: number().optional().meta(readingMeta("current")),
|
|
64916
|
+
/** Apparent power in volt-amperes. */
|
|
64917
|
+
va: number().optional().meta(readingMeta("apparent-power")),
|
|
64493
64918
|
/** Power factor (0..1) if reported. */
|
|
64494
|
-
powerFactor: number().min(0).max(1).optional(),
|
|
64919
|
+
powerFactor: number().min(0).max(1).optional().meta(readingMeta("ratio")),
|
|
64495
64920
|
/** Ms epoch when the slice was last updated. */
|
|
64496
|
-
lastFetchedAt: number()
|
|
64497
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
64498
|
-
* `attributes.unit_of_measurement` → 'V' / 'A' / 'W' / 'kW' / 'kWh').
|
|
64499
|
-
* Each upstream `sensor.*` entity surfaces ONE device_class, so one
|
|
64500
|
-
* unit per slice is unambiguous. The UI prefers this over the role's
|
|
64501
|
-
* canonical unit so a 'kW' / 'Wh' feed renders verbatim. */
|
|
64502
|
-
unit: string().optional(),
|
|
64503
|
-
/** Suggested decimal places for numeric display.
|
|
64504
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
64505
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
64506
|
-
* auto-formatting when absent. */
|
|
64507
|
-
precision: number().int().min(0).max(10).optional()
|
|
64921
|
+
lastFetchedAt: number()
|
|
64508
64922
|
});
|
|
64509
64923
|
var powerMeterCapability = {
|
|
64510
64924
|
name: "power-meter",
|
|
@@ -64568,12 +64982,7 @@ var powerMeterCapability = {
|
|
|
64568
64982
|
} },
|
|
64569
64983
|
/** Clock fields: written, but excluded from the compare that decides
|
|
64570
64984
|
* whether persisting is worth a SQLite commit. */
|
|
64571
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
64572
|
-
customize: {
|
|
64573
|
-
version: 1,
|
|
64574
|
-
advanced: "derive",
|
|
64575
|
-
targets: []
|
|
64576
|
-
}
|
|
64985
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
64577
64986
|
};
|
|
64578
64987
|
/**
|
|
64579
64988
|
* Presence cap. Models HA `person.*` and `device_tracker.*` entities
|
|
@@ -64593,11 +65002,11 @@ var powerMeterCapability = {
|
|
|
64593
65002
|
*/
|
|
64594
65003
|
var GpsLocationSchema = object({
|
|
64595
65004
|
/** Latitude in decimal degrees, -90..90. */
|
|
64596
|
-
latitude: number().min(-90).max(90),
|
|
65005
|
+
latitude: number().min(-90).max(90).meta(readingMeta("angle")),
|
|
64597
65006
|
/** Longitude in decimal degrees, -180..180. */
|
|
64598
|
-
longitude: number().min(-180).max(180),
|
|
65007
|
+
longitude: number().min(-180).max(180).meta(readingMeta("angle")),
|
|
64599
65008
|
/** Reported accuracy in meters (lower = better). */
|
|
64600
|
-
accuracyMeters: number().nonnegative()
|
|
65009
|
+
accuracyMeters: number().nonnegative().meta(readingMeta("length"))
|
|
64601
65010
|
});
|
|
64602
65011
|
var PresenceStatusSchema = object({
|
|
64603
65012
|
/** `home` / `not_home` / any user-defined zone name. */
|
|
@@ -64609,7 +65018,7 @@ var PresenceStatusSchema = object({
|
|
|
64609
65018
|
gps: GpsLocationSchema.nullable(),
|
|
64610
65019
|
/** Optional battery level of the tracking device (0..100). Null
|
|
64611
65020
|
* when not reported. */
|
|
64612
|
-
batteryPercent: number().min(0).max(100).nullable(),
|
|
65021
|
+
batteryPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
64613
65022
|
/** Ms epoch when the slice was last updated. */
|
|
64614
65023
|
lastChangedAt: number()
|
|
64615
65024
|
});
|
|
@@ -64659,19 +65068,10 @@ var presenceCapability = {
|
|
|
64659
65068
|
* `sourceInfo`.
|
|
64660
65069
|
*/
|
|
64661
65070
|
var PressureSensorStatusSchema = object({
|
|
64662
|
-
/** Current pressure in hPa. */
|
|
64663
|
-
hpa: number(),
|
|
65071
|
+
/** Current pressure in hPa. `null` when the sample was refused (D393). */
|
|
65072
|
+
hpa: number().nullable().meta(readingMeta("pressure", { precision: 0 })),
|
|
64664
65073
|
/** Ms epoch when the slice was last updated. */
|
|
64665
|
-
lastFetchedAt: number()
|
|
64666
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
64667
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
64668
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
64669
|
-
unit: string().optional(),
|
|
64670
|
-
/** Suggested decimal places for numeric display.
|
|
64671
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
64672
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
64673
|
-
* auto-formatting when absent. */
|
|
64674
|
-
precision: number().int().min(0).max(10).optional()
|
|
65074
|
+
lastFetchedAt: number()
|
|
64675
65075
|
});
|
|
64676
65076
|
var pressureSensorCapability = {
|
|
64677
65077
|
name: "pressure-sensor",
|
|
@@ -65085,8 +65485,8 @@ DeviceType.Camera, method(PtzMoveCommandSchema.extend({ deviceId: number() }), _
|
|
|
65085
65485
|
}), _void(), { kind: "mutation" });
|
|
65086
65486
|
var PtzAutotrackSettingsSchema = object({
|
|
65087
65487
|
targetType: string().describe("Vendor target string (people/vehicle/pet); empty = camera default"),
|
|
65088
|
-
stopDelaySeconds: number().int().min(0).max(300),
|
|
65089
|
-
disappearDelaySeconds: number().int().min(0).max(300)
|
|
65488
|
+
stopDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration")),
|
|
65489
|
+
disappearDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration"))
|
|
65090
65490
|
});
|
|
65091
65491
|
/**
|
|
65092
65492
|
* One option the camera advertises as a valid `targetType`. Drivers
|
|
@@ -65240,7 +65640,7 @@ var RunningStateStatusSchema = object({
|
|
|
65240
65640
|
/** null = unknown — never coerced to false (D393). */
|
|
65241
65641
|
running: boolean().nullable(),
|
|
65242
65642
|
/** Epoch ms the current boolean began; null while `running` is null. */
|
|
65243
|
-
since: number().nullable(),
|
|
65643
|
+
since: number().nullable().meta(readingMeta("none")),
|
|
65244
65644
|
source: RunningStateSourceSchema.meta({ label: "Source" }),
|
|
65245
65645
|
phase: string().nullable(),
|
|
65246
65646
|
/** null until a reading has been published (D393). */
|
|
@@ -65255,7 +65655,6 @@ var RUNNING_DEVICE_TYPES = Object.values(DeviceType);
|
|
|
65255
65655
|
/** Generic Customize target for the running boolean (D936). */
|
|
65256
65656
|
var runningCustomize = {
|
|
65257
65657
|
version: 1,
|
|
65258
|
-
advanced: "derive",
|
|
65259
65658
|
targets: [{
|
|
65260
65659
|
id: "running",
|
|
65261
65660
|
cardinality: "scalar",
|
|
@@ -65275,7 +65674,7 @@ var runningCustomize = {
|
|
|
65275
65674
|
DeviceType.Thermostat,
|
|
65276
65675
|
DeviceType.PetFeeder
|
|
65277
65676
|
],
|
|
65278
|
-
apply: "add
|
|
65677
|
+
apply: "add",
|
|
65279
65678
|
path: "running",
|
|
65280
65679
|
sources: [
|
|
65281
65680
|
{
|
|
@@ -66539,9 +66938,9 @@ var RecordTriggerSchema = _enum([
|
|
|
66539
66938
|
*/
|
|
66540
66939
|
var RecordWindowSchema = object({
|
|
66541
66940
|
trigger: RecordTriggerSchema,
|
|
66542
|
-
day: number().int().min(0).max(6),
|
|
66543
|
-
startMinute: number().int().min(0).max(1439),
|
|
66544
|
-
endMinute: number().int().min(1).max(1440)
|
|
66941
|
+
day: number().int().min(0).max(6).meta(readingMeta("none")),
|
|
66942
|
+
startMinute: number().int().min(0).max(1439).meta(readingMeta("none")),
|
|
66943
|
+
endMinute: number().int().min(1).max(1440).meta(readingMeta("none"))
|
|
66545
66944
|
});
|
|
66546
66945
|
/** Status of one physical volume, as the camera itself describes it. */
|
|
66547
66946
|
var OnboardStorageVolumeSchema = object({
|
|
@@ -66617,10 +67016,10 @@ var RecordingOnboardStatusSchema = object({
|
|
|
66617
67016
|
/** Master "record to the card at all" switch. */
|
|
66618
67017
|
enabled: boolean().nullable(),
|
|
66619
67018
|
overwriteWhenFull: boolean().nullable(),
|
|
66620
|
-
preRecordSec: number().nullable(),
|
|
66621
|
-
postRecordSec: number().nullable(),
|
|
67019
|
+
preRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
67020
|
+
postRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
66622
67021
|
/** Length of one recorded file, in minutes. */
|
|
66623
|
-
segmentMinutes: number().nullable(),
|
|
67022
|
+
segmentMinutes: number().nullable().meta(readingMeta("none")),
|
|
66624
67023
|
/** The primary track's weekly windows, flattened. */
|
|
66625
67024
|
windows: array(RecordWindowSchema),
|
|
66626
67025
|
/**
|
|
@@ -66636,7 +67035,7 @@ var RecordingOnboardStatusSchema = object({
|
|
|
66636
67035
|
* provider reporting a non-zero count also reports the schedule as not
|
|
66637
67036
|
* writable.
|
|
66638
67037
|
*/
|
|
66639
|
-
unreadableWindows: number(),
|
|
67038
|
+
unreadableWindows: number().meta(readingMeta("count")),
|
|
66640
67039
|
/**
|
|
66641
67040
|
* The camera is scheduled to record and has NO usable storage.
|
|
66642
67041
|
*
|
|
@@ -67481,7 +67880,7 @@ var CamStreamDescriptorSchema = object({
|
|
|
67481
67880
|
url: string().optional(),
|
|
67482
67881
|
codec: string().optional(),
|
|
67483
67882
|
resolution: CamStreamResolutionSchema.optional(),
|
|
67484
|
-
fps: number().positive().optional(),
|
|
67883
|
+
fps: number().positive().optional().meta(readingMeta("rate")),
|
|
67485
67884
|
label: string().optional(),
|
|
67486
67885
|
/** Device-level features (e.g. `battery-operated`) — drives broker policy. */
|
|
67487
67886
|
deviceFeatures: array(string()).optional(),
|
|
@@ -67568,18 +67967,18 @@ var StreamProfileSchema = _enum([
|
|
|
67568
67967
|
]);
|
|
67569
67968
|
/** The current encoding config of one stream profile. */
|
|
67570
67969
|
var StreamProfileConfigSchema = object({
|
|
67571
|
-
width: number(),
|
|
67572
|
-
height: number(),
|
|
67970
|
+
width: number().meta(readingMeta("none")),
|
|
67971
|
+
height: number().meta(readingMeta("none")),
|
|
67573
67972
|
codec: _enum(["h264", "h265"]),
|
|
67574
|
-
framerate: number(),
|
|
67575
|
-
bitrate: number(),
|
|
67973
|
+
framerate: number().meta(readingMeta("rate")),
|
|
67974
|
+
bitrate: number().meta(readingMeta("bitrate")),
|
|
67576
67975
|
bitrateMode: _enum(["vbr", "cbr"]).optional(),
|
|
67577
67976
|
encoderProfile: _enum([
|
|
67578
67977
|
"high",
|
|
67579
67978
|
"main",
|
|
67580
67979
|
"baseline"
|
|
67581
67980
|
]).optional(),
|
|
67582
|
-
gop: number().optional(),
|
|
67981
|
+
gop: number().optional().meta(readingMeta("none")),
|
|
67583
67982
|
/**
|
|
67584
67983
|
* Whether THIS profile currently carries an audio track. READ-ONLY here.
|
|
67585
67984
|
*
|
|
@@ -67800,12 +68199,7 @@ var switchCapability = {
|
|
|
67800
68199
|
label: "On",
|
|
67801
68200
|
kind: "boolean"
|
|
67802
68201
|
}
|
|
67803
|
-
}] }
|
|
67804
|
-
customize: {
|
|
67805
|
-
version: 1,
|
|
67806
|
-
advanced: "derive",
|
|
67807
|
-
targets: []
|
|
67808
|
-
}
|
|
68202
|
+
}] }
|
|
67809
68203
|
};
|
|
67810
68204
|
/** C0 controls, DEL and the C1 range: none of them belongs in a name. */
|
|
67811
68205
|
function hasControlCharacter(value) {
|
|
@@ -68388,35 +68782,21 @@ var tamperCapability = {
|
|
|
68388
68782
|
* entries with `device_class: temperature` and any future native
|
|
68389
68783
|
* thermometer.
|
|
68390
68784
|
*
|
|
68391
|
-
*
|
|
68392
|
-
*
|
|
68393
|
-
* (climate-control's `currentTemp`, energy analytics) can compose
|
|
68394
|
-
* without per-source unit fixups. The canonical display unit (`°C`) is
|
|
68395
|
-
* a descriptor constant in the UI (ROLE_DESCRIPTOR), not stored in
|
|
68396
|
-
* `sourceInfo`.
|
|
68785
|
+
* The number is Celsius (D944). Providers convert on ingest. A failed
|
|
68786
|
+
* conversion is `null`, never a guess. Display unit is a read-time preference.
|
|
68397
68787
|
*
|
|
68398
68788
|
* Status `lastFetchedAt` lets staleness-aware consumers detect a
|
|
68399
68789
|
* frozen feed (provider hung) distinct from a "temperature hasn't
|
|
68400
68790
|
* changed" steady state.
|
|
68401
68791
|
*/
|
|
68402
68792
|
var TemperatureSensorStatusSchema = object({
|
|
68403
|
-
/** Current temperature in Celsius. */
|
|
68404
|
-
celsius: number().meta({
|
|
68405
|
-
|
|
68793
|
+
/** Current temperature in Celsius. `null` when the sample was refused (D393). */
|
|
68794
|
+
celsius: number().nullable().meta(readingMeta("temperature", {
|
|
68795
|
+
precision: 1,
|
|
68406
68796
|
label: "Temperature"
|
|
68407
|
-
}),
|
|
68797
|
+
})),
|
|
68408
68798
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
68409
|
-
lastFetchedAt: number()
|
|
68410
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
68411
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
68412
|
-
* role's canonical unit, so a Fahrenheit feed renders '°F' not '°C'.
|
|
68413
|
-
* Absent → the UI falls back to the role's canonical unit. */
|
|
68414
|
-
unit: string().optional(),
|
|
68415
|
-
/** Suggested decimal places for numeric display.
|
|
68416
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
68417
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
68418
|
-
* auto-formatting when absent. */
|
|
68419
|
-
precision: number().int().min(0).max(10).optional()
|
|
68799
|
+
lastFetchedAt: number()
|
|
68420
68800
|
});
|
|
68421
68801
|
var temperatureSensorCapability = {
|
|
68422
68802
|
name: "temperature-sensor",
|
|
@@ -68447,12 +68827,7 @@ var temperatureSensorCapability = {
|
|
|
68447
68827
|
} } },
|
|
68448
68828
|
/** Clock fields: written, but excluded from the compare that decides
|
|
68449
68829
|
* whether persisting is worth a SQLite commit. */
|
|
68450
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
68451
|
-
customize: {
|
|
68452
|
-
version: 1,
|
|
68453
|
-
advanced: "derive",
|
|
68454
|
-
targets: []
|
|
68455
|
-
}
|
|
68830
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
68456
68831
|
};
|
|
68457
68832
|
/**
|
|
68458
68833
|
* toast — system-scoped singleton capability that streams toast
|
|
@@ -68735,16 +69110,16 @@ var VacuumControlStatusSchema = object({
|
|
|
68735
69110
|
]),
|
|
68736
69111
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
68737
69112
|
* reading. */
|
|
68738
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
69113
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
68739
69114
|
/** Current fan-speed token (provider-verbatim). Null when unknown or
|
|
68740
69115
|
* the vacuum has no speed control. */
|
|
68741
69116
|
fanSpeed: string().nullable(),
|
|
68742
69117
|
/** Speed tokens the hardware accepts — drives the UI selector. */
|
|
68743
69118
|
availableFanSpeeds: array(string()),
|
|
68744
69119
|
/** 0..100 cleaning-completion percentage of the current task, or null. */
|
|
68745
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
69120
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
68746
69121
|
/** Current error code (0 / null = no error). */
|
|
68747
|
-
errorCode: number().nullable(),
|
|
69122
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
68748
69123
|
/** Human label for {@link errorCode}, or null when none / undecodable. */
|
|
68749
69124
|
errorLabel: string().nullable(),
|
|
68750
69125
|
/** Ms epoch when the slice was last updated. */
|
|
@@ -68822,7 +69197,7 @@ var ValveStatusSchema = object({
|
|
|
68822
69197
|
]),
|
|
68823
69198
|
/** 0 = fully closed, 100 = fully open. Null when the device has no
|
|
68824
69199
|
* intermediate position surface. */
|
|
68825
|
-
position: number().min(0).max(100).nullable(),
|
|
69200
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
68826
69201
|
/** Ms epoch when the slice was last updated. */
|
|
68827
69202
|
lastChangedAt: number()
|
|
68828
69203
|
});
|
|
@@ -68930,9 +69305,9 @@ var vibrationCapability = {
|
|
|
68930
69305
|
*/
|
|
68931
69306
|
var WaterHeaterStatusSchema = object({
|
|
68932
69307
|
/** Current measured temperature. Null when not reported. */
|
|
68933
|
-
currentTemp: number().nullable(),
|
|
69308
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
68934
69309
|
/** Target temperature setpoint. Null when no setpoint surface. */
|
|
68935
|
-
targetTemp: number().nullable(),
|
|
69310
|
+
targetTemp: number().nullable().meta(readingMeta("temperature")),
|
|
68936
69311
|
/** Active operation mode = HA `state` (`eco` / `electric` / `gas` /
|
|
68937
69312
|
* `heat_pump` / `high_demand` / `performance` / `off`). Null when the
|
|
68938
69313
|
* device reports an unknown state. */
|
|
@@ -68943,9 +69318,9 @@ var WaterHeaterStatusSchema = object({
|
|
|
68943
69318
|
* has no away surface. */
|
|
68944
69319
|
away: boolean().nullable(),
|
|
68945
69320
|
/** HA `min_temp` attribute. Null when not reported. */
|
|
68946
|
-
minTemp: number().nullable(),
|
|
69321
|
+
minTemp: number().nullable().meta(readingMeta("temperature")),
|
|
68947
69322
|
/** HA `max_temp` attribute. Null when not reported. */
|
|
68948
|
-
maxTemp: number().nullable(),
|
|
69323
|
+
maxTemp: number().nullable().meta(readingMeta("temperature")),
|
|
68949
69324
|
/** Ms epoch when the slice was last updated. */
|
|
68950
69325
|
lastChangedAt: number()
|
|
68951
69326
|
});
|
|
@@ -69030,25 +69405,18 @@ var waterHeaterCapability = {
|
|
|
69030
69405
|
* Forecast deferred — current conditions only for v1.
|
|
69031
69406
|
*/
|
|
69032
69407
|
var WeatherStatusSchema = object({
|
|
69033
|
-
/** Verbatim
|
|
69034
|
-
* when no condition has been reported yet. */
|
|
69408
|
+
/** Verbatim condition state (`sunny`, `cloudy`, `rainy`, …). Null when none yet. */
|
|
69035
69409
|
condition: string().nullable(),
|
|
69036
|
-
/** Current temperature in
|
|
69037
|
-
temperature: number().nullable(),
|
|
69038
|
-
/** Temperature unit string (e.g. `°C` / `°F`). Null when not provided. */
|
|
69039
|
-
temperatureUnit: string().nullable(),
|
|
69410
|
+
/** Current temperature in Celsius. Null when not provided or refused. */
|
|
69411
|
+
temperature: number().nullable().meta(readingMeta("temperature", { precision: 1 })),
|
|
69040
69412
|
/** Relative humidity (0..100). Null when not provided. */
|
|
69041
|
-
humidity: number().min(0).max(100).nullable(),
|
|
69042
|
-
/** Barometric pressure in
|
|
69043
|
-
pressure: number().nullable(),
|
|
69044
|
-
/**
|
|
69045
|
-
|
|
69046
|
-
/** Wind speed in the reported unit. Null when not provided. */
|
|
69047
|
-
windSpeed: number().nullable(),
|
|
69048
|
-
/** Wind-speed unit string (e.g. `km/h` / `mph`). Null when not provided. */
|
|
69049
|
-
windSpeedUnit: string().nullable(),
|
|
69413
|
+
humidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
69414
|
+
/** Barometric pressure in hPa. Null when not provided or refused. */
|
|
69415
|
+
pressure: number().nullable().meta(readingMeta("pressure")),
|
|
69416
|
+
/** Wind speed in metres per second. Null when not provided or refused. */
|
|
69417
|
+
windSpeed: number().nullable().meta(readingMeta("speed")),
|
|
69050
69418
|
/** Wind bearing in degrees (0..360, meteorological). Null when not provided. */
|
|
69051
|
-
windBearing: number().nullable(),
|
|
69419
|
+
windBearing: number().nullable().meta(readingMeta("angle")),
|
|
69052
69420
|
/** Ms epoch when the slice was last updated. */
|
|
69053
69421
|
lastFetchedAt: number()
|
|
69054
69422
|
});
|
|
@@ -69076,12 +69444,12 @@ var weatherCapability = {
|
|
|
69076
69444
|
*/
|
|
69077
69445
|
durability: "session",
|
|
69078
69446
|
/**
|
|
69079
|
-
* History (D850): recorded series.
|
|
69447
|
+
* History (D850): recorded series. Numbers are the quantity base (D944).
|
|
69080
69448
|
*/
|
|
69081
69449
|
history: { fields: {
|
|
69082
69450
|
temperature: {
|
|
69083
69451
|
kind: "gauge",
|
|
69084
|
-
|
|
69452
|
+
unit: "°C",
|
|
69085
69453
|
deadband: .2
|
|
69086
69454
|
},
|
|
69087
69455
|
humidity: {
|
|
@@ -69091,12 +69459,12 @@ var weatherCapability = {
|
|
|
69091
69459
|
},
|
|
69092
69460
|
pressure: {
|
|
69093
69461
|
kind: "gauge",
|
|
69094
|
-
|
|
69462
|
+
unit: "hPa",
|
|
69095
69463
|
deadband: .5
|
|
69096
69464
|
},
|
|
69097
69465
|
windSpeed: {
|
|
69098
69466
|
kind: "gauge",
|
|
69099
|
-
|
|
69467
|
+
unit: "m/s",
|
|
69100
69468
|
deadband: .5
|
|
69101
69469
|
}
|
|
69102
69470
|
} }
|
|
@@ -70327,6 +70695,8 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
70327
70695
|
featureProbe: featureProbeCapability,
|
|
70328
70696
|
flood: floodCapability,
|
|
70329
70697
|
gas: gasCapability,
|
|
70698
|
+
groupCommands: groupCommandsCapability,
|
|
70699
|
+
groupStatus: groupStatusCapability,
|
|
70330
70700
|
heatingValve: heatingValveCapability,
|
|
70331
70701
|
humidifier: humidifierCapability,
|
|
70332
70702
|
humiditySensor: humiditySensorCapability,
|
|
@@ -71703,6 +72073,13 @@ Object.freeze({
|
|
|
71703
72073
|
access: "view",
|
|
71704
72074
|
role: "admin"
|
|
71705
72075
|
},
|
|
72076
|
+
"addons.getPackageDocs": {
|
|
72077
|
+
capName: "addons",
|
|
72078
|
+
capScope: "system",
|
|
72079
|
+
addonId: null,
|
|
72080
|
+
access: "view",
|
|
72081
|
+
role: "admin"
|
|
72082
|
+
},
|
|
71706
72083
|
"addons.getVersions": {
|
|
71707
72084
|
capName: "addons",
|
|
71708
72085
|
capScope: "system",
|
|
@@ -74811,6 +75188,20 @@ Object.freeze({
|
|
|
74811
75188
|
access: "view",
|
|
74812
75189
|
role: "viewer"
|
|
74813
75190
|
},
|
|
75191
|
+
"groupCommands.getStatus": {
|
|
75192
|
+
capName: "group-commands",
|
|
75193
|
+
capScope: "device",
|
|
75194
|
+
addonId: null,
|
|
75195
|
+
access: "view",
|
|
75196
|
+
role: "viewer"
|
|
75197
|
+
},
|
|
75198
|
+
"groupStatus.getStatus": {
|
|
75199
|
+
capName: "group-status",
|
|
75200
|
+
capScope: "device",
|
|
75201
|
+
addonId: null,
|
|
75202
|
+
access: "view",
|
|
75203
|
+
role: "viewer"
|
|
75204
|
+
},
|
|
74814
75205
|
"heatingValve.getStatus": {
|
|
74815
75206
|
capName: "heating-valve",
|
|
74816
75207
|
capScope: "device",
|
|
@@ -84633,6 +85024,37 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84633
85024
|
icon: "flame"
|
|
84634
85025
|
}]
|
|
84635
85026
|
},
|
|
85027
|
+
"group-commands": {
|
|
85028
|
+
scope: "device",
|
|
85029
|
+
noun: t("Group command", "Comando di gruppo")
|
|
85030
|
+
},
|
|
85031
|
+
"group-status": {
|
|
85032
|
+
scope: "device",
|
|
85033
|
+
noun: t("Group", "Gruppo"),
|
|
85034
|
+
state: [
|
|
85035
|
+
{
|
|
85036
|
+
kind: "numeric",
|
|
85037
|
+
field: "included",
|
|
85038
|
+
quantity: t("the members reporting", "i membri che rispondono"),
|
|
85039
|
+
label: t("Reporting", "Rispondono"),
|
|
85040
|
+
icon: "users"
|
|
85041
|
+
},
|
|
85042
|
+
{
|
|
85043
|
+
kind: "numeric",
|
|
85044
|
+
field: "excluded",
|
|
85045
|
+
quantity: t("the members left out", "i membri esclusi"),
|
|
85046
|
+
label: t("Excluded", "Esclusi"),
|
|
85047
|
+
icon: "users"
|
|
85048
|
+
},
|
|
85049
|
+
{
|
|
85050
|
+
kind: "numeric",
|
|
85051
|
+
field: "total",
|
|
85052
|
+
quantity: t("the member count", "il numero di membri"),
|
|
85053
|
+
label: t("Members", "Membri"),
|
|
85054
|
+
icon: "sigma"
|
|
85055
|
+
}
|
|
85056
|
+
]
|
|
85057
|
+
},
|
|
84636
85058
|
"humidity-sensor": {
|
|
84637
85059
|
scope: "device",
|
|
84638
85060
|
noun: t("Humidity", "Umidità"),
|
|
@@ -84666,7 +85088,6 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84666
85088
|
field: "value",
|
|
84667
85089
|
quantity: t("the reading", "il valore"),
|
|
84668
85090
|
label: t("Reading", "Valore"),
|
|
84669
|
-
unitField: "unit",
|
|
84670
85091
|
icon: "gauge"
|
|
84671
85092
|
}]
|
|
84672
85093
|
},
|
|
@@ -84802,7 +85223,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84802
85223
|
field: "temperature",
|
|
84803
85224
|
quantity: t("the outdoor temperature", "la temperatura esterna"),
|
|
84804
85225
|
label: t("Temperature", "Temperatura"),
|
|
84805
|
-
|
|
85226
|
+
unit: "°C",
|
|
84806
85227
|
icon: "thermometer"
|
|
84807
85228
|
},
|
|
84808
85229
|
{
|
|
@@ -84818,7 +85239,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84818
85239
|
field: "windSpeed",
|
|
84819
85240
|
quantity: t("the wind speed", "la velocità del vento"),
|
|
84820
85241
|
label: t("Wind", "Vento"),
|
|
84821
|
-
|
|
85242
|
+
unit: "m/s",
|
|
84822
85243
|
icon: "wind"
|
|
84823
85244
|
},
|
|
84824
85245
|
{
|
|
@@ -84826,7 +85247,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84826
85247
|
field: "pressure",
|
|
84827
85248
|
quantity: t("the air pressure", "la pressione atmosferica"),
|
|
84828
85249
|
label: t("Pressure", "Pressione"),
|
|
84829
|
-
|
|
85250
|
+
unit: "hPa",
|
|
84830
85251
|
icon: "gauge"
|
|
84831
85252
|
}
|
|
84832
85253
|
]
|
|
@@ -86099,6 +86520,16 @@ Object.freeze({
|
|
|
86099
86520
|
form: "single",
|
|
86100
86521
|
optional: false
|
|
86101
86522
|
}],
|
|
86523
|
+
"groupCommands.getStatus": [{
|
|
86524
|
+
name: "deviceId",
|
|
86525
|
+
form: "single",
|
|
86526
|
+
optional: false
|
|
86527
|
+
}],
|
|
86528
|
+
"groupStatus.getStatus": [{
|
|
86529
|
+
name: "deviceId",
|
|
86530
|
+
form: "single",
|
|
86531
|
+
optional: false
|
|
86532
|
+
}],
|
|
86102
86533
|
"heatingValve.getStatus": [{
|
|
86103
86534
|
name: "deviceId",
|
|
86104
86535
|
form: "single",
|
|
@@ -88083,6 +88514,8 @@ new Map(Object.entries({
|
|
|
88083
88514
|
"detection-blind": "device-events",
|
|
88084
88515
|
"motion-noisy": "device-events",
|
|
88085
88516
|
"motion-calm": "device-events",
|
|
88517
|
+
"package-llm-silent": "device-events",
|
|
88518
|
+
"package-llm-answered": "device-events",
|
|
88086
88519
|
"recording-stalled": "device-events",
|
|
88087
88520
|
"recording-healthy": "device-events",
|
|
88088
88521
|
"recording-degraded": "device-events",
|
|
@@ -88166,6 +88599,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
|
|
|
88166
88599
|
label: "Motion without a subject",
|
|
88167
88600
|
kinds: ["motion-noisy", "motion-calm"]
|
|
88168
88601
|
},
|
|
88602
|
+
{
|
|
88603
|
+
id: "package-llm",
|
|
88604
|
+
family: "device-events",
|
|
88605
|
+
label: "Package confirm",
|
|
88606
|
+
kinds: ["package-llm-silent", "package-llm-answered"]
|
|
88607
|
+
},
|
|
88169
88608
|
{
|
|
88170
88609
|
id: "recording",
|
|
88171
88610
|
family: "device-events",
|
|
@@ -88347,6 +88786,8 @@ var DEVICE_EVENTS = [
|
|
|
88347
88786
|
"detection-blind",
|
|
88348
88787
|
"motion-noisy",
|
|
88349
88788
|
"motion-calm",
|
|
88789
|
+
"package-llm-silent",
|
|
88790
|
+
"package-llm-answered",
|
|
88350
88791
|
"recording-stalled",
|
|
88351
88792
|
"recording-healthy",
|
|
88352
88793
|
"recording-degraded",
|
|
@@ -88615,6 +89056,15 @@ new Map([
|
|
|
88615
89056
|
snapshotLabel: "Cameras with constant motion now",
|
|
88616
89057
|
snapshotSection: null
|
|
88617
89058
|
},
|
|
89059
|
+
{
|
|
89060
|
+
id: "package-llm-confirm",
|
|
89061
|
+
family: "device-events",
|
|
89062
|
+
label: "Package confirm (not answering / answering again)",
|
|
89063
|
+
bad: ["package-llm-silent"],
|
|
89064
|
+
recovery: ["package-llm-answered"],
|
|
89065
|
+
snapshotLabel: "Cameras whose package confirm is not answering",
|
|
89066
|
+
snapshotSection: null
|
|
89067
|
+
},
|
|
88618
89068
|
{
|
|
88619
89069
|
id: "recording-health",
|
|
88620
89070
|
family: "device-events",
|