@camstack/addon-provider-unraid 0.2.147 → 0.2.149
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +18 -0
- package/dist/addon.js +981 -544
- package/dist/addon.mjs +981 -544
- package/package.json +4 -2
package/dist/addon.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
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"
|
|
@@ -10803,7 +10824,7 @@ function errMsg(err) {
|
|
|
10803
10824
|
return String(err);
|
|
10804
10825
|
}
|
|
10805
10826
|
//#endregion
|
|
10806
|
-
//#region ../types/dist/composition-
|
|
10827
|
+
//#region ../types/dist/composition-OhpuespA.mjs
|
|
10807
10828
|
/**
|
|
10808
10829
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
10809
10830
|
*
|
|
@@ -11558,15 +11579,74 @@ function validateExpressionSource(src) {
|
|
|
11558
11579
|
}
|
|
11559
11580
|
return null;
|
|
11560
11581
|
}
|
|
11561
|
-
/**
|
|
11562
|
-
|
|
11563
|
-
|
|
11564
|
-
|
|
11582
|
+
/**
|
|
11583
|
+
* A composition source identity: `(addonId, stableId)`, never a numeric device
|
|
11584
|
+
* id. Split out so helper schemas can name it without a cycle through
|
|
11585
|
+
* `composition.ts` (D659).
|
|
11586
|
+
*/
|
|
11565
11587
|
var CompositionSourceRefSchema = object({
|
|
11566
11588
|
/** The owning addon; `stableId` is unique only within it. */
|
|
11567
11589
|
addonId: string().min(1),
|
|
11568
11590
|
stableId: string().min(1)
|
|
11569
11591
|
});
|
|
11592
|
+
var GROUP_TEMPLATE_IDS = [
|
|
11593
|
+
"temperature",
|
|
11594
|
+
"humidity",
|
|
11595
|
+
"pressure",
|
|
11596
|
+
"illuminance",
|
|
11597
|
+
"power",
|
|
11598
|
+
"energy",
|
|
11599
|
+
"battery",
|
|
11600
|
+
"numeric",
|
|
11601
|
+
"motion",
|
|
11602
|
+
"contact",
|
|
11603
|
+
"leak",
|
|
11604
|
+
"smoke",
|
|
11605
|
+
"occupancy",
|
|
11606
|
+
"binary",
|
|
11607
|
+
"switch",
|
|
11608
|
+
"light"
|
|
11609
|
+
];
|
|
11610
|
+
var NUMERIC_AGGREGATES = [
|
|
11611
|
+
"mean",
|
|
11612
|
+
"median",
|
|
11613
|
+
"min",
|
|
11614
|
+
"max",
|
|
11615
|
+
"sum"
|
|
11616
|
+
];
|
|
11617
|
+
var BINARY_AGGREGATES = ["any", "all"];
|
|
11618
|
+
/** How an actuator group decides it is on. Unknown members never count as off. */
|
|
11619
|
+
var ACTIVE_CRITERIA = ["at-least-one", "all"];
|
|
11620
|
+
var AGGREGATE_REDUCERS = [
|
|
11621
|
+
"mean",
|
|
11622
|
+
"median",
|
|
11623
|
+
"min",
|
|
11624
|
+
"max",
|
|
11625
|
+
"sum",
|
|
11626
|
+
"any",
|
|
11627
|
+
"all"
|
|
11628
|
+
];
|
|
11629
|
+
var GroupTemplateIdSchema = _enum(GROUP_TEMPLATE_IDS);
|
|
11630
|
+
var AggregateReducerSchema = _enum(AGGREGATE_REDUCERS);
|
|
11631
|
+
var ActiveCriterionSchema = _enum(ACTIVE_CRITERIA);
|
|
11632
|
+
/** One member. The field is stored so occupancy can name motion or binary. */
|
|
11633
|
+
var HelperMemberSchema = object({
|
|
11634
|
+
source: CompositionSourceRefSchema,
|
|
11635
|
+
cap: string().min(1),
|
|
11636
|
+
fieldPath: string().min(1)
|
|
11637
|
+
});
|
|
11638
|
+
var HelperSpecSchema = discriminatedUnion("kind", [object({
|
|
11639
|
+
kind: literal("group"),
|
|
11640
|
+
templateId: GroupTemplateIdSchema,
|
|
11641
|
+
aggregate: AggregateReducerSchema,
|
|
11642
|
+
members: array(HelperMemberSchema).min(1).max(64),
|
|
11643
|
+
/** Actuator groups only. Readings leave this unset. */
|
|
11644
|
+
active: ActiveCriterionSchema.optional()
|
|
11645
|
+
})]);
|
|
11646
|
+
/** A composed device's stableId is this prefix plus the block id. */
|
|
11647
|
+
var COMPOSED_DEVICE_STABLE_ID_PREFIX = "composed-";
|
|
11648
|
+
/** Longest snippet a `code` source may carry (slice 4). */
|
|
11649
|
+
var MAX_COMPOSITION_CODE_LENGTH = 2e4;
|
|
11570
11650
|
/** One field of one capability of one source device. */
|
|
11571
11651
|
var CompositionFieldReadSchema = object({
|
|
11572
11652
|
source: CompositionSourceRefSchema,
|
|
@@ -11610,7 +11690,33 @@ var CompositionCodeSourceSchema = object({
|
|
|
11610
11690
|
var CompositionFieldSourceSchema = discriminatedUnion("kind", [
|
|
11611
11691
|
CompositionFromSourceSchema,
|
|
11612
11692
|
CompositionExpressionSourceSchema,
|
|
11613
|
-
CompositionCodeSourceSchema
|
|
11693
|
+
CompositionCodeSourceSchema,
|
|
11694
|
+
object({
|
|
11695
|
+
kind: literal("aggregate"),
|
|
11696
|
+
reducer: _enum([
|
|
11697
|
+
"mean",
|
|
11698
|
+
"median",
|
|
11699
|
+
"min",
|
|
11700
|
+
"max",
|
|
11701
|
+
"sum",
|
|
11702
|
+
"any",
|
|
11703
|
+
"all"
|
|
11704
|
+
]),
|
|
11705
|
+
reads: array(CompositionFieldReadSchema).min(1).max(64),
|
|
11706
|
+
/** `value` is the reading; the others are the member counts. */
|
|
11707
|
+
publish: _enum([
|
|
11708
|
+
"value",
|
|
11709
|
+
"included",
|
|
11710
|
+
"excluded",
|
|
11711
|
+
"total"
|
|
11712
|
+
]),
|
|
11713
|
+
/** What a `value` publish does when nobody is included. Counts ignore this. */
|
|
11714
|
+
empty: _enum([
|
|
11715
|
+
"null",
|
|
11716
|
+
"omit",
|
|
11717
|
+
"offline"
|
|
11718
|
+
])
|
|
11719
|
+
})
|
|
11614
11720
|
]);
|
|
11615
11721
|
var CompositionCommandTargetSchema = discriminatedUnion("kind", [object({
|
|
11616
11722
|
kind: literal("forward"),
|
|
@@ -11656,7 +11762,13 @@ var CompositionSchema = object({
|
|
|
11656
11762
|
kind: literal("existing"),
|
|
11657
11763
|
device: CompositionSourceRefSchema
|
|
11658
11764
|
})]),
|
|
11659
|
-
features: array(CompositionFeatureSchema).min(1).max(16)
|
|
11765
|
+
features: array(CompositionFeatureSchema).min(1).max(16),
|
|
11766
|
+
/**
|
|
11767
|
+
* Present when the block is a helper template. Absent on a free
|
|
11768
|
+
* composition (the room example, device 4603). The editor reads this,
|
|
11769
|
+
* never the compiled features.
|
|
11770
|
+
*/
|
|
11771
|
+
helper: HelperSpecSchema.optional()
|
|
11660
11772
|
}).superRefine((composition, ctx) => {
|
|
11661
11773
|
const seen = /* @__PURE__ */ new Set();
|
|
11662
11774
|
composition.features.forEach((feature, index) => {
|
|
@@ -17864,7 +17976,11 @@ var CompositionProblemSchema = object({
|
|
|
17864
17976
|
"item-field-reserved",
|
|
17865
17977
|
"target-missing",
|
|
17866
17978
|
"target-unreadable",
|
|
17867
|
-
"not-replaceable"
|
|
17979
|
+
"not-replaceable",
|
|
17980
|
+
"native-capability-replace",
|
|
17981
|
+
"mixed-quantity",
|
|
17982
|
+
"helper-mismatch",
|
|
17983
|
+
"member-constraint"
|
|
17868
17984
|
]),
|
|
17869
17985
|
path: string(),
|
|
17870
17986
|
message: string()
|
|
@@ -17885,7 +18001,8 @@ var CompositionUnavailableModeSchema = _enum([
|
|
|
17885
18001
|
"null",
|
|
17886
18002
|
"offline",
|
|
17887
18003
|
"unknown",
|
|
17888
|
-
"release"
|
|
18004
|
+
"release",
|
|
18005
|
+
"omit"
|
|
17889
18006
|
]);
|
|
17890
18007
|
/**
|
|
17891
18008
|
* `derived` reads a source · `clock` reads only `now`, recomputed when a sibling
|
|
@@ -17922,9 +18039,11 @@ var CompositionFieldPlanSchema = object({
|
|
|
17922
18039
|
reads: array(CompositionFieldReadSchema)
|
|
17923
18040
|
});
|
|
17924
18041
|
/**
|
|
17925
|
-
* What a feature does to its target (D663): `new` builds a capability on a
|
|
17926
|
-
* device; on an existing device it `add`s a capability the device lacks
|
|
17927
|
-
*
|
|
18042
|
+
* What a feature does to its target (D663, D944): `new` builds a capability on a
|
|
18043
|
+
* new device; on an existing device it `add`s a capability the device lacks.
|
|
18044
|
+
* Replacing a capability the device already serves is refused
|
|
18045
|
+
* (`native-capability-replace`), not planned. `replace` remains on the claim
|
|
18046
|
+
* wire for a claim the hub already holds.
|
|
17928
18047
|
*/
|
|
17929
18048
|
var CompositionFeatureModeSchema = _enum([
|
|
17930
18049
|
"new",
|
|
@@ -18097,6 +18216,275 @@ Object.freeze({
|
|
|
18097
18216
|
result: ["number", "null"]
|
|
18098
18217
|
}
|
|
18099
18218
|
});
|
|
18219
|
+
/**
|
|
18220
|
+
* One catalog row per base reading a group helper can build (D944 §3).
|
|
18221
|
+
* Data, not a form default written into the block.
|
|
18222
|
+
*/
|
|
18223
|
+
var NOW = {
|
|
18224
|
+
fieldPath: "lastFetchedAt",
|
|
18225
|
+
expr: "now"
|
|
18226
|
+
};
|
|
18227
|
+
var CHANGED = {
|
|
18228
|
+
fieldPath: "lastChangedAt",
|
|
18229
|
+
expr: "now"
|
|
18230
|
+
};
|
|
18231
|
+
function numeric(input) {
|
|
18232
|
+
return {
|
|
18233
|
+
...input,
|
|
18234
|
+
family: "numeric",
|
|
18235
|
+
deviceType: DeviceType.Sensor,
|
|
18236
|
+
memberDeviceType: DeviceType.Sensor,
|
|
18237
|
+
commandCaps: [],
|
|
18238
|
+
baseUnit: baseUnitOf(input.quantity),
|
|
18239
|
+
aggregates: NUMERIC_AGGREGATES,
|
|
18240
|
+
accept: [{
|
|
18241
|
+
cap: input.outputCap,
|
|
18242
|
+
fieldPath: input.outputField
|
|
18243
|
+
}]
|
|
18244
|
+
};
|
|
18245
|
+
}
|
|
18246
|
+
function binary(input) {
|
|
18247
|
+
return {
|
|
18248
|
+
...input,
|
|
18249
|
+
family: "binary",
|
|
18250
|
+
deviceType: DeviceType.Sensor,
|
|
18251
|
+
memberDeviceType: DeviceType.Sensor,
|
|
18252
|
+
commandCaps: [],
|
|
18253
|
+
quantity: "none",
|
|
18254
|
+
baseUnit: void 0,
|
|
18255
|
+
aggregates: BINARY_AGGREGATES,
|
|
18256
|
+
empty: "offline"
|
|
18257
|
+
};
|
|
18258
|
+
}
|
|
18259
|
+
var GROUP_TEMPLATES = [
|
|
18260
|
+
numeric({
|
|
18261
|
+
id: "temperature",
|
|
18262
|
+
summary: "Mean, median, min, max or sum of temperatures. Offline and unknown members are left out, never read as 0 °C.",
|
|
18263
|
+
role: DeviceRole.TemperatureSensor,
|
|
18264
|
+
outputCap: "temperature-sensor",
|
|
18265
|
+
outputField: "celsius",
|
|
18266
|
+
quantity: "temperature",
|
|
18267
|
+
defaultAggregate: "mean",
|
|
18268
|
+
empty: "null",
|
|
18269
|
+
companions: [NOW]
|
|
18270
|
+
}),
|
|
18271
|
+
numeric({
|
|
18272
|
+
id: "humidity",
|
|
18273
|
+
summary: "Humidity in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
18274
|
+
role: DeviceRole.HumiditySensor,
|
|
18275
|
+
outputCap: "humidity-sensor",
|
|
18276
|
+
outputField: "percent",
|
|
18277
|
+
quantity: "humidity",
|
|
18278
|
+
defaultAggregate: "mean",
|
|
18279
|
+
empty: "null",
|
|
18280
|
+
companions: [NOW]
|
|
18281
|
+
}),
|
|
18282
|
+
numeric({
|
|
18283
|
+
id: "pressure",
|
|
18284
|
+
summary: "Pressure in hectopascals. Offline and unknown members are left out, never read as 0 hPa.",
|
|
18285
|
+
role: DeviceRole.PressureSensor,
|
|
18286
|
+
outputCap: "pressure-sensor",
|
|
18287
|
+
outputField: "hpa",
|
|
18288
|
+
quantity: "pressure",
|
|
18289
|
+
defaultAggregate: "mean",
|
|
18290
|
+
empty: "null",
|
|
18291
|
+
companions: [NOW]
|
|
18292
|
+
}),
|
|
18293
|
+
numeric({
|
|
18294
|
+
id: "illuminance",
|
|
18295
|
+
summary: "Illuminance in lux. Offline and unknown members are left out, never read as 0 lx.",
|
|
18296
|
+
role: DeviceRole.AmbientLightSensor,
|
|
18297
|
+
outputCap: "ambient-light-sensor",
|
|
18298
|
+
outputField: "lux",
|
|
18299
|
+
quantity: "illuminance",
|
|
18300
|
+
defaultAggregate: "mean",
|
|
18301
|
+
empty: "null",
|
|
18302
|
+
companions: [NOW]
|
|
18303
|
+
}),
|
|
18304
|
+
numeric({
|
|
18305
|
+
id: "power",
|
|
18306
|
+
summary: "Power in watts, summed by default. Nobody reporting omits the key rather than writing 0 W.",
|
|
18307
|
+
role: DeviceRole.PowerSensor,
|
|
18308
|
+
outputCap: "power-meter",
|
|
18309
|
+
outputField: "watts",
|
|
18310
|
+
quantity: "power",
|
|
18311
|
+
defaultAggregate: "sum",
|
|
18312
|
+
empty: "omit",
|
|
18313
|
+
companions: [NOW]
|
|
18314
|
+
}),
|
|
18315
|
+
numeric({
|
|
18316
|
+
id: "energy",
|
|
18317
|
+
summary: "Energy in kilowatt-hours, summed by default. Nobody reporting omits the key rather than writing 0 kWh.",
|
|
18318
|
+
role: DeviceRole.EnergySensor,
|
|
18319
|
+
outputCap: "power-meter",
|
|
18320
|
+
outputField: "kwhTotal",
|
|
18321
|
+
quantity: "energy",
|
|
18322
|
+
defaultAggregate: "sum",
|
|
18323
|
+
empty: "omit",
|
|
18324
|
+
companions: [NOW]
|
|
18325
|
+
}),
|
|
18326
|
+
numeric({
|
|
18327
|
+
id: "battery",
|
|
18328
|
+
summary: "Battery charge in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
18329
|
+
role: DeviceRole.BatterySensor,
|
|
18330
|
+
outputCap: "battery",
|
|
18331
|
+
outputField: "percentage",
|
|
18332
|
+
quantity: "percentage",
|
|
18333
|
+
defaultAggregate: "mean",
|
|
18334
|
+
empty: "null",
|
|
18335
|
+
companions: [
|
|
18336
|
+
{
|
|
18337
|
+
fieldPath: "charging",
|
|
18338
|
+
expr: "\"unknown\""
|
|
18339
|
+
},
|
|
18340
|
+
{
|
|
18341
|
+
fieldPath: "sleeping",
|
|
18342
|
+
expr: "false"
|
|
18343
|
+
},
|
|
18344
|
+
{
|
|
18345
|
+
fieldPath: "lastUpdated",
|
|
18346
|
+
expr: "now"
|
|
18347
|
+
}
|
|
18348
|
+
]
|
|
18349
|
+
}),
|
|
18350
|
+
numeric({
|
|
18351
|
+
id: "numeric",
|
|
18352
|
+
summary: "A numeric reading in the members’ shared quantity. Mixed quantities are refused. Nobody reporting publishes null, not 0.",
|
|
18353
|
+
role: DeviceRole.NumericSensor,
|
|
18354
|
+
outputCap: "numeric-sensor",
|
|
18355
|
+
outputField: "value",
|
|
18356
|
+
quantity: "device",
|
|
18357
|
+
defaultAggregate: "mean",
|
|
18358
|
+
empty: "null",
|
|
18359
|
+
companions: [NOW]
|
|
18360
|
+
}),
|
|
18361
|
+
binary({
|
|
18362
|
+
id: "motion",
|
|
18363
|
+
summary: "Any or all motion. Offline and unknown members are left out, never read as off. Nobody reporting takes the device offline.",
|
|
18364
|
+
role: DeviceRole.MotionSensor,
|
|
18365
|
+
outputCap: "motion",
|
|
18366
|
+
outputField: "detected",
|
|
18367
|
+
defaultAggregate: "any",
|
|
18368
|
+
accept: [{
|
|
18369
|
+
cap: "motion",
|
|
18370
|
+
fieldPath: "detected"
|
|
18371
|
+
}],
|
|
18372
|
+
companions: [{
|
|
18373
|
+
fieldPath: "lastDetectedAt",
|
|
18374
|
+
expr: "null"
|
|
18375
|
+
}, {
|
|
18376
|
+
fieldPath: "autoClearAfterMs",
|
|
18377
|
+
expr: "null"
|
|
18378
|
+
}]
|
|
18379
|
+
}),
|
|
18380
|
+
binary({
|
|
18381
|
+
id: "contact",
|
|
18382
|
+
summary: "Any or all open contacts. Offline and unknown members are left out, never read as closed.",
|
|
18383
|
+
role: DeviceRole.ContactSensor,
|
|
18384
|
+
outputCap: "contact",
|
|
18385
|
+
outputField: "entryOpen",
|
|
18386
|
+
defaultAggregate: "any",
|
|
18387
|
+
accept: [{
|
|
18388
|
+
cap: "contact",
|
|
18389
|
+
fieldPath: "entryOpen"
|
|
18390
|
+
}],
|
|
18391
|
+
companions: [CHANGED]
|
|
18392
|
+
}),
|
|
18393
|
+
binary({
|
|
18394
|
+
id: "leak",
|
|
18395
|
+
summary: "Any or all leak detections. Offline and unknown members are left out, never read as dry.",
|
|
18396
|
+
role: DeviceRole.LeakSensor,
|
|
18397
|
+
outputCap: "flood",
|
|
18398
|
+
outputField: "flooded",
|
|
18399
|
+
defaultAggregate: "any",
|
|
18400
|
+
accept: [{
|
|
18401
|
+
cap: "flood",
|
|
18402
|
+
fieldPath: "flooded"
|
|
18403
|
+
}],
|
|
18404
|
+
companions: [CHANGED]
|
|
18405
|
+
}),
|
|
18406
|
+
binary({
|
|
18407
|
+
id: "smoke",
|
|
18408
|
+
summary: "Any or all smoke detections. Offline and unknown members are left out, never read as clear.",
|
|
18409
|
+
role: DeviceRole.SmokeSensor,
|
|
18410
|
+
outputCap: "smoke",
|
|
18411
|
+
outputField: "detected",
|
|
18412
|
+
defaultAggregate: "any",
|
|
18413
|
+
accept: [{
|
|
18414
|
+
cap: "smoke",
|
|
18415
|
+
fieldPath: "detected"
|
|
18416
|
+
}],
|
|
18417
|
+
companions: [CHANGED]
|
|
18418
|
+
}),
|
|
18419
|
+
binary({
|
|
18420
|
+
id: "occupancy",
|
|
18421
|
+
summary: "Any or all of motion or binary sensors, published as a binary. Presence zones are not aggregated. Nobody reporting is offline, not off.",
|
|
18422
|
+
role: DeviceRole.BinarySensor,
|
|
18423
|
+
outputCap: "binary",
|
|
18424
|
+
outputField: "on",
|
|
18425
|
+
defaultAggregate: "any",
|
|
18426
|
+
accept: [{
|
|
18427
|
+
cap: "motion",
|
|
18428
|
+
fieldPath: "detected"
|
|
18429
|
+
}, {
|
|
18430
|
+
cap: "binary",
|
|
18431
|
+
fieldPath: "on"
|
|
18432
|
+
}],
|
|
18433
|
+
companions: [CHANGED]
|
|
18434
|
+
}),
|
|
18435
|
+
binary({
|
|
18436
|
+
id: "binary",
|
|
18437
|
+
summary: "Any or all generic binary sensors. Offline and unknown members are left out, never read as off.",
|
|
18438
|
+
role: DeviceRole.BinarySensor,
|
|
18439
|
+
outputCap: "binary",
|
|
18440
|
+
outputField: "on",
|
|
18441
|
+
defaultAggregate: "any",
|
|
18442
|
+
accept: [{
|
|
18443
|
+
cap: "binary",
|
|
18444
|
+
fieldPath: "on"
|
|
18445
|
+
}],
|
|
18446
|
+
companions: [CHANGED]
|
|
18447
|
+
}),
|
|
18448
|
+
actuator({
|
|
18449
|
+
id: "switch",
|
|
18450
|
+
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.",
|
|
18451
|
+
deviceType: DeviceType.Switch,
|
|
18452
|
+
outputCap: "switch",
|
|
18453
|
+
commandCaps: ["switch"]
|
|
18454
|
+
}),
|
|
18455
|
+
actuator({
|
|
18456
|
+
id: "light",
|
|
18457
|
+
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.",
|
|
18458
|
+
deviceType: DeviceType.Light,
|
|
18459
|
+
outputCap: "switch",
|
|
18460
|
+
commandCaps: [
|
|
18461
|
+
"switch",
|
|
18462
|
+
"brightness",
|
|
18463
|
+
"color"
|
|
18464
|
+
]
|
|
18465
|
+
})
|
|
18466
|
+
];
|
|
18467
|
+
function actuator(input) {
|
|
18468
|
+
return {
|
|
18469
|
+
...input,
|
|
18470
|
+
family: "actuator",
|
|
18471
|
+
role: void 0,
|
|
18472
|
+
memberDeviceType: input.deviceType,
|
|
18473
|
+
outputField: "on",
|
|
18474
|
+
quantity: "none",
|
|
18475
|
+
baseUnit: void 0,
|
|
18476
|
+
aggregates: BINARY_AGGREGATES,
|
|
18477
|
+
defaultAggregate: "any",
|
|
18478
|
+
empty: "offline",
|
|
18479
|
+
accept: [{
|
|
18480
|
+
cap: "switch",
|
|
18481
|
+
fieldPath: "on"
|
|
18482
|
+
}],
|
|
18483
|
+
companions: [CHANGED]
|
|
18484
|
+
};
|
|
18485
|
+
}
|
|
18486
|
+
new Map(GROUP_TEMPLATES.map((template) => [template.id, template]));
|
|
18487
|
+
DeviceFeature.LightColorRgb, DeviceFeature.LightColorHsv, DeviceFeature.LightColorMired;
|
|
18100
18488
|
`${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
|
|
18101
18489
|
/**
|
|
18102
18490
|
* What a composition may BUILD on a device type (G2, D676): the caps a new
|
|
@@ -19923,12 +20311,12 @@ function buildDeviceAdminUrl(parts) {
|
|
|
19923
20311
|
* providers detect renames by matching `uniqueId` and patch `id`
|
|
19924
20312
|
* in-place so dispatch keeps working.
|
|
19925
20313
|
*
|
|
19926
|
-
* **
|
|
19927
|
-
*
|
|
19928
|
-
*
|
|
19929
|
-
*
|
|
19930
|
-
* (`ha-domain-mapping`)
|
|
19931
|
-
* stored after that point.
|
|
20314
|
+
* **Display unit and precision are NOT stored here.** They are a read-time
|
|
20315
|
+
* preference (D944). A polymorphic reading stores its `quantity` here once,
|
|
20316
|
+
* at adopt, and a date/time value stores `dateTimeShape` the same way —
|
|
20317
|
+
* neither is repeated on each sample. The `device_class` tag is an
|
|
20318
|
+
* HA-specific input consumed at the discovery boundary (`ha-domain-mapping`)
|
|
20319
|
+
* to derive the CamStack `DeviceRole`; it is never stored after that point.
|
|
19932
20320
|
*
|
|
19933
20321
|
* The `raw` escape hatch carries provider-specific attributes that don't
|
|
19934
20322
|
* fit the structured slots (HA `attributes` whitelist, Reolink `deviceCache`
|
|
@@ -19942,6 +20330,14 @@ var SourceInfoSchema = object({
|
|
|
19942
20330
|
/** Immutable upstream identifier when available (HA `unique_id`, … ).
|
|
19943
20331
|
* Used to detect rename when `id` changes. */
|
|
19944
20332
|
uniqueId: string().optional(),
|
|
20333
|
+
/** Quantity of a polymorphic reading, written once at adopt (D944). */
|
|
20334
|
+
quantity: ReadingQuantitySchema.optional(),
|
|
20335
|
+
/** Date / time / datetime shape of a string reading, written once at adopt. */
|
|
20336
|
+
dateTimeShape: _enum([
|
|
20337
|
+
"date",
|
|
20338
|
+
"time",
|
|
20339
|
+
"datetime"
|
|
20340
|
+
]).optional(),
|
|
19945
20341
|
/** Provider-specific extras that don't fit the structured slots.
|
|
19946
20342
|
* Whitelist what goes here per provider — do NOT dump entire HA
|
|
19947
20343
|
* attribute blobs (would explode the meta JSON column). */
|
|
@@ -41046,7 +41442,8 @@ method(object({
|
|
|
41046
41442
|
"enum"
|
|
41047
41443
|
]),
|
|
41048
41444
|
enumValues: array(string()).optional(),
|
|
41049
|
-
item: boolean().optional()
|
|
41445
|
+
item: boolean().optional(),
|
|
41446
|
+
quantity: ReadingQuantitySchema.optional()
|
|
41050
41447
|
})).readonly(),
|
|
41051
41448
|
itemArray: object({
|
|
41052
41449
|
path: string(),
|
|
@@ -44890,8 +45287,8 @@ var MaskPolygonShapeSchema = object({
|
|
|
44890
45287
|
/** Boolean cell grid — row-major, length === gridWidth*gridHeight. */
|
|
44891
45288
|
var MaskGridShapeSchema = object({
|
|
44892
45289
|
kind: literal("grid"),
|
|
44893
|
-
gridWidth: number(),
|
|
44894
|
-
gridHeight: number(),
|
|
45290
|
+
gridWidth: number().meta(readingMeta("none")),
|
|
45291
|
+
gridHeight: number().meta(readingMeta("none")),
|
|
44895
45292
|
cells: array(boolean())
|
|
44896
45293
|
});
|
|
44897
45294
|
discriminatedUnion("kind", [
|
|
@@ -45003,6 +45400,8 @@ var NcSystemEventKindSchema = _enum([
|
|
|
45003
45400
|
"detection-blind",
|
|
45004
45401
|
"motion-noisy",
|
|
45005
45402
|
"motion-calm",
|
|
45403
|
+
"package-llm-silent",
|
|
45404
|
+
"package-llm-answered",
|
|
45006
45405
|
"recording-stalled",
|
|
45007
45406
|
"recording-healthy",
|
|
45008
45407
|
"recording-degraded",
|
|
@@ -56094,6 +56493,28 @@ var PackageVersionInfoSchema = object({
|
|
|
56094
56493
|
deprecated: string().optional(),
|
|
56095
56494
|
distTags: array(string()).readonly()
|
|
56096
56495
|
});
|
|
56496
|
+
/**
|
|
56497
|
+
* One published document. `ok` is markdown from the registry. `missing` means
|
|
56498
|
+
* the registry answered and the file was not there. `error` is a registry or
|
|
56499
|
+
* tarball failure — never an empty string standing in for either.
|
|
56500
|
+
*/
|
|
56501
|
+
var PackageDocBodySchema = discriminatedUnion("status", [
|
|
56502
|
+
object({
|
|
56503
|
+
status: literal("ok"),
|
|
56504
|
+
markdown: string()
|
|
56505
|
+
}),
|
|
56506
|
+
object({ status: literal("missing") }),
|
|
56507
|
+
object({
|
|
56508
|
+
status: literal("error"),
|
|
56509
|
+
message: string()
|
|
56510
|
+
})
|
|
56511
|
+
]);
|
|
56512
|
+
var PackageDocsSchema = object({
|
|
56513
|
+
name: string(),
|
|
56514
|
+
version: string(),
|
|
56515
|
+
readme: PackageDocBodySchema,
|
|
56516
|
+
changelog: PackageDocBodySchema
|
|
56517
|
+
});
|
|
56097
56518
|
var SearchResultSchema = object({
|
|
56098
56519
|
name: string(),
|
|
56099
56520
|
version: string(),
|
|
@@ -56312,7 +56733,10 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
|
|
|
56312
56733
|
}), object({ success: literal(true) }), {
|
|
56313
56734
|
kind: "mutation",
|
|
56314
56735
|
auth: "admin"
|
|
56315
|
-
}), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({
|
|
56736
|
+
}), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({
|
|
56737
|
+
name: string().min(1),
|
|
56738
|
+
version: string().min(1).optional()
|
|
56739
|
+
}), PackageDocsSchema, { auth: "admin" }), method(object({ addonId: string() }), RestartAddonResultSchema, {
|
|
56316
56740
|
kind: "mutation",
|
|
56317
56741
|
auth: "admin"
|
|
56318
56742
|
}), method(object({ packageName: string() }), object({ success: literal(true) }), {
|
|
@@ -56371,27 +56795,17 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
|
|
|
56371
56795
|
*/
|
|
56372
56796
|
var AirQualitySensorStatusSchema = object({
|
|
56373
56797
|
/** Carbon dioxide concentration in ppm. */
|
|
56374
|
-
co2Ppm: number().min(0).optional(),
|
|
56798
|
+
co2Ppm: number().min(0).optional().meta(readingMeta("concentration-volume")),
|
|
56375
56799
|
/** Total volatile organic compounds in ppb. */
|
|
56376
|
-
vocPpb: number().min(0).optional(),
|
|
56800
|
+
vocPpb: number().min(0).optional().meta(readingMeta("concentration-ppb")),
|
|
56377
56801
|
/** Particulate matter ≤ 2.5 μm in µg/m³. */
|
|
56378
|
-
pm25: number().min(0).optional(),
|
|
56802
|
+
pm25: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
56379
56803
|
/** Particulate matter ≤ 10 μm in µg/m³. */
|
|
56380
|
-
pm10: number().min(0).optional(),
|
|
56804
|
+
pm10: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
56381
56805
|
/** Composite AQI value (typically 0..500). */
|
|
56382
|
-
aqi: number().optional(),
|
|
56806
|
+
aqi: number().optional().meta(readingMeta("index")),
|
|
56383
56807
|
/** Ms epoch when the slice was last updated. */
|
|
56384
|
-
lastFetchedAt: number()
|
|
56385
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
56386
|
-
* `attributes.unit_of_measurement` → 'ppm' / 'ppb' / 'µg/m³'). Each
|
|
56387
|
-
* upstream `sensor.*` entity surfaces ONE device_class, so one unit
|
|
56388
|
-
* per slice is unambiguous. */
|
|
56389
|
-
unit: string().optional(),
|
|
56390
|
-
/** Suggested decimal places for numeric display.
|
|
56391
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
56392
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
56393
|
-
* auto-formatting when absent. */
|
|
56394
|
-
precision: number().int().min(0).max(10).optional()
|
|
56808
|
+
lastFetchedAt: number()
|
|
56395
56809
|
});
|
|
56396
56810
|
var airQualitySensorCapability = {
|
|
56397
56811
|
name: "air-quality-sensor",
|
|
@@ -56428,12 +56842,12 @@ var airQualitySensorCapability = {
|
|
|
56428
56842
|
},
|
|
56429
56843
|
pm25: {
|
|
56430
56844
|
kind: "gauge",
|
|
56431
|
-
unit: "
|
|
56845
|
+
unit: "µg/m³",
|
|
56432
56846
|
deadband: 1
|
|
56433
56847
|
},
|
|
56434
56848
|
pm10: {
|
|
56435
56849
|
kind: "gauge",
|
|
56436
|
-
unit: "
|
|
56850
|
+
unit: "µg/m³",
|
|
56437
56851
|
deadband: 1
|
|
56438
56852
|
},
|
|
56439
56853
|
aqi: {
|
|
@@ -56451,22 +56865,13 @@ var airQualitySensorCapability = {
|
|
|
56451
56865
|
* entries with `device_class: illuminance`.
|
|
56452
56866
|
*/
|
|
56453
56867
|
var AmbientLightSensorStatusSchema = object({
|
|
56454
|
-
/** Current illuminance in lux (lx). */
|
|
56455
|
-
lux: number().min(0).meta({
|
|
56456
|
-
|
|
56868
|
+
/** Current illuminance in lux (lx). `null` when the sample was refused (D393). */
|
|
56869
|
+
lux: number().min(0).nullable().meta(readingMeta("illuminance", {
|
|
56870
|
+
precision: 0,
|
|
56457
56871
|
label: "Illuminance"
|
|
56458
|
-
}),
|
|
56872
|
+
})),
|
|
56459
56873
|
/** Ms epoch when the slice was last updated. */
|
|
56460
|
-
lastFetchedAt: number()
|
|
56461
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
56462
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
56463
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
56464
|
-
unit: string().optional(),
|
|
56465
|
-
/** Suggested decimal places for numeric display.
|
|
56466
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
56467
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
56468
|
-
* auto-formatting when absent. */
|
|
56469
|
-
precision: number().int().min(0).max(10).optional()
|
|
56874
|
+
lastFetchedAt: number()
|
|
56470
56875
|
});
|
|
56471
56876
|
var ambientLightSensorCapability = {
|
|
56472
56877
|
name: "ambient-light-sensor",
|
|
@@ -56498,12 +56903,7 @@ var ambientLightSensorCapability = {
|
|
|
56498
56903
|
} } },
|
|
56499
56904
|
/** Clock fields: written, but excluded from the compare that decides
|
|
56500
56905
|
* whether persisting is worth a SQLite commit. */
|
|
56501
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
56502
|
-
customize: {
|
|
56503
|
-
version: 1,
|
|
56504
|
-
advanced: "derive",
|
|
56505
|
-
targets: []
|
|
56506
|
-
}
|
|
56906
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
56507
56907
|
};
|
|
56508
56908
|
/**
|
|
56509
56909
|
* Per-class audio metrics aggregated over a sliding window.
|
|
@@ -56730,10 +57130,7 @@ var BatteryStatusSchema = object({
|
|
|
56730
57130
|
* Consumers must SKIP a null rather than coerce it — `battery-band` already
|
|
56731
57131
|
* declines to band a non-finite reading, which is the correct shape.
|
|
56732
57132
|
*/
|
|
56733
|
-
percentage: number().min(0).max(100).nullable().meta({
|
|
56734
|
-
unit: "%",
|
|
56735
|
-
label: "Charge"
|
|
56736
|
-
}),
|
|
57133
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage", { label: "Charge" })),
|
|
56737
57134
|
/**
|
|
56738
57135
|
* Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
|
|
56739
57136
|
* Reolink-specific for the Solar Panel 2 accessory (will become
|
|
@@ -56760,7 +57157,14 @@ var BatteryStatusSchema = object({
|
|
|
56760
57157
|
*/
|
|
56761
57158
|
sleeping: boolean().meta({ label: "Sleeping" }),
|
|
56762
57159
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
56763
|
-
lastUpdated: number(),
|
|
57160
|
+
lastUpdated: number().meta(readingMeta("none")),
|
|
57161
|
+
/**
|
|
57162
|
+
* Battery voltage in volts, for a cell the firmware reports as voltage
|
|
57163
|
+
* rather than a percentage (Ecowitt capacitor packs). Absent on cameras
|
|
57164
|
+
* that only report charge. A second reading on this cap, not a second
|
|
57165
|
+
* `numeric-sensor` on the same device.
|
|
57166
|
+
*/
|
|
57167
|
+
volts: number().nullable().optional().meta(readingMeta("voltage", { label: "Voltage" })),
|
|
56764
57168
|
/**
|
|
56765
57169
|
* Ms epoch of the last time the device PROVED it was reachable — a
|
|
56766
57170
|
* completed firmware round-trip, an observed wake, or an inbound push
|
|
@@ -56812,7 +57216,6 @@ var BATTERY_DEVICE_TYPES = [
|
|
|
56812
57216
|
/** Generic Customize target for the percentage reading (D936). */
|
|
56813
57217
|
var batteryCustomize = {
|
|
56814
57218
|
version: 1,
|
|
56815
|
-
advanced: "derive",
|
|
56816
57219
|
targets: [{
|
|
56817
57220
|
id: "percentage",
|
|
56818
57221
|
cardinality: "scalar",
|
|
@@ -56821,7 +57224,7 @@ var batteryCustomize = {
|
|
|
56821
57224
|
stateField: "percentage"
|
|
56822
57225
|
},
|
|
56823
57226
|
deviceTypes: BATTERY_DEVICE_TYPES,
|
|
56824
|
-
apply: "add
|
|
57227
|
+
apply: "add",
|
|
56825
57228
|
path: "percentage",
|
|
56826
57229
|
sources: [{
|
|
56827
57230
|
kind: "field",
|
|
@@ -56942,10 +57345,16 @@ onStatusChanged: { data: object({
|
|
|
56942
57345
|
/**
|
|
56943
57346
|
* History (D850): recorded series. The generic capture replaces the `battery` series of `pipeline-analytics:stats-5m`.
|
|
56944
57347
|
*/
|
|
56945
|
-
history: { fields: {
|
|
56946
|
-
|
|
56947
|
-
|
|
56948
|
-
|
|
57348
|
+
history: { fields: {
|
|
57349
|
+
percentage: {
|
|
57350
|
+
kind: "gauge",
|
|
57351
|
+
unit: "%"
|
|
57352
|
+
},
|
|
57353
|
+
volts: {
|
|
57354
|
+
kind: "gauge",
|
|
57355
|
+
unit: "V"
|
|
57356
|
+
}
|
|
57357
|
+
} },
|
|
56949
57358
|
customize: batteryCustomize,
|
|
56950
57359
|
/** Clock fields: written, but excluded from the compare that decides
|
|
56951
57360
|
* whether persisting is worth a SQLite commit. */
|
|
@@ -56992,12 +57401,7 @@ var binaryCapability = {
|
|
|
56992
57401
|
history: { fields: { on: { kind: "boolean" } } },
|
|
56993
57402
|
/** Clock fields: written, but excluded from the compare that decides
|
|
56994
57403
|
* whether persisting is worth a SQLite commit. */
|
|
56995
|
-
volatileStateFields: ["lastChangedAt"]
|
|
56996
|
-
customize: {
|
|
56997
|
-
version: 1,
|
|
56998
|
-
advanced: "derive",
|
|
56999
|
-
targets: []
|
|
57000
|
-
}
|
|
57404
|
+
volatileStateFields: ["lastChangedAt"]
|
|
57001
57405
|
};
|
|
57002
57406
|
/**
|
|
57003
57407
|
* Dimmable-light brightness control. Co-exists with `switch` on the
|
|
@@ -57013,7 +57417,7 @@ var binaryCapability = {
|
|
|
57013
57417
|
*/
|
|
57014
57418
|
var BrightnessStatusSchema = object({
|
|
57015
57419
|
/** Current level as 0..100 inclusive. Firmware-reported. */
|
|
57016
|
-
percentage: number().min(0).max(100),
|
|
57420
|
+
percentage: number().min(0).max(100).meta(readingMeta("percentage")),
|
|
57017
57421
|
/** Ms epoch of the last operator-driven change. Useful for UI freshness. */
|
|
57018
57422
|
lastChangedAt: number()
|
|
57019
57423
|
});
|
|
@@ -57484,21 +57888,21 @@ var ClimateControlStatusSchema = object({
|
|
|
57484
57888
|
/** Single setpoint in Celsius. Used by single-target modes
|
|
57485
57889
|
* (heat / cool / dry). Null when the device is in a range mode
|
|
57486
57890
|
* (`heat_cool`) or has no setpoint at all (`fan_only`/`off`). */
|
|
57487
|
-
target: number().nullable(),
|
|
57891
|
+
target: number().nullable().meta(readingMeta("temperature")),
|
|
57488
57892
|
/** Upper bound of the dual setpoint in Celsius. Populated only
|
|
57489
57893
|
* in `heat_cool` mode. */
|
|
57490
|
-
targetHigh: number().nullable(),
|
|
57894
|
+
targetHigh: number().nullable().meta(readingMeta("temperature")),
|
|
57491
57895
|
/** Lower bound of the dual setpoint in Celsius. Populated only
|
|
57492
57896
|
* in `heat_cool` mode. */
|
|
57493
|
-
targetLow: number().nullable(),
|
|
57897
|
+
targetLow: number().nullable().meta(readingMeta("temperature")),
|
|
57494
57898
|
/** Target relative humidity (0..100). Null when the device has no
|
|
57495
57899
|
* humidity control. */
|
|
57496
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
57900
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
57497
57901
|
/** Current measured temperature in Celsius. Read-only — pushed by
|
|
57498
57902
|
* the device's internal sensor. */
|
|
57499
|
-
currentTemp: number().nullable(),
|
|
57903
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
57500
57904
|
/** Current measured relative humidity (0..100). Read-only. */
|
|
57501
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
57905
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
57502
57906
|
/** Vertical louver swing on/off. Null when the device has no vertical
|
|
57503
57907
|
* swing surface (gate with `DeviceFeature.ClimateSwingVertical`). */
|
|
57504
57908
|
swingVertical: boolean().nullable(),
|
|
@@ -57506,11 +57910,11 @@ var ClimateControlStatusSchema = object({
|
|
|
57506
57910
|
* horizontal swing surface (gate with `DeviceFeature.ClimateSwingHorizontal`). */
|
|
57507
57911
|
swingHorizontal: boolean().nullable(),
|
|
57508
57912
|
/** Lowest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
57509
|
-
minTemp: number().nullable().optional(),
|
|
57913
|
+
minTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
57510
57914
|
/** Highest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
57511
|
-
maxTemp: number().nullable().optional(),
|
|
57915
|
+
maxTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
57512
57916
|
/** Setpoint granularity, Celsius (0.5, 1). Absent / null = not reported. */
|
|
57513
|
-
tempStep: number().positive().nullable().optional(),
|
|
57917
|
+
tempStep: number().positive().nullable().optional().meta(readingMeta("temperature")),
|
|
57514
57918
|
/** Ms epoch when the slice was last updated (push or command). */
|
|
57515
57919
|
lastFetchedAt: number()
|
|
57516
57920
|
});
|
|
@@ -57652,17 +58056,17 @@ var climateControlCapability = {
|
|
|
57652
58056
|
* modes to expose in the picker without a slice fetch.
|
|
57653
58057
|
*/
|
|
57654
58058
|
var RgbTripletSchema = object({
|
|
57655
|
-
r: number().int().min(0).max(255),
|
|
57656
|
-
g: number().int().min(0).max(255),
|
|
57657
|
-
b: number().int().min(0).max(255)
|
|
58059
|
+
r: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
58060
|
+
g: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
58061
|
+
b: number().int().min(0).max(255).meta(readingMeta("none"))
|
|
57658
58062
|
});
|
|
57659
58063
|
var HsvTripletSchema = object({
|
|
57660
58064
|
/** Hue in degrees, 0..360. */
|
|
57661
|
-
h: number().min(0).max(360),
|
|
58065
|
+
h: number().min(0).max(360).meta(readingMeta("none")),
|
|
57662
58066
|
/** Saturation as 0..100 inclusive. */
|
|
57663
|
-
s: number().min(0).max(100),
|
|
58067
|
+
s: number().min(0).max(100).meta(readingMeta("none")),
|
|
57664
58068
|
/** Value/brightness as 0..100 inclusive. */
|
|
57665
|
-
v: number().min(0).max(100)
|
|
58069
|
+
v: number().min(0).max(100).meta(readingMeta("none"))
|
|
57666
58070
|
});
|
|
57667
58071
|
var ColorInputSchema = discriminatedUnion("mode", [
|
|
57668
58072
|
object({
|
|
@@ -57691,7 +58095,7 @@ var ColorStatusSchema = object({
|
|
|
57691
58095
|
/** Populated when `mode === 'hsv'`. */
|
|
57692
58096
|
hsv: HsvTripletSchema.optional(),
|
|
57693
58097
|
/** Populated when `mode === 'mired'`. */
|
|
57694
|
-
mireds: number().int().optional(),
|
|
58098
|
+
mireds: number().int().optional().meta(readingMeta("colour-temperature")),
|
|
57695
58099
|
/** Ms epoch of the last operator-driven change. */
|
|
57696
58100
|
lastChangedAt: number()
|
|
57697
58101
|
});
|
|
@@ -57886,18 +58290,12 @@ _enum([
|
|
|
57886
58290
|
"empty",
|
|
57887
58291
|
"full"
|
|
57888
58292
|
]);
|
|
57889
|
-
/**
|
|
57890
|
-
|
|
57891
|
-
|
|
57892
|
-
"days",
|
|
57893
|
-
"hours",
|
|
57894
|
-
"cycles"
|
|
57895
|
-
]);
|
|
57896
|
-
/** Remaining life as a COUNT, not a percentage (the PetKit desiccant reports
|
|
57897
|
-
* days). `value` null = unknown (D393). */
|
|
58293
|
+
/** Whether `remaining.value` is a duration in seconds or a dimensionless count. */
|
|
58294
|
+
var ConsumableRemainingKindSchema = _enum(["duration", "count"]);
|
|
58295
|
+
/** Remaining life. `value` null = unknown (D393). Duration is seconds. */
|
|
57898
58296
|
var ConsumableRemainingSchema = object({
|
|
57899
|
-
value: number().min(0).nullable(),
|
|
57900
|
-
|
|
58297
|
+
value: number().min(0).nullable().meta(readingMeta("device")),
|
|
58298
|
+
kind: ConsumableRemainingKindSchema
|
|
57901
58299
|
});
|
|
57902
58300
|
/** A single consumable item. Either a continuous `level` (remaining
|
|
57903
58301
|
* life %, or fill % for a `supply` / `waste` item) or a discrete `status`
|
|
@@ -57910,7 +58308,7 @@ var ConsumableItemSchema = object({
|
|
|
57910
58308
|
/** Display name. */
|
|
57911
58309
|
label: string().min(1),
|
|
57912
58310
|
/** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
|
|
57913
|
-
level: number().min(0).max(100).nullable(),
|
|
58311
|
+
level: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
57914
58312
|
/** The provider's discrete verdict when known (binary mode). */
|
|
57915
58313
|
status: ConsumableStatusSchema.nullable(),
|
|
57916
58314
|
/** What the item is — decides whether low or full is bad. Absent = `wear`. */
|
|
@@ -57992,8 +58390,8 @@ var consumablesCustomize = {
|
|
|
57992
58390
|
transforms: [{ kind: "identity" }]
|
|
57993
58391
|
}],
|
|
57994
58392
|
literals: [{
|
|
57995
|
-
path: "remaining.
|
|
57996
|
-
values: [...
|
|
58393
|
+
path: "remaining.kind",
|
|
58394
|
+
values: [...ConsumableRemainingKindSchema.options]
|
|
57997
58395
|
}]
|
|
57998
58396
|
},
|
|
57999
58397
|
{
|
|
@@ -58122,7 +58520,6 @@ reset: method(object({
|
|
|
58122
58520
|
},
|
|
58123
58521
|
"remaining.value": {
|
|
58124
58522
|
kind: "gauge",
|
|
58125
|
-
unitFrom: "remaining.unit",
|
|
58126
58523
|
deadband: 1,
|
|
58127
58524
|
displayName: "Remaining"
|
|
58128
58525
|
}
|
|
@@ -58192,10 +58589,9 @@ var contactCapability = {
|
|
|
58192
58589
|
* (empty array for the other kinds). It lives in the slice because
|
|
58193
58590
|
* HA `select.*` entities may update their options at runtime.
|
|
58194
58591
|
*
|
|
58195
|
-
*
|
|
58196
|
-
*
|
|
58197
|
-
*
|
|
58198
|
-
* push — consistent with `options` and the sensor-unit approach.
|
|
58592
|
+
* Numeric `min` / `max` / `step` live in the slice and share the device
|
|
58593
|
+
* quantity (`SourceInfo.quantity`, D944). Display precision is a read-time
|
|
58594
|
+
* preference. A datetime control's shape is `SourceInfo.dateTimeShape`.
|
|
58199
58595
|
*/
|
|
58200
58596
|
var ControlStatusSchema = object({
|
|
58201
58597
|
kind: _enum([
|
|
@@ -58207,39 +58603,17 @@ var ControlStatusSchema = object({
|
|
|
58207
58603
|
/** Current value. Numeric kind → number; select/text/datetime → string.
|
|
58208
58604
|
* Datetime values are ISO 8601 strings (full timestamp, date-only,
|
|
58209
58605
|
* or time-only — HA accepts all three forms). */
|
|
58210
|
-
value: union([number(), string()]),
|
|
58606
|
+
value: union([number().meta(readingMeta("device")), string()]),
|
|
58211
58607
|
/** Acceptable values when `kind === 'select'`. Empty for other kinds. */
|
|
58212
58608
|
options: array(string()),
|
|
58213
58609
|
/** Ms epoch when the slice was last updated. */
|
|
58214
58610
|
lastChangedAt: number(),
|
|
58215
|
-
/**
|
|
58216
|
-
|
|
58217
|
-
|
|
58218
|
-
|
|
58219
|
-
/**
|
|
58220
|
-
|
|
58221
|
-
min: number().optional(),
|
|
58222
|
-
/** Maximum allowed value. Populated live from HA `attributes.max`.
|
|
58223
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
58224
|
-
max: number().optional(),
|
|
58225
|
-
/** Step increment. Populated live from HA `attributes.step`.
|
|
58226
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
58227
|
-
step: number().optional(),
|
|
58228
|
-
/** Suggested decimal places for numeric display. Populated live from HA
|
|
58229
|
-
* `attributes.suggested_display_precision`, or derived from `step` when the
|
|
58230
|
-
* HA attribute is absent. Meaningful for `kind === 'numeric'`; absent for
|
|
58231
|
-
* other kinds. Falls back to auto-formatting when absent. */
|
|
58232
|
-
precision: number().int().min(0).max(10).optional(),
|
|
58233
|
-
/** Date-picker granularity for `kind === 'datetime'`. 'date' → date-only,
|
|
58234
|
-
* 'time' → time-only, 'datetime' → full timestamp. Absent for other kinds
|
|
58235
|
-
* (UI defaults to 'datetime'). Derived live from the device's HA domain
|
|
58236
|
-
* (date.* / time.* / datetime.*) or, for input_datetime, from the entity's
|
|
58237
|
-
* `has_date`/`has_time` attributes on each push. */
|
|
58238
|
-
format: _enum([
|
|
58239
|
-
"date",
|
|
58240
|
-
"time",
|
|
58241
|
-
"datetime"
|
|
58242
|
-
]).optional()
|
|
58611
|
+
/** Minimum allowed value, in the device quantity's base unit. */
|
|
58612
|
+
min: number().optional().meta(readingMeta("device")),
|
|
58613
|
+
/** Maximum allowed value, in the device quantity's base unit. */
|
|
58614
|
+
max: number().optional().meta(readingMeta("device")),
|
|
58615
|
+
/** Step increment, in the device quantity's base unit. */
|
|
58616
|
+
step: number().optional().meta(readingMeta("device"))
|
|
58243
58617
|
});
|
|
58244
58618
|
var ControlSetValueInputSchema = discriminatedUnion("kind", [
|
|
58245
58619
|
object({
|
|
@@ -58305,9 +58679,9 @@ var CoverStatusSchema = object({
|
|
|
58305
58679
|
]),
|
|
58306
58680
|
/** 0 = fully closed, 100 = fully open. Null when the device has
|
|
58307
58681
|
* no intermediate position surface. */
|
|
58308
|
-
position: number().min(0).max(100).nullable(),
|
|
58682
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58309
58683
|
/** 0 = closed slats, 100 = open slats. Null when no tilt support. */
|
|
58310
|
-
tiltPosition: number().min(0).max(100).nullable(),
|
|
58684
|
+
tiltPosition: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58311
58685
|
/** Ms epoch when the slice was last updated. */
|
|
58312
58686
|
lastChangedAt: number()
|
|
58313
58687
|
});
|
|
@@ -58410,9 +58784,9 @@ var NormalizedRangeSchema$1 = object({
|
|
|
58410
58784
|
var DayNightStatusSchema = object({
|
|
58411
58785
|
mode: DayNightModeSchema,
|
|
58412
58786
|
/** IR-cut trigger sensitivity, NORMALIZED 0–100 (higher = switches to night sooner). */
|
|
58413
|
-
sensitivity: number().optional(),
|
|
58787
|
+
sensitivity: number().optional().meta(readingMeta("none")),
|
|
58414
58788
|
/** Delay before the IR-cut filter flips, in seconds. */
|
|
58415
|
-
switchDelaySec: number().optional(),
|
|
58789
|
+
switchDelaySec: number().optional().meta(readingMeta("duration")),
|
|
58416
58790
|
lastFetchedAt: number()
|
|
58417
58791
|
});
|
|
58418
58792
|
/**
|
|
@@ -58630,11 +59004,11 @@ var DishwasherStatusSchema = object({
|
|
|
58630
59004
|
/** Feature keys of the programs the appliance currently offers — drives the UI selector. */
|
|
58631
59005
|
availablePrograms: array(string()),
|
|
58632
59006
|
/** Seconds remaining on the active cycle, or null when not running / not known. */
|
|
58633
|
-
remainingSeconds: number().int().nonnegative().nullable(),
|
|
59007
|
+
remainingSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
58634
59008
|
/** Seconds the delayed start is set to (time until the cycle starts), or null. */
|
|
58635
|
-
delayedStartSeconds: number().int().nonnegative().nullable(),
|
|
59009
|
+
delayedStartSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
58636
59010
|
/** Cycle completion 0..100, or null when not applicable. */
|
|
58637
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
59011
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58638
59012
|
/** True when the door is reported open; null when the door state is not known. */
|
|
58639
59013
|
doorOpen: boolean().nullable(),
|
|
58640
59014
|
/** True when the door is latched (locked) during a cycle; null when not reported. */
|
|
@@ -58658,7 +59032,7 @@ var DishwasherStatusSchema = object({
|
|
|
58658
59032
|
/** True while the machine-care (descaling / cleaning-program) reminder is raised; false when clear; null when not reported. */
|
|
58659
59033
|
machineCareDue: boolean().nullable(),
|
|
58660
59034
|
/** Program runs left before the machine-care reminder is due; null when the appliance does not say. */
|
|
58661
|
-
machineCareRemainingRuns: number().int().nonnegative().nullable(),
|
|
59035
|
+
machineCareRemainingRuns: number().int().nonnegative().nullable().meta(readingMeta("count")),
|
|
58662
59036
|
/** Option states: null when the appliance does not expose the option or has not said. */
|
|
58663
59037
|
halfLoad: boolean().nullable(),
|
|
58664
59038
|
hygienePlus: boolean().nullable(),
|
|
@@ -58673,7 +59047,7 @@ var DishwasherStatusSchema = object({
|
|
|
58673
59047
|
/** Feature keys of the events currently raised (salt low, rinse aid low, program finished, …). */
|
|
58674
59048
|
activeEvents: array(string()),
|
|
58675
59049
|
/** Numeric error code when the appliance reports one; null otherwise. */
|
|
58676
|
-
errorCode: number().nullable(),
|
|
59050
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
58677
59051
|
/** Name of the raised alert-level event while the appliance is in error; null otherwise. */
|
|
58678
59052
|
errorLabel: string().nullable(),
|
|
58679
59053
|
/** Ms epoch of the last value received from the appliance; 0 = never. */
|
|
@@ -58904,7 +59278,7 @@ var DoorbellStatusSchema = object({
|
|
|
58904
59278
|
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
58905
59279
|
lastPressedAt: number().nullable(),
|
|
58906
59280
|
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
58907
|
-
pressCountSinceStart: number()
|
|
59281
|
+
pressCountSinceStart: number().meta(readingMeta("count"))
|
|
58908
59282
|
});
|
|
58909
59283
|
var DoorbellPressEventSchema = object({
|
|
58910
59284
|
deviceId: number(),
|
|
@@ -58969,17 +59343,7 @@ onPressed: {
|
|
|
58969
59343
|
history: "none",
|
|
58970
59344
|
customize: doorbellCustomize
|
|
58971
59345
|
};
|
|
58972
|
-
|
|
58973
|
-
* Enum-state sensor — a string value picked from a finite option set.
|
|
58974
|
-
* Drives HA `sensor` entries with `state_class: enum` (HVAC action
|
|
58975
|
-
* states, weather conditions, contact-source channels, mode strings).
|
|
58976
|
-
* The option set is stable across observations; it is persisted in the
|
|
58977
|
-
* device config blob (via the control slice at adoption) and is NOT
|
|
58978
|
-
* stored in `sourceInfo`.
|
|
58979
|
-
*/
|
|
58980
|
-
/** Locale-render shape for an ISO `value` carried by a `DateTimeSensor`-role
|
|
58981
|
-
* enum sensor: `date` (date-only), `time` (time-only), `datetime` (both). */
|
|
58982
|
-
var EnumSensorDateTimeFormatSchema = _enum([
|
|
59346
|
+
_enum([
|
|
58983
59347
|
"date",
|
|
58984
59348
|
"time",
|
|
58985
59349
|
"datetime"
|
|
@@ -58987,12 +59351,11 @@ var EnumSensorDateTimeFormatSchema = _enum([
|
|
|
58987
59351
|
var EnumSensorStatusSchema = object({
|
|
58988
59352
|
value: string(),
|
|
58989
59353
|
/**
|
|
58990
|
-
* Set
|
|
58991
|
-
* as
|
|
58992
|
-
*
|
|
58993
|
-
* a time-only sensor → `'time'`.
|
|
59354
|
+
* Set when `value` is a timestamp rather than an enum state, so history
|
|
59355
|
+
* does not learn ISO strings as states. The display shape (date / time /
|
|
59356
|
+
* datetime) lives on `SourceInfo.dateTimeShape`, written once at adopt.
|
|
58994
59357
|
*/
|
|
58995
|
-
|
|
59358
|
+
timestamp: boolean().optional(),
|
|
58996
59359
|
/** Ms epoch when the slice was last updated. */
|
|
58997
59360
|
lastFetchedAt: number()
|
|
58998
59361
|
});
|
|
@@ -59019,11 +59382,11 @@ var enumSensorCapability = {
|
|
|
59019
59382
|
* History (D850): the value as an `enum` series (an appliance's program or
|
|
59020
59383
|
* operation state, an HVAC action). The option set is per device, so the
|
|
59021
59384
|
* value list is LEARNED as values are first seen (bounded). A sensor with a
|
|
59022
|
-
* `
|
|
59385
|
+
* `timestamp` carries a clock, not a state, and is not recorded.
|
|
59023
59386
|
*/
|
|
59024
59387
|
history: { fields: { value: {
|
|
59025
59388
|
kind: "enum",
|
|
59026
|
-
skipWhenSet: "
|
|
59389
|
+
skipWhenSet: "timestamp"
|
|
59027
59390
|
} } },
|
|
59028
59391
|
/** Clock fields: written, but excluded from the compare that decides
|
|
59029
59392
|
* whether persisting is worth a SQLite commit. */
|
|
@@ -59043,13 +59406,13 @@ var EventFireSchema = object({
|
|
|
59043
59406
|
deviceId: number(),
|
|
59044
59407
|
eventType: string(),
|
|
59045
59408
|
data: record(string(), unknown()).nullable(),
|
|
59046
|
-
timestamp: number(),
|
|
59047
|
-
seq: number()
|
|
59409
|
+
timestamp: number().meta(readingMeta("none")),
|
|
59410
|
+
seq: number().meta(readingMeta("count"))
|
|
59048
59411
|
});
|
|
59049
59412
|
var EventEmitterStatusSchema = object({
|
|
59050
59413
|
eventTypes: array(string()),
|
|
59051
59414
|
lastEvent: EventFireSchema.nullable(),
|
|
59052
|
-
eventCountSinceStart: number()
|
|
59415
|
+
eventCountSinceStart: number().meta(readingMeta("count"))
|
|
59053
59416
|
});
|
|
59054
59417
|
var eventEmitterCapability = {
|
|
59055
59418
|
name: "event-emitter",
|
|
@@ -59462,10 +59825,10 @@ var FanDirectionSchema = _enum(["forward", "reverse"]);
|
|
|
59462
59825
|
var FanControlStatusSchema = object({
|
|
59463
59826
|
/** Active speed as 0..100 inclusive. Null when the device has no
|
|
59464
59827
|
* speed surface (single-speed fan). */
|
|
59465
|
-
percentage: number().min(0).max(100).nullable(),
|
|
59828
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59466
59829
|
/** Speed granularity the device accepts (HA `percentage_step`, e.g. 25 for
|
|
59467
59830
|
* a 4-speed fan). Absent when unknown — the UI then falls back to step 1. */
|
|
59468
|
-
percentageStep: number().positive().optional(),
|
|
59831
|
+
percentageStep: number().positive().optional().meta(readingMeta("percentage")),
|
|
59469
59832
|
/** Active preset mode (`auto` / `quiet` / `turbo` / vendor-specific)
|
|
59470
59833
|
* — empty string when no preset is active or supported. */
|
|
59471
59834
|
preset: string(),
|
|
@@ -59586,7 +59949,7 @@ var FeatureProbeStatusSchema = object({
|
|
|
59586
59949
|
/** Camera/firmware model string. `null` when the firmware doesn't expose it. */
|
|
59587
59950
|
model: string().nullable(),
|
|
59588
59951
|
/** Channel count for NVR/Hub devices; `1` for standalone cameras; `null` pre-probe. */
|
|
59589
|
-
channelCount: number().nullable(),
|
|
59952
|
+
channelCount: number().nullable().meta(readingMeta("count")),
|
|
59590
59953
|
/**
|
|
59591
59954
|
* Ms epoch of the last SUCCESSFUL probe. `0` before the first probe
|
|
59592
59955
|
* completes — drivers' `getAccessoryChildren()` should treat zero as
|
|
@@ -59709,9 +60072,91 @@ var gasCapability = {
|
|
|
59709
60072
|
* whether persisting is worth a SQLite commit. */
|
|
59710
60073
|
volatileStateFields: ["lastChangedAt"]
|
|
59711
60074
|
};
|
|
60075
|
+
var GroupCommandsSchema = object({
|
|
60076
|
+
/** One row per member that has been commanded. A later command replaces that member's row. */
|
|
60077
|
+
results: array(object({
|
|
60078
|
+
deviceId: number().int().nonnegative(),
|
|
60079
|
+
cap: string().min(1),
|
|
60080
|
+
method: string().min(1),
|
|
60081
|
+
ok: boolean(),
|
|
60082
|
+
error: string().optional(),
|
|
60083
|
+
/** Ms epoch of the attempt. */
|
|
60084
|
+
at: number()
|
|
60085
|
+
})) });
|
|
60086
|
+
var groupCommandsCapability = {
|
|
60087
|
+
name: "group-commands",
|
|
60088
|
+
scope: "device",
|
|
60089
|
+
deviceNative: true,
|
|
60090
|
+
mode: "singleton",
|
|
60091
|
+
deviceTypes: [DeviceType.Switch, DeviceType.Light],
|
|
60092
|
+
methods: {},
|
|
60093
|
+
status: {
|
|
60094
|
+
schema: GroupCommandsSchema,
|
|
60095
|
+
kind: "push"
|
|
60096
|
+
},
|
|
60097
|
+
runtimeState: GroupCommandsSchema,
|
|
60098
|
+
/**
|
|
60099
|
+
* Runtime-state durability: **session** — the last attempt. A restored
|
|
60100
|
+
* failure would outlive the command that caused it.
|
|
60101
|
+
*
|
|
60102
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
60103
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
60104
|
+
*/
|
|
60105
|
+
durability: "session",
|
|
60106
|
+
history: "none"
|
|
60107
|
+
};
|
|
60108
|
+
/**
|
|
60109
|
+
* How many members of a helper group answered (D944). Counts are integers,
|
|
60110
|
+
* not measurements: zero included is a real count, never a stand-in reading.
|
|
60111
|
+
* The reading itself stays on the output capability. History is none — the
|
|
60112
|
+
* series that later statistics read is the output cap's own history block.
|
|
60113
|
+
*/
|
|
60114
|
+
var GroupStatusSchema = object({
|
|
60115
|
+
/** Members whose current value entered the aggregate. */
|
|
60116
|
+
included: number().int().nonnegative().meta(readingMeta("count", {
|
|
60117
|
+
precision: 0,
|
|
60118
|
+
label: "Reporting"
|
|
60119
|
+
})),
|
|
60120
|
+
/** Members left out: offline, unknown, or not a finite reading (D393). */
|
|
60121
|
+
excluded: number().int().nonnegative().meta(readingMeta("count", {
|
|
60122
|
+
precision: 0,
|
|
60123
|
+
label: "Excluded"
|
|
60124
|
+
})),
|
|
60125
|
+
/** `included` + `excluded`. */
|
|
60126
|
+
total: number().int().nonnegative().meta(readingMeta("count", {
|
|
60127
|
+
precision: 0,
|
|
60128
|
+
label: "Members"
|
|
60129
|
+
}))
|
|
60130
|
+
});
|
|
60131
|
+
var groupStatusCapability = {
|
|
60132
|
+
name: "group-status",
|
|
60133
|
+
scope: "device",
|
|
60134
|
+
deviceNative: true,
|
|
60135
|
+
mode: "singleton",
|
|
60136
|
+
deviceTypes: [
|
|
60137
|
+
DeviceType.Sensor,
|
|
60138
|
+
DeviceType.Switch,
|
|
60139
|
+
DeviceType.Light
|
|
60140
|
+
],
|
|
60141
|
+
methods: {},
|
|
60142
|
+
status: {
|
|
60143
|
+
schema: GroupStatusSchema,
|
|
60144
|
+
kind: "push"
|
|
60145
|
+
},
|
|
60146
|
+
runtimeState: GroupStatusSchema,
|
|
60147
|
+
/**
|
|
60148
|
+
* Runtime-state durability: **session** — recomputed from members on the
|
|
60149
|
+
* next source event; a restored count would outlive the readings it named.
|
|
60150
|
+
*
|
|
60151
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
60152
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
60153
|
+
*/
|
|
60154
|
+
durability: "session",
|
|
60155
|
+
history: "none"
|
|
60156
|
+
};
|
|
59712
60157
|
var HeatingValveStatusSchema = object({
|
|
59713
60158
|
/** Radiator valve opening 0 (closed) .. 100 (open). Null = not yet known. */
|
|
59714
|
-
position: number().min(0).max(100).nullable(),
|
|
60159
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59715
60160
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
59716
60161
|
lastFetchedAt: number()
|
|
59717
60162
|
});
|
|
@@ -59754,9 +60199,9 @@ var HumidifierStatusSchema = object({
|
|
|
59754
60199
|
/** Whether the humidifier is currently on. */
|
|
59755
60200
|
on: boolean(),
|
|
59756
60201
|
/** Current measured relative humidity (0..100). Null when not reported. */
|
|
59757
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
60202
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
59758
60203
|
/** Target relative humidity (0..100). Null when no setpoint surface. */
|
|
59759
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
60204
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
59760
60205
|
/** Active mode (`auto` / `normal` / `baby` / vendor). Null when the
|
|
59761
60206
|
* device has no mode surface. */
|
|
59762
60207
|
mode: string().nullable(),
|
|
@@ -59766,9 +60211,9 @@ var HumidifierStatusSchema = object({
|
|
|
59766
60211
|
* `idle` / `off`). Null when the device doesn't report it. */
|
|
59767
60212
|
action: string().nullable(),
|
|
59768
60213
|
/** HA `min_humidity` attribute. Null → UI uses 0. */
|
|
59769
|
-
minHumidity: number().nullable(),
|
|
60214
|
+
minHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
59770
60215
|
/** HA `max_humidity` attribute. Null → UI uses 100. */
|
|
59771
|
-
maxHumidity: number().nullable(),
|
|
60216
|
+
maxHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
59772
60217
|
/** Ms epoch when the slice was last updated. */
|
|
59773
60218
|
lastChangedAt: number()
|
|
59774
60219
|
});
|
|
@@ -59838,22 +60283,13 @@ var humidifierCapability = {
|
|
|
59838
60283
|
* `sourceInfo`.
|
|
59839
60284
|
*/
|
|
59840
60285
|
var HumiditySensorStatusSchema = object({
|
|
59841
|
-
/** Current relative humidity, 0..100. */
|
|
59842
|
-
percent: number().min(0).max(100).meta({
|
|
59843
|
-
|
|
60286
|
+
/** Current relative humidity, 0..100. `null` when the sample was refused (D393). */
|
|
60287
|
+
percent: number().min(0).max(100).nullable().meta(readingMeta("humidity", {
|
|
60288
|
+
precision: 0,
|
|
59844
60289
|
label: "Humidity"
|
|
59845
|
-
}),
|
|
60290
|
+
})),
|
|
59846
60291
|
/** Ms epoch when the slice was last updated. */
|
|
59847
|
-
lastFetchedAt: number()
|
|
59848
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
59849
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
59850
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
59851
|
-
unit: string().optional(),
|
|
59852
|
-
/** Suggested decimal places for numeric display.
|
|
59853
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
59854
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
59855
|
-
* auto-formatting when absent. */
|
|
59856
|
-
precision: number().int().min(0).max(10).optional()
|
|
60292
|
+
lastFetchedAt: number()
|
|
59857
60293
|
});
|
|
59858
60294
|
var humiditySensorCapability = {
|
|
59859
60295
|
name: "humidity-sensor",
|
|
@@ -59884,12 +60320,7 @@ var humiditySensorCapability = {
|
|
|
59884
60320
|
} } },
|
|
59885
60321
|
/** Clock fields: written, but excluded from the compare that decides
|
|
59886
60322
|
* whether persisting is worth a SQLite commit. */
|
|
59887
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
59888
|
-
customize: {
|
|
59889
|
-
version: 1,
|
|
59890
|
-
advanced: "derive",
|
|
59891
|
-
targets: []
|
|
59892
|
-
}
|
|
60323
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
59893
60324
|
};
|
|
59894
60325
|
/**
|
|
59895
60326
|
* Image display cap. Models a single still image exposed by an integration —
|
|
@@ -59910,7 +60341,7 @@ var ImageStatusSchema = object({
|
|
|
59910
60341
|
* entity exposes no `entity_picture` (yet). */
|
|
59911
60342
|
url: string().nullable(),
|
|
59912
60343
|
/** Ms epoch of the upstream last-updated timestamp. Null at cold-start. */
|
|
59913
|
-
lastUpdated: number().nullable()
|
|
60344
|
+
lastUpdated: number().nullable().meta(readingMeta("none"))
|
|
59914
60345
|
});
|
|
59915
60346
|
var imageCapability = {
|
|
59916
60347
|
name: "image",
|
|
@@ -59998,19 +60429,19 @@ var NormalizedRangeSchema = object({
|
|
|
59998
60429
|
*/
|
|
59999
60430
|
var ImageSettingsStatusSchema = object({
|
|
60000
60431
|
/** Normalized 0–100. */
|
|
60001
|
-
brightness: number().optional(),
|
|
60432
|
+
brightness: number().optional().meta(readingMeta("none")),
|
|
60002
60433
|
/** Normalized 0–100. */
|
|
60003
|
-
contrast: number().optional(),
|
|
60434
|
+
contrast: number().optional().meta(readingMeta("none")),
|
|
60004
60435
|
/** Normalized 0–100. */
|
|
60005
|
-
saturation: number().optional(),
|
|
60436
|
+
saturation: number().optional().meta(readingMeta("none")),
|
|
60006
60437
|
/** Normalized 0–100. */
|
|
60007
|
-
sharpness: number().optional(),
|
|
60438
|
+
sharpness: number().optional().meta(readingMeta("none")),
|
|
60008
60439
|
mirror: boolean().optional(),
|
|
60009
60440
|
flip: boolean().optional(),
|
|
60010
60441
|
rotate: ImageRotateSchema.optional(),
|
|
60011
60442
|
whiteBalance: WhiteBalanceModeSchema.optional(),
|
|
60012
60443
|
/** Manual white-balance warmth, NORMALIZED 0–100. Meaningful only when `whiteBalance === 'manual'`. */
|
|
60013
|
-
warmth: number().optional(),
|
|
60444
|
+
warmth: number().optional().meta(readingMeta("none")),
|
|
60014
60445
|
exposureMode: ExposureModeSchema.optional(),
|
|
60015
60446
|
backlightMode: BacklightModeSchema.optional(),
|
|
60016
60447
|
lastFetchedAt: number()
|
|
@@ -60289,10 +60720,10 @@ var IntercomAbilitySchema = object({
|
|
|
60289
60720
|
/** Codecs accepted by firmware, in preference order. Driver-authored strings. */
|
|
60290
60721
|
codecs: array(string()),
|
|
60291
60722
|
/** Sample rate (Hz) the firmware expects. Reolink typical: 16000. */
|
|
60292
|
-
sampleRate: number(),
|
|
60723
|
+
sampleRate: number().meta(readingMeta("none")),
|
|
60293
60724
|
duplex: _enum(["half", "full"]),
|
|
60294
60725
|
/** Max in-flight audio backlog before drop (ms). Server uses this to bound latency. */
|
|
60295
|
-
maxBacklogMs: number()
|
|
60726
|
+
maxBacklogMs: number().meta(readingMeta("duration-ms"))
|
|
60296
60727
|
});
|
|
60297
60728
|
var IntercomStatusSchema = object({
|
|
60298
60729
|
/** True while a talk session is open. */
|
|
@@ -60519,13 +60950,13 @@ var LawnMowerControlStatusSchema = object({
|
|
|
60519
60950
|
activity: LawnMowerActivitySchema,
|
|
60520
60951
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
60521
60952
|
* reading. */
|
|
60522
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
60953
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
60523
60954
|
/** 0..100 mowing-completion percentage of the current task, or null when no
|
|
60524
60955
|
* task is active / progress is unavailable. */
|
|
60525
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
60956
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
60526
60957
|
/** Current device/event code (dynamic — mostly status, sometimes an error),
|
|
60527
60958
|
* or null when unknown. */
|
|
60528
|
-
currentCode: number().nullable(),
|
|
60959
|
+
currentCode: number().nullable().meta(readingMeta("none")),
|
|
60529
60960
|
/** Human label for {@link currentCode}, or null when undecodable. */
|
|
60530
60961
|
currentCodeLabel: string().nullable(),
|
|
60531
60962
|
/** Severity of {@link currentCode}. `error` (and often `warning`) warrants UI
|
|
@@ -61058,7 +61489,7 @@ var MediaPlayerStatusSchema = object({
|
|
|
61058
61489
|
state: MediaPlayerStateSchema,
|
|
61059
61490
|
/** Volume as 0..100 inclusive. Null when the device has no volume
|
|
61060
61491
|
* surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
|
|
61061
|
-
volumeLevel: number().min(0).max(100).nullable(),
|
|
61492
|
+
volumeLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61062
61493
|
/** Mute toggle distinct from volume=0. Null when no mute surface.
|
|
61063
61494
|
* Pair with `DeviceFeature.MediaPlayerMute`. */
|
|
61064
61495
|
isMuted: boolean().nullable(),
|
|
@@ -61071,10 +61502,10 @@ var MediaPlayerStatusSchema = object({
|
|
|
61071
61502
|
currentMedia: MediaInfoSchema.nullable(),
|
|
61072
61503
|
/** Current playback position in ms. Null when not seekable or
|
|
61073
61504
|
* nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
|
|
61074
|
-
positionMs: number().int().nonnegative().nullable(),
|
|
61505
|
+
positionMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
61075
61506
|
/** Total duration of the current media in ms. Null when unknown
|
|
61076
61507
|
* (live stream) or nothing is playing. */
|
|
61077
|
-
durationMs: number().int().nonnegative().nullable(),
|
|
61508
|
+
durationMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
61078
61509
|
/** Shuffle toggle. Null when no shuffle surface.
|
|
61079
61510
|
* Pair with `DeviceFeature.MediaPlayerShuffle`. */
|
|
61080
61511
|
shuffle: boolean().nullable(),
|
|
@@ -61383,7 +61814,7 @@ var motionCustomize = {
|
|
|
61383
61814
|
eventName: "onMotionChanged"
|
|
61384
61815
|
},
|
|
61385
61816
|
deviceTypes: [DeviceType.Camera],
|
|
61386
|
-
apply: "
|
|
61817
|
+
apply: "add",
|
|
61387
61818
|
applyAuthority: {
|
|
61388
61819
|
kind: "camera-sensors",
|
|
61389
61820
|
timeoutField: "motionCooldownMs"
|
|
@@ -61455,7 +61886,7 @@ var MotionStatusSchema = object({
|
|
|
61455
61886
|
* it, every provider seeded it at boot, and every session left it
|
|
61456
61887
|
* `detected: true` after its detach.
|
|
61457
61888
|
*/
|
|
61458
|
-
autoClearAfterMs: number().nullable()
|
|
61889
|
+
autoClearAfterMs: number().nullable().meta(readingMeta("duration-ms"))
|
|
61459
61890
|
});
|
|
61460
61891
|
/**
|
|
61461
61892
|
* Payload of `motion.onMotionChanged` event + the corresponding bus
|
|
@@ -61492,12 +61923,18 @@ var motionCapability = {
|
|
|
61492
61923
|
methods: {
|
|
61493
61924
|
/**
|
|
61494
61925
|
* Pull the current motion state synchronously. Convenience shortcut
|
|
61495
|
-
* for consumers that don't need the full status object
|
|
61496
|
-
*
|
|
61497
|
-
* `getStatus` once the auto-injected status surface lands in every
|
|
61498
|
-
* consumer.
|
|
61926
|
+
* for consumers that don't need the full status object. A composed
|
|
61927
|
+
* group answers from its slice (D944): unknown throws, it is not off.
|
|
61499
61928
|
*/
|
|
61500
61929
|
isDetected: method(object({ deviceId: number() }), boolean()) },
|
|
61930
|
+
/**
|
|
61931
|
+
* A composed motion group serves `isDetected` from `detected` (D944).
|
|
61932
|
+
* Without this the cap stays uncomposable (`has-commands`).
|
|
61933
|
+
*/
|
|
61934
|
+
composedMethods: { isDetected: {
|
|
61935
|
+
kind: "slice",
|
|
61936
|
+
field: "detected"
|
|
61937
|
+
} },
|
|
61501
61938
|
events: {
|
|
61502
61939
|
/**
|
|
61503
61940
|
* Fires every time the runner transitions a camera between
|
|
@@ -61637,7 +62074,7 @@ var MotionZoneRegionSchema = object({
|
|
|
61637
62074
|
* the grid region(s). */
|
|
61638
62075
|
var MotionZoneStatusSchema = object({
|
|
61639
62076
|
enabled: boolean(),
|
|
61640
|
-
sensitivity: number(),
|
|
62077
|
+
sensitivity: number().meta(readingMeta("none")),
|
|
61641
62078
|
/** Grid region(s). Today exactly one `grid` shape. */
|
|
61642
62079
|
regions: array(MotionZoneRegionSchema),
|
|
61643
62080
|
lastFetchedAt: number()
|
|
@@ -62007,7 +62444,7 @@ var NavigationStatusSchema = object({
|
|
|
62007
62444
|
following: boolean(),
|
|
62008
62445
|
flash: boolean(),
|
|
62009
62446
|
lightMode: NavigationLightModeSchema,
|
|
62010
|
-
lightLevel: number().min(40).max(100),
|
|
62447
|
+
lightLevel: number().min(40).max(100).meta(readingMeta("none")),
|
|
62011
62448
|
/** Ms epoch when the slice was last updated. */
|
|
62012
62449
|
lastChangedAt: number()
|
|
62013
62450
|
});
|
|
@@ -62141,13 +62578,13 @@ var NetworkLinkStatusSchema = object({
|
|
|
62141
62578
|
* one whose reading has not landed must not be drawn at 0 %. Consumers
|
|
62142
62579
|
* SKIP a null rather than coerce it.
|
|
62143
62580
|
*/
|
|
62144
|
-
signalPercent: number().min(0).max(100).nullable(),
|
|
62581
|
+
signalPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
62145
62582
|
/** Raw received signal strength in dBm, when the firmware reports one. */
|
|
62146
|
-
rssiDbm: number().optional(),
|
|
62583
|
+
rssiDbm: number().optional().meta(readingMeta("signal-level")),
|
|
62147
62584
|
/** Network name of a wireless link, when the firmware reports it. */
|
|
62148
62585
|
ssid: string().optional(),
|
|
62149
62586
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
62150
|
-
lastUpdated: number()
|
|
62587
|
+
lastUpdated: number().meta(readingMeta("none"))
|
|
62151
62588
|
});
|
|
62152
62589
|
var networkLinkCapability = {
|
|
62153
62590
|
name: "network-link",
|
|
@@ -62532,7 +62969,7 @@ var NotifierStatusSchema = object({
|
|
|
62532
62969
|
lastError: string().nullable(),
|
|
62533
62970
|
/** Number of deliveries currently buffered server-side (rate-limited
|
|
62534
62971
|
* notifiers may queue). 0 when the provider sends synchronously. */
|
|
62535
|
-
queueDepth: number().int().nonnegative(),
|
|
62972
|
+
queueDepth: number().int().nonnegative().meta(readingMeta("count")),
|
|
62536
62973
|
/** Per-feature capability matrix — authoritative source for the
|
|
62537
62974
|
* compose-form field gating. */
|
|
62538
62975
|
supports: NotifierSupportsSchema
|
|
@@ -62624,11 +63061,9 @@ onSent: { data: object({
|
|
|
62624
63061
|
* cap fits (HA `sensor` whose `device_class` we don't have a typed cap
|
|
62625
63062
|
* for: water flow, distance, weight, frequency, signal strength, …).
|
|
62626
63063
|
*
|
|
62627
|
-
* The
|
|
62628
|
-
*
|
|
62629
|
-
*
|
|
62630
|
-
* The UI reads them directly from the slice — they are the single source
|
|
62631
|
-
* of truth for generic numeric rendering and do NOT live on `sourceInfo`.
|
|
63064
|
+
* The quantity is not on this slice. It is chosen when the device is
|
|
63065
|
+
* adopted and stored once on `SourceInfo.quantity` (D944). `value` is in
|
|
63066
|
+
* that quantity's base unit. `null` is a refused sample (D393).
|
|
62632
63067
|
*
|
|
62633
63068
|
* Prefer the typed alternatives (`temperature-sensor`, `humidity-sensor`,
|
|
62634
63069
|
* `ambient-light-sensor`, `pressure-sensor`, `power-meter`,
|
|
@@ -62637,15 +63072,8 @@ onSent: { data: object({
|
|
|
62637
63072
|
* numeric values land here.
|
|
62638
63073
|
*/
|
|
62639
63074
|
var NumericSensorStatusSchema = object({
|
|
62640
|
-
|
|
62641
|
-
|
|
62642
|
-
* Populated live from the upstream source on each state push.
|
|
62643
|
-
* Absent for unitless sensors. */
|
|
62644
|
-
unit: string().optional(),
|
|
62645
|
-
/** Suggested decimal places for numeric display.
|
|
62646
|
-
* Populated live from the upstream source when provided.
|
|
62647
|
-
* Falls back to auto-formatting when absent. */
|
|
62648
|
-
precision: number().int().min(0).max(10).optional(),
|
|
63075
|
+
/** Reading in the device quantity's base unit. `null` when refused (D393). */
|
|
63076
|
+
value: number().nullable().meta(readingMeta("device")),
|
|
62649
63077
|
/** Ms epoch when the slice was last updated. */
|
|
62650
63078
|
lastFetchedAt: number()
|
|
62651
63079
|
});
|
|
@@ -62669,11 +63097,11 @@ var numericSensorCapability = {
|
|
|
62669
63097
|
*/
|
|
62670
63098
|
durability: "restored",
|
|
62671
63099
|
/**
|
|
62672
|
-
* History (D850): recorded series. The unit is
|
|
63100
|
+
* History (D850): recorded series. The unit is the device quantity's base,
|
|
63101
|
+
* resolved when the series is read — the cap has no single unit.
|
|
62673
63102
|
*/
|
|
62674
63103
|
history: { fields: { value: {
|
|
62675
63104
|
kind: "gauge",
|
|
62676
|
-
unitFrom: "unit",
|
|
62677
63105
|
minIntervalMs: 3e4
|
|
62678
63106
|
} } },
|
|
62679
63107
|
/** Clock fields: written, but excluded from the compare that decides
|
|
@@ -62965,23 +63393,26 @@ var PetFeederStatusSchema = object({
|
|
|
62965
63393
|
/** Food currently in the bowl (grams). Null when the device has not
|
|
62966
63394
|
* reported a reading yet. On dual-hopper models this is the combined
|
|
62967
63395
|
* bowl reading; per-hopper levels live in `food1`/`food2`. */
|
|
62968
|
-
foodLevel: number().nullable(),
|
|
63396
|
+
foodLevel: number().nullable().meta(readingMeta("none")),
|
|
62969
63397
|
/** Hopper-1 food level (grams) on dual-hopper feeders; null on
|
|
62970
63398
|
* single-hopper models. */
|
|
62971
|
-
food1: number().nullable(),
|
|
63399
|
+
food1: number().nullable().meta(readingMeta("none")),
|
|
62972
63400
|
/** Hopper-2 food level (grams) on dual-hopper feeders; null on
|
|
62973
63401
|
* single-hopper models. */
|
|
62974
|
-
food2: number().nullable(),
|
|
63402
|
+
food2: number().nullable().meta(readingMeta("none")),
|
|
62975
63403
|
/** Derived low-food flag — mirrors the HA `food_level` binary_sensor
|
|
62976
63404
|
* (`device_class: problem`, on = low). True when the bowl is empty /
|
|
62977
63405
|
* below the feeder's low threshold. */
|
|
62978
63406
|
lowFood: boolean(),
|
|
62979
63407
|
/** Battery charge 0..100 (%). Null on mains-powered models or when the
|
|
62980
63408
|
* device has no battery reading. */
|
|
62981
|
-
batteryPower: number().min(0).max(100).nullable(),
|
|
62982
|
-
/**
|
|
62983
|
-
*
|
|
62984
|
-
|
|
63409
|
+
batteryPower: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
63410
|
+
/**
|
|
63411
|
+
* Desiccant life remaining, stored in seconds (duration base, D944).
|
|
63412
|
+
* Providers convert from the days the feeder reports. Null when the
|
|
63413
|
+
* model has no desiccant sensor.
|
|
63414
|
+
*/
|
|
63415
|
+
desiccantLeftDays: number().nullable().meta(readingMeta("duration")),
|
|
62985
63416
|
/** True while a feed is in progress. */
|
|
62986
63417
|
feeding: boolean(),
|
|
62987
63418
|
/** Decoded connectivity / power status (HA petkit device-status enum).
|
|
@@ -62992,7 +63423,7 @@ var PetFeederStatusSchema = object({
|
|
|
62992
63423
|
* with `errorCode` for consumers that want the raw integer. */
|
|
62993
63424
|
error: string().nullable(),
|
|
62994
63425
|
/** Raw device error code (0 / null = no error). */
|
|
62995
|
-
errorCode: number().nullable(),
|
|
63426
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
62996
63427
|
/** True for D4S/D4SH dual-hopper hardware — gates the per-hopper UI. */
|
|
62997
63428
|
isDualHopper: boolean(),
|
|
62998
63429
|
/** Child-lock (manual-lock) setting — buttons on the unit are disabled. */
|
|
@@ -63002,7 +63433,7 @@ var PetFeederStatusSchema = object({
|
|
|
63002
63433
|
/** Play a chime when dispensing. */
|
|
63003
63434
|
feedSound: boolean(),
|
|
63004
63435
|
/** Speaker / prompt volume level (device-scaled integer). */
|
|
63005
|
-
volume: number(),
|
|
63436
|
+
volume: number().meta(readingMeta("none")),
|
|
63006
63437
|
/** Ms epoch when the slice was last refreshed from the cloud. */
|
|
63007
63438
|
lastFetchedAt: number()
|
|
63008
63439
|
});
|
|
@@ -63121,7 +63552,7 @@ var petFeederCapability = {
|
|
|
63121
63552
|
},
|
|
63122
63553
|
desiccantLeftDays: {
|
|
63123
63554
|
kind: "gauge",
|
|
63124
|
-
unit: "
|
|
63555
|
+
unit: "s"
|
|
63125
63556
|
}
|
|
63126
63557
|
} }
|
|
63127
63558
|
};
|
|
@@ -63522,36 +63953,19 @@ method(_void(), PlatformCapabilitiesSchema), method(_void(), HardwareInfoSchema)
|
|
|
63522
63953
|
*/
|
|
63523
63954
|
var PowerMeterStatusSchema = object({
|
|
63524
63955
|
/** Instantaneous power draw in watts. */
|
|
63525
|
-
watts: number().optional().meta({
|
|
63526
|
-
unit: "W",
|
|
63527
|
-
label: "Power"
|
|
63528
|
-
}),
|
|
63956
|
+
watts: number().optional().meta(readingMeta("power", { label: "Power" })),
|
|
63529
63957
|
/** Cumulative energy in kilowatt-hours since the meter was reset. */
|
|
63530
|
-
kwhTotal: number().optional().meta({
|
|
63531
|
-
unit: "kWh",
|
|
63532
|
-
label: "Energy"
|
|
63533
|
-
}),
|
|
63958
|
+
kwhTotal: number().optional().meta(readingMeta("energy", { label: "Energy" })),
|
|
63534
63959
|
/** Voltage in volts. */
|
|
63535
|
-
volts: number().optional(),
|
|
63960
|
+
volts: number().optional().meta(readingMeta("voltage")),
|
|
63536
63961
|
/** Current in amperes. */
|
|
63537
|
-
amps: number().optional(),
|
|
63538
|
-
/** Apparent power in volt-amperes
|
|
63539
|
-
va: number().optional(),
|
|
63962
|
+
amps: number().optional().meta(readingMeta("current")),
|
|
63963
|
+
/** Apparent power in volt-amperes. */
|
|
63964
|
+
va: number().optional().meta(readingMeta("apparent-power")),
|
|
63540
63965
|
/** Power factor (0..1) if reported. */
|
|
63541
|
-
powerFactor: number().min(0).max(1).optional(),
|
|
63966
|
+
powerFactor: number().min(0).max(1).optional().meta(readingMeta("ratio")),
|
|
63542
63967
|
/** Ms epoch when the slice was last updated. */
|
|
63543
|
-
lastFetchedAt: number()
|
|
63544
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
63545
|
-
* `attributes.unit_of_measurement` → 'V' / 'A' / 'W' / 'kW' / 'kWh').
|
|
63546
|
-
* Each upstream `sensor.*` entity surfaces ONE device_class, so one
|
|
63547
|
-
* unit per slice is unambiguous. The UI prefers this over the role's
|
|
63548
|
-
* canonical unit so a 'kW' / 'Wh' feed renders verbatim. */
|
|
63549
|
-
unit: string().optional(),
|
|
63550
|
-
/** Suggested decimal places for numeric display.
|
|
63551
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
63552
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
63553
|
-
* auto-formatting when absent. */
|
|
63554
|
-
precision: number().int().min(0).max(10).optional()
|
|
63968
|
+
lastFetchedAt: number()
|
|
63555
63969
|
});
|
|
63556
63970
|
var powerMeterCapability = {
|
|
63557
63971
|
name: "power-meter",
|
|
@@ -63615,12 +64029,7 @@ var powerMeterCapability = {
|
|
|
63615
64029
|
} },
|
|
63616
64030
|
/** Clock fields: written, but excluded from the compare that decides
|
|
63617
64031
|
* whether persisting is worth a SQLite commit. */
|
|
63618
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
63619
|
-
customize: {
|
|
63620
|
-
version: 1,
|
|
63621
|
-
advanced: "derive",
|
|
63622
|
-
targets: []
|
|
63623
|
-
}
|
|
64032
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
63624
64033
|
};
|
|
63625
64034
|
/**
|
|
63626
64035
|
* Presence cap. Models HA `person.*` and `device_tracker.*` entities
|
|
@@ -63640,11 +64049,11 @@ var powerMeterCapability = {
|
|
|
63640
64049
|
*/
|
|
63641
64050
|
var GpsLocationSchema = object({
|
|
63642
64051
|
/** Latitude in decimal degrees, -90..90. */
|
|
63643
|
-
latitude: number().min(-90).max(90),
|
|
64052
|
+
latitude: number().min(-90).max(90).meta(readingMeta("angle")),
|
|
63644
64053
|
/** Longitude in decimal degrees, -180..180. */
|
|
63645
|
-
longitude: number().min(-180).max(180),
|
|
64054
|
+
longitude: number().min(-180).max(180).meta(readingMeta("angle")),
|
|
63646
64055
|
/** Reported accuracy in meters (lower = better). */
|
|
63647
|
-
accuracyMeters: number().nonnegative()
|
|
64056
|
+
accuracyMeters: number().nonnegative().meta(readingMeta("length"))
|
|
63648
64057
|
});
|
|
63649
64058
|
var PresenceStatusSchema = object({
|
|
63650
64059
|
/** `home` / `not_home` / any user-defined zone name. */
|
|
@@ -63656,7 +64065,7 @@ var PresenceStatusSchema = object({
|
|
|
63656
64065
|
gps: GpsLocationSchema.nullable(),
|
|
63657
64066
|
/** Optional battery level of the tracking device (0..100). Null
|
|
63658
64067
|
* when not reported. */
|
|
63659
|
-
batteryPercent: number().min(0).max(100).nullable(),
|
|
64068
|
+
batteryPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
63660
64069
|
/** Ms epoch when the slice was last updated. */
|
|
63661
64070
|
lastChangedAt: number()
|
|
63662
64071
|
});
|
|
@@ -63706,19 +64115,10 @@ var presenceCapability = {
|
|
|
63706
64115
|
* `sourceInfo`.
|
|
63707
64116
|
*/
|
|
63708
64117
|
var PressureSensorStatusSchema = object({
|
|
63709
|
-
/** Current pressure in hPa. */
|
|
63710
|
-
hpa: number(),
|
|
64118
|
+
/** Current pressure in hPa. `null` when the sample was refused (D393). */
|
|
64119
|
+
hpa: number().nullable().meta(readingMeta("pressure", { precision: 0 })),
|
|
63711
64120
|
/** Ms epoch when the slice was last updated. */
|
|
63712
|
-
lastFetchedAt: number()
|
|
63713
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
63714
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
63715
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
63716
|
-
unit: string().optional(),
|
|
63717
|
-
/** Suggested decimal places for numeric display.
|
|
63718
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
63719
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
63720
|
-
* auto-formatting when absent. */
|
|
63721
|
-
precision: number().int().min(0).max(10).optional()
|
|
64121
|
+
lastFetchedAt: number()
|
|
63722
64122
|
});
|
|
63723
64123
|
var pressureSensorCapability = {
|
|
63724
64124
|
name: "pressure-sensor",
|
|
@@ -64132,8 +64532,8 @@ DeviceType.Camera, method(PtzMoveCommandSchema.extend({ deviceId: number() }), _
|
|
|
64132
64532
|
}), _void(), { kind: "mutation" });
|
|
64133
64533
|
var PtzAutotrackSettingsSchema = object({
|
|
64134
64534
|
targetType: string().describe("Vendor target string (people/vehicle/pet); empty = camera default"),
|
|
64135
|
-
stopDelaySeconds: number().int().min(0).max(300),
|
|
64136
|
-
disappearDelaySeconds: number().int().min(0).max(300)
|
|
64535
|
+
stopDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration")),
|
|
64536
|
+
disappearDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration"))
|
|
64137
64537
|
});
|
|
64138
64538
|
/**
|
|
64139
64539
|
* One option the camera advertises as a valid `targetType`. Drivers
|
|
@@ -64287,7 +64687,7 @@ var RunningStateStatusSchema = object({
|
|
|
64287
64687
|
/** null = unknown — never coerced to false (D393). */
|
|
64288
64688
|
running: boolean().nullable(),
|
|
64289
64689
|
/** Epoch ms the current boolean began; null while `running` is null. */
|
|
64290
|
-
since: number().nullable(),
|
|
64690
|
+
since: number().nullable().meta(readingMeta("none")),
|
|
64291
64691
|
source: RunningStateSourceSchema.meta({ label: "Source" }),
|
|
64292
64692
|
phase: string().nullable(),
|
|
64293
64693
|
/** null until a reading has been published (D393). */
|
|
@@ -64302,7 +64702,6 @@ var RUNNING_DEVICE_TYPES = Object.values(DeviceType);
|
|
|
64302
64702
|
/** Generic Customize target for the running boolean (D936). */
|
|
64303
64703
|
var runningCustomize = {
|
|
64304
64704
|
version: 1,
|
|
64305
|
-
advanced: "derive",
|
|
64306
64705
|
targets: [{
|
|
64307
64706
|
id: "running",
|
|
64308
64707
|
cardinality: "scalar",
|
|
@@ -64322,7 +64721,7 @@ var runningCustomize = {
|
|
|
64322
64721
|
DeviceType.Thermostat,
|
|
64323
64722
|
DeviceType.PetFeeder
|
|
64324
64723
|
],
|
|
64325
|
-
apply: "add
|
|
64724
|
+
apply: "add",
|
|
64326
64725
|
path: "running",
|
|
64327
64726
|
sources: [
|
|
64328
64727
|
{
|
|
@@ -65586,9 +65985,9 @@ var RecordTriggerSchema = _enum([
|
|
|
65586
65985
|
*/
|
|
65587
65986
|
var RecordWindowSchema = object({
|
|
65588
65987
|
trigger: RecordTriggerSchema,
|
|
65589
|
-
day: number().int().min(0).max(6),
|
|
65590
|
-
startMinute: number().int().min(0).max(1439),
|
|
65591
|
-
endMinute: number().int().min(1).max(1440)
|
|
65988
|
+
day: number().int().min(0).max(6).meta(readingMeta("none")),
|
|
65989
|
+
startMinute: number().int().min(0).max(1439).meta(readingMeta("none")),
|
|
65990
|
+
endMinute: number().int().min(1).max(1440).meta(readingMeta("none"))
|
|
65592
65991
|
});
|
|
65593
65992
|
/** Status of one physical volume, as the camera itself describes it. */
|
|
65594
65993
|
var OnboardStorageVolumeSchema = object({
|
|
@@ -65664,10 +66063,10 @@ var RecordingOnboardStatusSchema = object({
|
|
|
65664
66063
|
/** Master "record to the card at all" switch. */
|
|
65665
66064
|
enabled: boolean().nullable(),
|
|
65666
66065
|
overwriteWhenFull: boolean().nullable(),
|
|
65667
|
-
preRecordSec: number().nullable(),
|
|
65668
|
-
postRecordSec: number().nullable(),
|
|
66066
|
+
preRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
66067
|
+
postRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
65669
66068
|
/** Length of one recorded file, in minutes. */
|
|
65670
|
-
segmentMinutes: number().nullable(),
|
|
66069
|
+
segmentMinutes: number().nullable().meta(readingMeta("none")),
|
|
65671
66070
|
/** The primary track's weekly windows, flattened. */
|
|
65672
66071
|
windows: array(RecordWindowSchema),
|
|
65673
66072
|
/**
|
|
@@ -65683,7 +66082,7 @@ var RecordingOnboardStatusSchema = object({
|
|
|
65683
66082
|
* provider reporting a non-zero count also reports the schedule as not
|
|
65684
66083
|
* writable.
|
|
65685
66084
|
*/
|
|
65686
|
-
unreadableWindows: number(),
|
|
66085
|
+
unreadableWindows: number().meta(readingMeta("count")),
|
|
65687
66086
|
/**
|
|
65688
66087
|
* The camera is scheduled to record and has NO usable storage.
|
|
65689
66088
|
*
|
|
@@ -66528,7 +66927,7 @@ var CamStreamDescriptorSchema = object({
|
|
|
66528
66927
|
url: string().optional(),
|
|
66529
66928
|
codec: string().optional(),
|
|
66530
66929
|
resolution: CamStreamResolutionSchema.optional(),
|
|
66531
|
-
fps: number().positive().optional(),
|
|
66930
|
+
fps: number().positive().optional().meta(readingMeta("rate")),
|
|
66532
66931
|
label: string().optional(),
|
|
66533
66932
|
/** Device-level features (e.g. `battery-operated`) — drives broker policy. */
|
|
66534
66933
|
deviceFeatures: array(string()).optional(),
|
|
@@ -66615,18 +67014,18 @@ var StreamProfileSchema = _enum([
|
|
|
66615
67014
|
]);
|
|
66616
67015
|
/** The current encoding config of one stream profile. */
|
|
66617
67016
|
var StreamProfileConfigSchema = object({
|
|
66618
|
-
width: number(),
|
|
66619
|
-
height: number(),
|
|
67017
|
+
width: number().meta(readingMeta("none")),
|
|
67018
|
+
height: number().meta(readingMeta("none")),
|
|
66620
67019
|
codec: _enum(["h264", "h265"]),
|
|
66621
|
-
framerate: number(),
|
|
66622
|
-
bitrate: number(),
|
|
67020
|
+
framerate: number().meta(readingMeta("rate")),
|
|
67021
|
+
bitrate: number().meta(readingMeta("bitrate")),
|
|
66623
67022
|
bitrateMode: _enum(["vbr", "cbr"]).optional(),
|
|
66624
67023
|
encoderProfile: _enum([
|
|
66625
67024
|
"high",
|
|
66626
67025
|
"main",
|
|
66627
67026
|
"baseline"
|
|
66628
67027
|
]).optional(),
|
|
66629
|
-
gop: number().optional(),
|
|
67028
|
+
gop: number().optional().meta(readingMeta("none")),
|
|
66630
67029
|
/**
|
|
66631
67030
|
* Whether THIS profile currently carries an audio track. READ-ONLY here.
|
|
66632
67031
|
*
|
|
@@ -66847,12 +67246,7 @@ var switchCapability = {
|
|
|
66847
67246
|
label: "On",
|
|
66848
67247
|
kind: "boolean"
|
|
66849
67248
|
}
|
|
66850
|
-
}] }
|
|
66851
|
-
customize: {
|
|
66852
|
-
version: 1,
|
|
66853
|
-
advanced: "derive",
|
|
66854
|
-
targets: []
|
|
66855
|
-
}
|
|
67249
|
+
}] }
|
|
66856
67250
|
};
|
|
66857
67251
|
/** C0 controls, DEL and the C1 range: none of them belongs in a name. */
|
|
66858
67252
|
function hasControlCharacter(value) {
|
|
@@ -67435,35 +67829,21 @@ var tamperCapability = {
|
|
|
67435
67829
|
* entries with `device_class: temperature` and any future native
|
|
67436
67830
|
* thermometer.
|
|
67437
67831
|
*
|
|
67438
|
-
*
|
|
67439
|
-
*
|
|
67440
|
-
* (climate-control's `currentTemp`, energy analytics) can compose
|
|
67441
|
-
* without per-source unit fixups. The canonical display unit (`°C`) is
|
|
67442
|
-
* a descriptor constant in the UI (ROLE_DESCRIPTOR), not stored in
|
|
67443
|
-
* `sourceInfo`.
|
|
67832
|
+
* The number is Celsius (D944). Providers convert on ingest. A failed
|
|
67833
|
+
* conversion is `null`, never a guess. Display unit is a read-time preference.
|
|
67444
67834
|
*
|
|
67445
67835
|
* Status `lastFetchedAt` lets staleness-aware consumers detect a
|
|
67446
67836
|
* frozen feed (provider hung) distinct from a "temperature hasn't
|
|
67447
67837
|
* changed" steady state.
|
|
67448
67838
|
*/
|
|
67449
67839
|
var TemperatureSensorStatusSchema = object({
|
|
67450
|
-
/** Current temperature in Celsius. */
|
|
67451
|
-
celsius: number().meta({
|
|
67452
|
-
|
|
67840
|
+
/** Current temperature in Celsius. `null` when the sample was refused (D393). */
|
|
67841
|
+
celsius: number().nullable().meta(readingMeta("temperature", {
|
|
67842
|
+
precision: 1,
|
|
67453
67843
|
label: "Temperature"
|
|
67454
|
-
}),
|
|
67844
|
+
})),
|
|
67455
67845
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
67456
|
-
lastFetchedAt: number()
|
|
67457
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
67458
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
67459
|
-
* role's canonical unit, so a Fahrenheit feed renders '°F' not '°C'.
|
|
67460
|
-
* Absent → the UI falls back to the role's canonical unit. */
|
|
67461
|
-
unit: string().optional(),
|
|
67462
|
-
/** Suggested decimal places for numeric display.
|
|
67463
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
67464
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
67465
|
-
* auto-formatting when absent. */
|
|
67466
|
-
precision: number().int().min(0).max(10).optional()
|
|
67846
|
+
lastFetchedAt: number()
|
|
67467
67847
|
});
|
|
67468
67848
|
var temperatureSensorCapability = {
|
|
67469
67849
|
name: "temperature-sensor",
|
|
@@ -67494,12 +67874,7 @@ var temperatureSensorCapability = {
|
|
|
67494
67874
|
} } },
|
|
67495
67875
|
/** Clock fields: written, but excluded from the compare that decides
|
|
67496
67876
|
* whether persisting is worth a SQLite commit. */
|
|
67497
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
67498
|
-
customize: {
|
|
67499
|
-
version: 1,
|
|
67500
|
-
advanced: "derive",
|
|
67501
|
-
targets: []
|
|
67502
|
-
}
|
|
67877
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
67503
67878
|
};
|
|
67504
67879
|
/**
|
|
67505
67880
|
* toast — system-scoped singleton capability that streams toast
|
|
@@ -67782,16 +68157,16 @@ var VacuumControlStatusSchema = object({
|
|
|
67782
68157
|
]),
|
|
67783
68158
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
67784
68159
|
* reading. */
|
|
67785
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
68160
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
67786
68161
|
/** Current fan-speed token (provider-verbatim). Null when unknown or
|
|
67787
68162
|
* the vacuum has no speed control. */
|
|
67788
68163
|
fanSpeed: string().nullable(),
|
|
67789
68164
|
/** Speed tokens the hardware accepts — drives the UI selector. */
|
|
67790
68165
|
availableFanSpeeds: array(string()),
|
|
67791
68166
|
/** 0..100 cleaning-completion percentage of the current task, or null. */
|
|
67792
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
68167
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
67793
68168
|
/** Current error code (0 / null = no error). */
|
|
67794
|
-
errorCode: number().nullable(),
|
|
68169
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
67795
68170
|
/** Human label for {@link errorCode}, or null when none / undecodable. */
|
|
67796
68171
|
errorLabel: string().nullable(),
|
|
67797
68172
|
/** Ms epoch when the slice was last updated. */
|
|
@@ -67869,7 +68244,7 @@ var ValveStatusSchema = object({
|
|
|
67869
68244
|
]),
|
|
67870
68245
|
/** 0 = fully closed, 100 = fully open. Null when the device has no
|
|
67871
68246
|
* intermediate position surface. */
|
|
67872
|
-
position: number().min(0).max(100).nullable(),
|
|
68247
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
67873
68248
|
/** Ms epoch when the slice was last updated. */
|
|
67874
68249
|
lastChangedAt: number()
|
|
67875
68250
|
});
|
|
@@ -67977,9 +68352,9 @@ var vibrationCapability = {
|
|
|
67977
68352
|
*/
|
|
67978
68353
|
var WaterHeaterStatusSchema = object({
|
|
67979
68354
|
/** Current measured temperature. Null when not reported. */
|
|
67980
|
-
currentTemp: number().nullable(),
|
|
68355
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
67981
68356
|
/** Target temperature setpoint. Null when no setpoint surface. */
|
|
67982
|
-
targetTemp: number().nullable(),
|
|
68357
|
+
targetTemp: number().nullable().meta(readingMeta("temperature")),
|
|
67983
68358
|
/** Active operation mode = HA `state` (`eco` / `electric` / `gas` /
|
|
67984
68359
|
* `heat_pump` / `high_demand` / `performance` / `off`). Null when the
|
|
67985
68360
|
* device reports an unknown state. */
|
|
@@ -67990,9 +68365,9 @@ var WaterHeaterStatusSchema = object({
|
|
|
67990
68365
|
* has no away surface. */
|
|
67991
68366
|
away: boolean().nullable(),
|
|
67992
68367
|
/** HA `min_temp` attribute. Null when not reported. */
|
|
67993
|
-
minTemp: number().nullable(),
|
|
68368
|
+
minTemp: number().nullable().meta(readingMeta("temperature")),
|
|
67994
68369
|
/** HA `max_temp` attribute. Null when not reported. */
|
|
67995
|
-
maxTemp: number().nullable(),
|
|
68370
|
+
maxTemp: number().nullable().meta(readingMeta("temperature")),
|
|
67996
68371
|
/** Ms epoch when the slice was last updated. */
|
|
67997
68372
|
lastChangedAt: number()
|
|
67998
68373
|
});
|
|
@@ -68077,25 +68452,18 @@ var waterHeaterCapability = {
|
|
|
68077
68452
|
* Forecast deferred — current conditions only for v1.
|
|
68078
68453
|
*/
|
|
68079
68454
|
var WeatherStatusSchema = object({
|
|
68080
|
-
/** Verbatim
|
|
68081
|
-
* when no condition has been reported yet. */
|
|
68455
|
+
/** Verbatim condition state (`sunny`, `cloudy`, `rainy`, …). Null when none yet. */
|
|
68082
68456
|
condition: string().nullable(),
|
|
68083
|
-
/** Current temperature in
|
|
68084
|
-
temperature: number().nullable(),
|
|
68085
|
-
/** Temperature unit string (e.g. `°C` / `°F`). Null when not provided. */
|
|
68086
|
-
temperatureUnit: string().nullable(),
|
|
68457
|
+
/** Current temperature in Celsius. Null when not provided or refused. */
|
|
68458
|
+
temperature: number().nullable().meta(readingMeta("temperature", { precision: 1 })),
|
|
68087
68459
|
/** Relative humidity (0..100). Null when not provided. */
|
|
68088
|
-
humidity: number().min(0).max(100).nullable(),
|
|
68089
|
-
/** Barometric pressure in
|
|
68090
|
-
pressure: number().nullable(),
|
|
68091
|
-
/**
|
|
68092
|
-
|
|
68093
|
-
/** Wind speed in the reported unit. Null when not provided. */
|
|
68094
|
-
windSpeed: number().nullable(),
|
|
68095
|
-
/** Wind-speed unit string (e.g. `km/h` / `mph`). Null when not provided. */
|
|
68096
|
-
windSpeedUnit: string().nullable(),
|
|
68460
|
+
humidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
68461
|
+
/** Barometric pressure in hPa. Null when not provided or refused. */
|
|
68462
|
+
pressure: number().nullable().meta(readingMeta("pressure")),
|
|
68463
|
+
/** Wind speed in metres per second. Null when not provided or refused. */
|
|
68464
|
+
windSpeed: number().nullable().meta(readingMeta("speed")),
|
|
68097
68465
|
/** Wind bearing in degrees (0..360, meteorological). Null when not provided. */
|
|
68098
|
-
windBearing: number().nullable(),
|
|
68466
|
+
windBearing: number().nullable().meta(readingMeta("angle")),
|
|
68099
68467
|
/** Ms epoch when the slice was last updated. */
|
|
68100
68468
|
lastFetchedAt: number()
|
|
68101
68469
|
});
|
|
@@ -68123,12 +68491,12 @@ var weatherCapability = {
|
|
|
68123
68491
|
*/
|
|
68124
68492
|
durability: "session",
|
|
68125
68493
|
/**
|
|
68126
|
-
* History (D850): recorded series.
|
|
68494
|
+
* History (D850): recorded series. Numbers are the quantity base (D944).
|
|
68127
68495
|
*/
|
|
68128
68496
|
history: { fields: {
|
|
68129
68497
|
temperature: {
|
|
68130
68498
|
kind: "gauge",
|
|
68131
|
-
|
|
68499
|
+
unit: "°C",
|
|
68132
68500
|
deadband: .2
|
|
68133
68501
|
},
|
|
68134
68502
|
humidity: {
|
|
@@ -68138,12 +68506,12 @@ var weatherCapability = {
|
|
|
68138
68506
|
},
|
|
68139
68507
|
pressure: {
|
|
68140
68508
|
kind: "gauge",
|
|
68141
|
-
|
|
68509
|
+
unit: "hPa",
|
|
68142
68510
|
deadband: .5
|
|
68143
68511
|
},
|
|
68144
68512
|
windSpeed: {
|
|
68145
68513
|
kind: "gauge",
|
|
68146
|
-
|
|
68514
|
+
unit: "m/s",
|
|
68147
68515
|
deadband: .5
|
|
68148
68516
|
}
|
|
68149
68517
|
} }
|
|
@@ -69374,6 +69742,8 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
69374
69742
|
featureProbe: featureProbeCapability,
|
|
69375
69743
|
flood: floodCapability,
|
|
69376
69744
|
gas: gasCapability,
|
|
69745
|
+
groupCommands: groupCommandsCapability,
|
|
69746
|
+
groupStatus: groupStatusCapability,
|
|
69377
69747
|
heatingValve: heatingValveCapability,
|
|
69378
69748
|
humidifier: humidifierCapability,
|
|
69379
69749
|
humiditySensor: humiditySensorCapability,
|
|
@@ -70750,6 +71120,13 @@ Object.freeze({
|
|
|
70750
71120
|
access: "view",
|
|
70751
71121
|
role: "admin"
|
|
70752
71122
|
},
|
|
71123
|
+
"addons.getPackageDocs": {
|
|
71124
|
+
capName: "addons",
|
|
71125
|
+
capScope: "system",
|
|
71126
|
+
addonId: null,
|
|
71127
|
+
access: "view",
|
|
71128
|
+
role: "admin"
|
|
71129
|
+
},
|
|
70753
71130
|
"addons.getVersions": {
|
|
70754
71131
|
capName: "addons",
|
|
70755
71132
|
capScope: "system",
|
|
@@ -73858,6 +74235,20 @@ Object.freeze({
|
|
|
73858
74235
|
access: "view",
|
|
73859
74236
|
role: "viewer"
|
|
73860
74237
|
},
|
|
74238
|
+
"groupCommands.getStatus": {
|
|
74239
|
+
capName: "group-commands",
|
|
74240
|
+
capScope: "device",
|
|
74241
|
+
addonId: null,
|
|
74242
|
+
access: "view",
|
|
74243
|
+
role: "viewer"
|
|
74244
|
+
},
|
|
74245
|
+
"groupStatus.getStatus": {
|
|
74246
|
+
capName: "group-status",
|
|
74247
|
+
capScope: "device",
|
|
74248
|
+
addonId: null,
|
|
74249
|
+
access: "view",
|
|
74250
|
+
role: "viewer"
|
|
74251
|
+
},
|
|
73861
74252
|
"heatingValve.getStatus": {
|
|
73862
74253
|
capName: "heating-valve",
|
|
73863
74254
|
capScope: "device",
|
|
@@ -80332,7 +80723,7 @@ function t(en, it) {
|
|
|
80332
80723
|
* covers, valves, locks, climate, fans, alarm panels.
|
|
80333
80724
|
*/
|
|
80334
80725
|
var ON = t("On", "Acceso");
|
|
80335
|
-
var PERCENT
|
|
80726
|
+
var PERCENT = t("Percentage", "Percentuale");
|
|
80336
80727
|
var OPEN_CLOSE_STATES = [
|
|
80337
80728
|
{
|
|
80338
80729
|
value: "open",
|
|
@@ -80560,7 +80951,7 @@ var ACTUATOR_CAP_VOCABULARY = {
|
|
|
80560
80951
|
icon: "sun-medium",
|
|
80561
80952
|
openArgs: [{
|
|
80562
80953
|
key: "percentage",
|
|
80563
|
-
label: PERCENT
|
|
80954
|
+
label: PERCENT,
|
|
80564
80955
|
offer: {
|
|
80565
80956
|
kind: "number",
|
|
80566
80957
|
min: 0,
|
|
@@ -83680,6 +84071,37 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83680
84071
|
icon: "flame"
|
|
83681
84072
|
}]
|
|
83682
84073
|
},
|
|
84074
|
+
"group-commands": {
|
|
84075
|
+
scope: "device",
|
|
84076
|
+
noun: t("Group command", "Comando di gruppo")
|
|
84077
|
+
},
|
|
84078
|
+
"group-status": {
|
|
84079
|
+
scope: "device",
|
|
84080
|
+
noun: t("Group", "Gruppo"),
|
|
84081
|
+
state: [
|
|
84082
|
+
{
|
|
84083
|
+
kind: "numeric",
|
|
84084
|
+
field: "included",
|
|
84085
|
+
quantity: t("the members reporting", "i membri che rispondono"),
|
|
84086
|
+
label: t("Reporting", "Rispondono"),
|
|
84087
|
+
icon: "users"
|
|
84088
|
+
},
|
|
84089
|
+
{
|
|
84090
|
+
kind: "numeric",
|
|
84091
|
+
field: "excluded",
|
|
84092
|
+
quantity: t("the members left out", "i membri esclusi"),
|
|
84093
|
+
label: t("Excluded", "Esclusi"),
|
|
84094
|
+
icon: "users"
|
|
84095
|
+
},
|
|
84096
|
+
{
|
|
84097
|
+
kind: "numeric",
|
|
84098
|
+
field: "total",
|
|
84099
|
+
quantity: t("the member count", "il numero di membri"),
|
|
84100
|
+
label: t("Members", "Membri"),
|
|
84101
|
+
icon: "sigma"
|
|
84102
|
+
}
|
|
84103
|
+
]
|
|
84104
|
+
},
|
|
83683
84105
|
"humidity-sensor": {
|
|
83684
84106
|
scope: "device",
|
|
83685
84107
|
noun: t("Humidity", "Umidità"),
|
|
@@ -83713,7 +84135,6 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83713
84135
|
field: "value",
|
|
83714
84136
|
quantity: t("the reading", "il valore"),
|
|
83715
84137
|
label: t("Reading", "Valore"),
|
|
83716
|
-
unitField: "unit",
|
|
83717
84138
|
icon: "gauge"
|
|
83718
84139
|
}]
|
|
83719
84140
|
},
|
|
@@ -83849,7 +84270,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83849
84270
|
field: "temperature",
|
|
83850
84271
|
quantity: t("the outdoor temperature", "la temperatura esterna"),
|
|
83851
84272
|
label: t("Temperature", "Temperatura"),
|
|
83852
|
-
|
|
84273
|
+
unit: "°C",
|
|
83853
84274
|
icon: "thermometer"
|
|
83854
84275
|
},
|
|
83855
84276
|
{
|
|
@@ -83865,7 +84286,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83865
84286
|
field: "windSpeed",
|
|
83866
84287
|
quantity: t("the wind speed", "la velocità del vento"),
|
|
83867
84288
|
label: t("Wind", "Vento"),
|
|
83868
|
-
|
|
84289
|
+
unit: "m/s",
|
|
83869
84290
|
icon: "wind"
|
|
83870
84291
|
},
|
|
83871
84292
|
{
|
|
@@ -83873,7 +84294,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83873
84294
|
field: "pressure",
|
|
83874
84295
|
quantity: t("the air pressure", "la pressione atmosferica"),
|
|
83875
84296
|
label: t("Pressure", "Pressione"),
|
|
83876
|
-
|
|
84297
|
+
unit: "hPa",
|
|
83877
84298
|
icon: "gauge"
|
|
83878
84299
|
}
|
|
83879
84300
|
]
|
|
@@ -85146,6 +85567,16 @@ Object.freeze({
|
|
|
85146
85567
|
form: "single",
|
|
85147
85568
|
optional: false
|
|
85148
85569
|
}],
|
|
85570
|
+
"groupCommands.getStatus": [{
|
|
85571
|
+
name: "deviceId",
|
|
85572
|
+
form: "single",
|
|
85573
|
+
optional: false
|
|
85574
|
+
}],
|
|
85575
|
+
"groupStatus.getStatus": [{
|
|
85576
|
+
name: "deviceId",
|
|
85577
|
+
form: "single",
|
|
85578
|
+
optional: false
|
|
85579
|
+
}],
|
|
85149
85580
|
"heatingValve.getStatus": [{
|
|
85150
85581
|
name: "deviceId",
|
|
85151
85582
|
form: "single",
|
|
@@ -87130,6 +87561,8 @@ new Map(Object.entries({
|
|
|
87130
87561
|
"detection-blind": "device-events",
|
|
87131
87562
|
"motion-noisy": "device-events",
|
|
87132
87563
|
"motion-calm": "device-events",
|
|
87564
|
+
"package-llm-silent": "device-events",
|
|
87565
|
+
"package-llm-answered": "device-events",
|
|
87133
87566
|
"recording-stalled": "device-events",
|
|
87134
87567
|
"recording-healthy": "device-events",
|
|
87135
87568
|
"recording-degraded": "device-events",
|
|
@@ -87213,6 +87646,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
|
|
|
87213
87646
|
label: "Motion without a subject",
|
|
87214
87647
|
kinds: ["motion-noisy", "motion-calm"]
|
|
87215
87648
|
},
|
|
87649
|
+
{
|
|
87650
|
+
id: "package-llm",
|
|
87651
|
+
family: "device-events",
|
|
87652
|
+
label: "Package confirm",
|
|
87653
|
+
kinds: ["package-llm-silent", "package-llm-answered"]
|
|
87654
|
+
},
|
|
87216
87655
|
{
|
|
87217
87656
|
id: "recording",
|
|
87218
87657
|
family: "device-events",
|
|
@@ -87394,6 +87833,8 @@ var DEVICE_EVENTS = [
|
|
|
87394
87833
|
"detection-blind",
|
|
87395
87834
|
"motion-noisy",
|
|
87396
87835
|
"motion-calm",
|
|
87836
|
+
"package-llm-silent",
|
|
87837
|
+
"package-llm-answered",
|
|
87397
87838
|
"recording-stalled",
|
|
87398
87839
|
"recording-healthy",
|
|
87399
87840
|
"recording-degraded",
|
|
@@ -87662,6 +88103,15 @@ new Map([
|
|
|
87662
88103
|
snapshotLabel: "Cameras with constant motion now",
|
|
87663
88104
|
snapshotSection: null
|
|
87664
88105
|
},
|
|
88106
|
+
{
|
|
88107
|
+
id: "package-llm-confirm",
|
|
88108
|
+
family: "device-events",
|
|
88109
|
+
label: "Package confirm (not answering / answering again)",
|
|
88110
|
+
bad: ["package-llm-silent"],
|
|
88111
|
+
recovery: ["package-llm-answered"],
|
|
88112
|
+
snapshotLabel: "Cameras whose package confirm is not answering",
|
|
88113
|
+
snapshotSection: null
|
|
88114
|
+
},
|
|
87665
88115
|
{
|
|
87666
88116
|
id: "recording-health",
|
|
87667
88117
|
family: "device-events",
|
|
@@ -88764,17 +89214,15 @@ function entityIdentity(descriptor) {
|
|
|
88764
89214
|
function slugifyKey(value) {
|
|
88765
89215
|
return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48);
|
|
88766
89216
|
}
|
|
88767
|
-
var PERCENT = "%";
|
|
88768
|
-
var WATT = "W";
|
|
88769
89217
|
/** Clamp a raw percentage into 0..100 (defensive — a hung feed can overshoot). */
|
|
88770
89218
|
function pct(value) {
|
|
88771
89219
|
if (!Number.isFinite(value)) return 0;
|
|
88772
89220
|
return Math.max(0, Math.min(100, value));
|
|
88773
89221
|
}
|
|
88774
|
-
/**
|
|
88775
|
-
function
|
|
88776
|
-
if (!Number.isFinite(
|
|
88777
|
-
return
|
|
89222
|
+
/** A byte count. Negative or non-finite input is an empty reading, not a guess. */
|
|
89223
|
+
function bytes(value) {
|
|
89224
|
+
if (!Number.isFinite(value) || value < 0) return 0;
|
|
89225
|
+
return value;
|
|
88778
89226
|
}
|
|
88779
89227
|
/** Array capacity + parity + CPU + notification-count metric descriptors. */
|
|
88780
89228
|
function arrayMetricDescriptors(snapshot) {
|
|
@@ -88801,8 +89249,7 @@ function arrayMetricDescriptors(snapshot) {
|
|
|
88801
89249
|
role: DeviceRole.NumericSensor,
|
|
88802
89250
|
numeric: {
|
|
88803
89251
|
value: usagePercent,
|
|
88804
|
-
|
|
88805
|
-
precision: 1
|
|
89252
|
+
quantity: "percentage"
|
|
88806
89253
|
}
|
|
88807
89254
|
},
|
|
88808
89255
|
{
|
|
@@ -88813,9 +89260,8 @@ function arrayMetricDescriptors(snapshot) {
|
|
|
88813
89260
|
name: "Array total",
|
|
88814
89261
|
role: DeviceRole.NumericSensor,
|
|
88815
89262
|
numeric: {
|
|
88816
|
-
value:
|
|
88817
|
-
|
|
88818
|
-
precision: 1
|
|
89263
|
+
value: bytes(totalKb * 1024),
|
|
89264
|
+
quantity: "information"
|
|
88819
89265
|
}
|
|
88820
89266
|
},
|
|
88821
89267
|
{
|
|
@@ -88826,9 +89272,8 @@ function arrayMetricDescriptors(snapshot) {
|
|
|
88826
89272
|
name: "Array used",
|
|
88827
89273
|
role: DeviceRole.NumericSensor,
|
|
88828
89274
|
numeric: {
|
|
88829
|
-
value:
|
|
88830
|
-
|
|
88831
|
-
precision: 1
|
|
89275
|
+
value: bytes(usedKb * 1024),
|
|
89276
|
+
quantity: "information"
|
|
88832
89277
|
}
|
|
88833
89278
|
},
|
|
88834
89279
|
{
|
|
@@ -88839,9 +89284,8 @@ function arrayMetricDescriptors(snapshot) {
|
|
|
88839
89284
|
name: "Array free",
|
|
88840
89285
|
role: DeviceRole.NumericSensor,
|
|
88841
89286
|
numeric: {
|
|
88842
|
-
value:
|
|
88843
|
-
|
|
88844
|
-
precision: 1
|
|
89287
|
+
value: bytes(array.capacityKb.free * 1024),
|
|
89288
|
+
quantity: "information"
|
|
88845
89289
|
}
|
|
88846
89290
|
},
|
|
88847
89291
|
{
|
|
@@ -88853,8 +89297,7 @@ function arrayMetricDescriptors(snapshot) {
|
|
|
88853
89297
|
role: DeviceRole.NumericSensor,
|
|
88854
89298
|
numeric: {
|
|
88855
89299
|
value: pct(cpu.percent),
|
|
88856
|
-
|
|
88857
|
-
precision: 1
|
|
89300
|
+
quantity: "percentage"
|
|
88858
89301
|
}
|
|
88859
89302
|
},
|
|
88860
89303
|
{
|
|
@@ -88866,8 +89309,7 @@ function arrayMetricDescriptors(snapshot) {
|
|
|
88866
89309
|
role: DeviceRole.NumericSensor,
|
|
88867
89310
|
numeric: {
|
|
88868
89311
|
value: pct(array.parityCheck?.progress ?? 0),
|
|
88869
|
-
|
|
88870
|
-
precision: 0
|
|
89312
|
+
quantity: "percentage"
|
|
88871
89313
|
}
|
|
88872
89314
|
},
|
|
88873
89315
|
{
|
|
@@ -88879,7 +89321,7 @@ function arrayMetricDescriptors(snapshot) {
|
|
|
88879
89321
|
role: DeviceRole.NumericSensor,
|
|
88880
89322
|
numeric: {
|
|
88881
89323
|
value: Math.max(0, notifications.activeCount),
|
|
88882
|
-
|
|
89324
|
+
quantity: "count"
|
|
88883
89325
|
}
|
|
88884
89326
|
}
|
|
88885
89327
|
];
|
|
@@ -88901,8 +89343,7 @@ function arrayMetricDescriptors(snapshot) {
|
|
|
88901
89343
|
role: DeviceRole.PowerSensor,
|
|
88902
89344
|
numeric: {
|
|
88903
89345
|
value: Math.max(0, cpu.powerW),
|
|
88904
|
-
|
|
88905
|
-
precision: 1
|
|
89346
|
+
quantity: "power"
|
|
88906
89347
|
}
|
|
88907
89348
|
});
|
|
88908
89349
|
return out;
|
|
@@ -88986,8 +89427,7 @@ function diskDescriptors(disks) {
|
|
|
88986
89427
|
role: DeviceRole.NumericSensor,
|
|
88987
89428
|
numeric: {
|
|
88988
89429
|
value: usagePercent,
|
|
88989
|
-
|
|
88990
|
-
precision: 1
|
|
89430
|
+
quantity: "percentage"
|
|
88991
89431
|
}
|
|
88992
89432
|
});
|
|
88993
89433
|
out.push({
|
|
@@ -89026,8 +89466,7 @@ function dockerDescriptors(containers) {
|
|
|
89026
89466
|
role: DeviceRole.NumericSensor,
|
|
89027
89467
|
numeric: {
|
|
89028
89468
|
value: pct(container.cpuPercent),
|
|
89029
|
-
|
|
89030
|
-
precision: 1
|
|
89469
|
+
quantity: "percentage"
|
|
89031
89470
|
}
|
|
89032
89471
|
});
|
|
89033
89472
|
out.push({
|
|
@@ -89039,8 +89478,7 @@ function dockerDescriptors(containers) {
|
|
|
89039
89478
|
role: DeviceRole.NumericSensor,
|
|
89040
89479
|
numeric: {
|
|
89041
89480
|
value: pct(container.memPercent),
|
|
89042
|
-
|
|
89043
|
-
precision: 1
|
|
89481
|
+
quantity: "percentage"
|
|
89044
89482
|
}
|
|
89045
89483
|
});
|
|
89046
89484
|
out.push(buttonDescriptor(`restart_container_${slug}`, `Restart ${container.name}`, {
|
|
@@ -89222,10 +89660,9 @@ var UnraidEntityDevice = class extends BaseDevice {
|
|
|
89222
89660
|
if (numeric === void 0) return;
|
|
89223
89661
|
const slice = {
|
|
89224
89662
|
value: numeric.value,
|
|
89225
|
-
lastFetchedAt: now
|
|
89226
|
-
...numeric.unit !== void 0 ? { unit: numeric.unit } : {},
|
|
89227
|
-
...numeric.precision !== void 0 ? { precision: numeric.precision } : {}
|
|
89663
|
+
lastFetchedAt: now
|
|
89228
89664
|
};
|
|
89665
|
+
if (this.sourceInfo.quantity !== numeric.quantity) this.updateSourceInfo({ quantity: numeric.quantity });
|
|
89229
89666
|
this.runtimeState.setCapState(numericSensorCapability.name, slice);
|
|
89230
89667
|
return;
|
|
89231
89668
|
}
|