@camstack/addon-provider-amcrest 0.2.160 → 0.2.161
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 +20 -0
- package/dist/addon.js +959 -509
- package/dist/addon.mjs +959 -509
- package/package.json +4 -2
package/dist/addon.mjs
CHANGED
|
@@ -14,7 +14,7 @@ import { networkInterfaces } from "node:os";
|
|
|
14
14
|
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
|
|
15
15
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
16
16
|
//#endregion
|
|
17
|
-
//#region ../types/dist/event-category-
|
|
17
|
+
//#region ../types/dist/event-category-CT-hz5Rb.mjs
|
|
18
18
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
19
19
|
EventCategory["SystemBoot"] = "system.boot";
|
|
20
20
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -340,6 +340,14 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
340
340
|
/** The recovery edge of {@link PipelineMotionNoisy}: the motion fell back, or a detection arrived. */
|
|
341
341
|
EventCategory["PipelineMotionCalm"] = "pipeline.motion-calm";
|
|
342
342
|
/**
|
|
343
|
+
* A camera's package LLM confirm has failed closed three times in a row
|
|
344
|
+
* (D931, 2026-10-26). One edge per camera until
|
|
345
|
+
* {@link PipelinePackageLlmAnswered}.
|
|
346
|
+
*/
|
|
347
|
+
EventCategory["PipelinePackageLlmSilent"] = "pipeline.package-llm-silent";
|
|
348
|
+
/** The recovery edge of {@link PipelinePackageLlmSilent}: a confirm returned yes or no. */
|
|
349
|
+
EventCategory["PipelinePackageLlmAnswered"] = "pipeline.package-llm-answered";
|
|
350
|
+
/**
|
|
343
351
|
* Per-camera pipeline config was mutated by the orchestrator
|
|
344
352
|
* (a settings change via `setAgentInferenceDevices` /
|
|
345
353
|
* `setCameraStepToggle` / `setCameraStepSettings`). Orchestrator
|
|
@@ -5449,7 +5457,7 @@ var ZodIssueCode = {
|
|
|
5449
5457
|
var ZodFirstPartyTypeKind;
|
|
5450
5458
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5451
5459
|
//#endregion
|
|
5452
|
-
//#region ../types/dist/sleep-
|
|
5460
|
+
//#region ../types/dist/sleep-bykKrTgu.mjs
|
|
5453
5461
|
/**
|
|
5454
5462
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5455
5463
|
* window to float samples (D455).
|
|
@@ -8003,6 +8011,99 @@ var RecordKindDeclarationSchema = object({
|
|
|
8003
8011
|
}).strict();
|
|
8004
8012
|
/** The kind names: lower-case, dash separated, short enough for an index name. */
|
|
8005
8013
|
var RecordKindNameSchema = string().regex(/^[a-z][a-z0-9-]{0,47}$/);
|
|
8014
|
+
var READING_QUANTITIES = [
|
|
8015
|
+
"temperature",
|
|
8016
|
+
"pressure",
|
|
8017
|
+
"speed",
|
|
8018
|
+
"precipitation",
|
|
8019
|
+
"precipitation-rate",
|
|
8020
|
+
"length",
|
|
8021
|
+
"area",
|
|
8022
|
+
"illuminance",
|
|
8023
|
+
"irradiance",
|
|
8024
|
+
"power",
|
|
8025
|
+
"energy",
|
|
8026
|
+
"voltage",
|
|
8027
|
+
"current",
|
|
8028
|
+
"apparent-power",
|
|
8029
|
+
"humidity",
|
|
8030
|
+
"percentage",
|
|
8031
|
+
"concentration-volume",
|
|
8032
|
+
"concentration-mass",
|
|
8033
|
+
"concentration-ppb",
|
|
8034
|
+
"volume",
|
|
8035
|
+
"duration",
|
|
8036
|
+
"duration-ms",
|
|
8037
|
+
"information",
|
|
8038
|
+
"sound-level",
|
|
8039
|
+
"signal-level",
|
|
8040
|
+
"colour-temperature",
|
|
8041
|
+
"angle",
|
|
8042
|
+
"bitrate",
|
|
8043
|
+
"rate",
|
|
8044
|
+
"mass",
|
|
8045
|
+
"index",
|
|
8046
|
+
"ratio",
|
|
8047
|
+
"count",
|
|
8048
|
+
"none",
|
|
8049
|
+
"device"
|
|
8050
|
+
];
|
|
8051
|
+
var ReadingQuantitySchema = _enum(READING_QUANTITIES);
|
|
8052
|
+
new Set(READING_QUANTITIES);
|
|
8053
|
+
/**
|
|
8054
|
+
* Stored unit symbol for a quantity. `none` means the number is dimensionless
|
|
8055
|
+
* (or an index / ratio / count). `device` means the cap has no single unit.
|
|
8056
|
+
*/
|
|
8057
|
+
var QUANTITY_BASE = {
|
|
8058
|
+
temperature: "°C",
|
|
8059
|
+
pressure: "hPa",
|
|
8060
|
+
speed: "m/s",
|
|
8061
|
+
precipitation: "mm",
|
|
8062
|
+
"precipitation-rate": "mm/h",
|
|
8063
|
+
length: "m",
|
|
8064
|
+
area: "m²",
|
|
8065
|
+
illuminance: "lx",
|
|
8066
|
+
irradiance: "W/m²",
|
|
8067
|
+
power: "W",
|
|
8068
|
+
energy: "kWh",
|
|
8069
|
+
voltage: "V",
|
|
8070
|
+
current: "A",
|
|
8071
|
+
"apparent-power": "VA",
|
|
8072
|
+
humidity: "%",
|
|
8073
|
+
percentage: "%",
|
|
8074
|
+
"concentration-volume": "ppm",
|
|
8075
|
+
"concentration-mass": "µg/m³",
|
|
8076
|
+
"concentration-ppb": "ppb",
|
|
8077
|
+
volume: "L",
|
|
8078
|
+
duration: "s",
|
|
8079
|
+
"duration-ms": "ms",
|
|
8080
|
+
information: "B",
|
|
8081
|
+
"sound-level": "dBFS",
|
|
8082
|
+
"signal-level": "dBm",
|
|
8083
|
+
"colour-temperature": "mired",
|
|
8084
|
+
angle: "°",
|
|
8085
|
+
bitrate: "kbps",
|
|
8086
|
+
rate: "fps",
|
|
8087
|
+
mass: "kg",
|
|
8088
|
+
index: "none",
|
|
8089
|
+
ratio: "none",
|
|
8090
|
+
count: "none",
|
|
8091
|
+
none: "none",
|
|
8092
|
+
device: "device"
|
|
8093
|
+
};
|
|
8094
|
+
/** The stored unit, or `undefined` when the quantity has no unit symbol. */
|
|
8095
|
+
function baseUnitOf(quantity) {
|
|
8096
|
+
const symbol = QUANTITY_BASE[quantity];
|
|
8097
|
+
if (symbol === "none" || symbol === "device") return void 0;
|
|
8098
|
+
return symbol;
|
|
8099
|
+
}
|
|
8100
|
+
function readingMeta(quantity, extras) {
|
|
8101
|
+
return {
|
|
8102
|
+
quantity,
|
|
8103
|
+
...extras?.precision !== void 0 ? { precision: extras.precision } : {},
|
|
8104
|
+
...extras?.label !== void 0 ? { label: extras.label } : {}
|
|
8105
|
+
};
|
|
8106
|
+
}
|
|
8006
8107
|
/** Shared Zod schemas used across streaming capabilities. */
|
|
8007
8108
|
var CamProfileSchema = _enum([
|
|
8008
8109
|
"high",
|
|
@@ -8030,8 +8131,8 @@ var CamStreamKindSchema = _enum([
|
|
|
8030
8131
|
"derived"
|
|
8031
8132
|
]);
|
|
8032
8133
|
var CamStreamResolutionSchema = object({
|
|
8033
|
-
width: number().int().positive(),
|
|
8034
|
-
height: number().int().positive()
|
|
8134
|
+
width: number().int().positive().meta(readingMeta("none")),
|
|
8135
|
+
height: number().int().positive().meta(readingMeta("none"))
|
|
8035
8136
|
});
|
|
8036
8137
|
var CameraStreamSchema = object({
|
|
8037
8138
|
/** Stable, provider-assigned id unique within the (deviceId) scope. */
|
|
@@ -8549,6 +8650,8 @@ var CAP_NAMES = Object.freeze([
|
|
|
8549
8650
|
"filesystem-browse",
|
|
8550
8651
|
"flood",
|
|
8551
8652
|
"gas",
|
|
8653
|
+
"group-commands",
|
|
8654
|
+
"group-status",
|
|
8552
8655
|
"heating-valve",
|
|
8553
8656
|
"humidifier",
|
|
8554
8657
|
"humidity-sensor",
|
|
@@ -8678,14 +8781,6 @@ Object.freeze({
|
|
|
8678
8781
|
{
|
|
8679
8782
|
"path": "aqi",
|
|
8680
8783
|
"valueType": "number"
|
|
8681
|
-
},
|
|
8682
|
-
{
|
|
8683
|
-
"path": "unit",
|
|
8684
|
-
"valueType": "string"
|
|
8685
|
-
},
|
|
8686
|
-
{
|
|
8687
|
-
"path": "precision",
|
|
8688
|
-
"valueType": "number"
|
|
8689
8784
|
}
|
|
8690
8785
|
],
|
|
8691
8786
|
"alarm-panel": [
|
|
@@ -8721,20 +8816,10 @@ Object.freeze({
|
|
|
8721
8816
|
"valueType": "boolean"
|
|
8722
8817
|
}
|
|
8723
8818
|
],
|
|
8724
|
-
"ambient-light-sensor": [
|
|
8725
|
-
|
|
8726
|
-
|
|
8727
|
-
|
|
8728
|
-
},
|
|
8729
|
-
{
|
|
8730
|
-
"path": "unit",
|
|
8731
|
-
"valueType": "string"
|
|
8732
|
-
},
|
|
8733
|
-
{
|
|
8734
|
-
"path": "precision",
|
|
8735
|
-
"valueType": "number"
|
|
8736
|
-
}
|
|
8737
|
-
],
|
|
8819
|
+
"ambient-light-sensor": [{
|
|
8820
|
+
"path": "lux",
|
|
8821
|
+
"valueType": "number"
|
|
8822
|
+
}],
|
|
8738
8823
|
"audio-metrics": [
|
|
8739
8824
|
{
|
|
8740
8825
|
"path": "ts",
|
|
@@ -8814,6 +8899,10 @@ Object.freeze({
|
|
|
8814
8899
|
"path": "lastUpdated",
|
|
8815
8900
|
"valueType": "number"
|
|
8816
8901
|
},
|
|
8902
|
+
{
|
|
8903
|
+
"path": "volts",
|
|
8904
|
+
"valueType": "number"
|
|
8905
|
+
},
|
|
8817
8906
|
{
|
|
8818
8907
|
"path": "lastContactAt",
|
|
8819
8908
|
"valueType": "number"
|
|
@@ -9056,10 +9145,6 @@ Object.freeze({
|
|
|
9056
9145
|
"datetime"
|
|
9057
9146
|
]
|
|
9058
9147
|
},
|
|
9059
|
-
{
|
|
9060
|
-
"path": "unit",
|
|
9061
|
-
"valueType": "string"
|
|
9062
|
-
},
|
|
9063
9148
|
{
|
|
9064
9149
|
"path": "min",
|
|
9065
9150
|
"valueType": "number"
|
|
@@ -9071,19 +9156,6 @@ Object.freeze({
|
|
|
9071
9156
|
{
|
|
9072
9157
|
"path": "step",
|
|
9073
9158
|
"valueType": "number"
|
|
9074
|
-
},
|
|
9075
|
-
{
|
|
9076
|
-
"path": "precision",
|
|
9077
|
-
"valueType": "number"
|
|
9078
|
-
},
|
|
9079
|
-
{
|
|
9080
|
-
"path": "format",
|
|
9081
|
-
"valueType": "enum",
|
|
9082
|
-
"enumValues": [
|
|
9083
|
-
"date",
|
|
9084
|
-
"time",
|
|
9085
|
-
"datetime"
|
|
9086
|
-
]
|
|
9087
9159
|
}
|
|
9088
9160
|
],
|
|
9089
9161
|
"cover": [
|
|
@@ -9324,13 +9396,8 @@ Object.freeze({
|
|
|
9324
9396
|
"path": "value",
|
|
9325
9397
|
"valueType": "string"
|
|
9326
9398
|
}, {
|
|
9327
|
-
"path": "
|
|
9328
|
-
"valueType": "
|
|
9329
|
-
"enumValues": [
|
|
9330
|
-
"date",
|
|
9331
|
-
"time",
|
|
9332
|
-
"datetime"
|
|
9333
|
-
]
|
|
9399
|
+
"path": "timestamp",
|
|
9400
|
+
"valueType": "boolean"
|
|
9334
9401
|
}],
|
|
9335
9402
|
"event-emitter": [
|
|
9336
9403
|
{
|
|
@@ -9403,6 +9470,20 @@ Object.freeze({
|
|
|
9403
9470
|
"path": "detected",
|
|
9404
9471
|
"valueType": "boolean"
|
|
9405
9472
|
}],
|
|
9473
|
+
"group-status": [
|
|
9474
|
+
{
|
|
9475
|
+
"path": "included",
|
|
9476
|
+
"valueType": "number"
|
|
9477
|
+
},
|
|
9478
|
+
{
|
|
9479
|
+
"path": "excluded",
|
|
9480
|
+
"valueType": "number"
|
|
9481
|
+
},
|
|
9482
|
+
{
|
|
9483
|
+
"path": "total",
|
|
9484
|
+
"valueType": "number"
|
|
9485
|
+
}
|
|
9486
|
+
],
|
|
9406
9487
|
"heating-valve": [{
|
|
9407
9488
|
"path": "position",
|
|
9408
9489
|
"valueType": "number"
|
|
@@ -9437,20 +9518,10 @@ Object.freeze({
|
|
|
9437
9518
|
"valueType": "number"
|
|
9438
9519
|
}
|
|
9439
9520
|
],
|
|
9440
|
-
"humidity-sensor": [
|
|
9441
|
-
|
|
9442
|
-
|
|
9443
|
-
|
|
9444
|
-
},
|
|
9445
|
-
{
|
|
9446
|
-
"path": "unit",
|
|
9447
|
-
"valueType": "string"
|
|
9448
|
-
},
|
|
9449
|
-
{
|
|
9450
|
-
"path": "precision",
|
|
9451
|
-
"valueType": "number"
|
|
9452
|
-
}
|
|
9453
|
-
],
|
|
9521
|
+
"humidity-sensor": [{
|
|
9522
|
+
"path": "percent",
|
|
9523
|
+
"valueType": "number"
|
|
9524
|
+
}],
|
|
9454
9525
|
"image": [{
|
|
9455
9526
|
"path": "url",
|
|
9456
9527
|
"valueType": "string"
|
|
@@ -9789,20 +9860,10 @@ Object.freeze({
|
|
|
9789
9860
|
"valueType": "boolean"
|
|
9790
9861
|
}
|
|
9791
9862
|
],
|
|
9792
|
-
"numeric-sensor": [
|
|
9793
|
-
|
|
9794
|
-
|
|
9795
|
-
|
|
9796
|
-
},
|
|
9797
|
-
{
|
|
9798
|
-
"path": "unit",
|
|
9799
|
-
"valueType": "string"
|
|
9800
|
-
},
|
|
9801
|
-
{
|
|
9802
|
-
"path": "precision",
|
|
9803
|
-
"valueType": "number"
|
|
9804
|
-
}
|
|
9805
|
-
],
|
|
9863
|
+
"numeric-sensor": [{
|
|
9864
|
+
"path": "value",
|
|
9865
|
+
"valueType": "number"
|
|
9866
|
+
}],
|
|
9806
9867
|
"pet-feeder": [
|
|
9807
9868
|
{
|
|
9808
9869
|
"path": "foodLevel",
|
|
@@ -9894,14 +9955,6 @@ Object.freeze({
|
|
|
9894
9955
|
{
|
|
9895
9956
|
"path": "powerFactor",
|
|
9896
9957
|
"valueType": "number"
|
|
9897
|
-
},
|
|
9898
|
-
{
|
|
9899
|
-
"path": "unit",
|
|
9900
|
-
"valueType": "string"
|
|
9901
|
-
},
|
|
9902
|
-
{
|
|
9903
|
-
"path": "precision",
|
|
9904
|
-
"valueType": "number"
|
|
9905
9958
|
}
|
|
9906
9959
|
],
|
|
9907
9960
|
"presence": [
|
|
@@ -9930,20 +9983,10 @@ Object.freeze({
|
|
|
9930
9983
|
"valueType": "number"
|
|
9931
9984
|
}
|
|
9932
9985
|
],
|
|
9933
|
-
"pressure-sensor": [
|
|
9934
|
-
|
|
9935
|
-
|
|
9936
|
-
|
|
9937
|
-
},
|
|
9938
|
-
{
|
|
9939
|
-
"path": "unit",
|
|
9940
|
-
"valueType": "string"
|
|
9941
|
-
},
|
|
9942
|
-
{
|
|
9943
|
-
"path": "precision",
|
|
9944
|
-
"valueType": "number"
|
|
9945
|
-
}
|
|
9946
|
-
],
|
|
9986
|
+
"pressure-sensor": [{
|
|
9987
|
+
"path": "hpa",
|
|
9988
|
+
"valueType": "number"
|
|
9989
|
+
}],
|
|
9947
9990
|
"privacy-mask": [{
|
|
9948
9991
|
"path": "enabled",
|
|
9949
9992
|
"valueType": "boolean"
|
|
@@ -10254,20 +10297,10 @@ Object.freeze({
|
|
|
10254
10297
|
"path": "tampered",
|
|
10255
10298
|
"valueType": "boolean"
|
|
10256
10299
|
}],
|
|
10257
|
-
"temperature-sensor": [
|
|
10258
|
-
|
|
10259
|
-
|
|
10260
|
-
|
|
10261
|
-
},
|
|
10262
|
-
{
|
|
10263
|
-
"path": "unit",
|
|
10264
|
-
"valueType": "string"
|
|
10265
|
-
},
|
|
10266
|
-
{
|
|
10267
|
-
"path": "precision",
|
|
10268
|
-
"valueType": "number"
|
|
10269
|
-
}
|
|
10270
|
-
],
|
|
10300
|
+
"temperature-sensor": [{
|
|
10301
|
+
"path": "celsius",
|
|
10302
|
+
"valueType": "number"
|
|
10303
|
+
}],
|
|
10271
10304
|
"update": [
|
|
10272
10305
|
{
|
|
10273
10306
|
"path": "currentVersion",
|
|
@@ -10378,10 +10411,6 @@ Object.freeze({
|
|
|
10378
10411
|
"path": "temperature",
|
|
10379
10412
|
"valueType": "number"
|
|
10380
10413
|
},
|
|
10381
|
-
{
|
|
10382
|
-
"path": "temperatureUnit",
|
|
10383
|
-
"valueType": "string"
|
|
10384
|
-
},
|
|
10385
10414
|
{
|
|
10386
10415
|
"path": "humidity",
|
|
10387
10416
|
"valueType": "number"
|
|
@@ -10390,18 +10419,10 @@ Object.freeze({
|
|
|
10390
10419
|
"path": "pressure",
|
|
10391
10420
|
"valueType": "number"
|
|
10392
10421
|
},
|
|
10393
|
-
{
|
|
10394
|
-
"path": "pressureUnit",
|
|
10395
|
-
"valueType": "string"
|
|
10396
|
-
},
|
|
10397
10422
|
{
|
|
10398
10423
|
"path": "windSpeed",
|
|
10399
10424
|
"valueType": "number"
|
|
10400
10425
|
},
|
|
10401
|
-
{
|
|
10402
|
-
"path": "windSpeedUnit",
|
|
10403
|
-
"valueType": "string"
|
|
10404
|
-
},
|
|
10405
10426
|
{
|
|
10406
10427
|
"path": "windBearing",
|
|
10407
10428
|
"valueType": "number"
|
|
@@ -10808,7 +10829,7 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
|
|
|
10808
10829
|
return DeviceRole;
|
|
10809
10830
|
}({});
|
|
10810
10831
|
//#endregion
|
|
10811
|
-
//#region ../types/dist/composition-
|
|
10832
|
+
//#region ../types/dist/composition-OhpuespA.mjs
|
|
10812
10833
|
/**
|
|
10813
10834
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
10814
10835
|
*
|
|
@@ -11563,15 +11584,74 @@ function validateExpressionSource(src) {
|
|
|
11563
11584
|
}
|
|
11564
11585
|
return null;
|
|
11565
11586
|
}
|
|
11566
|
-
/**
|
|
11567
|
-
|
|
11568
|
-
|
|
11569
|
-
|
|
11587
|
+
/**
|
|
11588
|
+
* A composition source identity: `(addonId, stableId)`, never a numeric device
|
|
11589
|
+
* id. Split out so helper schemas can name it without a cycle through
|
|
11590
|
+
* `composition.ts` (D659).
|
|
11591
|
+
*/
|
|
11570
11592
|
var CompositionSourceRefSchema = object({
|
|
11571
11593
|
/** The owning addon; `stableId` is unique only within it. */
|
|
11572
11594
|
addonId: string().min(1),
|
|
11573
11595
|
stableId: string().min(1)
|
|
11574
11596
|
});
|
|
11597
|
+
var GROUP_TEMPLATE_IDS = [
|
|
11598
|
+
"temperature",
|
|
11599
|
+
"humidity",
|
|
11600
|
+
"pressure",
|
|
11601
|
+
"illuminance",
|
|
11602
|
+
"power",
|
|
11603
|
+
"energy",
|
|
11604
|
+
"battery",
|
|
11605
|
+
"numeric",
|
|
11606
|
+
"motion",
|
|
11607
|
+
"contact",
|
|
11608
|
+
"leak",
|
|
11609
|
+
"smoke",
|
|
11610
|
+
"occupancy",
|
|
11611
|
+
"binary",
|
|
11612
|
+
"switch",
|
|
11613
|
+
"light"
|
|
11614
|
+
];
|
|
11615
|
+
var NUMERIC_AGGREGATES = [
|
|
11616
|
+
"mean",
|
|
11617
|
+
"median",
|
|
11618
|
+
"min",
|
|
11619
|
+
"max",
|
|
11620
|
+
"sum"
|
|
11621
|
+
];
|
|
11622
|
+
var BINARY_AGGREGATES = ["any", "all"];
|
|
11623
|
+
/** How an actuator group decides it is on. Unknown members never count as off. */
|
|
11624
|
+
var ACTIVE_CRITERIA = ["at-least-one", "all"];
|
|
11625
|
+
var AGGREGATE_REDUCERS = [
|
|
11626
|
+
"mean",
|
|
11627
|
+
"median",
|
|
11628
|
+
"min",
|
|
11629
|
+
"max",
|
|
11630
|
+
"sum",
|
|
11631
|
+
"any",
|
|
11632
|
+
"all"
|
|
11633
|
+
];
|
|
11634
|
+
var GroupTemplateIdSchema = _enum(GROUP_TEMPLATE_IDS);
|
|
11635
|
+
var AggregateReducerSchema = _enum(AGGREGATE_REDUCERS);
|
|
11636
|
+
var ActiveCriterionSchema = _enum(ACTIVE_CRITERIA);
|
|
11637
|
+
/** One member. The field is stored so occupancy can name motion or binary. */
|
|
11638
|
+
var HelperMemberSchema = object({
|
|
11639
|
+
source: CompositionSourceRefSchema,
|
|
11640
|
+
cap: string().min(1),
|
|
11641
|
+
fieldPath: string().min(1)
|
|
11642
|
+
});
|
|
11643
|
+
var HelperSpecSchema = discriminatedUnion("kind", [object({
|
|
11644
|
+
kind: literal("group"),
|
|
11645
|
+
templateId: GroupTemplateIdSchema,
|
|
11646
|
+
aggregate: AggregateReducerSchema,
|
|
11647
|
+
members: array(HelperMemberSchema).min(1).max(64),
|
|
11648
|
+
/** Actuator groups only. Readings leave this unset. */
|
|
11649
|
+
active: ActiveCriterionSchema.optional()
|
|
11650
|
+
})]);
|
|
11651
|
+
/** A composed device's stableId is this prefix plus the block id. */
|
|
11652
|
+
var COMPOSED_DEVICE_STABLE_ID_PREFIX = "composed-";
|
|
11653
|
+
/** Longest snippet a `code` source may carry (slice 4). */
|
|
11654
|
+
var MAX_COMPOSITION_CODE_LENGTH = 2e4;
|
|
11575
11655
|
/** One field of one capability of one source device. */
|
|
11576
11656
|
var CompositionFieldReadSchema = object({
|
|
11577
11657
|
source: CompositionSourceRefSchema,
|
|
@@ -11615,7 +11695,33 @@ var CompositionCodeSourceSchema = object({
|
|
|
11615
11695
|
var CompositionFieldSourceSchema = discriminatedUnion("kind", [
|
|
11616
11696
|
CompositionFromSourceSchema,
|
|
11617
11697
|
CompositionExpressionSourceSchema,
|
|
11618
|
-
CompositionCodeSourceSchema
|
|
11698
|
+
CompositionCodeSourceSchema,
|
|
11699
|
+
object({
|
|
11700
|
+
kind: literal("aggregate"),
|
|
11701
|
+
reducer: _enum([
|
|
11702
|
+
"mean",
|
|
11703
|
+
"median",
|
|
11704
|
+
"min",
|
|
11705
|
+
"max",
|
|
11706
|
+
"sum",
|
|
11707
|
+
"any",
|
|
11708
|
+
"all"
|
|
11709
|
+
]),
|
|
11710
|
+
reads: array(CompositionFieldReadSchema).min(1).max(64),
|
|
11711
|
+
/** `value` is the reading; the others are the member counts. */
|
|
11712
|
+
publish: _enum([
|
|
11713
|
+
"value",
|
|
11714
|
+
"included",
|
|
11715
|
+
"excluded",
|
|
11716
|
+
"total"
|
|
11717
|
+
]),
|
|
11718
|
+
/** What a `value` publish does when nobody is included. Counts ignore this. */
|
|
11719
|
+
empty: _enum([
|
|
11720
|
+
"null",
|
|
11721
|
+
"omit",
|
|
11722
|
+
"offline"
|
|
11723
|
+
])
|
|
11724
|
+
})
|
|
11619
11725
|
]);
|
|
11620
11726
|
var CompositionCommandTargetSchema = discriminatedUnion("kind", [object({
|
|
11621
11727
|
kind: literal("forward"),
|
|
@@ -11661,7 +11767,13 @@ var CompositionSchema = object({
|
|
|
11661
11767
|
kind: literal("existing"),
|
|
11662
11768
|
device: CompositionSourceRefSchema
|
|
11663
11769
|
})]),
|
|
11664
|
-
features: array(CompositionFeatureSchema).min(1).max(16)
|
|
11770
|
+
features: array(CompositionFeatureSchema).min(1).max(16),
|
|
11771
|
+
/**
|
|
11772
|
+
* Present when the block is a helper template. Absent on a free
|
|
11773
|
+
* composition (the room example, device 4603). The editor reads this,
|
|
11774
|
+
* never the compiled features.
|
|
11775
|
+
*/
|
|
11776
|
+
helper: HelperSpecSchema.optional()
|
|
11665
11777
|
}).superRefine((composition, ctx) => {
|
|
11666
11778
|
const seen = /* @__PURE__ */ new Set();
|
|
11667
11779
|
composition.features.forEach((feature, index) => {
|
|
@@ -17907,7 +18019,11 @@ var CompositionProblemSchema = object({
|
|
|
17907
18019
|
"item-field-reserved",
|
|
17908
18020
|
"target-missing",
|
|
17909
18021
|
"target-unreadable",
|
|
17910
|
-
"not-replaceable"
|
|
18022
|
+
"not-replaceable",
|
|
18023
|
+
"native-capability-replace",
|
|
18024
|
+
"mixed-quantity",
|
|
18025
|
+
"helper-mismatch",
|
|
18026
|
+
"member-constraint"
|
|
17911
18027
|
]),
|
|
17912
18028
|
path: string(),
|
|
17913
18029
|
message: string()
|
|
@@ -17928,7 +18044,8 @@ var CompositionUnavailableModeSchema = _enum([
|
|
|
17928
18044
|
"null",
|
|
17929
18045
|
"offline",
|
|
17930
18046
|
"unknown",
|
|
17931
|
-
"release"
|
|
18047
|
+
"release",
|
|
18048
|
+
"omit"
|
|
17932
18049
|
]);
|
|
17933
18050
|
/**
|
|
17934
18051
|
* `derived` reads a source · `clock` reads only `now`, recomputed when a sibling
|
|
@@ -17965,9 +18082,11 @@ var CompositionFieldPlanSchema = object({
|
|
|
17965
18082
|
reads: array(CompositionFieldReadSchema)
|
|
17966
18083
|
});
|
|
17967
18084
|
/**
|
|
17968
|
-
* What a feature does to its target (D663): `new` builds a capability on a
|
|
17969
|
-
* device; on an existing device it `add`s a capability the device lacks
|
|
17970
|
-
*
|
|
18085
|
+
* What a feature does to its target (D663, D944): `new` builds a capability on a
|
|
18086
|
+
* new device; on an existing device it `add`s a capability the device lacks.
|
|
18087
|
+
* Replacing a capability the device already serves is refused
|
|
18088
|
+
* (`native-capability-replace`), not planned. `replace` remains on the claim
|
|
18089
|
+
* wire for a claim the hub already holds.
|
|
17971
18090
|
*/
|
|
17972
18091
|
var CompositionFeatureModeSchema = _enum([
|
|
17973
18092
|
"new",
|
|
@@ -18140,6 +18259,275 @@ Object.freeze({
|
|
|
18140
18259
|
result: ["number", "null"]
|
|
18141
18260
|
}
|
|
18142
18261
|
});
|
|
18262
|
+
/**
|
|
18263
|
+
* One catalog row per base reading a group helper can build (D944 §3).
|
|
18264
|
+
* Data, not a form default written into the block.
|
|
18265
|
+
*/
|
|
18266
|
+
var NOW = {
|
|
18267
|
+
fieldPath: "lastFetchedAt",
|
|
18268
|
+
expr: "now"
|
|
18269
|
+
};
|
|
18270
|
+
var CHANGED = {
|
|
18271
|
+
fieldPath: "lastChangedAt",
|
|
18272
|
+
expr: "now"
|
|
18273
|
+
};
|
|
18274
|
+
function numeric(input) {
|
|
18275
|
+
return {
|
|
18276
|
+
...input,
|
|
18277
|
+
family: "numeric",
|
|
18278
|
+
deviceType: DeviceType.Sensor,
|
|
18279
|
+
memberDeviceType: DeviceType.Sensor,
|
|
18280
|
+
commandCaps: [],
|
|
18281
|
+
baseUnit: baseUnitOf(input.quantity),
|
|
18282
|
+
aggregates: NUMERIC_AGGREGATES,
|
|
18283
|
+
accept: [{
|
|
18284
|
+
cap: input.outputCap,
|
|
18285
|
+
fieldPath: input.outputField
|
|
18286
|
+
}]
|
|
18287
|
+
};
|
|
18288
|
+
}
|
|
18289
|
+
function binary(input) {
|
|
18290
|
+
return {
|
|
18291
|
+
...input,
|
|
18292
|
+
family: "binary",
|
|
18293
|
+
deviceType: DeviceType.Sensor,
|
|
18294
|
+
memberDeviceType: DeviceType.Sensor,
|
|
18295
|
+
commandCaps: [],
|
|
18296
|
+
quantity: "none",
|
|
18297
|
+
baseUnit: void 0,
|
|
18298
|
+
aggregates: BINARY_AGGREGATES,
|
|
18299
|
+
empty: "offline"
|
|
18300
|
+
};
|
|
18301
|
+
}
|
|
18302
|
+
var GROUP_TEMPLATES = [
|
|
18303
|
+
numeric({
|
|
18304
|
+
id: "temperature",
|
|
18305
|
+
summary: "Mean, median, min, max or sum of temperatures. Offline and unknown members are left out, never read as 0 °C.",
|
|
18306
|
+
role: DeviceRole.TemperatureSensor,
|
|
18307
|
+
outputCap: "temperature-sensor",
|
|
18308
|
+
outputField: "celsius",
|
|
18309
|
+
quantity: "temperature",
|
|
18310
|
+
defaultAggregate: "mean",
|
|
18311
|
+
empty: "null",
|
|
18312
|
+
companions: [NOW]
|
|
18313
|
+
}),
|
|
18314
|
+
numeric({
|
|
18315
|
+
id: "humidity",
|
|
18316
|
+
summary: "Humidity in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
18317
|
+
role: DeviceRole.HumiditySensor,
|
|
18318
|
+
outputCap: "humidity-sensor",
|
|
18319
|
+
outputField: "percent",
|
|
18320
|
+
quantity: "humidity",
|
|
18321
|
+
defaultAggregate: "mean",
|
|
18322
|
+
empty: "null",
|
|
18323
|
+
companions: [NOW]
|
|
18324
|
+
}),
|
|
18325
|
+
numeric({
|
|
18326
|
+
id: "pressure",
|
|
18327
|
+
summary: "Pressure in hectopascals. Offline and unknown members are left out, never read as 0 hPa.",
|
|
18328
|
+
role: DeviceRole.PressureSensor,
|
|
18329
|
+
outputCap: "pressure-sensor",
|
|
18330
|
+
outputField: "hpa",
|
|
18331
|
+
quantity: "pressure",
|
|
18332
|
+
defaultAggregate: "mean",
|
|
18333
|
+
empty: "null",
|
|
18334
|
+
companions: [NOW]
|
|
18335
|
+
}),
|
|
18336
|
+
numeric({
|
|
18337
|
+
id: "illuminance",
|
|
18338
|
+
summary: "Illuminance in lux. Offline and unknown members are left out, never read as 0 lx.",
|
|
18339
|
+
role: DeviceRole.AmbientLightSensor,
|
|
18340
|
+
outputCap: "ambient-light-sensor",
|
|
18341
|
+
outputField: "lux",
|
|
18342
|
+
quantity: "illuminance",
|
|
18343
|
+
defaultAggregate: "mean",
|
|
18344
|
+
empty: "null",
|
|
18345
|
+
companions: [NOW]
|
|
18346
|
+
}),
|
|
18347
|
+
numeric({
|
|
18348
|
+
id: "power",
|
|
18349
|
+
summary: "Power in watts, summed by default. Nobody reporting omits the key rather than writing 0 W.",
|
|
18350
|
+
role: DeviceRole.PowerSensor,
|
|
18351
|
+
outputCap: "power-meter",
|
|
18352
|
+
outputField: "watts",
|
|
18353
|
+
quantity: "power",
|
|
18354
|
+
defaultAggregate: "sum",
|
|
18355
|
+
empty: "omit",
|
|
18356
|
+
companions: [NOW]
|
|
18357
|
+
}),
|
|
18358
|
+
numeric({
|
|
18359
|
+
id: "energy",
|
|
18360
|
+
summary: "Energy in kilowatt-hours, summed by default. Nobody reporting omits the key rather than writing 0 kWh.",
|
|
18361
|
+
role: DeviceRole.EnergySensor,
|
|
18362
|
+
outputCap: "power-meter",
|
|
18363
|
+
outputField: "kwhTotal",
|
|
18364
|
+
quantity: "energy",
|
|
18365
|
+
defaultAggregate: "sum",
|
|
18366
|
+
empty: "omit",
|
|
18367
|
+
companions: [NOW]
|
|
18368
|
+
}),
|
|
18369
|
+
numeric({
|
|
18370
|
+
id: "battery",
|
|
18371
|
+
summary: "Battery charge in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
18372
|
+
role: DeviceRole.BatterySensor,
|
|
18373
|
+
outputCap: "battery",
|
|
18374
|
+
outputField: "percentage",
|
|
18375
|
+
quantity: "percentage",
|
|
18376
|
+
defaultAggregate: "mean",
|
|
18377
|
+
empty: "null",
|
|
18378
|
+
companions: [
|
|
18379
|
+
{
|
|
18380
|
+
fieldPath: "charging",
|
|
18381
|
+
expr: "\"unknown\""
|
|
18382
|
+
},
|
|
18383
|
+
{
|
|
18384
|
+
fieldPath: "sleeping",
|
|
18385
|
+
expr: "false"
|
|
18386
|
+
},
|
|
18387
|
+
{
|
|
18388
|
+
fieldPath: "lastUpdated",
|
|
18389
|
+
expr: "now"
|
|
18390
|
+
}
|
|
18391
|
+
]
|
|
18392
|
+
}),
|
|
18393
|
+
numeric({
|
|
18394
|
+
id: "numeric",
|
|
18395
|
+
summary: "A numeric reading in the members’ shared quantity. Mixed quantities are refused. Nobody reporting publishes null, not 0.",
|
|
18396
|
+
role: DeviceRole.NumericSensor,
|
|
18397
|
+
outputCap: "numeric-sensor",
|
|
18398
|
+
outputField: "value",
|
|
18399
|
+
quantity: "device",
|
|
18400
|
+
defaultAggregate: "mean",
|
|
18401
|
+
empty: "null",
|
|
18402
|
+
companions: [NOW]
|
|
18403
|
+
}),
|
|
18404
|
+
binary({
|
|
18405
|
+
id: "motion",
|
|
18406
|
+
summary: "Any or all motion. Offline and unknown members are left out, never read as off. Nobody reporting takes the device offline.",
|
|
18407
|
+
role: DeviceRole.MotionSensor,
|
|
18408
|
+
outputCap: "motion",
|
|
18409
|
+
outputField: "detected",
|
|
18410
|
+
defaultAggregate: "any",
|
|
18411
|
+
accept: [{
|
|
18412
|
+
cap: "motion",
|
|
18413
|
+
fieldPath: "detected"
|
|
18414
|
+
}],
|
|
18415
|
+
companions: [{
|
|
18416
|
+
fieldPath: "lastDetectedAt",
|
|
18417
|
+
expr: "null"
|
|
18418
|
+
}, {
|
|
18419
|
+
fieldPath: "autoClearAfterMs",
|
|
18420
|
+
expr: "null"
|
|
18421
|
+
}]
|
|
18422
|
+
}),
|
|
18423
|
+
binary({
|
|
18424
|
+
id: "contact",
|
|
18425
|
+
summary: "Any or all open contacts. Offline and unknown members are left out, never read as closed.",
|
|
18426
|
+
role: DeviceRole.ContactSensor,
|
|
18427
|
+
outputCap: "contact",
|
|
18428
|
+
outputField: "entryOpen",
|
|
18429
|
+
defaultAggregate: "any",
|
|
18430
|
+
accept: [{
|
|
18431
|
+
cap: "contact",
|
|
18432
|
+
fieldPath: "entryOpen"
|
|
18433
|
+
}],
|
|
18434
|
+
companions: [CHANGED]
|
|
18435
|
+
}),
|
|
18436
|
+
binary({
|
|
18437
|
+
id: "leak",
|
|
18438
|
+
summary: "Any or all leak detections. Offline and unknown members are left out, never read as dry.",
|
|
18439
|
+
role: DeviceRole.LeakSensor,
|
|
18440
|
+
outputCap: "flood",
|
|
18441
|
+
outputField: "flooded",
|
|
18442
|
+
defaultAggregate: "any",
|
|
18443
|
+
accept: [{
|
|
18444
|
+
cap: "flood",
|
|
18445
|
+
fieldPath: "flooded"
|
|
18446
|
+
}],
|
|
18447
|
+
companions: [CHANGED]
|
|
18448
|
+
}),
|
|
18449
|
+
binary({
|
|
18450
|
+
id: "smoke",
|
|
18451
|
+
summary: "Any or all smoke detections. Offline and unknown members are left out, never read as clear.",
|
|
18452
|
+
role: DeviceRole.SmokeSensor,
|
|
18453
|
+
outputCap: "smoke",
|
|
18454
|
+
outputField: "detected",
|
|
18455
|
+
defaultAggregate: "any",
|
|
18456
|
+
accept: [{
|
|
18457
|
+
cap: "smoke",
|
|
18458
|
+
fieldPath: "detected"
|
|
18459
|
+
}],
|
|
18460
|
+
companions: [CHANGED]
|
|
18461
|
+
}),
|
|
18462
|
+
binary({
|
|
18463
|
+
id: "occupancy",
|
|
18464
|
+
summary: "Any or all of motion or binary sensors, published as a binary. Presence zones are not aggregated. Nobody reporting is offline, not off.",
|
|
18465
|
+
role: DeviceRole.BinarySensor,
|
|
18466
|
+
outputCap: "binary",
|
|
18467
|
+
outputField: "on",
|
|
18468
|
+
defaultAggregate: "any",
|
|
18469
|
+
accept: [{
|
|
18470
|
+
cap: "motion",
|
|
18471
|
+
fieldPath: "detected"
|
|
18472
|
+
}, {
|
|
18473
|
+
cap: "binary",
|
|
18474
|
+
fieldPath: "on"
|
|
18475
|
+
}],
|
|
18476
|
+
companions: [CHANGED]
|
|
18477
|
+
}),
|
|
18478
|
+
binary({
|
|
18479
|
+
id: "binary",
|
|
18480
|
+
summary: "Any or all generic binary sensors. Offline and unknown members are left out, never read as off.",
|
|
18481
|
+
role: DeviceRole.BinarySensor,
|
|
18482
|
+
outputCap: "binary",
|
|
18483
|
+
outputField: "on",
|
|
18484
|
+
defaultAggregate: "any",
|
|
18485
|
+
accept: [{
|
|
18486
|
+
cap: "binary",
|
|
18487
|
+
fieldPath: "on"
|
|
18488
|
+
}],
|
|
18489
|
+
companions: [CHANGED]
|
|
18490
|
+
}),
|
|
18491
|
+
actuator({
|
|
18492
|
+
id: "switch",
|
|
18493
|
+
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.",
|
|
18494
|
+
deviceType: DeviceType.Switch,
|
|
18495
|
+
outputCap: "switch",
|
|
18496
|
+
commandCaps: ["switch"]
|
|
18497
|
+
}),
|
|
18498
|
+
actuator({
|
|
18499
|
+
id: "light",
|
|
18500
|
+
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.",
|
|
18501
|
+
deviceType: DeviceType.Light,
|
|
18502
|
+
outputCap: "switch",
|
|
18503
|
+
commandCaps: [
|
|
18504
|
+
"switch",
|
|
18505
|
+
"brightness",
|
|
18506
|
+
"color"
|
|
18507
|
+
]
|
|
18508
|
+
})
|
|
18509
|
+
];
|
|
18510
|
+
function actuator(input) {
|
|
18511
|
+
return {
|
|
18512
|
+
...input,
|
|
18513
|
+
family: "actuator",
|
|
18514
|
+
role: void 0,
|
|
18515
|
+
memberDeviceType: input.deviceType,
|
|
18516
|
+
outputField: "on",
|
|
18517
|
+
quantity: "none",
|
|
18518
|
+
baseUnit: void 0,
|
|
18519
|
+
aggregates: BINARY_AGGREGATES,
|
|
18520
|
+
defaultAggregate: "any",
|
|
18521
|
+
empty: "offline",
|
|
18522
|
+
accept: [{
|
|
18523
|
+
cap: "switch",
|
|
18524
|
+
fieldPath: "on"
|
|
18525
|
+
}],
|
|
18526
|
+
companions: [CHANGED]
|
|
18527
|
+
};
|
|
18528
|
+
}
|
|
18529
|
+
new Map(GROUP_TEMPLATES.map((template) => [template.id, template]));
|
|
18530
|
+
DeviceFeature.LightColorRgb, DeviceFeature.LightColorHsv, DeviceFeature.LightColorMired;
|
|
18143
18531
|
`${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
|
|
18144
18532
|
/**
|
|
18145
18533
|
* What a composition may BUILD on a device type (G2, D676): the caps a new
|
|
@@ -19966,12 +20354,12 @@ function buildDeviceAdminUrl(parts) {
|
|
|
19966
20354
|
* providers detect renames by matching `uniqueId` and patch `id`
|
|
19967
20355
|
* in-place so dispatch keeps working.
|
|
19968
20356
|
*
|
|
19969
|
-
* **
|
|
19970
|
-
*
|
|
19971
|
-
*
|
|
19972
|
-
*
|
|
19973
|
-
* (`ha-domain-mapping`)
|
|
19974
|
-
* stored after that point.
|
|
20357
|
+
* **Display unit and precision are NOT stored here.** They are a read-time
|
|
20358
|
+
* preference (D944). A polymorphic reading stores its `quantity` here once,
|
|
20359
|
+
* at adopt, and a date/time value stores `dateTimeShape` the same way —
|
|
20360
|
+
* neither is repeated on each sample. The `device_class` tag is an
|
|
20361
|
+
* HA-specific input consumed at the discovery boundary (`ha-domain-mapping`)
|
|
20362
|
+
* to derive the CamStack `DeviceRole`; it is never stored after that point.
|
|
19975
20363
|
*
|
|
19976
20364
|
* The `raw` escape hatch carries provider-specific attributes that don't
|
|
19977
20365
|
* fit the structured slots (HA `attributes` whitelist, Reolink `deviceCache`
|
|
@@ -19985,6 +20373,14 @@ var SourceInfoSchema = object({
|
|
|
19985
20373
|
/** Immutable upstream identifier when available (HA `unique_id`, … ).
|
|
19986
20374
|
* Used to detect rename when `id` changes. */
|
|
19987
20375
|
uniqueId: string().optional(),
|
|
20376
|
+
/** Quantity of a polymorphic reading, written once at adopt (D944). */
|
|
20377
|
+
quantity: ReadingQuantitySchema.optional(),
|
|
20378
|
+
/** Date / time / datetime shape of a string reading, written once at adopt. */
|
|
20379
|
+
dateTimeShape: _enum([
|
|
20380
|
+
"date",
|
|
20381
|
+
"time",
|
|
20382
|
+
"datetime"
|
|
20383
|
+
]).optional(),
|
|
19988
20384
|
/** Provider-specific extras that don't fit the structured slots.
|
|
19989
20385
|
* Whitelist what goes here per provider — do NOT dump entire HA
|
|
19990
20386
|
* attribute blobs (would explode the meta JSON column). */
|
|
@@ -41089,7 +41485,8 @@ method(object({
|
|
|
41089
41485
|
"enum"
|
|
41090
41486
|
]),
|
|
41091
41487
|
enumValues: array(string()).optional(),
|
|
41092
|
-
item: boolean().optional()
|
|
41488
|
+
item: boolean().optional(),
|
|
41489
|
+
quantity: ReadingQuantitySchema.optional()
|
|
41093
41490
|
})).readonly(),
|
|
41094
41491
|
itemArray: object({
|
|
41095
41492
|
path: string(),
|
|
@@ -44933,8 +45330,8 @@ var MaskPolygonShapeSchema = object({
|
|
|
44933
45330
|
/** Boolean cell grid — row-major, length === gridWidth*gridHeight. */
|
|
44934
45331
|
var MaskGridShapeSchema = object({
|
|
44935
45332
|
kind: literal("grid"),
|
|
44936
|
-
gridWidth: number(),
|
|
44937
|
-
gridHeight: number(),
|
|
45333
|
+
gridWidth: number().meta(readingMeta("none")),
|
|
45334
|
+
gridHeight: number().meta(readingMeta("none")),
|
|
44938
45335
|
cells: array(boolean())
|
|
44939
45336
|
});
|
|
44940
45337
|
discriminatedUnion("kind", [
|
|
@@ -45046,6 +45443,8 @@ var NcSystemEventKindSchema = _enum([
|
|
|
45046
45443
|
"detection-blind",
|
|
45047
45444
|
"motion-noisy",
|
|
45048
45445
|
"motion-calm",
|
|
45446
|
+
"package-llm-silent",
|
|
45447
|
+
"package-llm-answered",
|
|
45049
45448
|
"recording-stalled",
|
|
45050
45449
|
"recording-healthy",
|
|
45051
45450
|
"recording-degraded",
|
|
@@ -56650,6 +57049,28 @@ var PackageVersionInfoSchema = object({
|
|
|
56650
57049
|
deprecated: string().optional(),
|
|
56651
57050
|
distTags: array(string()).readonly()
|
|
56652
57051
|
});
|
|
57052
|
+
/**
|
|
57053
|
+
* One published document. `ok` is markdown from the registry. `missing` means
|
|
57054
|
+
* the registry answered and the file was not there. `error` is a registry or
|
|
57055
|
+
* tarball failure — never an empty string standing in for either.
|
|
57056
|
+
*/
|
|
57057
|
+
var PackageDocBodySchema = discriminatedUnion("status", [
|
|
57058
|
+
object({
|
|
57059
|
+
status: literal("ok"),
|
|
57060
|
+
markdown: string()
|
|
57061
|
+
}),
|
|
57062
|
+
object({ status: literal("missing") }),
|
|
57063
|
+
object({
|
|
57064
|
+
status: literal("error"),
|
|
57065
|
+
message: string()
|
|
57066
|
+
})
|
|
57067
|
+
]);
|
|
57068
|
+
var PackageDocsSchema = object({
|
|
57069
|
+
name: string(),
|
|
57070
|
+
version: string(),
|
|
57071
|
+
readme: PackageDocBodySchema,
|
|
57072
|
+
changelog: PackageDocBodySchema
|
|
57073
|
+
});
|
|
56653
57074
|
var SearchResultSchema = object({
|
|
56654
57075
|
name: string(),
|
|
56655
57076
|
version: string(),
|
|
@@ -56868,7 +57289,10 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
|
|
|
56868
57289
|
}), object({ success: literal(true) }), {
|
|
56869
57290
|
kind: "mutation",
|
|
56870
57291
|
auth: "admin"
|
|
56871
|
-
}), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({
|
|
57292
|
+
}), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({
|
|
57293
|
+
name: string().min(1),
|
|
57294
|
+
version: string().min(1).optional()
|
|
57295
|
+
}), PackageDocsSchema, { auth: "admin" }), method(object({ addonId: string() }), RestartAddonResultSchema, {
|
|
56872
57296
|
kind: "mutation",
|
|
56873
57297
|
auth: "admin"
|
|
56874
57298
|
}), method(object({ packageName: string() }), object({ success: literal(true) }), {
|
|
@@ -56927,27 +57351,17 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
|
|
|
56927
57351
|
*/
|
|
56928
57352
|
var AirQualitySensorStatusSchema = object({
|
|
56929
57353
|
/** Carbon dioxide concentration in ppm. */
|
|
56930
|
-
co2Ppm: number().min(0).optional(),
|
|
57354
|
+
co2Ppm: number().min(0).optional().meta(readingMeta("concentration-volume")),
|
|
56931
57355
|
/** Total volatile organic compounds in ppb. */
|
|
56932
|
-
vocPpb: number().min(0).optional(),
|
|
57356
|
+
vocPpb: number().min(0).optional().meta(readingMeta("concentration-ppb")),
|
|
56933
57357
|
/** Particulate matter ≤ 2.5 μm in µg/m³. */
|
|
56934
|
-
pm25: number().min(0).optional(),
|
|
57358
|
+
pm25: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
56935
57359
|
/** Particulate matter ≤ 10 μm in µg/m³. */
|
|
56936
|
-
pm10: number().min(0).optional(),
|
|
57360
|
+
pm10: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
56937
57361
|
/** Composite AQI value (typically 0..500). */
|
|
56938
|
-
aqi: number().optional(),
|
|
57362
|
+
aqi: number().optional().meta(readingMeta("index")),
|
|
56939
57363
|
/** Ms epoch when the slice was last updated. */
|
|
56940
|
-
lastFetchedAt: number()
|
|
56941
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
56942
|
-
* `attributes.unit_of_measurement` → 'ppm' / 'ppb' / 'µg/m³'). Each
|
|
56943
|
-
* upstream `sensor.*` entity surfaces ONE device_class, so one unit
|
|
56944
|
-
* per slice is unambiguous. */
|
|
56945
|
-
unit: string().optional(),
|
|
56946
|
-
/** Suggested decimal places for numeric display.
|
|
56947
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
56948
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
56949
|
-
* auto-formatting when absent. */
|
|
56950
|
-
precision: number().int().min(0).max(10).optional()
|
|
57364
|
+
lastFetchedAt: number()
|
|
56951
57365
|
});
|
|
56952
57366
|
var airQualitySensorCapability = {
|
|
56953
57367
|
name: "air-quality-sensor",
|
|
@@ -56984,12 +57398,12 @@ var airQualitySensorCapability = {
|
|
|
56984
57398
|
},
|
|
56985
57399
|
pm25: {
|
|
56986
57400
|
kind: "gauge",
|
|
56987
|
-
unit: "
|
|
57401
|
+
unit: "µg/m³",
|
|
56988
57402
|
deadband: 1
|
|
56989
57403
|
},
|
|
56990
57404
|
pm10: {
|
|
56991
57405
|
kind: "gauge",
|
|
56992
|
-
unit: "
|
|
57406
|
+
unit: "µg/m³",
|
|
56993
57407
|
deadband: 1
|
|
56994
57408
|
},
|
|
56995
57409
|
aqi: {
|
|
@@ -57007,22 +57421,13 @@ var airQualitySensorCapability = {
|
|
|
57007
57421
|
* entries with `device_class: illuminance`.
|
|
57008
57422
|
*/
|
|
57009
57423
|
var AmbientLightSensorStatusSchema = object({
|
|
57010
|
-
/** Current illuminance in lux (lx). */
|
|
57011
|
-
lux: number().min(0).meta({
|
|
57012
|
-
|
|
57424
|
+
/** Current illuminance in lux (lx). `null` when the sample was refused (D393). */
|
|
57425
|
+
lux: number().min(0).nullable().meta(readingMeta("illuminance", {
|
|
57426
|
+
precision: 0,
|
|
57013
57427
|
label: "Illuminance"
|
|
57014
|
-
}),
|
|
57428
|
+
})),
|
|
57015
57429
|
/** Ms epoch when the slice was last updated. */
|
|
57016
|
-
lastFetchedAt: number()
|
|
57017
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
57018
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
57019
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
57020
|
-
unit: string().optional(),
|
|
57021
|
-
/** Suggested decimal places for numeric display.
|
|
57022
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
57023
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
57024
|
-
* auto-formatting when absent. */
|
|
57025
|
-
precision: number().int().min(0).max(10).optional()
|
|
57430
|
+
lastFetchedAt: number()
|
|
57026
57431
|
});
|
|
57027
57432
|
var ambientLightSensorCapability = {
|
|
57028
57433
|
name: "ambient-light-sensor",
|
|
@@ -57054,12 +57459,7 @@ var ambientLightSensorCapability = {
|
|
|
57054
57459
|
} } },
|
|
57055
57460
|
/** Clock fields: written, but excluded from the compare that decides
|
|
57056
57461
|
* whether persisting is worth a SQLite commit. */
|
|
57057
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
57058
|
-
customize: {
|
|
57059
|
-
version: 1,
|
|
57060
|
-
advanced: "derive",
|
|
57061
|
-
targets: []
|
|
57062
|
-
}
|
|
57462
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
57063
57463
|
};
|
|
57064
57464
|
/**
|
|
57065
57465
|
* Per-class audio metrics aggregated over a sliding window.
|
|
@@ -57286,10 +57686,7 @@ var BatteryStatusSchema = object({
|
|
|
57286
57686
|
* Consumers must SKIP a null rather than coerce it — `battery-band` already
|
|
57287
57687
|
* declines to band a non-finite reading, which is the correct shape.
|
|
57288
57688
|
*/
|
|
57289
|
-
percentage: number().min(0).max(100).nullable().meta({
|
|
57290
|
-
unit: "%",
|
|
57291
|
-
label: "Charge"
|
|
57292
|
-
}),
|
|
57689
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage", { label: "Charge" })),
|
|
57293
57690
|
/**
|
|
57294
57691
|
* Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
|
|
57295
57692
|
* Reolink-specific for the Solar Panel 2 accessory (will become
|
|
@@ -57316,7 +57713,14 @@ var BatteryStatusSchema = object({
|
|
|
57316
57713
|
*/
|
|
57317
57714
|
sleeping: boolean().meta({ label: "Sleeping" }),
|
|
57318
57715
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
57319
|
-
lastUpdated: number(),
|
|
57716
|
+
lastUpdated: number().meta(readingMeta("none")),
|
|
57717
|
+
/**
|
|
57718
|
+
* Battery voltage in volts, for a cell the firmware reports as voltage
|
|
57719
|
+
* rather than a percentage (Ecowitt capacitor packs). Absent on cameras
|
|
57720
|
+
* that only report charge. A second reading on this cap, not a second
|
|
57721
|
+
* `numeric-sensor` on the same device.
|
|
57722
|
+
*/
|
|
57723
|
+
volts: number().nullable().optional().meta(readingMeta("voltage", { label: "Voltage" })),
|
|
57320
57724
|
/**
|
|
57321
57725
|
* Ms epoch of the last time the device PROVED it was reachable — a
|
|
57322
57726
|
* completed firmware round-trip, an observed wake, or an inbound push
|
|
@@ -57368,7 +57772,6 @@ var BATTERY_DEVICE_TYPES = [
|
|
|
57368
57772
|
/** Generic Customize target for the percentage reading (D936). */
|
|
57369
57773
|
var batteryCustomize = {
|
|
57370
57774
|
version: 1,
|
|
57371
|
-
advanced: "derive",
|
|
57372
57775
|
targets: [{
|
|
57373
57776
|
id: "percentage",
|
|
57374
57777
|
cardinality: "scalar",
|
|
@@ -57377,7 +57780,7 @@ var batteryCustomize = {
|
|
|
57377
57780
|
stateField: "percentage"
|
|
57378
57781
|
},
|
|
57379
57782
|
deviceTypes: BATTERY_DEVICE_TYPES,
|
|
57380
|
-
apply: "add
|
|
57783
|
+
apply: "add",
|
|
57381
57784
|
path: "percentage",
|
|
57382
57785
|
sources: [{
|
|
57383
57786
|
kind: "field",
|
|
@@ -57498,10 +57901,16 @@ onStatusChanged: { data: object({
|
|
|
57498
57901
|
/**
|
|
57499
57902
|
* History (D850): recorded series. The generic capture replaces the `battery` series of `pipeline-analytics:stats-5m`.
|
|
57500
57903
|
*/
|
|
57501
|
-
history: { fields: {
|
|
57502
|
-
|
|
57503
|
-
|
|
57504
|
-
|
|
57904
|
+
history: { fields: {
|
|
57905
|
+
percentage: {
|
|
57906
|
+
kind: "gauge",
|
|
57907
|
+
unit: "%"
|
|
57908
|
+
},
|
|
57909
|
+
volts: {
|
|
57910
|
+
kind: "gauge",
|
|
57911
|
+
unit: "V"
|
|
57912
|
+
}
|
|
57913
|
+
} },
|
|
57505
57914
|
customize: batteryCustomize,
|
|
57506
57915
|
/** Clock fields: written, but excluded from the compare that decides
|
|
57507
57916
|
* whether persisting is worth a SQLite commit. */
|
|
@@ -57548,12 +57957,7 @@ var binaryCapability = {
|
|
|
57548
57957
|
history: { fields: { on: { kind: "boolean" } } },
|
|
57549
57958
|
/** Clock fields: written, but excluded from the compare that decides
|
|
57550
57959
|
* whether persisting is worth a SQLite commit. */
|
|
57551
|
-
volatileStateFields: ["lastChangedAt"]
|
|
57552
|
-
customize: {
|
|
57553
|
-
version: 1,
|
|
57554
|
-
advanced: "derive",
|
|
57555
|
-
targets: []
|
|
57556
|
-
}
|
|
57960
|
+
volatileStateFields: ["lastChangedAt"]
|
|
57557
57961
|
};
|
|
57558
57962
|
/**
|
|
57559
57963
|
* Dimmable-light brightness control. Co-exists with `switch` on the
|
|
@@ -57569,7 +57973,7 @@ var binaryCapability = {
|
|
|
57569
57973
|
*/
|
|
57570
57974
|
var BrightnessStatusSchema = object({
|
|
57571
57975
|
/** Current level as 0..100 inclusive. Firmware-reported. */
|
|
57572
|
-
percentage: number().min(0).max(100),
|
|
57976
|
+
percentage: number().min(0).max(100).meta(readingMeta("percentage")),
|
|
57573
57977
|
/** Ms epoch of the last operator-driven change. Useful for UI freshness. */
|
|
57574
57978
|
lastChangedAt: number()
|
|
57575
57979
|
});
|
|
@@ -58023,21 +58427,21 @@ var ClimateControlStatusSchema = object({
|
|
|
58023
58427
|
/** Single setpoint in Celsius. Used by single-target modes
|
|
58024
58428
|
* (heat / cool / dry). Null when the device is in a range mode
|
|
58025
58429
|
* (`heat_cool`) or has no setpoint at all (`fan_only`/`off`). */
|
|
58026
|
-
target: number().nullable(),
|
|
58430
|
+
target: number().nullable().meta(readingMeta("temperature")),
|
|
58027
58431
|
/** Upper bound of the dual setpoint in Celsius. Populated only
|
|
58028
58432
|
* in `heat_cool` mode. */
|
|
58029
|
-
targetHigh: number().nullable(),
|
|
58433
|
+
targetHigh: number().nullable().meta(readingMeta("temperature")),
|
|
58030
58434
|
/** Lower bound of the dual setpoint in Celsius. Populated only
|
|
58031
58435
|
* in `heat_cool` mode. */
|
|
58032
|
-
targetLow: number().nullable(),
|
|
58436
|
+
targetLow: number().nullable().meta(readingMeta("temperature")),
|
|
58033
58437
|
/** Target relative humidity (0..100). Null when the device has no
|
|
58034
58438
|
* humidity control. */
|
|
58035
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
58439
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
58036
58440
|
/** Current measured temperature in Celsius. Read-only — pushed by
|
|
58037
58441
|
* the device's internal sensor. */
|
|
58038
|
-
currentTemp: number().nullable(),
|
|
58442
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
58039
58443
|
/** Current measured relative humidity (0..100). Read-only. */
|
|
58040
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
58444
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
58041
58445
|
/** Vertical louver swing on/off. Null when the device has no vertical
|
|
58042
58446
|
* swing surface (gate with `DeviceFeature.ClimateSwingVertical`). */
|
|
58043
58447
|
swingVertical: boolean().nullable(),
|
|
@@ -58045,11 +58449,11 @@ var ClimateControlStatusSchema = object({
|
|
|
58045
58449
|
* horizontal swing surface (gate with `DeviceFeature.ClimateSwingHorizontal`). */
|
|
58046
58450
|
swingHorizontal: boolean().nullable(),
|
|
58047
58451
|
/** Lowest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
58048
|
-
minTemp: number().nullable().optional(),
|
|
58452
|
+
minTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
58049
58453
|
/** Highest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
58050
|
-
maxTemp: number().nullable().optional(),
|
|
58454
|
+
maxTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
58051
58455
|
/** Setpoint granularity, Celsius (0.5, 1). Absent / null = not reported. */
|
|
58052
|
-
tempStep: number().positive().nullable().optional(),
|
|
58456
|
+
tempStep: number().positive().nullable().optional().meta(readingMeta("temperature")),
|
|
58053
58457
|
/** Ms epoch when the slice was last updated (push or command). */
|
|
58054
58458
|
lastFetchedAt: number()
|
|
58055
58459
|
});
|
|
@@ -58191,17 +58595,17 @@ var climateControlCapability = {
|
|
|
58191
58595
|
* modes to expose in the picker without a slice fetch.
|
|
58192
58596
|
*/
|
|
58193
58597
|
var RgbTripletSchema = object({
|
|
58194
|
-
r: number().int().min(0).max(255),
|
|
58195
|
-
g: number().int().min(0).max(255),
|
|
58196
|
-
b: number().int().min(0).max(255)
|
|
58598
|
+
r: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
58599
|
+
g: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
58600
|
+
b: number().int().min(0).max(255).meta(readingMeta("none"))
|
|
58197
58601
|
});
|
|
58198
58602
|
var HsvTripletSchema = object({
|
|
58199
58603
|
/** Hue in degrees, 0..360. */
|
|
58200
|
-
h: number().min(0).max(360),
|
|
58604
|
+
h: number().min(0).max(360).meta(readingMeta("none")),
|
|
58201
58605
|
/** Saturation as 0..100 inclusive. */
|
|
58202
|
-
s: number().min(0).max(100),
|
|
58606
|
+
s: number().min(0).max(100).meta(readingMeta("none")),
|
|
58203
58607
|
/** Value/brightness as 0..100 inclusive. */
|
|
58204
|
-
v: number().min(0).max(100)
|
|
58608
|
+
v: number().min(0).max(100).meta(readingMeta("none"))
|
|
58205
58609
|
});
|
|
58206
58610
|
var ColorInputSchema = discriminatedUnion("mode", [
|
|
58207
58611
|
object({
|
|
@@ -58230,7 +58634,7 @@ var ColorStatusSchema = object({
|
|
|
58230
58634
|
/** Populated when `mode === 'hsv'`. */
|
|
58231
58635
|
hsv: HsvTripletSchema.optional(),
|
|
58232
58636
|
/** Populated when `mode === 'mired'`. */
|
|
58233
|
-
mireds: number().int().optional(),
|
|
58637
|
+
mireds: number().int().optional().meta(readingMeta("colour-temperature")),
|
|
58234
58638
|
/** Ms epoch of the last operator-driven change. */
|
|
58235
58639
|
lastChangedAt: number()
|
|
58236
58640
|
});
|
|
@@ -58425,18 +58829,12 @@ _enum([
|
|
|
58425
58829
|
"empty",
|
|
58426
58830
|
"full"
|
|
58427
58831
|
]);
|
|
58428
|
-
/**
|
|
58429
|
-
|
|
58430
|
-
|
|
58431
|
-
"days",
|
|
58432
|
-
"hours",
|
|
58433
|
-
"cycles"
|
|
58434
|
-
]);
|
|
58435
|
-
/** Remaining life as a COUNT, not a percentage (the PetKit desiccant reports
|
|
58436
|
-
* days). `value` null = unknown (D393). */
|
|
58832
|
+
/** Whether `remaining.value` is a duration in seconds or a dimensionless count. */
|
|
58833
|
+
var ConsumableRemainingKindSchema = _enum(["duration", "count"]);
|
|
58834
|
+
/** Remaining life. `value` null = unknown (D393). Duration is seconds. */
|
|
58437
58835
|
var ConsumableRemainingSchema = object({
|
|
58438
|
-
value: number().min(0).nullable(),
|
|
58439
|
-
|
|
58836
|
+
value: number().min(0).nullable().meta(readingMeta("device")),
|
|
58837
|
+
kind: ConsumableRemainingKindSchema
|
|
58440
58838
|
});
|
|
58441
58839
|
/** A single consumable item. Either a continuous `level` (remaining
|
|
58442
58840
|
* life %, or fill % for a `supply` / `waste` item) or a discrete `status`
|
|
@@ -58449,7 +58847,7 @@ var ConsumableItemSchema = object({
|
|
|
58449
58847
|
/** Display name. */
|
|
58450
58848
|
label: string().min(1),
|
|
58451
58849
|
/** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
|
|
58452
|
-
level: number().min(0).max(100).nullable(),
|
|
58850
|
+
level: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58453
58851
|
/** The provider's discrete verdict when known (binary mode). */
|
|
58454
58852
|
status: ConsumableStatusSchema.nullable(),
|
|
58455
58853
|
/** What the item is — decides whether low or full is bad. Absent = `wear`. */
|
|
@@ -58531,8 +58929,8 @@ var consumablesCustomize = {
|
|
|
58531
58929
|
transforms: [{ kind: "identity" }]
|
|
58532
58930
|
}],
|
|
58533
58931
|
literals: [{
|
|
58534
|
-
path: "remaining.
|
|
58535
|
-
values: [...
|
|
58932
|
+
path: "remaining.kind",
|
|
58933
|
+
values: [...ConsumableRemainingKindSchema.options]
|
|
58536
58934
|
}]
|
|
58537
58935
|
},
|
|
58538
58936
|
{
|
|
@@ -58661,7 +59059,6 @@ reset: method(object({
|
|
|
58661
59059
|
},
|
|
58662
59060
|
"remaining.value": {
|
|
58663
59061
|
kind: "gauge",
|
|
58664
|
-
unitFrom: "remaining.unit",
|
|
58665
59062
|
deadband: 1,
|
|
58666
59063
|
displayName: "Remaining"
|
|
58667
59064
|
}
|
|
@@ -58731,10 +59128,9 @@ var contactCapability = {
|
|
|
58731
59128
|
* (empty array for the other kinds). It lives in the slice because
|
|
58732
59129
|
* HA `select.*` entities may update their options at runtime.
|
|
58733
59130
|
*
|
|
58734
|
-
*
|
|
58735
|
-
*
|
|
58736
|
-
*
|
|
58737
|
-
* push — consistent with `options` and the sensor-unit approach.
|
|
59131
|
+
* Numeric `min` / `max` / `step` live in the slice and share the device
|
|
59132
|
+
* quantity (`SourceInfo.quantity`, D944). Display precision is a read-time
|
|
59133
|
+
* preference. A datetime control's shape is `SourceInfo.dateTimeShape`.
|
|
58738
59134
|
*/
|
|
58739
59135
|
var ControlStatusSchema = object({
|
|
58740
59136
|
kind: _enum([
|
|
@@ -58746,39 +59142,17 @@ var ControlStatusSchema = object({
|
|
|
58746
59142
|
/** Current value. Numeric kind → number; select/text/datetime → string.
|
|
58747
59143
|
* Datetime values are ISO 8601 strings (full timestamp, date-only,
|
|
58748
59144
|
* or time-only — HA accepts all three forms). */
|
|
58749
|
-
value: union([number(), string()]),
|
|
59145
|
+
value: union([number().meta(readingMeta("device")), string()]),
|
|
58750
59146
|
/** Acceptable values when `kind === 'select'`. Empty for other kinds. */
|
|
58751
59147
|
options: array(string()),
|
|
58752
59148
|
/** Ms epoch when the slice was last updated. */
|
|
58753
59149
|
lastChangedAt: number(),
|
|
58754
|
-
/**
|
|
58755
|
-
|
|
58756
|
-
|
|
58757
|
-
|
|
58758
|
-
/**
|
|
58759
|
-
|
|
58760
|
-
min: number().optional(),
|
|
58761
|
-
/** Maximum allowed value. Populated live from HA `attributes.max`.
|
|
58762
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
58763
|
-
max: number().optional(),
|
|
58764
|
-
/** Step increment. Populated live from HA `attributes.step`.
|
|
58765
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
58766
|
-
step: number().optional(),
|
|
58767
|
-
/** Suggested decimal places for numeric display. Populated live from HA
|
|
58768
|
-
* `attributes.suggested_display_precision`, or derived from `step` when the
|
|
58769
|
-
* HA attribute is absent. Meaningful for `kind === 'numeric'`; absent for
|
|
58770
|
-
* other kinds. Falls back to auto-formatting when absent. */
|
|
58771
|
-
precision: number().int().min(0).max(10).optional(),
|
|
58772
|
-
/** Date-picker granularity for `kind === 'datetime'`. 'date' → date-only,
|
|
58773
|
-
* 'time' → time-only, 'datetime' → full timestamp. Absent for other kinds
|
|
58774
|
-
* (UI defaults to 'datetime'). Derived live from the device's HA domain
|
|
58775
|
-
* (date.* / time.* / datetime.*) or, for input_datetime, from the entity's
|
|
58776
|
-
* `has_date`/`has_time` attributes on each push. */
|
|
58777
|
-
format: _enum([
|
|
58778
|
-
"date",
|
|
58779
|
-
"time",
|
|
58780
|
-
"datetime"
|
|
58781
|
-
]).optional()
|
|
59150
|
+
/** Minimum allowed value, in the device quantity's base unit. */
|
|
59151
|
+
min: number().optional().meta(readingMeta("device")),
|
|
59152
|
+
/** Maximum allowed value, in the device quantity's base unit. */
|
|
59153
|
+
max: number().optional().meta(readingMeta("device")),
|
|
59154
|
+
/** Step increment, in the device quantity's base unit. */
|
|
59155
|
+
step: number().optional().meta(readingMeta("device"))
|
|
58782
59156
|
});
|
|
58783
59157
|
var ControlSetValueInputSchema = discriminatedUnion("kind", [
|
|
58784
59158
|
object({
|
|
@@ -58844,9 +59218,9 @@ var CoverStatusSchema = object({
|
|
|
58844
59218
|
]),
|
|
58845
59219
|
/** 0 = fully closed, 100 = fully open. Null when the device has
|
|
58846
59220
|
* no intermediate position surface. */
|
|
58847
|
-
position: number().min(0).max(100).nullable(),
|
|
59221
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58848
59222
|
/** 0 = closed slats, 100 = open slats. Null when no tilt support. */
|
|
58849
|
-
tiltPosition: number().min(0).max(100).nullable(),
|
|
59223
|
+
tiltPosition: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58850
59224
|
/** Ms epoch when the slice was last updated. */
|
|
58851
59225
|
lastChangedAt: number()
|
|
58852
59226
|
});
|
|
@@ -58949,9 +59323,9 @@ var NormalizedRangeSchema$1 = object({
|
|
|
58949
59323
|
var DayNightStatusSchema = object({
|
|
58950
59324
|
mode: DayNightModeSchema,
|
|
58951
59325
|
/** IR-cut trigger sensitivity, NORMALIZED 0–100 (higher = switches to night sooner). */
|
|
58952
|
-
sensitivity: number().optional(),
|
|
59326
|
+
sensitivity: number().optional().meta(readingMeta("none")),
|
|
58953
59327
|
/** Delay before the IR-cut filter flips, in seconds. */
|
|
58954
|
-
switchDelaySec: number().optional(),
|
|
59328
|
+
switchDelaySec: number().optional().meta(readingMeta("duration")),
|
|
58955
59329
|
lastFetchedAt: number()
|
|
58956
59330
|
});
|
|
58957
59331
|
/**
|
|
@@ -59169,11 +59543,11 @@ var DishwasherStatusSchema = object({
|
|
|
59169
59543
|
/** Feature keys of the programs the appliance currently offers — drives the UI selector. */
|
|
59170
59544
|
availablePrograms: array(string()),
|
|
59171
59545
|
/** Seconds remaining on the active cycle, or null when not running / not known. */
|
|
59172
|
-
remainingSeconds: number().int().nonnegative().nullable(),
|
|
59546
|
+
remainingSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
59173
59547
|
/** Seconds the delayed start is set to (time until the cycle starts), or null. */
|
|
59174
|
-
delayedStartSeconds: number().int().nonnegative().nullable(),
|
|
59548
|
+
delayedStartSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
59175
59549
|
/** Cycle completion 0..100, or null when not applicable. */
|
|
59176
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
59550
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59177
59551
|
/** True when the door is reported open; null when the door state is not known. */
|
|
59178
59552
|
doorOpen: boolean().nullable(),
|
|
59179
59553
|
/** True when the door is latched (locked) during a cycle; null when not reported. */
|
|
@@ -59197,7 +59571,7 @@ var DishwasherStatusSchema = object({
|
|
|
59197
59571
|
/** True while the machine-care (descaling / cleaning-program) reminder is raised; false when clear; null when not reported. */
|
|
59198
59572
|
machineCareDue: boolean().nullable(),
|
|
59199
59573
|
/** Program runs left before the machine-care reminder is due; null when the appliance does not say. */
|
|
59200
|
-
machineCareRemainingRuns: number().int().nonnegative().nullable(),
|
|
59574
|
+
machineCareRemainingRuns: number().int().nonnegative().nullable().meta(readingMeta("count")),
|
|
59201
59575
|
/** Option states: null when the appliance does not expose the option or has not said. */
|
|
59202
59576
|
halfLoad: boolean().nullable(),
|
|
59203
59577
|
hygienePlus: boolean().nullable(),
|
|
@@ -59212,7 +59586,7 @@ var DishwasherStatusSchema = object({
|
|
|
59212
59586
|
/** Feature keys of the events currently raised (salt low, rinse aid low, program finished, …). */
|
|
59213
59587
|
activeEvents: array(string()),
|
|
59214
59588
|
/** Numeric error code when the appliance reports one; null otherwise. */
|
|
59215
|
-
errorCode: number().nullable(),
|
|
59589
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
59216
59590
|
/** Name of the raised alert-level event while the appliance is in error; null otherwise. */
|
|
59217
59591
|
errorLabel: string().nullable(),
|
|
59218
59592
|
/** Ms epoch of the last value received from the appliance; 0 = never. */
|
|
@@ -59443,7 +59817,7 @@ var DoorbellStatusSchema = object({
|
|
|
59443
59817
|
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
59444
59818
|
lastPressedAt: number().nullable(),
|
|
59445
59819
|
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
59446
|
-
pressCountSinceStart: number()
|
|
59820
|
+
pressCountSinceStart: number().meta(readingMeta("count"))
|
|
59447
59821
|
});
|
|
59448
59822
|
var DoorbellPressEventSchema = object({
|
|
59449
59823
|
deviceId: number(),
|
|
@@ -59508,17 +59882,7 @@ onPressed: {
|
|
|
59508
59882
|
history: "none",
|
|
59509
59883
|
customize: doorbellCustomize
|
|
59510
59884
|
};
|
|
59511
|
-
|
|
59512
|
-
* Enum-state sensor — a string value picked from a finite option set.
|
|
59513
|
-
* Drives HA `sensor` entries with `state_class: enum` (HVAC action
|
|
59514
|
-
* states, weather conditions, contact-source channels, mode strings).
|
|
59515
|
-
* The option set is stable across observations; it is persisted in the
|
|
59516
|
-
* device config blob (via the control slice at adoption) and is NOT
|
|
59517
|
-
* stored in `sourceInfo`.
|
|
59518
|
-
*/
|
|
59519
|
-
/** Locale-render shape for an ISO `value` carried by a `DateTimeSensor`-role
|
|
59520
|
-
* enum sensor: `date` (date-only), `time` (time-only), `datetime` (both). */
|
|
59521
|
-
var EnumSensorDateTimeFormatSchema = _enum([
|
|
59885
|
+
_enum([
|
|
59522
59886
|
"date",
|
|
59523
59887
|
"time",
|
|
59524
59888
|
"datetime"
|
|
@@ -59526,12 +59890,11 @@ var EnumSensorDateTimeFormatSchema = _enum([
|
|
|
59526
59890
|
var EnumSensorStatusSchema = object({
|
|
59527
59891
|
value: string(),
|
|
59528
59892
|
/**
|
|
59529
|
-
* Set
|
|
59530
|
-
* as
|
|
59531
|
-
*
|
|
59532
|
-
* a time-only sensor → `'time'`.
|
|
59893
|
+
* Set when `value` is a timestamp rather than an enum state, so history
|
|
59894
|
+
* does not learn ISO strings as states. The display shape (date / time /
|
|
59895
|
+
* datetime) lives on `SourceInfo.dateTimeShape`, written once at adopt.
|
|
59533
59896
|
*/
|
|
59534
|
-
|
|
59897
|
+
timestamp: boolean().optional(),
|
|
59535
59898
|
/** Ms epoch when the slice was last updated. */
|
|
59536
59899
|
lastFetchedAt: number()
|
|
59537
59900
|
});
|
|
@@ -59558,11 +59921,11 @@ var enumSensorCapability = {
|
|
|
59558
59921
|
* History (D850): the value as an `enum` series (an appliance's program or
|
|
59559
59922
|
* operation state, an HVAC action). The option set is per device, so the
|
|
59560
59923
|
* value list is LEARNED as values are first seen (bounded). A sensor with a
|
|
59561
|
-
* `
|
|
59924
|
+
* `timestamp` carries a clock, not a state, and is not recorded.
|
|
59562
59925
|
*/
|
|
59563
59926
|
history: { fields: { value: {
|
|
59564
59927
|
kind: "enum",
|
|
59565
|
-
skipWhenSet: "
|
|
59928
|
+
skipWhenSet: "timestamp"
|
|
59566
59929
|
} } },
|
|
59567
59930
|
/** Clock fields: written, but excluded from the compare that decides
|
|
59568
59931
|
* whether persisting is worth a SQLite commit. */
|
|
@@ -59582,13 +59945,13 @@ var EventFireSchema = object({
|
|
|
59582
59945
|
deviceId: number(),
|
|
59583
59946
|
eventType: string(),
|
|
59584
59947
|
data: record(string(), unknown()).nullable(),
|
|
59585
|
-
timestamp: number(),
|
|
59586
|
-
seq: number()
|
|
59948
|
+
timestamp: number().meta(readingMeta("none")),
|
|
59949
|
+
seq: number().meta(readingMeta("count"))
|
|
59587
59950
|
});
|
|
59588
59951
|
var EventEmitterStatusSchema = object({
|
|
59589
59952
|
eventTypes: array(string()),
|
|
59590
59953
|
lastEvent: EventFireSchema.nullable(),
|
|
59591
|
-
eventCountSinceStart: number()
|
|
59954
|
+
eventCountSinceStart: number().meta(readingMeta("count"))
|
|
59592
59955
|
});
|
|
59593
59956
|
var eventEmitterCapability = {
|
|
59594
59957
|
name: "event-emitter",
|
|
@@ -60001,10 +60364,10 @@ var FanDirectionSchema = _enum(["forward", "reverse"]);
|
|
|
60001
60364
|
var FanControlStatusSchema = object({
|
|
60002
60365
|
/** Active speed as 0..100 inclusive. Null when the device has no
|
|
60003
60366
|
* speed surface (single-speed fan). */
|
|
60004
|
-
percentage: number().min(0).max(100).nullable(),
|
|
60367
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
60005
60368
|
/** Speed granularity the device accepts (HA `percentage_step`, e.g. 25 for
|
|
60006
60369
|
* a 4-speed fan). Absent when unknown — the UI then falls back to step 1. */
|
|
60007
|
-
percentageStep: number().positive().optional(),
|
|
60370
|
+
percentageStep: number().positive().optional().meta(readingMeta("percentage")),
|
|
60008
60371
|
/** Active preset mode (`auto` / `quiet` / `turbo` / vendor-specific)
|
|
60009
60372
|
* — empty string when no preset is active or supported. */
|
|
60010
60373
|
preset: string(),
|
|
@@ -60125,7 +60488,7 @@ var FeatureProbeStatusSchema = object({
|
|
|
60125
60488
|
/** Camera/firmware model string. `null` when the firmware doesn't expose it. */
|
|
60126
60489
|
model: string().nullable(),
|
|
60127
60490
|
/** Channel count for NVR/Hub devices; `1` for standalone cameras; `null` pre-probe. */
|
|
60128
|
-
channelCount: number().nullable(),
|
|
60491
|
+
channelCount: number().nullable().meta(readingMeta("count")),
|
|
60129
60492
|
/**
|
|
60130
60493
|
* Ms epoch of the last SUCCESSFUL probe. `0` before the first probe
|
|
60131
60494
|
* completes — drivers' `getAccessoryChildren()` should treat zero as
|
|
@@ -60248,9 +60611,91 @@ var gasCapability = {
|
|
|
60248
60611
|
* whether persisting is worth a SQLite commit. */
|
|
60249
60612
|
volatileStateFields: ["lastChangedAt"]
|
|
60250
60613
|
};
|
|
60614
|
+
var GroupCommandsSchema = object({
|
|
60615
|
+
/** One row per member that has been commanded. A later command replaces that member's row. */
|
|
60616
|
+
results: array(object({
|
|
60617
|
+
deviceId: number().int().nonnegative(),
|
|
60618
|
+
cap: string().min(1),
|
|
60619
|
+
method: string().min(1),
|
|
60620
|
+
ok: boolean(),
|
|
60621
|
+
error: string().optional(),
|
|
60622
|
+
/** Ms epoch of the attempt. */
|
|
60623
|
+
at: number()
|
|
60624
|
+
})) });
|
|
60625
|
+
var groupCommandsCapability = {
|
|
60626
|
+
name: "group-commands",
|
|
60627
|
+
scope: "device",
|
|
60628
|
+
deviceNative: true,
|
|
60629
|
+
mode: "singleton",
|
|
60630
|
+
deviceTypes: [DeviceType.Switch, DeviceType.Light],
|
|
60631
|
+
methods: {},
|
|
60632
|
+
status: {
|
|
60633
|
+
schema: GroupCommandsSchema,
|
|
60634
|
+
kind: "push"
|
|
60635
|
+
},
|
|
60636
|
+
runtimeState: GroupCommandsSchema,
|
|
60637
|
+
/**
|
|
60638
|
+
* Runtime-state durability: **session** — the last attempt. A restored
|
|
60639
|
+
* failure would outlive the command that caused it.
|
|
60640
|
+
*
|
|
60641
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
60642
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
60643
|
+
*/
|
|
60644
|
+
durability: "session",
|
|
60645
|
+
history: "none"
|
|
60646
|
+
};
|
|
60647
|
+
/**
|
|
60648
|
+
* How many members of a helper group answered (D944). Counts are integers,
|
|
60649
|
+
* not measurements: zero included is a real count, never a stand-in reading.
|
|
60650
|
+
* The reading itself stays on the output capability. History is none — the
|
|
60651
|
+
* series that later statistics read is the output cap's own history block.
|
|
60652
|
+
*/
|
|
60653
|
+
var GroupStatusSchema = object({
|
|
60654
|
+
/** Members whose current value entered the aggregate. */
|
|
60655
|
+
included: number().int().nonnegative().meta(readingMeta("count", {
|
|
60656
|
+
precision: 0,
|
|
60657
|
+
label: "Reporting"
|
|
60658
|
+
})),
|
|
60659
|
+
/** Members left out: offline, unknown, or not a finite reading (D393). */
|
|
60660
|
+
excluded: number().int().nonnegative().meta(readingMeta("count", {
|
|
60661
|
+
precision: 0,
|
|
60662
|
+
label: "Excluded"
|
|
60663
|
+
})),
|
|
60664
|
+
/** `included` + `excluded`. */
|
|
60665
|
+
total: number().int().nonnegative().meta(readingMeta("count", {
|
|
60666
|
+
precision: 0,
|
|
60667
|
+
label: "Members"
|
|
60668
|
+
}))
|
|
60669
|
+
});
|
|
60670
|
+
var groupStatusCapability = {
|
|
60671
|
+
name: "group-status",
|
|
60672
|
+
scope: "device",
|
|
60673
|
+
deviceNative: true,
|
|
60674
|
+
mode: "singleton",
|
|
60675
|
+
deviceTypes: [
|
|
60676
|
+
DeviceType.Sensor,
|
|
60677
|
+
DeviceType.Switch,
|
|
60678
|
+
DeviceType.Light
|
|
60679
|
+
],
|
|
60680
|
+
methods: {},
|
|
60681
|
+
status: {
|
|
60682
|
+
schema: GroupStatusSchema,
|
|
60683
|
+
kind: "push"
|
|
60684
|
+
},
|
|
60685
|
+
runtimeState: GroupStatusSchema,
|
|
60686
|
+
/**
|
|
60687
|
+
* Runtime-state durability: **session** — recomputed from members on the
|
|
60688
|
+
* next source event; a restored count would outlive the readings it named.
|
|
60689
|
+
*
|
|
60690
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
60691
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
60692
|
+
*/
|
|
60693
|
+
durability: "session",
|
|
60694
|
+
history: "none"
|
|
60695
|
+
};
|
|
60251
60696
|
var HeatingValveStatusSchema = object({
|
|
60252
60697
|
/** Radiator valve opening 0 (closed) .. 100 (open). Null = not yet known. */
|
|
60253
|
-
position: number().min(0).max(100).nullable(),
|
|
60698
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
60254
60699
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
60255
60700
|
lastFetchedAt: number()
|
|
60256
60701
|
});
|
|
@@ -60293,9 +60738,9 @@ var HumidifierStatusSchema = object({
|
|
|
60293
60738
|
/** Whether the humidifier is currently on. */
|
|
60294
60739
|
on: boolean(),
|
|
60295
60740
|
/** Current measured relative humidity (0..100). Null when not reported. */
|
|
60296
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
60741
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
60297
60742
|
/** Target relative humidity (0..100). Null when no setpoint surface. */
|
|
60298
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
60743
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
60299
60744
|
/** Active mode (`auto` / `normal` / `baby` / vendor). Null when the
|
|
60300
60745
|
* device has no mode surface. */
|
|
60301
60746
|
mode: string().nullable(),
|
|
@@ -60305,9 +60750,9 @@ var HumidifierStatusSchema = object({
|
|
|
60305
60750
|
* `idle` / `off`). Null when the device doesn't report it. */
|
|
60306
60751
|
action: string().nullable(),
|
|
60307
60752
|
/** HA `min_humidity` attribute. Null → UI uses 0. */
|
|
60308
|
-
minHumidity: number().nullable(),
|
|
60753
|
+
minHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
60309
60754
|
/** HA `max_humidity` attribute. Null → UI uses 100. */
|
|
60310
|
-
maxHumidity: number().nullable(),
|
|
60755
|
+
maxHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
60311
60756
|
/** Ms epoch when the slice was last updated. */
|
|
60312
60757
|
lastChangedAt: number()
|
|
60313
60758
|
});
|
|
@@ -60377,22 +60822,13 @@ var humidifierCapability = {
|
|
|
60377
60822
|
* `sourceInfo`.
|
|
60378
60823
|
*/
|
|
60379
60824
|
var HumiditySensorStatusSchema = object({
|
|
60380
|
-
/** Current relative humidity, 0..100. */
|
|
60381
|
-
percent: number().min(0).max(100).meta({
|
|
60382
|
-
|
|
60825
|
+
/** Current relative humidity, 0..100. `null` when the sample was refused (D393). */
|
|
60826
|
+
percent: number().min(0).max(100).nullable().meta(readingMeta("humidity", {
|
|
60827
|
+
precision: 0,
|
|
60383
60828
|
label: "Humidity"
|
|
60384
|
-
}),
|
|
60829
|
+
})),
|
|
60385
60830
|
/** Ms epoch when the slice was last updated. */
|
|
60386
|
-
lastFetchedAt: number()
|
|
60387
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
60388
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
60389
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
60390
|
-
unit: string().optional(),
|
|
60391
|
-
/** Suggested decimal places for numeric display.
|
|
60392
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
60393
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
60394
|
-
* auto-formatting when absent. */
|
|
60395
|
-
precision: number().int().min(0).max(10).optional()
|
|
60831
|
+
lastFetchedAt: number()
|
|
60396
60832
|
});
|
|
60397
60833
|
var humiditySensorCapability = {
|
|
60398
60834
|
name: "humidity-sensor",
|
|
@@ -60423,12 +60859,7 @@ var humiditySensorCapability = {
|
|
|
60423
60859
|
} } },
|
|
60424
60860
|
/** Clock fields: written, but excluded from the compare that decides
|
|
60425
60861
|
* whether persisting is worth a SQLite commit. */
|
|
60426
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
60427
|
-
customize: {
|
|
60428
|
-
version: 1,
|
|
60429
|
-
advanced: "derive",
|
|
60430
|
-
targets: []
|
|
60431
|
-
}
|
|
60862
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
60432
60863
|
};
|
|
60433
60864
|
/**
|
|
60434
60865
|
* Image display cap. Models a single still image exposed by an integration —
|
|
@@ -60449,7 +60880,7 @@ var ImageStatusSchema = object({
|
|
|
60449
60880
|
* entity exposes no `entity_picture` (yet). */
|
|
60450
60881
|
url: string().nullable(),
|
|
60451
60882
|
/** Ms epoch of the upstream last-updated timestamp. Null at cold-start. */
|
|
60452
|
-
lastUpdated: number().nullable()
|
|
60883
|
+
lastUpdated: number().nullable().meta(readingMeta("none"))
|
|
60453
60884
|
});
|
|
60454
60885
|
var imageCapability = {
|
|
60455
60886
|
name: "image",
|
|
@@ -60537,19 +60968,19 @@ var NormalizedRangeSchema = object({
|
|
|
60537
60968
|
*/
|
|
60538
60969
|
var ImageSettingsStatusSchema = object({
|
|
60539
60970
|
/** Normalized 0–100. */
|
|
60540
|
-
brightness: number().optional(),
|
|
60971
|
+
brightness: number().optional().meta(readingMeta("none")),
|
|
60541
60972
|
/** Normalized 0–100. */
|
|
60542
|
-
contrast: number().optional(),
|
|
60973
|
+
contrast: number().optional().meta(readingMeta("none")),
|
|
60543
60974
|
/** Normalized 0–100. */
|
|
60544
|
-
saturation: number().optional(),
|
|
60975
|
+
saturation: number().optional().meta(readingMeta("none")),
|
|
60545
60976
|
/** Normalized 0–100. */
|
|
60546
|
-
sharpness: number().optional(),
|
|
60977
|
+
sharpness: number().optional().meta(readingMeta("none")),
|
|
60547
60978
|
mirror: boolean().optional(),
|
|
60548
60979
|
flip: boolean().optional(),
|
|
60549
60980
|
rotate: ImageRotateSchema.optional(),
|
|
60550
60981
|
whiteBalance: WhiteBalanceModeSchema.optional(),
|
|
60551
60982
|
/** Manual white-balance warmth, NORMALIZED 0–100. Meaningful only when `whiteBalance === 'manual'`. */
|
|
60552
|
-
warmth: number().optional(),
|
|
60983
|
+
warmth: number().optional().meta(readingMeta("none")),
|
|
60553
60984
|
exposureMode: ExposureModeSchema.optional(),
|
|
60554
60985
|
backlightMode: BacklightModeSchema.optional(),
|
|
60555
60986
|
lastFetchedAt: number()
|
|
@@ -60828,10 +61259,10 @@ var IntercomAbilitySchema = object({
|
|
|
60828
61259
|
/** Codecs accepted by firmware, in preference order. Driver-authored strings. */
|
|
60829
61260
|
codecs: array(string()),
|
|
60830
61261
|
/** Sample rate (Hz) the firmware expects. Reolink typical: 16000. */
|
|
60831
|
-
sampleRate: number(),
|
|
61262
|
+
sampleRate: number().meta(readingMeta("none")),
|
|
60832
61263
|
duplex: _enum(["half", "full"]),
|
|
60833
61264
|
/** Max in-flight audio backlog before drop (ms). Server uses this to bound latency. */
|
|
60834
|
-
maxBacklogMs: number()
|
|
61265
|
+
maxBacklogMs: number().meta(readingMeta("duration-ms"))
|
|
60835
61266
|
});
|
|
60836
61267
|
var IntercomStatusSchema = object({
|
|
60837
61268
|
/** True while a talk session is open. */
|
|
@@ -61058,13 +61489,13 @@ var LawnMowerControlStatusSchema = object({
|
|
|
61058
61489
|
activity: LawnMowerActivitySchema,
|
|
61059
61490
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
61060
61491
|
* reading. */
|
|
61061
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
61492
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61062
61493
|
/** 0..100 mowing-completion percentage of the current task, or null when no
|
|
61063
61494
|
* task is active / progress is unavailable. */
|
|
61064
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
61495
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61065
61496
|
/** Current device/event code (dynamic — mostly status, sometimes an error),
|
|
61066
61497
|
* or null when unknown. */
|
|
61067
|
-
currentCode: number().nullable(),
|
|
61498
|
+
currentCode: number().nullable().meta(readingMeta("none")),
|
|
61068
61499
|
/** Human label for {@link currentCode}, or null when undecodable. */
|
|
61069
61500
|
currentCodeLabel: string().nullable(),
|
|
61070
61501
|
/** Severity of {@link currentCode}. `error` (and often `warning`) warrants UI
|
|
@@ -61597,7 +62028,7 @@ var MediaPlayerStatusSchema = object({
|
|
|
61597
62028
|
state: MediaPlayerStateSchema,
|
|
61598
62029
|
/** Volume as 0..100 inclusive. Null when the device has no volume
|
|
61599
62030
|
* surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
|
|
61600
|
-
volumeLevel: number().min(0).max(100).nullable(),
|
|
62031
|
+
volumeLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61601
62032
|
/** Mute toggle distinct from volume=0. Null when no mute surface.
|
|
61602
62033
|
* Pair with `DeviceFeature.MediaPlayerMute`. */
|
|
61603
62034
|
isMuted: boolean().nullable(),
|
|
@@ -61610,10 +62041,10 @@ var MediaPlayerStatusSchema = object({
|
|
|
61610
62041
|
currentMedia: MediaInfoSchema.nullable(),
|
|
61611
62042
|
/** Current playback position in ms. Null when not seekable or
|
|
61612
62043
|
* nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
|
|
61613
|
-
positionMs: number().int().nonnegative().nullable(),
|
|
62044
|
+
positionMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
61614
62045
|
/** Total duration of the current media in ms. Null when unknown
|
|
61615
62046
|
* (live stream) or nothing is playing. */
|
|
61616
|
-
durationMs: number().int().nonnegative().nullable(),
|
|
62047
|
+
durationMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
61617
62048
|
/** Shuffle toggle. Null when no shuffle surface.
|
|
61618
62049
|
* Pair with `DeviceFeature.MediaPlayerShuffle`. */
|
|
61619
62050
|
shuffle: boolean().nullable(),
|
|
@@ -61922,7 +62353,7 @@ var motionCustomize = {
|
|
|
61922
62353
|
eventName: "onMotionChanged"
|
|
61923
62354
|
},
|
|
61924
62355
|
deviceTypes: [DeviceType.Camera],
|
|
61925
|
-
apply: "
|
|
62356
|
+
apply: "add",
|
|
61926
62357
|
applyAuthority: {
|
|
61927
62358
|
kind: "camera-sensors",
|
|
61928
62359
|
timeoutField: "motionCooldownMs"
|
|
@@ -61994,7 +62425,7 @@ var MotionStatusSchema = object({
|
|
|
61994
62425
|
* it, every provider seeded it at boot, and every session left it
|
|
61995
62426
|
* `detected: true` after its detach.
|
|
61996
62427
|
*/
|
|
61997
|
-
autoClearAfterMs: number().nullable()
|
|
62428
|
+
autoClearAfterMs: number().nullable().meta(readingMeta("duration-ms"))
|
|
61998
62429
|
});
|
|
61999
62430
|
/**
|
|
62000
62431
|
* Payload of `motion.onMotionChanged` event + the corresponding bus
|
|
@@ -62031,12 +62462,18 @@ var motionCapability = {
|
|
|
62031
62462
|
methods: {
|
|
62032
62463
|
/**
|
|
62033
62464
|
* Pull the current motion state synchronously. Convenience shortcut
|
|
62034
|
-
* for consumers that don't need the full status object
|
|
62035
|
-
*
|
|
62036
|
-
* `getStatus` once the auto-injected status surface lands in every
|
|
62037
|
-
* consumer.
|
|
62465
|
+
* for consumers that don't need the full status object. A composed
|
|
62466
|
+
* group answers from its slice (D944): unknown throws, it is not off.
|
|
62038
62467
|
*/
|
|
62039
62468
|
isDetected: method(object({ deviceId: number() }), boolean()) },
|
|
62469
|
+
/**
|
|
62470
|
+
* A composed motion group serves `isDetected` from `detected` (D944).
|
|
62471
|
+
* Without this the cap stays uncomposable (`has-commands`).
|
|
62472
|
+
*/
|
|
62473
|
+
composedMethods: { isDetected: {
|
|
62474
|
+
kind: "slice",
|
|
62475
|
+
field: "detected"
|
|
62476
|
+
} },
|
|
62040
62477
|
events: {
|
|
62041
62478
|
/**
|
|
62042
62479
|
* Fires every time the runner transitions a camera between
|
|
@@ -62176,7 +62613,7 @@ var MotionZoneRegionSchema = object({
|
|
|
62176
62613
|
* the grid region(s). */
|
|
62177
62614
|
var MotionZoneStatusSchema = object({
|
|
62178
62615
|
enabled: boolean(),
|
|
62179
|
-
sensitivity: number(),
|
|
62616
|
+
sensitivity: number().meta(readingMeta("none")),
|
|
62180
62617
|
/** Grid region(s). Today exactly one `grid` shape. */
|
|
62181
62618
|
regions: array(MotionZoneRegionSchema),
|
|
62182
62619
|
lastFetchedAt: number()
|
|
@@ -62546,7 +62983,7 @@ var NavigationStatusSchema = object({
|
|
|
62546
62983
|
following: boolean(),
|
|
62547
62984
|
flash: boolean(),
|
|
62548
62985
|
lightMode: NavigationLightModeSchema,
|
|
62549
|
-
lightLevel: number().min(40).max(100),
|
|
62986
|
+
lightLevel: number().min(40).max(100).meta(readingMeta("none")),
|
|
62550
62987
|
/** Ms epoch when the slice was last updated. */
|
|
62551
62988
|
lastChangedAt: number()
|
|
62552
62989
|
});
|
|
@@ -62680,13 +63117,13 @@ var NetworkLinkStatusSchema = object({
|
|
|
62680
63117
|
* one whose reading has not landed must not be drawn at 0 %. Consumers
|
|
62681
63118
|
* SKIP a null rather than coerce it.
|
|
62682
63119
|
*/
|
|
62683
|
-
signalPercent: number().min(0).max(100).nullable(),
|
|
63120
|
+
signalPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
62684
63121
|
/** Raw received signal strength in dBm, when the firmware reports one. */
|
|
62685
|
-
rssiDbm: number().optional(),
|
|
63122
|
+
rssiDbm: number().optional().meta(readingMeta("signal-level")),
|
|
62686
63123
|
/** Network name of a wireless link, when the firmware reports it. */
|
|
62687
63124
|
ssid: string().optional(),
|
|
62688
63125
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
62689
|
-
lastUpdated: number()
|
|
63126
|
+
lastUpdated: number().meta(readingMeta("none"))
|
|
62690
63127
|
});
|
|
62691
63128
|
var networkLinkCapability = {
|
|
62692
63129
|
name: "network-link",
|
|
@@ -63071,7 +63508,7 @@ var NotifierStatusSchema = object({
|
|
|
63071
63508
|
lastError: string().nullable(),
|
|
63072
63509
|
/** Number of deliveries currently buffered server-side (rate-limited
|
|
63073
63510
|
* notifiers may queue). 0 when the provider sends synchronously. */
|
|
63074
|
-
queueDepth: number().int().nonnegative(),
|
|
63511
|
+
queueDepth: number().int().nonnegative().meta(readingMeta("count")),
|
|
63075
63512
|
/** Per-feature capability matrix — authoritative source for the
|
|
63076
63513
|
* compose-form field gating. */
|
|
63077
63514
|
supports: NotifierSupportsSchema
|
|
@@ -63163,11 +63600,9 @@ onSent: { data: object({
|
|
|
63163
63600
|
* cap fits (HA `sensor` whose `device_class` we don't have a typed cap
|
|
63164
63601
|
* for: water flow, distance, weight, frequency, signal strength, …).
|
|
63165
63602
|
*
|
|
63166
|
-
* The
|
|
63167
|
-
*
|
|
63168
|
-
*
|
|
63169
|
-
* The UI reads them directly from the slice — they are the single source
|
|
63170
|
-
* of truth for generic numeric rendering and do NOT live on `sourceInfo`.
|
|
63603
|
+
* The quantity is not on this slice. It is chosen when the device is
|
|
63604
|
+
* adopted and stored once on `SourceInfo.quantity` (D944). `value` is in
|
|
63605
|
+
* that quantity's base unit. `null` is a refused sample (D393).
|
|
63171
63606
|
*
|
|
63172
63607
|
* Prefer the typed alternatives (`temperature-sensor`, `humidity-sensor`,
|
|
63173
63608
|
* `ambient-light-sensor`, `pressure-sensor`, `power-meter`,
|
|
@@ -63176,15 +63611,8 @@ onSent: { data: object({
|
|
|
63176
63611
|
* numeric values land here.
|
|
63177
63612
|
*/
|
|
63178
63613
|
var NumericSensorStatusSchema = object({
|
|
63179
|
-
|
|
63180
|
-
|
|
63181
|
-
* Populated live from the upstream source on each state push.
|
|
63182
|
-
* Absent for unitless sensors. */
|
|
63183
|
-
unit: string().optional(),
|
|
63184
|
-
/** Suggested decimal places for numeric display.
|
|
63185
|
-
* Populated live from the upstream source when provided.
|
|
63186
|
-
* Falls back to auto-formatting when absent. */
|
|
63187
|
-
precision: number().int().min(0).max(10).optional(),
|
|
63614
|
+
/** Reading in the device quantity's base unit. `null` when refused (D393). */
|
|
63615
|
+
value: number().nullable().meta(readingMeta("device")),
|
|
63188
63616
|
/** Ms epoch when the slice was last updated. */
|
|
63189
63617
|
lastFetchedAt: number()
|
|
63190
63618
|
});
|
|
@@ -63208,11 +63636,11 @@ var numericSensorCapability = {
|
|
|
63208
63636
|
*/
|
|
63209
63637
|
durability: "restored",
|
|
63210
63638
|
/**
|
|
63211
|
-
* History (D850): recorded series. The unit is
|
|
63639
|
+
* History (D850): recorded series. The unit is the device quantity's base,
|
|
63640
|
+
* resolved when the series is read — the cap has no single unit.
|
|
63212
63641
|
*/
|
|
63213
63642
|
history: { fields: { value: {
|
|
63214
63643
|
kind: "gauge",
|
|
63215
|
-
unitFrom: "unit",
|
|
63216
63644
|
minIntervalMs: 3e4
|
|
63217
63645
|
} } },
|
|
63218
63646
|
/** Clock fields: written, but excluded from the compare that decides
|
|
@@ -63550,23 +63978,26 @@ var PetFeederStatusSchema = object({
|
|
|
63550
63978
|
/** Food currently in the bowl (grams). Null when the device has not
|
|
63551
63979
|
* reported a reading yet. On dual-hopper models this is the combined
|
|
63552
63980
|
* bowl reading; per-hopper levels live in `food1`/`food2`. */
|
|
63553
|
-
foodLevel: number().nullable(),
|
|
63981
|
+
foodLevel: number().nullable().meta(readingMeta("none")),
|
|
63554
63982
|
/** Hopper-1 food level (grams) on dual-hopper feeders; null on
|
|
63555
63983
|
* single-hopper models. */
|
|
63556
|
-
food1: number().nullable(),
|
|
63984
|
+
food1: number().nullable().meta(readingMeta("none")),
|
|
63557
63985
|
/** Hopper-2 food level (grams) on dual-hopper feeders; null on
|
|
63558
63986
|
* single-hopper models. */
|
|
63559
|
-
food2: number().nullable(),
|
|
63987
|
+
food2: number().nullable().meta(readingMeta("none")),
|
|
63560
63988
|
/** Derived low-food flag — mirrors the HA `food_level` binary_sensor
|
|
63561
63989
|
* (`device_class: problem`, on = low). True when the bowl is empty /
|
|
63562
63990
|
* below the feeder's low threshold. */
|
|
63563
63991
|
lowFood: boolean(),
|
|
63564
63992
|
/** Battery charge 0..100 (%). Null on mains-powered models or when the
|
|
63565
63993
|
* device has no battery reading. */
|
|
63566
|
-
batteryPower: number().min(0).max(100).nullable(),
|
|
63567
|
-
/**
|
|
63568
|
-
*
|
|
63569
|
-
|
|
63994
|
+
batteryPower: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
63995
|
+
/**
|
|
63996
|
+
* Desiccant life remaining, stored in seconds (duration base, D944).
|
|
63997
|
+
* Providers convert from the days the feeder reports. Null when the
|
|
63998
|
+
* model has no desiccant sensor.
|
|
63999
|
+
*/
|
|
64000
|
+
desiccantLeftDays: number().nullable().meta(readingMeta("duration")),
|
|
63570
64001
|
/** True while a feed is in progress. */
|
|
63571
64002
|
feeding: boolean(),
|
|
63572
64003
|
/** Decoded connectivity / power status (HA petkit device-status enum).
|
|
@@ -63577,7 +64008,7 @@ var PetFeederStatusSchema = object({
|
|
|
63577
64008
|
* with `errorCode` for consumers that want the raw integer. */
|
|
63578
64009
|
error: string().nullable(),
|
|
63579
64010
|
/** Raw device error code (0 / null = no error). */
|
|
63580
|
-
errorCode: number().nullable(),
|
|
64011
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
63581
64012
|
/** True for D4S/D4SH dual-hopper hardware — gates the per-hopper UI. */
|
|
63582
64013
|
isDualHopper: boolean(),
|
|
63583
64014
|
/** Child-lock (manual-lock) setting — buttons on the unit are disabled. */
|
|
@@ -63587,7 +64018,7 @@ var PetFeederStatusSchema = object({
|
|
|
63587
64018
|
/** Play a chime when dispensing. */
|
|
63588
64019
|
feedSound: boolean(),
|
|
63589
64020
|
/** Speaker / prompt volume level (device-scaled integer). */
|
|
63590
|
-
volume: number(),
|
|
64021
|
+
volume: number().meta(readingMeta("none")),
|
|
63591
64022
|
/** Ms epoch when the slice was last refreshed from the cloud. */
|
|
63592
64023
|
lastFetchedAt: number()
|
|
63593
64024
|
});
|
|
@@ -63706,7 +64137,7 @@ var petFeederCapability = {
|
|
|
63706
64137
|
},
|
|
63707
64138
|
desiccantLeftDays: {
|
|
63708
64139
|
kind: "gauge",
|
|
63709
|
-
unit: "
|
|
64140
|
+
unit: "s"
|
|
63710
64141
|
}
|
|
63711
64142
|
} }
|
|
63712
64143
|
};
|
|
@@ -64107,36 +64538,19 @@ method(_void(), PlatformCapabilitiesSchema), method(_void(), HardwareInfoSchema)
|
|
|
64107
64538
|
*/
|
|
64108
64539
|
var PowerMeterStatusSchema = object({
|
|
64109
64540
|
/** Instantaneous power draw in watts. */
|
|
64110
|
-
watts: number().optional().meta({
|
|
64111
|
-
unit: "W",
|
|
64112
|
-
label: "Power"
|
|
64113
|
-
}),
|
|
64541
|
+
watts: number().optional().meta(readingMeta("power", { label: "Power" })),
|
|
64114
64542
|
/** Cumulative energy in kilowatt-hours since the meter was reset. */
|
|
64115
|
-
kwhTotal: number().optional().meta({
|
|
64116
|
-
unit: "kWh",
|
|
64117
|
-
label: "Energy"
|
|
64118
|
-
}),
|
|
64543
|
+
kwhTotal: number().optional().meta(readingMeta("energy", { label: "Energy" })),
|
|
64119
64544
|
/** Voltage in volts. */
|
|
64120
|
-
volts: number().optional(),
|
|
64545
|
+
volts: number().optional().meta(readingMeta("voltage")),
|
|
64121
64546
|
/** Current in amperes. */
|
|
64122
|
-
amps: number().optional(),
|
|
64123
|
-
/** Apparent power in volt-amperes
|
|
64124
|
-
va: number().optional(),
|
|
64547
|
+
amps: number().optional().meta(readingMeta("current")),
|
|
64548
|
+
/** Apparent power in volt-amperes. */
|
|
64549
|
+
va: number().optional().meta(readingMeta("apparent-power")),
|
|
64125
64550
|
/** Power factor (0..1) if reported. */
|
|
64126
|
-
powerFactor: number().min(0).max(1).optional(),
|
|
64551
|
+
powerFactor: number().min(0).max(1).optional().meta(readingMeta("ratio")),
|
|
64127
64552
|
/** Ms epoch when the slice was last updated. */
|
|
64128
|
-
lastFetchedAt: number()
|
|
64129
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
64130
|
-
* `attributes.unit_of_measurement` → 'V' / 'A' / 'W' / 'kW' / 'kWh').
|
|
64131
|
-
* Each upstream `sensor.*` entity surfaces ONE device_class, so one
|
|
64132
|
-
* unit per slice is unambiguous. The UI prefers this over the role's
|
|
64133
|
-
* canonical unit so a 'kW' / 'Wh' feed renders verbatim. */
|
|
64134
|
-
unit: string().optional(),
|
|
64135
|
-
/** Suggested decimal places for numeric display.
|
|
64136
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
64137
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
64138
|
-
* auto-formatting when absent. */
|
|
64139
|
-
precision: number().int().min(0).max(10).optional()
|
|
64553
|
+
lastFetchedAt: number()
|
|
64140
64554
|
});
|
|
64141
64555
|
var powerMeterCapability = {
|
|
64142
64556
|
name: "power-meter",
|
|
@@ -64200,12 +64614,7 @@ var powerMeterCapability = {
|
|
|
64200
64614
|
} },
|
|
64201
64615
|
/** Clock fields: written, but excluded from the compare that decides
|
|
64202
64616
|
* whether persisting is worth a SQLite commit. */
|
|
64203
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
64204
|
-
customize: {
|
|
64205
|
-
version: 1,
|
|
64206
|
-
advanced: "derive",
|
|
64207
|
-
targets: []
|
|
64208
|
-
}
|
|
64617
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
64209
64618
|
};
|
|
64210
64619
|
/**
|
|
64211
64620
|
* Presence cap. Models HA `person.*` and `device_tracker.*` entities
|
|
@@ -64225,11 +64634,11 @@ var powerMeterCapability = {
|
|
|
64225
64634
|
*/
|
|
64226
64635
|
var GpsLocationSchema = object({
|
|
64227
64636
|
/** Latitude in decimal degrees, -90..90. */
|
|
64228
|
-
latitude: number().min(-90).max(90),
|
|
64637
|
+
latitude: number().min(-90).max(90).meta(readingMeta("angle")),
|
|
64229
64638
|
/** Longitude in decimal degrees, -180..180. */
|
|
64230
|
-
longitude: number().min(-180).max(180),
|
|
64639
|
+
longitude: number().min(-180).max(180).meta(readingMeta("angle")),
|
|
64231
64640
|
/** Reported accuracy in meters (lower = better). */
|
|
64232
|
-
accuracyMeters: number().nonnegative()
|
|
64641
|
+
accuracyMeters: number().nonnegative().meta(readingMeta("length"))
|
|
64233
64642
|
});
|
|
64234
64643
|
var PresenceStatusSchema = object({
|
|
64235
64644
|
/** `home` / `not_home` / any user-defined zone name. */
|
|
@@ -64241,7 +64650,7 @@ var PresenceStatusSchema = object({
|
|
|
64241
64650
|
gps: GpsLocationSchema.nullable(),
|
|
64242
64651
|
/** Optional battery level of the tracking device (0..100). Null
|
|
64243
64652
|
* when not reported. */
|
|
64244
|
-
batteryPercent: number().min(0).max(100).nullable(),
|
|
64653
|
+
batteryPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
64245
64654
|
/** Ms epoch when the slice was last updated. */
|
|
64246
64655
|
lastChangedAt: number()
|
|
64247
64656
|
});
|
|
@@ -64291,19 +64700,10 @@ var presenceCapability = {
|
|
|
64291
64700
|
* `sourceInfo`.
|
|
64292
64701
|
*/
|
|
64293
64702
|
var PressureSensorStatusSchema = object({
|
|
64294
|
-
/** Current pressure in hPa. */
|
|
64295
|
-
hpa: number(),
|
|
64703
|
+
/** Current pressure in hPa. `null` when the sample was refused (D393). */
|
|
64704
|
+
hpa: number().nullable().meta(readingMeta("pressure", { precision: 0 })),
|
|
64296
64705
|
/** Ms epoch when the slice was last updated. */
|
|
64297
|
-
lastFetchedAt: number()
|
|
64298
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
64299
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
64300
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
64301
|
-
unit: string().optional(),
|
|
64302
|
-
/** Suggested decimal places for numeric display.
|
|
64303
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
64304
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
64305
|
-
* auto-formatting when absent. */
|
|
64306
|
-
precision: number().int().min(0).max(10).optional()
|
|
64706
|
+
lastFetchedAt: number()
|
|
64307
64707
|
});
|
|
64308
64708
|
var pressureSensorCapability = {
|
|
64309
64709
|
name: "pressure-sensor",
|
|
@@ -64829,8 +65229,8 @@ var ptzCapability = {
|
|
|
64829
65229
|
};
|
|
64830
65230
|
var PtzAutotrackSettingsSchema = object({
|
|
64831
65231
|
targetType: string().describe("Vendor target string (people/vehicle/pet); empty = camera default"),
|
|
64832
|
-
stopDelaySeconds: number().int().min(0).max(300),
|
|
64833
|
-
disappearDelaySeconds: number().int().min(0).max(300)
|
|
65232
|
+
stopDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration")),
|
|
65233
|
+
disappearDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration"))
|
|
64834
65234
|
});
|
|
64835
65235
|
/**
|
|
64836
65236
|
* One option the camera advertises as a valid `targetType`. Drivers
|
|
@@ -64984,7 +65384,7 @@ var RunningStateStatusSchema = object({
|
|
|
64984
65384
|
/** null = unknown — never coerced to false (D393). */
|
|
64985
65385
|
running: boolean().nullable(),
|
|
64986
65386
|
/** Epoch ms the current boolean began; null while `running` is null. */
|
|
64987
|
-
since: number().nullable(),
|
|
65387
|
+
since: number().nullable().meta(readingMeta("none")),
|
|
64988
65388
|
source: RunningStateSourceSchema.meta({ label: "Source" }),
|
|
64989
65389
|
phase: string().nullable(),
|
|
64990
65390
|
/** null until a reading has been published (D393). */
|
|
@@ -64999,7 +65399,6 @@ var RUNNING_DEVICE_TYPES = Object.values(DeviceType);
|
|
|
64999
65399
|
/** Generic Customize target for the running boolean (D936). */
|
|
65000
65400
|
var runningCustomize = {
|
|
65001
65401
|
version: 1,
|
|
65002
|
-
advanced: "derive",
|
|
65003
65402
|
targets: [{
|
|
65004
65403
|
id: "running",
|
|
65005
65404
|
cardinality: "scalar",
|
|
@@ -65019,7 +65418,7 @@ var runningCustomize = {
|
|
|
65019
65418
|
DeviceType.Thermostat,
|
|
65020
65419
|
DeviceType.PetFeeder
|
|
65021
65420
|
],
|
|
65022
|
-
apply: "add
|
|
65421
|
+
apply: "add",
|
|
65023
65422
|
path: "running",
|
|
65024
65423
|
sources: [
|
|
65025
65424
|
{
|
|
@@ -66287,9 +66686,9 @@ var RecordTriggerSchema = _enum([
|
|
|
66287
66686
|
*/
|
|
66288
66687
|
var RecordWindowSchema = object({
|
|
66289
66688
|
trigger: RecordTriggerSchema,
|
|
66290
|
-
day: number().int().min(0).max(6),
|
|
66291
|
-
startMinute: number().int().min(0).max(1439),
|
|
66292
|
-
endMinute: number().int().min(1).max(1440)
|
|
66689
|
+
day: number().int().min(0).max(6).meta(readingMeta("none")),
|
|
66690
|
+
startMinute: number().int().min(0).max(1439).meta(readingMeta("none")),
|
|
66691
|
+
endMinute: number().int().min(1).max(1440).meta(readingMeta("none"))
|
|
66293
66692
|
});
|
|
66294
66693
|
/** Status of one physical volume, as the camera itself describes it. */
|
|
66295
66694
|
var OnboardStorageVolumeSchema = object({
|
|
@@ -66365,10 +66764,10 @@ var RecordingOnboardStatusSchema = object({
|
|
|
66365
66764
|
/** Master "record to the card at all" switch. */
|
|
66366
66765
|
enabled: boolean().nullable(),
|
|
66367
66766
|
overwriteWhenFull: boolean().nullable(),
|
|
66368
|
-
preRecordSec: number().nullable(),
|
|
66369
|
-
postRecordSec: number().nullable(),
|
|
66767
|
+
preRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
66768
|
+
postRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
66370
66769
|
/** Length of one recorded file, in minutes. */
|
|
66371
|
-
segmentMinutes: number().nullable(),
|
|
66770
|
+
segmentMinutes: number().nullable().meta(readingMeta("none")),
|
|
66372
66771
|
/** The primary track's weekly windows, flattened. */
|
|
66373
66772
|
windows: array(RecordWindowSchema),
|
|
66374
66773
|
/**
|
|
@@ -66384,7 +66783,7 @@ var RecordingOnboardStatusSchema = object({
|
|
|
66384
66783
|
* provider reporting a non-zero count also reports the schedule as not
|
|
66385
66784
|
* writable.
|
|
66386
66785
|
*/
|
|
66387
|
-
unreadableWindows: number(),
|
|
66786
|
+
unreadableWindows: number().meta(readingMeta("count")),
|
|
66388
66787
|
/**
|
|
66389
66788
|
* The camera is scheduled to record and has NO usable storage.
|
|
66390
66789
|
*
|
|
@@ -67331,7 +67730,7 @@ var CamStreamDescriptorSchema = object({
|
|
|
67331
67730
|
url: string().optional(),
|
|
67332
67731
|
codec: string().optional(),
|
|
67333
67732
|
resolution: CamStreamResolutionSchema.optional(),
|
|
67334
|
-
fps: number().positive().optional(),
|
|
67733
|
+
fps: number().positive().optional().meta(readingMeta("rate")),
|
|
67335
67734
|
label: string().optional(),
|
|
67336
67735
|
/** Device-level features (e.g. `battery-operated`) — drives broker policy. */
|
|
67337
67736
|
deviceFeatures: array(string()).optional(),
|
|
@@ -67418,18 +67817,18 @@ var StreamProfileSchema = _enum([
|
|
|
67418
67817
|
]);
|
|
67419
67818
|
/** The current encoding config of one stream profile. */
|
|
67420
67819
|
var StreamProfileConfigSchema = object({
|
|
67421
|
-
width: number(),
|
|
67422
|
-
height: number(),
|
|
67820
|
+
width: number().meta(readingMeta("none")),
|
|
67821
|
+
height: number().meta(readingMeta("none")),
|
|
67423
67822
|
codec: _enum(["h264", "h265"]),
|
|
67424
|
-
framerate: number(),
|
|
67425
|
-
bitrate: number(),
|
|
67823
|
+
framerate: number().meta(readingMeta("rate")),
|
|
67824
|
+
bitrate: number().meta(readingMeta("bitrate")),
|
|
67426
67825
|
bitrateMode: _enum(["vbr", "cbr"]).optional(),
|
|
67427
67826
|
encoderProfile: _enum([
|
|
67428
67827
|
"high",
|
|
67429
67828
|
"main",
|
|
67430
67829
|
"baseline"
|
|
67431
67830
|
]).optional(),
|
|
67432
|
-
gop: number().optional(),
|
|
67831
|
+
gop: number().optional().meta(readingMeta("none")),
|
|
67433
67832
|
/**
|
|
67434
67833
|
* Whether THIS profile currently carries an audio track. READ-ONLY here.
|
|
67435
67834
|
*
|
|
@@ -67848,12 +68247,7 @@ var switchCapability = {
|
|
|
67848
68247
|
label: "On",
|
|
67849
68248
|
kind: "boolean"
|
|
67850
68249
|
}
|
|
67851
|
-
}] }
|
|
67852
|
-
customize: {
|
|
67853
|
-
version: 1,
|
|
67854
|
-
advanced: "derive",
|
|
67855
|
-
targets: []
|
|
67856
|
-
}
|
|
68250
|
+
}] }
|
|
67857
68251
|
};
|
|
67858
68252
|
/** C0 controls, DEL and the C1 range: none of them belongs in a name. */
|
|
67859
68253
|
function hasControlCharacter(value) {
|
|
@@ -68436,35 +68830,21 @@ var tamperCapability = {
|
|
|
68436
68830
|
* entries with `device_class: temperature` and any future native
|
|
68437
68831
|
* thermometer.
|
|
68438
68832
|
*
|
|
68439
|
-
*
|
|
68440
|
-
*
|
|
68441
|
-
* (climate-control's `currentTemp`, energy analytics) can compose
|
|
68442
|
-
* without per-source unit fixups. The canonical display unit (`°C`) is
|
|
68443
|
-
* a descriptor constant in the UI (ROLE_DESCRIPTOR), not stored in
|
|
68444
|
-
* `sourceInfo`.
|
|
68833
|
+
* The number is Celsius (D944). Providers convert on ingest. A failed
|
|
68834
|
+
* conversion is `null`, never a guess. Display unit is a read-time preference.
|
|
68445
68835
|
*
|
|
68446
68836
|
* Status `lastFetchedAt` lets staleness-aware consumers detect a
|
|
68447
68837
|
* frozen feed (provider hung) distinct from a "temperature hasn't
|
|
68448
68838
|
* changed" steady state.
|
|
68449
68839
|
*/
|
|
68450
68840
|
var TemperatureSensorStatusSchema = object({
|
|
68451
|
-
/** Current temperature in Celsius. */
|
|
68452
|
-
celsius: number().meta({
|
|
68453
|
-
|
|
68841
|
+
/** Current temperature in Celsius. `null` when the sample was refused (D393). */
|
|
68842
|
+
celsius: number().nullable().meta(readingMeta("temperature", {
|
|
68843
|
+
precision: 1,
|
|
68454
68844
|
label: "Temperature"
|
|
68455
|
-
}),
|
|
68845
|
+
})),
|
|
68456
68846
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
68457
|
-
lastFetchedAt: number()
|
|
68458
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
68459
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
68460
|
-
* role's canonical unit, so a Fahrenheit feed renders '°F' not '°C'.
|
|
68461
|
-
* Absent → the UI falls back to the role's canonical unit. */
|
|
68462
|
-
unit: string().optional(),
|
|
68463
|
-
/** Suggested decimal places for numeric display.
|
|
68464
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
68465
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
68466
|
-
* auto-formatting when absent. */
|
|
68467
|
-
precision: number().int().min(0).max(10).optional()
|
|
68847
|
+
lastFetchedAt: number()
|
|
68468
68848
|
});
|
|
68469
68849
|
var temperatureSensorCapability = {
|
|
68470
68850
|
name: "temperature-sensor",
|
|
@@ -68495,12 +68875,7 @@ var temperatureSensorCapability = {
|
|
|
68495
68875
|
} } },
|
|
68496
68876
|
/** Clock fields: written, but excluded from the compare that decides
|
|
68497
68877
|
* whether persisting is worth a SQLite commit. */
|
|
68498
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
68499
|
-
customize: {
|
|
68500
|
-
version: 1,
|
|
68501
|
-
advanced: "derive",
|
|
68502
|
-
targets: []
|
|
68503
|
-
}
|
|
68878
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
68504
68879
|
};
|
|
68505
68880
|
/**
|
|
68506
68881
|
* toast — system-scoped singleton capability that streams toast
|
|
@@ -68783,16 +69158,16 @@ var VacuumControlStatusSchema = object({
|
|
|
68783
69158
|
]),
|
|
68784
69159
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
68785
69160
|
* reading. */
|
|
68786
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
69161
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
68787
69162
|
/** Current fan-speed token (provider-verbatim). Null when unknown or
|
|
68788
69163
|
* the vacuum has no speed control. */
|
|
68789
69164
|
fanSpeed: string().nullable(),
|
|
68790
69165
|
/** Speed tokens the hardware accepts — drives the UI selector. */
|
|
68791
69166
|
availableFanSpeeds: array(string()),
|
|
68792
69167
|
/** 0..100 cleaning-completion percentage of the current task, or null. */
|
|
68793
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
69168
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
68794
69169
|
/** Current error code (0 / null = no error). */
|
|
68795
|
-
errorCode: number().nullable(),
|
|
69170
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
68796
69171
|
/** Human label for {@link errorCode}, or null when none / undecodable. */
|
|
68797
69172
|
errorLabel: string().nullable(),
|
|
68798
69173
|
/** Ms epoch when the slice was last updated. */
|
|
@@ -68870,7 +69245,7 @@ var ValveStatusSchema = object({
|
|
|
68870
69245
|
]),
|
|
68871
69246
|
/** 0 = fully closed, 100 = fully open. Null when the device has no
|
|
68872
69247
|
* intermediate position surface. */
|
|
68873
|
-
position: number().min(0).max(100).nullable(),
|
|
69248
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
68874
69249
|
/** Ms epoch when the slice was last updated. */
|
|
68875
69250
|
lastChangedAt: number()
|
|
68876
69251
|
});
|
|
@@ -68978,9 +69353,9 @@ var vibrationCapability = {
|
|
|
68978
69353
|
*/
|
|
68979
69354
|
var WaterHeaterStatusSchema = object({
|
|
68980
69355
|
/** Current measured temperature. Null when not reported. */
|
|
68981
|
-
currentTemp: number().nullable(),
|
|
69356
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
68982
69357
|
/** Target temperature setpoint. Null when no setpoint surface. */
|
|
68983
|
-
targetTemp: number().nullable(),
|
|
69358
|
+
targetTemp: number().nullable().meta(readingMeta("temperature")),
|
|
68984
69359
|
/** Active operation mode = HA `state` (`eco` / `electric` / `gas` /
|
|
68985
69360
|
* `heat_pump` / `high_demand` / `performance` / `off`). Null when the
|
|
68986
69361
|
* device reports an unknown state. */
|
|
@@ -68991,9 +69366,9 @@ var WaterHeaterStatusSchema = object({
|
|
|
68991
69366
|
* has no away surface. */
|
|
68992
69367
|
away: boolean().nullable(),
|
|
68993
69368
|
/** HA `min_temp` attribute. Null when not reported. */
|
|
68994
|
-
minTemp: number().nullable(),
|
|
69369
|
+
minTemp: number().nullable().meta(readingMeta("temperature")),
|
|
68995
69370
|
/** HA `max_temp` attribute. Null when not reported. */
|
|
68996
|
-
maxTemp: number().nullable(),
|
|
69371
|
+
maxTemp: number().nullable().meta(readingMeta("temperature")),
|
|
68997
69372
|
/** Ms epoch when the slice was last updated. */
|
|
68998
69373
|
lastChangedAt: number()
|
|
68999
69374
|
});
|
|
@@ -69078,25 +69453,18 @@ var waterHeaterCapability = {
|
|
|
69078
69453
|
* Forecast deferred — current conditions only for v1.
|
|
69079
69454
|
*/
|
|
69080
69455
|
var WeatherStatusSchema = object({
|
|
69081
|
-
/** Verbatim
|
|
69082
|
-
* when no condition has been reported yet. */
|
|
69456
|
+
/** Verbatim condition state (`sunny`, `cloudy`, `rainy`, …). Null when none yet. */
|
|
69083
69457
|
condition: string().nullable(),
|
|
69084
|
-
/** Current temperature in
|
|
69085
|
-
temperature: number().nullable(),
|
|
69086
|
-
/** Temperature unit string (e.g. `°C` / `°F`). Null when not provided. */
|
|
69087
|
-
temperatureUnit: string().nullable(),
|
|
69458
|
+
/** Current temperature in Celsius. Null when not provided or refused. */
|
|
69459
|
+
temperature: number().nullable().meta(readingMeta("temperature", { precision: 1 })),
|
|
69088
69460
|
/** Relative humidity (0..100). Null when not provided. */
|
|
69089
|
-
humidity: number().min(0).max(100).nullable(),
|
|
69090
|
-
/** Barometric pressure in
|
|
69091
|
-
pressure: number().nullable(),
|
|
69092
|
-
/**
|
|
69093
|
-
|
|
69094
|
-
/** Wind speed in the reported unit. Null when not provided. */
|
|
69095
|
-
windSpeed: number().nullable(),
|
|
69096
|
-
/** Wind-speed unit string (e.g. `km/h` / `mph`). Null when not provided. */
|
|
69097
|
-
windSpeedUnit: string().nullable(),
|
|
69461
|
+
humidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
69462
|
+
/** Barometric pressure in hPa. Null when not provided or refused. */
|
|
69463
|
+
pressure: number().nullable().meta(readingMeta("pressure")),
|
|
69464
|
+
/** Wind speed in metres per second. Null when not provided or refused. */
|
|
69465
|
+
windSpeed: number().nullable().meta(readingMeta("speed")),
|
|
69098
69466
|
/** Wind bearing in degrees (0..360, meteorological). Null when not provided. */
|
|
69099
|
-
windBearing: number().nullable(),
|
|
69467
|
+
windBearing: number().nullable().meta(readingMeta("angle")),
|
|
69100
69468
|
/** Ms epoch when the slice was last updated. */
|
|
69101
69469
|
lastFetchedAt: number()
|
|
69102
69470
|
});
|
|
@@ -69124,12 +69492,12 @@ var weatherCapability = {
|
|
|
69124
69492
|
*/
|
|
69125
69493
|
durability: "session",
|
|
69126
69494
|
/**
|
|
69127
|
-
* History (D850): recorded series.
|
|
69495
|
+
* History (D850): recorded series. Numbers are the quantity base (D944).
|
|
69128
69496
|
*/
|
|
69129
69497
|
history: { fields: {
|
|
69130
69498
|
temperature: {
|
|
69131
69499
|
kind: "gauge",
|
|
69132
|
-
|
|
69500
|
+
unit: "°C",
|
|
69133
69501
|
deadband: .2
|
|
69134
69502
|
},
|
|
69135
69503
|
humidity: {
|
|
@@ -69139,12 +69507,12 @@ var weatherCapability = {
|
|
|
69139
69507
|
},
|
|
69140
69508
|
pressure: {
|
|
69141
69509
|
kind: "gauge",
|
|
69142
|
-
|
|
69510
|
+
unit: "hPa",
|
|
69143
69511
|
deadband: .5
|
|
69144
69512
|
},
|
|
69145
69513
|
windSpeed: {
|
|
69146
69514
|
kind: "gauge",
|
|
69147
|
-
|
|
69515
|
+
unit: "m/s",
|
|
69148
69516
|
deadband: .5
|
|
69149
69517
|
}
|
|
69150
69518
|
} }
|
|
@@ -70508,6 +70876,8 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
70508
70876
|
featureProbe: featureProbeCapability,
|
|
70509
70877
|
flood: floodCapability,
|
|
70510
70878
|
gas: gasCapability,
|
|
70879
|
+
groupCommands: groupCommandsCapability,
|
|
70880
|
+
groupStatus: groupStatusCapability,
|
|
70511
70881
|
heatingValve: heatingValveCapability,
|
|
70512
70882
|
humidifier: humidifierCapability,
|
|
70513
70883
|
humiditySensor: humiditySensorCapability,
|
|
@@ -71888,6 +72258,13 @@ Object.freeze({
|
|
|
71888
72258
|
access: "view",
|
|
71889
72259
|
role: "admin"
|
|
71890
72260
|
},
|
|
72261
|
+
"addons.getPackageDocs": {
|
|
72262
|
+
capName: "addons",
|
|
72263
|
+
capScope: "system",
|
|
72264
|
+
addonId: null,
|
|
72265
|
+
access: "view",
|
|
72266
|
+
role: "admin"
|
|
72267
|
+
},
|
|
71891
72268
|
"addons.getVersions": {
|
|
71892
72269
|
capName: "addons",
|
|
71893
72270
|
capScope: "system",
|
|
@@ -74996,6 +75373,20 @@ Object.freeze({
|
|
|
74996
75373
|
access: "view",
|
|
74997
75374
|
role: "viewer"
|
|
74998
75375
|
},
|
|
75376
|
+
"groupCommands.getStatus": {
|
|
75377
|
+
capName: "group-commands",
|
|
75378
|
+
capScope: "device",
|
|
75379
|
+
addonId: null,
|
|
75380
|
+
access: "view",
|
|
75381
|
+
role: "viewer"
|
|
75382
|
+
},
|
|
75383
|
+
"groupStatus.getStatus": {
|
|
75384
|
+
capName: "group-status",
|
|
75385
|
+
capScope: "device",
|
|
75386
|
+
addonId: null,
|
|
75387
|
+
access: "view",
|
|
75388
|
+
role: "viewer"
|
|
75389
|
+
},
|
|
74999
75390
|
"heatingValve.getStatus": {
|
|
75000
75391
|
capName: "heating-valve",
|
|
75001
75392
|
capScope: "device",
|
|
@@ -84818,6 +85209,37 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84818
85209
|
icon: "flame"
|
|
84819
85210
|
}]
|
|
84820
85211
|
},
|
|
85212
|
+
"group-commands": {
|
|
85213
|
+
scope: "device",
|
|
85214
|
+
noun: t("Group command", "Comando di gruppo")
|
|
85215
|
+
},
|
|
85216
|
+
"group-status": {
|
|
85217
|
+
scope: "device",
|
|
85218
|
+
noun: t("Group", "Gruppo"),
|
|
85219
|
+
state: [
|
|
85220
|
+
{
|
|
85221
|
+
kind: "numeric",
|
|
85222
|
+
field: "included",
|
|
85223
|
+
quantity: t("the members reporting", "i membri che rispondono"),
|
|
85224
|
+
label: t("Reporting", "Rispondono"),
|
|
85225
|
+
icon: "users"
|
|
85226
|
+
},
|
|
85227
|
+
{
|
|
85228
|
+
kind: "numeric",
|
|
85229
|
+
field: "excluded",
|
|
85230
|
+
quantity: t("the members left out", "i membri esclusi"),
|
|
85231
|
+
label: t("Excluded", "Esclusi"),
|
|
85232
|
+
icon: "users"
|
|
85233
|
+
},
|
|
85234
|
+
{
|
|
85235
|
+
kind: "numeric",
|
|
85236
|
+
field: "total",
|
|
85237
|
+
quantity: t("the member count", "il numero di membri"),
|
|
85238
|
+
label: t("Members", "Membri"),
|
|
85239
|
+
icon: "sigma"
|
|
85240
|
+
}
|
|
85241
|
+
]
|
|
85242
|
+
},
|
|
84821
85243
|
"humidity-sensor": {
|
|
84822
85244
|
scope: "device",
|
|
84823
85245
|
noun: t("Humidity", "Umidità"),
|
|
@@ -84851,7 +85273,6 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84851
85273
|
field: "value",
|
|
84852
85274
|
quantity: t("the reading", "il valore"),
|
|
84853
85275
|
label: t("Reading", "Valore"),
|
|
84854
|
-
unitField: "unit",
|
|
84855
85276
|
icon: "gauge"
|
|
84856
85277
|
}]
|
|
84857
85278
|
},
|
|
@@ -84987,7 +85408,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84987
85408
|
field: "temperature",
|
|
84988
85409
|
quantity: t("the outdoor temperature", "la temperatura esterna"),
|
|
84989
85410
|
label: t("Temperature", "Temperatura"),
|
|
84990
|
-
|
|
85411
|
+
unit: "°C",
|
|
84991
85412
|
icon: "thermometer"
|
|
84992
85413
|
},
|
|
84993
85414
|
{
|
|
@@ -85003,7 +85424,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
85003
85424
|
field: "windSpeed",
|
|
85004
85425
|
quantity: t("the wind speed", "la velocità del vento"),
|
|
85005
85426
|
label: t("Wind", "Vento"),
|
|
85006
|
-
|
|
85427
|
+
unit: "m/s",
|
|
85007
85428
|
icon: "wind"
|
|
85008
85429
|
},
|
|
85009
85430
|
{
|
|
@@ -85011,7 +85432,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
85011
85432
|
field: "pressure",
|
|
85012
85433
|
quantity: t("the air pressure", "la pressione atmosferica"),
|
|
85013
85434
|
label: t("Pressure", "Pressione"),
|
|
85014
|
-
|
|
85435
|
+
unit: "hPa",
|
|
85015
85436
|
icon: "gauge"
|
|
85016
85437
|
}
|
|
85017
85438
|
]
|
|
@@ -86490,6 +86911,16 @@ Object.freeze({
|
|
|
86490
86911
|
form: "single",
|
|
86491
86912
|
optional: false
|
|
86492
86913
|
}],
|
|
86914
|
+
"groupCommands.getStatus": [{
|
|
86915
|
+
name: "deviceId",
|
|
86916
|
+
form: "single",
|
|
86917
|
+
optional: false
|
|
86918
|
+
}],
|
|
86919
|
+
"groupStatus.getStatus": [{
|
|
86920
|
+
name: "deviceId",
|
|
86921
|
+
form: "single",
|
|
86922
|
+
optional: false
|
|
86923
|
+
}],
|
|
86493
86924
|
"heatingValve.getStatus": [{
|
|
86494
86925
|
name: "deviceId",
|
|
86495
86926
|
form: "single",
|
|
@@ -88474,6 +88905,8 @@ new Map(Object.entries({
|
|
|
88474
88905
|
"detection-blind": "device-events",
|
|
88475
88906
|
"motion-noisy": "device-events",
|
|
88476
88907
|
"motion-calm": "device-events",
|
|
88908
|
+
"package-llm-silent": "device-events",
|
|
88909
|
+
"package-llm-answered": "device-events",
|
|
88477
88910
|
"recording-stalled": "device-events",
|
|
88478
88911
|
"recording-healthy": "device-events",
|
|
88479
88912
|
"recording-degraded": "device-events",
|
|
@@ -88557,6 +88990,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
|
|
|
88557
88990
|
label: "Motion without a subject",
|
|
88558
88991
|
kinds: ["motion-noisy", "motion-calm"]
|
|
88559
88992
|
},
|
|
88993
|
+
{
|
|
88994
|
+
id: "package-llm",
|
|
88995
|
+
family: "device-events",
|
|
88996
|
+
label: "Package confirm",
|
|
88997
|
+
kinds: ["package-llm-silent", "package-llm-answered"]
|
|
88998
|
+
},
|
|
88560
88999
|
{
|
|
88561
89000
|
id: "recording",
|
|
88562
89001
|
family: "device-events",
|
|
@@ -88738,6 +89177,8 @@ var DEVICE_EVENTS = [
|
|
|
88738
89177
|
"detection-blind",
|
|
88739
89178
|
"motion-noisy",
|
|
88740
89179
|
"motion-calm",
|
|
89180
|
+
"package-llm-silent",
|
|
89181
|
+
"package-llm-answered",
|
|
88741
89182
|
"recording-stalled",
|
|
88742
89183
|
"recording-healthy",
|
|
88743
89184
|
"recording-degraded",
|
|
@@ -89006,6 +89447,15 @@ new Map([
|
|
|
89006
89447
|
snapshotLabel: "Cameras with constant motion now",
|
|
89007
89448
|
snapshotSection: null
|
|
89008
89449
|
},
|
|
89450
|
+
{
|
|
89451
|
+
id: "package-llm-confirm",
|
|
89452
|
+
family: "device-events",
|
|
89453
|
+
label: "Package confirm (not answering / answering again)",
|
|
89454
|
+
bad: ["package-llm-silent"],
|
|
89455
|
+
recovery: ["package-llm-answered"],
|
|
89456
|
+
snapshotLabel: "Cameras whose package confirm is not answering",
|
|
89457
|
+
snapshotSection: null
|
|
89458
|
+
},
|
|
89009
89459
|
{
|
|
89010
89460
|
id: "recording-health",
|
|
89011
89461
|
family: "device-events",
|