@camstack/addon-provider-reolink 1.2.210 → 1.2.211
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
|
@@ -28,7 +28,7 @@ import { URL as URL$1 } from "url";
|
|
|
28
28
|
import { spawn as spawn$1 } from "node:child_process";
|
|
29
29
|
import os, { tmpdir } from "node:os";
|
|
30
30
|
import { createReadStream } from "node:fs";
|
|
31
|
-
//#region ../types/dist/event-category-
|
|
31
|
+
//#region ../types/dist/event-category-CT-hz5Rb.mjs
|
|
32
32
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
33
33
|
EventCategory["SystemBoot"] = "system.boot";
|
|
34
34
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -354,6 +354,14 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
354
354
|
/** The recovery edge of {@link PipelineMotionNoisy}: the motion fell back, or a detection arrived. */
|
|
355
355
|
EventCategory["PipelineMotionCalm"] = "pipeline.motion-calm";
|
|
356
356
|
/**
|
|
357
|
+
* A camera's package LLM confirm has failed closed three times in a row
|
|
358
|
+
* (D931, 2026-10-26). One edge per camera until
|
|
359
|
+
* {@link PipelinePackageLlmAnswered}.
|
|
360
|
+
*/
|
|
361
|
+
EventCategory["PipelinePackageLlmSilent"] = "pipeline.package-llm-silent";
|
|
362
|
+
/** The recovery edge of {@link PipelinePackageLlmSilent}: a confirm returned yes or no. */
|
|
363
|
+
EventCategory["PipelinePackageLlmAnswered"] = "pipeline.package-llm-answered";
|
|
364
|
+
/**
|
|
357
365
|
* Per-camera pipeline config was mutated by the orchestrator
|
|
358
366
|
* (a settings change via `setAgentInferenceDevices` /
|
|
359
367
|
* `setCameraStepToggle` / `setCameraStepSettings`). Orchestrator
|
|
@@ -5463,7 +5471,7 @@ var ZodIssueCode = {
|
|
|
5463
5471
|
var ZodFirstPartyTypeKind;
|
|
5464
5472
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5465
5473
|
//#endregion
|
|
5466
|
-
//#region ../types/dist/sleep-
|
|
5474
|
+
//#region ../types/dist/sleep-bykKrTgu.mjs
|
|
5467
5475
|
/**
|
|
5468
5476
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5469
5477
|
* window to float samples (D455).
|
|
@@ -8021,6 +8029,99 @@ var RecordKindDeclarationSchema = object({
|
|
|
8021
8029
|
}).strict();
|
|
8022
8030
|
/** The kind names: lower-case, dash separated, short enough for an index name. */
|
|
8023
8031
|
var RecordKindNameSchema = string().regex(/^[a-z][a-z0-9-]{0,47}$/);
|
|
8032
|
+
var READING_QUANTITIES = [
|
|
8033
|
+
"temperature",
|
|
8034
|
+
"pressure",
|
|
8035
|
+
"speed",
|
|
8036
|
+
"precipitation",
|
|
8037
|
+
"precipitation-rate",
|
|
8038
|
+
"length",
|
|
8039
|
+
"area",
|
|
8040
|
+
"illuminance",
|
|
8041
|
+
"irradiance",
|
|
8042
|
+
"power",
|
|
8043
|
+
"energy",
|
|
8044
|
+
"voltage",
|
|
8045
|
+
"current",
|
|
8046
|
+
"apparent-power",
|
|
8047
|
+
"humidity",
|
|
8048
|
+
"percentage",
|
|
8049
|
+
"concentration-volume",
|
|
8050
|
+
"concentration-mass",
|
|
8051
|
+
"concentration-ppb",
|
|
8052
|
+
"volume",
|
|
8053
|
+
"duration",
|
|
8054
|
+
"duration-ms",
|
|
8055
|
+
"information",
|
|
8056
|
+
"sound-level",
|
|
8057
|
+
"signal-level",
|
|
8058
|
+
"colour-temperature",
|
|
8059
|
+
"angle",
|
|
8060
|
+
"bitrate",
|
|
8061
|
+
"rate",
|
|
8062
|
+
"mass",
|
|
8063
|
+
"index",
|
|
8064
|
+
"ratio",
|
|
8065
|
+
"count",
|
|
8066
|
+
"none",
|
|
8067
|
+
"device"
|
|
8068
|
+
];
|
|
8069
|
+
var ReadingQuantitySchema = _enum(READING_QUANTITIES);
|
|
8070
|
+
new Set(READING_QUANTITIES);
|
|
8071
|
+
/**
|
|
8072
|
+
* Stored unit symbol for a quantity. `none` means the number is dimensionless
|
|
8073
|
+
* (or an index / ratio / count). `device` means the cap has no single unit.
|
|
8074
|
+
*/
|
|
8075
|
+
var QUANTITY_BASE = {
|
|
8076
|
+
temperature: "°C",
|
|
8077
|
+
pressure: "hPa",
|
|
8078
|
+
speed: "m/s",
|
|
8079
|
+
precipitation: "mm",
|
|
8080
|
+
"precipitation-rate": "mm/h",
|
|
8081
|
+
length: "m",
|
|
8082
|
+
area: "m²",
|
|
8083
|
+
illuminance: "lx",
|
|
8084
|
+
irradiance: "W/m²",
|
|
8085
|
+
power: "W",
|
|
8086
|
+
energy: "kWh",
|
|
8087
|
+
voltage: "V",
|
|
8088
|
+
current: "A",
|
|
8089
|
+
"apparent-power": "VA",
|
|
8090
|
+
humidity: "%",
|
|
8091
|
+
percentage: "%",
|
|
8092
|
+
"concentration-volume": "ppm",
|
|
8093
|
+
"concentration-mass": "µg/m³",
|
|
8094
|
+
"concentration-ppb": "ppb",
|
|
8095
|
+
volume: "L",
|
|
8096
|
+
duration: "s",
|
|
8097
|
+
"duration-ms": "ms",
|
|
8098
|
+
information: "B",
|
|
8099
|
+
"sound-level": "dBFS",
|
|
8100
|
+
"signal-level": "dBm",
|
|
8101
|
+
"colour-temperature": "mired",
|
|
8102
|
+
angle: "°",
|
|
8103
|
+
bitrate: "kbps",
|
|
8104
|
+
rate: "fps",
|
|
8105
|
+
mass: "kg",
|
|
8106
|
+
index: "none",
|
|
8107
|
+
ratio: "none",
|
|
8108
|
+
count: "none",
|
|
8109
|
+
none: "none",
|
|
8110
|
+
device: "device"
|
|
8111
|
+
};
|
|
8112
|
+
/** The stored unit, or `undefined` when the quantity has no unit symbol. */
|
|
8113
|
+
function baseUnitOf(quantity) {
|
|
8114
|
+
const symbol = QUANTITY_BASE[quantity];
|
|
8115
|
+
if (symbol === "none" || symbol === "device") return void 0;
|
|
8116
|
+
return symbol;
|
|
8117
|
+
}
|
|
8118
|
+
function readingMeta(quantity, extras) {
|
|
8119
|
+
return {
|
|
8120
|
+
quantity,
|
|
8121
|
+
...extras?.precision !== void 0 ? { precision: extras.precision } : {},
|
|
8122
|
+
...extras?.label !== void 0 ? { label: extras.label } : {}
|
|
8123
|
+
};
|
|
8124
|
+
}
|
|
8024
8125
|
/** Shared Zod schemas used across streaming capabilities. */
|
|
8025
8126
|
var CamProfileSchema = _enum([
|
|
8026
8127
|
"high",
|
|
@@ -8048,8 +8149,8 @@ var CamStreamKindSchema = _enum([
|
|
|
8048
8149
|
"derived"
|
|
8049
8150
|
]);
|
|
8050
8151
|
var CamStreamResolutionSchema = object({
|
|
8051
|
-
width: number().int().positive(),
|
|
8052
|
-
height: number().int().positive()
|
|
8152
|
+
width: number().int().positive().meta(readingMeta("none")),
|
|
8153
|
+
height: number().int().positive().meta(readingMeta("none"))
|
|
8053
8154
|
});
|
|
8054
8155
|
var CameraStreamSchema = object({
|
|
8055
8156
|
/** Stable, provider-assigned id unique within the (deviceId) scope. */
|
|
@@ -8601,6 +8702,8 @@ var CAP_NAMES = Object.freeze([
|
|
|
8601
8702
|
"filesystem-browse",
|
|
8602
8703
|
"flood",
|
|
8603
8704
|
"gas",
|
|
8705
|
+
"group-commands",
|
|
8706
|
+
"group-status",
|
|
8604
8707
|
"heating-valve",
|
|
8605
8708
|
"humidifier",
|
|
8606
8709
|
"humidity-sensor",
|
|
@@ -8730,14 +8833,6 @@ Object.freeze({
|
|
|
8730
8833
|
{
|
|
8731
8834
|
"path": "aqi",
|
|
8732
8835
|
"valueType": "number"
|
|
8733
|
-
},
|
|
8734
|
-
{
|
|
8735
|
-
"path": "unit",
|
|
8736
|
-
"valueType": "string"
|
|
8737
|
-
},
|
|
8738
|
-
{
|
|
8739
|
-
"path": "precision",
|
|
8740
|
-
"valueType": "number"
|
|
8741
8836
|
}
|
|
8742
8837
|
],
|
|
8743
8838
|
"alarm-panel": [
|
|
@@ -8773,20 +8868,10 @@ Object.freeze({
|
|
|
8773
8868
|
"valueType": "boolean"
|
|
8774
8869
|
}
|
|
8775
8870
|
],
|
|
8776
|
-
"ambient-light-sensor": [
|
|
8777
|
-
|
|
8778
|
-
|
|
8779
|
-
|
|
8780
|
-
},
|
|
8781
|
-
{
|
|
8782
|
-
"path": "unit",
|
|
8783
|
-
"valueType": "string"
|
|
8784
|
-
},
|
|
8785
|
-
{
|
|
8786
|
-
"path": "precision",
|
|
8787
|
-
"valueType": "number"
|
|
8788
|
-
}
|
|
8789
|
-
],
|
|
8871
|
+
"ambient-light-sensor": [{
|
|
8872
|
+
"path": "lux",
|
|
8873
|
+
"valueType": "number"
|
|
8874
|
+
}],
|
|
8790
8875
|
"audio-metrics": [
|
|
8791
8876
|
{
|
|
8792
8877
|
"path": "ts",
|
|
@@ -8866,6 +8951,10 @@ Object.freeze({
|
|
|
8866
8951
|
"path": "lastUpdated",
|
|
8867
8952
|
"valueType": "number"
|
|
8868
8953
|
},
|
|
8954
|
+
{
|
|
8955
|
+
"path": "volts",
|
|
8956
|
+
"valueType": "number"
|
|
8957
|
+
},
|
|
8869
8958
|
{
|
|
8870
8959
|
"path": "lastContactAt",
|
|
8871
8960
|
"valueType": "number"
|
|
@@ -9108,10 +9197,6 @@ Object.freeze({
|
|
|
9108
9197
|
"datetime"
|
|
9109
9198
|
]
|
|
9110
9199
|
},
|
|
9111
|
-
{
|
|
9112
|
-
"path": "unit",
|
|
9113
|
-
"valueType": "string"
|
|
9114
|
-
},
|
|
9115
9200
|
{
|
|
9116
9201
|
"path": "min",
|
|
9117
9202
|
"valueType": "number"
|
|
@@ -9123,19 +9208,6 @@ Object.freeze({
|
|
|
9123
9208
|
{
|
|
9124
9209
|
"path": "step",
|
|
9125
9210
|
"valueType": "number"
|
|
9126
|
-
},
|
|
9127
|
-
{
|
|
9128
|
-
"path": "precision",
|
|
9129
|
-
"valueType": "number"
|
|
9130
|
-
},
|
|
9131
|
-
{
|
|
9132
|
-
"path": "format",
|
|
9133
|
-
"valueType": "enum",
|
|
9134
|
-
"enumValues": [
|
|
9135
|
-
"date",
|
|
9136
|
-
"time",
|
|
9137
|
-
"datetime"
|
|
9138
|
-
]
|
|
9139
9211
|
}
|
|
9140
9212
|
],
|
|
9141
9213
|
"cover": [
|
|
@@ -9376,13 +9448,8 @@ Object.freeze({
|
|
|
9376
9448
|
"path": "value",
|
|
9377
9449
|
"valueType": "string"
|
|
9378
9450
|
}, {
|
|
9379
|
-
"path": "
|
|
9380
|
-
"valueType": "
|
|
9381
|
-
"enumValues": [
|
|
9382
|
-
"date",
|
|
9383
|
-
"time",
|
|
9384
|
-
"datetime"
|
|
9385
|
-
]
|
|
9451
|
+
"path": "timestamp",
|
|
9452
|
+
"valueType": "boolean"
|
|
9386
9453
|
}],
|
|
9387
9454
|
"event-emitter": [
|
|
9388
9455
|
{
|
|
@@ -9455,6 +9522,20 @@ Object.freeze({
|
|
|
9455
9522
|
"path": "detected",
|
|
9456
9523
|
"valueType": "boolean"
|
|
9457
9524
|
}],
|
|
9525
|
+
"group-status": [
|
|
9526
|
+
{
|
|
9527
|
+
"path": "included",
|
|
9528
|
+
"valueType": "number"
|
|
9529
|
+
},
|
|
9530
|
+
{
|
|
9531
|
+
"path": "excluded",
|
|
9532
|
+
"valueType": "number"
|
|
9533
|
+
},
|
|
9534
|
+
{
|
|
9535
|
+
"path": "total",
|
|
9536
|
+
"valueType": "number"
|
|
9537
|
+
}
|
|
9538
|
+
],
|
|
9458
9539
|
"heating-valve": [{
|
|
9459
9540
|
"path": "position",
|
|
9460
9541
|
"valueType": "number"
|
|
@@ -9489,20 +9570,10 @@ Object.freeze({
|
|
|
9489
9570
|
"valueType": "number"
|
|
9490
9571
|
}
|
|
9491
9572
|
],
|
|
9492
|
-
"humidity-sensor": [
|
|
9493
|
-
|
|
9494
|
-
|
|
9495
|
-
|
|
9496
|
-
},
|
|
9497
|
-
{
|
|
9498
|
-
"path": "unit",
|
|
9499
|
-
"valueType": "string"
|
|
9500
|
-
},
|
|
9501
|
-
{
|
|
9502
|
-
"path": "precision",
|
|
9503
|
-
"valueType": "number"
|
|
9504
|
-
}
|
|
9505
|
-
],
|
|
9573
|
+
"humidity-sensor": [{
|
|
9574
|
+
"path": "percent",
|
|
9575
|
+
"valueType": "number"
|
|
9576
|
+
}],
|
|
9506
9577
|
"image": [{
|
|
9507
9578
|
"path": "url",
|
|
9508
9579
|
"valueType": "string"
|
|
@@ -9841,20 +9912,10 @@ Object.freeze({
|
|
|
9841
9912
|
"valueType": "boolean"
|
|
9842
9913
|
}
|
|
9843
9914
|
],
|
|
9844
|
-
"numeric-sensor": [
|
|
9845
|
-
|
|
9846
|
-
|
|
9847
|
-
|
|
9848
|
-
},
|
|
9849
|
-
{
|
|
9850
|
-
"path": "unit",
|
|
9851
|
-
"valueType": "string"
|
|
9852
|
-
},
|
|
9853
|
-
{
|
|
9854
|
-
"path": "precision",
|
|
9855
|
-
"valueType": "number"
|
|
9856
|
-
}
|
|
9857
|
-
],
|
|
9915
|
+
"numeric-sensor": [{
|
|
9916
|
+
"path": "value",
|
|
9917
|
+
"valueType": "number"
|
|
9918
|
+
}],
|
|
9858
9919
|
"pet-feeder": [
|
|
9859
9920
|
{
|
|
9860
9921
|
"path": "foodLevel",
|
|
@@ -9946,14 +10007,6 @@ Object.freeze({
|
|
|
9946
10007
|
{
|
|
9947
10008
|
"path": "powerFactor",
|
|
9948
10009
|
"valueType": "number"
|
|
9949
|
-
},
|
|
9950
|
-
{
|
|
9951
|
-
"path": "unit",
|
|
9952
|
-
"valueType": "string"
|
|
9953
|
-
},
|
|
9954
|
-
{
|
|
9955
|
-
"path": "precision",
|
|
9956
|
-
"valueType": "number"
|
|
9957
10010
|
}
|
|
9958
10011
|
],
|
|
9959
10012
|
"presence": [
|
|
@@ -9982,20 +10035,10 @@ Object.freeze({
|
|
|
9982
10035
|
"valueType": "number"
|
|
9983
10036
|
}
|
|
9984
10037
|
],
|
|
9985
|
-
"pressure-sensor": [
|
|
9986
|
-
|
|
9987
|
-
|
|
9988
|
-
|
|
9989
|
-
},
|
|
9990
|
-
{
|
|
9991
|
-
"path": "unit",
|
|
9992
|
-
"valueType": "string"
|
|
9993
|
-
},
|
|
9994
|
-
{
|
|
9995
|
-
"path": "precision",
|
|
9996
|
-
"valueType": "number"
|
|
9997
|
-
}
|
|
9998
|
-
],
|
|
10038
|
+
"pressure-sensor": [{
|
|
10039
|
+
"path": "hpa",
|
|
10040
|
+
"valueType": "number"
|
|
10041
|
+
}],
|
|
9999
10042
|
"privacy-mask": [{
|
|
10000
10043
|
"path": "enabled",
|
|
10001
10044
|
"valueType": "boolean"
|
|
@@ -10306,20 +10349,10 @@ Object.freeze({
|
|
|
10306
10349
|
"path": "tampered",
|
|
10307
10350
|
"valueType": "boolean"
|
|
10308
10351
|
}],
|
|
10309
|
-
"temperature-sensor": [
|
|
10310
|
-
|
|
10311
|
-
|
|
10312
|
-
|
|
10313
|
-
},
|
|
10314
|
-
{
|
|
10315
|
-
"path": "unit",
|
|
10316
|
-
"valueType": "string"
|
|
10317
|
-
},
|
|
10318
|
-
{
|
|
10319
|
-
"path": "precision",
|
|
10320
|
-
"valueType": "number"
|
|
10321
|
-
}
|
|
10322
|
-
],
|
|
10352
|
+
"temperature-sensor": [{
|
|
10353
|
+
"path": "celsius",
|
|
10354
|
+
"valueType": "number"
|
|
10355
|
+
}],
|
|
10323
10356
|
"update": [
|
|
10324
10357
|
{
|
|
10325
10358
|
"path": "currentVersion",
|
|
@@ -10430,10 +10463,6 @@ Object.freeze({
|
|
|
10430
10463
|
"path": "temperature",
|
|
10431
10464
|
"valueType": "number"
|
|
10432
10465
|
},
|
|
10433
|
-
{
|
|
10434
|
-
"path": "temperatureUnit",
|
|
10435
|
-
"valueType": "string"
|
|
10436
|
-
},
|
|
10437
10466
|
{
|
|
10438
10467
|
"path": "humidity",
|
|
10439
10468
|
"valueType": "number"
|
|
@@ -10442,18 +10471,10 @@ Object.freeze({
|
|
|
10442
10471
|
"path": "pressure",
|
|
10443
10472
|
"valueType": "number"
|
|
10444
10473
|
},
|
|
10445
|
-
{
|
|
10446
|
-
"path": "pressureUnit",
|
|
10447
|
-
"valueType": "string"
|
|
10448
|
-
},
|
|
10449
10474
|
{
|
|
10450
10475
|
"path": "windSpeed",
|
|
10451
10476
|
"valueType": "number"
|
|
10452
10477
|
},
|
|
10453
|
-
{
|
|
10454
|
-
"path": "windSpeedUnit",
|
|
10455
|
-
"valueType": "string"
|
|
10456
|
-
},
|
|
10457
10478
|
{
|
|
10458
10479
|
"path": "windBearing",
|
|
10459
10480
|
"valueType": "number"
|
|
@@ -10884,7 +10905,7 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
|
|
|
10884
10905
|
return DeviceRole;
|
|
10885
10906
|
}({});
|
|
10886
10907
|
//#endregion
|
|
10887
|
-
//#region ../types/dist/composition-
|
|
10908
|
+
//#region ../types/dist/composition-OhpuespA.mjs
|
|
10888
10909
|
/**
|
|
10889
10910
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
10890
10911
|
*
|
|
@@ -11639,15 +11660,74 @@ function validateExpressionSource(src) {
|
|
|
11639
11660
|
}
|
|
11640
11661
|
return null;
|
|
11641
11662
|
}
|
|
11642
|
-
/**
|
|
11643
|
-
|
|
11644
|
-
|
|
11645
|
-
|
|
11663
|
+
/**
|
|
11664
|
+
* A composition source identity: `(addonId, stableId)`, never a numeric device
|
|
11665
|
+
* id. Split out so helper schemas can name it without a cycle through
|
|
11666
|
+
* `composition.ts` (D659).
|
|
11667
|
+
*/
|
|
11646
11668
|
var CompositionSourceRefSchema = object({
|
|
11647
11669
|
/** The owning addon; `stableId` is unique only within it. */
|
|
11648
11670
|
addonId: string().min(1),
|
|
11649
11671
|
stableId: string().min(1)
|
|
11650
11672
|
});
|
|
11673
|
+
var GROUP_TEMPLATE_IDS = [
|
|
11674
|
+
"temperature",
|
|
11675
|
+
"humidity",
|
|
11676
|
+
"pressure",
|
|
11677
|
+
"illuminance",
|
|
11678
|
+
"power",
|
|
11679
|
+
"energy",
|
|
11680
|
+
"battery",
|
|
11681
|
+
"numeric",
|
|
11682
|
+
"motion",
|
|
11683
|
+
"contact",
|
|
11684
|
+
"leak",
|
|
11685
|
+
"smoke",
|
|
11686
|
+
"occupancy",
|
|
11687
|
+
"binary",
|
|
11688
|
+
"switch",
|
|
11689
|
+
"light"
|
|
11690
|
+
];
|
|
11691
|
+
var NUMERIC_AGGREGATES = [
|
|
11692
|
+
"mean",
|
|
11693
|
+
"median",
|
|
11694
|
+
"min",
|
|
11695
|
+
"max",
|
|
11696
|
+
"sum"
|
|
11697
|
+
];
|
|
11698
|
+
var BINARY_AGGREGATES = ["any", "all"];
|
|
11699
|
+
/** How an actuator group decides it is on. Unknown members never count as off. */
|
|
11700
|
+
var ACTIVE_CRITERIA = ["at-least-one", "all"];
|
|
11701
|
+
var AGGREGATE_REDUCERS = [
|
|
11702
|
+
"mean",
|
|
11703
|
+
"median",
|
|
11704
|
+
"min",
|
|
11705
|
+
"max",
|
|
11706
|
+
"sum",
|
|
11707
|
+
"any",
|
|
11708
|
+
"all"
|
|
11709
|
+
];
|
|
11710
|
+
var GroupTemplateIdSchema = _enum(GROUP_TEMPLATE_IDS);
|
|
11711
|
+
var AggregateReducerSchema = _enum(AGGREGATE_REDUCERS);
|
|
11712
|
+
var ActiveCriterionSchema = _enum(ACTIVE_CRITERIA);
|
|
11713
|
+
/** One member. The field is stored so occupancy can name motion or binary. */
|
|
11714
|
+
var HelperMemberSchema = object({
|
|
11715
|
+
source: CompositionSourceRefSchema,
|
|
11716
|
+
cap: string().min(1),
|
|
11717
|
+
fieldPath: string().min(1)
|
|
11718
|
+
});
|
|
11719
|
+
var HelperSpecSchema = discriminatedUnion("kind", [object({
|
|
11720
|
+
kind: literal("group"),
|
|
11721
|
+
templateId: GroupTemplateIdSchema,
|
|
11722
|
+
aggregate: AggregateReducerSchema,
|
|
11723
|
+
members: array(HelperMemberSchema).min(1).max(64),
|
|
11724
|
+
/** Actuator groups only. Readings leave this unset. */
|
|
11725
|
+
active: ActiveCriterionSchema.optional()
|
|
11726
|
+
})]);
|
|
11727
|
+
/** A composed device's stableId is this prefix plus the block id. */
|
|
11728
|
+
var COMPOSED_DEVICE_STABLE_ID_PREFIX = "composed-";
|
|
11729
|
+
/** Longest snippet a `code` source may carry (slice 4). */
|
|
11730
|
+
var MAX_COMPOSITION_CODE_LENGTH = 2e4;
|
|
11651
11731
|
/** One field of one capability of one source device. */
|
|
11652
11732
|
var CompositionFieldReadSchema = object({
|
|
11653
11733
|
source: CompositionSourceRefSchema,
|
|
@@ -11691,7 +11771,33 @@ var CompositionCodeSourceSchema = object({
|
|
|
11691
11771
|
var CompositionFieldSourceSchema = discriminatedUnion("kind", [
|
|
11692
11772
|
CompositionFromSourceSchema,
|
|
11693
11773
|
CompositionExpressionSourceSchema,
|
|
11694
|
-
CompositionCodeSourceSchema
|
|
11774
|
+
CompositionCodeSourceSchema,
|
|
11775
|
+
object({
|
|
11776
|
+
kind: literal("aggregate"),
|
|
11777
|
+
reducer: _enum([
|
|
11778
|
+
"mean",
|
|
11779
|
+
"median",
|
|
11780
|
+
"min",
|
|
11781
|
+
"max",
|
|
11782
|
+
"sum",
|
|
11783
|
+
"any",
|
|
11784
|
+
"all"
|
|
11785
|
+
]),
|
|
11786
|
+
reads: array(CompositionFieldReadSchema).min(1).max(64),
|
|
11787
|
+
/** `value` is the reading; the others are the member counts. */
|
|
11788
|
+
publish: _enum([
|
|
11789
|
+
"value",
|
|
11790
|
+
"included",
|
|
11791
|
+
"excluded",
|
|
11792
|
+
"total"
|
|
11793
|
+
]),
|
|
11794
|
+
/** What a `value` publish does when nobody is included. Counts ignore this. */
|
|
11795
|
+
empty: _enum([
|
|
11796
|
+
"null",
|
|
11797
|
+
"omit",
|
|
11798
|
+
"offline"
|
|
11799
|
+
])
|
|
11800
|
+
})
|
|
11695
11801
|
]);
|
|
11696
11802
|
var CompositionCommandTargetSchema = discriminatedUnion("kind", [object({
|
|
11697
11803
|
kind: literal("forward"),
|
|
@@ -11737,7 +11843,13 @@ var CompositionSchema = object({
|
|
|
11737
11843
|
kind: literal("existing"),
|
|
11738
11844
|
device: CompositionSourceRefSchema
|
|
11739
11845
|
})]),
|
|
11740
|
-
features: array(CompositionFeatureSchema).min(1).max(16)
|
|
11846
|
+
features: array(CompositionFeatureSchema).min(1).max(16),
|
|
11847
|
+
/**
|
|
11848
|
+
* Present when the block is a helper template. Absent on a free
|
|
11849
|
+
* composition (the room example, device 4603). The editor reads this,
|
|
11850
|
+
* never the compiled features.
|
|
11851
|
+
*/
|
|
11852
|
+
helper: HelperSpecSchema.optional()
|
|
11741
11853
|
}).superRefine((composition, ctx) => {
|
|
11742
11854
|
const seen = /* @__PURE__ */ new Set();
|
|
11743
11855
|
composition.features.forEach((feature, index) => {
|
|
@@ -18515,7 +18627,11 @@ var CompositionProblemSchema = object({
|
|
|
18515
18627
|
"item-field-reserved",
|
|
18516
18628
|
"target-missing",
|
|
18517
18629
|
"target-unreadable",
|
|
18518
|
-
"not-replaceable"
|
|
18630
|
+
"not-replaceable",
|
|
18631
|
+
"native-capability-replace",
|
|
18632
|
+
"mixed-quantity",
|
|
18633
|
+
"helper-mismatch",
|
|
18634
|
+
"member-constraint"
|
|
18519
18635
|
]),
|
|
18520
18636
|
path: string(),
|
|
18521
18637
|
message: string()
|
|
@@ -18536,7 +18652,8 @@ var CompositionUnavailableModeSchema = _enum([
|
|
|
18536
18652
|
"null",
|
|
18537
18653
|
"offline",
|
|
18538
18654
|
"unknown",
|
|
18539
|
-
"release"
|
|
18655
|
+
"release",
|
|
18656
|
+
"omit"
|
|
18540
18657
|
]);
|
|
18541
18658
|
/**
|
|
18542
18659
|
* `derived` reads a source · `clock` reads only `now`, recomputed when a sibling
|
|
@@ -18573,9 +18690,11 @@ var CompositionFieldPlanSchema = object({
|
|
|
18573
18690
|
reads: array(CompositionFieldReadSchema)
|
|
18574
18691
|
});
|
|
18575
18692
|
/**
|
|
18576
|
-
* What a feature does to its target (D663): `new` builds a capability on a
|
|
18577
|
-
* device; on an existing device it `add`s a capability the device lacks
|
|
18578
|
-
*
|
|
18693
|
+
* What a feature does to its target (D663, D944): `new` builds a capability on a
|
|
18694
|
+
* new device; on an existing device it `add`s a capability the device lacks.
|
|
18695
|
+
* Replacing a capability the device already serves is refused
|
|
18696
|
+
* (`native-capability-replace`), not planned. `replace` remains on the claim
|
|
18697
|
+
* wire for a claim the hub already holds.
|
|
18579
18698
|
*/
|
|
18580
18699
|
var CompositionFeatureModeSchema = _enum([
|
|
18581
18700
|
"new",
|
|
@@ -18748,6 +18867,275 @@ Object.freeze({
|
|
|
18748
18867
|
result: ["number", "null"]
|
|
18749
18868
|
}
|
|
18750
18869
|
});
|
|
18870
|
+
/**
|
|
18871
|
+
* One catalog row per base reading a group helper can build (D944 §3).
|
|
18872
|
+
* Data, not a form default written into the block.
|
|
18873
|
+
*/
|
|
18874
|
+
var NOW = {
|
|
18875
|
+
fieldPath: "lastFetchedAt",
|
|
18876
|
+
expr: "now"
|
|
18877
|
+
};
|
|
18878
|
+
var CHANGED = {
|
|
18879
|
+
fieldPath: "lastChangedAt",
|
|
18880
|
+
expr: "now"
|
|
18881
|
+
};
|
|
18882
|
+
function numeric(input) {
|
|
18883
|
+
return {
|
|
18884
|
+
...input,
|
|
18885
|
+
family: "numeric",
|
|
18886
|
+
deviceType: DeviceType.Sensor,
|
|
18887
|
+
memberDeviceType: DeviceType.Sensor,
|
|
18888
|
+
commandCaps: [],
|
|
18889
|
+
baseUnit: baseUnitOf(input.quantity),
|
|
18890
|
+
aggregates: NUMERIC_AGGREGATES,
|
|
18891
|
+
accept: [{
|
|
18892
|
+
cap: input.outputCap,
|
|
18893
|
+
fieldPath: input.outputField
|
|
18894
|
+
}]
|
|
18895
|
+
};
|
|
18896
|
+
}
|
|
18897
|
+
function binary(input) {
|
|
18898
|
+
return {
|
|
18899
|
+
...input,
|
|
18900
|
+
family: "binary",
|
|
18901
|
+
deviceType: DeviceType.Sensor,
|
|
18902
|
+
memberDeviceType: DeviceType.Sensor,
|
|
18903
|
+
commandCaps: [],
|
|
18904
|
+
quantity: "none",
|
|
18905
|
+
baseUnit: void 0,
|
|
18906
|
+
aggregates: BINARY_AGGREGATES,
|
|
18907
|
+
empty: "offline"
|
|
18908
|
+
};
|
|
18909
|
+
}
|
|
18910
|
+
var GROUP_TEMPLATES = [
|
|
18911
|
+
numeric({
|
|
18912
|
+
id: "temperature",
|
|
18913
|
+
summary: "Mean, median, min, max or sum of temperatures. Offline and unknown members are left out, never read as 0 °C.",
|
|
18914
|
+
role: DeviceRole.TemperatureSensor,
|
|
18915
|
+
outputCap: "temperature-sensor",
|
|
18916
|
+
outputField: "celsius",
|
|
18917
|
+
quantity: "temperature",
|
|
18918
|
+
defaultAggregate: "mean",
|
|
18919
|
+
empty: "null",
|
|
18920
|
+
companions: [NOW]
|
|
18921
|
+
}),
|
|
18922
|
+
numeric({
|
|
18923
|
+
id: "humidity",
|
|
18924
|
+
summary: "Humidity in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
18925
|
+
role: DeviceRole.HumiditySensor,
|
|
18926
|
+
outputCap: "humidity-sensor",
|
|
18927
|
+
outputField: "percent",
|
|
18928
|
+
quantity: "humidity",
|
|
18929
|
+
defaultAggregate: "mean",
|
|
18930
|
+
empty: "null",
|
|
18931
|
+
companions: [NOW]
|
|
18932
|
+
}),
|
|
18933
|
+
numeric({
|
|
18934
|
+
id: "pressure",
|
|
18935
|
+
summary: "Pressure in hectopascals. Offline and unknown members are left out, never read as 0 hPa.",
|
|
18936
|
+
role: DeviceRole.PressureSensor,
|
|
18937
|
+
outputCap: "pressure-sensor",
|
|
18938
|
+
outputField: "hpa",
|
|
18939
|
+
quantity: "pressure",
|
|
18940
|
+
defaultAggregate: "mean",
|
|
18941
|
+
empty: "null",
|
|
18942
|
+
companions: [NOW]
|
|
18943
|
+
}),
|
|
18944
|
+
numeric({
|
|
18945
|
+
id: "illuminance",
|
|
18946
|
+
summary: "Illuminance in lux. Offline and unknown members are left out, never read as 0 lx.",
|
|
18947
|
+
role: DeviceRole.AmbientLightSensor,
|
|
18948
|
+
outputCap: "ambient-light-sensor",
|
|
18949
|
+
outputField: "lux",
|
|
18950
|
+
quantity: "illuminance",
|
|
18951
|
+
defaultAggregate: "mean",
|
|
18952
|
+
empty: "null",
|
|
18953
|
+
companions: [NOW]
|
|
18954
|
+
}),
|
|
18955
|
+
numeric({
|
|
18956
|
+
id: "power",
|
|
18957
|
+
summary: "Power in watts, summed by default. Nobody reporting omits the key rather than writing 0 W.",
|
|
18958
|
+
role: DeviceRole.PowerSensor,
|
|
18959
|
+
outputCap: "power-meter",
|
|
18960
|
+
outputField: "watts",
|
|
18961
|
+
quantity: "power",
|
|
18962
|
+
defaultAggregate: "sum",
|
|
18963
|
+
empty: "omit",
|
|
18964
|
+
companions: [NOW]
|
|
18965
|
+
}),
|
|
18966
|
+
numeric({
|
|
18967
|
+
id: "energy",
|
|
18968
|
+
summary: "Energy in kilowatt-hours, summed by default. Nobody reporting omits the key rather than writing 0 kWh.",
|
|
18969
|
+
role: DeviceRole.EnergySensor,
|
|
18970
|
+
outputCap: "power-meter",
|
|
18971
|
+
outputField: "kwhTotal",
|
|
18972
|
+
quantity: "energy",
|
|
18973
|
+
defaultAggregate: "sum",
|
|
18974
|
+
empty: "omit",
|
|
18975
|
+
companions: [NOW]
|
|
18976
|
+
}),
|
|
18977
|
+
numeric({
|
|
18978
|
+
id: "battery",
|
|
18979
|
+
summary: "Battery charge in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
18980
|
+
role: DeviceRole.BatterySensor,
|
|
18981
|
+
outputCap: "battery",
|
|
18982
|
+
outputField: "percentage",
|
|
18983
|
+
quantity: "percentage",
|
|
18984
|
+
defaultAggregate: "mean",
|
|
18985
|
+
empty: "null",
|
|
18986
|
+
companions: [
|
|
18987
|
+
{
|
|
18988
|
+
fieldPath: "charging",
|
|
18989
|
+
expr: "\"unknown\""
|
|
18990
|
+
},
|
|
18991
|
+
{
|
|
18992
|
+
fieldPath: "sleeping",
|
|
18993
|
+
expr: "false"
|
|
18994
|
+
},
|
|
18995
|
+
{
|
|
18996
|
+
fieldPath: "lastUpdated",
|
|
18997
|
+
expr: "now"
|
|
18998
|
+
}
|
|
18999
|
+
]
|
|
19000
|
+
}),
|
|
19001
|
+
numeric({
|
|
19002
|
+
id: "numeric",
|
|
19003
|
+
summary: "A numeric reading in the members’ shared quantity. Mixed quantities are refused. Nobody reporting publishes null, not 0.",
|
|
19004
|
+
role: DeviceRole.NumericSensor,
|
|
19005
|
+
outputCap: "numeric-sensor",
|
|
19006
|
+
outputField: "value",
|
|
19007
|
+
quantity: "device",
|
|
19008
|
+
defaultAggregate: "mean",
|
|
19009
|
+
empty: "null",
|
|
19010
|
+
companions: [NOW]
|
|
19011
|
+
}),
|
|
19012
|
+
binary({
|
|
19013
|
+
id: "motion",
|
|
19014
|
+
summary: "Any or all motion. Offline and unknown members are left out, never read as off. Nobody reporting takes the device offline.",
|
|
19015
|
+
role: DeviceRole.MotionSensor,
|
|
19016
|
+
outputCap: "motion",
|
|
19017
|
+
outputField: "detected",
|
|
19018
|
+
defaultAggregate: "any",
|
|
19019
|
+
accept: [{
|
|
19020
|
+
cap: "motion",
|
|
19021
|
+
fieldPath: "detected"
|
|
19022
|
+
}],
|
|
19023
|
+
companions: [{
|
|
19024
|
+
fieldPath: "lastDetectedAt",
|
|
19025
|
+
expr: "null"
|
|
19026
|
+
}, {
|
|
19027
|
+
fieldPath: "autoClearAfterMs",
|
|
19028
|
+
expr: "null"
|
|
19029
|
+
}]
|
|
19030
|
+
}),
|
|
19031
|
+
binary({
|
|
19032
|
+
id: "contact",
|
|
19033
|
+
summary: "Any or all open contacts. Offline and unknown members are left out, never read as closed.",
|
|
19034
|
+
role: DeviceRole.ContactSensor,
|
|
19035
|
+
outputCap: "contact",
|
|
19036
|
+
outputField: "entryOpen",
|
|
19037
|
+
defaultAggregate: "any",
|
|
19038
|
+
accept: [{
|
|
19039
|
+
cap: "contact",
|
|
19040
|
+
fieldPath: "entryOpen"
|
|
19041
|
+
}],
|
|
19042
|
+
companions: [CHANGED]
|
|
19043
|
+
}),
|
|
19044
|
+
binary({
|
|
19045
|
+
id: "leak",
|
|
19046
|
+
summary: "Any or all leak detections. Offline and unknown members are left out, never read as dry.",
|
|
19047
|
+
role: DeviceRole.LeakSensor,
|
|
19048
|
+
outputCap: "flood",
|
|
19049
|
+
outputField: "flooded",
|
|
19050
|
+
defaultAggregate: "any",
|
|
19051
|
+
accept: [{
|
|
19052
|
+
cap: "flood",
|
|
19053
|
+
fieldPath: "flooded"
|
|
19054
|
+
}],
|
|
19055
|
+
companions: [CHANGED]
|
|
19056
|
+
}),
|
|
19057
|
+
binary({
|
|
19058
|
+
id: "smoke",
|
|
19059
|
+
summary: "Any or all smoke detections. Offline and unknown members are left out, never read as clear.",
|
|
19060
|
+
role: DeviceRole.SmokeSensor,
|
|
19061
|
+
outputCap: "smoke",
|
|
19062
|
+
outputField: "detected",
|
|
19063
|
+
defaultAggregate: "any",
|
|
19064
|
+
accept: [{
|
|
19065
|
+
cap: "smoke",
|
|
19066
|
+
fieldPath: "detected"
|
|
19067
|
+
}],
|
|
19068
|
+
companions: [CHANGED]
|
|
19069
|
+
}),
|
|
19070
|
+
binary({
|
|
19071
|
+
id: "occupancy",
|
|
19072
|
+
summary: "Any or all of motion or binary sensors, published as a binary. Presence zones are not aggregated. Nobody reporting is offline, not off.",
|
|
19073
|
+
role: DeviceRole.BinarySensor,
|
|
19074
|
+
outputCap: "binary",
|
|
19075
|
+
outputField: "on",
|
|
19076
|
+
defaultAggregate: "any",
|
|
19077
|
+
accept: [{
|
|
19078
|
+
cap: "motion",
|
|
19079
|
+
fieldPath: "detected"
|
|
19080
|
+
}, {
|
|
19081
|
+
cap: "binary",
|
|
19082
|
+
fieldPath: "on"
|
|
19083
|
+
}],
|
|
19084
|
+
companions: [CHANGED]
|
|
19085
|
+
}),
|
|
19086
|
+
binary({
|
|
19087
|
+
id: "binary",
|
|
19088
|
+
summary: "Any or all generic binary sensors. Offline and unknown members are left out, never read as off.",
|
|
19089
|
+
role: DeviceRole.BinarySensor,
|
|
19090
|
+
outputCap: "binary",
|
|
19091
|
+
outputField: "on",
|
|
19092
|
+
defaultAggregate: "any",
|
|
19093
|
+
accept: [{
|
|
19094
|
+
cap: "binary",
|
|
19095
|
+
fieldPath: "on"
|
|
19096
|
+
}],
|
|
19097
|
+
companions: [CHANGED]
|
|
19098
|
+
}),
|
|
19099
|
+
actuator({
|
|
19100
|
+
id: "switch",
|
|
19101
|
+
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.",
|
|
19102
|
+
deviceType: DeviceType.Switch,
|
|
19103
|
+
outputCap: "switch",
|
|
19104
|
+
commandCaps: ["switch"]
|
|
19105
|
+
}),
|
|
19106
|
+
actuator({
|
|
19107
|
+
id: "light",
|
|
19108
|
+
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.",
|
|
19109
|
+
deviceType: DeviceType.Light,
|
|
19110
|
+
outputCap: "switch",
|
|
19111
|
+
commandCaps: [
|
|
19112
|
+
"switch",
|
|
19113
|
+
"brightness",
|
|
19114
|
+
"color"
|
|
19115
|
+
]
|
|
19116
|
+
})
|
|
19117
|
+
];
|
|
19118
|
+
function actuator(input) {
|
|
19119
|
+
return {
|
|
19120
|
+
...input,
|
|
19121
|
+
family: "actuator",
|
|
19122
|
+
role: void 0,
|
|
19123
|
+
memberDeviceType: input.deviceType,
|
|
19124
|
+
outputField: "on",
|
|
19125
|
+
quantity: "none",
|
|
19126
|
+
baseUnit: void 0,
|
|
19127
|
+
aggregates: BINARY_AGGREGATES,
|
|
19128
|
+
defaultAggregate: "any",
|
|
19129
|
+
empty: "offline",
|
|
19130
|
+
accept: [{
|
|
19131
|
+
cap: "switch",
|
|
19132
|
+
fieldPath: "on"
|
|
19133
|
+
}],
|
|
19134
|
+
companions: [CHANGED]
|
|
19135
|
+
};
|
|
19136
|
+
}
|
|
19137
|
+
new Map(GROUP_TEMPLATES.map((template) => [template.id, template]));
|
|
19138
|
+
DeviceFeature.LightColorRgb, DeviceFeature.LightColorHsv, DeviceFeature.LightColorMired;
|
|
18751
19139
|
`${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
|
|
18752
19140
|
/**
|
|
18753
19141
|
* What a composition may BUILD on a device type (G2, D676): the caps a new
|
|
@@ -20574,12 +20962,12 @@ function buildDeviceAdminUrl(parts) {
|
|
|
20574
20962
|
* providers detect renames by matching `uniqueId` and patch `id`
|
|
20575
20963
|
* in-place so dispatch keeps working.
|
|
20576
20964
|
*
|
|
20577
|
-
* **
|
|
20578
|
-
*
|
|
20579
|
-
*
|
|
20580
|
-
*
|
|
20581
|
-
* (`ha-domain-mapping`)
|
|
20582
|
-
* stored after that point.
|
|
20965
|
+
* **Display unit and precision are NOT stored here.** They are a read-time
|
|
20966
|
+
* preference (D944). A polymorphic reading stores its `quantity` here once,
|
|
20967
|
+
* at adopt, and a date/time value stores `dateTimeShape` the same way —
|
|
20968
|
+
* neither is repeated on each sample. The `device_class` tag is an
|
|
20969
|
+
* HA-specific input consumed at the discovery boundary (`ha-domain-mapping`)
|
|
20970
|
+
* to derive the CamStack `DeviceRole`; it is never stored after that point.
|
|
20583
20971
|
*
|
|
20584
20972
|
* The `raw` escape hatch carries provider-specific attributes that don't
|
|
20585
20973
|
* fit the structured slots (HA `attributes` whitelist, Reolink `deviceCache`
|
|
@@ -20593,6 +20981,14 @@ var SourceInfoSchema = object({
|
|
|
20593
20981
|
/** Immutable upstream identifier when available (HA `unique_id`, … ).
|
|
20594
20982
|
* Used to detect rename when `id` changes. */
|
|
20595
20983
|
uniqueId: string().optional(),
|
|
20984
|
+
/** Quantity of a polymorphic reading, written once at adopt (D944). */
|
|
20985
|
+
quantity: ReadingQuantitySchema.optional(),
|
|
20986
|
+
/** Date / time / datetime shape of a string reading, written once at adopt. */
|
|
20987
|
+
dateTimeShape: _enum([
|
|
20988
|
+
"date",
|
|
20989
|
+
"time",
|
|
20990
|
+
"datetime"
|
|
20991
|
+
]).optional(),
|
|
20596
20992
|
/** Provider-specific extras that don't fit the structured slots.
|
|
20597
20993
|
* Whitelist what goes here per provider — do NOT dump entire HA
|
|
20598
20994
|
* attribute blobs (would explode the meta JSON column). */
|
|
@@ -41697,7 +42093,8 @@ method(object({
|
|
|
41697
42093
|
"enum"
|
|
41698
42094
|
]),
|
|
41699
42095
|
enumValues: array(string()).optional(),
|
|
41700
|
-
item: boolean().optional()
|
|
42096
|
+
item: boolean().optional(),
|
|
42097
|
+
quantity: ReadingQuantitySchema.optional()
|
|
41701
42098
|
})).readonly(),
|
|
41702
42099
|
itemArray: object({
|
|
41703
42100
|
path: string(),
|
|
@@ -45581,8 +45978,8 @@ var MaskPolygonShapeSchema = object({
|
|
|
45581
45978
|
/** Boolean cell grid — row-major, length === gridWidth*gridHeight. */
|
|
45582
45979
|
var MaskGridShapeSchema = object({
|
|
45583
45980
|
kind: literal("grid"),
|
|
45584
|
-
gridWidth: number(),
|
|
45585
|
-
gridHeight: number(),
|
|
45981
|
+
gridWidth: number().meta(readingMeta("none")),
|
|
45982
|
+
gridHeight: number().meta(readingMeta("none")),
|
|
45586
45983
|
cells: array(boolean())
|
|
45587
45984
|
});
|
|
45588
45985
|
discriminatedUnion("kind", [
|
|
@@ -45694,6 +46091,8 @@ var NcSystemEventKindSchema = _enum([
|
|
|
45694
46091
|
"detection-blind",
|
|
45695
46092
|
"motion-noisy",
|
|
45696
46093
|
"motion-calm",
|
|
46094
|
+
"package-llm-silent",
|
|
46095
|
+
"package-llm-answered",
|
|
45697
46096
|
"recording-stalled",
|
|
45698
46097
|
"recording-healthy",
|
|
45699
46098
|
"recording-degraded",
|
|
@@ -57307,6 +57706,28 @@ var PackageVersionInfoSchema = object({
|
|
|
57307
57706
|
deprecated: string().optional(),
|
|
57308
57707
|
distTags: array(string()).readonly()
|
|
57309
57708
|
});
|
|
57709
|
+
/**
|
|
57710
|
+
* One published document. `ok` is markdown from the registry. `missing` means
|
|
57711
|
+
* the registry answered and the file was not there. `error` is a registry or
|
|
57712
|
+
* tarball failure — never an empty string standing in for either.
|
|
57713
|
+
*/
|
|
57714
|
+
var PackageDocBodySchema = discriminatedUnion("status", [
|
|
57715
|
+
object({
|
|
57716
|
+
status: literal("ok"),
|
|
57717
|
+
markdown: string()
|
|
57718
|
+
}),
|
|
57719
|
+
object({ status: literal("missing") }),
|
|
57720
|
+
object({
|
|
57721
|
+
status: literal("error"),
|
|
57722
|
+
message: string()
|
|
57723
|
+
})
|
|
57724
|
+
]);
|
|
57725
|
+
var PackageDocsSchema = object({
|
|
57726
|
+
name: string(),
|
|
57727
|
+
version: string(),
|
|
57728
|
+
readme: PackageDocBodySchema,
|
|
57729
|
+
changelog: PackageDocBodySchema
|
|
57730
|
+
});
|
|
57310
57731
|
var SearchResultSchema = object({
|
|
57311
57732
|
name: string(),
|
|
57312
57733
|
version: string(),
|
|
@@ -57525,7 +57946,10 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
|
|
|
57525
57946
|
}), object({ success: literal(true) }), {
|
|
57526
57947
|
kind: "mutation",
|
|
57527
57948
|
auth: "admin"
|
|
57528
|
-
}), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({
|
|
57949
|
+
}), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({
|
|
57950
|
+
name: string().min(1),
|
|
57951
|
+
version: string().min(1).optional()
|
|
57952
|
+
}), PackageDocsSchema, { auth: "admin" }), method(object({ addonId: string() }), RestartAddonResultSchema, {
|
|
57529
57953
|
kind: "mutation",
|
|
57530
57954
|
auth: "admin"
|
|
57531
57955
|
}), method(object({ packageName: string() }), object({ success: literal(true) }), {
|
|
@@ -57584,27 +58008,17 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
|
|
|
57584
58008
|
*/
|
|
57585
58009
|
var AirQualitySensorStatusSchema = object({
|
|
57586
58010
|
/** Carbon dioxide concentration in ppm. */
|
|
57587
|
-
co2Ppm: number().min(0).optional(),
|
|
58011
|
+
co2Ppm: number().min(0).optional().meta(readingMeta("concentration-volume")),
|
|
57588
58012
|
/** Total volatile organic compounds in ppb. */
|
|
57589
|
-
vocPpb: number().min(0).optional(),
|
|
58013
|
+
vocPpb: number().min(0).optional().meta(readingMeta("concentration-ppb")),
|
|
57590
58014
|
/** Particulate matter ≤ 2.5 μm in µg/m³. */
|
|
57591
|
-
pm25: number().min(0).optional(),
|
|
58015
|
+
pm25: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
57592
58016
|
/** Particulate matter ≤ 10 μm in µg/m³. */
|
|
57593
|
-
pm10: number().min(0).optional(),
|
|
58017
|
+
pm10: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
57594
58018
|
/** Composite AQI value (typically 0..500). */
|
|
57595
|
-
aqi: number().optional(),
|
|
58019
|
+
aqi: number().optional().meta(readingMeta("index")),
|
|
57596
58020
|
/** Ms epoch when the slice was last updated. */
|
|
57597
|
-
lastFetchedAt: number()
|
|
57598
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
57599
|
-
* `attributes.unit_of_measurement` → 'ppm' / 'ppb' / 'µg/m³'). Each
|
|
57600
|
-
* upstream `sensor.*` entity surfaces ONE device_class, so one unit
|
|
57601
|
-
* per slice is unambiguous. */
|
|
57602
|
-
unit: string().optional(),
|
|
57603
|
-
/** Suggested decimal places for numeric display.
|
|
57604
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
57605
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
57606
|
-
* auto-formatting when absent. */
|
|
57607
|
-
precision: number().int().min(0).max(10).optional()
|
|
58021
|
+
lastFetchedAt: number()
|
|
57608
58022
|
});
|
|
57609
58023
|
var airQualitySensorCapability = {
|
|
57610
58024
|
name: "air-quality-sensor",
|
|
@@ -57641,12 +58055,12 @@ var airQualitySensorCapability = {
|
|
|
57641
58055
|
},
|
|
57642
58056
|
pm25: {
|
|
57643
58057
|
kind: "gauge",
|
|
57644
|
-
unit: "
|
|
58058
|
+
unit: "µg/m³",
|
|
57645
58059
|
deadband: 1
|
|
57646
58060
|
},
|
|
57647
58061
|
pm10: {
|
|
57648
58062
|
kind: "gauge",
|
|
57649
|
-
unit: "
|
|
58063
|
+
unit: "µg/m³",
|
|
57650
58064
|
deadband: 1
|
|
57651
58065
|
},
|
|
57652
58066
|
aqi: {
|
|
@@ -57664,22 +58078,13 @@ var airQualitySensorCapability = {
|
|
|
57664
58078
|
* entries with `device_class: illuminance`.
|
|
57665
58079
|
*/
|
|
57666
58080
|
var AmbientLightSensorStatusSchema = object({
|
|
57667
|
-
/** Current illuminance in lux (lx). */
|
|
57668
|
-
lux: number().min(0).meta({
|
|
57669
|
-
|
|
58081
|
+
/** Current illuminance in lux (lx). `null` when the sample was refused (D393). */
|
|
58082
|
+
lux: number().min(0).nullable().meta(readingMeta("illuminance", {
|
|
58083
|
+
precision: 0,
|
|
57670
58084
|
label: "Illuminance"
|
|
57671
|
-
}),
|
|
58085
|
+
})),
|
|
57672
58086
|
/** Ms epoch when the slice was last updated. */
|
|
57673
|
-
lastFetchedAt: number()
|
|
57674
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
57675
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
57676
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
57677
|
-
unit: string().optional(),
|
|
57678
|
-
/** Suggested decimal places for numeric display.
|
|
57679
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
57680
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
57681
|
-
* auto-formatting when absent. */
|
|
57682
|
-
precision: number().int().min(0).max(10).optional()
|
|
58087
|
+
lastFetchedAt: number()
|
|
57683
58088
|
});
|
|
57684
58089
|
var ambientLightSensorCapability = {
|
|
57685
58090
|
name: "ambient-light-sensor",
|
|
@@ -57711,12 +58116,7 @@ var ambientLightSensorCapability = {
|
|
|
57711
58116
|
} } },
|
|
57712
58117
|
/** Clock fields: written, but excluded from the compare that decides
|
|
57713
58118
|
* whether persisting is worth a SQLite commit. */
|
|
57714
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
57715
|
-
customize: {
|
|
57716
|
-
version: 1,
|
|
57717
|
-
advanced: "derive",
|
|
57718
|
-
targets: []
|
|
57719
|
-
}
|
|
58119
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
57720
58120
|
};
|
|
57721
58121
|
/**
|
|
57722
58122
|
* Per-class audio metrics aggregated over a sliding window.
|
|
@@ -57943,10 +58343,7 @@ var BatteryStatusSchema = object({
|
|
|
57943
58343
|
* Consumers must SKIP a null rather than coerce it — `battery-band` already
|
|
57944
58344
|
* declines to band a non-finite reading, which is the correct shape.
|
|
57945
58345
|
*/
|
|
57946
|
-
percentage: number().min(0).max(100).nullable().meta({
|
|
57947
|
-
unit: "%",
|
|
57948
|
-
label: "Charge"
|
|
57949
|
-
}),
|
|
58346
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage", { label: "Charge" })),
|
|
57950
58347
|
/**
|
|
57951
58348
|
* Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
|
|
57952
58349
|
* Reolink-specific for the Solar Panel 2 accessory (will become
|
|
@@ -57973,7 +58370,14 @@ var BatteryStatusSchema = object({
|
|
|
57973
58370
|
*/
|
|
57974
58371
|
sleeping: boolean().meta({ label: "Sleeping" }),
|
|
57975
58372
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
57976
|
-
lastUpdated: number(),
|
|
58373
|
+
lastUpdated: number().meta(readingMeta("none")),
|
|
58374
|
+
/**
|
|
58375
|
+
* Battery voltage in volts, for a cell the firmware reports as voltage
|
|
58376
|
+
* rather than a percentage (Ecowitt capacitor packs). Absent on cameras
|
|
58377
|
+
* that only report charge. A second reading on this cap, not a second
|
|
58378
|
+
* `numeric-sensor` on the same device.
|
|
58379
|
+
*/
|
|
58380
|
+
volts: number().nullable().optional().meta(readingMeta("voltage", { label: "Voltage" })),
|
|
57977
58381
|
/**
|
|
57978
58382
|
* Ms epoch of the last time the device PROVED it was reachable — a
|
|
57979
58383
|
* completed firmware round-trip, an observed wake, or an inbound push
|
|
@@ -58025,7 +58429,6 @@ var BATTERY_DEVICE_TYPES = [
|
|
|
58025
58429
|
/** Generic Customize target for the percentage reading (D936). */
|
|
58026
58430
|
var batteryCustomize = {
|
|
58027
58431
|
version: 1,
|
|
58028
|
-
advanced: "derive",
|
|
58029
58432
|
targets: [{
|
|
58030
58433
|
id: "percentage",
|
|
58031
58434
|
cardinality: "scalar",
|
|
@@ -58034,7 +58437,7 @@ var batteryCustomize = {
|
|
|
58034
58437
|
stateField: "percentage"
|
|
58035
58438
|
},
|
|
58036
58439
|
deviceTypes: BATTERY_DEVICE_TYPES,
|
|
58037
|
-
apply: "add
|
|
58440
|
+
apply: "add",
|
|
58038
58441
|
path: "percentage",
|
|
58039
58442
|
sources: [{
|
|
58040
58443
|
kind: "field",
|
|
@@ -58155,10 +58558,16 @@ onStatusChanged: { data: object({
|
|
|
58155
58558
|
/**
|
|
58156
58559
|
* History (D850): recorded series. The generic capture replaces the `battery` series of `pipeline-analytics:stats-5m`.
|
|
58157
58560
|
*/
|
|
58158
|
-
history: { fields: {
|
|
58159
|
-
|
|
58160
|
-
|
|
58161
|
-
|
|
58561
|
+
history: { fields: {
|
|
58562
|
+
percentage: {
|
|
58563
|
+
kind: "gauge",
|
|
58564
|
+
unit: "%"
|
|
58565
|
+
},
|
|
58566
|
+
volts: {
|
|
58567
|
+
kind: "gauge",
|
|
58568
|
+
unit: "V"
|
|
58569
|
+
}
|
|
58570
|
+
} },
|
|
58162
58571
|
customize: batteryCustomize,
|
|
58163
58572
|
/** Clock fields: written, but excluded from the compare that decides
|
|
58164
58573
|
* whether persisting is worth a SQLite commit. */
|
|
@@ -58205,12 +58614,7 @@ var binaryCapability = {
|
|
|
58205
58614
|
history: { fields: { on: { kind: "boolean" } } },
|
|
58206
58615
|
/** Clock fields: written, but excluded from the compare that decides
|
|
58207
58616
|
* whether persisting is worth a SQLite commit. */
|
|
58208
|
-
volatileStateFields: ["lastChangedAt"]
|
|
58209
|
-
customize: {
|
|
58210
|
-
version: 1,
|
|
58211
|
-
advanced: "derive",
|
|
58212
|
-
targets: []
|
|
58213
|
-
}
|
|
58617
|
+
volatileStateFields: ["lastChangedAt"]
|
|
58214
58618
|
};
|
|
58215
58619
|
/**
|
|
58216
58620
|
* Dimmable-light brightness control. Co-exists with `switch` on the
|
|
@@ -58226,7 +58630,7 @@ var binaryCapability = {
|
|
|
58226
58630
|
*/
|
|
58227
58631
|
var BrightnessStatusSchema = object({
|
|
58228
58632
|
/** Current level as 0..100 inclusive. Firmware-reported. */
|
|
58229
|
-
percentage: number().min(0).max(100),
|
|
58633
|
+
percentage: number().min(0).max(100).meta(readingMeta("percentage")),
|
|
58230
58634
|
/** Ms epoch of the last operator-driven change. Useful for UI freshness. */
|
|
58231
58635
|
lastChangedAt: number()
|
|
58232
58636
|
});
|
|
@@ -58680,21 +59084,21 @@ var ClimateControlStatusSchema = object({
|
|
|
58680
59084
|
/** Single setpoint in Celsius. Used by single-target modes
|
|
58681
59085
|
* (heat / cool / dry). Null when the device is in a range mode
|
|
58682
59086
|
* (`heat_cool`) or has no setpoint at all (`fan_only`/`off`). */
|
|
58683
|
-
target: number().nullable(),
|
|
59087
|
+
target: number().nullable().meta(readingMeta("temperature")),
|
|
58684
59088
|
/** Upper bound of the dual setpoint in Celsius. Populated only
|
|
58685
59089
|
* in `heat_cool` mode. */
|
|
58686
|
-
targetHigh: number().nullable(),
|
|
59090
|
+
targetHigh: number().nullable().meta(readingMeta("temperature")),
|
|
58687
59091
|
/** Lower bound of the dual setpoint in Celsius. Populated only
|
|
58688
59092
|
* in `heat_cool` mode. */
|
|
58689
|
-
targetLow: number().nullable(),
|
|
59093
|
+
targetLow: number().nullable().meta(readingMeta("temperature")),
|
|
58690
59094
|
/** Target relative humidity (0..100). Null when the device has no
|
|
58691
59095
|
* humidity control. */
|
|
58692
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
59096
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
58693
59097
|
/** Current measured temperature in Celsius. Read-only — pushed by
|
|
58694
59098
|
* the device's internal sensor. */
|
|
58695
|
-
currentTemp: number().nullable(),
|
|
59099
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
58696
59100
|
/** Current measured relative humidity (0..100). Read-only. */
|
|
58697
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
59101
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
58698
59102
|
/** Vertical louver swing on/off. Null when the device has no vertical
|
|
58699
59103
|
* swing surface (gate with `DeviceFeature.ClimateSwingVertical`). */
|
|
58700
59104
|
swingVertical: boolean().nullable(),
|
|
@@ -58702,11 +59106,11 @@ var ClimateControlStatusSchema = object({
|
|
|
58702
59106
|
* horizontal swing surface (gate with `DeviceFeature.ClimateSwingHorizontal`). */
|
|
58703
59107
|
swingHorizontal: boolean().nullable(),
|
|
58704
59108
|
/** Lowest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
58705
|
-
minTemp: number().nullable().optional(),
|
|
59109
|
+
minTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
58706
59110
|
/** Highest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
58707
|
-
maxTemp: number().nullable().optional(),
|
|
59111
|
+
maxTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
58708
59112
|
/** Setpoint granularity, Celsius (0.5, 1). Absent / null = not reported. */
|
|
58709
|
-
tempStep: number().positive().nullable().optional(),
|
|
59113
|
+
tempStep: number().positive().nullable().optional().meta(readingMeta("temperature")),
|
|
58710
59114
|
/** Ms epoch when the slice was last updated (push or command). */
|
|
58711
59115
|
lastFetchedAt: number()
|
|
58712
59116
|
});
|
|
@@ -58848,17 +59252,17 @@ var climateControlCapability = {
|
|
|
58848
59252
|
* modes to expose in the picker without a slice fetch.
|
|
58849
59253
|
*/
|
|
58850
59254
|
var RgbTripletSchema = object({
|
|
58851
|
-
r: number().int().min(0).max(255),
|
|
58852
|
-
g: number().int().min(0).max(255),
|
|
58853
|
-
b: number().int().min(0).max(255)
|
|
59255
|
+
r: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
59256
|
+
g: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
59257
|
+
b: number().int().min(0).max(255).meta(readingMeta("none"))
|
|
58854
59258
|
});
|
|
58855
59259
|
var HsvTripletSchema = object({
|
|
58856
59260
|
/** Hue in degrees, 0..360. */
|
|
58857
|
-
h: number().min(0).max(360),
|
|
59261
|
+
h: number().min(0).max(360).meta(readingMeta("none")),
|
|
58858
59262
|
/** Saturation as 0..100 inclusive. */
|
|
58859
|
-
s: number().min(0).max(100),
|
|
59263
|
+
s: number().min(0).max(100).meta(readingMeta("none")),
|
|
58860
59264
|
/** Value/brightness as 0..100 inclusive. */
|
|
58861
|
-
v: number().min(0).max(100)
|
|
59265
|
+
v: number().min(0).max(100).meta(readingMeta("none"))
|
|
58862
59266
|
});
|
|
58863
59267
|
var ColorInputSchema = discriminatedUnion("mode", [
|
|
58864
59268
|
object({
|
|
@@ -58887,7 +59291,7 @@ var ColorStatusSchema = object({
|
|
|
58887
59291
|
/** Populated when `mode === 'hsv'`. */
|
|
58888
59292
|
hsv: HsvTripletSchema.optional(),
|
|
58889
59293
|
/** Populated when `mode === 'mired'`. */
|
|
58890
|
-
mireds: number().int().optional(),
|
|
59294
|
+
mireds: number().int().optional().meta(readingMeta("colour-temperature")),
|
|
58891
59295
|
/** Ms epoch of the last operator-driven change. */
|
|
58892
59296
|
lastChangedAt: number()
|
|
58893
59297
|
});
|
|
@@ -59082,18 +59486,12 @@ _enum([
|
|
|
59082
59486
|
"empty",
|
|
59083
59487
|
"full"
|
|
59084
59488
|
]);
|
|
59085
|
-
/**
|
|
59086
|
-
|
|
59087
|
-
|
|
59088
|
-
"days",
|
|
59089
|
-
"hours",
|
|
59090
|
-
"cycles"
|
|
59091
|
-
]);
|
|
59092
|
-
/** Remaining life as a COUNT, not a percentage (the PetKit desiccant reports
|
|
59093
|
-
* days). `value` null = unknown (D393). */
|
|
59489
|
+
/** Whether `remaining.value` is a duration in seconds or a dimensionless count. */
|
|
59490
|
+
var ConsumableRemainingKindSchema = _enum(["duration", "count"]);
|
|
59491
|
+
/** Remaining life. `value` null = unknown (D393). Duration is seconds. */
|
|
59094
59492
|
var ConsumableRemainingSchema = object({
|
|
59095
|
-
value: number().min(0).nullable(),
|
|
59096
|
-
|
|
59493
|
+
value: number().min(0).nullable().meta(readingMeta("device")),
|
|
59494
|
+
kind: ConsumableRemainingKindSchema
|
|
59097
59495
|
});
|
|
59098
59496
|
/** A single consumable item. Either a continuous `level` (remaining
|
|
59099
59497
|
* life %, or fill % for a `supply` / `waste` item) or a discrete `status`
|
|
@@ -59106,7 +59504,7 @@ var ConsumableItemSchema = object({
|
|
|
59106
59504
|
/** Display name. */
|
|
59107
59505
|
label: string().min(1),
|
|
59108
59506
|
/** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
|
|
59109
|
-
level: number().min(0).max(100).nullable(),
|
|
59507
|
+
level: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59110
59508
|
/** The provider's discrete verdict when known (binary mode). */
|
|
59111
59509
|
status: ConsumableStatusSchema.nullable(),
|
|
59112
59510
|
/** What the item is — decides whether low or full is bad. Absent = `wear`. */
|
|
@@ -59188,8 +59586,8 @@ var consumablesCustomize = {
|
|
|
59188
59586
|
transforms: [{ kind: "identity" }]
|
|
59189
59587
|
}],
|
|
59190
59588
|
literals: [{
|
|
59191
|
-
path: "remaining.
|
|
59192
|
-
values: [...
|
|
59589
|
+
path: "remaining.kind",
|
|
59590
|
+
values: [...ConsumableRemainingKindSchema.options]
|
|
59193
59591
|
}]
|
|
59194
59592
|
},
|
|
59195
59593
|
{
|
|
@@ -59318,7 +59716,6 @@ reset: method(object({
|
|
|
59318
59716
|
},
|
|
59319
59717
|
"remaining.value": {
|
|
59320
59718
|
kind: "gauge",
|
|
59321
|
-
unitFrom: "remaining.unit",
|
|
59322
59719
|
deadband: 1,
|
|
59323
59720
|
displayName: "Remaining"
|
|
59324
59721
|
}
|
|
@@ -59388,10 +59785,9 @@ var contactCapability = {
|
|
|
59388
59785
|
* (empty array for the other kinds). It lives in the slice because
|
|
59389
59786
|
* HA `select.*` entities may update their options at runtime.
|
|
59390
59787
|
*
|
|
59391
|
-
*
|
|
59392
|
-
*
|
|
59393
|
-
*
|
|
59394
|
-
* push — consistent with `options` and the sensor-unit approach.
|
|
59788
|
+
* Numeric `min` / `max` / `step` live in the slice and share the device
|
|
59789
|
+
* quantity (`SourceInfo.quantity`, D944). Display precision is a read-time
|
|
59790
|
+
* preference. A datetime control's shape is `SourceInfo.dateTimeShape`.
|
|
59395
59791
|
*/
|
|
59396
59792
|
var ControlStatusSchema = object({
|
|
59397
59793
|
kind: _enum([
|
|
@@ -59403,39 +59799,17 @@ var ControlStatusSchema = object({
|
|
|
59403
59799
|
/** Current value. Numeric kind → number; select/text/datetime → string.
|
|
59404
59800
|
* Datetime values are ISO 8601 strings (full timestamp, date-only,
|
|
59405
59801
|
* or time-only — HA accepts all three forms). */
|
|
59406
|
-
value: union([number(), string()]),
|
|
59802
|
+
value: union([number().meta(readingMeta("device")), string()]),
|
|
59407
59803
|
/** Acceptable values when `kind === 'select'`. Empty for other kinds. */
|
|
59408
59804
|
options: array(string()),
|
|
59409
59805
|
/** Ms epoch when the slice was last updated. */
|
|
59410
59806
|
lastChangedAt: number(),
|
|
59411
|
-
/**
|
|
59412
|
-
|
|
59413
|
-
|
|
59414
|
-
|
|
59415
|
-
/**
|
|
59416
|
-
|
|
59417
|
-
min: number().optional(),
|
|
59418
|
-
/** Maximum allowed value. Populated live from HA `attributes.max`.
|
|
59419
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
59420
|
-
max: number().optional(),
|
|
59421
|
-
/** Step increment. Populated live from HA `attributes.step`.
|
|
59422
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
59423
|
-
step: number().optional(),
|
|
59424
|
-
/** Suggested decimal places for numeric display. Populated live from HA
|
|
59425
|
-
* `attributes.suggested_display_precision`, or derived from `step` when the
|
|
59426
|
-
* HA attribute is absent. Meaningful for `kind === 'numeric'`; absent for
|
|
59427
|
-
* other kinds. Falls back to auto-formatting when absent. */
|
|
59428
|
-
precision: number().int().min(0).max(10).optional(),
|
|
59429
|
-
/** Date-picker granularity for `kind === 'datetime'`. 'date' → date-only,
|
|
59430
|
-
* 'time' → time-only, 'datetime' → full timestamp. Absent for other kinds
|
|
59431
|
-
* (UI defaults to 'datetime'). Derived live from the device's HA domain
|
|
59432
|
-
* (date.* / time.* / datetime.*) or, for input_datetime, from the entity's
|
|
59433
|
-
* `has_date`/`has_time` attributes on each push. */
|
|
59434
|
-
format: _enum([
|
|
59435
|
-
"date",
|
|
59436
|
-
"time",
|
|
59437
|
-
"datetime"
|
|
59438
|
-
]).optional()
|
|
59807
|
+
/** Minimum allowed value, in the device quantity's base unit. */
|
|
59808
|
+
min: number().optional().meta(readingMeta("device")),
|
|
59809
|
+
/** Maximum allowed value, in the device quantity's base unit. */
|
|
59810
|
+
max: number().optional().meta(readingMeta("device")),
|
|
59811
|
+
/** Step increment, in the device quantity's base unit. */
|
|
59812
|
+
step: number().optional().meta(readingMeta("device"))
|
|
59439
59813
|
});
|
|
59440
59814
|
var ControlSetValueInputSchema = discriminatedUnion("kind", [
|
|
59441
59815
|
object({
|
|
@@ -59501,9 +59875,9 @@ var CoverStatusSchema = object({
|
|
|
59501
59875
|
]),
|
|
59502
59876
|
/** 0 = fully closed, 100 = fully open. Null when the device has
|
|
59503
59877
|
* no intermediate position surface. */
|
|
59504
|
-
position: number().min(0).max(100).nullable(),
|
|
59878
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59505
59879
|
/** 0 = closed slats, 100 = open slats. Null when no tilt support. */
|
|
59506
|
-
tiltPosition: number().min(0).max(100).nullable(),
|
|
59880
|
+
tiltPosition: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59507
59881
|
/** Ms epoch when the slice was last updated. */
|
|
59508
59882
|
lastChangedAt: number()
|
|
59509
59883
|
});
|
|
@@ -59606,9 +59980,9 @@ var NormalizedRangeSchema$1 = object({
|
|
|
59606
59980
|
var DayNightStatusSchema = object({
|
|
59607
59981
|
mode: DayNightModeSchema,
|
|
59608
59982
|
/** IR-cut trigger sensitivity, NORMALIZED 0–100 (higher = switches to night sooner). */
|
|
59609
|
-
sensitivity: number().optional(),
|
|
59983
|
+
sensitivity: number().optional().meta(readingMeta("none")),
|
|
59610
59984
|
/** Delay before the IR-cut filter flips, in seconds. */
|
|
59611
|
-
switchDelaySec: number().optional(),
|
|
59985
|
+
switchDelaySec: number().optional().meta(readingMeta("duration")),
|
|
59612
59986
|
lastFetchedAt: number()
|
|
59613
59987
|
});
|
|
59614
59988
|
/**
|
|
@@ -59826,11 +60200,11 @@ var DishwasherStatusSchema = object({
|
|
|
59826
60200
|
/** Feature keys of the programs the appliance currently offers — drives the UI selector. */
|
|
59827
60201
|
availablePrograms: array(string()),
|
|
59828
60202
|
/** Seconds remaining on the active cycle, or null when not running / not known. */
|
|
59829
|
-
remainingSeconds: number().int().nonnegative().nullable(),
|
|
60203
|
+
remainingSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
59830
60204
|
/** Seconds the delayed start is set to (time until the cycle starts), or null. */
|
|
59831
|
-
delayedStartSeconds: number().int().nonnegative().nullable(),
|
|
60205
|
+
delayedStartSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
59832
60206
|
/** Cycle completion 0..100, or null when not applicable. */
|
|
59833
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
60207
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59834
60208
|
/** True when the door is reported open; null when the door state is not known. */
|
|
59835
60209
|
doorOpen: boolean().nullable(),
|
|
59836
60210
|
/** True when the door is latched (locked) during a cycle; null when not reported. */
|
|
@@ -59854,7 +60228,7 @@ var DishwasherStatusSchema = object({
|
|
|
59854
60228
|
/** True while the machine-care (descaling / cleaning-program) reminder is raised; false when clear; null when not reported. */
|
|
59855
60229
|
machineCareDue: boolean().nullable(),
|
|
59856
60230
|
/** Program runs left before the machine-care reminder is due; null when the appliance does not say. */
|
|
59857
|
-
machineCareRemainingRuns: number().int().nonnegative().nullable(),
|
|
60231
|
+
machineCareRemainingRuns: number().int().nonnegative().nullable().meta(readingMeta("count")),
|
|
59858
60232
|
/** Option states: null when the appliance does not expose the option or has not said. */
|
|
59859
60233
|
halfLoad: boolean().nullable(),
|
|
59860
60234
|
hygienePlus: boolean().nullable(),
|
|
@@ -59869,7 +60243,7 @@ var DishwasherStatusSchema = object({
|
|
|
59869
60243
|
/** Feature keys of the events currently raised (salt low, rinse aid low, program finished, …). */
|
|
59870
60244
|
activeEvents: array(string()),
|
|
59871
60245
|
/** Numeric error code when the appliance reports one; null otherwise. */
|
|
59872
|
-
errorCode: number().nullable(),
|
|
60246
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
59873
60247
|
/** Name of the raised alert-level event while the appliance is in error; null otherwise. */
|
|
59874
60248
|
errorLabel: string().nullable(),
|
|
59875
60249
|
/** Ms epoch of the last value received from the appliance; 0 = never. */
|
|
@@ -60100,7 +60474,7 @@ var DoorbellStatusSchema = object({
|
|
|
60100
60474
|
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
60101
60475
|
lastPressedAt: number().nullable(),
|
|
60102
60476
|
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
60103
|
-
pressCountSinceStart: number()
|
|
60477
|
+
pressCountSinceStart: number().meta(readingMeta("count"))
|
|
60104
60478
|
});
|
|
60105
60479
|
var DoorbellPressEventSchema = object({
|
|
60106
60480
|
deviceId: number(),
|
|
@@ -60165,17 +60539,7 @@ onPressed: {
|
|
|
60165
60539
|
history: "none",
|
|
60166
60540
|
customize: doorbellCustomize
|
|
60167
60541
|
};
|
|
60168
|
-
|
|
60169
|
-
* Enum-state sensor — a string value picked from a finite option set.
|
|
60170
|
-
* Drives HA `sensor` entries with `state_class: enum` (HVAC action
|
|
60171
|
-
* states, weather conditions, contact-source channels, mode strings).
|
|
60172
|
-
* The option set is stable across observations; it is persisted in the
|
|
60173
|
-
* device config blob (via the control slice at adoption) and is NOT
|
|
60174
|
-
* stored in `sourceInfo`.
|
|
60175
|
-
*/
|
|
60176
|
-
/** Locale-render shape for an ISO `value` carried by a `DateTimeSensor`-role
|
|
60177
|
-
* enum sensor: `date` (date-only), `time` (time-only), `datetime` (both). */
|
|
60178
|
-
var EnumSensorDateTimeFormatSchema = _enum([
|
|
60542
|
+
_enum([
|
|
60179
60543
|
"date",
|
|
60180
60544
|
"time",
|
|
60181
60545
|
"datetime"
|
|
@@ -60183,12 +60547,11 @@ var EnumSensorDateTimeFormatSchema = _enum([
|
|
|
60183
60547
|
var EnumSensorStatusSchema = object({
|
|
60184
60548
|
value: string(),
|
|
60185
60549
|
/**
|
|
60186
|
-
* Set
|
|
60187
|
-
* as
|
|
60188
|
-
*
|
|
60189
|
-
* a time-only sensor → `'time'`.
|
|
60550
|
+
* Set when `value` is a timestamp rather than an enum state, so history
|
|
60551
|
+
* does not learn ISO strings as states. The display shape (date / time /
|
|
60552
|
+
* datetime) lives on `SourceInfo.dateTimeShape`, written once at adopt.
|
|
60190
60553
|
*/
|
|
60191
|
-
|
|
60554
|
+
timestamp: boolean().optional(),
|
|
60192
60555
|
/** Ms epoch when the slice was last updated. */
|
|
60193
60556
|
lastFetchedAt: number()
|
|
60194
60557
|
});
|
|
@@ -60215,11 +60578,11 @@ var enumSensorCapability = {
|
|
|
60215
60578
|
* History (D850): the value as an `enum` series (an appliance's program or
|
|
60216
60579
|
* operation state, an HVAC action). The option set is per device, so the
|
|
60217
60580
|
* value list is LEARNED as values are first seen (bounded). A sensor with a
|
|
60218
|
-
* `
|
|
60581
|
+
* `timestamp` carries a clock, not a state, and is not recorded.
|
|
60219
60582
|
*/
|
|
60220
60583
|
history: { fields: { value: {
|
|
60221
60584
|
kind: "enum",
|
|
60222
|
-
skipWhenSet: "
|
|
60585
|
+
skipWhenSet: "timestamp"
|
|
60223
60586
|
} } },
|
|
60224
60587
|
/** Clock fields: written, but excluded from the compare that decides
|
|
60225
60588
|
* whether persisting is worth a SQLite commit. */
|
|
@@ -60239,13 +60602,13 @@ var EventFireSchema = object({
|
|
|
60239
60602
|
deviceId: number(),
|
|
60240
60603
|
eventType: string(),
|
|
60241
60604
|
data: record(string(), unknown()).nullable(),
|
|
60242
|
-
timestamp: number(),
|
|
60243
|
-
seq: number()
|
|
60605
|
+
timestamp: number().meta(readingMeta("none")),
|
|
60606
|
+
seq: number().meta(readingMeta("count"))
|
|
60244
60607
|
});
|
|
60245
60608
|
var EventEmitterStatusSchema = object({
|
|
60246
60609
|
eventTypes: array(string()),
|
|
60247
60610
|
lastEvent: EventFireSchema.nullable(),
|
|
60248
|
-
eventCountSinceStart: number()
|
|
60611
|
+
eventCountSinceStart: number().meta(readingMeta("count"))
|
|
60249
60612
|
});
|
|
60250
60613
|
var eventEmitterCapability = {
|
|
60251
60614
|
name: "event-emitter",
|
|
@@ -60658,10 +61021,10 @@ var FanDirectionSchema = _enum(["forward", "reverse"]);
|
|
|
60658
61021
|
var FanControlStatusSchema = object({
|
|
60659
61022
|
/** Active speed as 0..100 inclusive. Null when the device has no
|
|
60660
61023
|
* speed surface (single-speed fan). */
|
|
60661
|
-
percentage: number().min(0).max(100).nullable(),
|
|
61024
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
60662
61025
|
/** Speed granularity the device accepts (HA `percentage_step`, e.g. 25 for
|
|
60663
61026
|
* a 4-speed fan). Absent when unknown — the UI then falls back to step 1. */
|
|
60664
|
-
percentageStep: number().positive().optional(),
|
|
61027
|
+
percentageStep: number().positive().optional().meta(readingMeta("percentage")),
|
|
60665
61028
|
/** Active preset mode (`auto` / `quiet` / `turbo` / vendor-specific)
|
|
60666
61029
|
* — empty string when no preset is active or supported. */
|
|
60667
61030
|
preset: string(),
|
|
@@ -60782,7 +61145,7 @@ var FeatureProbeStatusSchema = object({
|
|
|
60782
61145
|
/** Camera/firmware model string. `null` when the firmware doesn't expose it. */
|
|
60783
61146
|
model: string().nullable(),
|
|
60784
61147
|
/** Channel count for NVR/Hub devices; `1` for standalone cameras; `null` pre-probe. */
|
|
60785
|
-
channelCount: number().nullable(),
|
|
61148
|
+
channelCount: number().nullable().meta(readingMeta("count")),
|
|
60786
61149
|
/**
|
|
60787
61150
|
* Ms epoch of the last SUCCESSFUL probe. `0` before the first probe
|
|
60788
61151
|
* completes — drivers' `getAccessoryChildren()` should treat zero as
|
|
@@ -60905,9 +61268,91 @@ var gasCapability = {
|
|
|
60905
61268
|
* whether persisting is worth a SQLite commit. */
|
|
60906
61269
|
volatileStateFields: ["lastChangedAt"]
|
|
60907
61270
|
};
|
|
61271
|
+
var GroupCommandsSchema = object({
|
|
61272
|
+
/** One row per member that has been commanded. A later command replaces that member's row. */
|
|
61273
|
+
results: array(object({
|
|
61274
|
+
deviceId: number().int().nonnegative(),
|
|
61275
|
+
cap: string().min(1),
|
|
61276
|
+
method: string().min(1),
|
|
61277
|
+
ok: boolean(),
|
|
61278
|
+
error: string().optional(),
|
|
61279
|
+
/** Ms epoch of the attempt. */
|
|
61280
|
+
at: number()
|
|
61281
|
+
})) });
|
|
61282
|
+
var groupCommandsCapability = {
|
|
61283
|
+
name: "group-commands",
|
|
61284
|
+
scope: "device",
|
|
61285
|
+
deviceNative: true,
|
|
61286
|
+
mode: "singleton",
|
|
61287
|
+
deviceTypes: [DeviceType.Switch, DeviceType.Light],
|
|
61288
|
+
methods: {},
|
|
61289
|
+
status: {
|
|
61290
|
+
schema: GroupCommandsSchema,
|
|
61291
|
+
kind: "push"
|
|
61292
|
+
},
|
|
61293
|
+
runtimeState: GroupCommandsSchema,
|
|
61294
|
+
/**
|
|
61295
|
+
* Runtime-state durability: **session** — the last attempt. A restored
|
|
61296
|
+
* failure would outlive the command that caused it.
|
|
61297
|
+
*
|
|
61298
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
61299
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
61300
|
+
*/
|
|
61301
|
+
durability: "session",
|
|
61302
|
+
history: "none"
|
|
61303
|
+
};
|
|
61304
|
+
/**
|
|
61305
|
+
* How many members of a helper group answered (D944). Counts are integers,
|
|
61306
|
+
* not measurements: zero included is a real count, never a stand-in reading.
|
|
61307
|
+
* The reading itself stays on the output capability. History is none — the
|
|
61308
|
+
* series that later statistics read is the output cap's own history block.
|
|
61309
|
+
*/
|
|
61310
|
+
var GroupStatusSchema = object({
|
|
61311
|
+
/** Members whose current value entered the aggregate. */
|
|
61312
|
+
included: number().int().nonnegative().meta(readingMeta("count", {
|
|
61313
|
+
precision: 0,
|
|
61314
|
+
label: "Reporting"
|
|
61315
|
+
})),
|
|
61316
|
+
/** Members left out: offline, unknown, or not a finite reading (D393). */
|
|
61317
|
+
excluded: number().int().nonnegative().meta(readingMeta("count", {
|
|
61318
|
+
precision: 0,
|
|
61319
|
+
label: "Excluded"
|
|
61320
|
+
})),
|
|
61321
|
+
/** `included` + `excluded`. */
|
|
61322
|
+
total: number().int().nonnegative().meta(readingMeta("count", {
|
|
61323
|
+
precision: 0,
|
|
61324
|
+
label: "Members"
|
|
61325
|
+
}))
|
|
61326
|
+
});
|
|
61327
|
+
var groupStatusCapability = {
|
|
61328
|
+
name: "group-status",
|
|
61329
|
+
scope: "device",
|
|
61330
|
+
deviceNative: true,
|
|
61331
|
+
mode: "singleton",
|
|
61332
|
+
deviceTypes: [
|
|
61333
|
+
DeviceType.Sensor,
|
|
61334
|
+
DeviceType.Switch,
|
|
61335
|
+
DeviceType.Light
|
|
61336
|
+
],
|
|
61337
|
+
methods: {},
|
|
61338
|
+
status: {
|
|
61339
|
+
schema: GroupStatusSchema,
|
|
61340
|
+
kind: "push"
|
|
61341
|
+
},
|
|
61342
|
+
runtimeState: GroupStatusSchema,
|
|
61343
|
+
/**
|
|
61344
|
+
* Runtime-state durability: **session** — recomputed from members on the
|
|
61345
|
+
* next source event; a restored count would outlive the readings it named.
|
|
61346
|
+
*
|
|
61347
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
61348
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
61349
|
+
*/
|
|
61350
|
+
durability: "session",
|
|
61351
|
+
history: "none"
|
|
61352
|
+
};
|
|
60908
61353
|
var HeatingValveStatusSchema = object({
|
|
60909
61354
|
/** Radiator valve opening 0 (closed) .. 100 (open). Null = not yet known. */
|
|
60910
|
-
position: number().min(0).max(100).nullable(),
|
|
61355
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
60911
61356
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
60912
61357
|
lastFetchedAt: number()
|
|
60913
61358
|
});
|
|
@@ -60950,9 +61395,9 @@ var HumidifierStatusSchema = object({
|
|
|
60950
61395
|
/** Whether the humidifier is currently on. */
|
|
60951
61396
|
on: boolean(),
|
|
60952
61397
|
/** Current measured relative humidity (0..100). Null when not reported. */
|
|
60953
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
61398
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
60954
61399
|
/** Target relative humidity (0..100). Null when no setpoint surface. */
|
|
60955
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
61400
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
60956
61401
|
/** Active mode (`auto` / `normal` / `baby` / vendor). Null when the
|
|
60957
61402
|
* device has no mode surface. */
|
|
60958
61403
|
mode: string().nullable(),
|
|
@@ -60962,9 +61407,9 @@ var HumidifierStatusSchema = object({
|
|
|
60962
61407
|
* `idle` / `off`). Null when the device doesn't report it. */
|
|
60963
61408
|
action: string().nullable(),
|
|
60964
61409
|
/** HA `min_humidity` attribute. Null → UI uses 0. */
|
|
60965
|
-
minHumidity: number().nullable(),
|
|
61410
|
+
minHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
60966
61411
|
/** HA `max_humidity` attribute. Null → UI uses 100. */
|
|
60967
|
-
maxHumidity: number().nullable(),
|
|
61412
|
+
maxHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
60968
61413
|
/** Ms epoch when the slice was last updated. */
|
|
60969
61414
|
lastChangedAt: number()
|
|
60970
61415
|
});
|
|
@@ -61034,22 +61479,13 @@ var humidifierCapability = {
|
|
|
61034
61479
|
* `sourceInfo`.
|
|
61035
61480
|
*/
|
|
61036
61481
|
var HumiditySensorStatusSchema = object({
|
|
61037
|
-
/** Current relative humidity, 0..100. */
|
|
61038
|
-
percent: number().min(0).max(100).meta({
|
|
61039
|
-
|
|
61482
|
+
/** Current relative humidity, 0..100. `null` when the sample was refused (D393). */
|
|
61483
|
+
percent: number().min(0).max(100).nullable().meta(readingMeta("humidity", {
|
|
61484
|
+
precision: 0,
|
|
61040
61485
|
label: "Humidity"
|
|
61041
|
-
}),
|
|
61486
|
+
})),
|
|
61042
61487
|
/** Ms epoch when the slice was last updated. */
|
|
61043
|
-
lastFetchedAt: number()
|
|
61044
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
61045
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
61046
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
61047
|
-
unit: string().optional(),
|
|
61048
|
-
/** Suggested decimal places for numeric display.
|
|
61049
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
61050
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
61051
|
-
* auto-formatting when absent. */
|
|
61052
|
-
precision: number().int().min(0).max(10).optional()
|
|
61488
|
+
lastFetchedAt: number()
|
|
61053
61489
|
});
|
|
61054
61490
|
var humiditySensorCapability = {
|
|
61055
61491
|
name: "humidity-sensor",
|
|
@@ -61080,12 +61516,7 @@ var humiditySensorCapability = {
|
|
|
61080
61516
|
} } },
|
|
61081
61517
|
/** Clock fields: written, but excluded from the compare that decides
|
|
61082
61518
|
* whether persisting is worth a SQLite commit. */
|
|
61083
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
61084
|
-
customize: {
|
|
61085
|
-
version: 1,
|
|
61086
|
-
advanced: "derive",
|
|
61087
|
-
targets: []
|
|
61088
|
-
}
|
|
61519
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
61089
61520
|
};
|
|
61090
61521
|
/**
|
|
61091
61522
|
* Image display cap. Models a single still image exposed by an integration —
|
|
@@ -61106,7 +61537,7 @@ var ImageStatusSchema = object({
|
|
|
61106
61537
|
* entity exposes no `entity_picture` (yet). */
|
|
61107
61538
|
url: string().nullable(),
|
|
61108
61539
|
/** Ms epoch of the upstream last-updated timestamp. Null at cold-start. */
|
|
61109
|
-
lastUpdated: number().nullable()
|
|
61540
|
+
lastUpdated: number().nullable().meta(readingMeta("none"))
|
|
61110
61541
|
});
|
|
61111
61542
|
var imageCapability = {
|
|
61112
61543
|
name: "image",
|
|
@@ -61194,19 +61625,19 @@ var NormalizedRangeSchema = object({
|
|
|
61194
61625
|
*/
|
|
61195
61626
|
var ImageSettingsStatusSchema = object({
|
|
61196
61627
|
/** Normalized 0–100. */
|
|
61197
|
-
brightness: number().optional(),
|
|
61628
|
+
brightness: number().optional().meta(readingMeta("none")),
|
|
61198
61629
|
/** Normalized 0–100. */
|
|
61199
|
-
contrast: number().optional(),
|
|
61630
|
+
contrast: number().optional().meta(readingMeta("none")),
|
|
61200
61631
|
/** Normalized 0–100. */
|
|
61201
|
-
saturation: number().optional(),
|
|
61632
|
+
saturation: number().optional().meta(readingMeta("none")),
|
|
61202
61633
|
/** Normalized 0–100. */
|
|
61203
|
-
sharpness: number().optional(),
|
|
61634
|
+
sharpness: number().optional().meta(readingMeta("none")),
|
|
61204
61635
|
mirror: boolean().optional(),
|
|
61205
61636
|
flip: boolean().optional(),
|
|
61206
61637
|
rotate: ImageRotateSchema.optional(),
|
|
61207
61638
|
whiteBalance: WhiteBalanceModeSchema.optional(),
|
|
61208
61639
|
/** Manual white-balance warmth, NORMALIZED 0–100. Meaningful only when `whiteBalance === 'manual'`. */
|
|
61209
|
-
warmth: number().optional(),
|
|
61640
|
+
warmth: number().optional().meta(readingMeta("none")),
|
|
61210
61641
|
exposureMode: ExposureModeSchema.optional(),
|
|
61211
61642
|
backlightMode: BacklightModeSchema.optional(),
|
|
61212
61643
|
lastFetchedAt: number()
|
|
@@ -61485,10 +61916,10 @@ var IntercomAbilitySchema = object({
|
|
|
61485
61916
|
/** Codecs accepted by firmware, in preference order. Driver-authored strings. */
|
|
61486
61917
|
codecs: array(string()),
|
|
61487
61918
|
/** Sample rate (Hz) the firmware expects. Reolink typical: 16000. */
|
|
61488
|
-
sampleRate: number(),
|
|
61919
|
+
sampleRate: number().meta(readingMeta("none")),
|
|
61489
61920
|
duplex: _enum(["half", "full"]),
|
|
61490
61921
|
/** Max in-flight audio backlog before drop (ms). Server uses this to bound latency. */
|
|
61491
|
-
maxBacklogMs: number()
|
|
61922
|
+
maxBacklogMs: number().meta(readingMeta("duration-ms"))
|
|
61492
61923
|
});
|
|
61493
61924
|
var IntercomStatusSchema = object({
|
|
61494
61925
|
/** True while a talk session is open. */
|
|
@@ -61715,13 +62146,13 @@ var LawnMowerControlStatusSchema = object({
|
|
|
61715
62146
|
activity: LawnMowerActivitySchema,
|
|
61716
62147
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
61717
62148
|
* reading. */
|
|
61718
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
62149
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61719
62150
|
/** 0..100 mowing-completion percentage of the current task, or null when no
|
|
61720
62151
|
* task is active / progress is unavailable. */
|
|
61721
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
62152
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61722
62153
|
/** Current device/event code (dynamic — mostly status, sometimes an error),
|
|
61723
62154
|
* or null when unknown. */
|
|
61724
|
-
currentCode: number().nullable(),
|
|
62155
|
+
currentCode: number().nullable().meta(readingMeta("none")),
|
|
61725
62156
|
/** Human label for {@link currentCode}, or null when undecodable. */
|
|
61726
62157
|
currentCodeLabel: string().nullable(),
|
|
61727
62158
|
/** Severity of {@link currentCode}. `error` (and often `warning`) warrants UI
|
|
@@ -62254,7 +62685,7 @@ var MediaPlayerStatusSchema = object({
|
|
|
62254
62685
|
state: MediaPlayerStateSchema,
|
|
62255
62686
|
/** Volume as 0..100 inclusive. Null when the device has no volume
|
|
62256
62687
|
* surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
|
|
62257
|
-
volumeLevel: number().min(0).max(100).nullable(),
|
|
62688
|
+
volumeLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
62258
62689
|
/** Mute toggle distinct from volume=0. Null when no mute surface.
|
|
62259
62690
|
* Pair with `DeviceFeature.MediaPlayerMute`. */
|
|
62260
62691
|
isMuted: boolean().nullable(),
|
|
@@ -62267,10 +62698,10 @@ var MediaPlayerStatusSchema = object({
|
|
|
62267
62698
|
currentMedia: MediaInfoSchema.nullable(),
|
|
62268
62699
|
/** Current playback position in ms. Null when not seekable or
|
|
62269
62700
|
* nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
|
|
62270
|
-
positionMs: number().int().nonnegative().nullable(),
|
|
62701
|
+
positionMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
62271
62702
|
/** Total duration of the current media in ms. Null when unknown
|
|
62272
62703
|
* (live stream) or nothing is playing. */
|
|
62273
|
-
durationMs: number().int().nonnegative().nullable(),
|
|
62704
|
+
durationMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
62274
62705
|
/** Shuffle toggle. Null when no shuffle surface.
|
|
62275
62706
|
* Pair with `DeviceFeature.MediaPlayerShuffle`. */
|
|
62276
62707
|
shuffle: boolean().nullable(),
|
|
@@ -62579,7 +63010,7 @@ var motionCustomize = {
|
|
|
62579
63010
|
eventName: "onMotionChanged"
|
|
62580
63011
|
},
|
|
62581
63012
|
deviceTypes: [DeviceType.Camera],
|
|
62582
|
-
apply: "
|
|
63013
|
+
apply: "add",
|
|
62583
63014
|
applyAuthority: {
|
|
62584
63015
|
kind: "camera-sensors",
|
|
62585
63016
|
timeoutField: "motionCooldownMs"
|
|
@@ -62651,7 +63082,7 @@ var MotionStatusSchema = object({
|
|
|
62651
63082
|
* it, every provider seeded it at boot, and every session left it
|
|
62652
63083
|
* `detected: true` after its detach.
|
|
62653
63084
|
*/
|
|
62654
|
-
autoClearAfterMs: number().nullable()
|
|
63085
|
+
autoClearAfterMs: number().nullable().meta(readingMeta("duration-ms"))
|
|
62655
63086
|
});
|
|
62656
63087
|
/**
|
|
62657
63088
|
* Payload of `motion.onMotionChanged` event + the corresponding bus
|
|
@@ -62688,12 +63119,18 @@ var motionCapability = {
|
|
|
62688
63119
|
methods: {
|
|
62689
63120
|
/**
|
|
62690
63121
|
* Pull the current motion state synchronously. Convenience shortcut
|
|
62691
|
-
* for consumers that don't need the full status object
|
|
62692
|
-
*
|
|
62693
|
-
* `getStatus` once the auto-injected status surface lands in every
|
|
62694
|
-
* consumer.
|
|
63122
|
+
* for consumers that don't need the full status object. A composed
|
|
63123
|
+
* group answers from its slice (D944): unknown throws, it is not off.
|
|
62695
63124
|
*/
|
|
62696
63125
|
isDetected: method(object({ deviceId: number() }), boolean()) },
|
|
63126
|
+
/**
|
|
63127
|
+
* A composed motion group serves `isDetected` from `detected` (D944).
|
|
63128
|
+
* Without this the cap stays uncomposable (`has-commands`).
|
|
63129
|
+
*/
|
|
63130
|
+
composedMethods: { isDetected: {
|
|
63131
|
+
kind: "slice",
|
|
63132
|
+
field: "detected"
|
|
63133
|
+
} },
|
|
62697
63134
|
events: {
|
|
62698
63135
|
/**
|
|
62699
63136
|
* Fires every time the runner transitions a camera between
|
|
@@ -62833,7 +63270,7 @@ var MotionZoneRegionSchema = object({
|
|
|
62833
63270
|
* the grid region(s). */
|
|
62834
63271
|
var MotionZoneStatusSchema = object({
|
|
62835
63272
|
enabled: boolean(),
|
|
62836
|
-
sensitivity: number(),
|
|
63273
|
+
sensitivity: number().meta(readingMeta("none")),
|
|
62837
63274
|
/** Grid region(s). Today exactly one `grid` shape. */
|
|
62838
63275
|
regions: array(MotionZoneRegionSchema),
|
|
62839
63276
|
lastFetchedAt: number()
|
|
@@ -63203,7 +63640,7 @@ var NavigationStatusSchema = object({
|
|
|
63203
63640
|
following: boolean(),
|
|
63204
63641
|
flash: boolean(),
|
|
63205
63642
|
lightMode: NavigationLightModeSchema,
|
|
63206
|
-
lightLevel: number().min(40).max(100),
|
|
63643
|
+
lightLevel: number().min(40).max(100).meta(readingMeta("none")),
|
|
63207
63644
|
/** Ms epoch when the slice was last updated. */
|
|
63208
63645
|
lastChangedAt: number()
|
|
63209
63646
|
});
|
|
@@ -63337,13 +63774,13 @@ var NetworkLinkStatusSchema = object({
|
|
|
63337
63774
|
* one whose reading has not landed must not be drawn at 0 %. Consumers
|
|
63338
63775
|
* SKIP a null rather than coerce it.
|
|
63339
63776
|
*/
|
|
63340
|
-
signalPercent: number().min(0).max(100).nullable(),
|
|
63777
|
+
signalPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
63341
63778
|
/** Raw received signal strength in dBm, when the firmware reports one. */
|
|
63342
|
-
rssiDbm: number().optional(),
|
|
63779
|
+
rssiDbm: number().optional().meta(readingMeta("signal-level")),
|
|
63343
63780
|
/** Network name of a wireless link, when the firmware reports it. */
|
|
63344
63781
|
ssid: string().optional(),
|
|
63345
63782
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
63346
|
-
lastUpdated: number()
|
|
63783
|
+
lastUpdated: number().meta(readingMeta("none"))
|
|
63347
63784
|
});
|
|
63348
63785
|
/** The slice a provider seeds before its first read: nothing is known yet. */
|
|
63349
63786
|
var NETWORK_LINK_UNKNOWN = {
|
|
@@ -63748,7 +64185,7 @@ var NotifierStatusSchema = object({
|
|
|
63748
64185
|
lastError: string().nullable(),
|
|
63749
64186
|
/** Number of deliveries currently buffered server-side (rate-limited
|
|
63750
64187
|
* notifiers may queue). 0 when the provider sends synchronously. */
|
|
63751
|
-
queueDepth: number().int().nonnegative(),
|
|
64188
|
+
queueDepth: number().int().nonnegative().meta(readingMeta("count")),
|
|
63752
64189
|
/** Per-feature capability matrix — authoritative source for the
|
|
63753
64190
|
* compose-form field gating. */
|
|
63754
64191
|
supports: NotifierSupportsSchema
|
|
@@ -63840,11 +64277,9 @@ onSent: { data: object({
|
|
|
63840
64277
|
* cap fits (HA `sensor` whose `device_class` we don't have a typed cap
|
|
63841
64278
|
* for: water flow, distance, weight, frequency, signal strength, …).
|
|
63842
64279
|
*
|
|
63843
|
-
* The
|
|
63844
|
-
*
|
|
63845
|
-
*
|
|
63846
|
-
* The UI reads them directly from the slice — they are the single source
|
|
63847
|
-
* of truth for generic numeric rendering and do NOT live on `sourceInfo`.
|
|
64280
|
+
* The quantity is not on this slice. It is chosen when the device is
|
|
64281
|
+
* adopted and stored once on `SourceInfo.quantity` (D944). `value` is in
|
|
64282
|
+
* that quantity's base unit. `null` is a refused sample (D393).
|
|
63848
64283
|
*
|
|
63849
64284
|
* Prefer the typed alternatives (`temperature-sensor`, `humidity-sensor`,
|
|
63850
64285
|
* `ambient-light-sensor`, `pressure-sensor`, `power-meter`,
|
|
@@ -63853,15 +64288,8 @@ onSent: { data: object({
|
|
|
63853
64288
|
* numeric values land here.
|
|
63854
64289
|
*/
|
|
63855
64290
|
var NumericSensorStatusSchema = object({
|
|
63856
|
-
|
|
63857
|
-
|
|
63858
|
-
* Populated live from the upstream source on each state push.
|
|
63859
|
-
* Absent for unitless sensors. */
|
|
63860
|
-
unit: string().optional(),
|
|
63861
|
-
/** Suggested decimal places for numeric display.
|
|
63862
|
-
* Populated live from the upstream source when provided.
|
|
63863
|
-
* Falls back to auto-formatting when absent. */
|
|
63864
|
-
precision: number().int().min(0).max(10).optional(),
|
|
64291
|
+
/** Reading in the device quantity's base unit. `null` when refused (D393). */
|
|
64292
|
+
value: number().nullable().meta(readingMeta("device")),
|
|
63865
64293
|
/** Ms epoch when the slice was last updated. */
|
|
63866
64294
|
lastFetchedAt: number()
|
|
63867
64295
|
});
|
|
@@ -63885,11 +64313,11 @@ var numericSensorCapability = {
|
|
|
63885
64313
|
*/
|
|
63886
64314
|
durability: "restored",
|
|
63887
64315
|
/**
|
|
63888
|
-
* History (D850): recorded series. The unit is
|
|
64316
|
+
* History (D850): recorded series. The unit is the device quantity's base,
|
|
64317
|
+
* resolved when the series is read — the cap has no single unit.
|
|
63889
64318
|
*/
|
|
63890
64319
|
history: { fields: { value: {
|
|
63891
64320
|
kind: "gauge",
|
|
63892
|
-
unitFrom: "unit",
|
|
63893
64321
|
minIntervalMs: 3e4
|
|
63894
64322
|
} } },
|
|
63895
64323
|
/** Clock fields: written, but excluded from the compare that decides
|
|
@@ -64227,23 +64655,26 @@ var PetFeederStatusSchema = object({
|
|
|
64227
64655
|
/** Food currently in the bowl (grams). Null when the device has not
|
|
64228
64656
|
* reported a reading yet. On dual-hopper models this is the combined
|
|
64229
64657
|
* bowl reading; per-hopper levels live in `food1`/`food2`. */
|
|
64230
|
-
foodLevel: number().nullable(),
|
|
64658
|
+
foodLevel: number().nullable().meta(readingMeta("none")),
|
|
64231
64659
|
/** Hopper-1 food level (grams) on dual-hopper feeders; null on
|
|
64232
64660
|
* single-hopper models. */
|
|
64233
|
-
food1: number().nullable(),
|
|
64661
|
+
food1: number().nullable().meta(readingMeta("none")),
|
|
64234
64662
|
/** Hopper-2 food level (grams) on dual-hopper feeders; null on
|
|
64235
64663
|
* single-hopper models. */
|
|
64236
|
-
food2: number().nullable(),
|
|
64664
|
+
food2: number().nullable().meta(readingMeta("none")),
|
|
64237
64665
|
/** Derived low-food flag — mirrors the HA `food_level` binary_sensor
|
|
64238
64666
|
* (`device_class: problem`, on = low). True when the bowl is empty /
|
|
64239
64667
|
* below the feeder's low threshold. */
|
|
64240
64668
|
lowFood: boolean(),
|
|
64241
64669
|
/** Battery charge 0..100 (%). Null on mains-powered models or when the
|
|
64242
64670
|
* device has no battery reading. */
|
|
64243
|
-
batteryPower: number().min(0).max(100).nullable(),
|
|
64244
|
-
/**
|
|
64245
|
-
*
|
|
64246
|
-
|
|
64671
|
+
batteryPower: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
64672
|
+
/**
|
|
64673
|
+
* Desiccant life remaining, stored in seconds (duration base, D944).
|
|
64674
|
+
* Providers convert from the days the feeder reports. Null when the
|
|
64675
|
+
* model has no desiccant sensor.
|
|
64676
|
+
*/
|
|
64677
|
+
desiccantLeftDays: number().nullable().meta(readingMeta("duration")),
|
|
64247
64678
|
/** True while a feed is in progress. */
|
|
64248
64679
|
feeding: boolean(),
|
|
64249
64680
|
/** Decoded connectivity / power status (HA petkit device-status enum).
|
|
@@ -64254,7 +64685,7 @@ var PetFeederStatusSchema = object({
|
|
|
64254
64685
|
* with `errorCode` for consumers that want the raw integer. */
|
|
64255
64686
|
error: string().nullable(),
|
|
64256
64687
|
/** Raw device error code (0 / null = no error). */
|
|
64257
|
-
errorCode: number().nullable(),
|
|
64688
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
64258
64689
|
/** True for D4S/D4SH dual-hopper hardware — gates the per-hopper UI. */
|
|
64259
64690
|
isDualHopper: boolean(),
|
|
64260
64691
|
/** Child-lock (manual-lock) setting — buttons on the unit are disabled. */
|
|
@@ -64264,7 +64695,7 @@ var PetFeederStatusSchema = object({
|
|
|
64264
64695
|
/** Play a chime when dispensing. */
|
|
64265
64696
|
feedSound: boolean(),
|
|
64266
64697
|
/** Speaker / prompt volume level (device-scaled integer). */
|
|
64267
|
-
volume: number(),
|
|
64698
|
+
volume: number().meta(readingMeta("none")),
|
|
64268
64699
|
/** Ms epoch when the slice was last refreshed from the cloud. */
|
|
64269
64700
|
lastFetchedAt: number()
|
|
64270
64701
|
});
|
|
@@ -64383,7 +64814,7 @@ var petFeederCapability = {
|
|
|
64383
64814
|
},
|
|
64384
64815
|
desiccantLeftDays: {
|
|
64385
64816
|
kind: "gauge",
|
|
64386
|
-
unit: "
|
|
64817
|
+
unit: "s"
|
|
64387
64818
|
}
|
|
64388
64819
|
} }
|
|
64389
64820
|
};
|
|
@@ -64784,36 +65215,19 @@ method(_void(), PlatformCapabilitiesSchema), method(_void(), HardwareInfoSchema)
|
|
|
64784
65215
|
*/
|
|
64785
65216
|
var PowerMeterStatusSchema = object({
|
|
64786
65217
|
/** Instantaneous power draw in watts. */
|
|
64787
|
-
watts: number().optional().meta({
|
|
64788
|
-
unit: "W",
|
|
64789
|
-
label: "Power"
|
|
64790
|
-
}),
|
|
65218
|
+
watts: number().optional().meta(readingMeta("power", { label: "Power" })),
|
|
64791
65219
|
/** Cumulative energy in kilowatt-hours since the meter was reset. */
|
|
64792
|
-
kwhTotal: number().optional().meta({
|
|
64793
|
-
unit: "kWh",
|
|
64794
|
-
label: "Energy"
|
|
64795
|
-
}),
|
|
65220
|
+
kwhTotal: number().optional().meta(readingMeta("energy", { label: "Energy" })),
|
|
64796
65221
|
/** Voltage in volts. */
|
|
64797
|
-
volts: number().optional(),
|
|
65222
|
+
volts: number().optional().meta(readingMeta("voltage")),
|
|
64798
65223
|
/** Current in amperes. */
|
|
64799
|
-
amps: number().optional(),
|
|
64800
|
-
/** Apparent power in volt-amperes
|
|
64801
|
-
va: number().optional(),
|
|
65224
|
+
amps: number().optional().meta(readingMeta("current")),
|
|
65225
|
+
/** Apparent power in volt-amperes. */
|
|
65226
|
+
va: number().optional().meta(readingMeta("apparent-power")),
|
|
64802
65227
|
/** Power factor (0..1) if reported. */
|
|
64803
|
-
powerFactor: number().min(0).max(1).optional(),
|
|
65228
|
+
powerFactor: number().min(0).max(1).optional().meta(readingMeta("ratio")),
|
|
64804
65229
|
/** Ms epoch when the slice was last updated. */
|
|
64805
|
-
lastFetchedAt: number()
|
|
64806
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
64807
|
-
* `attributes.unit_of_measurement` → 'V' / 'A' / 'W' / 'kW' / 'kWh').
|
|
64808
|
-
* Each upstream `sensor.*` entity surfaces ONE device_class, so one
|
|
64809
|
-
* unit per slice is unambiguous. The UI prefers this over the role's
|
|
64810
|
-
* canonical unit so a 'kW' / 'Wh' feed renders verbatim. */
|
|
64811
|
-
unit: string().optional(),
|
|
64812
|
-
/** Suggested decimal places for numeric display.
|
|
64813
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
64814
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
64815
|
-
* auto-formatting when absent. */
|
|
64816
|
-
precision: number().int().min(0).max(10).optional()
|
|
65230
|
+
lastFetchedAt: number()
|
|
64817
65231
|
});
|
|
64818
65232
|
var powerMeterCapability = {
|
|
64819
65233
|
name: "power-meter",
|
|
@@ -64877,12 +65291,7 @@ var powerMeterCapability = {
|
|
|
64877
65291
|
} },
|
|
64878
65292
|
/** Clock fields: written, but excluded from the compare that decides
|
|
64879
65293
|
* whether persisting is worth a SQLite commit. */
|
|
64880
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
64881
|
-
customize: {
|
|
64882
|
-
version: 1,
|
|
64883
|
-
advanced: "derive",
|
|
64884
|
-
targets: []
|
|
64885
|
-
}
|
|
65294
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
64886
65295
|
};
|
|
64887
65296
|
/**
|
|
64888
65297
|
* Presence cap. Models HA `person.*` and `device_tracker.*` entities
|
|
@@ -64902,11 +65311,11 @@ var powerMeterCapability = {
|
|
|
64902
65311
|
*/
|
|
64903
65312
|
var GpsLocationSchema = object({
|
|
64904
65313
|
/** Latitude in decimal degrees, -90..90. */
|
|
64905
|
-
latitude: number().min(-90).max(90),
|
|
65314
|
+
latitude: number().min(-90).max(90).meta(readingMeta("angle")),
|
|
64906
65315
|
/** Longitude in decimal degrees, -180..180. */
|
|
64907
|
-
longitude: number().min(-180).max(180),
|
|
65316
|
+
longitude: number().min(-180).max(180).meta(readingMeta("angle")),
|
|
64908
65317
|
/** Reported accuracy in meters (lower = better). */
|
|
64909
|
-
accuracyMeters: number().nonnegative()
|
|
65318
|
+
accuracyMeters: number().nonnegative().meta(readingMeta("length"))
|
|
64910
65319
|
});
|
|
64911
65320
|
var PresenceStatusSchema = object({
|
|
64912
65321
|
/** `home` / `not_home` / any user-defined zone name. */
|
|
@@ -64918,7 +65327,7 @@ var PresenceStatusSchema = object({
|
|
|
64918
65327
|
gps: GpsLocationSchema.nullable(),
|
|
64919
65328
|
/** Optional battery level of the tracking device (0..100). Null
|
|
64920
65329
|
* when not reported. */
|
|
64921
|
-
batteryPercent: number().min(0).max(100).nullable(),
|
|
65330
|
+
batteryPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
64922
65331
|
/** Ms epoch when the slice was last updated. */
|
|
64923
65332
|
lastChangedAt: number()
|
|
64924
65333
|
});
|
|
@@ -64968,19 +65377,10 @@ var presenceCapability = {
|
|
|
64968
65377
|
* `sourceInfo`.
|
|
64969
65378
|
*/
|
|
64970
65379
|
var PressureSensorStatusSchema = object({
|
|
64971
|
-
/** Current pressure in hPa. */
|
|
64972
|
-
hpa: number(),
|
|
65380
|
+
/** Current pressure in hPa. `null` when the sample was refused (D393). */
|
|
65381
|
+
hpa: number().nullable().meta(readingMeta("pressure", { precision: 0 })),
|
|
64973
65382
|
/** Ms epoch when the slice was last updated. */
|
|
64974
|
-
lastFetchedAt: number()
|
|
64975
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
64976
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
64977
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
64978
|
-
unit: string().optional(),
|
|
64979
|
-
/** Suggested decimal places for numeric display.
|
|
64980
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
64981
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
64982
|
-
* auto-formatting when absent. */
|
|
64983
|
-
precision: number().int().min(0).max(10).optional()
|
|
65383
|
+
lastFetchedAt: number()
|
|
64984
65384
|
});
|
|
64985
65385
|
var pressureSensorCapability = {
|
|
64986
65386
|
name: "pressure-sensor",
|
|
@@ -65506,8 +65906,8 @@ var ptzCapability = {
|
|
|
65506
65906
|
};
|
|
65507
65907
|
var PtzAutotrackSettingsSchema = object({
|
|
65508
65908
|
targetType: string().describe("Vendor target string (people/vehicle/pet); empty = camera default"),
|
|
65509
|
-
stopDelaySeconds: number().int().min(0).max(300),
|
|
65510
|
-
disappearDelaySeconds: number().int().min(0).max(300)
|
|
65909
|
+
stopDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration")),
|
|
65910
|
+
disappearDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration"))
|
|
65511
65911
|
});
|
|
65512
65912
|
/**
|
|
65513
65913
|
* One option the camera advertises as a valid `targetType`. Drivers
|
|
@@ -65661,7 +66061,7 @@ var RunningStateStatusSchema = object({
|
|
|
65661
66061
|
/** null = unknown — never coerced to false (D393). */
|
|
65662
66062
|
running: boolean().nullable(),
|
|
65663
66063
|
/** Epoch ms the current boolean began; null while `running` is null. */
|
|
65664
|
-
since: number().nullable(),
|
|
66064
|
+
since: number().nullable().meta(readingMeta("none")),
|
|
65665
66065
|
source: RunningStateSourceSchema.meta({ label: "Source" }),
|
|
65666
66066
|
phase: string().nullable(),
|
|
65667
66067
|
/** null until a reading has been published (D393). */
|
|
@@ -65676,7 +66076,6 @@ var RUNNING_DEVICE_TYPES = Object.values(DeviceType);
|
|
|
65676
66076
|
/** Generic Customize target for the running boolean (D936). */
|
|
65677
66077
|
var runningCustomize = {
|
|
65678
66078
|
version: 1,
|
|
65679
|
-
advanced: "derive",
|
|
65680
66079
|
targets: [{
|
|
65681
66080
|
id: "running",
|
|
65682
66081
|
cardinality: "scalar",
|
|
@@ -65696,7 +66095,7 @@ var runningCustomize = {
|
|
|
65696
66095
|
DeviceType.Thermostat,
|
|
65697
66096
|
DeviceType.PetFeeder
|
|
65698
66097
|
],
|
|
65699
|
-
apply: "add
|
|
66098
|
+
apply: "add",
|
|
65700
66099
|
path: "running",
|
|
65701
66100
|
sources: [
|
|
65702
66101
|
{
|
|
@@ -66989,9 +67388,9 @@ var RecordTriggerSchema = _enum([
|
|
|
66989
67388
|
*/
|
|
66990
67389
|
var RecordWindowSchema = object({
|
|
66991
67390
|
trigger: RecordTriggerSchema,
|
|
66992
|
-
day: number().int().min(0).max(6),
|
|
66993
|
-
startMinute: number().int().min(0).max(1439),
|
|
66994
|
-
endMinute: number().int().min(1).max(1440)
|
|
67391
|
+
day: number().int().min(0).max(6).meta(readingMeta("none")),
|
|
67392
|
+
startMinute: number().int().min(0).max(1439).meta(readingMeta("none")),
|
|
67393
|
+
endMinute: number().int().min(1).max(1440).meta(readingMeta("none"))
|
|
66995
67394
|
});
|
|
66996
67395
|
/** Status of one physical volume, as the camera itself describes it. */
|
|
66997
67396
|
var OnboardStorageVolumeSchema = object({
|
|
@@ -67067,10 +67466,10 @@ var RecordingOnboardStatusSchema = object({
|
|
|
67067
67466
|
/** Master "record to the card at all" switch. */
|
|
67068
67467
|
enabled: boolean().nullable(),
|
|
67069
67468
|
overwriteWhenFull: boolean().nullable(),
|
|
67070
|
-
preRecordSec: number().nullable(),
|
|
67071
|
-
postRecordSec: number().nullable(),
|
|
67469
|
+
preRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
67470
|
+
postRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
67072
67471
|
/** Length of one recorded file, in minutes. */
|
|
67073
|
-
segmentMinutes: number().nullable(),
|
|
67472
|
+
segmentMinutes: number().nullable().meta(readingMeta("none")),
|
|
67074
67473
|
/** The primary track's weekly windows, flattened. */
|
|
67075
67474
|
windows: array(RecordWindowSchema),
|
|
67076
67475
|
/**
|
|
@@ -67086,7 +67485,7 @@ var RecordingOnboardStatusSchema = object({
|
|
|
67086
67485
|
* provider reporting a non-zero count also reports the schedule as not
|
|
67087
67486
|
* writable.
|
|
67088
67487
|
*/
|
|
67089
|
-
unreadableWindows: number(),
|
|
67488
|
+
unreadableWindows: number().meta(readingMeta("count")),
|
|
67090
67489
|
/**
|
|
67091
67490
|
* The camera is scheduled to record and has NO usable storage.
|
|
67092
67491
|
*
|
|
@@ -68096,7 +68495,7 @@ var CamStreamDescriptorSchema = object({
|
|
|
68096
68495
|
url: string().optional(),
|
|
68097
68496
|
codec: string().optional(),
|
|
68098
68497
|
resolution: CamStreamResolutionSchema.optional(),
|
|
68099
|
-
fps: number().positive().optional(),
|
|
68498
|
+
fps: number().positive().optional().meta(readingMeta("rate")),
|
|
68100
68499
|
label: string().optional(),
|
|
68101
68500
|
/** Device-level features (e.g. `battery-operated`) — drives broker policy. */
|
|
68102
68501
|
deviceFeatures: array(string()).optional(),
|
|
@@ -68183,18 +68582,18 @@ var StreamProfileSchema = _enum([
|
|
|
68183
68582
|
]);
|
|
68184
68583
|
/** The current encoding config of one stream profile. */
|
|
68185
68584
|
var StreamProfileConfigSchema = object({
|
|
68186
|
-
width: number(),
|
|
68187
|
-
height: number(),
|
|
68585
|
+
width: number().meta(readingMeta("none")),
|
|
68586
|
+
height: number().meta(readingMeta("none")),
|
|
68188
68587
|
codec: _enum(["h264", "h265"]),
|
|
68189
|
-
framerate: number(),
|
|
68190
|
-
bitrate: number(),
|
|
68588
|
+
framerate: number().meta(readingMeta("rate")),
|
|
68589
|
+
bitrate: number().meta(readingMeta("bitrate")),
|
|
68191
68590
|
bitrateMode: _enum(["vbr", "cbr"]).optional(),
|
|
68192
68591
|
encoderProfile: _enum([
|
|
68193
68592
|
"high",
|
|
68194
68593
|
"main",
|
|
68195
68594
|
"baseline"
|
|
68196
68595
|
]).optional(),
|
|
68197
|
-
gop: number().optional(),
|
|
68596
|
+
gop: number().optional().meta(readingMeta("none")),
|
|
68198
68597
|
/**
|
|
68199
68598
|
* Whether THIS profile currently carries an audio track. READ-ONLY here.
|
|
68200
68599
|
*
|
|
@@ -68613,12 +69012,7 @@ var switchCapability = {
|
|
|
68613
69012
|
label: "On",
|
|
68614
69013
|
kind: "boolean"
|
|
68615
69014
|
}
|
|
68616
|
-
}] }
|
|
68617
|
-
customize: {
|
|
68618
|
-
version: 1,
|
|
68619
|
-
advanced: "derive",
|
|
68620
|
-
targets: []
|
|
68621
|
-
}
|
|
69015
|
+
}] }
|
|
68622
69016
|
};
|
|
68623
69017
|
/** C0 controls, DEL and the C1 range: none of them belongs in a name. */
|
|
68624
69018
|
function hasControlCharacter(value) {
|
|
@@ -69201,35 +69595,21 @@ var tamperCapability = {
|
|
|
69201
69595
|
* entries with `device_class: temperature` and any future native
|
|
69202
69596
|
* thermometer.
|
|
69203
69597
|
*
|
|
69204
|
-
*
|
|
69205
|
-
*
|
|
69206
|
-
* (climate-control's `currentTemp`, energy analytics) can compose
|
|
69207
|
-
* without per-source unit fixups. The canonical display unit (`°C`) is
|
|
69208
|
-
* a descriptor constant in the UI (ROLE_DESCRIPTOR), not stored in
|
|
69209
|
-
* `sourceInfo`.
|
|
69598
|
+
* The number is Celsius (D944). Providers convert on ingest. A failed
|
|
69599
|
+
* conversion is `null`, never a guess. Display unit is a read-time preference.
|
|
69210
69600
|
*
|
|
69211
69601
|
* Status `lastFetchedAt` lets staleness-aware consumers detect a
|
|
69212
69602
|
* frozen feed (provider hung) distinct from a "temperature hasn't
|
|
69213
69603
|
* changed" steady state.
|
|
69214
69604
|
*/
|
|
69215
69605
|
var TemperatureSensorStatusSchema = object({
|
|
69216
|
-
/** Current temperature in Celsius. */
|
|
69217
|
-
celsius: number().meta({
|
|
69218
|
-
|
|
69606
|
+
/** Current temperature in Celsius. `null` when the sample was refused (D393). */
|
|
69607
|
+
celsius: number().nullable().meta(readingMeta("temperature", {
|
|
69608
|
+
precision: 1,
|
|
69219
69609
|
label: "Temperature"
|
|
69220
|
-
}),
|
|
69610
|
+
})),
|
|
69221
69611
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
69222
|
-
lastFetchedAt: number()
|
|
69223
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
69224
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
69225
|
-
* role's canonical unit, so a Fahrenheit feed renders '°F' not '°C'.
|
|
69226
|
-
* Absent → the UI falls back to the role's canonical unit. */
|
|
69227
|
-
unit: string().optional(),
|
|
69228
|
-
/** Suggested decimal places for numeric display.
|
|
69229
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
69230
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
69231
|
-
* auto-formatting when absent. */
|
|
69232
|
-
precision: number().int().min(0).max(10).optional()
|
|
69612
|
+
lastFetchedAt: number()
|
|
69233
69613
|
});
|
|
69234
69614
|
var temperatureSensorCapability = {
|
|
69235
69615
|
name: "temperature-sensor",
|
|
@@ -69260,12 +69640,7 @@ var temperatureSensorCapability = {
|
|
|
69260
69640
|
} } },
|
|
69261
69641
|
/** Clock fields: written, but excluded from the compare that decides
|
|
69262
69642
|
* whether persisting is worth a SQLite commit. */
|
|
69263
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
69264
|
-
customize: {
|
|
69265
|
-
version: 1,
|
|
69266
|
-
advanced: "derive",
|
|
69267
|
-
targets: []
|
|
69268
|
-
}
|
|
69643
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
69269
69644
|
};
|
|
69270
69645
|
/**
|
|
69271
69646
|
* toast — system-scoped singleton capability that streams toast
|
|
@@ -69548,16 +69923,16 @@ var VacuumControlStatusSchema = object({
|
|
|
69548
69923
|
]),
|
|
69549
69924
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
69550
69925
|
* reading. */
|
|
69551
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
69926
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
69552
69927
|
/** Current fan-speed token (provider-verbatim). Null when unknown or
|
|
69553
69928
|
* the vacuum has no speed control. */
|
|
69554
69929
|
fanSpeed: string().nullable(),
|
|
69555
69930
|
/** Speed tokens the hardware accepts — drives the UI selector. */
|
|
69556
69931
|
availableFanSpeeds: array(string()),
|
|
69557
69932
|
/** 0..100 cleaning-completion percentage of the current task, or null. */
|
|
69558
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
69933
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
69559
69934
|
/** Current error code (0 / null = no error). */
|
|
69560
|
-
errorCode: number().nullable(),
|
|
69935
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
69561
69936
|
/** Human label for {@link errorCode}, or null when none / undecodable. */
|
|
69562
69937
|
errorLabel: string().nullable(),
|
|
69563
69938
|
/** Ms epoch when the slice was last updated. */
|
|
@@ -69635,7 +70010,7 @@ var ValveStatusSchema = object({
|
|
|
69635
70010
|
]),
|
|
69636
70011
|
/** 0 = fully closed, 100 = fully open. Null when the device has no
|
|
69637
70012
|
* intermediate position surface. */
|
|
69638
|
-
position: number().min(0).max(100).nullable(),
|
|
70013
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
69639
70014
|
/** Ms epoch when the slice was last updated. */
|
|
69640
70015
|
lastChangedAt: number()
|
|
69641
70016
|
});
|
|
@@ -69743,9 +70118,9 @@ var vibrationCapability = {
|
|
|
69743
70118
|
*/
|
|
69744
70119
|
var WaterHeaterStatusSchema = object({
|
|
69745
70120
|
/** Current measured temperature. Null when not reported. */
|
|
69746
|
-
currentTemp: number().nullable(),
|
|
70121
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
69747
70122
|
/** Target temperature setpoint. Null when no setpoint surface. */
|
|
69748
|
-
targetTemp: number().nullable(),
|
|
70123
|
+
targetTemp: number().nullable().meta(readingMeta("temperature")),
|
|
69749
70124
|
/** Active operation mode = HA `state` (`eco` / `electric` / `gas` /
|
|
69750
70125
|
* `heat_pump` / `high_demand` / `performance` / `off`). Null when the
|
|
69751
70126
|
* device reports an unknown state. */
|
|
@@ -69756,9 +70131,9 @@ var WaterHeaterStatusSchema = object({
|
|
|
69756
70131
|
* has no away surface. */
|
|
69757
70132
|
away: boolean().nullable(),
|
|
69758
70133
|
/** HA `min_temp` attribute. Null when not reported. */
|
|
69759
|
-
minTemp: number().nullable(),
|
|
70134
|
+
minTemp: number().nullable().meta(readingMeta("temperature")),
|
|
69760
70135
|
/** HA `max_temp` attribute. Null when not reported. */
|
|
69761
|
-
maxTemp: number().nullable(),
|
|
70136
|
+
maxTemp: number().nullable().meta(readingMeta("temperature")),
|
|
69762
70137
|
/** Ms epoch when the slice was last updated. */
|
|
69763
70138
|
lastChangedAt: number()
|
|
69764
70139
|
});
|
|
@@ -69843,25 +70218,18 @@ var waterHeaterCapability = {
|
|
|
69843
70218
|
* Forecast deferred — current conditions only for v1.
|
|
69844
70219
|
*/
|
|
69845
70220
|
var WeatherStatusSchema = object({
|
|
69846
|
-
/** Verbatim
|
|
69847
|
-
* when no condition has been reported yet. */
|
|
70221
|
+
/** Verbatim condition state (`sunny`, `cloudy`, `rainy`, …). Null when none yet. */
|
|
69848
70222
|
condition: string().nullable(),
|
|
69849
|
-
/** Current temperature in
|
|
69850
|
-
temperature: number().nullable(),
|
|
69851
|
-
/** Temperature unit string (e.g. `°C` / `°F`). Null when not provided. */
|
|
69852
|
-
temperatureUnit: string().nullable(),
|
|
70223
|
+
/** Current temperature in Celsius. Null when not provided or refused. */
|
|
70224
|
+
temperature: number().nullable().meta(readingMeta("temperature", { precision: 1 })),
|
|
69853
70225
|
/** Relative humidity (0..100). Null when not provided. */
|
|
69854
|
-
humidity: number().min(0).max(100).nullable(),
|
|
69855
|
-
/** Barometric pressure in
|
|
69856
|
-
pressure: number().nullable(),
|
|
69857
|
-
/**
|
|
69858
|
-
|
|
69859
|
-
/** Wind speed in the reported unit. Null when not provided. */
|
|
69860
|
-
windSpeed: number().nullable(),
|
|
69861
|
-
/** Wind-speed unit string (e.g. `km/h` / `mph`). Null when not provided. */
|
|
69862
|
-
windSpeedUnit: string().nullable(),
|
|
70226
|
+
humidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
70227
|
+
/** Barometric pressure in hPa. Null when not provided or refused. */
|
|
70228
|
+
pressure: number().nullable().meta(readingMeta("pressure")),
|
|
70229
|
+
/** Wind speed in metres per second. Null when not provided or refused. */
|
|
70230
|
+
windSpeed: number().nullable().meta(readingMeta("speed")),
|
|
69863
70231
|
/** Wind bearing in degrees (0..360, meteorological). Null when not provided. */
|
|
69864
|
-
windBearing: number().nullable(),
|
|
70232
|
+
windBearing: number().nullable().meta(readingMeta("angle")),
|
|
69865
70233
|
/** Ms epoch when the slice was last updated. */
|
|
69866
70234
|
lastFetchedAt: number()
|
|
69867
70235
|
});
|
|
@@ -69889,12 +70257,12 @@ var weatherCapability = {
|
|
|
69889
70257
|
*/
|
|
69890
70258
|
durability: "session",
|
|
69891
70259
|
/**
|
|
69892
|
-
* History (D850): recorded series.
|
|
70260
|
+
* History (D850): recorded series. Numbers are the quantity base (D944).
|
|
69893
70261
|
*/
|
|
69894
70262
|
history: { fields: {
|
|
69895
70263
|
temperature: {
|
|
69896
70264
|
kind: "gauge",
|
|
69897
|
-
|
|
70265
|
+
unit: "°C",
|
|
69898
70266
|
deadband: .2
|
|
69899
70267
|
},
|
|
69900
70268
|
humidity: {
|
|
@@ -69904,12 +70272,12 @@ var weatherCapability = {
|
|
|
69904
70272
|
},
|
|
69905
70273
|
pressure: {
|
|
69906
70274
|
kind: "gauge",
|
|
69907
|
-
|
|
70275
|
+
unit: "hPa",
|
|
69908
70276
|
deadband: .5
|
|
69909
70277
|
},
|
|
69910
70278
|
windSpeed: {
|
|
69911
70279
|
kind: "gauge",
|
|
69912
|
-
|
|
70280
|
+
unit: "m/s",
|
|
69913
70281
|
deadband: .5
|
|
69914
70282
|
}
|
|
69915
70283
|
} }
|
|
@@ -71288,6 +71656,8 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
71288
71656
|
featureProbe: featureProbeCapability,
|
|
71289
71657
|
flood: floodCapability,
|
|
71290
71658
|
gas: gasCapability,
|
|
71659
|
+
groupCommands: groupCommandsCapability,
|
|
71660
|
+
groupStatus: groupStatusCapability,
|
|
71291
71661
|
heatingValve: heatingValveCapability,
|
|
71292
71662
|
humidifier: humidifierCapability,
|
|
71293
71663
|
humiditySensor: humiditySensorCapability,
|
|
@@ -72664,6 +73034,13 @@ Object.freeze({
|
|
|
72664
73034
|
access: "view",
|
|
72665
73035
|
role: "admin"
|
|
72666
73036
|
},
|
|
73037
|
+
"addons.getPackageDocs": {
|
|
73038
|
+
capName: "addons",
|
|
73039
|
+
capScope: "system",
|
|
73040
|
+
addonId: null,
|
|
73041
|
+
access: "view",
|
|
73042
|
+
role: "admin"
|
|
73043
|
+
},
|
|
72667
73044
|
"addons.getVersions": {
|
|
72668
73045
|
capName: "addons",
|
|
72669
73046
|
capScope: "system",
|
|
@@ -75772,6 +76149,20 @@ Object.freeze({
|
|
|
75772
76149
|
access: "view",
|
|
75773
76150
|
role: "viewer"
|
|
75774
76151
|
},
|
|
76152
|
+
"groupCommands.getStatus": {
|
|
76153
|
+
capName: "group-commands",
|
|
76154
|
+
capScope: "device",
|
|
76155
|
+
addonId: null,
|
|
76156
|
+
access: "view",
|
|
76157
|
+
role: "viewer"
|
|
76158
|
+
},
|
|
76159
|
+
"groupStatus.getStatus": {
|
|
76160
|
+
capName: "group-status",
|
|
76161
|
+
capScope: "device",
|
|
76162
|
+
addonId: null,
|
|
76163
|
+
access: "view",
|
|
76164
|
+
role: "viewer"
|
|
76165
|
+
},
|
|
75775
76166
|
"heatingValve.getStatus": {
|
|
75776
76167
|
capName: "heating-valve",
|
|
75777
76168
|
capScope: "device",
|
|
@@ -85594,6 +85985,37 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
85594
85985
|
icon: "flame"
|
|
85595
85986
|
}]
|
|
85596
85987
|
},
|
|
85988
|
+
"group-commands": {
|
|
85989
|
+
scope: "device",
|
|
85990
|
+
noun: t("Group command", "Comando di gruppo")
|
|
85991
|
+
},
|
|
85992
|
+
"group-status": {
|
|
85993
|
+
scope: "device",
|
|
85994
|
+
noun: t("Group", "Gruppo"),
|
|
85995
|
+
state: [
|
|
85996
|
+
{
|
|
85997
|
+
kind: "numeric",
|
|
85998
|
+
field: "included",
|
|
85999
|
+
quantity: t("the members reporting", "i membri che rispondono"),
|
|
86000
|
+
label: t("Reporting", "Rispondono"),
|
|
86001
|
+
icon: "users"
|
|
86002
|
+
},
|
|
86003
|
+
{
|
|
86004
|
+
kind: "numeric",
|
|
86005
|
+
field: "excluded",
|
|
86006
|
+
quantity: t("the members left out", "i membri esclusi"),
|
|
86007
|
+
label: t("Excluded", "Esclusi"),
|
|
86008
|
+
icon: "users"
|
|
86009
|
+
},
|
|
86010
|
+
{
|
|
86011
|
+
kind: "numeric",
|
|
86012
|
+
field: "total",
|
|
86013
|
+
quantity: t("the member count", "il numero di membri"),
|
|
86014
|
+
label: t("Members", "Membri"),
|
|
86015
|
+
icon: "sigma"
|
|
86016
|
+
}
|
|
86017
|
+
]
|
|
86018
|
+
},
|
|
85597
86019
|
"humidity-sensor": {
|
|
85598
86020
|
scope: "device",
|
|
85599
86021
|
noun: t("Humidity", "Umidità"),
|
|
@@ -85627,7 +86049,6 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
85627
86049
|
field: "value",
|
|
85628
86050
|
quantity: t("the reading", "il valore"),
|
|
85629
86051
|
label: t("Reading", "Valore"),
|
|
85630
|
-
unitField: "unit",
|
|
85631
86052
|
icon: "gauge"
|
|
85632
86053
|
}]
|
|
85633
86054
|
},
|
|
@@ -85763,7 +86184,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
85763
86184
|
field: "temperature",
|
|
85764
86185
|
quantity: t("the outdoor temperature", "la temperatura esterna"),
|
|
85765
86186
|
label: t("Temperature", "Temperatura"),
|
|
85766
|
-
|
|
86187
|
+
unit: "°C",
|
|
85767
86188
|
icon: "thermometer"
|
|
85768
86189
|
},
|
|
85769
86190
|
{
|
|
@@ -85779,7 +86200,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
85779
86200
|
field: "windSpeed",
|
|
85780
86201
|
quantity: t("the wind speed", "la velocità del vento"),
|
|
85781
86202
|
label: t("Wind", "Vento"),
|
|
85782
|
-
|
|
86203
|
+
unit: "m/s",
|
|
85783
86204
|
icon: "wind"
|
|
85784
86205
|
},
|
|
85785
86206
|
{
|
|
@@ -85787,7 +86208,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
85787
86208
|
field: "pressure",
|
|
85788
86209
|
quantity: t("the air pressure", "la pressione atmosferica"),
|
|
85789
86210
|
label: t("Pressure", "Pressione"),
|
|
85790
|
-
|
|
86211
|
+
unit: "hPa",
|
|
85791
86212
|
icon: "gauge"
|
|
85792
86213
|
}
|
|
85793
86214
|
]
|
|
@@ -87212,6 +87633,16 @@ Object.freeze({
|
|
|
87212
87633
|
form: "single",
|
|
87213
87634
|
optional: false
|
|
87214
87635
|
}],
|
|
87636
|
+
"groupCommands.getStatus": [{
|
|
87637
|
+
name: "deviceId",
|
|
87638
|
+
form: "single",
|
|
87639
|
+
optional: false
|
|
87640
|
+
}],
|
|
87641
|
+
"groupStatus.getStatus": [{
|
|
87642
|
+
name: "deviceId",
|
|
87643
|
+
form: "single",
|
|
87644
|
+
optional: false
|
|
87645
|
+
}],
|
|
87215
87646
|
"heatingValve.getStatus": [{
|
|
87216
87647
|
name: "deviceId",
|
|
87217
87648
|
form: "single",
|
|
@@ -89196,6 +89627,8 @@ new Map(Object.entries({
|
|
|
89196
89627
|
"detection-blind": "device-events",
|
|
89197
89628
|
"motion-noisy": "device-events",
|
|
89198
89629
|
"motion-calm": "device-events",
|
|
89630
|
+
"package-llm-silent": "device-events",
|
|
89631
|
+
"package-llm-answered": "device-events",
|
|
89199
89632
|
"recording-stalled": "device-events",
|
|
89200
89633
|
"recording-healthy": "device-events",
|
|
89201
89634
|
"recording-degraded": "device-events",
|
|
@@ -89279,6 +89712,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
|
|
|
89279
89712
|
label: "Motion without a subject",
|
|
89280
89713
|
kinds: ["motion-noisy", "motion-calm"]
|
|
89281
89714
|
},
|
|
89715
|
+
{
|
|
89716
|
+
id: "package-llm",
|
|
89717
|
+
family: "device-events",
|
|
89718
|
+
label: "Package confirm",
|
|
89719
|
+
kinds: ["package-llm-silent", "package-llm-answered"]
|
|
89720
|
+
},
|
|
89282
89721
|
{
|
|
89283
89722
|
id: "recording",
|
|
89284
89723
|
family: "device-events",
|
|
@@ -89460,6 +89899,8 @@ var DEVICE_EVENTS = [
|
|
|
89460
89899
|
"detection-blind",
|
|
89461
89900
|
"motion-noisy",
|
|
89462
89901
|
"motion-calm",
|
|
89902
|
+
"package-llm-silent",
|
|
89903
|
+
"package-llm-answered",
|
|
89463
89904
|
"recording-stalled",
|
|
89464
89905
|
"recording-healthy",
|
|
89465
89906
|
"recording-degraded",
|
|
@@ -89728,6 +90169,15 @@ new Map([
|
|
|
89728
90169
|
snapshotLabel: "Cameras with constant motion now",
|
|
89729
90170
|
snapshotSection: null
|
|
89730
90171
|
},
|
|
90172
|
+
{
|
|
90173
|
+
id: "package-llm-confirm",
|
|
90174
|
+
family: "device-events",
|
|
90175
|
+
label: "Package confirm (not answering / answering again)",
|
|
90176
|
+
bad: ["package-llm-silent"],
|
|
90177
|
+
recovery: ["package-llm-answered"],
|
|
90178
|
+
snapshotLabel: "Cameras whose package confirm is not answering",
|
|
90179
|
+
snapshotSection: null
|
|
90180
|
+
},
|
|
89731
90181
|
{
|
|
89732
90182
|
id: "recording-health",
|
|
89733
90183
|
family: "device-events",
|