@camstack/addon-provider-rtsp 1.2.146 → 1.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 +19 -0
- package/dist/addon.js +959 -509
- package/dist/addon.mjs +959 -509
- package/package.json +4 -2
package/dist/addon.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import net from "node:net";
|
|
2
|
-
//#region ../types/dist/event-category-
|
|
2
|
+
//#region ../types/dist/event-category-CT-hz5Rb.mjs
|
|
3
3
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
4
4
|
EventCategory["SystemBoot"] = "system.boot";
|
|
5
5
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -325,6 +325,14 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
325
325
|
/** The recovery edge of {@link PipelineMotionNoisy}: the motion fell back, or a detection arrived. */
|
|
326
326
|
EventCategory["PipelineMotionCalm"] = "pipeline.motion-calm";
|
|
327
327
|
/**
|
|
328
|
+
* A camera's package LLM confirm has failed closed three times in a row
|
|
329
|
+
* (D931, 2026-10-26). One edge per camera until
|
|
330
|
+
* {@link PipelinePackageLlmAnswered}.
|
|
331
|
+
*/
|
|
332
|
+
EventCategory["PipelinePackageLlmSilent"] = "pipeline.package-llm-silent";
|
|
333
|
+
/** The recovery edge of {@link PipelinePackageLlmSilent}: a confirm returned yes or no. */
|
|
334
|
+
EventCategory["PipelinePackageLlmAnswered"] = "pipeline.package-llm-answered";
|
|
335
|
+
/**
|
|
328
336
|
* Per-camera pipeline config was mutated by the orchestrator
|
|
329
337
|
* (a settings change via `setAgentInferenceDevices` /
|
|
330
338
|
* `setCameraStepToggle` / `setCameraStepSettings`). Orchestrator
|
|
@@ -5434,7 +5442,7 @@ var ZodIssueCode = {
|
|
|
5434
5442
|
var ZodFirstPartyTypeKind;
|
|
5435
5443
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5436
5444
|
//#endregion
|
|
5437
|
-
//#region ../types/dist/sleep-
|
|
5445
|
+
//#region ../types/dist/sleep-bykKrTgu.mjs
|
|
5438
5446
|
/**
|
|
5439
5447
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5440
5448
|
* window to float samples (D455).
|
|
@@ -7988,6 +7996,99 @@ var RecordKindDeclarationSchema = object({
|
|
|
7988
7996
|
}).strict();
|
|
7989
7997
|
/** The kind names: lower-case, dash separated, short enough for an index name. */
|
|
7990
7998
|
var RecordKindNameSchema = string().regex(/^[a-z][a-z0-9-]{0,47}$/);
|
|
7999
|
+
var READING_QUANTITIES = [
|
|
8000
|
+
"temperature",
|
|
8001
|
+
"pressure",
|
|
8002
|
+
"speed",
|
|
8003
|
+
"precipitation",
|
|
8004
|
+
"precipitation-rate",
|
|
8005
|
+
"length",
|
|
8006
|
+
"area",
|
|
8007
|
+
"illuminance",
|
|
8008
|
+
"irradiance",
|
|
8009
|
+
"power",
|
|
8010
|
+
"energy",
|
|
8011
|
+
"voltage",
|
|
8012
|
+
"current",
|
|
8013
|
+
"apparent-power",
|
|
8014
|
+
"humidity",
|
|
8015
|
+
"percentage",
|
|
8016
|
+
"concentration-volume",
|
|
8017
|
+
"concentration-mass",
|
|
8018
|
+
"concentration-ppb",
|
|
8019
|
+
"volume",
|
|
8020
|
+
"duration",
|
|
8021
|
+
"duration-ms",
|
|
8022
|
+
"information",
|
|
8023
|
+
"sound-level",
|
|
8024
|
+
"signal-level",
|
|
8025
|
+
"colour-temperature",
|
|
8026
|
+
"angle",
|
|
8027
|
+
"bitrate",
|
|
8028
|
+
"rate",
|
|
8029
|
+
"mass",
|
|
8030
|
+
"index",
|
|
8031
|
+
"ratio",
|
|
8032
|
+
"count",
|
|
8033
|
+
"none",
|
|
8034
|
+
"device"
|
|
8035
|
+
];
|
|
8036
|
+
var ReadingQuantitySchema = _enum(READING_QUANTITIES);
|
|
8037
|
+
new Set(READING_QUANTITIES);
|
|
8038
|
+
/**
|
|
8039
|
+
* Stored unit symbol for a quantity. `none` means the number is dimensionless
|
|
8040
|
+
* (or an index / ratio / count). `device` means the cap has no single unit.
|
|
8041
|
+
*/
|
|
8042
|
+
var QUANTITY_BASE = {
|
|
8043
|
+
temperature: "°C",
|
|
8044
|
+
pressure: "hPa",
|
|
8045
|
+
speed: "m/s",
|
|
8046
|
+
precipitation: "mm",
|
|
8047
|
+
"precipitation-rate": "mm/h",
|
|
8048
|
+
length: "m",
|
|
8049
|
+
area: "m²",
|
|
8050
|
+
illuminance: "lx",
|
|
8051
|
+
irradiance: "W/m²",
|
|
8052
|
+
power: "W",
|
|
8053
|
+
energy: "kWh",
|
|
8054
|
+
voltage: "V",
|
|
8055
|
+
current: "A",
|
|
8056
|
+
"apparent-power": "VA",
|
|
8057
|
+
humidity: "%",
|
|
8058
|
+
percentage: "%",
|
|
8059
|
+
"concentration-volume": "ppm",
|
|
8060
|
+
"concentration-mass": "µg/m³",
|
|
8061
|
+
"concentration-ppb": "ppb",
|
|
8062
|
+
volume: "L",
|
|
8063
|
+
duration: "s",
|
|
8064
|
+
"duration-ms": "ms",
|
|
8065
|
+
information: "B",
|
|
8066
|
+
"sound-level": "dBFS",
|
|
8067
|
+
"signal-level": "dBm",
|
|
8068
|
+
"colour-temperature": "mired",
|
|
8069
|
+
angle: "°",
|
|
8070
|
+
bitrate: "kbps",
|
|
8071
|
+
rate: "fps",
|
|
8072
|
+
mass: "kg",
|
|
8073
|
+
index: "none",
|
|
8074
|
+
ratio: "none",
|
|
8075
|
+
count: "none",
|
|
8076
|
+
none: "none",
|
|
8077
|
+
device: "device"
|
|
8078
|
+
};
|
|
8079
|
+
/** The stored unit, or `undefined` when the quantity has no unit symbol. */
|
|
8080
|
+
function baseUnitOf(quantity) {
|
|
8081
|
+
const symbol = QUANTITY_BASE[quantity];
|
|
8082
|
+
if (symbol === "none" || symbol === "device") return void 0;
|
|
8083
|
+
return symbol;
|
|
8084
|
+
}
|
|
8085
|
+
function readingMeta(quantity, extras) {
|
|
8086
|
+
return {
|
|
8087
|
+
quantity,
|
|
8088
|
+
...extras?.precision !== void 0 ? { precision: extras.precision } : {},
|
|
8089
|
+
...extras?.label !== void 0 ? { label: extras.label } : {}
|
|
8090
|
+
};
|
|
8091
|
+
}
|
|
7991
8092
|
/** Shared Zod schemas used across streaming capabilities. */
|
|
7992
8093
|
var CamProfileSchema = _enum([
|
|
7993
8094
|
"high",
|
|
@@ -8015,8 +8116,8 @@ var CamStreamKindSchema = _enum([
|
|
|
8015
8116
|
"derived"
|
|
8016
8117
|
]);
|
|
8017
8118
|
var CamStreamResolutionSchema = object({
|
|
8018
|
-
width: number().int().positive(),
|
|
8019
|
-
height: number().int().positive()
|
|
8119
|
+
width: number().int().positive().meta(readingMeta("none")),
|
|
8120
|
+
height: number().int().positive().meta(readingMeta("none"))
|
|
8020
8121
|
});
|
|
8021
8122
|
var CameraStreamSchema = object({
|
|
8022
8123
|
/** Stable, provider-assigned id unique within the (deviceId) scope. */
|
|
@@ -8534,6 +8635,8 @@ var CAP_NAMES = Object.freeze([
|
|
|
8534
8635
|
"filesystem-browse",
|
|
8535
8636
|
"flood",
|
|
8536
8637
|
"gas",
|
|
8638
|
+
"group-commands",
|
|
8639
|
+
"group-status",
|
|
8537
8640
|
"heating-valve",
|
|
8538
8641
|
"humidifier",
|
|
8539
8642
|
"humidity-sensor",
|
|
@@ -8663,14 +8766,6 @@ Object.freeze({
|
|
|
8663
8766
|
{
|
|
8664
8767
|
"path": "aqi",
|
|
8665
8768
|
"valueType": "number"
|
|
8666
|
-
},
|
|
8667
|
-
{
|
|
8668
|
-
"path": "unit",
|
|
8669
|
-
"valueType": "string"
|
|
8670
|
-
},
|
|
8671
|
-
{
|
|
8672
|
-
"path": "precision",
|
|
8673
|
-
"valueType": "number"
|
|
8674
8769
|
}
|
|
8675
8770
|
],
|
|
8676
8771
|
"alarm-panel": [
|
|
@@ -8706,20 +8801,10 @@ Object.freeze({
|
|
|
8706
8801
|
"valueType": "boolean"
|
|
8707
8802
|
}
|
|
8708
8803
|
],
|
|
8709
|
-
"ambient-light-sensor": [
|
|
8710
|
-
|
|
8711
|
-
|
|
8712
|
-
|
|
8713
|
-
},
|
|
8714
|
-
{
|
|
8715
|
-
"path": "unit",
|
|
8716
|
-
"valueType": "string"
|
|
8717
|
-
},
|
|
8718
|
-
{
|
|
8719
|
-
"path": "precision",
|
|
8720
|
-
"valueType": "number"
|
|
8721
|
-
}
|
|
8722
|
-
],
|
|
8804
|
+
"ambient-light-sensor": [{
|
|
8805
|
+
"path": "lux",
|
|
8806
|
+
"valueType": "number"
|
|
8807
|
+
}],
|
|
8723
8808
|
"audio-metrics": [
|
|
8724
8809
|
{
|
|
8725
8810
|
"path": "ts",
|
|
@@ -8799,6 +8884,10 @@ Object.freeze({
|
|
|
8799
8884
|
"path": "lastUpdated",
|
|
8800
8885
|
"valueType": "number"
|
|
8801
8886
|
},
|
|
8887
|
+
{
|
|
8888
|
+
"path": "volts",
|
|
8889
|
+
"valueType": "number"
|
|
8890
|
+
},
|
|
8802
8891
|
{
|
|
8803
8892
|
"path": "lastContactAt",
|
|
8804
8893
|
"valueType": "number"
|
|
@@ -9041,10 +9130,6 @@ Object.freeze({
|
|
|
9041
9130
|
"datetime"
|
|
9042
9131
|
]
|
|
9043
9132
|
},
|
|
9044
|
-
{
|
|
9045
|
-
"path": "unit",
|
|
9046
|
-
"valueType": "string"
|
|
9047
|
-
},
|
|
9048
9133
|
{
|
|
9049
9134
|
"path": "min",
|
|
9050
9135
|
"valueType": "number"
|
|
@@ -9056,19 +9141,6 @@ Object.freeze({
|
|
|
9056
9141
|
{
|
|
9057
9142
|
"path": "step",
|
|
9058
9143
|
"valueType": "number"
|
|
9059
|
-
},
|
|
9060
|
-
{
|
|
9061
|
-
"path": "precision",
|
|
9062
|
-
"valueType": "number"
|
|
9063
|
-
},
|
|
9064
|
-
{
|
|
9065
|
-
"path": "format",
|
|
9066
|
-
"valueType": "enum",
|
|
9067
|
-
"enumValues": [
|
|
9068
|
-
"date",
|
|
9069
|
-
"time",
|
|
9070
|
-
"datetime"
|
|
9071
|
-
]
|
|
9072
9144
|
}
|
|
9073
9145
|
],
|
|
9074
9146
|
"cover": [
|
|
@@ -9309,13 +9381,8 @@ Object.freeze({
|
|
|
9309
9381
|
"path": "value",
|
|
9310
9382
|
"valueType": "string"
|
|
9311
9383
|
}, {
|
|
9312
|
-
"path": "
|
|
9313
|
-
"valueType": "
|
|
9314
|
-
"enumValues": [
|
|
9315
|
-
"date",
|
|
9316
|
-
"time",
|
|
9317
|
-
"datetime"
|
|
9318
|
-
]
|
|
9384
|
+
"path": "timestamp",
|
|
9385
|
+
"valueType": "boolean"
|
|
9319
9386
|
}],
|
|
9320
9387
|
"event-emitter": [
|
|
9321
9388
|
{
|
|
@@ -9388,6 +9455,20 @@ Object.freeze({
|
|
|
9388
9455
|
"path": "detected",
|
|
9389
9456
|
"valueType": "boolean"
|
|
9390
9457
|
}],
|
|
9458
|
+
"group-status": [
|
|
9459
|
+
{
|
|
9460
|
+
"path": "included",
|
|
9461
|
+
"valueType": "number"
|
|
9462
|
+
},
|
|
9463
|
+
{
|
|
9464
|
+
"path": "excluded",
|
|
9465
|
+
"valueType": "number"
|
|
9466
|
+
},
|
|
9467
|
+
{
|
|
9468
|
+
"path": "total",
|
|
9469
|
+
"valueType": "number"
|
|
9470
|
+
}
|
|
9471
|
+
],
|
|
9391
9472
|
"heating-valve": [{
|
|
9392
9473
|
"path": "position",
|
|
9393
9474
|
"valueType": "number"
|
|
@@ -9422,20 +9503,10 @@ Object.freeze({
|
|
|
9422
9503
|
"valueType": "number"
|
|
9423
9504
|
}
|
|
9424
9505
|
],
|
|
9425
|
-
"humidity-sensor": [
|
|
9426
|
-
|
|
9427
|
-
|
|
9428
|
-
|
|
9429
|
-
},
|
|
9430
|
-
{
|
|
9431
|
-
"path": "unit",
|
|
9432
|
-
"valueType": "string"
|
|
9433
|
-
},
|
|
9434
|
-
{
|
|
9435
|
-
"path": "precision",
|
|
9436
|
-
"valueType": "number"
|
|
9437
|
-
}
|
|
9438
|
-
],
|
|
9506
|
+
"humidity-sensor": [{
|
|
9507
|
+
"path": "percent",
|
|
9508
|
+
"valueType": "number"
|
|
9509
|
+
}],
|
|
9439
9510
|
"image": [{
|
|
9440
9511
|
"path": "url",
|
|
9441
9512
|
"valueType": "string"
|
|
@@ -9774,20 +9845,10 @@ Object.freeze({
|
|
|
9774
9845
|
"valueType": "boolean"
|
|
9775
9846
|
}
|
|
9776
9847
|
],
|
|
9777
|
-
"numeric-sensor": [
|
|
9778
|
-
|
|
9779
|
-
|
|
9780
|
-
|
|
9781
|
-
},
|
|
9782
|
-
{
|
|
9783
|
-
"path": "unit",
|
|
9784
|
-
"valueType": "string"
|
|
9785
|
-
},
|
|
9786
|
-
{
|
|
9787
|
-
"path": "precision",
|
|
9788
|
-
"valueType": "number"
|
|
9789
|
-
}
|
|
9790
|
-
],
|
|
9848
|
+
"numeric-sensor": [{
|
|
9849
|
+
"path": "value",
|
|
9850
|
+
"valueType": "number"
|
|
9851
|
+
}],
|
|
9791
9852
|
"pet-feeder": [
|
|
9792
9853
|
{
|
|
9793
9854
|
"path": "foodLevel",
|
|
@@ -9879,14 +9940,6 @@ Object.freeze({
|
|
|
9879
9940
|
{
|
|
9880
9941
|
"path": "powerFactor",
|
|
9881
9942
|
"valueType": "number"
|
|
9882
|
-
},
|
|
9883
|
-
{
|
|
9884
|
-
"path": "unit",
|
|
9885
|
-
"valueType": "string"
|
|
9886
|
-
},
|
|
9887
|
-
{
|
|
9888
|
-
"path": "precision",
|
|
9889
|
-
"valueType": "number"
|
|
9890
9943
|
}
|
|
9891
9944
|
],
|
|
9892
9945
|
"presence": [
|
|
@@ -9915,20 +9968,10 @@ Object.freeze({
|
|
|
9915
9968
|
"valueType": "number"
|
|
9916
9969
|
}
|
|
9917
9970
|
],
|
|
9918
|
-
"pressure-sensor": [
|
|
9919
|
-
|
|
9920
|
-
|
|
9921
|
-
|
|
9922
|
-
},
|
|
9923
|
-
{
|
|
9924
|
-
"path": "unit",
|
|
9925
|
-
"valueType": "string"
|
|
9926
|
-
},
|
|
9927
|
-
{
|
|
9928
|
-
"path": "precision",
|
|
9929
|
-
"valueType": "number"
|
|
9930
|
-
}
|
|
9931
|
-
],
|
|
9971
|
+
"pressure-sensor": [{
|
|
9972
|
+
"path": "hpa",
|
|
9973
|
+
"valueType": "number"
|
|
9974
|
+
}],
|
|
9932
9975
|
"privacy-mask": [{
|
|
9933
9976
|
"path": "enabled",
|
|
9934
9977
|
"valueType": "boolean"
|
|
@@ -10239,20 +10282,10 @@ Object.freeze({
|
|
|
10239
10282
|
"path": "tampered",
|
|
10240
10283
|
"valueType": "boolean"
|
|
10241
10284
|
}],
|
|
10242
|
-
"temperature-sensor": [
|
|
10243
|
-
|
|
10244
|
-
|
|
10245
|
-
|
|
10246
|
-
},
|
|
10247
|
-
{
|
|
10248
|
-
"path": "unit",
|
|
10249
|
-
"valueType": "string"
|
|
10250
|
-
},
|
|
10251
|
-
{
|
|
10252
|
-
"path": "precision",
|
|
10253
|
-
"valueType": "number"
|
|
10254
|
-
}
|
|
10255
|
-
],
|
|
10285
|
+
"temperature-sensor": [{
|
|
10286
|
+
"path": "celsius",
|
|
10287
|
+
"valueType": "number"
|
|
10288
|
+
}],
|
|
10256
10289
|
"update": [
|
|
10257
10290
|
{
|
|
10258
10291
|
"path": "currentVersion",
|
|
@@ -10363,10 +10396,6 @@ Object.freeze({
|
|
|
10363
10396
|
"path": "temperature",
|
|
10364
10397
|
"valueType": "number"
|
|
10365
10398
|
},
|
|
10366
|
-
{
|
|
10367
|
-
"path": "temperatureUnit",
|
|
10368
|
-
"valueType": "string"
|
|
10369
|
-
},
|
|
10370
10399
|
{
|
|
10371
10400
|
"path": "humidity",
|
|
10372
10401
|
"valueType": "number"
|
|
@@ -10375,18 +10404,10 @@ Object.freeze({
|
|
|
10375
10404
|
"path": "pressure",
|
|
10376
10405
|
"valueType": "number"
|
|
10377
10406
|
},
|
|
10378
|
-
{
|
|
10379
|
-
"path": "pressureUnit",
|
|
10380
|
-
"valueType": "string"
|
|
10381
|
-
},
|
|
10382
10407
|
{
|
|
10383
10408
|
"path": "windSpeed",
|
|
10384
10409
|
"valueType": "number"
|
|
10385
10410
|
},
|
|
10386
|
-
{
|
|
10387
|
-
"path": "windSpeedUnit",
|
|
10388
|
-
"valueType": "string"
|
|
10389
|
-
},
|
|
10390
10411
|
{
|
|
10391
10412
|
"path": "windBearing",
|
|
10392
10413
|
"valueType": "number"
|
|
@@ -10878,7 +10899,7 @@ function errMsg(err) {
|
|
|
10878
10899
|
return String(err);
|
|
10879
10900
|
}
|
|
10880
10901
|
//#endregion
|
|
10881
|
-
//#region ../types/dist/composition-
|
|
10902
|
+
//#region ../types/dist/composition-OhpuespA.mjs
|
|
10882
10903
|
/**
|
|
10883
10904
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
10884
10905
|
*
|
|
@@ -11633,15 +11654,74 @@ function validateExpressionSource(src) {
|
|
|
11633
11654
|
}
|
|
11634
11655
|
return null;
|
|
11635
11656
|
}
|
|
11636
|
-
/**
|
|
11637
|
-
|
|
11638
|
-
|
|
11639
|
-
|
|
11657
|
+
/**
|
|
11658
|
+
* A composition source identity: `(addonId, stableId)`, never a numeric device
|
|
11659
|
+
* id. Split out so helper schemas can name it without a cycle through
|
|
11660
|
+
* `composition.ts` (D659).
|
|
11661
|
+
*/
|
|
11640
11662
|
var CompositionSourceRefSchema = object({
|
|
11641
11663
|
/** The owning addon; `stableId` is unique only within it. */
|
|
11642
11664
|
addonId: string().min(1),
|
|
11643
11665
|
stableId: string().min(1)
|
|
11644
11666
|
});
|
|
11667
|
+
var GROUP_TEMPLATE_IDS = [
|
|
11668
|
+
"temperature",
|
|
11669
|
+
"humidity",
|
|
11670
|
+
"pressure",
|
|
11671
|
+
"illuminance",
|
|
11672
|
+
"power",
|
|
11673
|
+
"energy",
|
|
11674
|
+
"battery",
|
|
11675
|
+
"numeric",
|
|
11676
|
+
"motion",
|
|
11677
|
+
"contact",
|
|
11678
|
+
"leak",
|
|
11679
|
+
"smoke",
|
|
11680
|
+
"occupancy",
|
|
11681
|
+
"binary",
|
|
11682
|
+
"switch",
|
|
11683
|
+
"light"
|
|
11684
|
+
];
|
|
11685
|
+
var NUMERIC_AGGREGATES = [
|
|
11686
|
+
"mean",
|
|
11687
|
+
"median",
|
|
11688
|
+
"min",
|
|
11689
|
+
"max",
|
|
11690
|
+
"sum"
|
|
11691
|
+
];
|
|
11692
|
+
var BINARY_AGGREGATES = ["any", "all"];
|
|
11693
|
+
/** How an actuator group decides it is on. Unknown members never count as off. */
|
|
11694
|
+
var ACTIVE_CRITERIA = ["at-least-one", "all"];
|
|
11695
|
+
var AGGREGATE_REDUCERS = [
|
|
11696
|
+
"mean",
|
|
11697
|
+
"median",
|
|
11698
|
+
"min",
|
|
11699
|
+
"max",
|
|
11700
|
+
"sum",
|
|
11701
|
+
"any",
|
|
11702
|
+
"all"
|
|
11703
|
+
];
|
|
11704
|
+
var GroupTemplateIdSchema = _enum(GROUP_TEMPLATE_IDS);
|
|
11705
|
+
var AggregateReducerSchema = _enum(AGGREGATE_REDUCERS);
|
|
11706
|
+
var ActiveCriterionSchema = _enum(ACTIVE_CRITERIA);
|
|
11707
|
+
/** One member. The field is stored so occupancy can name motion or binary. */
|
|
11708
|
+
var HelperMemberSchema = object({
|
|
11709
|
+
source: CompositionSourceRefSchema,
|
|
11710
|
+
cap: string().min(1),
|
|
11711
|
+
fieldPath: string().min(1)
|
|
11712
|
+
});
|
|
11713
|
+
var HelperSpecSchema = discriminatedUnion("kind", [object({
|
|
11714
|
+
kind: literal("group"),
|
|
11715
|
+
templateId: GroupTemplateIdSchema,
|
|
11716
|
+
aggregate: AggregateReducerSchema,
|
|
11717
|
+
members: array(HelperMemberSchema).min(1).max(64),
|
|
11718
|
+
/** Actuator groups only. Readings leave this unset. */
|
|
11719
|
+
active: ActiveCriterionSchema.optional()
|
|
11720
|
+
})]);
|
|
11721
|
+
/** A composed device's stableId is this prefix plus the block id. */
|
|
11722
|
+
var COMPOSED_DEVICE_STABLE_ID_PREFIX = "composed-";
|
|
11723
|
+
/** Longest snippet a `code` source may carry (slice 4). */
|
|
11724
|
+
var MAX_COMPOSITION_CODE_LENGTH = 2e4;
|
|
11645
11725
|
/** One field of one capability of one source device. */
|
|
11646
11726
|
var CompositionFieldReadSchema = object({
|
|
11647
11727
|
source: CompositionSourceRefSchema,
|
|
@@ -11685,7 +11765,33 @@ var CompositionCodeSourceSchema = object({
|
|
|
11685
11765
|
var CompositionFieldSourceSchema = discriminatedUnion("kind", [
|
|
11686
11766
|
CompositionFromSourceSchema,
|
|
11687
11767
|
CompositionExpressionSourceSchema,
|
|
11688
|
-
CompositionCodeSourceSchema
|
|
11768
|
+
CompositionCodeSourceSchema,
|
|
11769
|
+
object({
|
|
11770
|
+
kind: literal("aggregate"),
|
|
11771
|
+
reducer: _enum([
|
|
11772
|
+
"mean",
|
|
11773
|
+
"median",
|
|
11774
|
+
"min",
|
|
11775
|
+
"max",
|
|
11776
|
+
"sum",
|
|
11777
|
+
"any",
|
|
11778
|
+
"all"
|
|
11779
|
+
]),
|
|
11780
|
+
reads: array(CompositionFieldReadSchema).min(1).max(64),
|
|
11781
|
+
/** `value` is the reading; the others are the member counts. */
|
|
11782
|
+
publish: _enum([
|
|
11783
|
+
"value",
|
|
11784
|
+
"included",
|
|
11785
|
+
"excluded",
|
|
11786
|
+
"total"
|
|
11787
|
+
]),
|
|
11788
|
+
/** What a `value` publish does when nobody is included. Counts ignore this. */
|
|
11789
|
+
empty: _enum([
|
|
11790
|
+
"null",
|
|
11791
|
+
"omit",
|
|
11792
|
+
"offline"
|
|
11793
|
+
])
|
|
11794
|
+
})
|
|
11689
11795
|
]);
|
|
11690
11796
|
var CompositionCommandTargetSchema = discriminatedUnion("kind", [object({
|
|
11691
11797
|
kind: literal("forward"),
|
|
@@ -11731,7 +11837,13 @@ var CompositionSchema = object({
|
|
|
11731
11837
|
kind: literal("existing"),
|
|
11732
11838
|
device: CompositionSourceRefSchema
|
|
11733
11839
|
})]),
|
|
11734
|
-
features: array(CompositionFeatureSchema).min(1).max(16)
|
|
11840
|
+
features: array(CompositionFeatureSchema).min(1).max(16),
|
|
11841
|
+
/**
|
|
11842
|
+
* Present when the block is a helper template. Absent on a free
|
|
11843
|
+
* composition (the room example, device 4603). The editor reads this,
|
|
11844
|
+
* never the compiled features.
|
|
11845
|
+
*/
|
|
11846
|
+
helper: HelperSpecSchema.optional()
|
|
11735
11847
|
}).superRefine((composition, ctx) => {
|
|
11736
11848
|
const seen = /* @__PURE__ */ new Set();
|
|
11737
11849
|
composition.features.forEach((feature, index) => {
|
|
@@ -17971,7 +18083,11 @@ var CompositionProblemSchema = object({
|
|
|
17971
18083
|
"item-field-reserved",
|
|
17972
18084
|
"target-missing",
|
|
17973
18085
|
"target-unreadable",
|
|
17974
|
-
"not-replaceable"
|
|
18086
|
+
"not-replaceable",
|
|
18087
|
+
"native-capability-replace",
|
|
18088
|
+
"mixed-quantity",
|
|
18089
|
+
"helper-mismatch",
|
|
18090
|
+
"member-constraint"
|
|
17975
18091
|
]),
|
|
17976
18092
|
path: string(),
|
|
17977
18093
|
message: string()
|
|
@@ -17992,7 +18108,8 @@ var CompositionUnavailableModeSchema = _enum([
|
|
|
17992
18108
|
"null",
|
|
17993
18109
|
"offline",
|
|
17994
18110
|
"unknown",
|
|
17995
|
-
"release"
|
|
18111
|
+
"release",
|
|
18112
|
+
"omit"
|
|
17996
18113
|
]);
|
|
17997
18114
|
/**
|
|
17998
18115
|
* `derived` reads a source · `clock` reads only `now`, recomputed when a sibling
|
|
@@ -18029,9 +18146,11 @@ var CompositionFieldPlanSchema = object({
|
|
|
18029
18146
|
reads: array(CompositionFieldReadSchema)
|
|
18030
18147
|
});
|
|
18031
18148
|
/**
|
|
18032
|
-
* What a feature does to its target (D663): `new` builds a capability on a
|
|
18033
|
-
* device; on an existing device it `add`s a capability the device lacks
|
|
18034
|
-
*
|
|
18149
|
+
* What a feature does to its target (D663, D944): `new` builds a capability on a
|
|
18150
|
+
* new device; on an existing device it `add`s a capability the device lacks.
|
|
18151
|
+
* Replacing a capability the device already serves is refused
|
|
18152
|
+
* (`native-capability-replace`), not planned. `replace` remains on the claim
|
|
18153
|
+
* wire for a claim the hub already holds.
|
|
18035
18154
|
*/
|
|
18036
18155
|
var CompositionFeatureModeSchema = _enum([
|
|
18037
18156
|
"new",
|
|
@@ -18204,6 +18323,275 @@ Object.freeze({
|
|
|
18204
18323
|
result: ["number", "null"]
|
|
18205
18324
|
}
|
|
18206
18325
|
});
|
|
18326
|
+
/**
|
|
18327
|
+
* One catalog row per base reading a group helper can build (D944 §3).
|
|
18328
|
+
* Data, not a form default written into the block.
|
|
18329
|
+
*/
|
|
18330
|
+
var NOW = {
|
|
18331
|
+
fieldPath: "lastFetchedAt",
|
|
18332
|
+
expr: "now"
|
|
18333
|
+
};
|
|
18334
|
+
var CHANGED = {
|
|
18335
|
+
fieldPath: "lastChangedAt",
|
|
18336
|
+
expr: "now"
|
|
18337
|
+
};
|
|
18338
|
+
function numeric(input) {
|
|
18339
|
+
return {
|
|
18340
|
+
...input,
|
|
18341
|
+
family: "numeric",
|
|
18342
|
+
deviceType: DeviceType.Sensor,
|
|
18343
|
+
memberDeviceType: DeviceType.Sensor,
|
|
18344
|
+
commandCaps: [],
|
|
18345
|
+
baseUnit: baseUnitOf(input.quantity),
|
|
18346
|
+
aggregates: NUMERIC_AGGREGATES,
|
|
18347
|
+
accept: [{
|
|
18348
|
+
cap: input.outputCap,
|
|
18349
|
+
fieldPath: input.outputField
|
|
18350
|
+
}]
|
|
18351
|
+
};
|
|
18352
|
+
}
|
|
18353
|
+
function binary(input) {
|
|
18354
|
+
return {
|
|
18355
|
+
...input,
|
|
18356
|
+
family: "binary",
|
|
18357
|
+
deviceType: DeviceType.Sensor,
|
|
18358
|
+
memberDeviceType: DeviceType.Sensor,
|
|
18359
|
+
commandCaps: [],
|
|
18360
|
+
quantity: "none",
|
|
18361
|
+
baseUnit: void 0,
|
|
18362
|
+
aggregates: BINARY_AGGREGATES,
|
|
18363
|
+
empty: "offline"
|
|
18364
|
+
};
|
|
18365
|
+
}
|
|
18366
|
+
var GROUP_TEMPLATES = [
|
|
18367
|
+
numeric({
|
|
18368
|
+
id: "temperature",
|
|
18369
|
+
summary: "Mean, median, min, max or sum of temperatures. Offline and unknown members are left out, never read as 0 °C.",
|
|
18370
|
+
role: DeviceRole.TemperatureSensor,
|
|
18371
|
+
outputCap: "temperature-sensor",
|
|
18372
|
+
outputField: "celsius",
|
|
18373
|
+
quantity: "temperature",
|
|
18374
|
+
defaultAggregate: "mean",
|
|
18375
|
+
empty: "null",
|
|
18376
|
+
companions: [NOW]
|
|
18377
|
+
}),
|
|
18378
|
+
numeric({
|
|
18379
|
+
id: "humidity",
|
|
18380
|
+
summary: "Humidity in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
18381
|
+
role: DeviceRole.HumiditySensor,
|
|
18382
|
+
outputCap: "humidity-sensor",
|
|
18383
|
+
outputField: "percent",
|
|
18384
|
+
quantity: "humidity",
|
|
18385
|
+
defaultAggregate: "mean",
|
|
18386
|
+
empty: "null",
|
|
18387
|
+
companions: [NOW]
|
|
18388
|
+
}),
|
|
18389
|
+
numeric({
|
|
18390
|
+
id: "pressure",
|
|
18391
|
+
summary: "Pressure in hectopascals. Offline and unknown members are left out, never read as 0 hPa.",
|
|
18392
|
+
role: DeviceRole.PressureSensor,
|
|
18393
|
+
outputCap: "pressure-sensor",
|
|
18394
|
+
outputField: "hpa",
|
|
18395
|
+
quantity: "pressure",
|
|
18396
|
+
defaultAggregate: "mean",
|
|
18397
|
+
empty: "null",
|
|
18398
|
+
companions: [NOW]
|
|
18399
|
+
}),
|
|
18400
|
+
numeric({
|
|
18401
|
+
id: "illuminance",
|
|
18402
|
+
summary: "Illuminance in lux. Offline and unknown members are left out, never read as 0 lx.",
|
|
18403
|
+
role: DeviceRole.AmbientLightSensor,
|
|
18404
|
+
outputCap: "ambient-light-sensor",
|
|
18405
|
+
outputField: "lux",
|
|
18406
|
+
quantity: "illuminance",
|
|
18407
|
+
defaultAggregate: "mean",
|
|
18408
|
+
empty: "null",
|
|
18409
|
+
companions: [NOW]
|
|
18410
|
+
}),
|
|
18411
|
+
numeric({
|
|
18412
|
+
id: "power",
|
|
18413
|
+
summary: "Power in watts, summed by default. Nobody reporting omits the key rather than writing 0 W.",
|
|
18414
|
+
role: DeviceRole.PowerSensor,
|
|
18415
|
+
outputCap: "power-meter",
|
|
18416
|
+
outputField: "watts",
|
|
18417
|
+
quantity: "power",
|
|
18418
|
+
defaultAggregate: "sum",
|
|
18419
|
+
empty: "omit",
|
|
18420
|
+
companions: [NOW]
|
|
18421
|
+
}),
|
|
18422
|
+
numeric({
|
|
18423
|
+
id: "energy",
|
|
18424
|
+
summary: "Energy in kilowatt-hours, summed by default. Nobody reporting omits the key rather than writing 0 kWh.",
|
|
18425
|
+
role: DeviceRole.EnergySensor,
|
|
18426
|
+
outputCap: "power-meter",
|
|
18427
|
+
outputField: "kwhTotal",
|
|
18428
|
+
quantity: "energy",
|
|
18429
|
+
defaultAggregate: "sum",
|
|
18430
|
+
empty: "omit",
|
|
18431
|
+
companions: [NOW]
|
|
18432
|
+
}),
|
|
18433
|
+
numeric({
|
|
18434
|
+
id: "battery",
|
|
18435
|
+
summary: "Battery charge in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
18436
|
+
role: DeviceRole.BatterySensor,
|
|
18437
|
+
outputCap: "battery",
|
|
18438
|
+
outputField: "percentage",
|
|
18439
|
+
quantity: "percentage",
|
|
18440
|
+
defaultAggregate: "mean",
|
|
18441
|
+
empty: "null",
|
|
18442
|
+
companions: [
|
|
18443
|
+
{
|
|
18444
|
+
fieldPath: "charging",
|
|
18445
|
+
expr: "\"unknown\""
|
|
18446
|
+
},
|
|
18447
|
+
{
|
|
18448
|
+
fieldPath: "sleeping",
|
|
18449
|
+
expr: "false"
|
|
18450
|
+
},
|
|
18451
|
+
{
|
|
18452
|
+
fieldPath: "lastUpdated",
|
|
18453
|
+
expr: "now"
|
|
18454
|
+
}
|
|
18455
|
+
]
|
|
18456
|
+
}),
|
|
18457
|
+
numeric({
|
|
18458
|
+
id: "numeric",
|
|
18459
|
+
summary: "A numeric reading in the members’ shared quantity. Mixed quantities are refused. Nobody reporting publishes null, not 0.",
|
|
18460
|
+
role: DeviceRole.NumericSensor,
|
|
18461
|
+
outputCap: "numeric-sensor",
|
|
18462
|
+
outputField: "value",
|
|
18463
|
+
quantity: "device",
|
|
18464
|
+
defaultAggregate: "mean",
|
|
18465
|
+
empty: "null",
|
|
18466
|
+
companions: [NOW]
|
|
18467
|
+
}),
|
|
18468
|
+
binary({
|
|
18469
|
+
id: "motion",
|
|
18470
|
+
summary: "Any or all motion. Offline and unknown members are left out, never read as off. Nobody reporting takes the device offline.",
|
|
18471
|
+
role: DeviceRole.MotionSensor,
|
|
18472
|
+
outputCap: "motion",
|
|
18473
|
+
outputField: "detected",
|
|
18474
|
+
defaultAggregate: "any",
|
|
18475
|
+
accept: [{
|
|
18476
|
+
cap: "motion",
|
|
18477
|
+
fieldPath: "detected"
|
|
18478
|
+
}],
|
|
18479
|
+
companions: [{
|
|
18480
|
+
fieldPath: "lastDetectedAt",
|
|
18481
|
+
expr: "null"
|
|
18482
|
+
}, {
|
|
18483
|
+
fieldPath: "autoClearAfterMs",
|
|
18484
|
+
expr: "null"
|
|
18485
|
+
}]
|
|
18486
|
+
}),
|
|
18487
|
+
binary({
|
|
18488
|
+
id: "contact",
|
|
18489
|
+
summary: "Any or all open contacts. Offline and unknown members are left out, never read as closed.",
|
|
18490
|
+
role: DeviceRole.ContactSensor,
|
|
18491
|
+
outputCap: "contact",
|
|
18492
|
+
outputField: "entryOpen",
|
|
18493
|
+
defaultAggregate: "any",
|
|
18494
|
+
accept: [{
|
|
18495
|
+
cap: "contact",
|
|
18496
|
+
fieldPath: "entryOpen"
|
|
18497
|
+
}],
|
|
18498
|
+
companions: [CHANGED]
|
|
18499
|
+
}),
|
|
18500
|
+
binary({
|
|
18501
|
+
id: "leak",
|
|
18502
|
+
summary: "Any or all leak detections. Offline and unknown members are left out, never read as dry.",
|
|
18503
|
+
role: DeviceRole.LeakSensor,
|
|
18504
|
+
outputCap: "flood",
|
|
18505
|
+
outputField: "flooded",
|
|
18506
|
+
defaultAggregate: "any",
|
|
18507
|
+
accept: [{
|
|
18508
|
+
cap: "flood",
|
|
18509
|
+
fieldPath: "flooded"
|
|
18510
|
+
}],
|
|
18511
|
+
companions: [CHANGED]
|
|
18512
|
+
}),
|
|
18513
|
+
binary({
|
|
18514
|
+
id: "smoke",
|
|
18515
|
+
summary: "Any or all smoke detections. Offline and unknown members are left out, never read as clear.",
|
|
18516
|
+
role: DeviceRole.SmokeSensor,
|
|
18517
|
+
outputCap: "smoke",
|
|
18518
|
+
outputField: "detected",
|
|
18519
|
+
defaultAggregate: "any",
|
|
18520
|
+
accept: [{
|
|
18521
|
+
cap: "smoke",
|
|
18522
|
+
fieldPath: "detected"
|
|
18523
|
+
}],
|
|
18524
|
+
companions: [CHANGED]
|
|
18525
|
+
}),
|
|
18526
|
+
binary({
|
|
18527
|
+
id: "occupancy",
|
|
18528
|
+
summary: "Any or all of motion or binary sensors, published as a binary. Presence zones are not aggregated. Nobody reporting is offline, not off.",
|
|
18529
|
+
role: DeviceRole.BinarySensor,
|
|
18530
|
+
outputCap: "binary",
|
|
18531
|
+
outputField: "on",
|
|
18532
|
+
defaultAggregate: "any",
|
|
18533
|
+
accept: [{
|
|
18534
|
+
cap: "motion",
|
|
18535
|
+
fieldPath: "detected"
|
|
18536
|
+
}, {
|
|
18537
|
+
cap: "binary",
|
|
18538
|
+
fieldPath: "on"
|
|
18539
|
+
}],
|
|
18540
|
+
companions: [CHANGED]
|
|
18541
|
+
}),
|
|
18542
|
+
binary({
|
|
18543
|
+
id: "binary",
|
|
18544
|
+
summary: "Any or all generic binary sensors. Offline and unknown members are left out, never read as off.",
|
|
18545
|
+
role: DeviceRole.BinarySensor,
|
|
18546
|
+
outputCap: "binary",
|
|
18547
|
+
outputField: "on",
|
|
18548
|
+
defaultAggregate: "any",
|
|
18549
|
+
accept: [{
|
|
18550
|
+
cap: "binary",
|
|
18551
|
+
fieldPath: "on"
|
|
18552
|
+
}],
|
|
18553
|
+
companions: [CHANGED]
|
|
18554
|
+
}),
|
|
18555
|
+
actuator({
|
|
18556
|
+
id: "switch",
|
|
18557
|
+
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.",
|
|
18558
|
+
deviceType: DeviceType.Switch,
|
|
18559
|
+
outputCap: "switch",
|
|
18560
|
+
commandCaps: ["switch"]
|
|
18561
|
+
}),
|
|
18562
|
+
actuator({
|
|
18563
|
+
id: "light",
|
|
18564
|
+
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.",
|
|
18565
|
+
deviceType: DeviceType.Light,
|
|
18566
|
+
outputCap: "switch",
|
|
18567
|
+
commandCaps: [
|
|
18568
|
+
"switch",
|
|
18569
|
+
"brightness",
|
|
18570
|
+
"color"
|
|
18571
|
+
]
|
|
18572
|
+
})
|
|
18573
|
+
];
|
|
18574
|
+
function actuator(input) {
|
|
18575
|
+
return {
|
|
18576
|
+
...input,
|
|
18577
|
+
family: "actuator",
|
|
18578
|
+
role: void 0,
|
|
18579
|
+
memberDeviceType: input.deviceType,
|
|
18580
|
+
outputField: "on",
|
|
18581
|
+
quantity: "none",
|
|
18582
|
+
baseUnit: void 0,
|
|
18583
|
+
aggregates: BINARY_AGGREGATES,
|
|
18584
|
+
defaultAggregate: "any",
|
|
18585
|
+
empty: "offline",
|
|
18586
|
+
accept: [{
|
|
18587
|
+
cap: "switch",
|
|
18588
|
+
fieldPath: "on"
|
|
18589
|
+
}],
|
|
18590
|
+
companions: [CHANGED]
|
|
18591
|
+
};
|
|
18592
|
+
}
|
|
18593
|
+
new Map(GROUP_TEMPLATES.map((template) => [template.id, template]));
|
|
18594
|
+
DeviceFeature.LightColorRgb, DeviceFeature.LightColorHsv, DeviceFeature.LightColorMired;
|
|
18207
18595
|
`${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
|
|
18208
18596
|
/**
|
|
18209
18597
|
* What a composition may BUILD on a device type (G2, D676): the caps a new
|
|
@@ -19917,12 +20305,12 @@ method(object({ deviceId: number().int().nonnegative() }), DeviceAdminLinkSchema
|
|
|
19917
20305
|
* providers detect renames by matching `uniqueId` and patch `id`
|
|
19918
20306
|
* in-place so dispatch keeps working.
|
|
19919
20307
|
*
|
|
19920
|
-
* **
|
|
19921
|
-
*
|
|
19922
|
-
*
|
|
19923
|
-
*
|
|
19924
|
-
* (`ha-domain-mapping`)
|
|
19925
|
-
* stored after that point.
|
|
20308
|
+
* **Display unit and precision are NOT stored here.** They are a read-time
|
|
20309
|
+
* preference (D944). A polymorphic reading stores its `quantity` here once,
|
|
20310
|
+
* at adopt, and a date/time value stores `dateTimeShape` the same way —
|
|
20311
|
+
* neither is repeated on each sample. The `device_class` tag is an
|
|
20312
|
+
* HA-specific input consumed at the discovery boundary (`ha-domain-mapping`)
|
|
20313
|
+
* to derive the CamStack `DeviceRole`; it is never stored after that point.
|
|
19926
20314
|
*
|
|
19927
20315
|
* The `raw` escape hatch carries provider-specific attributes that don't
|
|
19928
20316
|
* fit the structured slots (HA `attributes` whitelist, Reolink `deviceCache`
|
|
@@ -19936,6 +20324,14 @@ var SourceInfoSchema = object({
|
|
|
19936
20324
|
/** Immutable upstream identifier when available (HA `unique_id`, … ).
|
|
19937
20325
|
* Used to detect rename when `id` changes. */
|
|
19938
20326
|
uniqueId: string().optional(),
|
|
20327
|
+
/** Quantity of a polymorphic reading, written once at adopt (D944). */
|
|
20328
|
+
quantity: ReadingQuantitySchema.optional(),
|
|
20329
|
+
/** Date / time / datetime shape of a string reading, written once at adopt. */
|
|
20330
|
+
dateTimeShape: _enum([
|
|
20331
|
+
"date",
|
|
20332
|
+
"time",
|
|
20333
|
+
"datetime"
|
|
20334
|
+
]).optional(),
|
|
19939
20335
|
/** Provider-specific extras that don't fit the structured slots.
|
|
19940
20336
|
* Whitelist what goes here per provider — do NOT dump entire HA
|
|
19941
20337
|
* attribute blobs (would explode the meta JSON column). */
|
|
@@ -41040,7 +41436,8 @@ method(object({
|
|
|
41040
41436
|
"enum"
|
|
41041
41437
|
]),
|
|
41042
41438
|
enumValues: array(string()).optional(),
|
|
41043
|
-
item: boolean().optional()
|
|
41439
|
+
item: boolean().optional(),
|
|
41440
|
+
quantity: ReadingQuantitySchema.optional()
|
|
41044
41441
|
})).readonly(),
|
|
41045
41442
|
itemArray: object({
|
|
41046
41443
|
path: string(),
|
|
@@ -44884,8 +45281,8 @@ var MaskPolygonShapeSchema = object({
|
|
|
44884
45281
|
/** Boolean cell grid — row-major, length === gridWidth*gridHeight. */
|
|
44885
45282
|
var MaskGridShapeSchema = object({
|
|
44886
45283
|
kind: literal("grid"),
|
|
44887
|
-
gridWidth: number(),
|
|
44888
|
-
gridHeight: number(),
|
|
45284
|
+
gridWidth: number().meta(readingMeta("none")),
|
|
45285
|
+
gridHeight: number().meta(readingMeta("none")),
|
|
44889
45286
|
cells: array(boolean())
|
|
44890
45287
|
});
|
|
44891
45288
|
discriminatedUnion("kind", [
|
|
@@ -44997,6 +45394,8 @@ var NcSystemEventKindSchema = _enum([
|
|
|
44997
45394
|
"detection-blind",
|
|
44998
45395
|
"motion-noisy",
|
|
44999
45396
|
"motion-calm",
|
|
45397
|
+
"package-llm-silent",
|
|
45398
|
+
"package-llm-answered",
|
|
45000
45399
|
"recording-stalled",
|
|
45001
45400
|
"recording-healthy",
|
|
45002
45401
|
"recording-degraded",
|
|
@@ -56192,6 +56591,28 @@ var PackageVersionInfoSchema = object({
|
|
|
56192
56591
|
deprecated: string().optional(),
|
|
56193
56592
|
distTags: array(string()).readonly()
|
|
56194
56593
|
});
|
|
56594
|
+
/**
|
|
56595
|
+
* One published document. `ok` is markdown from the registry. `missing` means
|
|
56596
|
+
* the registry answered and the file was not there. `error` is a registry or
|
|
56597
|
+
* tarball failure — never an empty string standing in for either.
|
|
56598
|
+
*/
|
|
56599
|
+
var PackageDocBodySchema = discriminatedUnion("status", [
|
|
56600
|
+
object({
|
|
56601
|
+
status: literal("ok"),
|
|
56602
|
+
markdown: string()
|
|
56603
|
+
}),
|
|
56604
|
+
object({ status: literal("missing") }),
|
|
56605
|
+
object({
|
|
56606
|
+
status: literal("error"),
|
|
56607
|
+
message: string()
|
|
56608
|
+
})
|
|
56609
|
+
]);
|
|
56610
|
+
var PackageDocsSchema = object({
|
|
56611
|
+
name: string(),
|
|
56612
|
+
version: string(),
|
|
56613
|
+
readme: PackageDocBodySchema,
|
|
56614
|
+
changelog: PackageDocBodySchema
|
|
56615
|
+
});
|
|
56195
56616
|
var SearchResultSchema = object({
|
|
56196
56617
|
name: string(),
|
|
56197
56618
|
version: string(),
|
|
@@ -56410,7 +56831,10 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
|
|
|
56410
56831
|
}), object({ success: literal(true) }), {
|
|
56411
56832
|
kind: "mutation",
|
|
56412
56833
|
auth: "admin"
|
|
56413
|
-
}), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({
|
|
56834
|
+
}), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({
|
|
56835
|
+
name: string().min(1),
|
|
56836
|
+
version: string().min(1).optional()
|
|
56837
|
+
}), PackageDocsSchema, { auth: "admin" }), method(object({ addonId: string() }), RestartAddonResultSchema, {
|
|
56414
56838
|
kind: "mutation",
|
|
56415
56839
|
auth: "admin"
|
|
56416
56840
|
}), method(object({ packageName: string() }), object({ success: literal(true) }), {
|
|
@@ -56469,27 +56893,17 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
|
|
|
56469
56893
|
*/
|
|
56470
56894
|
var AirQualitySensorStatusSchema = object({
|
|
56471
56895
|
/** Carbon dioxide concentration in ppm. */
|
|
56472
|
-
co2Ppm: number().min(0).optional(),
|
|
56896
|
+
co2Ppm: number().min(0).optional().meta(readingMeta("concentration-volume")),
|
|
56473
56897
|
/** Total volatile organic compounds in ppb. */
|
|
56474
|
-
vocPpb: number().min(0).optional(),
|
|
56898
|
+
vocPpb: number().min(0).optional().meta(readingMeta("concentration-ppb")),
|
|
56475
56899
|
/** Particulate matter ≤ 2.5 μm in µg/m³. */
|
|
56476
|
-
pm25: number().min(0).optional(),
|
|
56900
|
+
pm25: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
56477
56901
|
/** Particulate matter ≤ 10 μm in µg/m³. */
|
|
56478
|
-
pm10: number().min(0).optional(),
|
|
56902
|
+
pm10: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
56479
56903
|
/** Composite AQI value (typically 0..500). */
|
|
56480
|
-
aqi: number().optional(),
|
|
56904
|
+
aqi: number().optional().meta(readingMeta("index")),
|
|
56481
56905
|
/** Ms epoch when the slice was last updated. */
|
|
56482
|
-
lastFetchedAt: number()
|
|
56483
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
56484
|
-
* `attributes.unit_of_measurement` → 'ppm' / 'ppb' / 'µg/m³'). Each
|
|
56485
|
-
* upstream `sensor.*` entity surfaces ONE device_class, so one unit
|
|
56486
|
-
* per slice is unambiguous. */
|
|
56487
|
-
unit: string().optional(),
|
|
56488
|
-
/** Suggested decimal places for numeric display.
|
|
56489
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
56490
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
56491
|
-
* auto-formatting when absent. */
|
|
56492
|
-
precision: number().int().min(0).max(10).optional()
|
|
56906
|
+
lastFetchedAt: number()
|
|
56493
56907
|
});
|
|
56494
56908
|
var airQualitySensorCapability = {
|
|
56495
56909
|
name: "air-quality-sensor",
|
|
@@ -56526,12 +56940,12 @@ var airQualitySensorCapability = {
|
|
|
56526
56940
|
},
|
|
56527
56941
|
pm25: {
|
|
56528
56942
|
kind: "gauge",
|
|
56529
|
-
unit: "
|
|
56943
|
+
unit: "µg/m³",
|
|
56530
56944
|
deadband: 1
|
|
56531
56945
|
},
|
|
56532
56946
|
pm10: {
|
|
56533
56947
|
kind: "gauge",
|
|
56534
|
-
unit: "
|
|
56948
|
+
unit: "µg/m³",
|
|
56535
56949
|
deadband: 1
|
|
56536
56950
|
},
|
|
56537
56951
|
aqi: {
|
|
@@ -56549,22 +56963,13 @@ var airQualitySensorCapability = {
|
|
|
56549
56963
|
* entries with `device_class: illuminance`.
|
|
56550
56964
|
*/
|
|
56551
56965
|
var AmbientLightSensorStatusSchema = object({
|
|
56552
|
-
/** Current illuminance in lux (lx). */
|
|
56553
|
-
lux: number().min(0).meta({
|
|
56554
|
-
|
|
56966
|
+
/** Current illuminance in lux (lx). `null` when the sample was refused (D393). */
|
|
56967
|
+
lux: number().min(0).nullable().meta(readingMeta("illuminance", {
|
|
56968
|
+
precision: 0,
|
|
56555
56969
|
label: "Illuminance"
|
|
56556
|
-
}),
|
|
56970
|
+
})),
|
|
56557
56971
|
/** Ms epoch when the slice was last updated. */
|
|
56558
|
-
lastFetchedAt: number()
|
|
56559
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
56560
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
56561
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
56562
|
-
unit: string().optional(),
|
|
56563
|
-
/** Suggested decimal places for numeric display.
|
|
56564
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
56565
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
56566
|
-
* auto-formatting when absent. */
|
|
56567
|
-
precision: number().int().min(0).max(10).optional()
|
|
56972
|
+
lastFetchedAt: number()
|
|
56568
56973
|
});
|
|
56569
56974
|
var ambientLightSensorCapability = {
|
|
56570
56975
|
name: "ambient-light-sensor",
|
|
@@ -56596,12 +57001,7 @@ var ambientLightSensorCapability = {
|
|
|
56596
57001
|
} } },
|
|
56597
57002
|
/** Clock fields: written, but excluded from the compare that decides
|
|
56598
57003
|
* whether persisting is worth a SQLite commit. */
|
|
56599
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
56600
|
-
customize: {
|
|
56601
|
-
version: 1,
|
|
56602
|
-
advanced: "derive",
|
|
56603
|
-
targets: []
|
|
56604
|
-
}
|
|
57004
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
56605
57005
|
};
|
|
56606
57006
|
/**
|
|
56607
57007
|
* Per-class audio metrics aggregated over a sliding window.
|
|
@@ -56828,10 +57228,7 @@ var BatteryStatusSchema = object({
|
|
|
56828
57228
|
* Consumers must SKIP a null rather than coerce it — `battery-band` already
|
|
56829
57229
|
* declines to band a non-finite reading, which is the correct shape.
|
|
56830
57230
|
*/
|
|
56831
|
-
percentage: number().min(0).max(100).nullable().meta({
|
|
56832
|
-
unit: "%",
|
|
56833
|
-
label: "Charge"
|
|
56834
|
-
}),
|
|
57231
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage", { label: "Charge" })),
|
|
56835
57232
|
/**
|
|
56836
57233
|
* Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
|
|
56837
57234
|
* Reolink-specific for the Solar Panel 2 accessory (will become
|
|
@@ -56858,7 +57255,14 @@ var BatteryStatusSchema = object({
|
|
|
56858
57255
|
*/
|
|
56859
57256
|
sleeping: boolean().meta({ label: "Sleeping" }),
|
|
56860
57257
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
56861
|
-
lastUpdated: number(),
|
|
57258
|
+
lastUpdated: number().meta(readingMeta("none")),
|
|
57259
|
+
/**
|
|
57260
|
+
* Battery voltage in volts, for a cell the firmware reports as voltage
|
|
57261
|
+
* rather than a percentage (Ecowitt capacitor packs). Absent on cameras
|
|
57262
|
+
* that only report charge. A second reading on this cap, not a second
|
|
57263
|
+
* `numeric-sensor` on the same device.
|
|
57264
|
+
*/
|
|
57265
|
+
volts: number().nullable().optional().meta(readingMeta("voltage", { label: "Voltage" })),
|
|
56862
57266
|
/**
|
|
56863
57267
|
* Ms epoch of the last time the device PROVED it was reachable — a
|
|
56864
57268
|
* completed firmware round-trip, an observed wake, or an inbound push
|
|
@@ -56910,7 +57314,6 @@ var BATTERY_DEVICE_TYPES = [
|
|
|
56910
57314
|
/** Generic Customize target for the percentage reading (D936). */
|
|
56911
57315
|
var batteryCustomize = {
|
|
56912
57316
|
version: 1,
|
|
56913
|
-
advanced: "derive",
|
|
56914
57317
|
targets: [{
|
|
56915
57318
|
id: "percentage",
|
|
56916
57319
|
cardinality: "scalar",
|
|
@@ -56919,7 +57322,7 @@ var batteryCustomize = {
|
|
|
56919
57322
|
stateField: "percentage"
|
|
56920
57323
|
},
|
|
56921
57324
|
deviceTypes: BATTERY_DEVICE_TYPES,
|
|
56922
|
-
apply: "add
|
|
57325
|
+
apply: "add",
|
|
56923
57326
|
path: "percentage",
|
|
56924
57327
|
sources: [{
|
|
56925
57328
|
kind: "field",
|
|
@@ -57040,10 +57443,16 @@ onStatusChanged: { data: object({
|
|
|
57040
57443
|
/**
|
|
57041
57444
|
* History (D850): recorded series. The generic capture replaces the `battery` series of `pipeline-analytics:stats-5m`.
|
|
57042
57445
|
*/
|
|
57043
|
-
history: { fields: {
|
|
57044
|
-
|
|
57045
|
-
|
|
57046
|
-
|
|
57446
|
+
history: { fields: {
|
|
57447
|
+
percentage: {
|
|
57448
|
+
kind: "gauge",
|
|
57449
|
+
unit: "%"
|
|
57450
|
+
},
|
|
57451
|
+
volts: {
|
|
57452
|
+
kind: "gauge",
|
|
57453
|
+
unit: "V"
|
|
57454
|
+
}
|
|
57455
|
+
} },
|
|
57047
57456
|
customize: batteryCustomize,
|
|
57048
57457
|
/** Clock fields: written, but excluded from the compare that decides
|
|
57049
57458
|
* whether persisting is worth a SQLite commit. */
|
|
@@ -57090,12 +57499,7 @@ var binaryCapability = {
|
|
|
57090
57499
|
history: { fields: { on: { kind: "boolean" } } },
|
|
57091
57500
|
/** Clock fields: written, but excluded from the compare that decides
|
|
57092
57501
|
* whether persisting is worth a SQLite commit. */
|
|
57093
|
-
volatileStateFields: ["lastChangedAt"]
|
|
57094
|
-
customize: {
|
|
57095
|
-
version: 1,
|
|
57096
|
-
advanced: "derive",
|
|
57097
|
-
targets: []
|
|
57098
|
-
}
|
|
57502
|
+
volatileStateFields: ["lastChangedAt"]
|
|
57099
57503
|
};
|
|
57100
57504
|
/**
|
|
57101
57505
|
* Dimmable-light brightness control. Co-exists with `switch` on the
|
|
@@ -57111,7 +57515,7 @@ var binaryCapability = {
|
|
|
57111
57515
|
*/
|
|
57112
57516
|
var BrightnessStatusSchema = object({
|
|
57113
57517
|
/** Current level as 0..100 inclusive. Firmware-reported. */
|
|
57114
|
-
percentage: number().min(0).max(100),
|
|
57518
|
+
percentage: number().min(0).max(100).meta(readingMeta("percentage")),
|
|
57115
57519
|
/** Ms epoch of the last operator-driven change. Useful for UI freshness. */
|
|
57116
57520
|
lastChangedAt: number()
|
|
57117
57521
|
});
|
|
@@ -57565,21 +57969,21 @@ var ClimateControlStatusSchema = object({
|
|
|
57565
57969
|
/** Single setpoint in Celsius. Used by single-target modes
|
|
57566
57970
|
* (heat / cool / dry). Null when the device is in a range mode
|
|
57567
57971
|
* (`heat_cool`) or has no setpoint at all (`fan_only`/`off`). */
|
|
57568
|
-
target: number().nullable(),
|
|
57972
|
+
target: number().nullable().meta(readingMeta("temperature")),
|
|
57569
57973
|
/** Upper bound of the dual setpoint in Celsius. Populated only
|
|
57570
57974
|
* in `heat_cool` mode. */
|
|
57571
|
-
targetHigh: number().nullable(),
|
|
57975
|
+
targetHigh: number().nullable().meta(readingMeta("temperature")),
|
|
57572
57976
|
/** Lower bound of the dual setpoint in Celsius. Populated only
|
|
57573
57977
|
* in `heat_cool` mode. */
|
|
57574
|
-
targetLow: number().nullable(),
|
|
57978
|
+
targetLow: number().nullable().meta(readingMeta("temperature")),
|
|
57575
57979
|
/** Target relative humidity (0..100). Null when the device has no
|
|
57576
57980
|
* humidity control. */
|
|
57577
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
57981
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
57578
57982
|
/** Current measured temperature in Celsius. Read-only — pushed by
|
|
57579
57983
|
* the device's internal sensor. */
|
|
57580
|
-
currentTemp: number().nullable(),
|
|
57984
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
57581
57985
|
/** Current measured relative humidity (0..100). Read-only. */
|
|
57582
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
57986
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
57583
57987
|
/** Vertical louver swing on/off. Null when the device has no vertical
|
|
57584
57988
|
* swing surface (gate with `DeviceFeature.ClimateSwingVertical`). */
|
|
57585
57989
|
swingVertical: boolean().nullable(),
|
|
@@ -57587,11 +57991,11 @@ var ClimateControlStatusSchema = object({
|
|
|
57587
57991
|
* horizontal swing surface (gate with `DeviceFeature.ClimateSwingHorizontal`). */
|
|
57588
57992
|
swingHorizontal: boolean().nullable(),
|
|
57589
57993
|
/** Lowest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
57590
|
-
minTemp: number().nullable().optional(),
|
|
57994
|
+
minTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
57591
57995
|
/** Highest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
57592
|
-
maxTemp: number().nullable().optional(),
|
|
57996
|
+
maxTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
57593
57997
|
/** Setpoint granularity, Celsius (0.5, 1). Absent / null = not reported. */
|
|
57594
|
-
tempStep: number().positive().nullable().optional(),
|
|
57998
|
+
tempStep: number().positive().nullable().optional().meta(readingMeta("temperature")),
|
|
57595
57999
|
/** Ms epoch when the slice was last updated (push or command). */
|
|
57596
58000
|
lastFetchedAt: number()
|
|
57597
58001
|
});
|
|
@@ -57733,17 +58137,17 @@ var climateControlCapability = {
|
|
|
57733
58137
|
* modes to expose in the picker without a slice fetch.
|
|
57734
58138
|
*/
|
|
57735
58139
|
var RgbTripletSchema = object({
|
|
57736
|
-
r: number().int().min(0).max(255),
|
|
57737
|
-
g: number().int().min(0).max(255),
|
|
57738
|
-
b: number().int().min(0).max(255)
|
|
58140
|
+
r: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
58141
|
+
g: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
58142
|
+
b: number().int().min(0).max(255).meta(readingMeta("none"))
|
|
57739
58143
|
});
|
|
57740
58144
|
var HsvTripletSchema = object({
|
|
57741
58145
|
/** Hue in degrees, 0..360. */
|
|
57742
|
-
h: number().min(0).max(360),
|
|
58146
|
+
h: number().min(0).max(360).meta(readingMeta("none")),
|
|
57743
58147
|
/** Saturation as 0..100 inclusive. */
|
|
57744
|
-
s: number().min(0).max(100),
|
|
58148
|
+
s: number().min(0).max(100).meta(readingMeta("none")),
|
|
57745
58149
|
/** Value/brightness as 0..100 inclusive. */
|
|
57746
|
-
v: number().min(0).max(100)
|
|
58150
|
+
v: number().min(0).max(100).meta(readingMeta("none"))
|
|
57747
58151
|
});
|
|
57748
58152
|
var ColorInputSchema = discriminatedUnion("mode", [
|
|
57749
58153
|
object({
|
|
@@ -57772,7 +58176,7 @@ var ColorStatusSchema = object({
|
|
|
57772
58176
|
/** Populated when `mode === 'hsv'`. */
|
|
57773
58177
|
hsv: HsvTripletSchema.optional(),
|
|
57774
58178
|
/** Populated when `mode === 'mired'`. */
|
|
57775
|
-
mireds: number().int().optional(),
|
|
58179
|
+
mireds: number().int().optional().meta(readingMeta("colour-temperature")),
|
|
57776
58180
|
/** Ms epoch of the last operator-driven change. */
|
|
57777
58181
|
lastChangedAt: number()
|
|
57778
58182
|
});
|
|
@@ -57975,18 +58379,12 @@ _enum([
|
|
|
57975
58379
|
"empty",
|
|
57976
58380
|
"full"
|
|
57977
58381
|
]);
|
|
57978
|
-
/**
|
|
57979
|
-
|
|
57980
|
-
|
|
57981
|
-
"days",
|
|
57982
|
-
"hours",
|
|
57983
|
-
"cycles"
|
|
57984
|
-
]);
|
|
57985
|
-
/** Remaining life as a COUNT, not a percentage (the PetKit desiccant reports
|
|
57986
|
-
* days). `value` null = unknown (D393). */
|
|
58382
|
+
/** Whether `remaining.value` is a duration in seconds or a dimensionless count. */
|
|
58383
|
+
var ConsumableRemainingKindSchema = _enum(["duration", "count"]);
|
|
58384
|
+
/** Remaining life. `value` null = unknown (D393). Duration is seconds. */
|
|
57987
58385
|
var ConsumableRemainingSchema = object({
|
|
57988
|
-
value: number().min(0).nullable(),
|
|
57989
|
-
|
|
58386
|
+
value: number().min(0).nullable().meta(readingMeta("device")),
|
|
58387
|
+
kind: ConsumableRemainingKindSchema
|
|
57990
58388
|
});
|
|
57991
58389
|
/** A single consumable item. Either a continuous `level` (remaining
|
|
57992
58390
|
* life %, or fill % for a `supply` / `waste` item) or a discrete `status`
|
|
@@ -57999,7 +58397,7 @@ var ConsumableItemSchema = object({
|
|
|
57999
58397
|
/** Display name. */
|
|
58000
58398
|
label: string().min(1),
|
|
58001
58399
|
/** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
|
|
58002
|
-
level: number().min(0).max(100).nullable(),
|
|
58400
|
+
level: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58003
58401
|
/** The provider's discrete verdict when known (binary mode). */
|
|
58004
58402
|
status: ConsumableStatusSchema.nullable(),
|
|
58005
58403
|
/** What the item is — decides whether low or full is bad. Absent = `wear`. */
|
|
@@ -58081,8 +58479,8 @@ var consumablesCustomize = {
|
|
|
58081
58479
|
transforms: [{ kind: "identity" }]
|
|
58082
58480
|
}],
|
|
58083
58481
|
literals: [{
|
|
58084
|
-
path: "remaining.
|
|
58085
|
-
values: [...
|
|
58482
|
+
path: "remaining.kind",
|
|
58483
|
+
values: [...ConsumableRemainingKindSchema.options]
|
|
58086
58484
|
}]
|
|
58087
58485
|
},
|
|
58088
58486
|
{
|
|
@@ -58211,7 +58609,6 @@ reset: method(object({
|
|
|
58211
58609
|
},
|
|
58212
58610
|
"remaining.value": {
|
|
58213
58611
|
kind: "gauge",
|
|
58214
|
-
unitFrom: "remaining.unit",
|
|
58215
58612
|
deadband: 1,
|
|
58216
58613
|
displayName: "Remaining"
|
|
58217
58614
|
}
|
|
@@ -58281,10 +58678,9 @@ var contactCapability = {
|
|
|
58281
58678
|
* (empty array for the other kinds). It lives in the slice because
|
|
58282
58679
|
* HA `select.*` entities may update their options at runtime.
|
|
58283
58680
|
*
|
|
58284
|
-
*
|
|
58285
|
-
*
|
|
58286
|
-
*
|
|
58287
|
-
* push — consistent with `options` and the sensor-unit approach.
|
|
58681
|
+
* Numeric `min` / `max` / `step` live in the slice and share the device
|
|
58682
|
+
* quantity (`SourceInfo.quantity`, D944). Display precision is a read-time
|
|
58683
|
+
* preference. A datetime control's shape is `SourceInfo.dateTimeShape`.
|
|
58288
58684
|
*/
|
|
58289
58685
|
var ControlStatusSchema = object({
|
|
58290
58686
|
kind: _enum([
|
|
@@ -58296,39 +58692,17 @@ var ControlStatusSchema = object({
|
|
|
58296
58692
|
/** Current value. Numeric kind → number; select/text/datetime → string.
|
|
58297
58693
|
* Datetime values are ISO 8601 strings (full timestamp, date-only,
|
|
58298
58694
|
* or time-only — HA accepts all three forms). */
|
|
58299
|
-
value: union([number(), string()]),
|
|
58695
|
+
value: union([number().meta(readingMeta("device")), string()]),
|
|
58300
58696
|
/** Acceptable values when `kind === 'select'`. Empty for other kinds. */
|
|
58301
58697
|
options: array(string()),
|
|
58302
58698
|
/** Ms epoch when the slice was last updated. */
|
|
58303
58699
|
lastChangedAt: number(),
|
|
58304
|
-
/**
|
|
58305
|
-
|
|
58306
|
-
|
|
58307
|
-
|
|
58308
|
-
/**
|
|
58309
|
-
|
|
58310
|
-
min: number().optional(),
|
|
58311
|
-
/** Maximum allowed value. Populated live from HA `attributes.max`.
|
|
58312
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
58313
|
-
max: number().optional(),
|
|
58314
|
-
/** Step increment. Populated live from HA `attributes.step`.
|
|
58315
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
58316
|
-
step: number().optional(),
|
|
58317
|
-
/** Suggested decimal places for numeric display. Populated live from HA
|
|
58318
|
-
* `attributes.suggested_display_precision`, or derived from `step` when the
|
|
58319
|
-
* HA attribute is absent. Meaningful for `kind === 'numeric'`; absent for
|
|
58320
|
-
* other kinds. Falls back to auto-formatting when absent. */
|
|
58321
|
-
precision: number().int().min(0).max(10).optional(),
|
|
58322
|
-
/** Date-picker granularity for `kind === 'datetime'`. 'date' → date-only,
|
|
58323
|
-
* 'time' → time-only, 'datetime' → full timestamp. Absent for other kinds
|
|
58324
|
-
* (UI defaults to 'datetime'). Derived live from the device's HA domain
|
|
58325
|
-
* (date.* / time.* / datetime.*) or, for input_datetime, from the entity's
|
|
58326
|
-
* `has_date`/`has_time` attributes on each push. */
|
|
58327
|
-
format: _enum([
|
|
58328
|
-
"date",
|
|
58329
|
-
"time",
|
|
58330
|
-
"datetime"
|
|
58331
|
-
]).optional()
|
|
58700
|
+
/** Minimum allowed value, in the device quantity's base unit. */
|
|
58701
|
+
min: number().optional().meta(readingMeta("device")),
|
|
58702
|
+
/** Maximum allowed value, in the device quantity's base unit. */
|
|
58703
|
+
max: number().optional().meta(readingMeta("device")),
|
|
58704
|
+
/** Step increment, in the device quantity's base unit. */
|
|
58705
|
+
step: number().optional().meta(readingMeta("device"))
|
|
58332
58706
|
});
|
|
58333
58707
|
var ControlSetValueInputSchema = discriminatedUnion("kind", [
|
|
58334
58708
|
object({
|
|
@@ -58394,9 +58768,9 @@ var CoverStatusSchema = object({
|
|
|
58394
58768
|
]),
|
|
58395
58769
|
/** 0 = fully closed, 100 = fully open. Null when the device has
|
|
58396
58770
|
* no intermediate position surface. */
|
|
58397
|
-
position: number().min(0).max(100).nullable(),
|
|
58771
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58398
58772
|
/** 0 = closed slats, 100 = open slats. Null when no tilt support. */
|
|
58399
|
-
tiltPosition: number().min(0).max(100).nullable(),
|
|
58773
|
+
tiltPosition: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58400
58774
|
/** Ms epoch when the slice was last updated. */
|
|
58401
58775
|
lastChangedAt: number()
|
|
58402
58776
|
});
|
|
@@ -58499,9 +58873,9 @@ var NormalizedRangeSchema$1 = object({
|
|
|
58499
58873
|
var DayNightStatusSchema = object({
|
|
58500
58874
|
mode: DayNightModeSchema,
|
|
58501
58875
|
/** IR-cut trigger sensitivity, NORMALIZED 0–100 (higher = switches to night sooner). */
|
|
58502
|
-
sensitivity: number().optional(),
|
|
58876
|
+
sensitivity: number().optional().meta(readingMeta("none")),
|
|
58503
58877
|
/** Delay before the IR-cut filter flips, in seconds. */
|
|
58504
|
-
switchDelaySec: number().optional(),
|
|
58878
|
+
switchDelaySec: number().optional().meta(readingMeta("duration")),
|
|
58505
58879
|
lastFetchedAt: number()
|
|
58506
58880
|
});
|
|
58507
58881
|
/**
|
|
@@ -58719,11 +59093,11 @@ var DishwasherStatusSchema = object({
|
|
|
58719
59093
|
/** Feature keys of the programs the appliance currently offers — drives the UI selector. */
|
|
58720
59094
|
availablePrograms: array(string()),
|
|
58721
59095
|
/** Seconds remaining on the active cycle, or null when not running / not known. */
|
|
58722
|
-
remainingSeconds: number().int().nonnegative().nullable(),
|
|
59096
|
+
remainingSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
58723
59097
|
/** Seconds the delayed start is set to (time until the cycle starts), or null. */
|
|
58724
|
-
delayedStartSeconds: number().int().nonnegative().nullable(),
|
|
59098
|
+
delayedStartSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
58725
59099
|
/** Cycle completion 0..100, or null when not applicable. */
|
|
58726
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
59100
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58727
59101
|
/** True when the door is reported open; null when the door state is not known. */
|
|
58728
59102
|
doorOpen: boolean().nullable(),
|
|
58729
59103
|
/** True when the door is latched (locked) during a cycle; null when not reported. */
|
|
@@ -58747,7 +59121,7 @@ var DishwasherStatusSchema = object({
|
|
|
58747
59121
|
/** True while the machine-care (descaling / cleaning-program) reminder is raised; false when clear; null when not reported. */
|
|
58748
59122
|
machineCareDue: boolean().nullable(),
|
|
58749
59123
|
/** Program runs left before the machine-care reminder is due; null when the appliance does not say. */
|
|
58750
|
-
machineCareRemainingRuns: number().int().nonnegative().nullable(),
|
|
59124
|
+
machineCareRemainingRuns: number().int().nonnegative().nullable().meta(readingMeta("count")),
|
|
58751
59125
|
/** Option states: null when the appliance does not expose the option or has not said. */
|
|
58752
59126
|
halfLoad: boolean().nullable(),
|
|
58753
59127
|
hygienePlus: boolean().nullable(),
|
|
@@ -58762,7 +59136,7 @@ var DishwasherStatusSchema = object({
|
|
|
58762
59136
|
/** Feature keys of the events currently raised (salt low, rinse aid low, program finished, …). */
|
|
58763
59137
|
activeEvents: array(string()),
|
|
58764
59138
|
/** Numeric error code when the appliance reports one; null otherwise. */
|
|
58765
|
-
errorCode: number().nullable(),
|
|
59139
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
58766
59140
|
/** Name of the raised alert-level event while the appliance is in error; null otherwise. */
|
|
58767
59141
|
errorLabel: string().nullable(),
|
|
58768
59142
|
/** Ms epoch of the last value received from the appliance; 0 = never. */
|
|
@@ -58993,7 +59367,7 @@ var DoorbellStatusSchema = object({
|
|
|
58993
59367
|
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
58994
59368
|
lastPressedAt: number().nullable(),
|
|
58995
59369
|
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
58996
|
-
pressCountSinceStart: number()
|
|
59370
|
+
pressCountSinceStart: number().meta(readingMeta("count"))
|
|
58997
59371
|
});
|
|
58998
59372
|
var DoorbellPressEventSchema = object({
|
|
58999
59373
|
deviceId: number(),
|
|
@@ -59058,17 +59432,7 @@ onPressed: {
|
|
|
59058
59432
|
history: "none",
|
|
59059
59433
|
customize: doorbellCustomize
|
|
59060
59434
|
};
|
|
59061
|
-
|
|
59062
|
-
* Enum-state sensor — a string value picked from a finite option set.
|
|
59063
|
-
* Drives HA `sensor` entries with `state_class: enum` (HVAC action
|
|
59064
|
-
* states, weather conditions, contact-source channels, mode strings).
|
|
59065
|
-
* The option set is stable across observations; it is persisted in the
|
|
59066
|
-
* device config blob (via the control slice at adoption) and is NOT
|
|
59067
|
-
* stored in `sourceInfo`.
|
|
59068
|
-
*/
|
|
59069
|
-
/** Locale-render shape for an ISO `value` carried by a `DateTimeSensor`-role
|
|
59070
|
-
* enum sensor: `date` (date-only), `time` (time-only), `datetime` (both). */
|
|
59071
|
-
var EnumSensorDateTimeFormatSchema = _enum([
|
|
59435
|
+
_enum([
|
|
59072
59436
|
"date",
|
|
59073
59437
|
"time",
|
|
59074
59438
|
"datetime"
|
|
@@ -59076,12 +59440,11 @@ var EnumSensorDateTimeFormatSchema = _enum([
|
|
|
59076
59440
|
var EnumSensorStatusSchema = object({
|
|
59077
59441
|
value: string(),
|
|
59078
59442
|
/**
|
|
59079
|
-
* Set
|
|
59080
|
-
* as
|
|
59081
|
-
*
|
|
59082
|
-
* a time-only sensor → `'time'`.
|
|
59443
|
+
* Set when `value` is a timestamp rather than an enum state, so history
|
|
59444
|
+
* does not learn ISO strings as states. The display shape (date / time /
|
|
59445
|
+
* datetime) lives on `SourceInfo.dateTimeShape`, written once at adopt.
|
|
59083
59446
|
*/
|
|
59084
|
-
|
|
59447
|
+
timestamp: boolean().optional(),
|
|
59085
59448
|
/** Ms epoch when the slice was last updated. */
|
|
59086
59449
|
lastFetchedAt: number()
|
|
59087
59450
|
});
|
|
@@ -59108,11 +59471,11 @@ var enumSensorCapability = {
|
|
|
59108
59471
|
* History (D850): the value as an `enum` series (an appliance's program or
|
|
59109
59472
|
* operation state, an HVAC action). The option set is per device, so the
|
|
59110
59473
|
* value list is LEARNED as values are first seen (bounded). A sensor with a
|
|
59111
|
-
* `
|
|
59474
|
+
* `timestamp` carries a clock, not a state, and is not recorded.
|
|
59112
59475
|
*/
|
|
59113
59476
|
history: { fields: { value: {
|
|
59114
59477
|
kind: "enum",
|
|
59115
|
-
skipWhenSet: "
|
|
59478
|
+
skipWhenSet: "timestamp"
|
|
59116
59479
|
} } },
|
|
59117
59480
|
/** Clock fields: written, but excluded from the compare that decides
|
|
59118
59481
|
* whether persisting is worth a SQLite commit. */
|
|
@@ -59132,13 +59495,13 @@ var EventFireSchema = object({
|
|
|
59132
59495
|
deviceId: number(),
|
|
59133
59496
|
eventType: string(),
|
|
59134
59497
|
data: record(string(), unknown()).nullable(),
|
|
59135
|
-
timestamp: number(),
|
|
59136
|
-
seq: number()
|
|
59498
|
+
timestamp: number().meta(readingMeta("none")),
|
|
59499
|
+
seq: number().meta(readingMeta("count"))
|
|
59137
59500
|
});
|
|
59138
59501
|
var EventEmitterStatusSchema = object({
|
|
59139
59502
|
eventTypes: array(string()),
|
|
59140
59503
|
lastEvent: EventFireSchema.nullable(),
|
|
59141
|
-
eventCountSinceStart: number()
|
|
59504
|
+
eventCountSinceStart: number().meta(readingMeta("count"))
|
|
59142
59505
|
});
|
|
59143
59506
|
var eventEmitterCapability = {
|
|
59144
59507
|
name: "event-emitter",
|
|
@@ -59551,10 +59914,10 @@ var FanDirectionSchema = _enum(["forward", "reverse"]);
|
|
|
59551
59914
|
var FanControlStatusSchema = object({
|
|
59552
59915
|
/** Active speed as 0..100 inclusive. Null when the device has no
|
|
59553
59916
|
* speed surface (single-speed fan). */
|
|
59554
|
-
percentage: number().min(0).max(100).nullable(),
|
|
59917
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59555
59918
|
/** Speed granularity the device accepts (HA `percentage_step`, e.g. 25 for
|
|
59556
59919
|
* a 4-speed fan). Absent when unknown — the UI then falls back to step 1. */
|
|
59557
|
-
percentageStep: number().positive().optional(),
|
|
59920
|
+
percentageStep: number().positive().optional().meta(readingMeta("percentage")),
|
|
59558
59921
|
/** Active preset mode (`auto` / `quiet` / `turbo` / vendor-specific)
|
|
59559
59922
|
* — empty string when no preset is active or supported. */
|
|
59560
59923
|
preset: string(),
|
|
@@ -59675,7 +60038,7 @@ var FeatureProbeStatusSchema = object({
|
|
|
59675
60038
|
/** Camera/firmware model string. `null` when the firmware doesn't expose it. */
|
|
59676
60039
|
model: string().nullable(),
|
|
59677
60040
|
/** Channel count for NVR/Hub devices; `1` for standalone cameras; `null` pre-probe. */
|
|
59678
|
-
channelCount: number().nullable(),
|
|
60041
|
+
channelCount: number().nullable().meta(readingMeta("count")),
|
|
59679
60042
|
/**
|
|
59680
60043
|
* Ms epoch of the last SUCCESSFUL probe. `0` before the first probe
|
|
59681
60044
|
* completes — drivers' `getAccessoryChildren()` should treat zero as
|
|
@@ -59798,9 +60161,91 @@ var gasCapability = {
|
|
|
59798
60161
|
* whether persisting is worth a SQLite commit. */
|
|
59799
60162
|
volatileStateFields: ["lastChangedAt"]
|
|
59800
60163
|
};
|
|
60164
|
+
var GroupCommandsSchema = object({
|
|
60165
|
+
/** One row per member that has been commanded. A later command replaces that member's row. */
|
|
60166
|
+
results: array(object({
|
|
60167
|
+
deviceId: number().int().nonnegative(),
|
|
60168
|
+
cap: string().min(1),
|
|
60169
|
+
method: string().min(1),
|
|
60170
|
+
ok: boolean(),
|
|
60171
|
+
error: string().optional(),
|
|
60172
|
+
/** Ms epoch of the attempt. */
|
|
60173
|
+
at: number()
|
|
60174
|
+
})) });
|
|
60175
|
+
var groupCommandsCapability = {
|
|
60176
|
+
name: "group-commands",
|
|
60177
|
+
scope: "device",
|
|
60178
|
+
deviceNative: true,
|
|
60179
|
+
mode: "singleton",
|
|
60180
|
+
deviceTypes: [DeviceType.Switch, DeviceType.Light],
|
|
60181
|
+
methods: {},
|
|
60182
|
+
status: {
|
|
60183
|
+
schema: GroupCommandsSchema,
|
|
60184
|
+
kind: "push"
|
|
60185
|
+
},
|
|
60186
|
+
runtimeState: GroupCommandsSchema,
|
|
60187
|
+
/**
|
|
60188
|
+
* Runtime-state durability: **session** — the last attempt. A restored
|
|
60189
|
+
* failure would outlive the command that caused it.
|
|
60190
|
+
*
|
|
60191
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
60192
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
60193
|
+
*/
|
|
60194
|
+
durability: "session",
|
|
60195
|
+
history: "none"
|
|
60196
|
+
};
|
|
60197
|
+
/**
|
|
60198
|
+
* How many members of a helper group answered (D944). Counts are integers,
|
|
60199
|
+
* not measurements: zero included is a real count, never a stand-in reading.
|
|
60200
|
+
* The reading itself stays on the output capability. History is none — the
|
|
60201
|
+
* series that later statistics read is the output cap's own history block.
|
|
60202
|
+
*/
|
|
60203
|
+
var GroupStatusSchema = object({
|
|
60204
|
+
/** Members whose current value entered the aggregate. */
|
|
60205
|
+
included: number().int().nonnegative().meta(readingMeta("count", {
|
|
60206
|
+
precision: 0,
|
|
60207
|
+
label: "Reporting"
|
|
60208
|
+
})),
|
|
60209
|
+
/** Members left out: offline, unknown, or not a finite reading (D393). */
|
|
60210
|
+
excluded: number().int().nonnegative().meta(readingMeta("count", {
|
|
60211
|
+
precision: 0,
|
|
60212
|
+
label: "Excluded"
|
|
60213
|
+
})),
|
|
60214
|
+
/** `included` + `excluded`. */
|
|
60215
|
+
total: number().int().nonnegative().meta(readingMeta("count", {
|
|
60216
|
+
precision: 0,
|
|
60217
|
+
label: "Members"
|
|
60218
|
+
}))
|
|
60219
|
+
});
|
|
60220
|
+
var groupStatusCapability = {
|
|
60221
|
+
name: "group-status",
|
|
60222
|
+
scope: "device",
|
|
60223
|
+
deviceNative: true,
|
|
60224
|
+
mode: "singleton",
|
|
60225
|
+
deviceTypes: [
|
|
60226
|
+
DeviceType.Sensor,
|
|
60227
|
+
DeviceType.Switch,
|
|
60228
|
+
DeviceType.Light
|
|
60229
|
+
],
|
|
60230
|
+
methods: {},
|
|
60231
|
+
status: {
|
|
60232
|
+
schema: GroupStatusSchema,
|
|
60233
|
+
kind: "push"
|
|
60234
|
+
},
|
|
60235
|
+
runtimeState: GroupStatusSchema,
|
|
60236
|
+
/**
|
|
60237
|
+
* Runtime-state durability: **session** — recomputed from members on the
|
|
60238
|
+
* next source event; a restored count would outlive the readings it named.
|
|
60239
|
+
*
|
|
60240
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
60241
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
60242
|
+
*/
|
|
60243
|
+
durability: "session",
|
|
60244
|
+
history: "none"
|
|
60245
|
+
};
|
|
59801
60246
|
var HeatingValveStatusSchema = object({
|
|
59802
60247
|
/** Radiator valve opening 0 (closed) .. 100 (open). Null = not yet known. */
|
|
59803
|
-
position: number().min(0).max(100).nullable(),
|
|
60248
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59804
60249
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
59805
60250
|
lastFetchedAt: number()
|
|
59806
60251
|
});
|
|
@@ -59843,9 +60288,9 @@ var HumidifierStatusSchema = object({
|
|
|
59843
60288
|
/** Whether the humidifier is currently on. */
|
|
59844
60289
|
on: boolean(),
|
|
59845
60290
|
/** Current measured relative humidity (0..100). Null when not reported. */
|
|
59846
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
60291
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
59847
60292
|
/** Target relative humidity (0..100). Null when no setpoint surface. */
|
|
59848
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
60293
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
59849
60294
|
/** Active mode (`auto` / `normal` / `baby` / vendor). Null when the
|
|
59850
60295
|
* device has no mode surface. */
|
|
59851
60296
|
mode: string().nullable(),
|
|
@@ -59855,9 +60300,9 @@ var HumidifierStatusSchema = object({
|
|
|
59855
60300
|
* `idle` / `off`). Null when the device doesn't report it. */
|
|
59856
60301
|
action: string().nullable(),
|
|
59857
60302
|
/** HA `min_humidity` attribute. Null → UI uses 0. */
|
|
59858
|
-
minHumidity: number().nullable(),
|
|
60303
|
+
minHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
59859
60304
|
/** HA `max_humidity` attribute. Null → UI uses 100. */
|
|
59860
|
-
maxHumidity: number().nullable(),
|
|
60305
|
+
maxHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
59861
60306
|
/** Ms epoch when the slice was last updated. */
|
|
59862
60307
|
lastChangedAt: number()
|
|
59863
60308
|
});
|
|
@@ -59927,22 +60372,13 @@ var humidifierCapability = {
|
|
|
59927
60372
|
* `sourceInfo`.
|
|
59928
60373
|
*/
|
|
59929
60374
|
var HumiditySensorStatusSchema = object({
|
|
59930
|
-
/** Current relative humidity, 0..100. */
|
|
59931
|
-
percent: number().min(0).max(100).meta({
|
|
59932
|
-
|
|
60375
|
+
/** Current relative humidity, 0..100. `null` when the sample was refused (D393). */
|
|
60376
|
+
percent: number().min(0).max(100).nullable().meta(readingMeta("humidity", {
|
|
60377
|
+
precision: 0,
|
|
59933
60378
|
label: "Humidity"
|
|
59934
|
-
}),
|
|
60379
|
+
})),
|
|
59935
60380
|
/** Ms epoch when the slice was last updated. */
|
|
59936
|
-
lastFetchedAt: number()
|
|
59937
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
59938
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
59939
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
59940
|
-
unit: string().optional(),
|
|
59941
|
-
/** Suggested decimal places for numeric display.
|
|
59942
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
59943
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
59944
|
-
* auto-formatting when absent. */
|
|
59945
|
-
precision: number().int().min(0).max(10).optional()
|
|
60381
|
+
lastFetchedAt: number()
|
|
59946
60382
|
});
|
|
59947
60383
|
var humiditySensorCapability = {
|
|
59948
60384
|
name: "humidity-sensor",
|
|
@@ -59973,12 +60409,7 @@ var humiditySensorCapability = {
|
|
|
59973
60409
|
} } },
|
|
59974
60410
|
/** Clock fields: written, but excluded from the compare that decides
|
|
59975
60411
|
* whether persisting is worth a SQLite commit. */
|
|
59976
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
59977
|
-
customize: {
|
|
59978
|
-
version: 1,
|
|
59979
|
-
advanced: "derive",
|
|
59980
|
-
targets: []
|
|
59981
|
-
}
|
|
60412
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
59982
60413
|
};
|
|
59983
60414
|
/**
|
|
59984
60415
|
* Image display cap. Models a single still image exposed by an integration —
|
|
@@ -59999,7 +60430,7 @@ var ImageStatusSchema = object({
|
|
|
59999
60430
|
* entity exposes no `entity_picture` (yet). */
|
|
60000
60431
|
url: string().nullable(),
|
|
60001
60432
|
/** Ms epoch of the upstream last-updated timestamp. Null at cold-start. */
|
|
60002
|
-
lastUpdated: number().nullable()
|
|
60433
|
+
lastUpdated: number().nullable().meta(readingMeta("none"))
|
|
60003
60434
|
});
|
|
60004
60435
|
var imageCapability = {
|
|
60005
60436
|
name: "image",
|
|
@@ -60087,19 +60518,19 @@ var NormalizedRangeSchema = object({
|
|
|
60087
60518
|
*/
|
|
60088
60519
|
var ImageSettingsStatusSchema = object({
|
|
60089
60520
|
/** Normalized 0–100. */
|
|
60090
|
-
brightness: number().optional(),
|
|
60521
|
+
brightness: number().optional().meta(readingMeta("none")),
|
|
60091
60522
|
/** Normalized 0–100. */
|
|
60092
|
-
contrast: number().optional(),
|
|
60523
|
+
contrast: number().optional().meta(readingMeta("none")),
|
|
60093
60524
|
/** Normalized 0–100. */
|
|
60094
|
-
saturation: number().optional(),
|
|
60525
|
+
saturation: number().optional().meta(readingMeta("none")),
|
|
60095
60526
|
/** Normalized 0–100. */
|
|
60096
|
-
sharpness: number().optional(),
|
|
60527
|
+
sharpness: number().optional().meta(readingMeta("none")),
|
|
60097
60528
|
mirror: boolean().optional(),
|
|
60098
60529
|
flip: boolean().optional(),
|
|
60099
60530
|
rotate: ImageRotateSchema.optional(),
|
|
60100
60531
|
whiteBalance: WhiteBalanceModeSchema.optional(),
|
|
60101
60532
|
/** Manual white-balance warmth, NORMALIZED 0–100. Meaningful only when `whiteBalance === 'manual'`. */
|
|
60102
|
-
warmth: number().optional(),
|
|
60533
|
+
warmth: number().optional().meta(readingMeta("none")),
|
|
60103
60534
|
exposureMode: ExposureModeSchema.optional(),
|
|
60104
60535
|
backlightMode: BacklightModeSchema.optional(),
|
|
60105
60536
|
lastFetchedAt: number()
|
|
@@ -60378,10 +60809,10 @@ var IntercomAbilitySchema = object({
|
|
|
60378
60809
|
/** Codecs accepted by firmware, in preference order. Driver-authored strings. */
|
|
60379
60810
|
codecs: array(string()),
|
|
60380
60811
|
/** Sample rate (Hz) the firmware expects. Reolink typical: 16000. */
|
|
60381
|
-
sampleRate: number(),
|
|
60812
|
+
sampleRate: number().meta(readingMeta("none")),
|
|
60382
60813
|
duplex: _enum(["half", "full"]),
|
|
60383
60814
|
/** Max in-flight audio backlog before drop (ms). Server uses this to bound latency. */
|
|
60384
|
-
maxBacklogMs: number()
|
|
60815
|
+
maxBacklogMs: number().meta(readingMeta("duration-ms"))
|
|
60385
60816
|
});
|
|
60386
60817
|
var IntercomStatusSchema = object({
|
|
60387
60818
|
/** True while a talk session is open. */
|
|
@@ -60608,13 +61039,13 @@ var LawnMowerControlStatusSchema = object({
|
|
|
60608
61039
|
activity: LawnMowerActivitySchema,
|
|
60609
61040
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
60610
61041
|
* reading. */
|
|
60611
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
61042
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
60612
61043
|
/** 0..100 mowing-completion percentage of the current task, or null when no
|
|
60613
61044
|
* task is active / progress is unavailable. */
|
|
60614
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
61045
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
60615
61046
|
/** Current device/event code (dynamic — mostly status, sometimes an error),
|
|
60616
61047
|
* or null when unknown. */
|
|
60617
|
-
currentCode: number().nullable(),
|
|
61048
|
+
currentCode: number().nullable().meta(readingMeta("none")),
|
|
60618
61049
|
/** Human label for {@link currentCode}, or null when undecodable. */
|
|
60619
61050
|
currentCodeLabel: string().nullable(),
|
|
60620
61051
|
/** Severity of {@link currentCode}. `error` (and often `warning`) warrants UI
|
|
@@ -61147,7 +61578,7 @@ var MediaPlayerStatusSchema = object({
|
|
|
61147
61578
|
state: MediaPlayerStateSchema,
|
|
61148
61579
|
/** Volume as 0..100 inclusive. Null when the device has no volume
|
|
61149
61580
|
* surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
|
|
61150
|
-
volumeLevel: number().min(0).max(100).nullable(),
|
|
61581
|
+
volumeLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61151
61582
|
/** Mute toggle distinct from volume=0. Null when no mute surface.
|
|
61152
61583
|
* Pair with `DeviceFeature.MediaPlayerMute`. */
|
|
61153
61584
|
isMuted: boolean().nullable(),
|
|
@@ -61160,10 +61591,10 @@ var MediaPlayerStatusSchema = object({
|
|
|
61160
61591
|
currentMedia: MediaInfoSchema.nullable(),
|
|
61161
61592
|
/** Current playback position in ms. Null when not seekable or
|
|
61162
61593
|
* nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
|
|
61163
|
-
positionMs: number().int().nonnegative().nullable(),
|
|
61594
|
+
positionMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
61164
61595
|
/** Total duration of the current media in ms. Null when unknown
|
|
61165
61596
|
* (live stream) or nothing is playing. */
|
|
61166
|
-
durationMs: number().int().nonnegative().nullable(),
|
|
61597
|
+
durationMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
61167
61598
|
/** Shuffle toggle. Null when no shuffle surface.
|
|
61168
61599
|
* Pair with `DeviceFeature.MediaPlayerShuffle`. */
|
|
61169
61600
|
shuffle: boolean().nullable(),
|
|
@@ -61472,7 +61903,7 @@ var motionCustomize = {
|
|
|
61472
61903
|
eventName: "onMotionChanged"
|
|
61473
61904
|
},
|
|
61474
61905
|
deviceTypes: [DeviceType.Camera],
|
|
61475
|
-
apply: "
|
|
61906
|
+
apply: "add",
|
|
61476
61907
|
applyAuthority: {
|
|
61477
61908
|
kind: "camera-sensors",
|
|
61478
61909
|
timeoutField: "motionCooldownMs"
|
|
@@ -61544,7 +61975,7 @@ var MotionStatusSchema = object({
|
|
|
61544
61975
|
* it, every provider seeded it at boot, and every session left it
|
|
61545
61976
|
* `detected: true` after its detach.
|
|
61546
61977
|
*/
|
|
61547
|
-
autoClearAfterMs: number().nullable()
|
|
61978
|
+
autoClearAfterMs: number().nullable().meta(readingMeta("duration-ms"))
|
|
61548
61979
|
});
|
|
61549
61980
|
/**
|
|
61550
61981
|
* Payload of `motion.onMotionChanged` event + the corresponding bus
|
|
@@ -61581,12 +62012,18 @@ var motionCapability = {
|
|
|
61581
62012
|
methods: {
|
|
61582
62013
|
/**
|
|
61583
62014
|
* Pull the current motion state synchronously. Convenience shortcut
|
|
61584
|
-
* for consumers that don't need the full status object
|
|
61585
|
-
*
|
|
61586
|
-
* `getStatus` once the auto-injected status surface lands in every
|
|
61587
|
-
* consumer.
|
|
62015
|
+
* for consumers that don't need the full status object. A composed
|
|
62016
|
+
* group answers from its slice (D944): unknown throws, it is not off.
|
|
61588
62017
|
*/
|
|
61589
62018
|
isDetected: method(object({ deviceId: number() }), boolean()) },
|
|
62019
|
+
/**
|
|
62020
|
+
* A composed motion group serves `isDetected` from `detected` (D944).
|
|
62021
|
+
* Without this the cap stays uncomposable (`has-commands`).
|
|
62022
|
+
*/
|
|
62023
|
+
composedMethods: { isDetected: {
|
|
62024
|
+
kind: "slice",
|
|
62025
|
+
field: "detected"
|
|
62026
|
+
} },
|
|
61590
62027
|
events: {
|
|
61591
62028
|
/**
|
|
61592
62029
|
* Fires every time the runner transitions a camera between
|
|
@@ -61726,7 +62163,7 @@ var MotionZoneRegionSchema = object({
|
|
|
61726
62163
|
* the grid region(s). */
|
|
61727
62164
|
var MotionZoneStatusSchema = object({
|
|
61728
62165
|
enabled: boolean(),
|
|
61729
|
-
sensitivity: number(),
|
|
62166
|
+
sensitivity: number().meta(readingMeta("none")),
|
|
61730
62167
|
/** Grid region(s). Today exactly one `grid` shape. */
|
|
61731
62168
|
regions: array(MotionZoneRegionSchema),
|
|
61732
62169
|
lastFetchedAt: number()
|
|
@@ -62096,7 +62533,7 @@ var NavigationStatusSchema = object({
|
|
|
62096
62533
|
following: boolean(),
|
|
62097
62534
|
flash: boolean(),
|
|
62098
62535
|
lightMode: NavigationLightModeSchema,
|
|
62099
|
-
lightLevel: number().min(40).max(100),
|
|
62536
|
+
lightLevel: number().min(40).max(100).meta(readingMeta("none")),
|
|
62100
62537
|
/** Ms epoch when the slice was last updated. */
|
|
62101
62538
|
lastChangedAt: number()
|
|
62102
62539
|
});
|
|
@@ -62230,13 +62667,13 @@ var NetworkLinkStatusSchema = object({
|
|
|
62230
62667
|
* one whose reading has not landed must not be drawn at 0 %. Consumers
|
|
62231
62668
|
* SKIP a null rather than coerce it.
|
|
62232
62669
|
*/
|
|
62233
|
-
signalPercent: number().min(0).max(100).nullable(),
|
|
62670
|
+
signalPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
62234
62671
|
/** Raw received signal strength in dBm, when the firmware reports one. */
|
|
62235
|
-
rssiDbm: number().optional(),
|
|
62672
|
+
rssiDbm: number().optional().meta(readingMeta("signal-level")),
|
|
62236
62673
|
/** Network name of a wireless link, when the firmware reports it. */
|
|
62237
62674
|
ssid: string().optional(),
|
|
62238
62675
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
62239
|
-
lastUpdated: number()
|
|
62676
|
+
lastUpdated: number().meta(readingMeta("none"))
|
|
62240
62677
|
});
|
|
62241
62678
|
var networkLinkCapability = {
|
|
62242
62679
|
name: "network-link",
|
|
@@ -62621,7 +63058,7 @@ var NotifierStatusSchema = object({
|
|
|
62621
63058
|
lastError: string().nullable(),
|
|
62622
63059
|
/** Number of deliveries currently buffered server-side (rate-limited
|
|
62623
63060
|
* notifiers may queue). 0 when the provider sends synchronously. */
|
|
62624
|
-
queueDepth: number().int().nonnegative(),
|
|
63061
|
+
queueDepth: number().int().nonnegative().meta(readingMeta("count")),
|
|
62625
63062
|
/** Per-feature capability matrix — authoritative source for the
|
|
62626
63063
|
* compose-form field gating. */
|
|
62627
63064
|
supports: NotifierSupportsSchema
|
|
@@ -62713,11 +63150,9 @@ onSent: { data: object({
|
|
|
62713
63150
|
* cap fits (HA `sensor` whose `device_class` we don't have a typed cap
|
|
62714
63151
|
* for: water flow, distance, weight, frequency, signal strength, …).
|
|
62715
63152
|
*
|
|
62716
|
-
* The
|
|
62717
|
-
*
|
|
62718
|
-
*
|
|
62719
|
-
* The UI reads them directly from the slice — they are the single source
|
|
62720
|
-
* of truth for generic numeric rendering and do NOT live on `sourceInfo`.
|
|
63153
|
+
* The quantity is not on this slice. It is chosen when the device is
|
|
63154
|
+
* adopted and stored once on `SourceInfo.quantity` (D944). `value` is in
|
|
63155
|
+
* that quantity's base unit. `null` is a refused sample (D393).
|
|
62721
63156
|
*
|
|
62722
63157
|
* Prefer the typed alternatives (`temperature-sensor`, `humidity-sensor`,
|
|
62723
63158
|
* `ambient-light-sensor`, `pressure-sensor`, `power-meter`,
|
|
@@ -62726,15 +63161,8 @@ onSent: { data: object({
|
|
|
62726
63161
|
* numeric values land here.
|
|
62727
63162
|
*/
|
|
62728
63163
|
var NumericSensorStatusSchema = object({
|
|
62729
|
-
|
|
62730
|
-
|
|
62731
|
-
* Populated live from the upstream source on each state push.
|
|
62732
|
-
* Absent for unitless sensors. */
|
|
62733
|
-
unit: string().optional(),
|
|
62734
|
-
/** Suggested decimal places for numeric display.
|
|
62735
|
-
* Populated live from the upstream source when provided.
|
|
62736
|
-
* Falls back to auto-formatting when absent. */
|
|
62737
|
-
precision: number().int().min(0).max(10).optional(),
|
|
63164
|
+
/** Reading in the device quantity's base unit. `null` when refused (D393). */
|
|
63165
|
+
value: number().nullable().meta(readingMeta("device")),
|
|
62738
63166
|
/** Ms epoch when the slice was last updated. */
|
|
62739
63167
|
lastFetchedAt: number()
|
|
62740
63168
|
});
|
|
@@ -62758,11 +63186,11 @@ var numericSensorCapability = {
|
|
|
62758
63186
|
*/
|
|
62759
63187
|
durability: "restored",
|
|
62760
63188
|
/**
|
|
62761
|
-
* History (D850): recorded series. The unit is
|
|
63189
|
+
* History (D850): recorded series. The unit is the device quantity's base,
|
|
63190
|
+
* resolved when the series is read — the cap has no single unit.
|
|
62762
63191
|
*/
|
|
62763
63192
|
history: { fields: { value: {
|
|
62764
63193
|
kind: "gauge",
|
|
62765
|
-
unitFrom: "unit",
|
|
62766
63194
|
minIntervalMs: 3e4
|
|
62767
63195
|
} } },
|
|
62768
63196
|
/** Clock fields: written, but excluded from the compare that decides
|
|
@@ -63054,23 +63482,26 @@ var PetFeederStatusSchema = object({
|
|
|
63054
63482
|
/** Food currently in the bowl (grams). Null when the device has not
|
|
63055
63483
|
* reported a reading yet. On dual-hopper models this is the combined
|
|
63056
63484
|
* bowl reading; per-hopper levels live in `food1`/`food2`. */
|
|
63057
|
-
foodLevel: number().nullable(),
|
|
63485
|
+
foodLevel: number().nullable().meta(readingMeta("none")),
|
|
63058
63486
|
/** Hopper-1 food level (grams) on dual-hopper feeders; null on
|
|
63059
63487
|
* single-hopper models. */
|
|
63060
|
-
food1: number().nullable(),
|
|
63488
|
+
food1: number().nullable().meta(readingMeta("none")),
|
|
63061
63489
|
/** Hopper-2 food level (grams) on dual-hopper feeders; null on
|
|
63062
63490
|
* single-hopper models. */
|
|
63063
|
-
food2: number().nullable(),
|
|
63491
|
+
food2: number().nullable().meta(readingMeta("none")),
|
|
63064
63492
|
/** Derived low-food flag — mirrors the HA `food_level` binary_sensor
|
|
63065
63493
|
* (`device_class: problem`, on = low). True when the bowl is empty /
|
|
63066
63494
|
* below the feeder's low threshold. */
|
|
63067
63495
|
lowFood: boolean(),
|
|
63068
63496
|
/** Battery charge 0..100 (%). Null on mains-powered models or when the
|
|
63069
63497
|
* device has no battery reading. */
|
|
63070
|
-
batteryPower: number().min(0).max(100).nullable(),
|
|
63071
|
-
/**
|
|
63072
|
-
*
|
|
63073
|
-
|
|
63498
|
+
batteryPower: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
63499
|
+
/**
|
|
63500
|
+
* Desiccant life remaining, stored in seconds (duration base, D944).
|
|
63501
|
+
* Providers convert from the days the feeder reports. Null when the
|
|
63502
|
+
* model has no desiccant sensor.
|
|
63503
|
+
*/
|
|
63504
|
+
desiccantLeftDays: number().nullable().meta(readingMeta("duration")),
|
|
63074
63505
|
/** True while a feed is in progress. */
|
|
63075
63506
|
feeding: boolean(),
|
|
63076
63507
|
/** Decoded connectivity / power status (HA petkit device-status enum).
|
|
@@ -63081,7 +63512,7 @@ var PetFeederStatusSchema = object({
|
|
|
63081
63512
|
* with `errorCode` for consumers that want the raw integer. */
|
|
63082
63513
|
error: string().nullable(),
|
|
63083
63514
|
/** Raw device error code (0 / null = no error). */
|
|
63084
|
-
errorCode: number().nullable(),
|
|
63515
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
63085
63516
|
/** True for D4S/D4SH dual-hopper hardware — gates the per-hopper UI. */
|
|
63086
63517
|
isDualHopper: boolean(),
|
|
63087
63518
|
/** Child-lock (manual-lock) setting — buttons on the unit are disabled. */
|
|
@@ -63091,7 +63522,7 @@ var PetFeederStatusSchema = object({
|
|
|
63091
63522
|
/** Play a chime when dispensing. */
|
|
63092
63523
|
feedSound: boolean(),
|
|
63093
63524
|
/** Speaker / prompt volume level (device-scaled integer). */
|
|
63094
|
-
volume: number(),
|
|
63525
|
+
volume: number().meta(readingMeta("none")),
|
|
63095
63526
|
/** Ms epoch when the slice was last refreshed from the cloud. */
|
|
63096
63527
|
lastFetchedAt: number()
|
|
63097
63528
|
});
|
|
@@ -63210,7 +63641,7 @@ var petFeederCapability = {
|
|
|
63210
63641
|
},
|
|
63211
63642
|
desiccantLeftDays: {
|
|
63212
63643
|
kind: "gauge",
|
|
63213
|
-
unit: "
|
|
63644
|
+
unit: "s"
|
|
63214
63645
|
}
|
|
63215
63646
|
} }
|
|
63216
63647
|
};
|
|
@@ -63611,36 +64042,19 @@ method(_void(), PlatformCapabilitiesSchema), method(_void(), HardwareInfoSchema)
|
|
|
63611
64042
|
*/
|
|
63612
64043
|
var PowerMeterStatusSchema = object({
|
|
63613
64044
|
/** Instantaneous power draw in watts. */
|
|
63614
|
-
watts: number().optional().meta({
|
|
63615
|
-
unit: "W",
|
|
63616
|
-
label: "Power"
|
|
63617
|
-
}),
|
|
64045
|
+
watts: number().optional().meta(readingMeta("power", { label: "Power" })),
|
|
63618
64046
|
/** Cumulative energy in kilowatt-hours since the meter was reset. */
|
|
63619
|
-
kwhTotal: number().optional().meta({
|
|
63620
|
-
unit: "kWh",
|
|
63621
|
-
label: "Energy"
|
|
63622
|
-
}),
|
|
64047
|
+
kwhTotal: number().optional().meta(readingMeta("energy", { label: "Energy" })),
|
|
63623
64048
|
/** Voltage in volts. */
|
|
63624
|
-
volts: number().optional(),
|
|
64049
|
+
volts: number().optional().meta(readingMeta("voltage")),
|
|
63625
64050
|
/** Current in amperes. */
|
|
63626
|
-
amps: number().optional(),
|
|
63627
|
-
/** Apparent power in volt-amperes
|
|
63628
|
-
va: number().optional(),
|
|
64051
|
+
amps: number().optional().meta(readingMeta("current")),
|
|
64052
|
+
/** Apparent power in volt-amperes. */
|
|
64053
|
+
va: number().optional().meta(readingMeta("apparent-power")),
|
|
63629
64054
|
/** Power factor (0..1) if reported. */
|
|
63630
|
-
powerFactor: number().min(0).max(1).optional(),
|
|
64055
|
+
powerFactor: number().min(0).max(1).optional().meta(readingMeta("ratio")),
|
|
63631
64056
|
/** Ms epoch when the slice was last updated. */
|
|
63632
|
-
lastFetchedAt: number()
|
|
63633
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
63634
|
-
* `attributes.unit_of_measurement` → 'V' / 'A' / 'W' / 'kW' / 'kWh').
|
|
63635
|
-
* Each upstream `sensor.*` entity surfaces ONE device_class, so one
|
|
63636
|
-
* unit per slice is unambiguous. The UI prefers this over the role's
|
|
63637
|
-
* canonical unit so a 'kW' / 'Wh' feed renders verbatim. */
|
|
63638
|
-
unit: string().optional(),
|
|
63639
|
-
/** Suggested decimal places for numeric display.
|
|
63640
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
63641
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
63642
|
-
* auto-formatting when absent. */
|
|
63643
|
-
precision: number().int().min(0).max(10).optional()
|
|
64057
|
+
lastFetchedAt: number()
|
|
63644
64058
|
});
|
|
63645
64059
|
var powerMeterCapability = {
|
|
63646
64060
|
name: "power-meter",
|
|
@@ -63704,12 +64118,7 @@ var powerMeterCapability = {
|
|
|
63704
64118
|
} },
|
|
63705
64119
|
/** Clock fields: written, but excluded from the compare that decides
|
|
63706
64120
|
* whether persisting is worth a SQLite commit. */
|
|
63707
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
63708
|
-
customize: {
|
|
63709
|
-
version: 1,
|
|
63710
|
-
advanced: "derive",
|
|
63711
|
-
targets: []
|
|
63712
|
-
}
|
|
64121
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
63713
64122
|
};
|
|
63714
64123
|
/**
|
|
63715
64124
|
* Presence cap. Models HA `person.*` and `device_tracker.*` entities
|
|
@@ -63729,11 +64138,11 @@ var powerMeterCapability = {
|
|
|
63729
64138
|
*/
|
|
63730
64139
|
var GpsLocationSchema = object({
|
|
63731
64140
|
/** Latitude in decimal degrees, -90..90. */
|
|
63732
|
-
latitude: number().min(-90).max(90),
|
|
64141
|
+
latitude: number().min(-90).max(90).meta(readingMeta("angle")),
|
|
63733
64142
|
/** Longitude in decimal degrees, -180..180. */
|
|
63734
|
-
longitude: number().min(-180).max(180),
|
|
64143
|
+
longitude: number().min(-180).max(180).meta(readingMeta("angle")),
|
|
63735
64144
|
/** Reported accuracy in meters (lower = better). */
|
|
63736
|
-
accuracyMeters: number().nonnegative()
|
|
64145
|
+
accuracyMeters: number().nonnegative().meta(readingMeta("length"))
|
|
63737
64146
|
});
|
|
63738
64147
|
var PresenceStatusSchema = object({
|
|
63739
64148
|
/** `home` / `not_home` / any user-defined zone name. */
|
|
@@ -63745,7 +64154,7 @@ var PresenceStatusSchema = object({
|
|
|
63745
64154
|
gps: GpsLocationSchema.nullable(),
|
|
63746
64155
|
/** Optional battery level of the tracking device (0..100). Null
|
|
63747
64156
|
* when not reported. */
|
|
63748
|
-
batteryPercent: number().min(0).max(100).nullable(),
|
|
64157
|
+
batteryPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
63749
64158
|
/** Ms epoch when the slice was last updated. */
|
|
63750
64159
|
lastChangedAt: number()
|
|
63751
64160
|
});
|
|
@@ -63795,19 +64204,10 @@ var presenceCapability = {
|
|
|
63795
64204
|
* `sourceInfo`.
|
|
63796
64205
|
*/
|
|
63797
64206
|
var PressureSensorStatusSchema = object({
|
|
63798
|
-
/** Current pressure in hPa. */
|
|
63799
|
-
hpa: number(),
|
|
64207
|
+
/** Current pressure in hPa. `null` when the sample was refused (D393). */
|
|
64208
|
+
hpa: number().nullable().meta(readingMeta("pressure", { precision: 0 })),
|
|
63800
64209
|
/** Ms epoch when the slice was last updated. */
|
|
63801
|
-
lastFetchedAt: number()
|
|
63802
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
63803
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
63804
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
63805
|
-
unit: string().optional(),
|
|
63806
|
-
/** Suggested decimal places for numeric display.
|
|
63807
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
63808
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
63809
|
-
* auto-formatting when absent. */
|
|
63810
|
-
precision: number().int().min(0).max(10).optional()
|
|
64210
|
+
lastFetchedAt: number()
|
|
63811
64211
|
});
|
|
63812
64212
|
var pressureSensorCapability = {
|
|
63813
64213
|
name: "pressure-sensor",
|
|
@@ -64221,8 +64621,8 @@ DeviceType.Camera, method(PtzMoveCommandSchema.extend({ deviceId: number() }), _
|
|
|
64221
64621
|
}), _void(), { kind: "mutation" });
|
|
64222
64622
|
var PtzAutotrackSettingsSchema = object({
|
|
64223
64623
|
targetType: string().describe("Vendor target string (people/vehicle/pet); empty = camera default"),
|
|
64224
|
-
stopDelaySeconds: number().int().min(0).max(300),
|
|
64225
|
-
disappearDelaySeconds: number().int().min(0).max(300)
|
|
64624
|
+
stopDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration")),
|
|
64625
|
+
disappearDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration"))
|
|
64226
64626
|
});
|
|
64227
64627
|
/**
|
|
64228
64628
|
* One option the camera advertises as a valid `targetType`. Drivers
|
|
@@ -64376,7 +64776,7 @@ var RunningStateStatusSchema = object({
|
|
|
64376
64776
|
/** null = unknown — never coerced to false (D393). */
|
|
64377
64777
|
running: boolean().nullable(),
|
|
64378
64778
|
/** Epoch ms the current boolean began; null while `running` is null. */
|
|
64379
|
-
since: number().nullable(),
|
|
64779
|
+
since: number().nullable().meta(readingMeta("none")),
|
|
64380
64780
|
source: RunningStateSourceSchema.meta({ label: "Source" }),
|
|
64381
64781
|
phase: string().nullable(),
|
|
64382
64782
|
/** null until a reading has been published (D393). */
|
|
@@ -64391,7 +64791,6 @@ var RUNNING_DEVICE_TYPES = Object.values(DeviceType);
|
|
|
64391
64791
|
/** Generic Customize target for the running boolean (D936). */
|
|
64392
64792
|
var runningCustomize = {
|
|
64393
64793
|
version: 1,
|
|
64394
|
-
advanced: "derive",
|
|
64395
64794
|
targets: [{
|
|
64396
64795
|
id: "running",
|
|
64397
64796
|
cardinality: "scalar",
|
|
@@ -64411,7 +64810,7 @@ var runningCustomize = {
|
|
|
64411
64810
|
DeviceType.Thermostat,
|
|
64412
64811
|
DeviceType.PetFeeder
|
|
64413
64812
|
],
|
|
64414
|
-
apply: "add
|
|
64813
|
+
apply: "add",
|
|
64415
64814
|
path: "running",
|
|
64416
64815
|
sources: [
|
|
64417
64816
|
{
|
|
@@ -65675,9 +66074,9 @@ var RecordTriggerSchema = _enum([
|
|
|
65675
66074
|
*/
|
|
65676
66075
|
var RecordWindowSchema = object({
|
|
65677
66076
|
trigger: RecordTriggerSchema,
|
|
65678
|
-
day: number().int().min(0).max(6),
|
|
65679
|
-
startMinute: number().int().min(0).max(1439),
|
|
65680
|
-
endMinute: number().int().min(1).max(1440)
|
|
66077
|
+
day: number().int().min(0).max(6).meta(readingMeta("none")),
|
|
66078
|
+
startMinute: number().int().min(0).max(1439).meta(readingMeta("none")),
|
|
66079
|
+
endMinute: number().int().min(1).max(1440).meta(readingMeta("none"))
|
|
65681
66080
|
});
|
|
65682
66081
|
/** Status of one physical volume, as the camera itself describes it. */
|
|
65683
66082
|
var OnboardStorageVolumeSchema = object({
|
|
@@ -65753,10 +66152,10 @@ var RecordingOnboardStatusSchema = object({
|
|
|
65753
66152
|
/** Master "record to the card at all" switch. */
|
|
65754
66153
|
enabled: boolean().nullable(),
|
|
65755
66154
|
overwriteWhenFull: boolean().nullable(),
|
|
65756
|
-
preRecordSec: number().nullable(),
|
|
65757
|
-
postRecordSec: number().nullable(),
|
|
66155
|
+
preRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
66156
|
+
postRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
65758
66157
|
/** Length of one recorded file, in minutes. */
|
|
65759
|
-
segmentMinutes: number().nullable(),
|
|
66158
|
+
segmentMinutes: number().nullable().meta(readingMeta("none")),
|
|
65760
66159
|
/** The primary track's weekly windows, flattened. */
|
|
65761
66160
|
windows: array(RecordWindowSchema),
|
|
65762
66161
|
/**
|
|
@@ -65772,7 +66171,7 @@ var RecordingOnboardStatusSchema = object({
|
|
|
65772
66171
|
* provider reporting a non-zero count also reports the schedule as not
|
|
65773
66172
|
* writable.
|
|
65774
66173
|
*/
|
|
65775
|
-
unreadableWindows: number(),
|
|
66174
|
+
unreadableWindows: number().meta(readingMeta("count")),
|
|
65776
66175
|
/**
|
|
65777
66176
|
* The camera is scheduled to record and has NO usable storage.
|
|
65778
66177
|
*
|
|
@@ -66617,7 +67016,7 @@ var CamStreamDescriptorSchema = object({
|
|
|
66617
67016
|
url: string().optional(),
|
|
66618
67017
|
codec: string().optional(),
|
|
66619
67018
|
resolution: CamStreamResolutionSchema.optional(),
|
|
66620
|
-
fps: number().positive().optional(),
|
|
67019
|
+
fps: number().positive().optional().meta(readingMeta("rate")),
|
|
66621
67020
|
label: string().optional(),
|
|
66622
67021
|
/** Device-level features (e.g. `battery-operated`) — drives broker policy. */
|
|
66623
67022
|
deviceFeatures: array(string()).optional(),
|
|
@@ -66704,18 +67103,18 @@ var StreamProfileSchema = _enum([
|
|
|
66704
67103
|
]);
|
|
66705
67104
|
/** The current encoding config of one stream profile. */
|
|
66706
67105
|
var StreamProfileConfigSchema = object({
|
|
66707
|
-
width: number(),
|
|
66708
|
-
height: number(),
|
|
67106
|
+
width: number().meta(readingMeta("none")),
|
|
67107
|
+
height: number().meta(readingMeta("none")),
|
|
66709
67108
|
codec: _enum(["h264", "h265"]),
|
|
66710
|
-
framerate: number(),
|
|
66711
|
-
bitrate: number(),
|
|
67109
|
+
framerate: number().meta(readingMeta("rate")),
|
|
67110
|
+
bitrate: number().meta(readingMeta("bitrate")),
|
|
66712
67111
|
bitrateMode: _enum(["vbr", "cbr"]).optional(),
|
|
66713
67112
|
encoderProfile: _enum([
|
|
66714
67113
|
"high",
|
|
66715
67114
|
"main",
|
|
66716
67115
|
"baseline"
|
|
66717
67116
|
]).optional(),
|
|
66718
|
-
gop: number().optional(),
|
|
67117
|
+
gop: number().optional().meta(readingMeta("none")),
|
|
66719
67118
|
/**
|
|
66720
67119
|
* Whether THIS profile currently carries an audio track. READ-ONLY here.
|
|
66721
67120
|
*
|
|
@@ -66936,12 +67335,7 @@ var switchCapability = {
|
|
|
66936
67335
|
label: "On",
|
|
66937
67336
|
kind: "boolean"
|
|
66938
67337
|
}
|
|
66939
|
-
}] }
|
|
66940
|
-
customize: {
|
|
66941
|
-
version: 1,
|
|
66942
|
-
advanced: "derive",
|
|
66943
|
-
targets: []
|
|
66944
|
-
}
|
|
67338
|
+
}] }
|
|
66945
67339
|
};
|
|
66946
67340
|
/** C0 controls, DEL and the C1 range: none of them belongs in a name. */
|
|
66947
67341
|
function hasControlCharacter(value) {
|
|
@@ -67524,35 +67918,21 @@ var tamperCapability = {
|
|
|
67524
67918
|
* entries with `device_class: temperature` and any future native
|
|
67525
67919
|
* thermometer.
|
|
67526
67920
|
*
|
|
67527
|
-
*
|
|
67528
|
-
*
|
|
67529
|
-
* (climate-control's `currentTemp`, energy analytics) can compose
|
|
67530
|
-
* without per-source unit fixups. The canonical display unit (`°C`) is
|
|
67531
|
-
* a descriptor constant in the UI (ROLE_DESCRIPTOR), not stored in
|
|
67532
|
-
* `sourceInfo`.
|
|
67921
|
+
* The number is Celsius (D944). Providers convert on ingest. A failed
|
|
67922
|
+
* conversion is `null`, never a guess. Display unit is a read-time preference.
|
|
67533
67923
|
*
|
|
67534
67924
|
* Status `lastFetchedAt` lets staleness-aware consumers detect a
|
|
67535
67925
|
* frozen feed (provider hung) distinct from a "temperature hasn't
|
|
67536
67926
|
* changed" steady state.
|
|
67537
67927
|
*/
|
|
67538
67928
|
var TemperatureSensorStatusSchema = object({
|
|
67539
|
-
/** Current temperature in Celsius. */
|
|
67540
|
-
celsius: number().meta({
|
|
67541
|
-
|
|
67929
|
+
/** Current temperature in Celsius. `null` when the sample was refused (D393). */
|
|
67930
|
+
celsius: number().nullable().meta(readingMeta("temperature", {
|
|
67931
|
+
precision: 1,
|
|
67542
67932
|
label: "Temperature"
|
|
67543
|
-
}),
|
|
67933
|
+
})),
|
|
67544
67934
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
67545
|
-
lastFetchedAt: number()
|
|
67546
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
67547
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
67548
|
-
* role's canonical unit, so a Fahrenheit feed renders '°F' not '°C'.
|
|
67549
|
-
* Absent → the UI falls back to the role's canonical unit. */
|
|
67550
|
-
unit: string().optional(),
|
|
67551
|
-
/** Suggested decimal places for numeric display.
|
|
67552
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
67553
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
67554
|
-
* auto-formatting when absent. */
|
|
67555
|
-
precision: number().int().min(0).max(10).optional()
|
|
67935
|
+
lastFetchedAt: number()
|
|
67556
67936
|
});
|
|
67557
67937
|
var temperatureSensorCapability = {
|
|
67558
67938
|
name: "temperature-sensor",
|
|
@@ -67583,12 +67963,7 @@ var temperatureSensorCapability = {
|
|
|
67583
67963
|
} } },
|
|
67584
67964
|
/** Clock fields: written, but excluded from the compare that decides
|
|
67585
67965
|
* whether persisting is worth a SQLite commit. */
|
|
67586
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
67587
|
-
customize: {
|
|
67588
|
-
version: 1,
|
|
67589
|
-
advanced: "derive",
|
|
67590
|
-
targets: []
|
|
67591
|
-
}
|
|
67966
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
67592
67967
|
};
|
|
67593
67968
|
/**
|
|
67594
67969
|
* toast — system-scoped singleton capability that streams toast
|
|
@@ -67871,16 +68246,16 @@ var VacuumControlStatusSchema = object({
|
|
|
67871
68246
|
]),
|
|
67872
68247
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
67873
68248
|
* reading. */
|
|
67874
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
68249
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
67875
68250
|
/** Current fan-speed token (provider-verbatim). Null when unknown or
|
|
67876
68251
|
* the vacuum has no speed control. */
|
|
67877
68252
|
fanSpeed: string().nullable(),
|
|
67878
68253
|
/** Speed tokens the hardware accepts — drives the UI selector. */
|
|
67879
68254
|
availableFanSpeeds: array(string()),
|
|
67880
68255
|
/** 0..100 cleaning-completion percentage of the current task, or null. */
|
|
67881
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
68256
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
67882
68257
|
/** Current error code (0 / null = no error). */
|
|
67883
|
-
errorCode: number().nullable(),
|
|
68258
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
67884
68259
|
/** Human label for {@link errorCode}, or null when none / undecodable. */
|
|
67885
68260
|
errorLabel: string().nullable(),
|
|
67886
68261
|
/** Ms epoch when the slice was last updated. */
|
|
@@ -67958,7 +68333,7 @@ var ValveStatusSchema = object({
|
|
|
67958
68333
|
]),
|
|
67959
68334
|
/** 0 = fully closed, 100 = fully open. Null when the device has no
|
|
67960
68335
|
* intermediate position surface. */
|
|
67961
|
-
position: number().min(0).max(100).nullable(),
|
|
68336
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
67962
68337
|
/** Ms epoch when the slice was last updated. */
|
|
67963
68338
|
lastChangedAt: number()
|
|
67964
68339
|
});
|
|
@@ -68066,9 +68441,9 @@ var vibrationCapability = {
|
|
|
68066
68441
|
*/
|
|
68067
68442
|
var WaterHeaterStatusSchema = object({
|
|
68068
68443
|
/** Current measured temperature. Null when not reported. */
|
|
68069
|
-
currentTemp: number().nullable(),
|
|
68444
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
68070
68445
|
/** Target temperature setpoint. Null when no setpoint surface. */
|
|
68071
|
-
targetTemp: number().nullable(),
|
|
68446
|
+
targetTemp: number().nullable().meta(readingMeta("temperature")),
|
|
68072
68447
|
/** Active operation mode = HA `state` (`eco` / `electric` / `gas` /
|
|
68073
68448
|
* `heat_pump` / `high_demand` / `performance` / `off`). Null when the
|
|
68074
68449
|
* device reports an unknown state. */
|
|
@@ -68079,9 +68454,9 @@ var WaterHeaterStatusSchema = object({
|
|
|
68079
68454
|
* has no away surface. */
|
|
68080
68455
|
away: boolean().nullable(),
|
|
68081
68456
|
/** HA `min_temp` attribute. Null when not reported. */
|
|
68082
|
-
minTemp: number().nullable(),
|
|
68457
|
+
minTemp: number().nullable().meta(readingMeta("temperature")),
|
|
68083
68458
|
/** HA `max_temp` attribute. Null when not reported. */
|
|
68084
|
-
maxTemp: number().nullable(),
|
|
68459
|
+
maxTemp: number().nullable().meta(readingMeta("temperature")),
|
|
68085
68460
|
/** Ms epoch when the slice was last updated. */
|
|
68086
68461
|
lastChangedAt: number()
|
|
68087
68462
|
});
|
|
@@ -68166,25 +68541,18 @@ var waterHeaterCapability = {
|
|
|
68166
68541
|
* Forecast deferred — current conditions only for v1.
|
|
68167
68542
|
*/
|
|
68168
68543
|
var WeatherStatusSchema = object({
|
|
68169
|
-
/** Verbatim
|
|
68170
|
-
* when no condition has been reported yet. */
|
|
68544
|
+
/** Verbatim condition state (`sunny`, `cloudy`, `rainy`, …). Null when none yet. */
|
|
68171
68545
|
condition: string().nullable(),
|
|
68172
|
-
/** Current temperature in
|
|
68173
|
-
temperature: number().nullable(),
|
|
68174
|
-
/** Temperature unit string (e.g. `°C` / `°F`). Null when not provided. */
|
|
68175
|
-
temperatureUnit: string().nullable(),
|
|
68546
|
+
/** Current temperature in Celsius. Null when not provided or refused. */
|
|
68547
|
+
temperature: number().nullable().meta(readingMeta("temperature", { precision: 1 })),
|
|
68176
68548
|
/** Relative humidity (0..100). Null when not provided. */
|
|
68177
|
-
humidity: number().min(0).max(100).nullable(),
|
|
68178
|
-
/** Barometric pressure in
|
|
68179
|
-
pressure: number().nullable(),
|
|
68180
|
-
/**
|
|
68181
|
-
|
|
68182
|
-
/** Wind speed in the reported unit. Null when not provided. */
|
|
68183
|
-
windSpeed: number().nullable(),
|
|
68184
|
-
/** Wind-speed unit string (e.g. `km/h` / `mph`). Null when not provided. */
|
|
68185
|
-
windSpeedUnit: string().nullable(),
|
|
68549
|
+
humidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
68550
|
+
/** Barometric pressure in hPa. Null when not provided or refused. */
|
|
68551
|
+
pressure: number().nullable().meta(readingMeta("pressure")),
|
|
68552
|
+
/** Wind speed in metres per second. Null when not provided or refused. */
|
|
68553
|
+
windSpeed: number().nullable().meta(readingMeta("speed")),
|
|
68186
68554
|
/** Wind bearing in degrees (0..360, meteorological). Null when not provided. */
|
|
68187
|
-
windBearing: number().nullable(),
|
|
68555
|
+
windBearing: number().nullable().meta(readingMeta("angle")),
|
|
68188
68556
|
/** Ms epoch when the slice was last updated. */
|
|
68189
68557
|
lastFetchedAt: number()
|
|
68190
68558
|
});
|
|
@@ -68212,12 +68580,12 @@ var weatherCapability = {
|
|
|
68212
68580
|
*/
|
|
68213
68581
|
durability: "session",
|
|
68214
68582
|
/**
|
|
68215
|
-
* History (D850): recorded series.
|
|
68583
|
+
* History (D850): recorded series. Numbers are the quantity base (D944).
|
|
68216
68584
|
*/
|
|
68217
68585
|
history: { fields: {
|
|
68218
68586
|
temperature: {
|
|
68219
68587
|
kind: "gauge",
|
|
68220
|
-
|
|
68588
|
+
unit: "°C",
|
|
68221
68589
|
deadband: .2
|
|
68222
68590
|
},
|
|
68223
68591
|
humidity: {
|
|
@@ -68227,12 +68595,12 @@ var weatherCapability = {
|
|
|
68227
68595
|
},
|
|
68228
68596
|
pressure: {
|
|
68229
68597
|
kind: "gauge",
|
|
68230
|
-
|
|
68598
|
+
unit: "hPa",
|
|
68231
68599
|
deadband: .5
|
|
68232
68600
|
},
|
|
68233
68601
|
windSpeed: {
|
|
68234
68602
|
kind: "gauge",
|
|
68235
|
-
|
|
68603
|
+
unit: "m/s",
|
|
68236
68604
|
deadband: .5
|
|
68237
68605
|
}
|
|
68238
68606
|
} }
|
|
@@ -69463,6 +69831,8 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
69463
69831
|
featureProbe: featureProbeCapability,
|
|
69464
69832
|
flood: floodCapability,
|
|
69465
69833
|
gas: gasCapability,
|
|
69834
|
+
groupCommands: groupCommandsCapability,
|
|
69835
|
+
groupStatus: groupStatusCapability,
|
|
69466
69836
|
heatingValve: heatingValveCapability,
|
|
69467
69837
|
humidifier: humidifierCapability,
|
|
69468
69838
|
humiditySensor: humiditySensorCapability,
|
|
@@ -70839,6 +71209,13 @@ Object.freeze({
|
|
|
70839
71209
|
access: "view",
|
|
70840
71210
|
role: "admin"
|
|
70841
71211
|
},
|
|
71212
|
+
"addons.getPackageDocs": {
|
|
71213
|
+
capName: "addons",
|
|
71214
|
+
capScope: "system",
|
|
71215
|
+
addonId: null,
|
|
71216
|
+
access: "view",
|
|
71217
|
+
role: "admin"
|
|
71218
|
+
},
|
|
70842
71219
|
"addons.getVersions": {
|
|
70843
71220
|
capName: "addons",
|
|
70844
71221
|
capScope: "system",
|
|
@@ -73947,6 +74324,20 @@ Object.freeze({
|
|
|
73947
74324
|
access: "view",
|
|
73948
74325
|
role: "viewer"
|
|
73949
74326
|
},
|
|
74327
|
+
"groupCommands.getStatus": {
|
|
74328
|
+
capName: "group-commands",
|
|
74329
|
+
capScope: "device",
|
|
74330
|
+
addonId: null,
|
|
74331
|
+
access: "view",
|
|
74332
|
+
role: "viewer"
|
|
74333
|
+
},
|
|
74334
|
+
"groupStatus.getStatus": {
|
|
74335
|
+
capName: "group-status",
|
|
74336
|
+
capScope: "device",
|
|
74337
|
+
addonId: null,
|
|
74338
|
+
access: "view",
|
|
74339
|
+
role: "viewer"
|
|
74340
|
+
},
|
|
73950
74341
|
"heatingValve.getStatus": {
|
|
73951
74342
|
capName: "heating-valve",
|
|
73952
74343
|
capScope: "device",
|
|
@@ -83769,6 +84160,37 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83769
84160
|
icon: "flame"
|
|
83770
84161
|
}]
|
|
83771
84162
|
},
|
|
84163
|
+
"group-commands": {
|
|
84164
|
+
scope: "device",
|
|
84165
|
+
noun: t("Group command", "Comando di gruppo")
|
|
84166
|
+
},
|
|
84167
|
+
"group-status": {
|
|
84168
|
+
scope: "device",
|
|
84169
|
+
noun: t("Group", "Gruppo"),
|
|
84170
|
+
state: [
|
|
84171
|
+
{
|
|
84172
|
+
kind: "numeric",
|
|
84173
|
+
field: "included",
|
|
84174
|
+
quantity: t("the members reporting", "i membri che rispondono"),
|
|
84175
|
+
label: t("Reporting", "Rispondono"),
|
|
84176
|
+
icon: "users"
|
|
84177
|
+
},
|
|
84178
|
+
{
|
|
84179
|
+
kind: "numeric",
|
|
84180
|
+
field: "excluded",
|
|
84181
|
+
quantity: t("the members left out", "i membri esclusi"),
|
|
84182
|
+
label: t("Excluded", "Esclusi"),
|
|
84183
|
+
icon: "users"
|
|
84184
|
+
},
|
|
84185
|
+
{
|
|
84186
|
+
kind: "numeric",
|
|
84187
|
+
field: "total",
|
|
84188
|
+
quantity: t("the member count", "il numero di membri"),
|
|
84189
|
+
label: t("Members", "Membri"),
|
|
84190
|
+
icon: "sigma"
|
|
84191
|
+
}
|
|
84192
|
+
]
|
|
84193
|
+
},
|
|
83772
84194
|
"humidity-sensor": {
|
|
83773
84195
|
scope: "device",
|
|
83774
84196
|
noun: t("Humidity", "Umidità"),
|
|
@@ -83802,7 +84224,6 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83802
84224
|
field: "value",
|
|
83803
84225
|
quantity: t("the reading", "il valore"),
|
|
83804
84226
|
label: t("Reading", "Valore"),
|
|
83805
|
-
unitField: "unit",
|
|
83806
84227
|
icon: "gauge"
|
|
83807
84228
|
}]
|
|
83808
84229
|
},
|
|
@@ -83938,7 +84359,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83938
84359
|
field: "temperature",
|
|
83939
84360
|
quantity: t("the outdoor temperature", "la temperatura esterna"),
|
|
83940
84361
|
label: t("Temperature", "Temperatura"),
|
|
83941
|
-
|
|
84362
|
+
unit: "°C",
|
|
83942
84363
|
icon: "thermometer"
|
|
83943
84364
|
},
|
|
83944
84365
|
{
|
|
@@ -83954,7 +84375,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83954
84375
|
field: "windSpeed",
|
|
83955
84376
|
quantity: t("the wind speed", "la velocità del vento"),
|
|
83956
84377
|
label: t("Wind", "Vento"),
|
|
83957
|
-
|
|
84378
|
+
unit: "m/s",
|
|
83958
84379
|
icon: "wind"
|
|
83959
84380
|
},
|
|
83960
84381
|
{
|
|
@@ -83962,7 +84383,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83962
84383
|
field: "pressure",
|
|
83963
84384
|
quantity: t("the air pressure", "la pressione atmosferica"),
|
|
83964
84385
|
label: t("Pressure", "Pressione"),
|
|
83965
|
-
|
|
84386
|
+
unit: "hPa",
|
|
83966
84387
|
icon: "gauge"
|
|
83967
84388
|
}
|
|
83968
84389
|
]
|
|
@@ -85301,6 +85722,16 @@ Object.freeze({
|
|
|
85301
85722
|
form: "single",
|
|
85302
85723
|
optional: false
|
|
85303
85724
|
}],
|
|
85725
|
+
"groupCommands.getStatus": [{
|
|
85726
|
+
name: "deviceId",
|
|
85727
|
+
form: "single",
|
|
85728
|
+
optional: false
|
|
85729
|
+
}],
|
|
85730
|
+
"groupStatus.getStatus": [{
|
|
85731
|
+
name: "deviceId",
|
|
85732
|
+
form: "single",
|
|
85733
|
+
optional: false
|
|
85734
|
+
}],
|
|
85304
85735
|
"heatingValve.getStatus": [{
|
|
85305
85736
|
name: "deviceId",
|
|
85306
85737
|
form: "single",
|
|
@@ -87285,6 +87716,8 @@ new Map(Object.entries({
|
|
|
87285
87716
|
"detection-blind": "device-events",
|
|
87286
87717
|
"motion-noisy": "device-events",
|
|
87287
87718
|
"motion-calm": "device-events",
|
|
87719
|
+
"package-llm-silent": "device-events",
|
|
87720
|
+
"package-llm-answered": "device-events",
|
|
87288
87721
|
"recording-stalled": "device-events",
|
|
87289
87722
|
"recording-healthy": "device-events",
|
|
87290
87723
|
"recording-degraded": "device-events",
|
|
@@ -87368,6 +87801,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
|
|
|
87368
87801
|
label: "Motion without a subject",
|
|
87369
87802
|
kinds: ["motion-noisy", "motion-calm"]
|
|
87370
87803
|
},
|
|
87804
|
+
{
|
|
87805
|
+
id: "package-llm",
|
|
87806
|
+
family: "device-events",
|
|
87807
|
+
label: "Package confirm",
|
|
87808
|
+
kinds: ["package-llm-silent", "package-llm-answered"]
|
|
87809
|
+
},
|
|
87371
87810
|
{
|
|
87372
87811
|
id: "recording",
|
|
87373
87812
|
family: "device-events",
|
|
@@ -87549,6 +87988,8 @@ var DEVICE_EVENTS = [
|
|
|
87549
87988
|
"detection-blind",
|
|
87550
87989
|
"motion-noisy",
|
|
87551
87990
|
"motion-calm",
|
|
87991
|
+
"package-llm-silent",
|
|
87992
|
+
"package-llm-answered",
|
|
87552
87993
|
"recording-stalled",
|
|
87553
87994
|
"recording-healthy",
|
|
87554
87995
|
"recording-degraded",
|
|
@@ -87817,6 +88258,15 @@ new Map([
|
|
|
87817
88258
|
snapshotLabel: "Cameras with constant motion now",
|
|
87818
88259
|
snapshotSection: null
|
|
87819
88260
|
},
|
|
88261
|
+
{
|
|
88262
|
+
id: "package-llm-confirm",
|
|
88263
|
+
family: "device-events",
|
|
88264
|
+
label: "Package confirm (not answering / answering again)",
|
|
88265
|
+
bad: ["package-llm-silent"],
|
|
88266
|
+
recovery: ["package-llm-answered"],
|
|
88267
|
+
snapshotLabel: "Cameras whose package confirm is not answering",
|
|
88268
|
+
snapshotSection: null
|
|
88269
|
+
},
|
|
87820
88270
|
{
|
|
87821
88271
|
id: "recording-health",
|
|
87822
88272
|
family: "device-events",
|