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