@camstack/addon-terminal 0.1.153 → 0.1.154
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +19 -0
- package/dist/addon.js +959 -509
- package/dist/addon.mjs +959 -509
- package/package.json +4 -2
package/dist/addon.js
CHANGED
|
@@ -31,7 +31,7 @@ let node_module = require("node:module");
|
|
|
31
31
|
let sharp = require("sharp");
|
|
32
32
|
sharp = __toESM(sharp);
|
|
33
33
|
let node_http = require("node:http");
|
|
34
|
-
//#region ../types/dist/event-category-
|
|
34
|
+
//#region ../types/dist/event-category-CT-hz5Rb.mjs
|
|
35
35
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
36
36
|
EventCategory["SystemBoot"] = "system.boot";
|
|
37
37
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -357,6 +357,14 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
357
357
|
/** The recovery edge of {@link PipelineMotionNoisy}: the motion fell back, or a detection arrived. */
|
|
358
358
|
EventCategory["PipelineMotionCalm"] = "pipeline.motion-calm";
|
|
359
359
|
/**
|
|
360
|
+
* A camera's package LLM confirm has failed closed three times in a row
|
|
361
|
+
* (D931, 2026-10-26). One edge per camera until
|
|
362
|
+
* {@link PipelinePackageLlmAnswered}.
|
|
363
|
+
*/
|
|
364
|
+
EventCategory["PipelinePackageLlmSilent"] = "pipeline.package-llm-silent";
|
|
365
|
+
/** The recovery edge of {@link PipelinePackageLlmSilent}: a confirm returned yes or no. */
|
|
366
|
+
EventCategory["PipelinePackageLlmAnswered"] = "pipeline.package-llm-answered";
|
|
367
|
+
/**
|
|
360
368
|
* Per-camera pipeline config was mutated by the orchestrator
|
|
361
369
|
* (a settings change via `setAgentInferenceDevices` /
|
|
362
370
|
* `setCameraStepToggle` / `setCameraStepSettings`). Orchestrator
|
|
@@ -5466,7 +5474,7 @@ var ZodIssueCode = {
|
|
|
5466
5474
|
var ZodFirstPartyTypeKind;
|
|
5467
5475
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5468
5476
|
//#endregion
|
|
5469
|
-
//#region ../types/dist/sleep-
|
|
5477
|
+
//#region ../types/dist/sleep-bykKrTgu.mjs
|
|
5470
5478
|
/**
|
|
5471
5479
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5472
5480
|
* window to float samples (D455).
|
|
@@ -8020,6 +8028,99 @@ var RecordKindDeclarationSchema = object({
|
|
|
8020
8028
|
}).strict();
|
|
8021
8029
|
/** The kind names: lower-case, dash separated, short enough for an index name. */
|
|
8022
8030
|
var RecordKindNameSchema = string().regex(/^[a-z][a-z0-9-]{0,47}$/);
|
|
8031
|
+
var READING_QUANTITIES = [
|
|
8032
|
+
"temperature",
|
|
8033
|
+
"pressure",
|
|
8034
|
+
"speed",
|
|
8035
|
+
"precipitation",
|
|
8036
|
+
"precipitation-rate",
|
|
8037
|
+
"length",
|
|
8038
|
+
"area",
|
|
8039
|
+
"illuminance",
|
|
8040
|
+
"irradiance",
|
|
8041
|
+
"power",
|
|
8042
|
+
"energy",
|
|
8043
|
+
"voltage",
|
|
8044
|
+
"current",
|
|
8045
|
+
"apparent-power",
|
|
8046
|
+
"humidity",
|
|
8047
|
+
"percentage",
|
|
8048
|
+
"concentration-volume",
|
|
8049
|
+
"concentration-mass",
|
|
8050
|
+
"concentration-ppb",
|
|
8051
|
+
"volume",
|
|
8052
|
+
"duration",
|
|
8053
|
+
"duration-ms",
|
|
8054
|
+
"information",
|
|
8055
|
+
"sound-level",
|
|
8056
|
+
"signal-level",
|
|
8057
|
+
"colour-temperature",
|
|
8058
|
+
"angle",
|
|
8059
|
+
"bitrate",
|
|
8060
|
+
"rate",
|
|
8061
|
+
"mass",
|
|
8062
|
+
"index",
|
|
8063
|
+
"ratio",
|
|
8064
|
+
"count",
|
|
8065
|
+
"none",
|
|
8066
|
+
"device"
|
|
8067
|
+
];
|
|
8068
|
+
var ReadingQuantitySchema = _enum(READING_QUANTITIES);
|
|
8069
|
+
new Set(READING_QUANTITIES);
|
|
8070
|
+
/**
|
|
8071
|
+
* Stored unit symbol for a quantity. `none` means the number is dimensionless
|
|
8072
|
+
* (or an index / ratio / count). `device` means the cap has no single unit.
|
|
8073
|
+
*/
|
|
8074
|
+
var QUANTITY_BASE = {
|
|
8075
|
+
temperature: "°C",
|
|
8076
|
+
pressure: "hPa",
|
|
8077
|
+
speed: "m/s",
|
|
8078
|
+
precipitation: "mm",
|
|
8079
|
+
"precipitation-rate": "mm/h",
|
|
8080
|
+
length: "m",
|
|
8081
|
+
area: "m²",
|
|
8082
|
+
illuminance: "lx",
|
|
8083
|
+
irradiance: "W/m²",
|
|
8084
|
+
power: "W",
|
|
8085
|
+
energy: "kWh",
|
|
8086
|
+
voltage: "V",
|
|
8087
|
+
current: "A",
|
|
8088
|
+
"apparent-power": "VA",
|
|
8089
|
+
humidity: "%",
|
|
8090
|
+
percentage: "%",
|
|
8091
|
+
"concentration-volume": "ppm",
|
|
8092
|
+
"concentration-mass": "µg/m³",
|
|
8093
|
+
"concentration-ppb": "ppb",
|
|
8094
|
+
volume: "L",
|
|
8095
|
+
duration: "s",
|
|
8096
|
+
"duration-ms": "ms",
|
|
8097
|
+
information: "B",
|
|
8098
|
+
"sound-level": "dBFS",
|
|
8099
|
+
"signal-level": "dBm",
|
|
8100
|
+
"colour-temperature": "mired",
|
|
8101
|
+
angle: "°",
|
|
8102
|
+
bitrate: "kbps",
|
|
8103
|
+
rate: "fps",
|
|
8104
|
+
mass: "kg",
|
|
8105
|
+
index: "none",
|
|
8106
|
+
ratio: "none",
|
|
8107
|
+
count: "none",
|
|
8108
|
+
none: "none",
|
|
8109
|
+
device: "device"
|
|
8110
|
+
};
|
|
8111
|
+
/** The stored unit, or `undefined` when the quantity has no unit symbol. */
|
|
8112
|
+
function baseUnitOf(quantity) {
|
|
8113
|
+
const symbol = QUANTITY_BASE[quantity];
|
|
8114
|
+
if (symbol === "none" || symbol === "device") return void 0;
|
|
8115
|
+
return symbol;
|
|
8116
|
+
}
|
|
8117
|
+
function readingMeta(quantity, extras) {
|
|
8118
|
+
return {
|
|
8119
|
+
quantity,
|
|
8120
|
+
...extras?.precision !== void 0 ? { precision: extras.precision } : {},
|
|
8121
|
+
...extras?.label !== void 0 ? { label: extras.label } : {}
|
|
8122
|
+
};
|
|
8123
|
+
}
|
|
8023
8124
|
/** Shared Zod schemas used across streaming capabilities. */
|
|
8024
8125
|
var CamProfileSchema = _enum([
|
|
8025
8126
|
"high",
|
|
@@ -8047,8 +8148,8 @@ var CamStreamKindSchema = _enum([
|
|
|
8047
8148
|
"derived"
|
|
8048
8149
|
]);
|
|
8049
8150
|
var CamStreamResolutionSchema = object({
|
|
8050
|
-
width: number().int().positive(),
|
|
8051
|
-
height: number().int().positive()
|
|
8151
|
+
width: number().int().positive().meta(readingMeta("none")),
|
|
8152
|
+
height: number().int().positive().meta(readingMeta("none"))
|
|
8052
8153
|
});
|
|
8053
8154
|
var CameraStreamSchema = object({
|
|
8054
8155
|
/** Stable, provider-assigned id unique within the (deviceId) scope. */
|
|
@@ -8625,6 +8726,8 @@ var CAP_NAMES = Object.freeze([
|
|
|
8625
8726
|
"filesystem-browse",
|
|
8626
8727
|
"flood",
|
|
8627
8728
|
"gas",
|
|
8729
|
+
"group-commands",
|
|
8730
|
+
"group-status",
|
|
8628
8731
|
"heating-valve",
|
|
8629
8732
|
"humidifier",
|
|
8630
8733
|
"humidity-sensor",
|
|
@@ -8754,14 +8857,6 @@ Object.freeze({
|
|
|
8754
8857
|
{
|
|
8755
8858
|
"path": "aqi",
|
|
8756
8859
|
"valueType": "number"
|
|
8757
|
-
},
|
|
8758
|
-
{
|
|
8759
|
-
"path": "unit",
|
|
8760
|
-
"valueType": "string"
|
|
8761
|
-
},
|
|
8762
|
-
{
|
|
8763
|
-
"path": "precision",
|
|
8764
|
-
"valueType": "number"
|
|
8765
8860
|
}
|
|
8766
8861
|
],
|
|
8767
8862
|
"alarm-panel": [
|
|
@@ -8797,20 +8892,10 @@ Object.freeze({
|
|
|
8797
8892
|
"valueType": "boolean"
|
|
8798
8893
|
}
|
|
8799
8894
|
],
|
|
8800
|
-
"ambient-light-sensor": [
|
|
8801
|
-
|
|
8802
|
-
|
|
8803
|
-
|
|
8804
|
-
},
|
|
8805
|
-
{
|
|
8806
|
-
"path": "unit",
|
|
8807
|
-
"valueType": "string"
|
|
8808
|
-
},
|
|
8809
|
-
{
|
|
8810
|
-
"path": "precision",
|
|
8811
|
-
"valueType": "number"
|
|
8812
|
-
}
|
|
8813
|
-
],
|
|
8895
|
+
"ambient-light-sensor": [{
|
|
8896
|
+
"path": "lux",
|
|
8897
|
+
"valueType": "number"
|
|
8898
|
+
}],
|
|
8814
8899
|
"audio-metrics": [
|
|
8815
8900
|
{
|
|
8816
8901
|
"path": "ts",
|
|
@@ -8890,6 +8975,10 @@ Object.freeze({
|
|
|
8890
8975
|
"path": "lastUpdated",
|
|
8891
8976
|
"valueType": "number"
|
|
8892
8977
|
},
|
|
8978
|
+
{
|
|
8979
|
+
"path": "volts",
|
|
8980
|
+
"valueType": "number"
|
|
8981
|
+
},
|
|
8893
8982
|
{
|
|
8894
8983
|
"path": "lastContactAt",
|
|
8895
8984
|
"valueType": "number"
|
|
@@ -9132,10 +9221,6 @@ Object.freeze({
|
|
|
9132
9221
|
"datetime"
|
|
9133
9222
|
]
|
|
9134
9223
|
},
|
|
9135
|
-
{
|
|
9136
|
-
"path": "unit",
|
|
9137
|
-
"valueType": "string"
|
|
9138
|
-
},
|
|
9139
9224
|
{
|
|
9140
9225
|
"path": "min",
|
|
9141
9226
|
"valueType": "number"
|
|
@@ -9147,19 +9232,6 @@ Object.freeze({
|
|
|
9147
9232
|
{
|
|
9148
9233
|
"path": "step",
|
|
9149
9234
|
"valueType": "number"
|
|
9150
|
-
},
|
|
9151
|
-
{
|
|
9152
|
-
"path": "precision",
|
|
9153
|
-
"valueType": "number"
|
|
9154
|
-
},
|
|
9155
|
-
{
|
|
9156
|
-
"path": "format",
|
|
9157
|
-
"valueType": "enum",
|
|
9158
|
-
"enumValues": [
|
|
9159
|
-
"date",
|
|
9160
|
-
"time",
|
|
9161
|
-
"datetime"
|
|
9162
|
-
]
|
|
9163
9235
|
}
|
|
9164
9236
|
],
|
|
9165
9237
|
"cover": [
|
|
@@ -9400,13 +9472,8 @@ Object.freeze({
|
|
|
9400
9472
|
"path": "value",
|
|
9401
9473
|
"valueType": "string"
|
|
9402
9474
|
}, {
|
|
9403
|
-
"path": "
|
|
9404
|
-
"valueType": "
|
|
9405
|
-
"enumValues": [
|
|
9406
|
-
"date",
|
|
9407
|
-
"time",
|
|
9408
|
-
"datetime"
|
|
9409
|
-
]
|
|
9475
|
+
"path": "timestamp",
|
|
9476
|
+
"valueType": "boolean"
|
|
9410
9477
|
}],
|
|
9411
9478
|
"event-emitter": [
|
|
9412
9479
|
{
|
|
@@ -9479,6 +9546,20 @@ Object.freeze({
|
|
|
9479
9546
|
"path": "detected",
|
|
9480
9547
|
"valueType": "boolean"
|
|
9481
9548
|
}],
|
|
9549
|
+
"group-status": [
|
|
9550
|
+
{
|
|
9551
|
+
"path": "included",
|
|
9552
|
+
"valueType": "number"
|
|
9553
|
+
},
|
|
9554
|
+
{
|
|
9555
|
+
"path": "excluded",
|
|
9556
|
+
"valueType": "number"
|
|
9557
|
+
},
|
|
9558
|
+
{
|
|
9559
|
+
"path": "total",
|
|
9560
|
+
"valueType": "number"
|
|
9561
|
+
}
|
|
9562
|
+
],
|
|
9482
9563
|
"heating-valve": [{
|
|
9483
9564
|
"path": "position",
|
|
9484
9565
|
"valueType": "number"
|
|
@@ -9513,20 +9594,10 @@ Object.freeze({
|
|
|
9513
9594
|
"valueType": "number"
|
|
9514
9595
|
}
|
|
9515
9596
|
],
|
|
9516
|
-
"humidity-sensor": [
|
|
9517
|
-
|
|
9518
|
-
|
|
9519
|
-
|
|
9520
|
-
},
|
|
9521
|
-
{
|
|
9522
|
-
"path": "unit",
|
|
9523
|
-
"valueType": "string"
|
|
9524
|
-
},
|
|
9525
|
-
{
|
|
9526
|
-
"path": "precision",
|
|
9527
|
-
"valueType": "number"
|
|
9528
|
-
}
|
|
9529
|
-
],
|
|
9597
|
+
"humidity-sensor": [{
|
|
9598
|
+
"path": "percent",
|
|
9599
|
+
"valueType": "number"
|
|
9600
|
+
}],
|
|
9530
9601
|
"image": [{
|
|
9531
9602
|
"path": "url",
|
|
9532
9603
|
"valueType": "string"
|
|
@@ -9865,20 +9936,10 @@ Object.freeze({
|
|
|
9865
9936
|
"valueType": "boolean"
|
|
9866
9937
|
}
|
|
9867
9938
|
],
|
|
9868
|
-
"numeric-sensor": [
|
|
9869
|
-
|
|
9870
|
-
|
|
9871
|
-
|
|
9872
|
-
},
|
|
9873
|
-
{
|
|
9874
|
-
"path": "unit",
|
|
9875
|
-
"valueType": "string"
|
|
9876
|
-
},
|
|
9877
|
-
{
|
|
9878
|
-
"path": "precision",
|
|
9879
|
-
"valueType": "number"
|
|
9880
|
-
}
|
|
9881
|
-
],
|
|
9939
|
+
"numeric-sensor": [{
|
|
9940
|
+
"path": "value",
|
|
9941
|
+
"valueType": "number"
|
|
9942
|
+
}],
|
|
9882
9943
|
"pet-feeder": [
|
|
9883
9944
|
{
|
|
9884
9945
|
"path": "foodLevel",
|
|
@@ -9970,14 +10031,6 @@ Object.freeze({
|
|
|
9970
10031
|
{
|
|
9971
10032
|
"path": "powerFactor",
|
|
9972
10033
|
"valueType": "number"
|
|
9973
|
-
},
|
|
9974
|
-
{
|
|
9975
|
-
"path": "unit",
|
|
9976
|
-
"valueType": "string"
|
|
9977
|
-
},
|
|
9978
|
-
{
|
|
9979
|
-
"path": "precision",
|
|
9980
|
-
"valueType": "number"
|
|
9981
10034
|
}
|
|
9982
10035
|
],
|
|
9983
10036
|
"presence": [
|
|
@@ -10006,20 +10059,10 @@ Object.freeze({
|
|
|
10006
10059
|
"valueType": "number"
|
|
10007
10060
|
}
|
|
10008
10061
|
],
|
|
10009
|
-
"pressure-sensor": [
|
|
10010
|
-
|
|
10011
|
-
|
|
10012
|
-
|
|
10013
|
-
},
|
|
10014
|
-
{
|
|
10015
|
-
"path": "unit",
|
|
10016
|
-
"valueType": "string"
|
|
10017
|
-
},
|
|
10018
|
-
{
|
|
10019
|
-
"path": "precision",
|
|
10020
|
-
"valueType": "number"
|
|
10021
|
-
}
|
|
10022
|
-
],
|
|
10062
|
+
"pressure-sensor": [{
|
|
10063
|
+
"path": "hpa",
|
|
10064
|
+
"valueType": "number"
|
|
10065
|
+
}],
|
|
10023
10066
|
"privacy-mask": [{
|
|
10024
10067
|
"path": "enabled",
|
|
10025
10068
|
"valueType": "boolean"
|
|
@@ -10330,20 +10373,10 @@ Object.freeze({
|
|
|
10330
10373
|
"path": "tampered",
|
|
10331
10374
|
"valueType": "boolean"
|
|
10332
10375
|
}],
|
|
10333
|
-
"temperature-sensor": [
|
|
10334
|
-
|
|
10335
|
-
|
|
10336
|
-
|
|
10337
|
-
},
|
|
10338
|
-
{
|
|
10339
|
-
"path": "unit",
|
|
10340
|
-
"valueType": "string"
|
|
10341
|
-
},
|
|
10342
|
-
{
|
|
10343
|
-
"path": "precision",
|
|
10344
|
-
"valueType": "number"
|
|
10345
|
-
}
|
|
10346
|
-
],
|
|
10376
|
+
"temperature-sensor": [{
|
|
10377
|
+
"path": "celsius",
|
|
10378
|
+
"valueType": "number"
|
|
10379
|
+
}],
|
|
10347
10380
|
"update": [
|
|
10348
10381
|
{
|
|
10349
10382
|
"path": "currentVersion",
|
|
@@ -10454,10 +10487,6 @@ Object.freeze({
|
|
|
10454
10487
|
"path": "temperature",
|
|
10455
10488
|
"valueType": "number"
|
|
10456
10489
|
},
|
|
10457
|
-
{
|
|
10458
|
-
"path": "temperatureUnit",
|
|
10459
|
-
"valueType": "string"
|
|
10460
|
-
},
|
|
10461
10490
|
{
|
|
10462
10491
|
"path": "humidity",
|
|
10463
10492
|
"valueType": "number"
|
|
@@ -10466,18 +10495,10 @@ Object.freeze({
|
|
|
10466
10495
|
"path": "pressure",
|
|
10467
10496
|
"valueType": "number"
|
|
10468
10497
|
},
|
|
10469
|
-
{
|
|
10470
|
-
"path": "pressureUnit",
|
|
10471
|
-
"valueType": "string"
|
|
10472
|
-
},
|
|
10473
10498
|
{
|
|
10474
10499
|
"path": "windSpeed",
|
|
10475
10500
|
"valueType": "number"
|
|
10476
10501
|
},
|
|
10477
|
-
{
|
|
10478
|
-
"path": "windSpeedUnit",
|
|
10479
|
-
"valueType": "string"
|
|
10480
|
-
},
|
|
10481
10502
|
{
|
|
10482
10503
|
"path": "windBearing",
|
|
10483
10504
|
"valueType": "number"
|
|
@@ -10880,7 +10901,7 @@ function errMsg(err) {
|
|
|
10880
10901
|
return String(err);
|
|
10881
10902
|
}
|
|
10882
10903
|
//#endregion
|
|
10883
|
-
//#region ../types/dist/composition-
|
|
10904
|
+
//#region ../types/dist/composition-OhpuespA.mjs
|
|
10884
10905
|
/**
|
|
10885
10906
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
10886
10907
|
*
|
|
@@ -11635,15 +11656,74 @@ function validateExpressionSource(src) {
|
|
|
11635
11656
|
}
|
|
11636
11657
|
return null;
|
|
11637
11658
|
}
|
|
11638
|
-
/**
|
|
11639
|
-
|
|
11640
|
-
|
|
11641
|
-
|
|
11659
|
+
/**
|
|
11660
|
+
* A composition source identity: `(addonId, stableId)`, never a numeric device
|
|
11661
|
+
* id. Split out so helper schemas can name it without a cycle through
|
|
11662
|
+
* `composition.ts` (D659).
|
|
11663
|
+
*/
|
|
11642
11664
|
var CompositionSourceRefSchema = object({
|
|
11643
11665
|
/** The owning addon; `stableId` is unique only within it. */
|
|
11644
11666
|
addonId: string().min(1),
|
|
11645
11667
|
stableId: string().min(1)
|
|
11646
11668
|
});
|
|
11669
|
+
var GROUP_TEMPLATE_IDS = [
|
|
11670
|
+
"temperature",
|
|
11671
|
+
"humidity",
|
|
11672
|
+
"pressure",
|
|
11673
|
+
"illuminance",
|
|
11674
|
+
"power",
|
|
11675
|
+
"energy",
|
|
11676
|
+
"battery",
|
|
11677
|
+
"numeric",
|
|
11678
|
+
"motion",
|
|
11679
|
+
"contact",
|
|
11680
|
+
"leak",
|
|
11681
|
+
"smoke",
|
|
11682
|
+
"occupancy",
|
|
11683
|
+
"binary",
|
|
11684
|
+
"switch",
|
|
11685
|
+
"light"
|
|
11686
|
+
];
|
|
11687
|
+
var NUMERIC_AGGREGATES = [
|
|
11688
|
+
"mean",
|
|
11689
|
+
"median",
|
|
11690
|
+
"min",
|
|
11691
|
+
"max",
|
|
11692
|
+
"sum"
|
|
11693
|
+
];
|
|
11694
|
+
var BINARY_AGGREGATES = ["any", "all"];
|
|
11695
|
+
/** How an actuator group decides it is on. Unknown members never count as off. */
|
|
11696
|
+
var ACTIVE_CRITERIA = ["at-least-one", "all"];
|
|
11697
|
+
var AGGREGATE_REDUCERS = [
|
|
11698
|
+
"mean",
|
|
11699
|
+
"median",
|
|
11700
|
+
"min",
|
|
11701
|
+
"max",
|
|
11702
|
+
"sum",
|
|
11703
|
+
"any",
|
|
11704
|
+
"all"
|
|
11705
|
+
];
|
|
11706
|
+
var GroupTemplateIdSchema = _enum(GROUP_TEMPLATE_IDS);
|
|
11707
|
+
var AggregateReducerSchema = _enum(AGGREGATE_REDUCERS);
|
|
11708
|
+
var ActiveCriterionSchema = _enum(ACTIVE_CRITERIA);
|
|
11709
|
+
/** One member. The field is stored so occupancy can name motion or binary. */
|
|
11710
|
+
var HelperMemberSchema = object({
|
|
11711
|
+
source: CompositionSourceRefSchema,
|
|
11712
|
+
cap: string().min(1),
|
|
11713
|
+
fieldPath: string().min(1)
|
|
11714
|
+
});
|
|
11715
|
+
var HelperSpecSchema = discriminatedUnion("kind", [object({
|
|
11716
|
+
kind: literal("group"),
|
|
11717
|
+
templateId: GroupTemplateIdSchema,
|
|
11718
|
+
aggregate: AggregateReducerSchema,
|
|
11719
|
+
members: array(HelperMemberSchema).min(1).max(64),
|
|
11720
|
+
/** Actuator groups only. Readings leave this unset. */
|
|
11721
|
+
active: ActiveCriterionSchema.optional()
|
|
11722
|
+
})]);
|
|
11723
|
+
/** A composed device's stableId is this prefix plus the block id. */
|
|
11724
|
+
var COMPOSED_DEVICE_STABLE_ID_PREFIX = "composed-";
|
|
11725
|
+
/** Longest snippet a `code` source may carry (slice 4). */
|
|
11726
|
+
var MAX_COMPOSITION_CODE_LENGTH = 2e4;
|
|
11647
11727
|
/** One field of one capability of one source device. */
|
|
11648
11728
|
var CompositionFieldReadSchema = object({
|
|
11649
11729
|
source: CompositionSourceRefSchema,
|
|
@@ -11687,7 +11767,33 @@ var CompositionCodeSourceSchema = object({
|
|
|
11687
11767
|
var CompositionFieldSourceSchema = discriminatedUnion("kind", [
|
|
11688
11768
|
CompositionFromSourceSchema,
|
|
11689
11769
|
CompositionExpressionSourceSchema,
|
|
11690
|
-
CompositionCodeSourceSchema
|
|
11770
|
+
CompositionCodeSourceSchema,
|
|
11771
|
+
object({
|
|
11772
|
+
kind: literal("aggregate"),
|
|
11773
|
+
reducer: _enum([
|
|
11774
|
+
"mean",
|
|
11775
|
+
"median",
|
|
11776
|
+
"min",
|
|
11777
|
+
"max",
|
|
11778
|
+
"sum",
|
|
11779
|
+
"any",
|
|
11780
|
+
"all"
|
|
11781
|
+
]),
|
|
11782
|
+
reads: array(CompositionFieldReadSchema).min(1).max(64),
|
|
11783
|
+
/** `value` is the reading; the others are the member counts. */
|
|
11784
|
+
publish: _enum([
|
|
11785
|
+
"value",
|
|
11786
|
+
"included",
|
|
11787
|
+
"excluded",
|
|
11788
|
+
"total"
|
|
11789
|
+
]),
|
|
11790
|
+
/** What a `value` publish does when nobody is included. Counts ignore this. */
|
|
11791
|
+
empty: _enum([
|
|
11792
|
+
"null",
|
|
11793
|
+
"omit",
|
|
11794
|
+
"offline"
|
|
11795
|
+
])
|
|
11796
|
+
})
|
|
11691
11797
|
]);
|
|
11692
11798
|
var CompositionCommandTargetSchema = discriminatedUnion("kind", [object({
|
|
11693
11799
|
kind: literal("forward"),
|
|
@@ -11733,7 +11839,13 @@ var CompositionSchema = object({
|
|
|
11733
11839
|
kind: literal("existing"),
|
|
11734
11840
|
device: CompositionSourceRefSchema
|
|
11735
11841
|
})]),
|
|
11736
|
-
features: array(CompositionFeatureSchema).min(1).max(16)
|
|
11842
|
+
features: array(CompositionFeatureSchema).min(1).max(16),
|
|
11843
|
+
/**
|
|
11844
|
+
* Present when the block is a helper template. Absent on a free
|
|
11845
|
+
* composition (the room example, device 4603). The editor reads this,
|
|
11846
|
+
* never the compiled features.
|
|
11847
|
+
*/
|
|
11848
|
+
helper: HelperSpecSchema.optional()
|
|
11737
11849
|
}).superRefine((composition, ctx) => {
|
|
11738
11850
|
const seen = /* @__PURE__ */ new Set();
|
|
11739
11851
|
composition.features.forEach((feature, index) => {
|
|
@@ -17973,7 +18085,11 @@ var CompositionProblemSchema = object({
|
|
|
17973
18085
|
"item-field-reserved",
|
|
17974
18086
|
"target-missing",
|
|
17975
18087
|
"target-unreadable",
|
|
17976
|
-
"not-replaceable"
|
|
18088
|
+
"not-replaceable",
|
|
18089
|
+
"native-capability-replace",
|
|
18090
|
+
"mixed-quantity",
|
|
18091
|
+
"helper-mismatch",
|
|
18092
|
+
"member-constraint"
|
|
17977
18093
|
]),
|
|
17978
18094
|
path: string(),
|
|
17979
18095
|
message: string()
|
|
@@ -17994,7 +18110,8 @@ var CompositionUnavailableModeSchema = _enum([
|
|
|
17994
18110
|
"null",
|
|
17995
18111
|
"offline",
|
|
17996
18112
|
"unknown",
|
|
17997
|
-
"release"
|
|
18113
|
+
"release",
|
|
18114
|
+
"omit"
|
|
17998
18115
|
]);
|
|
17999
18116
|
/**
|
|
18000
18117
|
* `derived` reads a source · `clock` reads only `now`, recomputed when a sibling
|
|
@@ -18031,9 +18148,11 @@ var CompositionFieldPlanSchema = object({
|
|
|
18031
18148
|
reads: array(CompositionFieldReadSchema)
|
|
18032
18149
|
});
|
|
18033
18150
|
/**
|
|
18034
|
-
* What a feature does to its target (D663): `new` builds a capability on a
|
|
18035
|
-
* device; on an existing device it `add`s a capability the device lacks
|
|
18036
|
-
*
|
|
18151
|
+
* What a feature does to its target (D663, D944): `new` builds a capability on a
|
|
18152
|
+
* new device; on an existing device it `add`s a capability the device lacks.
|
|
18153
|
+
* Replacing a capability the device already serves is refused
|
|
18154
|
+
* (`native-capability-replace`), not planned. `replace` remains on the claim
|
|
18155
|
+
* wire for a claim the hub already holds.
|
|
18037
18156
|
*/
|
|
18038
18157
|
var CompositionFeatureModeSchema = _enum([
|
|
18039
18158
|
"new",
|
|
@@ -18206,6 +18325,275 @@ Object.freeze({
|
|
|
18206
18325
|
result: ["number", "null"]
|
|
18207
18326
|
}
|
|
18208
18327
|
});
|
|
18328
|
+
/**
|
|
18329
|
+
* One catalog row per base reading a group helper can build (D944 §3).
|
|
18330
|
+
* Data, not a form default written into the block.
|
|
18331
|
+
*/
|
|
18332
|
+
var NOW = {
|
|
18333
|
+
fieldPath: "lastFetchedAt",
|
|
18334
|
+
expr: "now"
|
|
18335
|
+
};
|
|
18336
|
+
var CHANGED = {
|
|
18337
|
+
fieldPath: "lastChangedAt",
|
|
18338
|
+
expr: "now"
|
|
18339
|
+
};
|
|
18340
|
+
function numeric(input) {
|
|
18341
|
+
return {
|
|
18342
|
+
...input,
|
|
18343
|
+
family: "numeric",
|
|
18344
|
+
deviceType: DeviceType.Sensor,
|
|
18345
|
+
memberDeviceType: DeviceType.Sensor,
|
|
18346
|
+
commandCaps: [],
|
|
18347
|
+
baseUnit: baseUnitOf(input.quantity),
|
|
18348
|
+
aggregates: NUMERIC_AGGREGATES,
|
|
18349
|
+
accept: [{
|
|
18350
|
+
cap: input.outputCap,
|
|
18351
|
+
fieldPath: input.outputField
|
|
18352
|
+
}]
|
|
18353
|
+
};
|
|
18354
|
+
}
|
|
18355
|
+
function binary(input) {
|
|
18356
|
+
return {
|
|
18357
|
+
...input,
|
|
18358
|
+
family: "binary",
|
|
18359
|
+
deviceType: DeviceType.Sensor,
|
|
18360
|
+
memberDeviceType: DeviceType.Sensor,
|
|
18361
|
+
commandCaps: [],
|
|
18362
|
+
quantity: "none",
|
|
18363
|
+
baseUnit: void 0,
|
|
18364
|
+
aggregates: BINARY_AGGREGATES,
|
|
18365
|
+
empty: "offline"
|
|
18366
|
+
};
|
|
18367
|
+
}
|
|
18368
|
+
var GROUP_TEMPLATES = [
|
|
18369
|
+
numeric({
|
|
18370
|
+
id: "temperature",
|
|
18371
|
+
summary: "Mean, median, min, max or sum of temperatures. Offline and unknown members are left out, never read as 0 °C.",
|
|
18372
|
+
role: DeviceRole.TemperatureSensor,
|
|
18373
|
+
outputCap: "temperature-sensor",
|
|
18374
|
+
outputField: "celsius",
|
|
18375
|
+
quantity: "temperature",
|
|
18376
|
+
defaultAggregate: "mean",
|
|
18377
|
+
empty: "null",
|
|
18378
|
+
companions: [NOW]
|
|
18379
|
+
}),
|
|
18380
|
+
numeric({
|
|
18381
|
+
id: "humidity",
|
|
18382
|
+
summary: "Humidity in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
18383
|
+
role: DeviceRole.HumiditySensor,
|
|
18384
|
+
outputCap: "humidity-sensor",
|
|
18385
|
+
outputField: "percent",
|
|
18386
|
+
quantity: "humidity",
|
|
18387
|
+
defaultAggregate: "mean",
|
|
18388
|
+
empty: "null",
|
|
18389
|
+
companions: [NOW]
|
|
18390
|
+
}),
|
|
18391
|
+
numeric({
|
|
18392
|
+
id: "pressure",
|
|
18393
|
+
summary: "Pressure in hectopascals. Offline and unknown members are left out, never read as 0 hPa.",
|
|
18394
|
+
role: DeviceRole.PressureSensor,
|
|
18395
|
+
outputCap: "pressure-sensor",
|
|
18396
|
+
outputField: "hpa",
|
|
18397
|
+
quantity: "pressure",
|
|
18398
|
+
defaultAggregate: "mean",
|
|
18399
|
+
empty: "null",
|
|
18400
|
+
companions: [NOW]
|
|
18401
|
+
}),
|
|
18402
|
+
numeric({
|
|
18403
|
+
id: "illuminance",
|
|
18404
|
+
summary: "Illuminance in lux. Offline and unknown members are left out, never read as 0 lx.",
|
|
18405
|
+
role: DeviceRole.AmbientLightSensor,
|
|
18406
|
+
outputCap: "ambient-light-sensor",
|
|
18407
|
+
outputField: "lux",
|
|
18408
|
+
quantity: "illuminance",
|
|
18409
|
+
defaultAggregate: "mean",
|
|
18410
|
+
empty: "null",
|
|
18411
|
+
companions: [NOW]
|
|
18412
|
+
}),
|
|
18413
|
+
numeric({
|
|
18414
|
+
id: "power",
|
|
18415
|
+
summary: "Power in watts, summed by default. Nobody reporting omits the key rather than writing 0 W.",
|
|
18416
|
+
role: DeviceRole.PowerSensor,
|
|
18417
|
+
outputCap: "power-meter",
|
|
18418
|
+
outputField: "watts",
|
|
18419
|
+
quantity: "power",
|
|
18420
|
+
defaultAggregate: "sum",
|
|
18421
|
+
empty: "omit",
|
|
18422
|
+
companions: [NOW]
|
|
18423
|
+
}),
|
|
18424
|
+
numeric({
|
|
18425
|
+
id: "energy",
|
|
18426
|
+
summary: "Energy in kilowatt-hours, summed by default. Nobody reporting omits the key rather than writing 0 kWh.",
|
|
18427
|
+
role: DeviceRole.EnergySensor,
|
|
18428
|
+
outputCap: "power-meter",
|
|
18429
|
+
outputField: "kwhTotal",
|
|
18430
|
+
quantity: "energy",
|
|
18431
|
+
defaultAggregate: "sum",
|
|
18432
|
+
empty: "omit",
|
|
18433
|
+
companions: [NOW]
|
|
18434
|
+
}),
|
|
18435
|
+
numeric({
|
|
18436
|
+
id: "battery",
|
|
18437
|
+
summary: "Battery charge in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
18438
|
+
role: DeviceRole.BatterySensor,
|
|
18439
|
+
outputCap: "battery",
|
|
18440
|
+
outputField: "percentage",
|
|
18441
|
+
quantity: "percentage",
|
|
18442
|
+
defaultAggregate: "mean",
|
|
18443
|
+
empty: "null",
|
|
18444
|
+
companions: [
|
|
18445
|
+
{
|
|
18446
|
+
fieldPath: "charging",
|
|
18447
|
+
expr: "\"unknown\""
|
|
18448
|
+
},
|
|
18449
|
+
{
|
|
18450
|
+
fieldPath: "sleeping",
|
|
18451
|
+
expr: "false"
|
|
18452
|
+
},
|
|
18453
|
+
{
|
|
18454
|
+
fieldPath: "lastUpdated",
|
|
18455
|
+
expr: "now"
|
|
18456
|
+
}
|
|
18457
|
+
]
|
|
18458
|
+
}),
|
|
18459
|
+
numeric({
|
|
18460
|
+
id: "numeric",
|
|
18461
|
+
summary: "A numeric reading in the members’ shared quantity. Mixed quantities are refused. Nobody reporting publishes null, not 0.",
|
|
18462
|
+
role: DeviceRole.NumericSensor,
|
|
18463
|
+
outputCap: "numeric-sensor",
|
|
18464
|
+
outputField: "value",
|
|
18465
|
+
quantity: "device",
|
|
18466
|
+
defaultAggregate: "mean",
|
|
18467
|
+
empty: "null",
|
|
18468
|
+
companions: [NOW]
|
|
18469
|
+
}),
|
|
18470
|
+
binary({
|
|
18471
|
+
id: "motion",
|
|
18472
|
+
summary: "Any or all motion. Offline and unknown members are left out, never read as off. Nobody reporting takes the device offline.",
|
|
18473
|
+
role: DeviceRole.MotionSensor,
|
|
18474
|
+
outputCap: "motion",
|
|
18475
|
+
outputField: "detected",
|
|
18476
|
+
defaultAggregate: "any",
|
|
18477
|
+
accept: [{
|
|
18478
|
+
cap: "motion",
|
|
18479
|
+
fieldPath: "detected"
|
|
18480
|
+
}],
|
|
18481
|
+
companions: [{
|
|
18482
|
+
fieldPath: "lastDetectedAt",
|
|
18483
|
+
expr: "null"
|
|
18484
|
+
}, {
|
|
18485
|
+
fieldPath: "autoClearAfterMs",
|
|
18486
|
+
expr: "null"
|
|
18487
|
+
}]
|
|
18488
|
+
}),
|
|
18489
|
+
binary({
|
|
18490
|
+
id: "contact",
|
|
18491
|
+
summary: "Any or all open contacts. Offline and unknown members are left out, never read as closed.",
|
|
18492
|
+
role: DeviceRole.ContactSensor,
|
|
18493
|
+
outputCap: "contact",
|
|
18494
|
+
outputField: "entryOpen",
|
|
18495
|
+
defaultAggregate: "any",
|
|
18496
|
+
accept: [{
|
|
18497
|
+
cap: "contact",
|
|
18498
|
+
fieldPath: "entryOpen"
|
|
18499
|
+
}],
|
|
18500
|
+
companions: [CHANGED]
|
|
18501
|
+
}),
|
|
18502
|
+
binary({
|
|
18503
|
+
id: "leak",
|
|
18504
|
+
summary: "Any or all leak detections. Offline and unknown members are left out, never read as dry.",
|
|
18505
|
+
role: DeviceRole.LeakSensor,
|
|
18506
|
+
outputCap: "flood",
|
|
18507
|
+
outputField: "flooded",
|
|
18508
|
+
defaultAggregate: "any",
|
|
18509
|
+
accept: [{
|
|
18510
|
+
cap: "flood",
|
|
18511
|
+
fieldPath: "flooded"
|
|
18512
|
+
}],
|
|
18513
|
+
companions: [CHANGED]
|
|
18514
|
+
}),
|
|
18515
|
+
binary({
|
|
18516
|
+
id: "smoke",
|
|
18517
|
+
summary: "Any or all smoke detections. Offline and unknown members are left out, never read as clear.",
|
|
18518
|
+
role: DeviceRole.SmokeSensor,
|
|
18519
|
+
outputCap: "smoke",
|
|
18520
|
+
outputField: "detected",
|
|
18521
|
+
defaultAggregate: "any",
|
|
18522
|
+
accept: [{
|
|
18523
|
+
cap: "smoke",
|
|
18524
|
+
fieldPath: "detected"
|
|
18525
|
+
}],
|
|
18526
|
+
companions: [CHANGED]
|
|
18527
|
+
}),
|
|
18528
|
+
binary({
|
|
18529
|
+
id: "occupancy",
|
|
18530
|
+
summary: "Any or all of motion or binary sensors, published as a binary. Presence zones are not aggregated. Nobody reporting is offline, not off.",
|
|
18531
|
+
role: DeviceRole.BinarySensor,
|
|
18532
|
+
outputCap: "binary",
|
|
18533
|
+
outputField: "on",
|
|
18534
|
+
defaultAggregate: "any",
|
|
18535
|
+
accept: [{
|
|
18536
|
+
cap: "motion",
|
|
18537
|
+
fieldPath: "detected"
|
|
18538
|
+
}, {
|
|
18539
|
+
cap: "binary",
|
|
18540
|
+
fieldPath: "on"
|
|
18541
|
+
}],
|
|
18542
|
+
companions: [CHANGED]
|
|
18543
|
+
}),
|
|
18544
|
+
binary({
|
|
18545
|
+
id: "binary",
|
|
18546
|
+
summary: "Any or all generic binary sensors. Offline and unknown members are left out, never read as off.",
|
|
18547
|
+
role: DeviceRole.BinarySensor,
|
|
18548
|
+
outputCap: "binary",
|
|
18549
|
+
outputField: "on",
|
|
18550
|
+
defaultAggregate: "any",
|
|
18551
|
+
accept: [{
|
|
18552
|
+
cap: "binary",
|
|
18553
|
+
fieldPath: "on"
|
|
18554
|
+
}],
|
|
18555
|
+
companions: [CHANGED]
|
|
18556
|
+
}),
|
|
18557
|
+
actuator({
|
|
18558
|
+
id: "switch",
|
|
18559
|
+
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.",
|
|
18560
|
+
deviceType: DeviceType.Switch,
|
|
18561
|
+
outputCap: "switch",
|
|
18562
|
+
commandCaps: ["switch"]
|
|
18563
|
+
}),
|
|
18564
|
+
actuator({
|
|
18565
|
+
id: "light",
|
|
18566
|
+
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.",
|
|
18567
|
+
deviceType: DeviceType.Light,
|
|
18568
|
+
outputCap: "switch",
|
|
18569
|
+
commandCaps: [
|
|
18570
|
+
"switch",
|
|
18571
|
+
"brightness",
|
|
18572
|
+
"color"
|
|
18573
|
+
]
|
|
18574
|
+
})
|
|
18575
|
+
];
|
|
18576
|
+
function actuator(input) {
|
|
18577
|
+
return {
|
|
18578
|
+
...input,
|
|
18579
|
+
family: "actuator",
|
|
18580
|
+
role: void 0,
|
|
18581
|
+
memberDeviceType: input.deviceType,
|
|
18582
|
+
outputField: "on",
|
|
18583
|
+
quantity: "none",
|
|
18584
|
+
baseUnit: void 0,
|
|
18585
|
+
aggregates: BINARY_AGGREGATES,
|
|
18586
|
+
defaultAggregate: "any",
|
|
18587
|
+
empty: "offline",
|
|
18588
|
+
accept: [{
|
|
18589
|
+
cap: "switch",
|
|
18590
|
+
fieldPath: "on"
|
|
18591
|
+
}],
|
|
18592
|
+
companions: [CHANGED]
|
|
18593
|
+
};
|
|
18594
|
+
}
|
|
18595
|
+
new Map(GROUP_TEMPLATES.map((template) => [template.id, template]));
|
|
18596
|
+
DeviceFeature.LightColorRgb, DeviceFeature.LightColorHsv, DeviceFeature.LightColorMired;
|
|
18209
18597
|
`${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
|
|
18210
18598
|
/**
|
|
18211
18599
|
* What a composition may BUILD on a device type (G2, D676): the caps a new
|
|
@@ -19919,12 +20307,12 @@ method(object({ deviceId: number().int().nonnegative() }), DeviceAdminLinkSchema
|
|
|
19919
20307
|
* providers detect renames by matching `uniqueId` and patch `id`
|
|
19920
20308
|
* in-place so dispatch keeps working.
|
|
19921
20309
|
*
|
|
19922
|
-
* **
|
|
19923
|
-
*
|
|
19924
|
-
*
|
|
19925
|
-
*
|
|
19926
|
-
* (`ha-domain-mapping`)
|
|
19927
|
-
* stored after that point.
|
|
20310
|
+
* **Display unit and precision are NOT stored here.** They are a read-time
|
|
20311
|
+
* preference (D944). A polymorphic reading stores its `quantity` here once,
|
|
20312
|
+
* at adopt, and a date/time value stores `dateTimeShape` the same way —
|
|
20313
|
+
* neither is repeated on each sample. The `device_class` tag is an
|
|
20314
|
+
* HA-specific input consumed at the discovery boundary (`ha-domain-mapping`)
|
|
20315
|
+
* to derive the CamStack `DeviceRole`; it is never stored after that point.
|
|
19928
20316
|
*
|
|
19929
20317
|
* The `raw` escape hatch carries provider-specific attributes that don't
|
|
19930
20318
|
* fit the structured slots (HA `attributes` whitelist, Reolink `deviceCache`
|
|
@@ -19938,6 +20326,14 @@ var SourceInfoSchema = object({
|
|
|
19938
20326
|
/** Immutable upstream identifier when available (HA `unique_id`, … ).
|
|
19939
20327
|
* Used to detect rename when `id` changes. */
|
|
19940
20328
|
uniqueId: string().optional(),
|
|
20329
|
+
/** Quantity of a polymorphic reading, written once at adopt (D944). */
|
|
20330
|
+
quantity: ReadingQuantitySchema.optional(),
|
|
20331
|
+
/** Date / time / datetime shape of a string reading, written once at adopt. */
|
|
20332
|
+
dateTimeShape: _enum([
|
|
20333
|
+
"date",
|
|
20334
|
+
"time",
|
|
20335
|
+
"datetime"
|
|
20336
|
+
]).optional(),
|
|
19941
20337
|
/** Provider-specific extras that don't fit the structured slots.
|
|
19942
20338
|
* Whitelist what goes here per provider — do NOT dump entire HA
|
|
19943
20339
|
* attribute blobs (would explode the meta JSON column). */
|
|
@@ -40961,7 +41357,8 @@ method(object({
|
|
|
40961
41357
|
"enum"
|
|
40962
41358
|
]),
|
|
40963
41359
|
enumValues: array(string()).optional(),
|
|
40964
|
-
item: boolean().optional()
|
|
41360
|
+
item: boolean().optional(),
|
|
41361
|
+
quantity: ReadingQuantitySchema.optional()
|
|
40965
41362
|
})).readonly(),
|
|
40966
41363
|
itemArray: object({
|
|
40967
41364
|
path: string(),
|
|
@@ -44805,8 +45202,8 @@ var MaskPolygonShapeSchema = object({
|
|
|
44805
45202
|
/** Boolean cell grid — row-major, length === gridWidth*gridHeight. */
|
|
44806
45203
|
var MaskGridShapeSchema = object({
|
|
44807
45204
|
kind: literal("grid"),
|
|
44808
|
-
gridWidth: number(),
|
|
44809
|
-
gridHeight: number(),
|
|
45205
|
+
gridWidth: number().meta(readingMeta("none")),
|
|
45206
|
+
gridHeight: number().meta(readingMeta("none")),
|
|
44810
45207
|
cells: array(boolean())
|
|
44811
45208
|
});
|
|
44812
45209
|
discriminatedUnion("kind", [
|
|
@@ -44918,6 +45315,8 @@ var NcSystemEventKindSchema = _enum([
|
|
|
44918
45315
|
"detection-blind",
|
|
44919
45316
|
"motion-noisy",
|
|
44920
45317
|
"motion-calm",
|
|
45318
|
+
"package-llm-silent",
|
|
45319
|
+
"package-llm-answered",
|
|
44921
45320
|
"recording-stalled",
|
|
44922
45321
|
"recording-healthy",
|
|
44923
45322
|
"recording-degraded",
|
|
@@ -56157,6 +56556,28 @@ var PackageVersionInfoSchema = object({
|
|
|
56157
56556
|
deprecated: string().optional(),
|
|
56158
56557
|
distTags: array(string()).readonly()
|
|
56159
56558
|
});
|
|
56559
|
+
/**
|
|
56560
|
+
* One published document. `ok` is markdown from the registry. `missing` means
|
|
56561
|
+
* the registry answered and the file was not there. `error` is a registry or
|
|
56562
|
+
* tarball failure — never an empty string standing in for either.
|
|
56563
|
+
*/
|
|
56564
|
+
var PackageDocBodySchema = discriminatedUnion("status", [
|
|
56565
|
+
object({
|
|
56566
|
+
status: literal("ok"),
|
|
56567
|
+
markdown: string()
|
|
56568
|
+
}),
|
|
56569
|
+
object({ status: literal("missing") }),
|
|
56570
|
+
object({
|
|
56571
|
+
status: literal("error"),
|
|
56572
|
+
message: string()
|
|
56573
|
+
})
|
|
56574
|
+
]);
|
|
56575
|
+
var PackageDocsSchema = object({
|
|
56576
|
+
name: string(),
|
|
56577
|
+
version: string(),
|
|
56578
|
+
readme: PackageDocBodySchema,
|
|
56579
|
+
changelog: PackageDocBodySchema
|
|
56580
|
+
});
|
|
56160
56581
|
var SearchResultSchema = object({
|
|
56161
56582
|
name: string(),
|
|
56162
56583
|
version: string(),
|
|
@@ -56375,7 +56796,10 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
|
|
|
56375
56796
|
}), object({ success: literal(true) }), {
|
|
56376
56797
|
kind: "mutation",
|
|
56377
56798
|
auth: "admin"
|
|
56378
|
-
}), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({
|
|
56799
|
+
}), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({
|
|
56800
|
+
name: string().min(1),
|
|
56801
|
+
version: string().min(1).optional()
|
|
56802
|
+
}), PackageDocsSchema, { auth: "admin" }), method(object({ addonId: string() }), RestartAddonResultSchema, {
|
|
56379
56803
|
kind: "mutation",
|
|
56380
56804
|
auth: "admin"
|
|
56381
56805
|
}), method(object({ packageName: string() }), object({ success: literal(true) }), {
|
|
@@ -56434,27 +56858,17 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
|
|
|
56434
56858
|
*/
|
|
56435
56859
|
var AirQualitySensorStatusSchema = object({
|
|
56436
56860
|
/** Carbon dioxide concentration in ppm. */
|
|
56437
|
-
co2Ppm: number().min(0).optional(),
|
|
56861
|
+
co2Ppm: number().min(0).optional().meta(readingMeta("concentration-volume")),
|
|
56438
56862
|
/** Total volatile organic compounds in ppb. */
|
|
56439
|
-
vocPpb: number().min(0).optional(),
|
|
56863
|
+
vocPpb: number().min(0).optional().meta(readingMeta("concentration-ppb")),
|
|
56440
56864
|
/** Particulate matter ≤ 2.5 μm in µg/m³. */
|
|
56441
|
-
pm25: number().min(0).optional(),
|
|
56865
|
+
pm25: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
56442
56866
|
/** Particulate matter ≤ 10 μm in µg/m³. */
|
|
56443
|
-
pm10: number().min(0).optional(),
|
|
56867
|
+
pm10: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
56444
56868
|
/** Composite AQI value (typically 0..500). */
|
|
56445
|
-
aqi: number().optional(),
|
|
56869
|
+
aqi: number().optional().meta(readingMeta("index")),
|
|
56446
56870
|
/** Ms epoch when the slice was last updated. */
|
|
56447
|
-
lastFetchedAt: number()
|
|
56448
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
56449
|
-
* `attributes.unit_of_measurement` → 'ppm' / 'ppb' / 'µg/m³'). Each
|
|
56450
|
-
* upstream `sensor.*` entity surfaces ONE device_class, so one unit
|
|
56451
|
-
* per slice is unambiguous. */
|
|
56452
|
-
unit: string().optional(),
|
|
56453
|
-
/** Suggested decimal places for numeric display.
|
|
56454
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
56455
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
56456
|
-
* auto-formatting when absent. */
|
|
56457
|
-
precision: number().int().min(0).max(10).optional()
|
|
56871
|
+
lastFetchedAt: number()
|
|
56458
56872
|
});
|
|
56459
56873
|
var airQualitySensorCapability = {
|
|
56460
56874
|
name: "air-quality-sensor",
|
|
@@ -56491,12 +56905,12 @@ var airQualitySensorCapability = {
|
|
|
56491
56905
|
},
|
|
56492
56906
|
pm25: {
|
|
56493
56907
|
kind: "gauge",
|
|
56494
|
-
unit: "
|
|
56908
|
+
unit: "µg/m³",
|
|
56495
56909
|
deadband: 1
|
|
56496
56910
|
},
|
|
56497
56911
|
pm10: {
|
|
56498
56912
|
kind: "gauge",
|
|
56499
|
-
unit: "
|
|
56913
|
+
unit: "µg/m³",
|
|
56500
56914
|
deadband: 1
|
|
56501
56915
|
},
|
|
56502
56916
|
aqi: {
|
|
@@ -56514,22 +56928,13 @@ var airQualitySensorCapability = {
|
|
|
56514
56928
|
* entries with `device_class: illuminance`.
|
|
56515
56929
|
*/
|
|
56516
56930
|
var AmbientLightSensorStatusSchema = object({
|
|
56517
|
-
/** Current illuminance in lux (lx). */
|
|
56518
|
-
lux: number().min(0).meta({
|
|
56519
|
-
|
|
56931
|
+
/** Current illuminance in lux (lx). `null` when the sample was refused (D393). */
|
|
56932
|
+
lux: number().min(0).nullable().meta(readingMeta("illuminance", {
|
|
56933
|
+
precision: 0,
|
|
56520
56934
|
label: "Illuminance"
|
|
56521
|
-
}),
|
|
56935
|
+
})),
|
|
56522
56936
|
/** Ms epoch when the slice was last updated. */
|
|
56523
|
-
lastFetchedAt: number()
|
|
56524
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
56525
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
56526
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
56527
|
-
unit: string().optional(),
|
|
56528
|
-
/** Suggested decimal places for numeric display.
|
|
56529
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
56530
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
56531
|
-
* auto-formatting when absent. */
|
|
56532
|
-
precision: number().int().min(0).max(10).optional()
|
|
56937
|
+
lastFetchedAt: number()
|
|
56533
56938
|
});
|
|
56534
56939
|
var ambientLightSensorCapability = {
|
|
56535
56940
|
name: "ambient-light-sensor",
|
|
@@ -56561,12 +56966,7 @@ var ambientLightSensorCapability = {
|
|
|
56561
56966
|
} } },
|
|
56562
56967
|
/** Clock fields: written, but excluded from the compare that decides
|
|
56563
56968
|
* whether persisting is worth a SQLite commit. */
|
|
56564
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
56565
|
-
customize: {
|
|
56566
|
-
version: 1,
|
|
56567
|
-
advanced: "derive",
|
|
56568
|
-
targets: []
|
|
56569
|
-
}
|
|
56969
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
56570
56970
|
};
|
|
56571
56971
|
/**
|
|
56572
56972
|
* Per-class audio metrics aggregated over a sliding window.
|
|
@@ -56793,10 +57193,7 @@ var BatteryStatusSchema = object({
|
|
|
56793
57193
|
* Consumers must SKIP a null rather than coerce it — `battery-band` already
|
|
56794
57194
|
* declines to band a non-finite reading, which is the correct shape.
|
|
56795
57195
|
*/
|
|
56796
|
-
percentage: number().min(0).max(100).nullable().meta({
|
|
56797
|
-
unit: "%",
|
|
56798
|
-
label: "Charge"
|
|
56799
|
-
}),
|
|
57196
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage", { label: "Charge" })),
|
|
56800
57197
|
/**
|
|
56801
57198
|
* Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
|
|
56802
57199
|
* Reolink-specific for the Solar Panel 2 accessory (will become
|
|
@@ -56823,7 +57220,14 @@ var BatteryStatusSchema = object({
|
|
|
56823
57220
|
*/
|
|
56824
57221
|
sleeping: boolean().meta({ label: "Sleeping" }),
|
|
56825
57222
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
56826
|
-
lastUpdated: number(),
|
|
57223
|
+
lastUpdated: number().meta(readingMeta("none")),
|
|
57224
|
+
/**
|
|
57225
|
+
* Battery voltage in volts, for a cell the firmware reports as voltage
|
|
57226
|
+
* rather than a percentage (Ecowitt capacitor packs). Absent on cameras
|
|
57227
|
+
* that only report charge. A second reading on this cap, not a second
|
|
57228
|
+
* `numeric-sensor` on the same device.
|
|
57229
|
+
*/
|
|
57230
|
+
volts: number().nullable().optional().meta(readingMeta("voltage", { label: "Voltage" })),
|
|
56827
57231
|
/**
|
|
56828
57232
|
* Ms epoch of the last time the device PROVED it was reachable — a
|
|
56829
57233
|
* completed firmware round-trip, an observed wake, or an inbound push
|
|
@@ -56875,7 +57279,6 @@ var BATTERY_DEVICE_TYPES = [
|
|
|
56875
57279
|
/** Generic Customize target for the percentage reading (D936). */
|
|
56876
57280
|
var batteryCustomize = {
|
|
56877
57281
|
version: 1,
|
|
56878
|
-
advanced: "derive",
|
|
56879
57282
|
targets: [{
|
|
56880
57283
|
id: "percentage",
|
|
56881
57284
|
cardinality: "scalar",
|
|
@@ -56884,7 +57287,7 @@ var batteryCustomize = {
|
|
|
56884
57287
|
stateField: "percentage"
|
|
56885
57288
|
},
|
|
56886
57289
|
deviceTypes: BATTERY_DEVICE_TYPES,
|
|
56887
|
-
apply: "add
|
|
57290
|
+
apply: "add",
|
|
56888
57291
|
path: "percentage",
|
|
56889
57292
|
sources: [{
|
|
56890
57293
|
kind: "field",
|
|
@@ -57005,10 +57408,16 @@ onStatusChanged: { data: object({
|
|
|
57005
57408
|
/**
|
|
57006
57409
|
* History (D850): recorded series. The generic capture replaces the `battery` series of `pipeline-analytics:stats-5m`.
|
|
57007
57410
|
*/
|
|
57008
|
-
history: { fields: {
|
|
57009
|
-
|
|
57010
|
-
|
|
57011
|
-
|
|
57411
|
+
history: { fields: {
|
|
57412
|
+
percentage: {
|
|
57413
|
+
kind: "gauge",
|
|
57414
|
+
unit: "%"
|
|
57415
|
+
},
|
|
57416
|
+
volts: {
|
|
57417
|
+
kind: "gauge",
|
|
57418
|
+
unit: "V"
|
|
57419
|
+
}
|
|
57420
|
+
} },
|
|
57012
57421
|
customize: batteryCustomize,
|
|
57013
57422
|
/** Clock fields: written, but excluded from the compare that decides
|
|
57014
57423
|
* whether persisting is worth a SQLite commit. */
|
|
@@ -57055,12 +57464,7 @@ var binaryCapability = {
|
|
|
57055
57464
|
history: { fields: { on: { kind: "boolean" } } },
|
|
57056
57465
|
/** Clock fields: written, but excluded from the compare that decides
|
|
57057
57466
|
* whether persisting is worth a SQLite commit. */
|
|
57058
|
-
volatileStateFields: ["lastChangedAt"]
|
|
57059
|
-
customize: {
|
|
57060
|
-
version: 1,
|
|
57061
|
-
advanced: "derive",
|
|
57062
|
-
targets: []
|
|
57063
|
-
}
|
|
57467
|
+
volatileStateFields: ["lastChangedAt"]
|
|
57064
57468
|
};
|
|
57065
57469
|
/**
|
|
57066
57470
|
* Dimmable-light brightness control. Co-exists with `switch` on the
|
|
@@ -57076,7 +57480,7 @@ var binaryCapability = {
|
|
|
57076
57480
|
*/
|
|
57077
57481
|
var BrightnessStatusSchema = object({
|
|
57078
57482
|
/** Current level as 0..100 inclusive. Firmware-reported. */
|
|
57079
|
-
percentage: number().min(0).max(100),
|
|
57483
|
+
percentage: number().min(0).max(100).meta(readingMeta("percentage")),
|
|
57080
57484
|
/** Ms epoch of the last operator-driven change. Useful for UI freshness. */
|
|
57081
57485
|
lastChangedAt: number()
|
|
57082
57486
|
});
|
|
@@ -57530,21 +57934,21 @@ var ClimateControlStatusSchema = object({
|
|
|
57530
57934
|
/** Single setpoint in Celsius. Used by single-target modes
|
|
57531
57935
|
* (heat / cool / dry). Null when the device is in a range mode
|
|
57532
57936
|
* (`heat_cool`) or has no setpoint at all (`fan_only`/`off`). */
|
|
57533
|
-
target: number().nullable(),
|
|
57937
|
+
target: number().nullable().meta(readingMeta("temperature")),
|
|
57534
57938
|
/** Upper bound of the dual setpoint in Celsius. Populated only
|
|
57535
57939
|
* in `heat_cool` mode. */
|
|
57536
|
-
targetHigh: number().nullable(),
|
|
57940
|
+
targetHigh: number().nullable().meta(readingMeta("temperature")),
|
|
57537
57941
|
/** Lower bound of the dual setpoint in Celsius. Populated only
|
|
57538
57942
|
* in `heat_cool` mode. */
|
|
57539
|
-
targetLow: number().nullable(),
|
|
57943
|
+
targetLow: number().nullable().meta(readingMeta("temperature")),
|
|
57540
57944
|
/** Target relative humidity (0..100). Null when the device has no
|
|
57541
57945
|
* humidity control. */
|
|
57542
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
57946
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
57543
57947
|
/** Current measured temperature in Celsius. Read-only — pushed by
|
|
57544
57948
|
* the device's internal sensor. */
|
|
57545
|
-
currentTemp: number().nullable(),
|
|
57949
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
57546
57950
|
/** Current measured relative humidity (0..100). Read-only. */
|
|
57547
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
57951
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
57548
57952
|
/** Vertical louver swing on/off. Null when the device has no vertical
|
|
57549
57953
|
* swing surface (gate with `DeviceFeature.ClimateSwingVertical`). */
|
|
57550
57954
|
swingVertical: boolean().nullable(),
|
|
@@ -57552,11 +57956,11 @@ var ClimateControlStatusSchema = object({
|
|
|
57552
57956
|
* horizontal swing surface (gate with `DeviceFeature.ClimateSwingHorizontal`). */
|
|
57553
57957
|
swingHorizontal: boolean().nullable(),
|
|
57554
57958
|
/** Lowest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
57555
|
-
minTemp: number().nullable().optional(),
|
|
57959
|
+
minTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
57556
57960
|
/** Highest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
57557
|
-
maxTemp: number().nullable().optional(),
|
|
57961
|
+
maxTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
57558
57962
|
/** Setpoint granularity, Celsius (0.5, 1). Absent / null = not reported. */
|
|
57559
|
-
tempStep: number().positive().nullable().optional(),
|
|
57963
|
+
tempStep: number().positive().nullable().optional().meta(readingMeta("temperature")),
|
|
57560
57964
|
/** Ms epoch when the slice was last updated (push or command). */
|
|
57561
57965
|
lastFetchedAt: number()
|
|
57562
57966
|
});
|
|
@@ -57698,17 +58102,17 @@ var climateControlCapability = {
|
|
|
57698
58102
|
* modes to expose in the picker without a slice fetch.
|
|
57699
58103
|
*/
|
|
57700
58104
|
var RgbTripletSchema = object({
|
|
57701
|
-
r: number().int().min(0).max(255),
|
|
57702
|
-
g: number().int().min(0).max(255),
|
|
57703
|
-
b: number().int().min(0).max(255)
|
|
58105
|
+
r: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
58106
|
+
g: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
58107
|
+
b: number().int().min(0).max(255).meta(readingMeta("none"))
|
|
57704
58108
|
});
|
|
57705
58109
|
var HsvTripletSchema = object({
|
|
57706
58110
|
/** Hue in degrees, 0..360. */
|
|
57707
|
-
h: number().min(0).max(360),
|
|
58111
|
+
h: number().min(0).max(360).meta(readingMeta("none")),
|
|
57708
58112
|
/** Saturation as 0..100 inclusive. */
|
|
57709
|
-
s: number().min(0).max(100),
|
|
58113
|
+
s: number().min(0).max(100).meta(readingMeta("none")),
|
|
57710
58114
|
/** Value/brightness as 0..100 inclusive. */
|
|
57711
|
-
v: number().min(0).max(100)
|
|
58115
|
+
v: number().min(0).max(100).meta(readingMeta("none"))
|
|
57712
58116
|
});
|
|
57713
58117
|
var ColorInputSchema = discriminatedUnion("mode", [
|
|
57714
58118
|
object({
|
|
@@ -57737,7 +58141,7 @@ var ColorStatusSchema = object({
|
|
|
57737
58141
|
/** Populated when `mode === 'hsv'`. */
|
|
57738
58142
|
hsv: HsvTripletSchema.optional(),
|
|
57739
58143
|
/** Populated when `mode === 'mired'`. */
|
|
57740
|
-
mireds: number().int().optional(),
|
|
58144
|
+
mireds: number().int().optional().meta(readingMeta("colour-temperature")),
|
|
57741
58145
|
/** Ms epoch of the last operator-driven change. */
|
|
57742
58146
|
lastChangedAt: number()
|
|
57743
58147
|
});
|
|
@@ -57932,18 +58336,12 @@ _enum([
|
|
|
57932
58336
|
"empty",
|
|
57933
58337
|
"full"
|
|
57934
58338
|
]);
|
|
57935
|
-
/**
|
|
57936
|
-
|
|
57937
|
-
|
|
57938
|
-
"days",
|
|
57939
|
-
"hours",
|
|
57940
|
-
"cycles"
|
|
57941
|
-
]);
|
|
57942
|
-
/** Remaining life as a COUNT, not a percentage (the PetKit desiccant reports
|
|
57943
|
-
* days). `value` null = unknown (D393). */
|
|
58339
|
+
/** Whether `remaining.value` is a duration in seconds or a dimensionless count. */
|
|
58340
|
+
var ConsumableRemainingKindSchema = _enum(["duration", "count"]);
|
|
58341
|
+
/** Remaining life. `value` null = unknown (D393). Duration is seconds. */
|
|
57944
58342
|
var ConsumableRemainingSchema = object({
|
|
57945
|
-
value: number().min(0).nullable(),
|
|
57946
|
-
|
|
58343
|
+
value: number().min(0).nullable().meta(readingMeta("device")),
|
|
58344
|
+
kind: ConsumableRemainingKindSchema
|
|
57947
58345
|
});
|
|
57948
58346
|
/** A single consumable item. Either a continuous `level` (remaining
|
|
57949
58347
|
* life %, or fill % for a `supply` / `waste` item) or a discrete `status`
|
|
@@ -57956,7 +58354,7 @@ var ConsumableItemSchema = object({
|
|
|
57956
58354
|
/** Display name. */
|
|
57957
58355
|
label: string().min(1),
|
|
57958
58356
|
/** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
|
|
57959
|
-
level: number().min(0).max(100).nullable(),
|
|
58357
|
+
level: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
57960
58358
|
/** The provider's discrete verdict when known (binary mode). */
|
|
57961
58359
|
status: ConsumableStatusSchema.nullable(),
|
|
57962
58360
|
/** What the item is — decides whether low or full is bad. Absent = `wear`. */
|
|
@@ -58038,8 +58436,8 @@ var consumablesCustomize = {
|
|
|
58038
58436
|
transforms: [{ kind: "identity" }]
|
|
58039
58437
|
}],
|
|
58040
58438
|
literals: [{
|
|
58041
|
-
path: "remaining.
|
|
58042
|
-
values: [...
|
|
58439
|
+
path: "remaining.kind",
|
|
58440
|
+
values: [...ConsumableRemainingKindSchema.options]
|
|
58043
58441
|
}]
|
|
58044
58442
|
},
|
|
58045
58443
|
{
|
|
@@ -58168,7 +58566,6 @@ reset: method(object({
|
|
|
58168
58566
|
},
|
|
58169
58567
|
"remaining.value": {
|
|
58170
58568
|
kind: "gauge",
|
|
58171
|
-
unitFrom: "remaining.unit",
|
|
58172
58569
|
deadband: 1,
|
|
58173
58570
|
displayName: "Remaining"
|
|
58174
58571
|
}
|
|
@@ -58238,10 +58635,9 @@ var contactCapability = {
|
|
|
58238
58635
|
* (empty array for the other kinds). It lives in the slice because
|
|
58239
58636
|
* HA `select.*` entities may update their options at runtime.
|
|
58240
58637
|
*
|
|
58241
|
-
*
|
|
58242
|
-
*
|
|
58243
|
-
*
|
|
58244
|
-
* push — consistent with `options` and the sensor-unit approach.
|
|
58638
|
+
* Numeric `min` / `max` / `step` live in the slice and share the device
|
|
58639
|
+
* quantity (`SourceInfo.quantity`, D944). Display precision is a read-time
|
|
58640
|
+
* preference. A datetime control's shape is `SourceInfo.dateTimeShape`.
|
|
58245
58641
|
*/
|
|
58246
58642
|
var ControlStatusSchema = object({
|
|
58247
58643
|
kind: _enum([
|
|
@@ -58253,39 +58649,17 @@ var ControlStatusSchema = object({
|
|
|
58253
58649
|
/** Current value. Numeric kind → number; select/text/datetime → string.
|
|
58254
58650
|
* Datetime values are ISO 8601 strings (full timestamp, date-only,
|
|
58255
58651
|
* or time-only — HA accepts all three forms). */
|
|
58256
|
-
value: union([number(), string()]),
|
|
58652
|
+
value: union([number().meta(readingMeta("device")), string()]),
|
|
58257
58653
|
/** Acceptable values when `kind === 'select'`. Empty for other kinds. */
|
|
58258
58654
|
options: array(string()),
|
|
58259
58655
|
/** Ms epoch when the slice was last updated. */
|
|
58260
58656
|
lastChangedAt: number(),
|
|
58261
|
-
/**
|
|
58262
|
-
|
|
58263
|
-
|
|
58264
|
-
|
|
58265
|
-
/**
|
|
58266
|
-
|
|
58267
|
-
min: number().optional(),
|
|
58268
|
-
/** Maximum allowed value. Populated live from HA `attributes.max`.
|
|
58269
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
58270
|
-
max: number().optional(),
|
|
58271
|
-
/** Step increment. Populated live from HA `attributes.step`.
|
|
58272
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
58273
|
-
step: number().optional(),
|
|
58274
|
-
/** Suggested decimal places for numeric display. Populated live from HA
|
|
58275
|
-
* `attributes.suggested_display_precision`, or derived from `step` when the
|
|
58276
|
-
* HA attribute is absent. Meaningful for `kind === 'numeric'`; absent for
|
|
58277
|
-
* other kinds. Falls back to auto-formatting when absent. */
|
|
58278
|
-
precision: number().int().min(0).max(10).optional(),
|
|
58279
|
-
/** Date-picker granularity for `kind === 'datetime'`. 'date' → date-only,
|
|
58280
|
-
* 'time' → time-only, 'datetime' → full timestamp. Absent for other kinds
|
|
58281
|
-
* (UI defaults to 'datetime'). Derived live from the device's HA domain
|
|
58282
|
-
* (date.* / time.* / datetime.*) or, for input_datetime, from the entity's
|
|
58283
|
-
* `has_date`/`has_time` attributes on each push. */
|
|
58284
|
-
format: _enum([
|
|
58285
|
-
"date",
|
|
58286
|
-
"time",
|
|
58287
|
-
"datetime"
|
|
58288
|
-
]).optional()
|
|
58657
|
+
/** Minimum allowed value, in the device quantity's base unit. */
|
|
58658
|
+
min: number().optional().meta(readingMeta("device")),
|
|
58659
|
+
/** Maximum allowed value, in the device quantity's base unit. */
|
|
58660
|
+
max: number().optional().meta(readingMeta("device")),
|
|
58661
|
+
/** Step increment, in the device quantity's base unit. */
|
|
58662
|
+
step: number().optional().meta(readingMeta("device"))
|
|
58289
58663
|
});
|
|
58290
58664
|
var ControlSetValueInputSchema = discriminatedUnion("kind", [
|
|
58291
58665
|
object({
|
|
@@ -58351,9 +58725,9 @@ var CoverStatusSchema = object({
|
|
|
58351
58725
|
]),
|
|
58352
58726
|
/** 0 = fully closed, 100 = fully open. Null when the device has
|
|
58353
58727
|
* no intermediate position surface. */
|
|
58354
|
-
position: number().min(0).max(100).nullable(),
|
|
58728
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58355
58729
|
/** 0 = closed slats, 100 = open slats. Null when no tilt support. */
|
|
58356
|
-
tiltPosition: number().min(0).max(100).nullable(),
|
|
58730
|
+
tiltPosition: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58357
58731
|
/** Ms epoch when the slice was last updated. */
|
|
58358
58732
|
lastChangedAt: number()
|
|
58359
58733
|
});
|
|
@@ -58456,9 +58830,9 @@ var NormalizedRangeSchema$1 = object({
|
|
|
58456
58830
|
var DayNightStatusSchema = object({
|
|
58457
58831
|
mode: DayNightModeSchema,
|
|
58458
58832
|
/** IR-cut trigger sensitivity, NORMALIZED 0–100 (higher = switches to night sooner). */
|
|
58459
|
-
sensitivity: number().optional(),
|
|
58833
|
+
sensitivity: number().optional().meta(readingMeta("none")),
|
|
58460
58834
|
/** Delay before the IR-cut filter flips, in seconds. */
|
|
58461
|
-
switchDelaySec: number().optional(),
|
|
58835
|
+
switchDelaySec: number().optional().meta(readingMeta("duration")),
|
|
58462
58836
|
lastFetchedAt: number()
|
|
58463
58837
|
});
|
|
58464
58838
|
/**
|
|
@@ -58676,11 +59050,11 @@ var DishwasherStatusSchema = object({
|
|
|
58676
59050
|
/** Feature keys of the programs the appliance currently offers — drives the UI selector. */
|
|
58677
59051
|
availablePrograms: array(string()),
|
|
58678
59052
|
/** Seconds remaining on the active cycle, or null when not running / not known. */
|
|
58679
|
-
remainingSeconds: number().int().nonnegative().nullable(),
|
|
59053
|
+
remainingSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
58680
59054
|
/** Seconds the delayed start is set to (time until the cycle starts), or null. */
|
|
58681
|
-
delayedStartSeconds: number().int().nonnegative().nullable(),
|
|
59055
|
+
delayedStartSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
58682
59056
|
/** Cycle completion 0..100, or null when not applicable. */
|
|
58683
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
59057
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58684
59058
|
/** True when the door is reported open; null when the door state is not known. */
|
|
58685
59059
|
doorOpen: boolean().nullable(),
|
|
58686
59060
|
/** True when the door is latched (locked) during a cycle; null when not reported. */
|
|
@@ -58704,7 +59078,7 @@ var DishwasherStatusSchema = object({
|
|
|
58704
59078
|
/** True while the machine-care (descaling / cleaning-program) reminder is raised; false when clear; null when not reported. */
|
|
58705
59079
|
machineCareDue: boolean().nullable(),
|
|
58706
59080
|
/** Program runs left before the machine-care reminder is due; null when the appliance does not say. */
|
|
58707
|
-
machineCareRemainingRuns: number().int().nonnegative().nullable(),
|
|
59081
|
+
machineCareRemainingRuns: number().int().nonnegative().nullable().meta(readingMeta("count")),
|
|
58708
59082
|
/** Option states: null when the appliance does not expose the option or has not said. */
|
|
58709
59083
|
halfLoad: boolean().nullable(),
|
|
58710
59084
|
hygienePlus: boolean().nullable(),
|
|
@@ -58719,7 +59093,7 @@ var DishwasherStatusSchema = object({
|
|
|
58719
59093
|
/** Feature keys of the events currently raised (salt low, rinse aid low, program finished, …). */
|
|
58720
59094
|
activeEvents: array(string()),
|
|
58721
59095
|
/** Numeric error code when the appliance reports one; null otherwise. */
|
|
58722
|
-
errorCode: number().nullable(),
|
|
59096
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
58723
59097
|
/** Name of the raised alert-level event while the appliance is in error; null otherwise. */
|
|
58724
59098
|
errorLabel: string().nullable(),
|
|
58725
59099
|
/** Ms epoch of the last value received from the appliance; 0 = never. */
|
|
@@ -58950,7 +59324,7 @@ var DoorbellStatusSchema = object({
|
|
|
58950
59324
|
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
58951
59325
|
lastPressedAt: number().nullable(),
|
|
58952
59326
|
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
58953
|
-
pressCountSinceStart: number()
|
|
59327
|
+
pressCountSinceStart: number().meta(readingMeta("count"))
|
|
58954
59328
|
});
|
|
58955
59329
|
var DoorbellPressEventSchema = object({
|
|
58956
59330
|
deviceId: number(),
|
|
@@ -59015,17 +59389,7 @@ onPressed: {
|
|
|
59015
59389
|
history: "none",
|
|
59016
59390
|
customize: doorbellCustomize
|
|
59017
59391
|
};
|
|
59018
|
-
|
|
59019
|
-
* Enum-state sensor — a string value picked from a finite option set.
|
|
59020
|
-
* Drives HA `sensor` entries with `state_class: enum` (HVAC action
|
|
59021
|
-
* states, weather conditions, contact-source channels, mode strings).
|
|
59022
|
-
* The option set is stable across observations; it is persisted in the
|
|
59023
|
-
* device config blob (via the control slice at adoption) and is NOT
|
|
59024
|
-
* stored in `sourceInfo`.
|
|
59025
|
-
*/
|
|
59026
|
-
/** Locale-render shape for an ISO `value` carried by a `DateTimeSensor`-role
|
|
59027
|
-
* enum sensor: `date` (date-only), `time` (time-only), `datetime` (both). */
|
|
59028
|
-
var EnumSensorDateTimeFormatSchema = _enum([
|
|
59392
|
+
_enum([
|
|
59029
59393
|
"date",
|
|
59030
59394
|
"time",
|
|
59031
59395
|
"datetime"
|
|
@@ -59033,12 +59397,11 @@ var EnumSensorDateTimeFormatSchema = _enum([
|
|
|
59033
59397
|
var EnumSensorStatusSchema = object({
|
|
59034
59398
|
value: string(),
|
|
59035
59399
|
/**
|
|
59036
|
-
* Set
|
|
59037
|
-
* as
|
|
59038
|
-
*
|
|
59039
|
-
* a time-only sensor → `'time'`.
|
|
59400
|
+
* Set when `value` is a timestamp rather than an enum state, so history
|
|
59401
|
+
* does not learn ISO strings as states. The display shape (date / time /
|
|
59402
|
+
* datetime) lives on `SourceInfo.dateTimeShape`, written once at adopt.
|
|
59040
59403
|
*/
|
|
59041
|
-
|
|
59404
|
+
timestamp: boolean().optional(),
|
|
59042
59405
|
/** Ms epoch when the slice was last updated. */
|
|
59043
59406
|
lastFetchedAt: number()
|
|
59044
59407
|
});
|
|
@@ -59065,11 +59428,11 @@ var enumSensorCapability = {
|
|
|
59065
59428
|
* History (D850): the value as an `enum` series (an appliance's program or
|
|
59066
59429
|
* operation state, an HVAC action). The option set is per device, so the
|
|
59067
59430
|
* value list is LEARNED as values are first seen (bounded). A sensor with a
|
|
59068
|
-
* `
|
|
59431
|
+
* `timestamp` carries a clock, not a state, and is not recorded.
|
|
59069
59432
|
*/
|
|
59070
59433
|
history: { fields: { value: {
|
|
59071
59434
|
kind: "enum",
|
|
59072
|
-
skipWhenSet: "
|
|
59435
|
+
skipWhenSet: "timestamp"
|
|
59073
59436
|
} } },
|
|
59074
59437
|
/** Clock fields: written, but excluded from the compare that decides
|
|
59075
59438
|
* whether persisting is worth a SQLite commit. */
|
|
@@ -59089,13 +59452,13 @@ var EventFireSchema = object({
|
|
|
59089
59452
|
deviceId: number(),
|
|
59090
59453
|
eventType: string(),
|
|
59091
59454
|
data: record(string(), unknown()).nullable(),
|
|
59092
|
-
timestamp: number(),
|
|
59093
|
-
seq: number()
|
|
59455
|
+
timestamp: number().meta(readingMeta("none")),
|
|
59456
|
+
seq: number().meta(readingMeta("count"))
|
|
59094
59457
|
});
|
|
59095
59458
|
var EventEmitterStatusSchema = object({
|
|
59096
59459
|
eventTypes: array(string()),
|
|
59097
59460
|
lastEvent: EventFireSchema.nullable(),
|
|
59098
|
-
eventCountSinceStart: number()
|
|
59461
|
+
eventCountSinceStart: number().meta(readingMeta("count"))
|
|
59099
59462
|
});
|
|
59100
59463
|
var eventEmitterCapability = {
|
|
59101
59464
|
name: "event-emitter",
|
|
@@ -59508,10 +59871,10 @@ var FanDirectionSchema = _enum(["forward", "reverse"]);
|
|
|
59508
59871
|
var FanControlStatusSchema = object({
|
|
59509
59872
|
/** Active speed as 0..100 inclusive. Null when the device has no
|
|
59510
59873
|
* speed surface (single-speed fan). */
|
|
59511
|
-
percentage: number().min(0).max(100).nullable(),
|
|
59874
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59512
59875
|
/** Speed granularity the device accepts (HA `percentage_step`, e.g. 25 for
|
|
59513
59876
|
* a 4-speed fan). Absent when unknown — the UI then falls back to step 1. */
|
|
59514
|
-
percentageStep: number().positive().optional(),
|
|
59877
|
+
percentageStep: number().positive().optional().meta(readingMeta("percentage")),
|
|
59515
59878
|
/** Active preset mode (`auto` / `quiet` / `turbo` / vendor-specific)
|
|
59516
59879
|
* — empty string when no preset is active or supported. */
|
|
59517
59880
|
preset: string(),
|
|
@@ -59632,7 +59995,7 @@ var FeatureProbeStatusSchema = object({
|
|
|
59632
59995
|
/** Camera/firmware model string. `null` when the firmware doesn't expose it. */
|
|
59633
59996
|
model: string().nullable(),
|
|
59634
59997
|
/** Channel count for NVR/Hub devices; `1` for standalone cameras; `null` pre-probe. */
|
|
59635
|
-
channelCount: number().nullable(),
|
|
59998
|
+
channelCount: number().nullable().meta(readingMeta("count")),
|
|
59636
59999
|
/**
|
|
59637
60000
|
* Ms epoch of the last SUCCESSFUL probe. `0` before the first probe
|
|
59638
60001
|
* completes — drivers' `getAccessoryChildren()` should treat zero as
|
|
@@ -59755,9 +60118,91 @@ var gasCapability = {
|
|
|
59755
60118
|
* whether persisting is worth a SQLite commit. */
|
|
59756
60119
|
volatileStateFields: ["lastChangedAt"]
|
|
59757
60120
|
};
|
|
60121
|
+
var GroupCommandsSchema = object({
|
|
60122
|
+
/** One row per member that has been commanded. A later command replaces that member's row. */
|
|
60123
|
+
results: array(object({
|
|
60124
|
+
deviceId: number().int().nonnegative(),
|
|
60125
|
+
cap: string().min(1),
|
|
60126
|
+
method: string().min(1),
|
|
60127
|
+
ok: boolean(),
|
|
60128
|
+
error: string().optional(),
|
|
60129
|
+
/** Ms epoch of the attempt. */
|
|
60130
|
+
at: number()
|
|
60131
|
+
})) });
|
|
60132
|
+
var groupCommandsCapability = {
|
|
60133
|
+
name: "group-commands",
|
|
60134
|
+
scope: "device",
|
|
60135
|
+
deviceNative: true,
|
|
60136
|
+
mode: "singleton",
|
|
60137
|
+
deviceTypes: [DeviceType.Switch, DeviceType.Light],
|
|
60138
|
+
methods: {},
|
|
60139
|
+
status: {
|
|
60140
|
+
schema: GroupCommandsSchema,
|
|
60141
|
+
kind: "push"
|
|
60142
|
+
},
|
|
60143
|
+
runtimeState: GroupCommandsSchema,
|
|
60144
|
+
/**
|
|
60145
|
+
* Runtime-state durability: **session** — the last attempt. A restored
|
|
60146
|
+
* failure would outlive the command that caused it.
|
|
60147
|
+
*
|
|
60148
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
60149
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
60150
|
+
*/
|
|
60151
|
+
durability: "session",
|
|
60152
|
+
history: "none"
|
|
60153
|
+
};
|
|
60154
|
+
/**
|
|
60155
|
+
* How many members of a helper group answered (D944). Counts are integers,
|
|
60156
|
+
* not measurements: zero included is a real count, never a stand-in reading.
|
|
60157
|
+
* The reading itself stays on the output capability. History is none — the
|
|
60158
|
+
* series that later statistics read is the output cap's own history block.
|
|
60159
|
+
*/
|
|
60160
|
+
var GroupStatusSchema = object({
|
|
60161
|
+
/** Members whose current value entered the aggregate. */
|
|
60162
|
+
included: number().int().nonnegative().meta(readingMeta("count", {
|
|
60163
|
+
precision: 0,
|
|
60164
|
+
label: "Reporting"
|
|
60165
|
+
})),
|
|
60166
|
+
/** Members left out: offline, unknown, or not a finite reading (D393). */
|
|
60167
|
+
excluded: number().int().nonnegative().meta(readingMeta("count", {
|
|
60168
|
+
precision: 0,
|
|
60169
|
+
label: "Excluded"
|
|
60170
|
+
})),
|
|
60171
|
+
/** `included` + `excluded`. */
|
|
60172
|
+
total: number().int().nonnegative().meta(readingMeta("count", {
|
|
60173
|
+
precision: 0,
|
|
60174
|
+
label: "Members"
|
|
60175
|
+
}))
|
|
60176
|
+
});
|
|
60177
|
+
var groupStatusCapability = {
|
|
60178
|
+
name: "group-status",
|
|
60179
|
+
scope: "device",
|
|
60180
|
+
deviceNative: true,
|
|
60181
|
+
mode: "singleton",
|
|
60182
|
+
deviceTypes: [
|
|
60183
|
+
DeviceType.Sensor,
|
|
60184
|
+
DeviceType.Switch,
|
|
60185
|
+
DeviceType.Light
|
|
60186
|
+
],
|
|
60187
|
+
methods: {},
|
|
60188
|
+
status: {
|
|
60189
|
+
schema: GroupStatusSchema,
|
|
60190
|
+
kind: "push"
|
|
60191
|
+
},
|
|
60192
|
+
runtimeState: GroupStatusSchema,
|
|
60193
|
+
/**
|
|
60194
|
+
* Runtime-state durability: **session** — recomputed from members on the
|
|
60195
|
+
* next source event; a restored count would outlive the readings it named.
|
|
60196
|
+
*
|
|
60197
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
60198
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
60199
|
+
*/
|
|
60200
|
+
durability: "session",
|
|
60201
|
+
history: "none"
|
|
60202
|
+
};
|
|
59758
60203
|
var HeatingValveStatusSchema = object({
|
|
59759
60204
|
/** Radiator valve opening 0 (closed) .. 100 (open). Null = not yet known. */
|
|
59760
|
-
position: number().min(0).max(100).nullable(),
|
|
60205
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59761
60206
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
59762
60207
|
lastFetchedAt: number()
|
|
59763
60208
|
});
|
|
@@ -59800,9 +60245,9 @@ var HumidifierStatusSchema = object({
|
|
|
59800
60245
|
/** Whether the humidifier is currently on. */
|
|
59801
60246
|
on: boolean(),
|
|
59802
60247
|
/** Current measured relative humidity (0..100). Null when not reported. */
|
|
59803
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
60248
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
59804
60249
|
/** Target relative humidity (0..100). Null when no setpoint surface. */
|
|
59805
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
60250
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
59806
60251
|
/** Active mode (`auto` / `normal` / `baby` / vendor). Null when the
|
|
59807
60252
|
* device has no mode surface. */
|
|
59808
60253
|
mode: string().nullable(),
|
|
@@ -59812,9 +60257,9 @@ var HumidifierStatusSchema = object({
|
|
|
59812
60257
|
* `idle` / `off`). Null when the device doesn't report it. */
|
|
59813
60258
|
action: string().nullable(),
|
|
59814
60259
|
/** HA `min_humidity` attribute. Null → UI uses 0. */
|
|
59815
|
-
minHumidity: number().nullable(),
|
|
60260
|
+
minHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
59816
60261
|
/** HA `max_humidity` attribute. Null → UI uses 100. */
|
|
59817
|
-
maxHumidity: number().nullable(),
|
|
60262
|
+
maxHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
59818
60263
|
/** Ms epoch when the slice was last updated. */
|
|
59819
60264
|
lastChangedAt: number()
|
|
59820
60265
|
});
|
|
@@ -59884,22 +60329,13 @@ var humidifierCapability = {
|
|
|
59884
60329
|
* `sourceInfo`.
|
|
59885
60330
|
*/
|
|
59886
60331
|
var HumiditySensorStatusSchema = object({
|
|
59887
|
-
/** Current relative humidity, 0..100. */
|
|
59888
|
-
percent: number().min(0).max(100).meta({
|
|
59889
|
-
|
|
60332
|
+
/** Current relative humidity, 0..100. `null` when the sample was refused (D393). */
|
|
60333
|
+
percent: number().min(0).max(100).nullable().meta(readingMeta("humidity", {
|
|
60334
|
+
precision: 0,
|
|
59890
60335
|
label: "Humidity"
|
|
59891
|
-
}),
|
|
60336
|
+
})),
|
|
59892
60337
|
/** Ms epoch when the slice was last updated. */
|
|
59893
|
-
lastFetchedAt: number()
|
|
59894
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
59895
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
59896
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
59897
|
-
unit: string().optional(),
|
|
59898
|
-
/** Suggested decimal places for numeric display.
|
|
59899
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
59900
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
59901
|
-
* auto-formatting when absent. */
|
|
59902
|
-
precision: number().int().min(0).max(10).optional()
|
|
60338
|
+
lastFetchedAt: number()
|
|
59903
60339
|
});
|
|
59904
60340
|
var humiditySensorCapability = {
|
|
59905
60341
|
name: "humidity-sensor",
|
|
@@ -59930,12 +60366,7 @@ var humiditySensorCapability = {
|
|
|
59930
60366
|
} } },
|
|
59931
60367
|
/** Clock fields: written, but excluded from the compare that decides
|
|
59932
60368
|
* whether persisting is worth a SQLite commit. */
|
|
59933
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
59934
|
-
customize: {
|
|
59935
|
-
version: 1,
|
|
59936
|
-
advanced: "derive",
|
|
59937
|
-
targets: []
|
|
59938
|
-
}
|
|
60369
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
59939
60370
|
};
|
|
59940
60371
|
/**
|
|
59941
60372
|
* Image display cap. Models a single still image exposed by an integration —
|
|
@@ -59956,7 +60387,7 @@ var ImageStatusSchema = object({
|
|
|
59956
60387
|
* entity exposes no `entity_picture` (yet). */
|
|
59957
60388
|
url: string().nullable(),
|
|
59958
60389
|
/** Ms epoch of the upstream last-updated timestamp. Null at cold-start. */
|
|
59959
|
-
lastUpdated: number().nullable()
|
|
60390
|
+
lastUpdated: number().nullable().meta(readingMeta("none"))
|
|
59960
60391
|
});
|
|
59961
60392
|
var imageCapability = {
|
|
59962
60393
|
name: "image",
|
|
@@ -60044,19 +60475,19 @@ var NormalizedRangeSchema = object({
|
|
|
60044
60475
|
*/
|
|
60045
60476
|
var ImageSettingsStatusSchema = object({
|
|
60046
60477
|
/** Normalized 0–100. */
|
|
60047
|
-
brightness: number().optional(),
|
|
60478
|
+
brightness: number().optional().meta(readingMeta("none")),
|
|
60048
60479
|
/** Normalized 0–100. */
|
|
60049
|
-
contrast: number().optional(),
|
|
60480
|
+
contrast: number().optional().meta(readingMeta("none")),
|
|
60050
60481
|
/** Normalized 0–100. */
|
|
60051
|
-
saturation: number().optional(),
|
|
60482
|
+
saturation: number().optional().meta(readingMeta("none")),
|
|
60052
60483
|
/** Normalized 0–100. */
|
|
60053
|
-
sharpness: number().optional(),
|
|
60484
|
+
sharpness: number().optional().meta(readingMeta("none")),
|
|
60054
60485
|
mirror: boolean().optional(),
|
|
60055
60486
|
flip: boolean().optional(),
|
|
60056
60487
|
rotate: ImageRotateSchema.optional(),
|
|
60057
60488
|
whiteBalance: WhiteBalanceModeSchema.optional(),
|
|
60058
60489
|
/** Manual white-balance warmth, NORMALIZED 0–100. Meaningful only when `whiteBalance === 'manual'`. */
|
|
60059
|
-
warmth: number().optional(),
|
|
60490
|
+
warmth: number().optional().meta(readingMeta("none")),
|
|
60060
60491
|
exposureMode: ExposureModeSchema.optional(),
|
|
60061
60492
|
backlightMode: BacklightModeSchema.optional(),
|
|
60062
60493
|
lastFetchedAt: number()
|
|
@@ -60335,10 +60766,10 @@ var IntercomAbilitySchema = object({
|
|
|
60335
60766
|
/** Codecs accepted by firmware, in preference order. Driver-authored strings. */
|
|
60336
60767
|
codecs: array(string()),
|
|
60337
60768
|
/** Sample rate (Hz) the firmware expects. Reolink typical: 16000. */
|
|
60338
|
-
sampleRate: number(),
|
|
60769
|
+
sampleRate: number().meta(readingMeta("none")),
|
|
60339
60770
|
duplex: _enum(["half", "full"]),
|
|
60340
60771
|
/** Max in-flight audio backlog before drop (ms). Server uses this to bound latency. */
|
|
60341
|
-
maxBacklogMs: number()
|
|
60772
|
+
maxBacklogMs: number().meta(readingMeta("duration-ms"))
|
|
60342
60773
|
});
|
|
60343
60774
|
var IntercomStatusSchema = object({
|
|
60344
60775
|
/** True while a talk session is open. */
|
|
@@ -60565,13 +60996,13 @@ var LawnMowerControlStatusSchema = object({
|
|
|
60565
60996
|
activity: LawnMowerActivitySchema,
|
|
60566
60997
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
60567
60998
|
* reading. */
|
|
60568
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
60999
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
60569
61000
|
/** 0..100 mowing-completion percentage of the current task, or null when no
|
|
60570
61001
|
* task is active / progress is unavailable. */
|
|
60571
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
61002
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
60572
61003
|
/** Current device/event code (dynamic — mostly status, sometimes an error),
|
|
60573
61004
|
* or null when unknown. */
|
|
60574
|
-
currentCode: number().nullable(),
|
|
61005
|
+
currentCode: number().nullable().meta(readingMeta("none")),
|
|
60575
61006
|
/** Human label for {@link currentCode}, or null when undecodable. */
|
|
60576
61007
|
currentCodeLabel: string().nullable(),
|
|
60577
61008
|
/** Severity of {@link currentCode}. `error` (and often `warning`) warrants UI
|
|
@@ -61104,7 +61535,7 @@ var MediaPlayerStatusSchema = object({
|
|
|
61104
61535
|
state: MediaPlayerStateSchema,
|
|
61105
61536
|
/** Volume as 0..100 inclusive. Null when the device has no volume
|
|
61106
61537
|
* surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
|
|
61107
|
-
volumeLevel: number().min(0).max(100).nullable(),
|
|
61538
|
+
volumeLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61108
61539
|
/** Mute toggle distinct from volume=0. Null when no mute surface.
|
|
61109
61540
|
* Pair with `DeviceFeature.MediaPlayerMute`. */
|
|
61110
61541
|
isMuted: boolean().nullable(),
|
|
@@ -61117,10 +61548,10 @@ var MediaPlayerStatusSchema = object({
|
|
|
61117
61548
|
currentMedia: MediaInfoSchema.nullable(),
|
|
61118
61549
|
/** Current playback position in ms. Null when not seekable or
|
|
61119
61550
|
* nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
|
|
61120
|
-
positionMs: number().int().nonnegative().nullable(),
|
|
61551
|
+
positionMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
61121
61552
|
/** Total duration of the current media in ms. Null when unknown
|
|
61122
61553
|
* (live stream) or nothing is playing. */
|
|
61123
|
-
durationMs: number().int().nonnegative().nullable(),
|
|
61554
|
+
durationMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
61124
61555
|
/** Shuffle toggle. Null when no shuffle surface.
|
|
61125
61556
|
* Pair with `DeviceFeature.MediaPlayerShuffle`. */
|
|
61126
61557
|
shuffle: boolean().nullable(),
|
|
@@ -61429,7 +61860,7 @@ var motionCustomize = {
|
|
|
61429
61860
|
eventName: "onMotionChanged"
|
|
61430
61861
|
},
|
|
61431
61862
|
deviceTypes: [DeviceType.Camera],
|
|
61432
|
-
apply: "
|
|
61863
|
+
apply: "add",
|
|
61433
61864
|
applyAuthority: {
|
|
61434
61865
|
kind: "camera-sensors",
|
|
61435
61866
|
timeoutField: "motionCooldownMs"
|
|
@@ -61501,7 +61932,7 @@ var MotionStatusSchema = object({
|
|
|
61501
61932
|
* it, every provider seeded it at boot, and every session left it
|
|
61502
61933
|
* `detected: true` after its detach.
|
|
61503
61934
|
*/
|
|
61504
|
-
autoClearAfterMs: number().nullable()
|
|
61935
|
+
autoClearAfterMs: number().nullable().meta(readingMeta("duration-ms"))
|
|
61505
61936
|
});
|
|
61506
61937
|
/**
|
|
61507
61938
|
* Payload of `motion.onMotionChanged` event + the corresponding bus
|
|
@@ -61538,12 +61969,18 @@ var motionCapability = {
|
|
|
61538
61969
|
methods: {
|
|
61539
61970
|
/**
|
|
61540
61971
|
* Pull the current motion state synchronously. Convenience shortcut
|
|
61541
|
-
* for consumers that don't need the full status object
|
|
61542
|
-
*
|
|
61543
|
-
* `getStatus` once the auto-injected status surface lands in every
|
|
61544
|
-
* consumer.
|
|
61972
|
+
* for consumers that don't need the full status object. A composed
|
|
61973
|
+
* group answers from its slice (D944): unknown throws, it is not off.
|
|
61545
61974
|
*/
|
|
61546
61975
|
isDetected: method(object({ deviceId: number() }), boolean()) },
|
|
61976
|
+
/**
|
|
61977
|
+
* A composed motion group serves `isDetected` from `detected` (D944).
|
|
61978
|
+
* Without this the cap stays uncomposable (`has-commands`).
|
|
61979
|
+
*/
|
|
61980
|
+
composedMethods: { isDetected: {
|
|
61981
|
+
kind: "slice",
|
|
61982
|
+
field: "detected"
|
|
61983
|
+
} },
|
|
61547
61984
|
events: {
|
|
61548
61985
|
/**
|
|
61549
61986
|
* Fires every time the runner transitions a camera between
|
|
@@ -61683,7 +62120,7 @@ var MotionZoneRegionSchema = object({
|
|
|
61683
62120
|
* the grid region(s). */
|
|
61684
62121
|
var MotionZoneStatusSchema = object({
|
|
61685
62122
|
enabled: boolean(),
|
|
61686
|
-
sensitivity: number(),
|
|
62123
|
+
sensitivity: number().meta(readingMeta("none")),
|
|
61687
62124
|
/** Grid region(s). Today exactly one `grid` shape. */
|
|
61688
62125
|
regions: array(MotionZoneRegionSchema),
|
|
61689
62126
|
lastFetchedAt: number()
|
|
@@ -62053,7 +62490,7 @@ var NavigationStatusSchema = object({
|
|
|
62053
62490
|
following: boolean(),
|
|
62054
62491
|
flash: boolean(),
|
|
62055
62492
|
lightMode: NavigationLightModeSchema,
|
|
62056
|
-
lightLevel: number().min(40).max(100),
|
|
62493
|
+
lightLevel: number().min(40).max(100).meta(readingMeta("none")),
|
|
62057
62494
|
/** Ms epoch when the slice was last updated. */
|
|
62058
62495
|
lastChangedAt: number()
|
|
62059
62496
|
});
|
|
@@ -62187,13 +62624,13 @@ var NetworkLinkStatusSchema = object({
|
|
|
62187
62624
|
* one whose reading has not landed must not be drawn at 0 %. Consumers
|
|
62188
62625
|
* SKIP a null rather than coerce it.
|
|
62189
62626
|
*/
|
|
62190
|
-
signalPercent: number().min(0).max(100).nullable(),
|
|
62627
|
+
signalPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
62191
62628
|
/** Raw received signal strength in dBm, when the firmware reports one. */
|
|
62192
|
-
rssiDbm: number().optional(),
|
|
62629
|
+
rssiDbm: number().optional().meta(readingMeta("signal-level")),
|
|
62193
62630
|
/** Network name of a wireless link, when the firmware reports it. */
|
|
62194
62631
|
ssid: string().optional(),
|
|
62195
62632
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
62196
|
-
lastUpdated: number()
|
|
62633
|
+
lastUpdated: number().meta(readingMeta("none"))
|
|
62197
62634
|
});
|
|
62198
62635
|
var networkLinkCapability = {
|
|
62199
62636
|
name: "network-link",
|
|
@@ -62578,7 +63015,7 @@ var NotifierStatusSchema = object({
|
|
|
62578
63015
|
lastError: string().nullable(),
|
|
62579
63016
|
/** Number of deliveries currently buffered server-side (rate-limited
|
|
62580
63017
|
* notifiers may queue). 0 when the provider sends synchronously. */
|
|
62581
|
-
queueDepth: number().int().nonnegative(),
|
|
63018
|
+
queueDepth: number().int().nonnegative().meta(readingMeta("count")),
|
|
62582
63019
|
/** Per-feature capability matrix — authoritative source for the
|
|
62583
63020
|
* compose-form field gating. */
|
|
62584
63021
|
supports: NotifierSupportsSchema
|
|
@@ -62670,11 +63107,9 @@ onSent: { data: object({
|
|
|
62670
63107
|
* cap fits (HA `sensor` whose `device_class` we don't have a typed cap
|
|
62671
63108
|
* for: water flow, distance, weight, frequency, signal strength, …).
|
|
62672
63109
|
*
|
|
62673
|
-
* The
|
|
62674
|
-
*
|
|
62675
|
-
*
|
|
62676
|
-
* The UI reads them directly from the slice — they are the single source
|
|
62677
|
-
* of truth for generic numeric rendering and do NOT live on `sourceInfo`.
|
|
63110
|
+
* The quantity is not on this slice. It is chosen when the device is
|
|
63111
|
+
* adopted and stored once on `SourceInfo.quantity` (D944). `value` is in
|
|
63112
|
+
* that quantity's base unit. `null` is a refused sample (D393).
|
|
62678
63113
|
*
|
|
62679
63114
|
* Prefer the typed alternatives (`temperature-sensor`, `humidity-sensor`,
|
|
62680
63115
|
* `ambient-light-sensor`, `pressure-sensor`, `power-meter`,
|
|
@@ -62683,15 +63118,8 @@ onSent: { data: object({
|
|
|
62683
63118
|
* numeric values land here.
|
|
62684
63119
|
*/
|
|
62685
63120
|
var NumericSensorStatusSchema = object({
|
|
62686
|
-
|
|
62687
|
-
|
|
62688
|
-
* Populated live from the upstream source on each state push.
|
|
62689
|
-
* Absent for unitless sensors. */
|
|
62690
|
-
unit: string().optional(),
|
|
62691
|
-
/** Suggested decimal places for numeric display.
|
|
62692
|
-
* Populated live from the upstream source when provided.
|
|
62693
|
-
* Falls back to auto-formatting when absent. */
|
|
62694
|
-
precision: number().int().min(0).max(10).optional(),
|
|
63121
|
+
/** Reading in the device quantity's base unit. `null` when refused (D393). */
|
|
63122
|
+
value: number().nullable().meta(readingMeta("device")),
|
|
62695
63123
|
/** Ms epoch when the slice was last updated. */
|
|
62696
63124
|
lastFetchedAt: number()
|
|
62697
63125
|
});
|
|
@@ -62715,11 +63143,11 @@ var numericSensorCapability = {
|
|
|
62715
63143
|
*/
|
|
62716
63144
|
durability: "restored",
|
|
62717
63145
|
/**
|
|
62718
|
-
* History (D850): recorded series. The unit is
|
|
63146
|
+
* History (D850): recorded series. The unit is the device quantity's base,
|
|
63147
|
+
* resolved when the series is read — the cap has no single unit.
|
|
62719
63148
|
*/
|
|
62720
63149
|
history: { fields: { value: {
|
|
62721
63150
|
kind: "gauge",
|
|
62722
|
-
unitFrom: "unit",
|
|
62723
63151
|
minIntervalMs: 3e4
|
|
62724
63152
|
} } },
|
|
62725
63153
|
/** Clock fields: written, but excluded from the compare that decides
|
|
@@ -63011,23 +63439,26 @@ var PetFeederStatusSchema = object({
|
|
|
63011
63439
|
/** Food currently in the bowl (grams). Null when the device has not
|
|
63012
63440
|
* reported a reading yet. On dual-hopper models this is the combined
|
|
63013
63441
|
* bowl reading; per-hopper levels live in `food1`/`food2`. */
|
|
63014
|
-
foodLevel: number().nullable(),
|
|
63442
|
+
foodLevel: number().nullable().meta(readingMeta("none")),
|
|
63015
63443
|
/** Hopper-1 food level (grams) on dual-hopper feeders; null on
|
|
63016
63444
|
* single-hopper models. */
|
|
63017
|
-
food1: number().nullable(),
|
|
63445
|
+
food1: number().nullable().meta(readingMeta("none")),
|
|
63018
63446
|
/** Hopper-2 food level (grams) on dual-hopper feeders; null on
|
|
63019
63447
|
* single-hopper models. */
|
|
63020
|
-
food2: number().nullable(),
|
|
63448
|
+
food2: number().nullable().meta(readingMeta("none")),
|
|
63021
63449
|
/** Derived low-food flag — mirrors the HA `food_level` binary_sensor
|
|
63022
63450
|
* (`device_class: problem`, on = low). True when the bowl is empty /
|
|
63023
63451
|
* below the feeder's low threshold. */
|
|
63024
63452
|
lowFood: boolean(),
|
|
63025
63453
|
/** Battery charge 0..100 (%). Null on mains-powered models or when the
|
|
63026
63454
|
* device has no battery reading. */
|
|
63027
|
-
batteryPower: number().min(0).max(100).nullable(),
|
|
63028
|
-
/**
|
|
63029
|
-
*
|
|
63030
|
-
|
|
63455
|
+
batteryPower: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
63456
|
+
/**
|
|
63457
|
+
* Desiccant life remaining, stored in seconds (duration base, D944).
|
|
63458
|
+
* Providers convert from the days the feeder reports. Null when the
|
|
63459
|
+
* model has no desiccant sensor.
|
|
63460
|
+
*/
|
|
63461
|
+
desiccantLeftDays: number().nullable().meta(readingMeta("duration")),
|
|
63031
63462
|
/** True while a feed is in progress. */
|
|
63032
63463
|
feeding: boolean(),
|
|
63033
63464
|
/** Decoded connectivity / power status (HA petkit device-status enum).
|
|
@@ -63038,7 +63469,7 @@ var PetFeederStatusSchema = object({
|
|
|
63038
63469
|
* with `errorCode` for consumers that want the raw integer. */
|
|
63039
63470
|
error: string().nullable(),
|
|
63040
63471
|
/** Raw device error code (0 / null = no error). */
|
|
63041
|
-
errorCode: number().nullable(),
|
|
63472
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
63042
63473
|
/** True for D4S/D4SH dual-hopper hardware — gates the per-hopper UI. */
|
|
63043
63474
|
isDualHopper: boolean(),
|
|
63044
63475
|
/** Child-lock (manual-lock) setting — buttons on the unit are disabled. */
|
|
@@ -63048,7 +63479,7 @@ var PetFeederStatusSchema = object({
|
|
|
63048
63479
|
/** Play a chime when dispensing. */
|
|
63049
63480
|
feedSound: boolean(),
|
|
63050
63481
|
/** Speaker / prompt volume level (device-scaled integer). */
|
|
63051
|
-
volume: number(),
|
|
63482
|
+
volume: number().meta(readingMeta("none")),
|
|
63052
63483
|
/** Ms epoch when the slice was last refreshed from the cloud. */
|
|
63053
63484
|
lastFetchedAt: number()
|
|
63054
63485
|
});
|
|
@@ -63167,7 +63598,7 @@ var petFeederCapability = {
|
|
|
63167
63598
|
},
|
|
63168
63599
|
desiccantLeftDays: {
|
|
63169
63600
|
kind: "gauge",
|
|
63170
|
-
unit: "
|
|
63601
|
+
unit: "s"
|
|
63171
63602
|
}
|
|
63172
63603
|
} }
|
|
63173
63604
|
};
|
|
@@ -63568,36 +63999,19 @@ method(_void(), PlatformCapabilitiesSchema), method(_void(), HardwareInfoSchema)
|
|
|
63568
63999
|
*/
|
|
63569
64000
|
var PowerMeterStatusSchema = object({
|
|
63570
64001
|
/** Instantaneous power draw in watts. */
|
|
63571
|
-
watts: number().optional().meta({
|
|
63572
|
-
unit: "W",
|
|
63573
|
-
label: "Power"
|
|
63574
|
-
}),
|
|
64002
|
+
watts: number().optional().meta(readingMeta("power", { label: "Power" })),
|
|
63575
64003
|
/** Cumulative energy in kilowatt-hours since the meter was reset. */
|
|
63576
|
-
kwhTotal: number().optional().meta({
|
|
63577
|
-
unit: "kWh",
|
|
63578
|
-
label: "Energy"
|
|
63579
|
-
}),
|
|
64004
|
+
kwhTotal: number().optional().meta(readingMeta("energy", { label: "Energy" })),
|
|
63580
64005
|
/** Voltage in volts. */
|
|
63581
|
-
volts: number().optional(),
|
|
64006
|
+
volts: number().optional().meta(readingMeta("voltage")),
|
|
63582
64007
|
/** Current in amperes. */
|
|
63583
|
-
amps: number().optional(),
|
|
63584
|
-
/** Apparent power in volt-amperes
|
|
63585
|
-
va: number().optional(),
|
|
64008
|
+
amps: number().optional().meta(readingMeta("current")),
|
|
64009
|
+
/** Apparent power in volt-amperes. */
|
|
64010
|
+
va: number().optional().meta(readingMeta("apparent-power")),
|
|
63586
64011
|
/** Power factor (0..1) if reported. */
|
|
63587
|
-
powerFactor: number().min(0).max(1).optional(),
|
|
64012
|
+
powerFactor: number().min(0).max(1).optional().meta(readingMeta("ratio")),
|
|
63588
64013
|
/** Ms epoch when the slice was last updated. */
|
|
63589
|
-
lastFetchedAt: number()
|
|
63590
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
63591
|
-
* `attributes.unit_of_measurement` → 'V' / 'A' / 'W' / 'kW' / 'kWh').
|
|
63592
|
-
* Each upstream `sensor.*` entity surfaces ONE device_class, so one
|
|
63593
|
-
* unit per slice is unambiguous. The UI prefers this over the role's
|
|
63594
|
-
* canonical unit so a 'kW' / 'Wh' feed renders verbatim. */
|
|
63595
|
-
unit: string().optional(),
|
|
63596
|
-
/** Suggested decimal places for numeric display.
|
|
63597
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
63598
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
63599
|
-
* auto-formatting when absent. */
|
|
63600
|
-
precision: number().int().min(0).max(10).optional()
|
|
64014
|
+
lastFetchedAt: number()
|
|
63601
64015
|
});
|
|
63602
64016
|
var powerMeterCapability = {
|
|
63603
64017
|
name: "power-meter",
|
|
@@ -63661,12 +64075,7 @@ var powerMeterCapability = {
|
|
|
63661
64075
|
} },
|
|
63662
64076
|
/** Clock fields: written, but excluded from the compare that decides
|
|
63663
64077
|
* whether persisting is worth a SQLite commit. */
|
|
63664
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
63665
|
-
customize: {
|
|
63666
|
-
version: 1,
|
|
63667
|
-
advanced: "derive",
|
|
63668
|
-
targets: []
|
|
63669
|
-
}
|
|
64078
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
63670
64079
|
};
|
|
63671
64080
|
/**
|
|
63672
64081
|
* Presence cap. Models HA `person.*` and `device_tracker.*` entities
|
|
@@ -63686,11 +64095,11 @@ var powerMeterCapability = {
|
|
|
63686
64095
|
*/
|
|
63687
64096
|
var GpsLocationSchema = object({
|
|
63688
64097
|
/** Latitude in decimal degrees, -90..90. */
|
|
63689
|
-
latitude: number().min(-90).max(90),
|
|
64098
|
+
latitude: number().min(-90).max(90).meta(readingMeta("angle")),
|
|
63690
64099
|
/** Longitude in decimal degrees, -180..180. */
|
|
63691
|
-
longitude: number().min(-180).max(180),
|
|
64100
|
+
longitude: number().min(-180).max(180).meta(readingMeta("angle")),
|
|
63692
64101
|
/** Reported accuracy in meters (lower = better). */
|
|
63693
|
-
accuracyMeters: number().nonnegative()
|
|
64102
|
+
accuracyMeters: number().nonnegative().meta(readingMeta("length"))
|
|
63694
64103
|
});
|
|
63695
64104
|
var PresenceStatusSchema = object({
|
|
63696
64105
|
/** `home` / `not_home` / any user-defined zone name. */
|
|
@@ -63702,7 +64111,7 @@ var PresenceStatusSchema = object({
|
|
|
63702
64111
|
gps: GpsLocationSchema.nullable(),
|
|
63703
64112
|
/** Optional battery level of the tracking device (0..100). Null
|
|
63704
64113
|
* when not reported. */
|
|
63705
|
-
batteryPercent: number().min(0).max(100).nullable(),
|
|
64114
|
+
batteryPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
63706
64115
|
/** Ms epoch when the slice was last updated. */
|
|
63707
64116
|
lastChangedAt: number()
|
|
63708
64117
|
});
|
|
@@ -63752,19 +64161,10 @@ var presenceCapability = {
|
|
|
63752
64161
|
* `sourceInfo`.
|
|
63753
64162
|
*/
|
|
63754
64163
|
var PressureSensorStatusSchema = object({
|
|
63755
|
-
/** Current pressure in hPa. */
|
|
63756
|
-
hpa: number(),
|
|
64164
|
+
/** Current pressure in hPa. `null` when the sample was refused (D393). */
|
|
64165
|
+
hpa: number().nullable().meta(readingMeta("pressure", { precision: 0 })),
|
|
63757
64166
|
/** Ms epoch when the slice was last updated. */
|
|
63758
|
-
lastFetchedAt: number()
|
|
63759
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
63760
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
63761
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
63762
|
-
unit: string().optional(),
|
|
63763
|
-
/** Suggested decimal places for numeric display.
|
|
63764
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
63765
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
63766
|
-
* auto-formatting when absent. */
|
|
63767
|
-
precision: number().int().min(0).max(10).optional()
|
|
64167
|
+
lastFetchedAt: number()
|
|
63768
64168
|
});
|
|
63769
64169
|
var pressureSensorCapability = {
|
|
63770
64170
|
name: "pressure-sensor",
|
|
@@ -64178,8 +64578,8 @@ DeviceType.Camera, method(PtzMoveCommandSchema.extend({ deviceId: number() }), _
|
|
|
64178
64578
|
}), _void(), { kind: "mutation" });
|
|
64179
64579
|
var PtzAutotrackSettingsSchema = object({
|
|
64180
64580
|
targetType: string().describe("Vendor target string (people/vehicle/pet); empty = camera default"),
|
|
64181
|
-
stopDelaySeconds: number().int().min(0).max(300),
|
|
64182
|
-
disappearDelaySeconds: number().int().min(0).max(300)
|
|
64581
|
+
stopDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration")),
|
|
64582
|
+
disappearDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration"))
|
|
64183
64583
|
});
|
|
64184
64584
|
/**
|
|
64185
64585
|
* One option the camera advertises as a valid `targetType`. Drivers
|
|
@@ -64333,7 +64733,7 @@ var RunningStateStatusSchema = object({
|
|
|
64333
64733
|
/** null = unknown — never coerced to false (D393). */
|
|
64334
64734
|
running: boolean().nullable(),
|
|
64335
64735
|
/** Epoch ms the current boolean began; null while `running` is null. */
|
|
64336
|
-
since: number().nullable(),
|
|
64736
|
+
since: number().nullable().meta(readingMeta("none")),
|
|
64337
64737
|
source: RunningStateSourceSchema.meta({ label: "Source" }),
|
|
64338
64738
|
phase: string().nullable(),
|
|
64339
64739
|
/** null until a reading has been published (D393). */
|
|
@@ -64348,7 +64748,6 @@ var RUNNING_DEVICE_TYPES = Object.values(DeviceType);
|
|
|
64348
64748
|
/** Generic Customize target for the running boolean (D936). */
|
|
64349
64749
|
var runningCustomize = {
|
|
64350
64750
|
version: 1,
|
|
64351
|
-
advanced: "derive",
|
|
64352
64751
|
targets: [{
|
|
64353
64752
|
id: "running",
|
|
64354
64753
|
cardinality: "scalar",
|
|
@@ -64368,7 +64767,7 @@ var runningCustomize = {
|
|
|
64368
64767
|
DeviceType.Thermostat,
|
|
64369
64768
|
DeviceType.PetFeeder
|
|
64370
64769
|
],
|
|
64371
|
-
apply: "add
|
|
64770
|
+
apply: "add",
|
|
64372
64771
|
path: "running",
|
|
64373
64772
|
sources: [
|
|
64374
64773
|
{
|
|
@@ -65632,9 +66031,9 @@ var RecordTriggerSchema = _enum([
|
|
|
65632
66031
|
*/
|
|
65633
66032
|
var RecordWindowSchema = object({
|
|
65634
66033
|
trigger: RecordTriggerSchema,
|
|
65635
|
-
day: number().int().min(0).max(6),
|
|
65636
|
-
startMinute: number().int().min(0).max(1439),
|
|
65637
|
-
endMinute: number().int().min(1).max(1440)
|
|
66034
|
+
day: number().int().min(0).max(6).meta(readingMeta("none")),
|
|
66035
|
+
startMinute: number().int().min(0).max(1439).meta(readingMeta("none")),
|
|
66036
|
+
endMinute: number().int().min(1).max(1440).meta(readingMeta("none"))
|
|
65638
66037
|
});
|
|
65639
66038
|
/** Status of one physical volume, as the camera itself describes it. */
|
|
65640
66039
|
var OnboardStorageVolumeSchema = object({
|
|
@@ -65710,10 +66109,10 @@ var RecordingOnboardStatusSchema = object({
|
|
|
65710
66109
|
/** Master "record to the card at all" switch. */
|
|
65711
66110
|
enabled: boolean().nullable(),
|
|
65712
66111
|
overwriteWhenFull: boolean().nullable(),
|
|
65713
|
-
preRecordSec: number().nullable(),
|
|
65714
|
-
postRecordSec: number().nullable(),
|
|
66112
|
+
preRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
66113
|
+
postRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
65715
66114
|
/** Length of one recorded file, in minutes. */
|
|
65716
|
-
segmentMinutes: number().nullable(),
|
|
66115
|
+
segmentMinutes: number().nullable().meta(readingMeta("none")),
|
|
65717
66116
|
/** The primary track's weekly windows, flattened. */
|
|
65718
66117
|
windows: array(RecordWindowSchema),
|
|
65719
66118
|
/**
|
|
@@ -65729,7 +66128,7 @@ var RecordingOnboardStatusSchema = object({
|
|
|
65729
66128
|
* provider reporting a non-zero count also reports the schedule as not
|
|
65730
66129
|
* writable.
|
|
65731
66130
|
*/
|
|
65732
|
-
unreadableWindows: number(),
|
|
66131
|
+
unreadableWindows: number().meta(readingMeta("count")),
|
|
65733
66132
|
/**
|
|
65734
66133
|
* The camera is scheduled to record and has NO usable storage.
|
|
65735
66134
|
*
|
|
@@ -66574,7 +66973,7 @@ var CamStreamDescriptorSchema = object({
|
|
|
66574
66973
|
url: string().optional(),
|
|
66575
66974
|
codec: string().optional(),
|
|
66576
66975
|
resolution: CamStreamResolutionSchema.optional(),
|
|
66577
|
-
fps: number().positive().optional(),
|
|
66976
|
+
fps: number().positive().optional().meta(readingMeta("rate")),
|
|
66578
66977
|
label: string().optional(),
|
|
66579
66978
|
/** Device-level features (e.g. `battery-operated`) — drives broker policy. */
|
|
66580
66979
|
deviceFeatures: array(string()).optional(),
|
|
@@ -66661,18 +67060,18 @@ var StreamProfileSchema = _enum([
|
|
|
66661
67060
|
]);
|
|
66662
67061
|
/** The current encoding config of one stream profile. */
|
|
66663
67062
|
var StreamProfileConfigSchema = object({
|
|
66664
|
-
width: number(),
|
|
66665
|
-
height: number(),
|
|
67063
|
+
width: number().meta(readingMeta("none")),
|
|
67064
|
+
height: number().meta(readingMeta("none")),
|
|
66666
67065
|
codec: _enum(["h264", "h265"]),
|
|
66667
|
-
framerate: number(),
|
|
66668
|
-
bitrate: number(),
|
|
67066
|
+
framerate: number().meta(readingMeta("rate")),
|
|
67067
|
+
bitrate: number().meta(readingMeta("bitrate")),
|
|
66669
67068
|
bitrateMode: _enum(["vbr", "cbr"]).optional(),
|
|
66670
67069
|
encoderProfile: _enum([
|
|
66671
67070
|
"high",
|
|
66672
67071
|
"main",
|
|
66673
67072
|
"baseline"
|
|
66674
67073
|
]).optional(),
|
|
66675
|
-
gop: number().optional(),
|
|
67074
|
+
gop: number().optional().meta(readingMeta("none")),
|
|
66676
67075
|
/**
|
|
66677
67076
|
* Whether THIS profile currently carries an audio track. READ-ONLY here.
|
|
66678
67077
|
*
|
|
@@ -66893,12 +67292,7 @@ var switchCapability = {
|
|
|
66893
67292
|
label: "On",
|
|
66894
67293
|
kind: "boolean"
|
|
66895
67294
|
}
|
|
66896
|
-
}] }
|
|
66897
|
-
customize: {
|
|
66898
|
-
version: 1,
|
|
66899
|
-
advanced: "derive",
|
|
66900
|
-
targets: []
|
|
66901
|
-
}
|
|
67295
|
+
}] }
|
|
66902
67296
|
};
|
|
66903
67297
|
/** C0 controls, DEL and the C1 range: none of them belongs in a name. */
|
|
66904
67298
|
function hasControlCharacter(value) {
|
|
@@ -67481,35 +67875,21 @@ var tamperCapability = {
|
|
|
67481
67875
|
* entries with `device_class: temperature` and any future native
|
|
67482
67876
|
* thermometer.
|
|
67483
67877
|
*
|
|
67484
|
-
*
|
|
67485
|
-
*
|
|
67486
|
-
* (climate-control's `currentTemp`, energy analytics) can compose
|
|
67487
|
-
* without per-source unit fixups. The canonical display unit (`°C`) is
|
|
67488
|
-
* a descriptor constant in the UI (ROLE_DESCRIPTOR), not stored in
|
|
67489
|
-
* `sourceInfo`.
|
|
67878
|
+
* The number is Celsius (D944). Providers convert on ingest. A failed
|
|
67879
|
+
* conversion is `null`, never a guess. Display unit is a read-time preference.
|
|
67490
67880
|
*
|
|
67491
67881
|
* Status `lastFetchedAt` lets staleness-aware consumers detect a
|
|
67492
67882
|
* frozen feed (provider hung) distinct from a "temperature hasn't
|
|
67493
67883
|
* changed" steady state.
|
|
67494
67884
|
*/
|
|
67495
67885
|
var TemperatureSensorStatusSchema = object({
|
|
67496
|
-
/** Current temperature in Celsius. */
|
|
67497
|
-
celsius: number().meta({
|
|
67498
|
-
|
|
67886
|
+
/** Current temperature in Celsius. `null` when the sample was refused (D393). */
|
|
67887
|
+
celsius: number().nullable().meta(readingMeta("temperature", {
|
|
67888
|
+
precision: 1,
|
|
67499
67889
|
label: "Temperature"
|
|
67500
|
-
}),
|
|
67890
|
+
})),
|
|
67501
67891
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
67502
|
-
lastFetchedAt: number()
|
|
67503
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
67504
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
67505
|
-
* role's canonical unit, so a Fahrenheit feed renders '°F' not '°C'.
|
|
67506
|
-
* Absent → the UI falls back to the role's canonical unit. */
|
|
67507
|
-
unit: string().optional(),
|
|
67508
|
-
/** Suggested decimal places for numeric display.
|
|
67509
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
67510
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
67511
|
-
* auto-formatting when absent. */
|
|
67512
|
-
precision: number().int().min(0).max(10).optional()
|
|
67892
|
+
lastFetchedAt: number()
|
|
67513
67893
|
});
|
|
67514
67894
|
var temperatureSensorCapability = {
|
|
67515
67895
|
name: "temperature-sensor",
|
|
@@ -67540,12 +67920,7 @@ var temperatureSensorCapability = {
|
|
|
67540
67920
|
} } },
|
|
67541
67921
|
/** Clock fields: written, but excluded from the compare that decides
|
|
67542
67922
|
* whether persisting is worth a SQLite commit. */
|
|
67543
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
67544
|
-
customize: {
|
|
67545
|
-
version: 1,
|
|
67546
|
-
advanced: "derive",
|
|
67547
|
-
targets: []
|
|
67548
|
-
}
|
|
67923
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
67549
67924
|
};
|
|
67550
67925
|
/**
|
|
67551
67926
|
* toast — system-scoped singleton capability that streams toast
|
|
@@ -67828,16 +68203,16 @@ var VacuumControlStatusSchema = object({
|
|
|
67828
68203
|
]),
|
|
67829
68204
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
67830
68205
|
* reading. */
|
|
67831
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
68206
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
67832
68207
|
/** Current fan-speed token (provider-verbatim). Null when unknown or
|
|
67833
68208
|
* the vacuum has no speed control. */
|
|
67834
68209
|
fanSpeed: string().nullable(),
|
|
67835
68210
|
/** Speed tokens the hardware accepts — drives the UI selector. */
|
|
67836
68211
|
availableFanSpeeds: array(string()),
|
|
67837
68212
|
/** 0..100 cleaning-completion percentage of the current task, or null. */
|
|
67838
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
68213
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
67839
68214
|
/** Current error code (0 / null = no error). */
|
|
67840
|
-
errorCode: number().nullable(),
|
|
68215
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
67841
68216
|
/** Human label for {@link errorCode}, or null when none / undecodable. */
|
|
67842
68217
|
errorLabel: string().nullable(),
|
|
67843
68218
|
/** Ms epoch when the slice was last updated. */
|
|
@@ -67915,7 +68290,7 @@ var ValveStatusSchema = object({
|
|
|
67915
68290
|
]),
|
|
67916
68291
|
/** 0 = fully closed, 100 = fully open. Null when the device has no
|
|
67917
68292
|
* intermediate position surface. */
|
|
67918
|
-
position: number().min(0).max(100).nullable(),
|
|
68293
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
67919
68294
|
/** Ms epoch when the slice was last updated. */
|
|
67920
68295
|
lastChangedAt: number()
|
|
67921
68296
|
});
|
|
@@ -68023,9 +68398,9 @@ var vibrationCapability = {
|
|
|
68023
68398
|
*/
|
|
68024
68399
|
var WaterHeaterStatusSchema = object({
|
|
68025
68400
|
/** Current measured temperature. Null when not reported. */
|
|
68026
|
-
currentTemp: number().nullable(),
|
|
68401
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
68027
68402
|
/** Target temperature setpoint. Null when no setpoint surface. */
|
|
68028
|
-
targetTemp: number().nullable(),
|
|
68403
|
+
targetTemp: number().nullable().meta(readingMeta("temperature")),
|
|
68029
68404
|
/** Active operation mode = HA `state` (`eco` / `electric` / `gas` /
|
|
68030
68405
|
* `heat_pump` / `high_demand` / `performance` / `off`). Null when the
|
|
68031
68406
|
* device reports an unknown state. */
|
|
@@ -68036,9 +68411,9 @@ var WaterHeaterStatusSchema = object({
|
|
|
68036
68411
|
* has no away surface. */
|
|
68037
68412
|
away: boolean().nullable(),
|
|
68038
68413
|
/** HA `min_temp` attribute. Null when not reported. */
|
|
68039
|
-
minTemp: number().nullable(),
|
|
68414
|
+
minTemp: number().nullable().meta(readingMeta("temperature")),
|
|
68040
68415
|
/** HA `max_temp` attribute. Null when not reported. */
|
|
68041
|
-
maxTemp: number().nullable(),
|
|
68416
|
+
maxTemp: number().nullable().meta(readingMeta("temperature")),
|
|
68042
68417
|
/** Ms epoch when the slice was last updated. */
|
|
68043
68418
|
lastChangedAt: number()
|
|
68044
68419
|
});
|
|
@@ -68123,25 +68498,18 @@ var waterHeaterCapability = {
|
|
|
68123
68498
|
* Forecast deferred — current conditions only for v1.
|
|
68124
68499
|
*/
|
|
68125
68500
|
var WeatherStatusSchema = object({
|
|
68126
|
-
/** Verbatim
|
|
68127
|
-
* when no condition has been reported yet. */
|
|
68501
|
+
/** Verbatim condition state (`sunny`, `cloudy`, `rainy`, …). Null when none yet. */
|
|
68128
68502
|
condition: string().nullable(),
|
|
68129
|
-
/** Current temperature in
|
|
68130
|
-
temperature: number().nullable(),
|
|
68131
|
-
/** Temperature unit string (e.g. `°C` / `°F`). Null when not provided. */
|
|
68132
|
-
temperatureUnit: string().nullable(),
|
|
68503
|
+
/** Current temperature in Celsius. Null when not provided or refused. */
|
|
68504
|
+
temperature: number().nullable().meta(readingMeta("temperature", { precision: 1 })),
|
|
68133
68505
|
/** Relative humidity (0..100). Null when not provided. */
|
|
68134
|
-
humidity: number().min(0).max(100).nullable(),
|
|
68135
|
-
/** Barometric pressure in
|
|
68136
|
-
pressure: number().nullable(),
|
|
68137
|
-
/**
|
|
68138
|
-
|
|
68139
|
-
/** Wind speed in the reported unit. Null when not provided. */
|
|
68140
|
-
windSpeed: number().nullable(),
|
|
68141
|
-
/** Wind-speed unit string (e.g. `km/h` / `mph`). Null when not provided. */
|
|
68142
|
-
windSpeedUnit: string().nullable(),
|
|
68506
|
+
humidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
68507
|
+
/** Barometric pressure in hPa. Null when not provided or refused. */
|
|
68508
|
+
pressure: number().nullable().meta(readingMeta("pressure")),
|
|
68509
|
+
/** Wind speed in metres per second. Null when not provided or refused. */
|
|
68510
|
+
windSpeed: number().nullable().meta(readingMeta("speed")),
|
|
68143
68511
|
/** Wind bearing in degrees (0..360, meteorological). Null when not provided. */
|
|
68144
|
-
windBearing: number().nullable(),
|
|
68512
|
+
windBearing: number().nullable().meta(readingMeta("angle")),
|
|
68145
68513
|
/** Ms epoch when the slice was last updated. */
|
|
68146
68514
|
lastFetchedAt: number()
|
|
68147
68515
|
});
|
|
@@ -68169,12 +68537,12 @@ var weatherCapability = {
|
|
|
68169
68537
|
*/
|
|
68170
68538
|
durability: "session",
|
|
68171
68539
|
/**
|
|
68172
|
-
* History (D850): recorded series.
|
|
68540
|
+
* History (D850): recorded series. Numbers are the quantity base (D944).
|
|
68173
68541
|
*/
|
|
68174
68542
|
history: { fields: {
|
|
68175
68543
|
temperature: {
|
|
68176
68544
|
kind: "gauge",
|
|
68177
|
-
|
|
68545
|
+
unit: "°C",
|
|
68178
68546
|
deadband: .2
|
|
68179
68547
|
},
|
|
68180
68548
|
humidity: {
|
|
@@ -68184,12 +68552,12 @@ var weatherCapability = {
|
|
|
68184
68552
|
},
|
|
68185
68553
|
pressure: {
|
|
68186
68554
|
kind: "gauge",
|
|
68187
|
-
|
|
68555
|
+
unit: "hPa",
|
|
68188
68556
|
deadband: .5
|
|
68189
68557
|
},
|
|
68190
68558
|
windSpeed: {
|
|
68191
68559
|
kind: "gauge",
|
|
68192
|
-
|
|
68560
|
+
unit: "m/s",
|
|
68193
68561
|
deadband: .5
|
|
68194
68562
|
}
|
|
68195
68563
|
} }
|
|
@@ -69420,6 +69788,8 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
69420
69788
|
featureProbe: featureProbeCapability,
|
|
69421
69789
|
flood: floodCapability,
|
|
69422
69790
|
gas: gasCapability,
|
|
69791
|
+
groupCommands: groupCommandsCapability,
|
|
69792
|
+
groupStatus: groupStatusCapability,
|
|
69423
69793
|
heatingValve: heatingValveCapability,
|
|
69424
69794
|
humidifier: humidifierCapability,
|
|
69425
69795
|
humiditySensor: humiditySensorCapability,
|
|
@@ -70313,6 +70683,13 @@ Object.freeze({
|
|
|
70313
70683
|
access: "view",
|
|
70314
70684
|
role: "admin"
|
|
70315
70685
|
},
|
|
70686
|
+
"addons.getPackageDocs": {
|
|
70687
|
+
capName: "addons",
|
|
70688
|
+
capScope: "system",
|
|
70689
|
+
addonId: null,
|
|
70690
|
+
access: "view",
|
|
70691
|
+
role: "admin"
|
|
70692
|
+
},
|
|
70316
70693
|
"addons.getVersions": {
|
|
70317
70694
|
capName: "addons",
|
|
70318
70695
|
capScope: "system",
|
|
@@ -73421,6 +73798,20 @@ Object.freeze({
|
|
|
73421
73798
|
access: "view",
|
|
73422
73799
|
role: "viewer"
|
|
73423
73800
|
},
|
|
73801
|
+
"groupCommands.getStatus": {
|
|
73802
|
+
capName: "group-commands",
|
|
73803
|
+
capScope: "device",
|
|
73804
|
+
addonId: null,
|
|
73805
|
+
access: "view",
|
|
73806
|
+
role: "viewer"
|
|
73807
|
+
},
|
|
73808
|
+
"groupStatus.getStatus": {
|
|
73809
|
+
capName: "group-status",
|
|
73810
|
+
capScope: "device",
|
|
73811
|
+
addonId: null,
|
|
73812
|
+
access: "view",
|
|
73813
|
+
role: "viewer"
|
|
73814
|
+
},
|
|
73424
73815
|
"heatingValve.getStatus": {
|
|
73425
73816
|
capName: "heating-valve",
|
|
73426
73817
|
capScope: "device",
|
|
@@ -83243,6 +83634,37 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83243
83634
|
icon: "flame"
|
|
83244
83635
|
}]
|
|
83245
83636
|
},
|
|
83637
|
+
"group-commands": {
|
|
83638
|
+
scope: "device",
|
|
83639
|
+
noun: t("Group command", "Comando di gruppo")
|
|
83640
|
+
},
|
|
83641
|
+
"group-status": {
|
|
83642
|
+
scope: "device",
|
|
83643
|
+
noun: t("Group", "Gruppo"),
|
|
83644
|
+
state: [
|
|
83645
|
+
{
|
|
83646
|
+
kind: "numeric",
|
|
83647
|
+
field: "included",
|
|
83648
|
+
quantity: t("the members reporting", "i membri che rispondono"),
|
|
83649
|
+
label: t("Reporting", "Rispondono"),
|
|
83650
|
+
icon: "users"
|
|
83651
|
+
},
|
|
83652
|
+
{
|
|
83653
|
+
kind: "numeric",
|
|
83654
|
+
field: "excluded",
|
|
83655
|
+
quantity: t("the members left out", "i membri esclusi"),
|
|
83656
|
+
label: t("Excluded", "Esclusi"),
|
|
83657
|
+
icon: "users"
|
|
83658
|
+
},
|
|
83659
|
+
{
|
|
83660
|
+
kind: "numeric",
|
|
83661
|
+
field: "total",
|
|
83662
|
+
quantity: t("the member count", "il numero di membri"),
|
|
83663
|
+
label: t("Members", "Membri"),
|
|
83664
|
+
icon: "sigma"
|
|
83665
|
+
}
|
|
83666
|
+
]
|
|
83667
|
+
},
|
|
83246
83668
|
"humidity-sensor": {
|
|
83247
83669
|
scope: "device",
|
|
83248
83670
|
noun: t("Humidity", "Umidità"),
|
|
@@ -83276,7 +83698,6 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83276
83698
|
field: "value",
|
|
83277
83699
|
quantity: t("the reading", "il valore"),
|
|
83278
83700
|
label: t("Reading", "Valore"),
|
|
83279
|
-
unitField: "unit",
|
|
83280
83701
|
icon: "gauge"
|
|
83281
83702
|
}]
|
|
83282
83703
|
},
|
|
@@ -83412,7 +83833,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83412
83833
|
field: "temperature",
|
|
83413
83834
|
quantity: t("the outdoor temperature", "la temperatura esterna"),
|
|
83414
83835
|
label: t("Temperature", "Temperatura"),
|
|
83415
|
-
|
|
83836
|
+
unit: "°C",
|
|
83416
83837
|
icon: "thermometer"
|
|
83417
83838
|
},
|
|
83418
83839
|
{
|
|
@@ -83428,7 +83849,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83428
83849
|
field: "windSpeed",
|
|
83429
83850
|
quantity: t("the wind speed", "la velocità del vento"),
|
|
83430
83851
|
label: t("Wind", "Vento"),
|
|
83431
|
-
|
|
83852
|
+
unit: "m/s",
|
|
83432
83853
|
icon: "wind"
|
|
83433
83854
|
},
|
|
83434
83855
|
{
|
|
@@ -83436,7 +83857,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83436
83857
|
field: "pressure",
|
|
83437
83858
|
quantity: t("the air pressure", "la pressione atmosferica"),
|
|
83438
83859
|
label: t("Pressure", "Pressione"),
|
|
83439
|
-
|
|
83860
|
+
unit: "hPa",
|
|
83440
83861
|
icon: "gauge"
|
|
83441
83862
|
}
|
|
83442
83863
|
]
|
|
@@ -84709,6 +85130,16 @@ Object.freeze({
|
|
|
84709
85130
|
form: "single",
|
|
84710
85131
|
optional: false
|
|
84711
85132
|
}],
|
|
85133
|
+
"groupCommands.getStatus": [{
|
|
85134
|
+
name: "deviceId",
|
|
85135
|
+
form: "single",
|
|
85136
|
+
optional: false
|
|
85137
|
+
}],
|
|
85138
|
+
"groupStatus.getStatus": [{
|
|
85139
|
+
name: "deviceId",
|
|
85140
|
+
form: "single",
|
|
85141
|
+
optional: false
|
|
85142
|
+
}],
|
|
84712
85143
|
"heatingValve.getStatus": [{
|
|
84713
85144
|
name: "deviceId",
|
|
84714
85145
|
form: "single",
|
|
@@ -86693,6 +87124,8 @@ new Map(Object.entries({
|
|
|
86693
87124
|
"detection-blind": "device-events",
|
|
86694
87125
|
"motion-noisy": "device-events",
|
|
86695
87126
|
"motion-calm": "device-events",
|
|
87127
|
+
"package-llm-silent": "device-events",
|
|
87128
|
+
"package-llm-answered": "device-events",
|
|
86696
87129
|
"recording-stalled": "device-events",
|
|
86697
87130
|
"recording-healthy": "device-events",
|
|
86698
87131
|
"recording-degraded": "device-events",
|
|
@@ -86776,6 +87209,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
|
|
|
86776
87209
|
label: "Motion without a subject",
|
|
86777
87210
|
kinds: ["motion-noisy", "motion-calm"]
|
|
86778
87211
|
},
|
|
87212
|
+
{
|
|
87213
|
+
id: "package-llm",
|
|
87214
|
+
family: "device-events",
|
|
87215
|
+
label: "Package confirm",
|
|
87216
|
+
kinds: ["package-llm-silent", "package-llm-answered"]
|
|
87217
|
+
},
|
|
86779
87218
|
{
|
|
86780
87219
|
id: "recording",
|
|
86781
87220
|
family: "device-events",
|
|
@@ -86957,6 +87396,8 @@ var DEVICE_EVENTS = [
|
|
|
86957
87396
|
"detection-blind",
|
|
86958
87397
|
"motion-noisy",
|
|
86959
87398
|
"motion-calm",
|
|
87399
|
+
"package-llm-silent",
|
|
87400
|
+
"package-llm-answered",
|
|
86960
87401
|
"recording-stalled",
|
|
86961
87402
|
"recording-healthy",
|
|
86962
87403
|
"recording-degraded",
|
|
@@ -87225,6 +87666,15 @@ new Map([
|
|
|
87225
87666
|
snapshotLabel: "Cameras with constant motion now",
|
|
87226
87667
|
snapshotSection: null
|
|
87227
87668
|
},
|
|
87669
|
+
{
|
|
87670
|
+
id: "package-llm-confirm",
|
|
87671
|
+
family: "device-events",
|
|
87672
|
+
label: "Package confirm (not answering / answering again)",
|
|
87673
|
+
bad: ["package-llm-silent"],
|
|
87674
|
+
recovery: ["package-llm-answered"],
|
|
87675
|
+
snapshotLabel: "Cameras whose package confirm is not answering",
|
|
87676
|
+
snapshotSection: null
|
|
87677
|
+
},
|
|
87228
87678
|
{
|
|
87229
87679
|
id: "recording-health",
|
|
87230
87680
|
family: "device-events",
|