@camstack/addon-provider-amcrest 0.2.160 → 0.2.161
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +20 -0
- package/dist/addon.js +959 -509
- package/dist/addon.mjs +959 -509
- package/package.json +4 -2
package/dist/addon.js
CHANGED
|
@@ -35,7 +35,7 @@ let node_stream_promises = require("node:stream/promises");
|
|
|
35
35
|
let node_child_process = require("node:child_process");
|
|
36
36
|
require("node:zlib");
|
|
37
37
|
let node_os = require("node:os");
|
|
38
|
-
//#region ../types/dist/event-category-
|
|
38
|
+
//#region ../types/dist/event-category-CT-hz5Rb.mjs
|
|
39
39
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
40
40
|
EventCategory["SystemBoot"] = "system.boot";
|
|
41
41
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -361,6 +361,14 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
361
361
|
/** The recovery edge of {@link PipelineMotionNoisy}: the motion fell back, or a detection arrived. */
|
|
362
362
|
EventCategory["PipelineMotionCalm"] = "pipeline.motion-calm";
|
|
363
363
|
/**
|
|
364
|
+
* A camera's package LLM confirm has failed closed three times in a row
|
|
365
|
+
* (D931, 2026-10-26). One edge per camera until
|
|
366
|
+
* {@link PipelinePackageLlmAnswered}.
|
|
367
|
+
*/
|
|
368
|
+
EventCategory["PipelinePackageLlmSilent"] = "pipeline.package-llm-silent";
|
|
369
|
+
/** The recovery edge of {@link PipelinePackageLlmSilent}: a confirm returned yes or no. */
|
|
370
|
+
EventCategory["PipelinePackageLlmAnswered"] = "pipeline.package-llm-answered";
|
|
371
|
+
/**
|
|
364
372
|
* Per-camera pipeline config was mutated by the orchestrator
|
|
365
373
|
* (a settings change via `setAgentInferenceDevices` /
|
|
366
374
|
* `setCameraStepToggle` / `setCameraStepSettings`). Orchestrator
|
|
@@ -5470,7 +5478,7 @@ var ZodIssueCode = {
|
|
|
5470
5478
|
var ZodFirstPartyTypeKind;
|
|
5471
5479
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5472
5480
|
//#endregion
|
|
5473
|
-
//#region ../types/dist/sleep-
|
|
5481
|
+
//#region ../types/dist/sleep-bykKrTgu.mjs
|
|
5474
5482
|
/**
|
|
5475
5483
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5476
5484
|
* window to float samples (D455).
|
|
@@ -8024,6 +8032,99 @@ var RecordKindDeclarationSchema = object({
|
|
|
8024
8032
|
}).strict();
|
|
8025
8033
|
/** The kind names: lower-case, dash separated, short enough for an index name. */
|
|
8026
8034
|
var RecordKindNameSchema = string().regex(/^[a-z][a-z0-9-]{0,47}$/);
|
|
8035
|
+
var READING_QUANTITIES = [
|
|
8036
|
+
"temperature",
|
|
8037
|
+
"pressure",
|
|
8038
|
+
"speed",
|
|
8039
|
+
"precipitation",
|
|
8040
|
+
"precipitation-rate",
|
|
8041
|
+
"length",
|
|
8042
|
+
"area",
|
|
8043
|
+
"illuminance",
|
|
8044
|
+
"irradiance",
|
|
8045
|
+
"power",
|
|
8046
|
+
"energy",
|
|
8047
|
+
"voltage",
|
|
8048
|
+
"current",
|
|
8049
|
+
"apparent-power",
|
|
8050
|
+
"humidity",
|
|
8051
|
+
"percentage",
|
|
8052
|
+
"concentration-volume",
|
|
8053
|
+
"concentration-mass",
|
|
8054
|
+
"concentration-ppb",
|
|
8055
|
+
"volume",
|
|
8056
|
+
"duration",
|
|
8057
|
+
"duration-ms",
|
|
8058
|
+
"information",
|
|
8059
|
+
"sound-level",
|
|
8060
|
+
"signal-level",
|
|
8061
|
+
"colour-temperature",
|
|
8062
|
+
"angle",
|
|
8063
|
+
"bitrate",
|
|
8064
|
+
"rate",
|
|
8065
|
+
"mass",
|
|
8066
|
+
"index",
|
|
8067
|
+
"ratio",
|
|
8068
|
+
"count",
|
|
8069
|
+
"none",
|
|
8070
|
+
"device"
|
|
8071
|
+
];
|
|
8072
|
+
var ReadingQuantitySchema = _enum(READING_QUANTITIES);
|
|
8073
|
+
new Set(READING_QUANTITIES);
|
|
8074
|
+
/**
|
|
8075
|
+
* Stored unit symbol for a quantity. `none` means the number is dimensionless
|
|
8076
|
+
* (or an index / ratio / count). `device` means the cap has no single unit.
|
|
8077
|
+
*/
|
|
8078
|
+
var QUANTITY_BASE = {
|
|
8079
|
+
temperature: "°C",
|
|
8080
|
+
pressure: "hPa",
|
|
8081
|
+
speed: "m/s",
|
|
8082
|
+
precipitation: "mm",
|
|
8083
|
+
"precipitation-rate": "mm/h",
|
|
8084
|
+
length: "m",
|
|
8085
|
+
area: "m²",
|
|
8086
|
+
illuminance: "lx",
|
|
8087
|
+
irradiance: "W/m²",
|
|
8088
|
+
power: "W",
|
|
8089
|
+
energy: "kWh",
|
|
8090
|
+
voltage: "V",
|
|
8091
|
+
current: "A",
|
|
8092
|
+
"apparent-power": "VA",
|
|
8093
|
+
humidity: "%",
|
|
8094
|
+
percentage: "%",
|
|
8095
|
+
"concentration-volume": "ppm",
|
|
8096
|
+
"concentration-mass": "µg/m³",
|
|
8097
|
+
"concentration-ppb": "ppb",
|
|
8098
|
+
volume: "L",
|
|
8099
|
+
duration: "s",
|
|
8100
|
+
"duration-ms": "ms",
|
|
8101
|
+
information: "B",
|
|
8102
|
+
"sound-level": "dBFS",
|
|
8103
|
+
"signal-level": "dBm",
|
|
8104
|
+
"colour-temperature": "mired",
|
|
8105
|
+
angle: "°",
|
|
8106
|
+
bitrate: "kbps",
|
|
8107
|
+
rate: "fps",
|
|
8108
|
+
mass: "kg",
|
|
8109
|
+
index: "none",
|
|
8110
|
+
ratio: "none",
|
|
8111
|
+
count: "none",
|
|
8112
|
+
none: "none",
|
|
8113
|
+
device: "device"
|
|
8114
|
+
};
|
|
8115
|
+
/** The stored unit, or `undefined` when the quantity has no unit symbol. */
|
|
8116
|
+
function baseUnitOf(quantity) {
|
|
8117
|
+
const symbol = QUANTITY_BASE[quantity];
|
|
8118
|
+
if (symbol === "none" || symbol === "device") return void 0;
|
|
8119
|
+
return symbol;
|
|
8120
|
+
}
|
|
8121
|
+
function readingMeta(quantity, extras) {
|
|
8122
|
+
return {
|
|
8123
|
+
quantity,
|
|
8124
|
+
...extras?.precision !== void 0 ? { precision: extras.precision } : {},
|
|
8125
|
+
...extras?.label !== void 0 ? { label: extras.label } : {}
|
|
8126
|
+
};
|
|
8127
|
+
}
|
|
8027
8128
|
/** Shared Zod schemas used across streaming capabilities. */
|
|
8028
8129
|
var CamProfileSchema = _enum([
|
|
8029
8130
|
"high",
|
|
@@ -8051,8 +8152,8 @@ var CamStreamKindSchema = _enum([
|
|
|
8051
8152
|
"derived"
|
|
8052
8153
|
]);
|
|
8053
8154
|
var CamStreamResolutionSchema = object({
|
|
8054
|
-
width: number().int().positive(),
|
|
8055
|
-
height: number().int().positive()
|
|
8155
|
+
width: number().int().positive().meta(readingMeta("none")),
|
|
8156
|
+
height: number().int().positive().meta(readingMeta("none"))
|
|
8056
8157
|
});
|
|
8057
8158
|
var CameraStreamSchema = object({
|
|
8058
8159
|
/** Stable, provider-assigned id unique within the (deviceId) scope. */
|
|
@@ -8570,6 +8671,8 @@ var CAP_NAMES = Object.freeze([
|
|
|
8570
8671
|
"filesystem-browse",
|
|
8571
8672
|
"flood",
|
|
8572
8673
|
"gas",
|
|
8674
|
+
"group-commands",
|
|
8675
|
+
"group-status",
|
|
8573
8676
|
"heating-valve",
|
|
8574
8677
|
"humidifier",
|
|
8575
8678
|
"humidity-sensor",
|
|
@@ -8699,14 +8802,6 @@ Object.freeze({
|
|
|
8699
8802
|
{
|
|
8700
8803
|
"path": "aqi",
|
|
8701
8804
|
"valueType": "number"
|
|
8702
|
-
},
|
|
8703
|
-
{
|
|
8704
|
-
"path": "unit",
|
|
8705
|
-
"valueType": "string"
|
|
8706
|
-
},
|
|
8707
|
-
{
|
|
8708
|
-
"path": "precision",
|
|
8709
|
-
"valueType": "number"
|
|
8710
8805
|
}
|
|
8711
8806
|
],
|
|
8712
8807
|
"alarm-panel": [
|
|
@@ -8742,20 +8837,10 @@ Object.freeze({
|
|
|
8742
8837
|
"valueType": "boolean"
|
|
8743
8838
|
}
|
|
8744
8839
|
],
|
|
8745
|
-
"ambient-light-sensor": [
|
|
8746
|
-
|
|
8747
|
-
|
|
8748
|
-
|
|
8749
|
-
},
|
|
8750
|
-
{
|
|
8751
|
-
"path": "unit",
|
|
8752
|
-
"valueType": "string"
|
|
8753
|
-
},
|
|
8754
|
-
{
|
|
8755
|
-
"path": "precision",
|
|
8756
|
-
"valueType": "number"
|
|
8757
|
-
}
|
|
8758
|
-
],
|
|
8840
|
+
"ambient-light-sensor": [{
|
|
8841
|
+
"path": "lux",
|
|
8842
|
+
"valueType": "number"
|
|
8843
|
+
}],
|
|
8759
8844
|
"audio-metrics": [
|
|
8760
8845
|
{
|
|
8761
8846
|
"path": "ts",
|
|
@@ -8835,6 +8920,10 @@ Object.freeze({
|
|
|
8835
8920
|
"path": "lastUpdated",
|
|
8836
8921
|
"valueType": "number"
|
|
8837
8922
|
},
|
|
8923
|
+
{
|
|
8924
|
+
"path": "volts",
|
|
8925
|
+
"valueType": "number"
|
|
8926
|
+
},
|
|
8838
8927
|
{
|
|
8839
8928
|
"path": "lastContactAt",
|
|
8840
8929
|
"valueType": "number"
|
|
@@ -9077,10 +9166,6 @@ Object.freeze({
|
|
|
9077
9166
|
"datetime"
|
|
9078
9167
|
]
|
|
9079
9168
|
},
|
|
9080
|
-
{
|
|
9081
|
-
"path": "unit",
|
|
9082
|
-
"valueType": "string"
|
|
9083
|
-
},
|
|
9084
9169
|
{
|
|
9085
9170
|
"path": "min",
|
|
9086
9171
|
"valueType": "number"
|
|
@@ -9092,19 +9177,6 @@ Object.freeze({
|
|
|
9092
9177
|
{
|
|
9093
9178
|
"path": "step",
|
|
9094
9179
|
"valueType": "number"
|
|
9095
|
-
},
|
|
9096
|
-
{
|
|
9097
|
-
"path": "precision",
|
|
9098
|
-
"valueType": "number"
|
|
9099
|
-
},
|
|
9100
|
-
{
|
|
9101
|
-
"path": "format",
|
|
9102
|
-
"valueType": "enum",
|
|
9103
|
-
"enumValues": [
|
|
9104
|
-
"date",
|
|
9105
|
-
"time",
|
|
9106
|
-
"datetime"
|
|
9107
|
-
]
|
|
9108
9180
|
}
|
|
9109
9181
|
],
|
|
9110
9182
|
"cover": [
|
|
@@ -9345,13 +9417,8 @@ Object.freeze({
|
|
|
9345
9417
|
"path": "value",
|
|
9346
9418
|
"valueType": "string"
|
|
9347
9419
|
}, {
|
|
9348
|
-
"path": "
|
|
9349
|
-
"valueType": "
|
|
9350
|
-
"enumValues": [
|
|
9351
|
-
"date",
|
|
9352
|
-
"time",
|
|
9353
|
-
"datetime"
|
|
9354
|
-
]
|
|
9420
|
+
"path": "timestamp",
|
|
9421
|
+
"valueType": "boolean"
|
|
9355
9422
|
}],
|
|
9356
9423
|
"event-emitter": [
|
|
9357
9424
|
{
|
|
@@ -9424,6 +9491,20 @@ Object.freeze({
|
|
|
9424
9491
|
"path": "detected",
|
|
9425
9492
|
"valueType": "boolean"
|
|
9426
9493
|
}],
|
|
9494
|
+
"group-status": [
|
|
9495
|
+
{
|
|
9496
|
+
"path": "included",
|
|
9497
|
+
"valueType": "number"
|
|
9498
|
+
},
|
|
9499
|
+
{
|
|
9500
|
+
"path": "excluded",
|
|
9501
|
+
"valueType": "number"
|
|
9502
|
+
},
|
|
9503
|
+
{
|
|
9504
|
+
"path": "total",
|
|
9505
|
+
"valueType": "number"
|
|
9506
|
+
}
|
|
9507
|
+
],
|
|
9427
9508
|
"heating-valve": [{
|
|
9428
9509
|
"path": "position",
|
|
9429
9510
|
"valueType": "number"
|
|
@@ -9458,20 +9539,10 @@ Object.freeze({
|
|
|
9458
9539
|
"valueType": "number"
|
|
9459
9540
|
}
|
|
9460
9541
|
],
|
|
9461
|
-
"humidity-sensor": [
|
|
9462
|
-
|
|
9463
|
-
|
|
9464
|
-
|
|
9465
|
-
},
|
|
9466
|
-
{
|
|
9467
|
-
"path": "unit",
|
|
9468
|
-
"valueType": "string"
|
|
9469
|
-
},
|
|
9470
|
-
{
|
|
9471
|
-
"path": "precision",
|
|
9472
|
-
"valueType": "number"
|
|
9473
|
-
}
|
|
9474
|
-
],
|
|
9542
|
+
"humidity-sensor": [{
|
|
9543
|
+
"path": "percent",
|
|
9544
|
+
"valueType": "number"
|
|
9545
|
+
}],
|
|
9475
9546
|
"image": [{
|
|
9476
9547
|
"path": "url",
|
|
9477
9548
|
"valueType": "string"
|
|
@@ -9810,20 +9881,10 @@ Object.freeze({
|
|
|
9810
9881
|
"valueType": "boolean"
|
|
9811
9882
|
}
|
|
9812
9883
|
],
|
|
9813
|
-
"numeric-sensor": [
|
|
9814
|
-
|
|
9815
|
-
|
|
9816
|
-
|
|
9817
|
-
},
|
|
9818
|
-
{
|
|
9819
|
-
"path": "unit",
|
|
9820
|
-
"valueType": "string"
|
|
9821
|
-
},
|
|
9822
|
-
{
|
|
9823
|
-
"path": "precision",
|
|
9824
|
-
"valueType": "number"
|
|
9825
|
-
}
|
|
9826
|
-
],
|
|
9884
|
+
"numeric-sensor": [{
|
|
9885
|
+
"path": "value",
|
|
9886
|
+
"valueType": "number"
|
|
9887
|
+
}],
|
|
9827
9888
|
"pet-feeder": [
|
|
9828
9889
|
{
|
|
9829
9890
|
"path": "foodLevel",
|
|
@@ -9915,14 +9976,6 @@ Object.freeze({
|
|
|
9915
9976
|
{
|
|
9916
9977
|
"path": "powerFactor",
|
|
9917
9978
|
"valueType": "number"
|
|
9918
|
-
},
|
|
9919
|
-
{
|
|
9920
|
-
"path": "unit",
|
|
9921
|
-
"valueType": "string"
|
|
9922
|
-
},
|
|
9923
|
-
{
|
|
9924
|
-
"path": "precision",
|
|
9925
|
-
"valueType": "number"
|
|
9926
9979
|
}
|
|
9927
9980
|
],
|
|
9928
9981
|
"presence": [
|
|
@@ -9951,20 +10004,10 @@ Object.freeze({
|
|
|
9951
10004
|
"valueType": "number"
|
|
9952
10005
|
}
|
|
9953
10006
|
],
|
|
9954
|
-
"pressure-sensor": [
|
|
9955
|
-
|
|
9956
|
-
|
|
9957
|
-
|
|
9958
|
-
},
|
|
9959
|
-
{
|
|
9960
|
-
"path": "unit",
|
|
9961
|
-
"valueType": "string"
|
|
9962
|
-
},
|
|
9963
|
-
{
|
|
9964
|
-
"path": "precision",
|
|
9965
|
-
"valueType": "number"
|
|
9966
|
-
}
|
|
9967
|
-
],
|
|
10007
|
+
"pressure-sensor": [{
|
|
10008
|
+
"path": "hpa",
|
|
10009
|
+
"valueType": "number"
|
|
10010
|
+
}],
|
|
9968
10011
|
"privacy-mask": [{
|
|
9969
10012
|
"path": "enabled",
|
|
9970
10013
|
"valueType": "boolean"
|
|
@@ -10275,20 +10318,10 @@ Object.freeze({
|
|
|
10275
10318
|
"path": "tampered",
|
|
10276
10319
|
"valueType": "boolean"
|
|
10277
10320
|
}],
|
|
10278
|
-
"temperature-sensor": [
|
|
10279
|
-
|
|
10280
|
-
|
|
10281
|
-
|
|
10282
|
-
},
|
|
10283
|
-
{
|
|
10284
|
-
"path": "unit",
|
|
10285
|
-
"valueType": "string"
|
|
10286
|
-
},
|
|
10287
|
-
{
|
|
10288
|
-
"path": "precision",
|
|
10289
|
-
"valueType": "number"
|
|
10290
|
-
}
|
|
10291
|
-
],
|
|
10321
|
+
"temperature-sensor": [{
|
|
10322
|
+
"path": "celsius",
|
|
10323
|
+
"valueType": "number"
|
|
10324
|
+
}],
|
|
10292
10325
|
"update": [
|
|
10293
10326
|
{
|
|
10294
10327
|
"path": "currentVersion",
|
|
@@ -10399,10 +10432,6 @@ Object.freeze({
|
|
|
10399
10432
|
"path": "temperature",
|
|
10400
10433
|
"valueType": "number"
|
|
10401
10434
|
},
|
|
10402
|
-
{
|
|
10403
|
-
"path": "temperatureUnit",
|
|
10404
|
-
"valueType": "string"
|
|
10405
|
-
},
|
|
10406
10435
|
{
|
|
10407
10436
|
"path": "humidity",
|
|
10408
10437
|
"valueType": "number"
|
|
@@ -10411,18 +10440,10 @@ Object.freeze({
|
|
|
10411
10440
|
"path": "pressure",
|
|
10412
10441
|
"valueType": "number"
|
|
10413
10442
|
},
|
|
10414
|
-
{
|
|
10415
|
-
"path": "pressureUnit",
|
|
10416
|
-
"valueType": "string"
|
|
10417
|
-
},
|
|
10418
10443
|
{
|
|
10419
10444
|
"path": "windSpeed",
|
|
10420
10445
|
"valueType": "number"
|
|
10421
10446
|
},
|
|
10422
|
-
{
|
|
10423
|
-
"path": "windSpeedUnit",
|
|
10424
|
-
"valueType": "string"
|
|
10425
|
-
},
|
|
10426
10447
|
{
|
|
10427
10448
|
"path": "windBearing",
|
|
10428
10449
|
"valueType": "number"
|
|
@@ -10829,7 +10850,7 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
|
|
|
10829
10850
|
return DeviceRole;
|
|
10830
10851
|
}({});
|
|
10831
10852
|
//#endregion
|
|
10832
|
-
//#region ../types/dist/composition-
|
|
10853
|
+
//#region ../types/dist/composition-OhpuespA.mjs
|
|
10833
10854
|
/**
|
|
10834
10855
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
10835
10856
|
*
|
|
@@ -11584,15 +11605,74 @@ function validateExpressionSource(src) {
|
|
|
11584
11605
|
}
|
|
11585
11606
|
return null;
|
|
11586
11607
|
}
|
|
11587
|
-
/**
|
|
11588
|
-
|
|
11589
|
-
|
|
11590
|
-
|
|
11608
|
+
/**
|
|
11609
|
+
* A composition source identity: `(addonId, stableId)`, never a numeric device
|
|
11610
|
+
* id. Split out so helper schemas can name it without a cycle through
|
|
11611
|
+
* `composition.ts` (D659).
|
|
11612
|
+
*/
|
|
11591
11613
|
var CompositionSourceRefSchema = object({
|
|
11592
11614
|
/** The owning addon; `stableId` is unique only within it. */
|
|
11593
11615
|
addonId: string().min(1),
|
|
11594
11616
|
stableId: string().min(1)
|
|
11595
11617
|
});
|
|
11618
|
+
var GROUP_TEMPLATE_IDS = [
|
|
11619
|
+
"temperature",
|
|
11620
|
+
"humidity",
|
|
11621
|
+
"pressure",
|
|
11622
|
+
"illuminance",
|
|
11623
|
+
"power",
|
|
11624
|
+
"energy",
|
|
11625
|
+
"battery",
|
|
11626
|
+
"numeric",
|
|
11627
|
+
"motion",
|
|
11628
|
+
"contact",
|
|
11629
|
+
"leak",
|
|
11630
|
+
"smoke",
|
|
11631
|
+
"occupancy",
|
|
11632
|
+
"binary",
|
|
11633
|
+
"switch",
|
|
11634
|
+
"light"
|
|
11635
|
+
];
|
|
11636
|
+
var NUMERIC_AGGREGATES = [
|
|
11637
|
+
"mean",
|
|
11638
|
+
"median",
|
|
11639
|
+
"min",
|
|
11640
|
+
"max",
|
|
11641
|
+
"sum"
|
|
11642
|
+
];
|
|
11643
|
+
var BINARY_AGGREGATES = ["any", "all"];
|
|
11644
|
+
/** How an actuator group decides it is on. Unknown members never count as off. */
|
|
11645
|
+
var ACTIVE_CRITERIA = ["at-least-one", "all"];
|
|
11646
|
+
var AGGREGATE_REDUCERS = [
|
|
11647
|
+
"mean",
|
|
11648
|
+
"median",
|
|
11649
|
+
"min",
|
|
11650
|
+
"max",
|
|
11651
|
+
"sum",
|
|
11652
|
+
"any",
|
|
11653
|
+
"all"
|
|
11654
|
+
];
|
|
11655
|
+
var GroupTemplateIdSchema = _enum(GROUP_TEMPLATE_IDS);
|
|
11656
|
+
var AggregateReducerSchema = _enum(AGGREGATE_REDUCERS);
|
|
11657
|
+
var ActiveCriterionSchema = _enum(ACTIVE_CRITERIA);
|
|
11658
|
+
/** One member. The field is stored so occupancy can name motion or binary. */
|
|
11659
|
+
var HelperMemberSchema = object({
|
|
11660
|
+
source: CompositionSourceRefSchema,
|
|
11661
|
+
cap: string().min(1),
|
|
11662
|
+
fieldPath: string().min(1)
|
|
11663
|
+
});
|
|
11664
|
+
var HelperSpecSchema = discriminatedUnion("kind", [object({
|
|
11665
|
+
kind: literal("group"),
|
|
11666
|
+
templateId: GroupTemplateIdSchema,
|
|
11667
|
+
aggregate: AggregateReducerSchema,
|
|
11668
|
+
members: array(HelperMemberSchema).min(1).max(64),
|
|
11669
|
+
/** Actuator groups only. Readings leave this unset. */
|
|
11670
|
+
active: ActiveCriterionSchema.optional()
|
|
11671
|
+
})]);
|
|
11672
|
+
/** A composed device's stableId is this prefix plus the block id. */
|
|
11673
|
+
var COMPOSED_DEVICE_STABLE_ID_PREFIX = "composed-";
|
|
11674
|
+
/** Longest snippet a `code` source may carry (slice 4). */
|
|
11675
|
+
var MAX_COMPOSITION_CODE_LENGTH = 2e4;
|
|
11596
11676
|
/** One field of one capability of one source device. */
|
|
11597
11677
|
var CompositionFieldReadSchema = object({
|
|
11598
11678
|
source: CompositionSourceRefSchema,
|
|
@@ -11636,7 +11716,33 @@ var CompositionCodeSourceSchema = object({
|
|
|
11636
11716
|
var CompositionFieldSourceSchema = discriminatedUnion("kind", [
|
|
11637
11717
|
CompositionFromSourceSchema,
|
|
11638
11718
|
CompositionExpressionSourceSchema,
|
|
11639
|
-
CompositionCodeSourceSchema
|
|
11719
|
+
CompositionCodeSourceSchema,
|
|
11720
|
+
object({
|
|
11721
|
+
kind: literal("aggregate"),
|
|
11722
|
+
reducer: _enum([
|
|
11723
|
+
"mean",
|
|
11724
|
+
"median",
|
|
11725
|
+
"min",
|
|
11726
|
+
"max",
|
|
11727
|
+
"sum",
|
|
11728
|
+
"any",
|
|
11729
|
+
"all"
|
|
11730
|
+
]),
|
|
11731
|
+
reads: array(CompositionFieldReadSchema).min(1).max(64),
|
|
11732
|
+
/** `value` is the reading; the others are the member counts. */
|
|
11733
|
+
publish: _enum([
|
|
11734
|
+
"value",
|
|
11735
|
+
"included",
|
|
11736
|
+
"excluded",
|
|
11737
|
+
"total"
|
|
11738
|
+
]),
|
|
11739
|
+
/** What a `value` publish does when nobody is included. Counts ignore this. */
|
|
11740
|
+
empty: _enum([
|
|
11741
|
+
"null",
|
|
11742
|
+
"omit",
|
|
11743
|
+
"offline"
|
|
11744
|
+
])
|
|
11745
|
+
})
|
|
11640
11746
|
]);
|
|
11641
11747
|
var CompositionCommandTargetSchema = discriminatedUnion("kind", [object({
|
|
11642
11748
|
kind: literal("forward"),
|
|
@@ -11682,7 +11788,13 @@ var CompositionSchema = object({
|
|
|
11682
11788
|
kind: literal("existing"),
|
|
11683
11789
|
device: CompositionSourceRefSchema
|
|
11684
11790
|
})]),
|
|
11685
|
-
features: array(CompositionFeatureSchema).min(1).max(16)
|
|
11791
|
+
features: array(CompositionFeatureSchema).min(1).max(16),
|
|
11792
|
+
/**
|
|
11793
|
+
* Present when the block is a helper template. Absent on a free
|
|
11794
|
+
* composition (the room example, device 4603). The editor reads this,
|
|
11795
|
+
* never the compiled features.
|
|
11796
|
+
*/
|
|
11797
|
+
helper: HelperSpecSchema.optional()
|
|
11686
11798
|
}).superRefine((composition, ctx) => {
|
|
11687
11799
|
const seen = /* @__PURE__ */ new Set();
|
|
11688
11800
|
composition.features.forEach((feature, index) => {
|
|
@@ -17928,7 +18040,11 @@ var CompositionProblemSchema = object({
|
|
|
17928
18040
|
"item-field-reserved",
|
|
17929
18041
|
"target-missing",
|
|
17930
18042
|
"target-unreadable",
|
|
17931
|
-
"not-replaceable"
|
|
18043
|
+
"not-replaceable",
|
|
18044
|
+
"native-capability-replace",
|
|
18045
|
+
"mixed-quantity",
|
|
18046
|
+
"helper-mismatch",
|
|
18047
|
+
"member-constraint"
|
|
17932
18048
|
]),
|
|
17933
18049
|
path: string(),
|
|
17934
18050
|
message: string()
|
|
@@ -17949,7 +18065,8 @@ var CompositionUnavailableModeSchema = _enum([
|
|
|
17949
18065
|
"null",
|
|
17950
18066
|
"offline",
|
|
17951
18067
|
"unknown",
|
|
17952
|
-
"release"
|
|
18068
|
+
"release",
|
|
18069
|
+
"omit"
|
|
17953
18070
|
]);
|
|
17954
18071
|
/**
|
|
17955
18072
|
* `derived` reads a source · `clock` reads only `now`, recomputed when a sibling
|
|
@@ -17986,9 +18103,11 @@ var CompositionFieldPlanSchema = object({
|
|
|
17986
18103
|
reads: array(CompositionFieldReadSchema)
|
|
17987
18104
|
});
|
|
17988
18105
|
/**
|
|
17989
|
-
* What a feature does to its target (D663): `new` builds a capability on a
|
|
17990
|
-
* device; on an existing device it `add`s a capability the device lacks
|
|
17991
|
-
*
|
|
18106
|
+
* What a feature does to its target (D663, D944): `new` builds a capability on a
|
|
18107
|
+
* new device; on an existing device it `add`s a capability the device lacks.
|
|
18108
|
+
* Replacing a capability the device already serves is refused
|
|
18109
|
+
* (`native-capability-replace`), not planned. `replace` remains on the claim
|
|
18110
|
+
* wire for a claim the hub already holds.
|
|
17992
18111
|
*/
|
|
17993
18112
|
var CompositionFeatureModeSchema = _enum([
|
|
17994
18113
|
"new",
|
|
@@ -18161,6 +18280,275 @@ Object.freeze({
|
|
|
18161
18280
|
result: ["number", "null"]
|
|
18162
18281
|
}
|
|
18163
18282
|
});
|
|
18283
|
+
/**
|
|
18284
|
+
* One catalog row per base reading a group helper can build (D944 §3).
|
|
18285
|
+
* Data, not a form default written into the block.
|
|
18286
|
+
*/
|
|
18287
|
+
var NOW = {
|
|
18288
|
+
fieldPath: "lastFetchedAt",
|
|
18289
|
+
expr: "now"
|
|
18290
|
+
};
|
|
18291
|
+
var CHANGED = {
|
|
18292
|
+
fieldPath: "lastChangedAt",
|
|
18293
|
+
expr: "now"
|
|
18294
|
+
};
|
|
18295
|
+
function numeric(input) {
|
|
18296
|
+
return {
|
|
18297
|
+
...input,
|
|
18298
|
+
family: "numeric",
|
|
18299
|
+
deviceType: DeviceType.Sensor,
|
|
18300
|
+
memberDeviceType: DeviceType.Sensor,
|
|
18301
|
+
commandCaps: [],
|
|
18302
|
+
baseUnit: baseUnitOf(input.quantity),
|
|
18303
|
+
aggregates: NUMERIC_AGGREGATES,
|
|
18304
|
+
accept: [{
|
|
18305
|
+
cap: input.outputCap,
|
|
18306
|
+
fieldPath: input.outputField
|
|
18307
|
+
}]
|
|
18308
|
+
};
|
|
18309
|
+
}
|
|
18310
|
+
function binary(input) {
|
|
18311
|
+
return {
|
|
18312
|
+
...input,
|
|
18313
|
+
family: "binary",
|
|
18314
|
+
deviceType: DeviceType.Sensor,
|
|
18315
|
+
memberDeviceType: DeviceType.Sensor,
|
|
18316
|
+
commandCaps: [],
|
|
18317
|
+
quantity: "none",
|
|
18318
|
+
baseUnit: void 0,
|
|
18319
|
+
aggregates: BINARY_AGGREGATES,
|
|
18320
|
+
empty: "offline"
|
|
18321
|
+
};
|
|
18322
|
+
}
|
|
18323
|
+
var GROUP_TEMPLATES = [
|
|
18324
|
+
numeric({
|
|
18325
|
+
id: "temperature",
|
|
18326
|
+
summary: "Mean, median, min, max or sum of temperatures. Offline and unknown members are left out, never read as 0 °C.",
|
|
18327
|
+
role: DeviceRole.TemperatureSensor,
|
|
18328
|
+
outputCap: "temperature-sensor",
|
|
18329
|
+
outputField: "celsius",
|
|
18330
|
+
quantity: "temperature",
|
|
18331
|
+
defaultAggregate: "mean",
|
|
18332
|
+
empty: "null",
|
|
18333
|
+
companions: [NOW]
|
|
18334
|
+
}),
|
|
18335
|
+
numeric({
|
|
18336
|
+
id: "humidity",
|
|
18337
|
+
summary: "Humidity in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
18338
|
+
role: DeviceRole.HumiditySensor,
|
|
18339
|
+
outputCap: "humidity-sensor",
|
|
18340
|
+
outputField: "percent",
|
|
18341
|
+
quantity: "humidity",
|
|
18342
|
+
defaultAggregate: "mean",
|
|
18343
|
+
empty: "null",
|
|
18344
|
+
companions: [NOW]
|
|
18345
|
+
}),
|
|
18346
|
+
numeric({
|
|
18347
|
+
id: "pressure",
|
|
18348
|
+
summary: "Pressure in hectopascals. Offline and unknown members are left out, never read as 0 hPa.",
|
|
18349
|
+
role: DeviceRole.PressureSensor,
|
|
18350
|
+
outputCap: "pressure-sensor",
|
|
18351
|
+
outputField: "hpa",
|
|
18352
|
+
quantity: "pressure",
|
|
18353
|
+
defaultAggregate: "mean",
|
|
18354
|
+
empty: "null",
|
|
18355
|
+
companions: [NOW]
|
|
18356
|
+
}),
|
|
18357
|
+
numeric({
|
|
18358
|
+
id: "illuminance",
|
|
18359
|
+
summary: "Illuminance in lux. Offline and unknown members are left out, never read as 0 lx.",
|
|
18360
|
+
role: DeviceRole.AmbientLightSensor,
|
|
18361
|
+
outputCap: "ambient-light-sensor",
|
|
18362
|
+
outputField: "lux",
|
|
18363
|
+
quantity: "illuminance",
|
|
18364
|
+
defaultAggregate: "mean",
|
|
18365
|
+
empty: "null",
|
|
18366
|
+
companions: [NOW]
|
|
18367
|
+
}),
|
|
18368
|
+
numeric({
|
|
18369
|
+
id: "power",
|
|
18370
|
+
summary: "Power in watts, summed by default. Nobody reporting omits the key rather than writing 0 W.",
|
|
18371
|
+
role: DeviceRole.PowerSensor,
|
|
18372
|
+
outputCap: "power-meter",
|
|
18373
|
+
outputField: "watts",
|
|
18374
|
+
quantity: "power",
|
|
18375
|
+
defaultAggregate: "sum",
|
|
18376
|
+
empty: "omit",
|
|
18377
|
+
companions: [NOW]
|
|
18378
|
+
}),
|
|
18379
|
+
numeric({
|
|
18380
|
+
id: "energy",
|
|
18381
|
+
summary: "Energy in kilowatt-hours, summed by default. Nobody reporting omits the key rather than writing 0 kWh.",
|
|
18382
|
+
role: DeviceRole.EnergySensor,
|
|
18383
|
+
outputCap: "power-meter",
|
|
18384
|
+
outputField: "kwhTotal",
|
|
18385
|
+
quantity: "energy",
|
|
18386
|
+
defaultAggregate: "sum",
|
|
18387
|
+
empty: "omit",
|
|
18388
|
+
companions: [NOW]
|
|
18389
|
+
}),
|
|
18390
|
+
numeric({
|
|
18391
|
+
id: "battery",
|
|
18392
|
+
summary: "Battery charge in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
18393
|
+
role: DeviceRole.BatterySensor,
|
|
18394
|
+
outputCap: "battery",
|
|
18395
|
+
outputField: "percentage",
|
|
18396
|
+
quantity: "percentage",
|
|
18397
|
+
defaultAggregate: "mean",
|
|
18398
|
+
empty: "null",
|
|
18399
|
+
companions: [
|
|
18400
|
+
{
|
|
18401
|
+
fieldPath: "charging",
|
|
18402
|
+
expr: "\"unknown\""
|
|
18403
|
+
},
|
|
18404
|
+
{
|
|
18405
|
+
fieldPath: "sleeping",
|
|
18406
|
+
expr: "false"
|
|
18407
|
+
},
|
|
18408
|
+
{
|
|
18409
|
+
fieldPath: "lastUpdated",
|
|
18410
|
+
expr: "now"
|
|
18411
|
+
}
|
|
18412
|
+
]
|
|
18413
|
+
}),
|
|
18414
|
+
numeric({
|
|
18415
|
+
id: "numeric",
|
|
18416
|
+
summary: "A numeric reading in the members’ shared quantity. Mixed quantities are refused. Nobody reporting publishes null, not 0.",
|
|
18417
|
+
role: DeviceRole.NumericSensor,
|
|
18418
|
+
outputCap: "numeric-sensor",
|
|
18419
|
+
outputField: "value",
|
|
18420
|
+
quantity: "device",
|
|
18421
|
+
defaultAggregate: "mean",
|
|
18422
|
+
empty: "null",
|
|
18423
|
+
companions: [NOW]
|
|
18424
|
+
}),
|
|
18425
|
+
binary({
|
|
18426
|
+
id: "motion",
|
|
18427
|
+
summary: "Any or all motion. Offline and unknown members are left out, never read as off. Nobody reporting takes the device offline.",
|
|
18428
|
+
role: DeviceRole.MotionSensor,
|
|
18429
|
+
outputCap: "motion",
|
|
18430
|
+
outputField: "detected",
|
|
18431
|
+
defaultAggregate: "any",
|
|
18432
|
+
accept: [{
|
|
18433
|
+
cap: "motion",
|
|
18434
|
+
fieldPath: "detected"
|
|
18435
|
+
}],
|
|
18436
|
+
companions: [{
|
|
18437
|
+
fieldPath: "lastDetectedAt",
|
|
18438
|
+
expr: "null"
|
|
18439
|
+
}, {
|
|
18440
|
+
fieldPath: "autoClearAfterMs",
|
|
18441
|
+
expr: "null"
|
|
18442
|
+
}]
|
|
18443
|
+
}),
|
|
18444
|
+
binary({
|
|
18445
|
+
id: "contact",
|
|
18446
|
+
summary: "Any or all open contacts. Offline and unknown members are left out, never read as closed.",
|
|
18447
|
+
role: DeviceRole.ContactSensor,
|
|
18448
|
+
outputCap: "contact",
|
|
18449
|
+
outputField: "entryOpen",
|
|
18450
|
+
defaultAggregate: "any",
|
|
18451
|
+
accept: [{
|
|
18452
|
+
cap: "contact",
|
|
18453
|
+
fieldPath: "entryOpen"
|
|
18454
|
+
}],
|
|
18455
|
+
companions: [CHANGED]
|
|
18456
|
+
}),
|
|
18457
|
+
binary({
|
|
18458
|
+
id: "leak",
|
|
18459
|
+
summary: "Any or all leak detections. Offline and unknown members are left out, never read as dry.",
|
|
18460
|
+
role: DeviceRole.LeakSensor,
|
|
18461
|
+
outputCap: "flood",
|
|
18462
|
+
outputField: "flooded",
|
|
18463
|
+
defaultAggregate: "any",
|
|
18464
|
+
accept: [{
|
|
18465
|
+
cap: "flood",
|
|
18466
|
+
fieldPath: "flooded"
|
|
18467
|
+
}],
|
|
18468
|
+
companions: [CHANGED]
|
|
18469
|
+
}),
|
|
18470
|
+
binary({
|
|
18471
|
+
id: "smoke",
|
|
18472
|
+
summary: "Any or all smoke detections. Offline and unknown members are left out, never read as clear.",
|
|
18473
|
+
role: DeviceRole.SmokeSensor,
|
|
18474
|
+
outputCap: "smoke",
|
|
18475
|
+
outputField: "detected",
|
|
18476
|
+
defaultAggregate: "any",
|
|
18477
|
+
accept: [{
|
|
18478
|
+
cap: "smoke",
|
|
18479
|
+
fieldPath: "detected"
|
|
18480
|
+
}],
|
|
18481
|
+
companions: [CHANGED]
|
|
18482
|
+
}),
|
|
18483
|
+
binary({
|
|
18484
|
+
id: "occupancy",
|
|
18485
|
+
summary: "Any or all of motion or binary sensors, published as a binary. Presence zones are not aggregated. Nobody reporting is offline, not off.",
|
|
18486
|
+
role: DeviceRole.BinarySensor,
|
|
18487
|
+
outputCap: "binary",
|
|
18488
|
+
outputField: "on",
|
|
18489
|
+
defaultAggregate: "any",
|
|
18490
|
+
accept: [{
|
|
18491
|
+
cap: "motion",
|
|
18492
|
+
fieldPath: "detected"
|
|
18493
|
+
}, {
|
|
18494
|
+
cap: "binary",
|
|
18495
|
+
fieldPath: "on"
|
|
18496
|
+
}],
|
|
18497
|
+
companions: [CHANGED]
|
|
18498
|
+
}),
|
|
18499
|
+
binary({
|
|
18500
|
+
id: "binary",
|
|
18501
|
+
summary: "Any or all generic binary sensors. Offline and unknown members are left out, never read as off.",
|
|
18502
|
+
role: DeviceRole.BinarySensor,
|
|
18503
|
+
outputCap: "binary",
|
|
18504
|
+
outputField: "on",
|
|
18505
|
+
defaultAggregate: "any",
|
|
18506
|
+
accept: [{
|
|
18507
|
+
cap: "binary",
|
|
18508
|
+
fieldPath: "on"
|
|
18509
|
+
}],
|
|
18510
|
+
companions: [CHANGED]
|
|
18511
|
+
}),
|
|
18512
|
+
actuator({
|
|
18513
|
+
id: "switch",
|
|
18514
|
+
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.",
|
|
18515
|
+
deviceType: DeviceType.Switch,
|
|
18516
|
+
outputCap: "switch",
|
|
18517
|
+
commandCaps: ["switch"]
|
|
18518
|
+
}),
|
|
18519
|
+
actuator({
|
|
18520
|
+
id: "light",
|
|
18521
|
+
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.",
|
|
18522
|
+
deviceType: DeviceType.Light,
|
|
18523
|
+
outputCap: "switch",
|
|
18524
|
+
commandCaps: [
|
|
18525
|
+
"switch",
|
|
18526
|
+
"brightness",
|
|
18527
|
+
"color"
|
|
18528
|
+
]
|
|
18529
|
+
})
|
|
18530
|
+
];
|
|
18531
|
+
function actuator(input) {
|
|
18532
|
+
return {
|
|
18533
|
+
...input,
|
|
18534
|
+
family: "actuator",
|
|
18535
|
+
role: void 0,
|
|
18536
|
+
memberDeviceType: input.deviceType,
|
|
18537
|
+
outputField: "on",
|
|
18538
|
+
quantity: "none",
|
|
18539
|
+
baseUnit: void 0,
|
|
18540
|
+
aggregates: BINARY_AGGREGATES,
|
|
18541
|
+
defaultAggregate: "any",
|
|
18542
|
+
empty: "offline",
|
|
18543
|
+
accept: [{
|
|
18544
|
+
cap: "switch",
|
|
18545
|
+
fieldPath: "on"
|
|
18546
|
+
}],
|
|
18547
|
+
companions: [CHANGED]
|
|
18548
|
+
};
|
|
18549
|
+
}
|
|
18550
|
+
new Map(GROUP_TEMPLATES.map((template) => [template.id, template]));
|
|
18551
|
+
DeviceFeature.LightColorRgb, DeviceFeature.LightColorHsv, DeviceFeature.LightColorMired;
|
|
18164
18552
|
`${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
|
|
18165
18553
|
/**
|
|
18166
18554
|
* What a composition may BUILD on a device type (G2, D676): the caps a new
|
|
@@ -19987,12 +20375,12 @@ function buildDeviceAdminUrl(parts) {
|
|
|
19987
20375
|
* providers detect renames by matching `uniqueId` and patch `id`
|
|
19988
20376
|
* in-place so dispatch keeps working.
|
|
19989
20377
|
*
|
|
19990
|
-
* **
|
|
19991
|
-
*
|
|
19992
|
-
*
|
|
19993
|
-
*
|
|
19994
|
-
* (`ha-domain-mapping`)
|
|
19995
|
-
* stored after that point.
|
|
20378
|
+
* **Display unit and precision are NOT stored here.** They are a read-time
|
|
20379
|
+
* preference (D944). A polymorphic reading stores its `quantity` here once,
|
|
20380
|
+
* at adopt, and a date/time value stores `dateTimeShape` the same way —
|
|
20381
|
+
* neither is repeated on each sample. The `device_class` tag is an
|
|
20382
|
+
* HA-specific input consumed at the discovery boundary (`ha-domain-mapping`)
|
|
20383
|
+
* to derive the CamStack `DeviceRole`; it is never stored after that point.
|
|
19996
20384
|
*
|
|
19997
20385
|
* The `raw` escape hatch carries provider-specific attributes that don't
|
|
19998
20386
|
* fit the structured slots (HA `attributes` whitelist, Reolink `deviceCache`
|
|
@@ -20006,6 +20394,14 @@ var SourceInfoSchema = object({
|
|
|
20006
20394
|
/** Immutable upstream identifier when available (HA `unique_id`, … ).
|
|
20007
20395
|
* Used to detect rename when `id` changes. */
|
|
20008
20396
|
uniqueId: string().optional(),
|
|
20397
|
+
/** Quantity of a polymorphic reading, written once at adopt (D944). */
|
|
20398
|
+
quantity: ReadingQuantitySchema.optional(),
|
|
20399
|
+
/** Date / time / datetime shape of a string reading, written once at adopt. */
|
|
20400
|
+
dateTimeShape: _enum([
|
|
20401
|
+
"date",
|
|
20402
|
+
"time",
|
|
20403
|
+
"datetime"
|
|
20404
|
+
]).optional(),
|
|
20009
20405
|
/** Provider-specific extras that don't fit the structured slots.
|
|
20010
20406
|
* Whitelist what goes here per provider — do NOT dump entire HA
|
|
20011
20407
|
* attribute blobs (would explode the meta JSON column). */
|
|
@@ -41110,7 +41506,8 @@ method(object({
|
|
|
41110
41506
|
"enum"
|
|
41111
41507
|
]),
|
|
41112
41508
|
enumValues: array(string()).optional(),
|
|
41113
|
-
item: boolean().optional()
|
|
41509
|
+
item: boolean().optional(),
|
|
41510
|
+
quantity: ReadingQuantitySchema.optional()
|
|
41114
41511
|
})).readonly(),
|
|
41115
41512
|
itemArray: object({
|
|
41116
41513
|
path: string(),
|
|
@@ -44954,8 +45351,8 @@ var MaskPolygonShapeSchema = object({
|
|
|
44954
45351
|
/** Boolean cell grid — row-major, length === gridWidth*gridHeight. */
|
|
44955
45352
|
var MaskGridShapeSchema = object({
|
|
44956
45353
|
kind: literal("grid"),
|
|
44957
|
-
gridWidth: number(),
|
|
44958
|
-
gridHeight: number(),
|
|
45354
|
+
gridWidth: number().meta(readingMeta("none")),
|
|
45355
|
+
gridHeight: number().meta(readingMeta("none")),
|
|
44959
45356
|
cells: array(boolean())
|
|
44960
45357
|
});
|
|
44961
45358
|
discriminatedUnion("kind", [
|
|
@@ -45067,6 +45464,8 @@ var NcSystemEventKindSchema = _enum([
|
|
|
45067
45464
|
"detection-blind",
|
|
45068
45465
|
"motion-noisy",
|
|
45069
45466
|
"motion-calm",
|
|
45467
|
+
"package-llm-silent",
|
|
45468
|
+
"package-llm-answered",
|
|
45070
45469
|
"recording-stalled",
|
|
45071
45470
|
"recording-healthy",
|
|
45072
45471
|
"recording-degraded",
|
|
@@ -56671,6 +57070,28 @@ var PackageVersionInfoSchema = object({
|
|
|
56671
57070
|
deprecated: string().optional(),
|
|
56672
57071
|
distTags: array(string()).readonly()
|
|
56673
57072
|
});
|
|
57073
|
+
/**
|
|
57074
|
+
* One published document. `ok` is markdown from the registry. `missing` means
|
|
57075
|
+
* the registry answered and the file was not there. `error` is a registry or
|
|
57076
|
+
* tarball failure — never an empty string standing in for either.
|
|
57077
|
+
*/
|
|
57078
|
+
var PackageDocBodySchema = discriminatedUnion("status", [
|
|
57079
|
+
object({
|
|
57080
|
+
status: literal("ok"),
|
|
57081
|
+
markdown: string()
|
|
57082
|
+
}),
|
|
57083
|
+
object({ status: literal("missing") }),
|
|
57084
|
+
object({
|
|
57085
|
+
status: literal("error"),
|
|
57086
|
+
message: string()
|
|
57087
|
+
})
|
|
57088
|
+
]);
|
|
57089
|
+
var PackageDocsSchema = object({
|
|
57090
|
+
name: string(),
|
|
57091
|
+
version: string(),
|
|
57092
|
+
readme: PackageDocBodySchema,
|
|
57093
|
+
changelog: PackageDocBodySchema
|
|
57094
|
+
});
|
|
56674
57095
|
var SearchResultSchema = object({
|
|
56675
57096
|
name: string(),
|
|
56676
57097
|
version: string(),
|
|
@@ -56889,7 +57310,10 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
|
|
|
56889
57310
|
}), object({ success: literal(true) }), {
|
|
56890
57311
|
kind: "mutation",
|
|
56891
57312
|
auth: "admin"
|
|
56892
|
-
}), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({
|
|
57313
|
+
}), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({
|
|
57314
|
+
name: string().min(1),
|
|
57315
|
+
version: string().min(1).optional()
|
|
57316
|
+
}), PackageDocsSchema, { auth: "admin" }), method(object({ addonId: string() }), RestartAddonResultSchema, {
|
|
56893
57317
|
kind: "mutation",
|
|
56894
57318
|
auth: "admin"
|
|
56895
57319
|
}), method(object({ packageName: string() }), object({ success: literal(true) }), {
|
|
@@ -56948,27 +57372,17 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
|
|
|
56948
57372
|
*/
|
|
56949
57373
|
var AirQualitySensorStatusSchema = object({
|
|
56950
57374
|
/** Carbon dioxide concentration in ppm. */
|
|
56951
|
-
co2Ppm: number().min(0).optional(),
|
|
57375
|
+
co2Ppm: number().min(0).optional().meta(readingMeta("concentration-volume")),
|
|
56952
57376
|
/** Total volatile organic compounds in ppb. */
|
|
56953
|
-
vocPpb: number().min(0).optional(),
|
|
57377
|
+
vocPpb: number().min(0).optional().meta(readingMeta("concentration-ppb")),
|
|
56954
57378
|
/** Particulate matter ≤ 2.5 μm in µg/m³. */
|
|
56955
|
-
pm25: number().min(0).optional(),
|
|
57379
|
+
pm25: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
56956
57380
|
/** Particulate matter ≤ 10 μm in µg/m³. */
|
|
56957
|
-
pm10: number().min(0).optional(),
|
|
57381
|
+
pm10: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
56958
57382
|
/** Composite AQI value (typically 0..500). */
|
|
56959
|
-
aqi: number().optional(),
|
|
57383
|
+
aqi: number().optional().meta(readingMeta("index")),
|
|
56960
57384
|
/** Ms epoch when the slice was last updated. */
|
|
56961
|
-
lastFetchedAt: number()
|
|
56962
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
56963
|
-
* `attributes.unit_of_measurement` → 'ppm' / 'ppb' / 'µg/m³'). Each
|
|
56964
|
-
* upstream `sensor.*` entity surfaces ONE device_class, so one unit
|
|
56965
|
-
* per slice is unambiguous. */
|
|
56966
|
-
unit: string().optional(),
|
|
56967
|
-
/** Suggested decimal places for numeric display.
|
|
56968
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
56969
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
56970
|
-
* auto-formatting when absent. */
|
|
56971
|
-
precision: number().int().min(0).max(10).optional()
|
|
57385
|
+
lastFetchedAt: number()
|
|
56972
57386
|
});
|
|
56973
57387
|
var airQualitySensorCapability = {
|
|
56974
57388
|
name: "air-quality-sensor",
|
|
@@ -57005,12 +57419,12 @@ var airQualitySensorCapability = {
|
|
|
57005
57419
|
},
|
|
57006
57420
|
pm25: {
|
|
57007
57421
|
kind: "gauge",
|
|
57008
|
-
unit: "
|
|
57422
|
+
unit: "µg/m³",
|
|
57009
57423
|
deadband: 1
|
|
57010
57424
|
},
|
|
57011
57425
|
pm10: {
|
|
57012
57426
|
kind: "gauge",
|
|
57013
|
-
unit: "
|
|
57427
|
+
unit: "µg/m³",
|
|
57014
57428
|
deadband: 1
|
|
57015
57429
|
},
|
|
57016
57430
|
aqi: {
|
|
@@ -57028,22 +57442,13 @@ var airQualitySensorCapability = {
|
|
|
57028
57442
|
* entries with `device_class: illuminance`.
|
|
57029
57443
|
*/
|
|
57030
57444
|
var AmbientLightSensorStatusSchema = object({
|
|
57031
|
-
/** Current illuminance in lux (lx). */
|
|
57032
|
-
lux: number().min(0).meta({
|
|
57033
|
-
|
|
57445
|
+
/** Current illuminance in lux (lx). `null` when the sample was refused (D393). */
|
|
57446
|
+
lux: number().min(0).nullable().meta(readingMeta("illuminance", {
|
|
57447
|
+
precision: 0,
|
|
57034
57448
|
label: "Illuminance"
|
|
57035
|
-
}),
|
|
57449
|
+
})),
|
|
57036
57450
|
/** Ms epoch when the slice was last updated. */
|
|
57037
|
-
lastFetchedAt: number()
|
|
57038
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
57039
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
57040
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
57041
|
-
unit: string().optional(),
|
|
57042
|
-
/** Suggested decimal places for numeric display.
|
|
57043
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
57044
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
57045
|
-
* auto-formatting when absent. */
|
|
57046
|
-
precision: number().int().min(0).max(10).optional()
|
|
57451
|
+
lastFetchedAt: number()
|
|
57047
57452
|
});
|
|
57048
57453
|
var ambientLightSensorCapability = {
|
|
57049
57454
|
name: "ambient-light-sensor",
|
|
@@ -57075,12 +57480,7 @@ var ambientLightSensorCapability = {
|
|
|
57075
57480
|
} } },
|
|
57076
57481
|
/** Clock fields: written, but excluded from the compare that decides
|
|
57077
57482
|
* whether persisting is worth a SQLite commit. */
|
|
57078
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
57079
|
-
customize: {
|
|
57080
|
-
version: 1,
|
|
57081
|
-
advanced: "derive",
|
|
57082
|
-
targets: []
|
|
57083
|
-
}
|
|
57483
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
57084
57484
|
};
|
|
57085
57485
|
/**
|
|
57086
57486
|
* Per-class audio metrics aggregated over a sliding window.
|
|
@@ -57307,10 +57707,7 @@ var BatteryStatusSchema = object({
|
|
|
57307
57707
|
* Consumers must SKIP a null rather than coerce it — `battery-band` already
|
|
57308
57708
|
* declines to band a non-finite reading, which is the correct shape.
|
|
57309
57709
|
*/
|
|
57310
|
-
percentage: number().min(0).max(100).nullable().meta({
|
|
57311
|
-
unit: "%",
|
|
57312
|
-
label: "Charge"
|
|
57313
|
-
}),
|
|
57710
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage", { label: "Charge" })),
|
|
57314
57711
|
/**
|
|
57315
57712
|
* Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
|
|
57316
57713
|
* Reolink-specific for the Solar Panel 2 accessory (will become
|
|
@@ -57337,7 +57734,14 @@ var BatteryStatusSchema = object({
|
|
|
57337
57734
|
*/
|
|
57338
57735
|
sleeping: boolean().meta({ label: "Sleeping" }),
|
|
57339
57736
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
57340
|
-
lastUpdated: number(),
|
|
57737
|
+
lastUpdated: number().meta(readingMeta("none")),
|
|
57738
|
+
/**
|
|
57739
|
+
* Battery voltage in volts, for a cell the firmware reports as voltage
|
|
57740
|
+
* rather than a percentage (Ecowitt capacitor packs). Absent on cameras
|
|
57741
|
+
* that only report charge. A second reading on this cap, not a second
|
|
57742
|
+
* `numeric-sensor` on the same device.
|
|
57743
|
+
*/
|
|
57744
|
+
volts: number().nullable().optional().meta(readingMeta("voltage", { label: "Voltage" })),
|
|
57341
57745
|
/**
|
|
57342
57746
|
* Ms epoch of the last time the device PROVED it was reachable — a
|
|
57343
57747
|
* completed firmware round-trip, an observed wake, or an inbound push
|
|
@@ -57389,7 +57793,6 @@ var BATTERY_DEVICE_TYPES = [
|
|
|
57389
57793
|
/** Generic Customize target for the percentage reading (D936). */
|
|
57390
57794
|
var batteryCustomize = {
|
|
57391
57795
|
version: 1,
|
|
57392
|
-
advanced: "derive",
|
|
57393
57796
|
targets: [{
|
|
57394
57797
|
id: "percentage",
|
|
57395
57798
|
cardinality: "scalar",
|
|
@@ -57398,7 +57801,7 @@ var batteryCustomize = {
|
|
|
57398
57801
|
stateField: "percentage"
|
|
57399
57802
|
},
|
|
57400
57803
|
deviceTypes: BATTERY_DEVICE_TYPES,
|
|
57401
|
-
apply: "add
|
|
57804
|
+
apply: "add",
|
|
57402
57805
|
path: "percentage",
|
|
57403
57806
|
sources: [{
|
|
57404
57807
|
kind: "field",
|
|
@@ -57519,10 +57922,16 @@ onStatusChanged: { data: object({
|
|
|
57519
57922
|
/**
|
|
57520
57923
|
* History (D850): recorded series. The generic capture replaces the `battery` series of `pipeline-analytics:stats-5m`.
|
|
57521
57924
|
*/
|
|
57522
|
-
history: { fields: {
|
|
57523
|
-
|
|
57524
|
-
|
|
57525
|
-
|
|
57925
|
+
history: { fields: {
|
|
57926
|
+
percentage: {
|
|
57927
|
+
kind: "gauge",
|
|
57928
|
+
unit: "%"
|
|
57929
|
+
},
|
|
57930
|
+
volts: {
|
|
57931
|
+
kind: "gauge",
|
|
57932
|
+
unit: "V"
|
|
57933
|
+
}
|
|
57934
|
+
} },
|
|
57526
57935
|
customize: batteryCustomize,
|
|
57527
57936
|
/** Clock fields: written, but excluded from the compare that decides
|
|
57528
57937
|
* whether persisting is worth a SQLite commit. */
|
|
@@ -57569,12 +57978,7 @@ var binaryCapability = {
|
|
|
57569
57978
|
history: { fields: { on: { kind: "boolean" } } },
|
|
57570
57979
|
/** Clock fields: written, but excluded from the compare that decides
|
|
57571
57980
|
* whether persisting is worth a SQLite commit. */
|
|
57572
|
-
volatileStateFields: ["lastChangedAt"]
|
|
57573
|
-
customize: {
|
|
57574
|
-
version: 1,
|
|
57575
|
-
advanced: "derive",
|
|
57576
|
-
targets: []
|
|
57577
|
-
}
|
|
57981
|
+
volatileStateFields: ["lastChangedAt"]
|
|
57578
57982
|
};
|
|
57579
57983
|
/**
|
|
57580
57984
|
* Dimmable-light brightness control. Co-exists with `switch` on the
|
|
@@ -57590,7 +57994,7 @@ var binaryCapability = {
|
|
|
57590
57994
|
*/
|
|
57591
57995
|
var BrightnessStatusSchema = object({
|
|
57592
57996
|
/** Current level as 0..100 inclusive. Firmware-reported. */
|
|
57593
|
-
percentage: number().min(0).max(100),
|
|
57997
|
+
percentage: number().min(0).max(100).meta(readingMeta("percentage")),
|
|
57594
57998
|
/** Ms epoch of the last operator-driven change. Useful for UI freshness. */
|
|
57595
57999
|
lastChangedAt: number()
|
|
57596
58000
|
});
|
|
@@ -58044,21 +58448,21 @@ var ClimateControlStatusSchema = object({
|
|
|
58044
58448
|
/** Single setpoint in Celsius. Used by single-target modes
|
|
58045
58449
|
* (heat / cool / dry). Null when the device is in a range mode
|
|
58046
58450
|
* (`heat_cool`) or has no setpoint at all (`fan_only`/`off`). */
|
|
58047
|
-
target: number().nullable(),
|
|
58451
|
+
target: number().nullable().meta(readingMeta("temperature")),
|
|
58048
58452
|
/** Upper bound of the dual setpoint in Celsius. Populated only
|
|
58049
58453
|
* in `heat_cool` mode. */
|
|
58050
|
-
targetHigh: number().nullable(),
|
|
58454
|
+
targetHigh: number().nullable().meta(readingMeta("temperature")),
|
|
58051
58455
|
/** Lower bound of the dual setpoint in Celsius. Populated only
|
|
58052
58456
|
* in `heat_cool` mode. */
|
|
58053
|
-
targetLow: number().nullable(),
|
|
58457
|
+
targetLow: number().nullable().meta(readingMeta("temperature")),
|
|
58054
58458
|
/** Target relative humidity (0..100). Null when the device has no
|
|
58055
58459
|
* humidity control. */
|
|
58056
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
58460
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
58057
58461
|
/** Current measured temperature in Celsius. Read-only — pushed by
|
|
58058
58462
|
* the device's internal sensor. */
|
|
58059
|
-
currentTemp: number().nullable(),
|
|
58463
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
58060
58464
|
/** Current measured relative humidity (0..100). Read-only. */
|
|
58061
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
58465
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
58062
58466
|
/** Vertical louver swing on/off. Null when the device has no vertical
|
|
58063
58467
|
* swing surface (gate with `DeviceFeature.ClimateSwingVertical`). */
|
|
58064
58468
|
swingVertical: boolean().nullable(),
|
|
@@ -58066,11 +58470,11 @@ var ClimateControlStatusSchema = object({
|
|
|
58066
58470
|
* horizontal swing surface (gate with `DeviceFeature.ClimateSwingHorizontal`). */
|
|
58067
58471
|
swingHorizontal: boolean().nullable(),
|
|
58068
58472
|
/** Lowest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
58069
|
-
minTemp: number().nullable().optional(),
|
|
58473
|
+
minTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
58070
58474
|
/** Highest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
58071
|
-
maxTemp: number().nullable().optional(),
|
|
58475
|
+
maxTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
58072
58476
|
/** Setpoint granularity, Celsius (0.5, 1). Absent / null = not reported. */
|
|
58073
|
-
tempStep: number().positive().nullable().optional(),
|
|
58477
|
+
tempStep: number().positive().nullable().optional().meta(readingMeta("temperature")),
|
|
58074
58478
|
/** Ms epoch when the slice was last updated (push or command). */
|
|
58075
58479
|
lastFetchedAt: number()
|
|
58076
58480
|
});
|
|
@@ -58212,17 +58616,17 @@ var climateControlCapability = {
|
|
|
58212
58616
|
* modes to expose in the picker without a slice fetch.
|
|
58213
58617
|
*/
|
|
58214
58618
|
var RgbTripletSchema = object({
|
|
58215
|
-
r: number().int().min(0).max(255),
|
|
58216
|
-
g: number().int().min(0).max(255),
|
|
58217
|
-
b: number().int().min(0).max(255)
|
|
58619
|
+
r: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
58620
|
+
g: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
58621
|
+
b: number().int().min(0).max(255).meta(readingMeta("none"))
|
|
58218
58622
|
});
|
|
58219
58623
|
var HsvTripletSchema = object({
|
|
58220
58624
|
/** Hue in degrees, 0..360. */
|
|
58221
|
-
h: number().min(0).max(360),
|
|
58625
|
+
h: number().min(0).max(360).meta(readingMeta("none")),
|
|
58222
58626
|
/** Saturation as 0..100 inclusive. */
|
|
58223
|
-
s: number().min(0).max(100),
|
|
58627
|
+
s: number().min(0).max(100).meta(readingMeta("none")),
|
|
58224
58628
|
/** Value/brightness as 0..100 inclusive. */
|
|
58225
|
-
v: number().min(0).max(100)
|
|
58629
|
+
v: number().min(0).max(100).meta(readingMeta("none"))
|
|
58226
58630
|
});
|
|
58227
58631
|
var ColorInputSchema = discriminatedUnion("mode", [
|
|
58228
58632
|
object({
|
|
@@ -58251,7 +58655,7 @@ var ColorStatusSchema = object({
|
|
|
58251
58655
|
/** Populated when `mode === 'hsv'`. */
|
|
58252
58656
|
hsv: HsvTripletSchema.optional(),
|
|
58253
58657
|
/** Populated when `mode === 'mired'`. */
|
|
58254
|
-
mireds: number().int().optional(),
|
|
58658
|
+
mireds: number().int().optional().meta(readingMeta("colour-temperature")),
|
|
58255
58659
|
/** Ms epoch of the last operator-driven change. */
|
|
58256
58660
|
lastChangedAt: number()
|
|
58257
58661
|
});
|
|
@@ -58446,18 +58850,12 @@ _enum([
|
|
|
58446
58850
|
"empty",
|
|
58447
58851
|
"full"
|
|
58448
58852
|
]);
|
|
58449
|
-
/**
|
|
58450
|
-
|
|
58451
|
-
|
|
58452
|
-
"days",
|
|
58453
|
-
"hours",
|
|
58454
|
-
"cycles"
|
|
58455
|
-
]);
|
|
58456
|
-
/** Remaining life as a COUNT, not a percentage (the PetKit desiccant reports
|
|
58457
|
-
* days). `value` null = unknown (D393). */
|
|
58853
|
+
/** Whether `remaining.value` is a duration in seconds or a dimensionless count. */
|
|
58854
|
+
var ConsumableRemainingKindSchema = _enum(["duration", "count"]);
|
|
58855
|
+
/** Remaining life. `value` null = unknown (D393). Duration is seconds. */
|
|
58458
58856
|
var ConsumableRemainingSchema = object({
|
|
58459
|
-
value: number().min(0).nullable(),
|
|
58460
|
-
|
|
58857
|
+
value: number().min(0).nullable().meta(readingMeta("device")),
|
|
58858
|
+
kind: ConsumableRemainingKindSchema
|
|
58461
58859
|
});
|
|
58462
58860
|
/** A single consumable item. Either a continuous `level` (remaining
|
|
58463
58861
|
* life %, or fill % for a `supply` / `waste` item) or a discrete `status`
|
|
@@ -58470,7 +58868,7 @@ var ConsumableItemSchema = object({
|
|
|
58470
58868
|
/** Display name. */
|
|
58471
58869
|
label: string().min(1),
|
|
58472
58870
|
/** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
|
|
58473
|
-
level: number().min(0).max(100).nullable(),
|
|
58871
|
+
level: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58474
58872
|
/** The provider's discrete verdict when known (binary mode). */
|
|
58475
58873
|
status: ConsumableStatusSchema.nullable(),
|
|
58476
58874
|
/** What the item is — decides whether low or full is bad. Absent = `wear`. */
|
|
@@ -58552,8 +58950,8 @@ var consumablesCustomize = {
|
|
|
58552
58950
|
transforms: [{ kind: "identity" }]
|
|
58553
58951
|
}],
|
|
58554
58952
|
literals: [{
|
|
58555
|
-
path: "remaining.
|
|
58556
|
-
values: [...
|
|
58953
|
+
path: "remaining.kind",
|
|
58954
|
+
values: [...ConsumableRemainingKindSchema.options]
|
|
58557
58955
|
}]
|
|
58558
58956
|
},
|
|
58559
58957
|
{
|
|
@@ -58682,7 +59080,6 @@ reset: method(object({
|
|
|
58682
59080
|
},
|
|
58683
59081
|
"remaining.value": {
|
|
58684
59082
|
kind: "gauge",
|
|
58685
|
-
unitFrom: "remaining.unit",
|
|
58686
59083
|
deadband: 1,
|
|
58687
59084
|
displayName: "Remaining"
|
|
58688
59085
|
}
|
|
@@ -58752,10 +59149,9 @@ var contactCapability = {
|
|
|
58752
59149
|
* (empty array for the other kinds). It lives in the slice because
|
|
58753
59150
|
* HA `select.*` entities may update their options at runtime.
|
|
58754
59151
|
*
|
|
58755
|
-
*
|
|
58756
|
-
*
|
|
58757
|
-
*
|
|
58758
|
-
* push — consistent with `options` and the sensor-unit approach.
|
|
59152
|
+
* Numeric `min` / `max` / `step` live in the slice and share the device
|
|
59153
|
+
* quantity (`SourceInfo.quantity`, D944). Display precision is a read-time
|
|
59154
|
+
* preference. A datetime control's shape is `SourceInfo.dateTimeShape`.
|
|
58759
59155
|
*/
|
|
58760
59156
|
var ControlStatusSchema = object({
|
|
58761
59157
|
kind: _enum([
|
|
@@ -58767,39 +59163,17 @@ var ControlStatusSchema = object({
|
|
|
58767
59163
|
/** Current value. Numeric kind → number; select/text/datetime → string.
|
|
58768
59164
|
* Datetime values are ISO 8601 strings (full timestamp, date-only,
|
|
58769
59165
|
* or time-only — HA accepts all three forms). */
|
|
58770
|
-
value: union([number(), string()]),
|
|
59166
|
+
value: union([number().meta(readingMeta("device")), string()]),
|
|
58771
59167
|
/** Acceptable values when `kind === 'select'`. Empty for other kinds. */
|
|
58772
59168
|
options: array(string()),
|
|
58773
59169
|
/** Ms epoch when the slice was last updated. */
|
|
58774
59170
|
lastChangedAt: number(),
|
|
58775
|
-
/**
|
|
58776
|
-
|
|
58777
|
-
|
|
58778
|
-
|
|
58779
|
-
/**
|
|
58780
|
-
|
|
58781
|
-
min: number().optional(),
|
|
58782
|
-
/** Maximum allowed value. Populated live from HA `attributes.max`.
|
|
58783
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
58784
|
-
max: number().optional(),
|
|
58785
|
-
/** Step increment. Populated live from HA `attributes.step`.
|
|
58786
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
58787
|
-
step: number().optional(),
|
|
58788
|
-
/** Suggested decimal places for numeric display. Populated live from HA
|
|
58789
|
-
* `attributes.suggested_display_precision`, or derived from `step` when the
|
|
58790
|
-
* HA attribute is absent. Meaningful for `kind === 'numeric'`; absent for
|
|
58791
|
-
* other kinds. Falls back to auto-formatting when absent. */
|
|
58792
|
-
precision: number().int().min(0).max(10).optional(),
|
|
58793
|
-
/** Date-picker granularity for `kind === 'datetime'`. 'date' → date-only,
|
|
58794
|
-
* 'time' → time-only, 'datetime' → full timestamp. Absent for other kinds
|
|
58795
|
-
* (UI defaults to 'datetime'). Derived live from the device's HA domain
|
|
58796
|
-
* (date.* / time.* / datetime.*) or, for input_datetime, from the entity's
|
|
58797
|
-
* `has_date`/`has_time` attributes on each push. */
|
|
58798
|
-
format: _enum([
|
|
58799
|
-
"date",
|
|
58800
|
-
"time",
|
|
58801
|
-
"datetime"
|
|
58802
|
-
]).optional()
|
|
59171
|
+
/** Minimum allowed value, in the device quantity's base unit. */
|
|
59172
|
+
min: number().optional().meta(readingMeta("device")),
|
|
59173
|
+
/** Maximum allowed value, in the device quantity's base unit. */
|
|
59174
|
+
max: number().optional().meta(readingMeta("device")),
|
|
59175
|
+
/** Step increment, in the device quantity's base unit. */
|
|
59176
|
+
step: number().optional().meta(readingMeta("device"))
|
|
58803
59177
|
});
|
|
58804
59178
|
var ControlSetValueInputSchema = discriminatedUnion("kind", [
|
|
58805
59179
|
object({
|
|
@@ -58865,9 +59239,9 @@ var CoverStatusSchema = object({
|
|
|
58865
59239
|
]),
|
|
58866
59240
|
/** 0 = fully closed, 100 = fully open. Null when the device has
|
|
58867
59241
|
* no intermediate position surface. */
|
|
58868
|
-
position: number().min(0).max(100).nullable(),
|
|
59242
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58869
59243
|
/** 0 = closed slats, 100 = open slats. Null when no tilt support. */
|
|
58870
|
-
tiltPosition: number().min(0).max(100).nullable(),
|
|
59244
|
+
tiltPosition: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58871
59245
|
/** Ms epoch when the slice was last updated. */
|
|
58872
59246
|
lastChangedAt: number()
|
|
58873
59247
|
});
|
|
@@ -58970,9 +59344,9 @@ var NormalizedRangeSchema$1 = object({
|
|
|
58970
59344
|
var DayNightStatusSchema = object({
|
|
58971
59345
|
mode: DayNightModeSchema,
|
|
58972
59346
|
/** IR-cut trigger sensitivity, NORMALIZED 0–100 (higher = switches to night sooner). */
|
|
58973
|
-
sensitivity: number().optional(),
|
|
59347
|
+
sensitivity: number().optional().meta(readingMeta("none")),
|
|
58974
59348
|
/** Delay before the IR-cut filter flips, in seconds. */
|
|
58975
|
-
switchDelaySec: number().optional(),
|
|
59349
|
+
switchDelaySec: number().optional().meta(readingMeta("duration")),
|
|
58976
59350
|
lastFetchedAt: number()
|
|
58977
59351
|
});
|
|
58978
59352
|
/**
|
|
@@ -59190,11 +59564,11 @@ var DishwasherStatusSchema = object({
|
|
|
59190
59564
|
/** Feature keys of the programs the appliance currently offers — drives the UI selector. */
|
|
59191
59565
|
availablePrograms: array(string()),
|
|
59192
59566
|
/** Seconds remaining on the active cycle, or null when not running / not known. */
|
|
59193
|
-
remainingSeconds: number().int().nonnegative().nullable(),
|
|
59567
|
+
remainingSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
59194
59568
|
/** Seconds the delayed start is set to (time until the cycle starts), or null. */
|
|
59195
|
-
delayedStartSeconds: number().int().nonnegative().nullable(),
|
|
59569
|
+
delayedStartSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
59196
59570
|
/** Cycle completion 0..100, or null when not applicable. */
|
|
59197
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
59571
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59198
59572
|
/** True when the door is reported open; null when the door state is not known. */
|
|
59199
59573
|
doorOpen: boolean().nullable(),
|
|
59200
59574
|
/** True when the door is latched (locked) during a cycle; null when not reported. */
|
|
@@ -59218,7 +59592,7 @@ var DishwasherStatusSchema = object({
|
|
|
59218
59592
|
/** True while the machine-care (descaling / cleaning-program) reminder is raised; false when clear; null when not reported. */
|
|
59219
59593
|
machineCareDue: boolean().nullable(),
|
|
59220
59594
|
/** Program runs left before the machine-care reminder is due; null when the appliance does not say. */
|
|
59221
|
-
machineCareRemainingRuns: number().int().nonnegative().nullable(),
|
|
59595
|
+
machineCareRemainingRuns: number().int().nonnegative().nullable().meta(readingMeta("count")),
|
|
59222
59596
|
/** Option states: null when the appliance does not expose the option or has not said. */
|
|
59223
59597
|
halfLoad: boolean().nullable(),
|
|
59224
59598
|
hygienePlus: boolean().nullable(),
|
|
@@ -59233,7 +59607,7 @@ var DishwasherStatusSchema = object({
|
|
|
59233
59607
|
/** Feature keys of the events currently raised (salt low, rinse aid low, program finished, …). */
|
|
59234
59608
|
activeEvents: array(string()),
|
|
59235
59609
|
/** Numeric error code when the appliance reports one; null otherwise. */
|
|
59236
|
-
errorCode: number().nullable(),
|
|
59610
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
59237
59611
|
/** Name of the raised alert-level event while the appliance is in error; null otherwise. */
|
|
59238
59612
|
errorLabel: string().nullable(),
|
|
59239
59613
|
/** Ms epoch of the last value received from the appliance; 0 = never. */
|
|
@@ -59464,7 +59838,7 @@ var DoorbellStatusSchema = object({
|
|
|
59464
59838
|
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
59465
59839
|
lastPressedAt: number().nullable(),
|
|
59466
59840
|
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
59467
|
-
pressCountSinceStart: number()
|
|
59841
|
+
pressCountSinceStart: number().meta(readingMeta("count"))
|
|
59468
59842
|
});
|
|
59469
59843
|
var DoorbellPressEventSchema = object({
|
|
59470
59844
|
deviceId: number(),
|
|
@@ -59529,17 +59903,7 @@ onPressed: {
|
|
|
59529
59903
|
history: "none",
|
|
59530
59904
|
customize: doorbellCustomize
|
|
59531
59905
|
};
|
|
59532
|
-
|
|
59533
|
-
* Enum-state sensor — a string value picked from a finite option set.
|
|
59534
|
-
* Drives HA `sensor` entries with `state_class: enum` (HVAC action
|
|
59535
|
-
* states, weather conditions, contact-source channels, mode strings).
|
|
59536
|
-
* The option set is stable across observations; it is persisted in the
|
|
59537
|
-
* device config blob (via the control slice at adoption) and is NOT
|
|
59538
|
-
* stored in `sourceInfo`.
|
|
59539
|
-
*/
|
|
59540
|
-
/** Locale-render shape for an ISO `value` carried by a `DateTimeSensor`-role
|
|
59541
|
-
* enum sensor: `date` (date-only), `time` (time-only), `datetime` (both). */
|
|
59542
|
-
var EnumSensorDateTimeFormatSchema = _enum([
|
|
59906
|
+
_enum([
|
|
59543
59907
|
"date",
|
|
59544
59908
|
"time",
|
|
59545
59909
|
"datetime"
|
|
@@ -59547,12 +59911,11 @@ var EnumSensorDateTimeFormatSchema = _enum([
|
|
|
59547
59911
|
var EnumSensorStatusSchema = object({
|
|
59548
59912
|
value: string(),
|
|
59549
59913
|
/**
|
|
59550
|
-
* Set
|
|
59551
|
-
* as
|
|
59552
|
-
*
|
|
59553
|
-
* a time-only sensor → `'time'`.
|
|
59914
|
+
* Set when `value` is a timestamp rather than an enum state, so history
|
|
59915
|
+
* does not learn ISO strings as states. The display shape (date / time /
|
|
59916
|
+
* datetime) lives on `SourceInfo.dateTimeShape`, written once at adopt.
|
|
59554
59917
|
*/
|
|
59555
|
-
|
|
59918
|
+
timestamp: boolean().optional(),
|
|
59556
59919
|
/** Ms epoch when the slice was last updated. */
|
|
59557
59920
|
lastFetchedAt: number()
|
|
59558
59921
|
});
|
|
@@ -59579,11 +59942,11 @@ var enumSensorCapability = {
|
|
|
59579
59942
|
* History (D850): the value as an `enum` series (an appliance's program or
|
|
59580
59943
|
* operation state, an HVAC action). The option set is per device, so the
|
|
59581
59944
|
* value list is LEARNED as values are first seen (bounded). A sensor with a
|
|
59582
|
-
* `
|
|
59945
|
+
* `timestamp` carries a clock, not a state, and is not recorded.
|
|
59583
59946
|
*/
|
|
59584
59947
|
history: { fields: { value: {
|
|
59585
59948
|
kind: "enum",
|
|
59586
|
-
skipWhenSet: "
|
|
59949
|
+
skipWhenSet: "timestamp"
|
|
59587
59950
|
} } },
|
|
59588
59951
|
/** Clock fields: written, but excluded from the compare that decides
|
|
59589
59952
|
* whether persisting is worth a SQLite commit. */
|
|
@@ -59603,13 +59966,13 @@ var EventFireSchema = object({
|
|
|
59603
59966
|
deviceId: number(),
|
|
59604
59967
|
eventType: string(),
|
|
59605
59968
|
data: record(string(), unknown()).nullable(),
|
|
59606
|
-
timestamp: number(),
|
|
59607
|
-
seq: number()
|
|
59969
|
+
timestamp: number().meta(readingMeta("none")),
|
|
59970
|
+
seq: number().meta(readingMeta("count"))
|
|
59608
59971
|
});
|
|
59609
59972
|
var EventEmitterStatusSchema = object({
|
|
59610
59973
|
eventTypes: array(string()),
|
|
59611
59974
|
lastEvent: EventFireSchema.nullable(),
|
|
59612
|
-
eventCountSinceStart: number()
|
|
59975
|
+
eventCountSinceStart: number().meta(readingMeta("count"))
|
|
59613
59976
|
});
|
|
59614
59977
|
var eventEmitterCapability = {
|
|
59615
59978
|
name: "event-emitter",
|
|
@@ -60022,10 +60385,10 @@ var FanDirectionSchema = _enum(["forward", "reverse"]);
|
|
|
60022
60385
|
var FanControlStatusSchema = object({
|
|
60023
60386
|
/** Active speed as 0..100 inclusive. Null when the device has no
|
|
60024
60387
|
* speed surface (single-speed fan). */
|
|
60025
|
-
percentage: number().min(0).max(100).nullable(),
|
|
60388
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
60026
60389
|
/** Speed granularity the device accepts (HA `percentage_step`, e.g. 25 for
|
|
60027
60390
|
* a 4-speed fan). Absent when unknown — the UI then falls back to step 1. */
|
|
60028
|
-
percentageStep: number().positive().optional(),
|
|
60391
|
+
percentageStep: number().positive().optional().meta(readingMeta("percentage")),
|
|
60029
60392
|
/** Active preset mode (`auto` / `quiet` / `turbo` / vendor-specific)
|
|
60030
60393
|
* — empty string when no preset is active or supported. */
|
|
60031
60394
|
preset: string(),
|
|
@@ -60146,7 +60509,7 @@ var FeatureProbeStatusSchema = object({
|
|
|
60146
60509
|
/** Camera/firmware model string. `null` when the firmware doesn't expose it. */
|
|
60147
60510
|
model: string().nullable(),
|
|
60148
60511
|
/** Channel count for NVR/Hub devices; `1` for standalone cameras; `null` pre-probe. */
|
|
60149
|
-
channelCount: number().nullable(),
|
|
60512
|
+
channelCount: number().nullable().meta(readingMeta("count")),
|
|
60150
60513
|
/**
|
|
60151
60514
|
* Ms epoch of the last SUCCESSFUL probe. `0` before the first probe
|
|
60152
60515
|
* completes — drivers' `getAccessoryChildren()` should treat zero as
|
|
@@ -60269,9 +60632,91 @@ var gasCapability = {
|
|
|
60269
60632
|
* whether persisting is worth a SQLite commit. */
|
|
60270
60633
|
volatileStateFields: ["lastChangedAt"]
|
|
60271
60634
|
};
|
|
60635
|
+
var GroupCommandsSchema = object({
|
|
60636
|
+
/** One row per member that has been commanded. A later command replaces that member's row. */
|
|
60637
|
+
results: array(object({
|
|
60638
|
+
deviceId: number().int().nonnegative(),
|
|
60639
|
+
cap: string().min(1),
|
|
60640
|
+
method: string().min(1),
|
|
60641
|
+
ok: boolean(),
|
|
60642
|
+
error: string().optional(),
|
|
60643
|
+
/** Ms epoch of the attempt. */
|
|
60644
|
+
at: number()
|
|
60645
|
+
})) });
|
|
60646
|
+
var groupCommandsCapability = {
|
|
60647
|
+
name: "group-commands",
|
|
60648
|
+
scope: "device",
|
|
60649
|
+
deviceNative: true,
|
|
60650
|
+
mode: "singleton",
|
|
60651
|
+
deviceTypes: [DeviceType.Switch, DeviceType.Light],
|
|
60652
|
+
methods: {},
|
|
60653
|
+
status: {
|
|
60654
|
+
schema: GroupCommandsSchema,
|
|
60655
|
+
kind: "push"
|
|
60656
|
+
},
|
|
60657
|
+
runtimeState: GroupCommandsSchema,
|
|
60658
|
+
/**
|
|
60659
|
+
* Runtime-state durability: **session** — the last attempt. A restored
|
|
60660
|
+
* failure would outlive the command that caused it.
|
|
60661
|
+
*
|
|
60662
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
60663
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
60664
|
+
*/
|
|
60665
|
+
durability: "session",
|
|
60666
|
+
history: "none"
|
|
60667
|
+
};
|
|
60668
|
+
/**
|
|
60669
|
+
* How many members of a helper group answered (D944). Counts are integers,
|
|
60670
|
+
* not measurements: zero included is a real count, never a stand-in reading.
|
|
60671
|
+
* The reading itself stays on the output capability. History is none — the
|
|
60672
|
+
* series that later statistics read is the output cap's own history block.
|
|
60673
|
+
*/
|
|
60674
|
+
var GroupStatusSchema = object({
|
|
60675
|
+
/** Members whose current value entered the aggregate. */
|
|
60676
|
+
included: number().int().nonnegative().meta(readingMeta("count", {
|
|
60677
|
+
precision: 0,
|
|
60678
|
+
label: "Reporting"
|
|
60679
|
+
})),
|
|
60680
|
+
/** Members left out: offline, unknown, or not a finite reading (D393). */
|
|
60681
|
+
excluded: number().int().nonnegative().meta(readingMeta("count", {
|
|
60682
|
+
precision: 0,
|
|
60683
|
+
label: "Excluded"
|
|
60684
|
+
})),
|
|
60685
|
+
/** `included` + `excluded`. */
|
|
60686
|
+
total: number().int().nonnegative().meta(readingMeta("count", {
|
|
60687
|
+
precision: 0,
|
|
60688
|
+
label: "Members"
|
|
60689
|
+
}))
|
|
60690
|
+
});
|
|
60691
|
+
var groupStatusCapability = {
|
|
60692
|
+
name: "group-status",
|
|
60693
|
+
scope: "device",
|
|
60694
|
+
deviceNative: true,
|
|
60695
|
+
mode: "singleton",
|
|
60696
|
+
deviceTypes: [
|
|
60697
|
+
DeviceType.Sensor,
|
|
60698
|
+
DeviceType.Switch,
|
|
60699
|
+
DeviceType.Light
|
|
60700
|
+
],
|
|
60701
|
+
methods: {},
|
|
60702
|
+
status: {
|
|
60703
|
+
schema: GroupStatusSchema,
|
|
60704
|
+
kind: "push"
|
|
60705
|
+
},
|
|
60706
|
+
runtimeState: GroupStatusSchema,
|
|
60707
|
+
/**
|
|
60708
|
+
* Runtime-state durability: **session** — recomputed from members on the
|
|
60709
|
+
* next source event; a restored count would outlive the readings it named.
|
|
60710
|
+
*
|
|
60711
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
60712
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
60713
|
+
*/
|
|
60714
|
+
durability: "session",
|
|
60715
|
+
history: "none"
|
|
60716
|
+
};
|
|
60272
60717
|
var HeatingValveStatusSchema = object({
|
|
60273
60718
|
/** Radiator valve opening 0 (closed) .. 100 (open). Null = not yet known. */
|
|
60274
|
-
position: number().min(0).max(100).nullable(),
|
|
60719
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
60275
60720
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
60276
60721
|
lastFetchedAt: number()
|
|
60277
60722
|
});
|
|
@@ -60314,9 +60759,9 @@ var HumidifierStatusSchema = object({
|
|
|
60314
60759
|
/** Whether the humidifier is currently on. */
|
|
60315
60760
|
on: boolean(),
|
|
60316
60761
|
/** Current measured relative humidity (0..100). Null when not reported. */
|
|
60317
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
60762
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
60318
60763
|
/** Target relative humidity (0..100). Null when no setpoint surface. */
|
|
60319
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
60764
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
60320
60765
|
/** Active mode (`auto` / `normal` / `baby` / vendor). Null when the
|
|
60321
60766
|
* device has no mode surface. */
|
|
60322
60767
|
mode: string().nullable(),
|
|
@@ -60326,9 +60771,9 @@ var HumidifierStatusSchema = object({
|
|
|
60326
60771
|
* `idle` / `off`). Null when the device doesn't report it. */
|
|
60327
60772
|
action: string().nullable(),
|
|
60328
60773
|
/** HA `min_humidity` attribute. Null → UI uses 0. */
|
|
60329
|
-
minHumidity: number().nullable(),
|
|
60774
|
+
minHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
60330
60775
|
/** HA `max_humidity` attribute. Null → UI uses 100. */
|
|
60331
|
-
maxHumidity: number().nullable(),
|
|
60776
|
+
maxHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
60332
60777
|
/** Ms epoch when the slice was last updated. */
|
|
60333
60778
|
lastChangedAt: number()
|
|
60334
60779
|
});
|
|
@@ -60398,22 +60843,13 @@ var humidifierCapability = {
|
|
|
60398
60843
|
* `sourceInfo`.
|
|
60399
60844
|
*/
|
|
60400
60845
|
var HumiditySensorStatusSchema = object({
|
|
60401
|
-
/** Current relative humidity, 0..100. */
|
|
60402
|
-
percent: number().min(0).max(100).meta({
|
|
60403
|
-
|
|
60846
|
+
/** Current relative humidity, 0..100. `null` when the sample was refused (D393). */
|
|
60847
|
+
percent: number().min(0).max(100).nullable().meta(readingMeta("humidity", {
|
|
60848
|
+
precision: 0,
|
|
60404
60849
|
label: "Humidity"
|
|
60405
|
-
}),
|
|
60850
|
+
})),
|
|
60406
60851
|
/** Ms epoch when the slice was last updated. */
|
|
60407
|
-
lastFetchedAt: number()
|
|
60408
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
60409
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
60410
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
60411
|
-
unit: string().optional(),
|
|
60412
|
-
/** Suggested decimal places for numeric display.
|
|
60413
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
60414
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
60415
|
-
* auto-formatting when absent. */
|
|
60416
|
-
precision: number().int().min(0).max(10).optional()
|
|
60852
|
+
lastFetchedAt: number()
|
|
60417
60853
|
});
|
|
60418
60854
|
var humiditySensorCapability = {
|
|
60419
60855
|
name: "humidity-sensor",
|
|
@@ -60444,12 +60880,7 @@ var humiditySensorCapability = {
|
|
|
60444
60880
|
} } },
|
|
60445
60881
|
/** Clock fields: written, but excluded from the compare that decides
|
|
60446
60882
|
* whether persisting is worth a SQLite commit. */
|
|
60447
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
60448
|
-
customize: {
|
|
60449
|
-
version: 1,
|
|
60450
|
-
advanced: "derive",
|
|
60451
|
-
targets: []
|
|
60452
|
-
}
|
|
60883
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
60453
60884
|
};
|
|
60454
60885
|
/**
|
|
60455
60886
|
* Image display cap. Models a single still image exposed by an integration —
|
|
@@ -60470,7 +60901,7 @@ var ImageStatusSchema = object({
|
|
|
60470
60901
|
* entity exposes no `entity_picture` (yet). */
|
|
60471
60902
|
url: string().nullable(),
|
|
60472
60903
|
/** Ms epoch of the upstream last-updated timestamp. Null at cold-start. */
|
|
60473
|
-
lastUpdated: number().nullable()
|
|
60904
|
+
lastUpdated: number().nullable().meta(readingMeta("none"))
|
|
60474
60905
|
});
|
|
60475
60906
|
var imageCapability = {
|
|
60476
60907
|
name: "image",
|
|
@@ -60558,19 +60989,19 @@ var NormalizedRangeSchema = object({
|
|
|
60558
60989
|
*/
|
|
60559
60990
|
var ImageSettingsStatusSchema = object({
|
|
60560
60991
|
/** Normalized 0–100. */
|
|
60561
|
-
brightness: number().optional(),
|
|
60992
|
+
brightness: number().optional().meta(readingMeta("none")),
|
|
60562
60993
|
/** Normalized 0–100. */
|
|
60563
|
-
contrast: number().optional(),
|
|
60994
|
+
contrast: number().optional().meta(readingMeta("none")),
|
|
60564
60995
|
/** Normalized 0–100. */
|
|
60565
|
-
saturation: number().optional(),
|
|
60996
|
+
saturation: number().optional().meta(readingMeta("none")),
|
|
60566
60997
|
/** Normalized 0–100. */
|
|
60567
|
-
sharpness: number().optional(),
|
|
60998
|
+
sharpness: number().optional().meta(readingMeta("none")),
|
|
60568
60999
|
mirror: boolean().optional(),
|
|
60569
61000
|
flip: boolean().optional(),
|
|
60570
61001
|
rotate: ImageRotateSchema.optional(),
|
|
60571
61002
|
whiteBalance: WhiteBalanceModeSchema.optional(),
|
|
60572
61003
|
/** Manual white-balance warmth, NORMALIZED 0–100. Meaningful only when `whiteBalance === 'manual'`. */
|
|
60573
|
-
warmth: number().optional(),
|
|
61004
|
+
warmth: number().optional().meta(readingMeta("none")),
|
|
60574
61005
|
exposureMode: ExposureModeSchema.optional(),
|
|
60575
61006
|
backlightMode: BacklightModeSchema.optional(),
|
|
60576
61007
|
lastFetchedAt: number()
|
|
@@ -60849,10 +61280,10 @@ var IntercomAbilitySchema = object({
|
|
|
60849
61280
|
/** Codecs accepted by firmware, in preference order. Driver-authored strings. */
|
|
60850
61281
|
codecs: array(string()),
|
|
60851
61282
|
/** Sample rate (Hz) the firmware expects. Reolink typical: 16000. */
|
|
60852
|
-
sampleRate: number(),
|
|
61283
|
+
sampleRate: number().meta(readingMeta("none")),
|
|
60853
61284
|
duplex: _enum(["half", "full"]),
|
|
60854
61285
|
/** Max in-flight audio backlog before drop (ms). Server uses this to bound latency. */
|
|
60855
|
-
maxBacklogMs: number()
|
|
61286
|
+
maxBacklogMs: number().meta(readingMeta("duration-ms"))
|
|
60856
61287
|
});
|
|
60857
61288
|
var IntercomStatusSchema = object({
|
|
60858
61289
|
/** True while a talk session is open. */
|
|
@@ -61079,13 +61510,13 @@ var LawnMowerControlStatusSchema = object({
|
|
|
61079
61510
|
activity: LawnMowerActivitySchema,
|
|
61080
61511
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
61081
61512
|
* reading. */
|
|
61082
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
61513
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61083
61514
|
/** 0..100 mowing-completion percentage of the current task, or null when no
|
|
61084
61515
|
* task is active / progress is unavailable. */
|
|
61085
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
61516
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61086
61517
|
/** Current device/event code (dynamic — mostly status, sometimes an error),
|
|
61087
61518
|
* or null when unknown. */
|
|
61088
|
-
currentCode: number().nullable(),
|
|
61519
|
+
currentCode: number().nullable().meta(readingMeta("none")),
|
|
61089
61520
|
/** Human label for {@link currentCode}, or null when undecodable. */
|
|
61090
61521
|
currentCodeLabel: string().nullable(),
|
|
61091
61522
|
/** Severity of {@link currentCode}. `error` (and often `warning`) warrants UI
|
|
@@ -61618,7 +62049,7 @@ var MediaPlayerStatusSchema = object({
|
|
|
61618
62049
|
state: MediaPlayerStateSchema,
|
|
61619
62050
|
/** Volume as 0..100 inclusive. Null when the device has no volume
|
|
61620
62051
|
* surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
|
|
61621
|
-
volumeLevel: number().min(0).max(100).nullable(),
|
|
62052
|
+
volumeLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61622
62053
|
/** Mute toggle distinct from volume=0. Null when no mute surface.
|
|
61623
62054
|
* Pair with `DeviceFeature.MediaPlayerMute`. */
|
|
61624
62055
|
isMuted: boolean().nullable(),
|
|
@@ -61631,10 +62062,10 @@ var MediaPlayerStatusSchema = object({
|
|
|
61631
62062
|
currentMedia: MediaInfoSchema.nullable(),
|
|
61632
62063
|
/** Current playback position in ms. Null when not seekable or
|
|
61633
62064
|
* nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
|
|
61634
|
-
positionMs: number().int().nonnegative().nullable(),
|
|
62065
|
+
positionMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
61635
62066
|
/** Total duration of the current media in ms. Null when unknown
|
|
61636
62067
|
* (live stream) or nothing is playing. */
|
|
61637
|
-
durationMs: number().int().nonnegative().nullable(),
|
|
62068
|
+
durationMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
61638
62069
|
/** Shuffle toggle. Null when no shuffle surface.
|
|
61639
62070
|
* Pair with `DeviceFeature.MediaPlayerShuffle`. */
|
|
61640
62071
|
shuffle: boolean().nullable(),
|
|
@@ -61943,7 +62374,7 @@ var motionCustomize = {
|
|
|
61943
62374
|
eventName: "onMotionChanged"
|
|
61944
62375
|
},
|
|
61945
62376
|
deviceTypes: [DeviceType.Camera],
|
|
61946
|
-
apply: "
|
|
62377
|
+
apply: "add",
|
|
61947
62378
|
applyAuthority: {
|
|
61948
62379
|
kind: "camera-sensors",
|
|
61949
62380
|
timeoutField: "motionCooldownMs"
|
|
@@ -62015,7 +62446,7 @@ var MotionStatusSchema = object({
|
|
|
62015
62446
|
* it, every provider seeded it at boot, and every session left it
|
|
62016
62447
|
* `detected: true` after its detach.
|
|
62017
62448
|
*/
|
|
62018
|
-
autoClearAfterMs: number().nullable()
|
|
62449
|
+
autoClearAfterMs: number().nullable().meta(readingMeta("duration-ms"))
|
|
62019
62450
|
});
|
|
62020
62451
|
/**
|
|
62021
62452
|
* Payload of `motion.onMotionChanged` event + the corresponding bus
|
|
@@ -62052,12 +62483,18 @@ var motionCapability = {
|
|
|
62052
62483
|
methods: {
|
|
62053
62484
|
/**
|
|
62054
62485
|
* Pull the current motion state synchronously. Convenience shortcut
|
|
62055
|
-
* for consumers that don't need the full status object
|
|
62056
|
-
*
|
|
62057
|
-
* `getStatus` once the auto-injected status surface lands in every
|
|
62058
|
-
* consumer.
|
|
62486
|
+
* for consumers that don't need the full status object. A composed
|
|
62487
|
+
* group answers from its slice (D944): unknown throws, it is not off.
|
|
62059
62488
|
*/
|
|
62060
62489
|
isDetected: method(object({ deviceId: number() }), boolean()) },
|
|
62490
|
+
/**
|
|
62491
|
+
* A composed motion group serves `isDetected` from `detected` (D944).
|
|
62492
|
+
* Without this the cap stays uncomposable (`has-commands`).
|
|
62493
|
+
*/
|
|
62494
|
+
composedMethods: { isDetected: {
|
|
62495
|
+
kind: "slice",
|
|
62496
|
+
field: "detected"
|
|
62497
|
+
} },
|
|
62061
62498
|
events: {
|
|
62062
62499
|
/**
|
|
62063
62500
|
* Fires every time the runner transitions a camera between
|
|
@@ -62197,7 +62634,7 @@ var MotionZoneRegionSchema = object({
|
|
|
62197
62634
|
* the grid region(s). */
|
|
62198
62635
|
var MotionZoneStatusSchema = object({
|
|
62199
62636
|
enabled: boolean(),
|
|
62200
|
-
sensitivity: number(),
|
|
62637
|
+
sensitivity: number().meta(readingMeta("none")),
|
|
62201
62638
|
/** Grid region(s). Today exactly one `grid` shape. */
|
|
62202
62639
|
regions: array(MotionZoneRegionSchema),
|
|
62203
62640
|
lastFetchedAt: number()
|
|
@@ -62567,7 +63004,7 @@ var NavigationStatusSchema = object({
|
|
|
62567
63004
|
following: boolean(),
|
|
62568
63005
|
flash: boolean(),
|
|
62569
63006
|
lightMode: NavigationLightModeSchema,
|
|
62570
|
-
lightLevel: number().min(40).max(100),
|
|
63007
|
+
lightLevel: number().min(40).max(100).meta(readingMeta("none")),
|
|
62571
63008
|
/** Ms epoch when the slice was last updated. */
|
|
62572
63009
|
lastChangedAt: number()
|
|
62573
63010
|
});
|
|
@@ -62701,13 +63138,13 @@ var NetworkLinkStatusSchema = object({
|
|
|
62701
63138
|
* one whose reading has not landed must not be drawn at 0 %. Consumers
|
|
62702
63139
|
* SKIP a null rather than coerce it.
|
|
62703
63140
|
*/
|
|
62704
|
-
signalPercent: number().min(0).max(100).nullable(),
|
|
63141
|
+
signalPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
62705
63142
|
/** Raw received signal strength in dBm, when the firmware reports one. */
|
|
62706
|
-
rssiDbm: number().optional(),
|
|
63143
|
+
rssiDbm: number().optional().meta(readingMeta("signal-level")),
|
|
62707
63144
|
/** Network name of a wireless link, when the firmware reports it. */
|
|
62708
63145
|
ssid: string().optional(),
|
|
62709
63146
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
62710
|
-
lastUpdated: number()
|
|
63147
|
+
lastUpdated: number().meta(readingMeta("none"))
|
|
62711
63148
|
});
|
|
62712
63149
|
var networkLinkCapability = {
|
|
62713
63150
|
name: "network-link",
|
|
@@ -63092,7 +63529,7 @@ var NotifierStatusSchema = object({
|
|
|
63092
63529
|
lastError: string().nullable(),
|
|
63093
63530
|
/** Number of deliveries currently buffered server-side (rate-limited
|
|
63094
63531
|
* notifiers may queue). 0 when the provider sends synchronously. */
|
|
63095
|
-
queueDepth: number().int().nonnegative(),
|
|
63532
|
+
queueDepth: number().int().nonnegative().meta(readingMeta("count")),
|
|
63096
63533
|
/** Per-feature capability matrix — authoritative source for the
|
|
63097
63534
|
* compose-form field gating. */
|
|
63098
63535
|
supports: NotifierSupportsSchema
|
|
@@ -63184,11 +63621,9 @@ onSent: { data: object({
|
|
|
63184
63621
|
* cap fits (HA `sensor` whose `device_class` we don't have a typed cap
|
|
63185
63622
|
* for: water flow, distance, weight, frequency, signal strength, …).
|
|
63186
63623
|
*
|
|
63187
|
-
* The
|
|
63188
|
-
*
|
|
63189
|
-
*
|
|
63190
|
-
* The UI reads them directly from the slice — they are the single source
|
|
63191
|
-
* of truth for generic numeric rendering and do NOT live on `sourceInfo`.
|
|
63624
|
+
* The quantity is not on this slice. It is chosen when the device is
|
|
63625
|
+
* adopted and stored once on `SourceInfo.quantity` (D944). `value` is in
|
|
63626
|
+
* that quantity's base unit. `null` is a refused sample (D393).
|
|
63192
63627
|
*
|
|
63193
63628
|
* Prefer the typed alternatives (`temperature-sensor`, `humidity-sensor`,
|
|
63194
63629
|
* `ambient-light-sensor`, `pressure-sensor`, `power-meter`,
|
|
@@ -63197,15 +63632,8 @@ onSent: { data: object({
|
|
|
63197
63632
|
* numeric values land here.
|
|
63198
63633
|
*/
|
|
63199
63634
|
var NumericSensorStatusSchema = object({
|
|
63200
|
-
|
|
63201
|
-
|
|
63202
|
-
* Populated live from the upstream source on each state push.
|
|
63203
|
-
* Absent for unitless sensors. */
|
|
63204
|
-
unit: string().optional(),
|
|
63205
|
-
/** Suggested decimal places for numeric display.
|
|
63206
|
-
* Populated live from the upstream source when provided.
|
|
63207
|
-
* Falls back to auto-formatting when absent. */
|
|
63208
|
-
precision: number().int().min(0).max(10).optional(),
|
|
63635
|
+
/** Reading in the device quantity's base unit. `null` when refused (D393). */
|
|
63636
|
+
value: number().nullable().meta(readingMeta("device")),
|
|
63209
63637
|
/** Ms epoch when the slice was last updated. */
|
|
63210
63638
|
lastFetchedAt: number()
|
|
63211
63639
|
});
|
|
@@ -63229,11 +63657,11 @@ var numericSensorCapability = {
|
|
|
63229
63657
|
*/
|
|
63230
63658
|
durability: "restored",
|
|
63231
63659
|
/**
|
|
63232
|
-
* History (D850): recorded series. The unit is
|
|
63660
|
+
* History (D850): recorded series. The unit is the device quantity's base,
|
|
63661
|
+
* resolved when the series is read — the cap has no single unit.
|
|
63233
63662
|
*/
|
|
63234
63663
|
history: { fields: { value: {
|
|
63235
63664
|
kind: "gauge",
|
|
63236
|
-
unitFrom: "unit",
|
|
63237
63665
|
minIntervalMs: 3e4
|
|
63238
63666
|
} } },
|
|
63239
63667
|
/** Clock fields: written, but excluded from the compare that decides
|
|
@@ -63571,23 +63999,26 @@ var PetFeederStatusSchema = object({
|
|
|
63571
63999
|
/** Food currently in the bowl (grams). Null when the device has not
|
|
63572
64000
|
* reported a reading yet. On dual-hopper models this is the combined
|
|
63573
64001
|
* bowl reading; per-hopper levels live in `food1`/`food2`. */
|
|
63574
|
-
foodLevel: number().nullable(),
|
|
64002
|
+
foodLevel: number().nullable().meta(readingMeta("none")),
|
|
63575
64003
|
/** Hopper-1 food level (grams) on dual-hopper feeders; null on
|
|
63576
64004
|
* single-hopper models. */
|
|
63577
|
-
food1: number().nullable(),
|
|
64005
|
+
food1: number().nullable().meta(readingMeta("none")),
|
|
63578
64006
|
/** Hopper-2 food level (grams) on dual-hopper feeders; null on
|
|
63579
64007
|
* single-hopper models. */
|
|
63580
|
-
food2: number().nullable(),
|
|
64008
|
+
food2: number().nullable().meta(readingMeta("none")),
|
|
63581
64009
|
/** Derived low-food flag — mirrors the HA `food_level` binary_sensor
|
|
63582
64010
|
* (`device_class: problem`, on = low). True when the bowl is empty /
|
|
63583
64011
|
* below the feeder's low threshold. */
|
|
63584
64012
|
lowFood: boolean(),
|
|
63585
64013
|
/** Battery charge 0..100 (%). Null on mains-powered models or when the
|
|
63586
64014
|
* device has no battery reading. */
|
|
63587
|
-
batteryPower: number().min(0).max(100).nullable(),
|
|
63588
|
-
/**
|
|
63589
|
-
*
|
|
63590
|
-
|
|
64015
|
+
batteryPower: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
64016
|
+
/**
|
|
64017
|
+
* Desiccant life remaining, stored in seconds (duration base, D944).
|
|
64018
|
+
* Providers convert from the days the feeder reports. Null when the
|
|
64019
|
+
* model has no desiccant sensor.
|
|
64020
|
+
*/
|
|
64021
|
+
desiccantLeftDays: number().nullable().meta(readingMeta("duration")),
|
|
63591
64022
|
/** True while a feed is in progress. */
|
|
63592
64023
|
feeding: boolean(),
|
|
63593
64024
|
/** Decoded connectivity / power status (HA petkit device-status enum).
|
|
@@ -63598,7 +64029,7 @@ var PetFeederStatusSchema = object({
|
|
|
63598
64029
|
* with `errorCode` for consumers that want the raw integer. */
|
|
63599
64030
|
error: string().nullable(),
|
|
63600
64031
|
/** Raw device error code (0 / null = no error). */
|
|
63601
|
-
errorCode: number().nullable(),
|
|
64032
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
63602
64033
|
/** True for D4S/D4SH dual-hopper hardware — gates the per-hopper UI. */
|
|
63603
64034
|
isDualHopper: boolean(),
|
|
63604
64035
|
/** Child-lock (manual-lock) setting — buttons on the unit are disabled. */
|
|
@@ -63608,7 +64039,7 @@ var PetFeederStatusSchema = object({
|
|
|
63608
64039
|
/** Play a chime when dispensing. */
|
|
63609
64040
|
feedSound: boolean(),
|
|
63610
64041
|
/** Speaker / prompt volume level (device-scaled integer). */
|
|
63611
|
-
volume: number(),
|
|
64042
|
+
volume: number().meta(readingMeta("none")),
|
|
63612
64043
|
/** Ms epoch when the slice was last refreshed from the cloud. */
|
|
63613
64044
|
lastFetchedAt: number()
|
|
63614
64045
|
});
|
|
@@ -63727,7 +64158,7 @@ var petFeederCapability = {
|
|
|
63727
64158
|
},
|
|
63728
64159
|
desiccantLeftDays: {
|
|
63729
64160
|
kind: "gauge",
|
|
63730
|
-
unit: "
|
|
64161
|
+
unit: "s"
|
|
63731
64162
|
}
|
|
63732
64163
|
} }
|
|
63733
64164
|
};
|
|
@@ -64128,36 +64559,19 @@ method(_void(), PlatformCapabilitiesSchema), method(_void(), HardwareInfoSchema)
|
|
|
64128
64559
|
*/
|
|
64129
64560
|
var PowerMeterStatusSchema = object({
|
|
64130
64561
|
/** Instantaneous power draw in watts. */
|
|
64131
|
-
watts: number().optional().meta({
|
|
64132
|
-
unit: "W",
|
|
64133
|
-
label: "Power"
|
|
64134
|
-
}),
|
|
64562
|
+
watts: number().optional().meta(readingMeta("power", { label: "Power" })),
|
|
64135
64563
|
/** Cumulative energy in kilowatt-hours since the meter was reset. */
|
|
64136
|
-
kwhTotal: number().optional().meta({
|
|
64137
|
-
unit: "kWh",
|
|
64138
|
-
label: "Energy"
|
|
64139
|
-
}),
|
|
64564
|
+
kwhTotal: number().optional().meta(readingMeta("energy", { label: "Energy" })),
|
|
64140
64565
|
/** Voltage in volts. */
|
|
64141
|
-
volts: number().optional(),
|
|
64566
|
+
volts: number().optional().meta(readingMeta("voltage")),
|
|
64142
64567
|
/** Current in amperes. */
|
|
64143
|
-
amps: number().optional(),
|
|
64144
|
-
/** Apparent power in volt-amperes
|
|
64145
|
-
va: number().optional(),
|
|
64568
|
+
amps: number().optional().meta(readingMeta("current")),
|
|
64569
|
+
/** Apparent power in volt-amperes. */
|
|
64570
|
+
va: number().optional().meta(readingMeta("apparent-power")),
|
|
64146
64571
|
/** Power factor (0..1) if reported. */
|
|
64147
|
-
powerFactor: number().min(0).max(1).optional(),
|
|
64572
|
+
powerFactor: number().min(0).max(1).optional().meta(readingMeta("ratio")),
|
|
64148
64573
|
/** Ms epoch when the slice was last updated. */
|
|
64149
|
-
lastFetchedAt: number()
|
|
64150
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
64151
|
-
* `attributes.unit_of_measurement` → 'V' / 'A' / 'W' / 'kW' / 'kWh').
|
|
64152
|
-
* Each upstream `sensor.*` entity surfaces ONE device_class, so one
|
|
64153
|
-
* unit per slice is unambiguous. The UI prefers this over the role's
|
|
64154
|
-
* canonical unit so a 'kW' / 'Wh' feed renders verbatim. */
|
|
64155
|
-
unit: string().optional(),
|
|
64156
|
-
/** Suggested decimal places for numeric display.
|
|
64157
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
64158
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
64159
|
-
* auto-formatting when absent. */
|
|
64160
|
-
precision: number().int().min(0).max(10).optional()
|
|
64574
|
+
lastFetchedAt: number()
|
|
64161
64575
|
});
|
|
64162
64576
|
var powerMeterCapability = {
|
|
64163
64577
|
name: "power-meter",
|
|
@@ -64221,12 +64635,7 @@ var powerMeterCapability = {
|
|
|
64221
64635
|
} },
|
|
64222
64636
|
/** Clock fields: written, but excluded from the compare that decides
|
|
64223
64637
|
* whether persisting is worth a SQLite commit. */
|
|
64224
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
64225
|
-
customize: {
|
|
64226
|
-
version: 1,
|
|
64227
|
-
advanced: "derive",
|
|
64228
|
-
targets: []
|
|
64229
|
-
}
|
|
64638
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
64230
64639
|
};
|
|
64231
64640
|
/**
|
|
64232
64641
|
* Presence cap. Models HA `person.*` and `device_tracker.*` entities
|
|
@@ -64246,11 +64655,11 @@ var powerMeterCapability = {
|
|
|
64246
64655
|
*/
|
|
64247
64656
|
var GpsLocationSchema = object({
|
|
64248
64657
|
/** Latitude in decimal degrees, -90..90. */
|
|
64249
|
-
latitude: number().min(-90).max(90),
|
|
64658
|
+
latitude: number().min(-90).max(90).meta(readingMeta("angle")),
|
|
64250
64659
|
/** Longitude in decimal degrees, -180..180. */
|
|
64251
|
-
longitude: number().min(-180).max(180),
|
|
64660
|
+
longitude: number().min(-180).max(180).meta(readingMeta("angle")),
|
|
64252
64661
|
/** Reported accuracy in meters (lower = better). */
|
|
64253
|
-
accuracyMeters: number().nonnegative()
|
|
64662
|
+
accuracyMeters: number().nonnegative().meta(readingMeta("length"))
|
|
64254
64663
|
});
|
|
64255
64664
|
var PresenceStatusSchema = object({
|
|
64256
64665
|
/** `home` / `not_home` / any user-defined zone name. */
|
|
@@ -64262,7 +64671,7 @@ var PresenceStatusSchema = object({
|
|
|
64262
64671
|
gps: GpsLocationSchema.nullable(),
|
|
64263
64672
|
/** Optional battery level of the tracking device (0..100). Null
|
|
64264
64673
|
* when not reported. */
|
|
64265
|
-
batteryPercent: number().min(0).max(100).nullable(),
|
|
64674
|
+
batteryPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
64266
64675
|
/** Ms epoch when the slice was last updated. */
|
|
64267
64676
|
lastChangedAt: number()
|
|
64268
64677
|
});
|
|
@@ -64312,19 +64721,10 @@ var presenceCapability = {
|
|
|
64312
64721
|
* `sourceInfo`.
|
|
64313
64722
|
*/
|
|
64314
64723
|
var PressureSensorStatusSchema = object({
|
|
64315
|
-
/** Current pressure in hPa. */
|
|
64316
|
-
hpa: number(),
|
|
64724
|
+
/** Current pressure in hPa. `null` when the sample was refused (D393). */
|
|
64725
|
+
hpa: number().nullable().meta(readingMeta("pressure", { precision: 0 })),
|
|
64317
64726
|
/** Ms epoch when the slice was last updated. */
|
|
64318
|
-
lastFetchedAt: number()
|
|
64319
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
64320
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
64321
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
64322
|
-
unit: string().optional(),
|
|
64323
|
-
/** Suggested decimal places for numeric display.
|
|
64324
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
64325
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
64326
|
-
* auto-formatting when absent. */
|
|
64327
|
-
precision: number().int().min(0).max(10).optional()
|
|
64727
|
+
lastFetchedAt: number()
|
|
64328
64728
|
});
|
|
64329
64729
|
var pressureSensorCapability = {
|
|
64330
64730
|
name: "pressure-sensor",
|
|
@@ -64850,8 +65250,8 @@ var ptzCapability = {
|
|
|
64850
65250
|
};
|
|
64851
65251
|
var PtzAutotrackSettingsSchema = object({
|
|
64852
65252
|
targetType: string().describe("Vendor target string (people/vehicle/pet); empty = camera default"),
|
|
64853
|
-
stopDelaySeconds: number().int().min(0).max(300),
|
|
64854
|
-
disappearDelaySeconds: number().int().min(0).max(300)
|
|
65253
|
+
stopDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration")),
|
|
65254
|
+
disappearDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration"))
|
|
64855
65255
|
});
|
|
64856
65256
|
/**
|
|
64857
65257
|
* One option the camera advertises as a valid `targetType`. Drivers
|
|
@@ -65005,7 +65405,7 @@ var RunningStateStatusSchema = object({
|
|
|
65005
65405
|
/** null = unknown — never coerced to false (D393). */
|
|
65006
65406
|
running: boolean().nullable(),
|
|
65007
65407
|
/** Epoch ms the current boolean began; null while `running` is null. */
|
|
65008
|
-
since: number().nullable(),
|
|
65408
|
+
since: number().nullable().meta(readingMeta("none")),
|
|
65009
65409
|
source: RunningStateSourceSchema.meta({ label: "Source" }),
|
|
65010
65410
|
phase: string().nullable(),
|
|
65011
65411
|
/** null until a reading has been published (D393). */
|
|
@@ -65020,7 +65420,6 @@ var RUNNING_DEVICE_TYPES = Object.values(DeviceType);
|
|
|
65020
65420
|
/** Generic Customize target for the running boolean (D936). */
|
|
65021
65421
|
var runningCustomize = {
|
|
65022
65422
|
version: 1,
|
|
65023
|
-
advanced: "derive",
|
|
65024
65423
|
targets: [{
|
|
65025
65424
|
id: "running",
|
|
65026
65425
|
cardinality: "scalar",
|
|
@@ -65040,7 +65439,7 @@ var runningCustomize = {
|
|
|
65040
65439
|
DeviceType.Thermostat,
|
|
65041
65440
|
DeviceType.PetFeeder
|
|
65042
65441
|
],
|
|
65043
|
-
apply: "add
|
|
65442
|
+
apply: "add",
|
|
65044
65443
|
path: "running",
|
|
65045
65444
|
sources: [
|
|
65046
65445
|
{
|
|
@@ -66308,9 +66707,9 @@ var RecordTriggerSchema = _enum([
|
|
|
66308
66707
|
*/
|
|
66309
66708
|
var RecordWindowSchema = object({
|
|
66310
66709
|
trigger: RecordTriggerSchema,
|
|
66311
|
-
day: number().int().min(0).max(6),
|
|
66312
|
-
startMinute: number().int().min(0).max(1439),
|
|
66313
|
-
endMinute: number().int().min(1).max(1440)
|
|
66710
|
+
day: number().int().min(0).max(6).meta(readingMeta("none")),
|
|
66711
|
+
startMinute: number().int().min(0).max(1439).meta(readingMeta("none")),
|
|
66712
|
+
endMinute: number().int().min(1).max(1440).meta(readingMeta("none"))
|
|
66314
66713
|
});
|
|
66315
66714
|
/** Status of one physical volume, as the camera itself describes it. */
|
|
66316
66715
|
var OnboardStorageVolumeSchema = object({
|
|
@@ -66386,10 +66785,10 @@ var RecordingOnboardStatusSchema = object({
|
|
|
66386
66785
|
/** Master "record to the card at all" switch. */
|
|
66387
66786
|
enabled: boolean().nullable(),
|
|
66388
66787
|
overwriteWhenFull: boolean().nullable(),
|
|
66389
|
-
preRecordSec: number().nullable(),
|
|
66390
|
-
postRecordSec: number().nullable(),
|
|
66788
|
+
preRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
66789
|
+
postRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
66391
66790
|
/** Length of one recorded file, in minutes. */
|
|
66392
|
-
segmentMinutes: number().nullable(),
|
|
66791
|
+
segmentMinutes: number().nullable().meta(readingMeta("none")),
|
|
66393
66792
|
/** The primary track's weekly windows, flattened. */
|
|
66394
66793
|
windows: array(RecordWindowSchema),
|
|
66395
66794
|
/**
|
|
@@ -66405,7 +66804,7 @@ var RecordingOnboardStatusSchema = object({
|
|
|
66405
66804
|
* provider reporting a non-zero count also reports the schedule as not
|
|
66406
66805
|
* writable.
|
|
66407
66806
|
*/
|
|
66408
|
-
unreadableWindows: number(),
|
|
66807
|
+
unreadableWindows: number().meta(readingMeta("count")),
|
|
66409
66808
|
/**
|
|
66410
66809
|
* The camera is scheduled to record and has NO usable storage.
|
|
66411
66810
|
*
|
|
@@ -67352,7 +67751,7 @@ var CamStreamDescriptorSchema = object({
|
|
|
67352
67751
|
url: string().optional(),
|
|
67353
67752
|
codec: string().optional(),
|
|
67354
67753
|
resolution: CamStreamResolutionSchema.optional(),
|
|
67355
|
-
fps: number().positive().optional(),
|
|
67754
|
+
fps: number().positive().optional().meta(readingMeta("rate")),
|
|
67356
67755
|
label: string().optional(),
|
|
67357
67756
|
/** Device-level features (e.g. `battery-operated`) — drives broker policy. */
|
|
67358
67757
|
deviceFeatures: array(string()).optional(),
|
|
@@ -67439,18 +67838,18 @@ var StreamProfileSchema = _enum([
|
|
|
67439
67838
|
]);
|
|
67440
67839
|
/** The current encoding config of one stream profile. */
|
|
67441
67840
|
var StreamProfileConfigSchema = object({
|
|
67442
|
-
width: number(),
|
|
67443
|
-
height: number(),
|
|
67841
|
+
width: number().meta(readingMeta("none")),
|
|
67842
|
+
height: number().meta(readingMeta("none")),
|
|
67444
67843
|
codec: _enum(["h264", "h265"]),
|
|
67445
|
-
framerate: number(),
|
|
67446
|
-
bitrate: number(),
|
|
67844
|
+
framerate: number().meta(readingMeta("rate")),
|
|
67845
|
+
bitrate: number().meta(readingMeta("bitrate")),
|
|
67447
67846
|
bitrateMode: _enum(["vbr", "cbr"]).optional(),
|
|
67448
67847
|
encoderProfile: _enum([
|
|
67449
67848
|
"high",
|
|
67450
67849
|
"main",
|
|
67451
67850
|
"baseline"
|
|
67452
67851
|
]).optional(),
|
|
67453
|
-
gop: number().optional(),
|
|
67852
|
+
gop: number().optional().meta(readingMeta("none")),
|
|
67454
67853
|
/**
|
|
67455
67854
|
* Whether THIS profile currently carries an audio track. READ-ONLY here.
|
|
67456
67855
|
*
|
|
@@ -67869,12 +68268,7 @@ var switchCapability = {
|
|
|
67869
68268
|
label: "On",
|
|
67870
68269
|
kind: "boolean"
|
|
67871
68270
|
}
|
|
67872
|
-
}] }
|
|
67873
|
-
customize: {
|
|
67874
|
-
version: 1,
|
|
67875
|
-
advanced: "derive",
|
|
67876
|
-
targets: []
|
|
67877
|
-
}
|
|
68271
|
+
}] }
|
|
67878
68272
|
};
|
|
67879
68273
|
/** C0 controls, DEL and the C1 range: none of them belongs in a name. */
|
|
67880
68274
|
function hasControlCharacter(value) {
|
|
@@ -68457,35 +68851,21 @@ var tamperCapability = {
|
|
|
68457
68851
|
* entries with `device_class: temperature` and any future native
|
|
68458
68852
|
* thermometer.
|
|
68459
68853
|
*
|
|
68460
|
-
*
|
|
68461
|
-
*
|
|
68462
|
-
* (climate-control's `currentTemp`, energy analytics) can compose
|
|
68463
|
-
* without per-source unit fixups. The canonical display unit (`°C`) is
|
|
68464
|
-
* a descriptor constant in the UI (ROLE_DESCRIPTOR), not stored in
|
|
68465
|
-
* `sourceInfo`.
|
|
68854
|
+
* The number is Celsius (D944). Providers convert on ingest. A failed
|
|
68855
|
+
* conversion is `null`, never a guess. Display unit is a read-time preference.
|
|
68466
68856
|
*
|
|
68467
68857
|
* Status `lastFetchedAt` lets staleness-aware consumers detect a
|
|
68468
68858
|
* frozen feed (provider hung) distinct from a "temperature hasn't
|
|
68469
68859
|
* changed" steady state.
|
|
68470
68860
|
*/
|
|
68471
68861
|
var TemperatureSensorStatusSchema = object({
|
|
68472
|
-
/** Current temperature in Celsius. */
|
|
68473
|
-
celsius: number().meta({
|
|
68474
|
-
|
|
68862
|
+
/** Current temperature in Celsius. `null` when the sample was refused (D393). */
|
|
68863
|
+
celsius: number().nullable().meta(readingMeta("temperature", {
|
|
68864
|
+
precision: 1,
|
|
68475
68865
|
label: "Temperature"
|
|
68476
|
-
}),
|
|
68866
|
+
})),
|
|
68477
68867
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
68478
|
-
lastFetchedAt: number()
|
|
68479
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
68480
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
68481
|
-
* role's canonical unit, so a Fahrenheit feed renders '°F' not '°C'.
|
|
68482
|
-
* Absent → the UI falls back to the role's canonical unit. */
|
|
68483
|
-
unit: string().optional(),
|
|
68484
|
-
/** Suggested decimal places for numeric display.
|
|
68485
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
68486
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
68487
|
-
* auto-formatting when absent. */
|
|
68488
|
-
precision: number().int().min(0).max(10).optional()
|
|
68868
|
+
lastFetchedAt: number()
|
|
68489
68869
|
});
|
|
68490
68870
|
var temperatureSensorCapability = {
|
|
68491
68871
|
name: "temperature-sensor",
|
|
@@ -68516,12 +68896,7 @@ var temperatureSensorCapability = {
|
|
|
68516
68896
|
} } },
|
|
68517
68897
|
/** Clock fields: written, but excluded from the compare that decides
|
|
68518
68898
|
* whether persisting is worth a SQLite commit. */
|
|
68519
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
68520
|
-
customize: {
|
|
68521
|
-
version: 1,
|
|
68522
|
-
advanced: "derive",
|
|
68523
|
-
targets: []
|
|
68524
|
-
}
|
|
68899
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
68525
68900
|
};
|
|
68526
68901
|
/**
|
|
68527
68902
|
* toast — system-scoped singleton capability that streams toast
|
|
@@ -68804,16 +69179,16 @@ var VacuumControlStatusSchema = object({
|
|
|
68804
69179
|
]),
|
|
68805
69180
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
68806
69181
|
* reading. */
|
|
68807
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
69182
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
68808
69183
|
/** Current fan-speed token (provider-verbatim). Null when unknown or
|
|
68809
69184
|
* the vacuum has no speed control. */
|
|
68810
69185
|
fanSpeed: string().nullable(),
|
|
68811
69186
|
/** Speed tokens the hardware accepts — drives the UI selector. */
|
|
68812
69187
|
availableFanSpeeds: array(string()),
|
|
68813
69188
|
/** 0..100 cleaning-completion percentage of the current task, or null. */
|
|
68814
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
69189
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
68815
69190
|
/** Current error code (0 / null = no error). */
|
|
68816
|
-
errorCode: number().nullable(),
|
|
69191
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
68817
69192
|
/** Human label for {@link errorCode}, or null when none / undecodable. */
|
|
68818
69193
|
errorLabel: string().nullable(),
|
|
68819
69194
|
/** Ms epoch when the slice was last updated. */
|
|
@@ -68891,7 +69266,7 @@ var ValveStatusSchema = object({
|
|
|
68891
69266
|
]),
|
|
68892
69267
|
/** 0 = fully closed, 100 = fully open. Null when the device has no
|
|
68893
69268
|
* intermediate position surface. */
|
|
68894
|
-
position: number().min(0).max(100).nullable(),
|
|
69269
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
68895
69270
|
/** Ms epoch when the slice was last updated. */
|
|
68896
69271
|
lastChangedAt: number()
|
|
68897
69272
|
});
|
|
@@ -68999,9 +69374,9 @@ var vibrationCapability = {
|
|
|
68999
69374
|
*/
|
|
69000
69375
|
var WaterHeaterStatusSchema = object({
|
|
69001
69376
|
/** Current measured temperature. Null when not reported. */
|
|
69002
|
-
currentTemp: number().nullable(),
|
|
69377
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
69003
69378
|
/** Target temperature setpoint. Null when no setpoint surface. */
|
|
69004
|
-
targetTemp: number().nullable(),
|
|
69379
|
+
targetTemp: number().nullable().meta(readingMeta("temperature")),
|
|
69005
69380
|
/** Active operation mode = HA `state` (`eco` / `electric` / `gas` /
|
|
69006
69381
|
* `heat_pump` / `high_demand` / `performance` / `off`). Null when the
|
|
69007
69382
|
* device reports an unknown state. */
|
|
@@ -69012,9 +69387,9 @@ var WaterHeaterStatusSchema = object({
|
|
|
69012
69387
|
* has no away surface. */
|
|
69013
69388
|
away: boolean().nullable(),
|
|
69014
69389
|
/** HA `min_temp` attribute. Null when not reported. */
|
|
69015
|
-
minTemp: number().nullable(),
|
|
69390
|
+
minTemp: number().nullable().meta(readingMeta("temperature")),
|
|
69016
69391
|
/** HA `max_temp` attribute. Null when not reported. */
|
|
69017
|
-
maxTemp: number().nullable(),
|
|
69392
|
+
maxTemp: number().nullable().meta(readingMeta("temperature")),
|
|
69018
69393
|
/** Ms epoch when the slice was last updated. */
|
|
69019
69394
|
lastChangedAt: number()
|
|
69020
69395
|
});
|
|
@@ -69099,25 +69474,18 @@ var waterHeaterCapability = {
|
|
|
69099
69474
|
* Forecast deferred — current conditions only for v1.
|
|
69100
69475
|
*/
|
|
69101
69476
|
var WeatherStatusSchema = object({
|
|
69102
|
-
/** Verbatim
|
|
69103
|
-
* when no condition has been reported yet. */
|
|
69477
|
+
/** Verbatim condition state (`sunny`, `cloudy`, `rainy`, …). Null when none yet. */
|
|
69104
69478
|
condition: string().nullable(),
|
|
69105
|
-
/** Current temperature in
|
|
69106
|
-
temperature: number().nullable(),
|
|
69107
|
-
/** Temperature unit string (e.g. `°C` / `°F`). Null when not provided. */
|
|
69108
|
-
temperatureUnit: string().nullable(),
|
|
69479
|
+
/** Current temperature in Celsius. Null when not provided or refused. */
|
|
69480
|
+
temperature: number().nullable().meta(readingMeta("temperature", { precision: 1 })),
|
|
69109
69481
|
/** Relative humidity (0..100). Null when not provided. */
|
|
69110
|
-
humidity: number().min(0).max(100).nullable(),
|
|
69111
|
-
/** Barometric pressure in
|
|
69112
|
-
pressure: number().nullable(),
|
|
69113
|
-
/**
|
|
69114
|
-
|
|
69115
|
-
/** Wind speed in the reported unit. Null when not provided. */
|
|
69116
|
-
windSpeed: number().nullable(),
|
|
69117
|
-
/** Wind-speed unit string (e.g. `km/h` / `mph`). Null when not provided. */
|
|
69118
|
-
windSpeedUnit: string().nullable(),
|
|
69482
|
+
humidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
69483
|
+
/** Barometric pressure in hPa. Null when not provided or refused. */
|
|
69484
|
+
pressure: number().nullable().meta(readingMeta("pressure")),
|
|
69485
|
+
/** Wind speed in metres per second. Null when not provided or refused. */
|
|
69486
|
+
windSpeed: number().nullable().meta(readingMeta("speed")),
|
|
69119
69487
|
/** Wind bearing in degrees (0..360, meteorological). Null when not provided. */
|
|
69120
|
-
windBearing: number().nullable(),
|
|
69488
|
+
windBearing: number().nullable().meta(readingMeta("angle")),
|
|
69121
69489
|
/** Ms epoch when the slice was last updated. */
|
|
69122
69490
|
lastFetchedAt: number()
|
|
69123
69491
|
});
|
|
@@ -69145,12 +69513,12 @@ var weatherCapability = {
|
|
|
69145
69513
|
*/
|
|
69146
69514
|
durability: "session",
|
|
69147
69515
|
/**
|
|
69148
|
-
* History (D850): recorded series.
|
|
69516
|
+
* History (D850): recorded series. Numbers are the quantity base (D944).
|
|
69149
69517
|
*/
|
|
69150
69518
|
history: { fields: {
|
|
69151
69519
|
temperature: {
|
|
69152
69520
|
kind: "gauge",
|
|
69153
|
-
|
|
69521
|
+
unit: "°C",
|
|
69154
69522
|
deadband: .2
|
|
69155
69523
|
},
|
|
69156
69524
|
humidity: {
|
|
@@ -69160,12 +69528,12 @@ var weatherCapability = {
|
|
|
69160
69528
|
},
|
|
69161
69529
|
pressure: {
|
|
69162
69530
|
kind: "gauge",
|
|
69163
|
-
|
|
69531
|
+
unit: "hPa",
|
|
69164
69532
|
deadband: .5
|
|
69165
69533
|
},
|
|
69166
69534
|
windSpeed: {
|
|
69167
69535
|
kind: "gauge",
|
|
69168
|
-
|
|
69536
|
+
unit: "m/s",
|
|
69169
69537
|
deadband: .5
|
|
69170
69538
|
}
|
|
69171
69539
|
} }
|
|
@@ -70529,6 +70897,8 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
70529
70897
|
featureProbe: featureProbeCapability,
|
|
70530
70898
|
flood: floodCapability,
|
|
70531
70899
|
gas: gasCapability,
|
|
70900
|
+
groupCommands: groupCommandsCapability,
|
|
70901
|
+
groupStatus: groupStatusCapability,
|
|
70532
70902
|
heatingValve: heatingValveCapability,
|
|
70533
70903
|
humidifier: humidifierCapability,
|
|
70534
70904
|
humiditySensor: humiditySensorCapability,
|
|
@@ -71909,6 +72279,13 @@ Object.freeze({
|
|
|
71909
72279
|
access: "view",
|
|
71910
72280
|
role: "admin"
|
|
71911
72281
|
},
|
|
72282
|
+
"addons.getPackageDocs": {
|
|
72283
|
+
capName: "addons",
|
|
72284
|
+
capScope: "system",
|
|
72285
|
+
addonId: null,
|
|
72286
|
+
access: "view",
|
|
72287
|
+
role: "admin"
|
|
72288
|
+
},
|
|
71912
72289
|
"addons.getVersions": {
|
|
71913
72290
|
capName: "addons",
|
|
71914
72291
|
capScope: "system",
|
|
@@ -75017,6 +75394,20 @@ Object.freeze({
|
|
|
75017
75394
|
access: "view",
|
|
75018
75395
|
role: "viewer"
|
|
75019
75396
|
},
|
|
75397
|
+
"groupCommands.getStatus": {
|
|
75398
|
+
capName: "group-commands",
|
|
75399
|
+
capScope: "device",
|
|
75400
|
+
addonId: null,
|
|
75401
|
+
access: "view",
|
|
75402
|
+
role: "viewer"
|
|
75403
|
+
},
|
|
75404
|
+
"groupStatus.getStatus": {
|
|
75405
|
+
capName: "group-status",
|
|
75406
|
+
capScope: "device",
|
|
75407
|
+
addonId: null,
|
|
75408
|
+
access: "view",
|
|
75409
|
+
role: "viewer"
|
|
75410
|
+
},
|
|
75020
75411
|
"heatingValve.getStatus": {
|
|
75021
75412
|
capName: "heating-valve",
|
|
75022
75413
|
capScope: "device",
|
|
@@ -84839,6 +85230,37 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84839
85230
|
icon: "flame"
|
|
84840
85231
|
}]
|
|
84841
85232
|
},
|
|
85233
|
+
"group-commands": {
|
|
85234
|
+
scope: "device",
|
|
85235
|
+
noun: t("Group command", "Comando di gruppo")
|
|
85236
|
+
},
|
|
85237
|
+
"group-status": {
|
|
85238
|
+
scope: "device",
|
|
85239
|
+
noun: t("Group", "Gruppo"),
|
|
85240
|
+
state: [
|
|
85241
|
+
{
|
|
85242
|
+
kind: "numeric",
|
|
85243
|
+
field: "included",
|
|
85244
|
+
quantity: t("the members reporting", "i membri che rispondono"),
|
|
85245
|
+
label: t("Reporting", "Rispondono"),
|
|
85246
|
+
icon: "users"
|
|
85247
|
+
},
|
|
85248
|
+
{
|
|
85249
|
+
kind: "numeric",
|
|
85250
|
+
field: "excluded",
|
|
85251
|
+
quantity: t("the members left out", "i membri esclusi"),
|
|
85252
|
+
label: t("Excluded", "Esclusi"),
|
|
85253
|
+
icon: "users"
|
|
85254
|
+
},
|
|
85255
|
+
{
|
|
85256
|
+
kind: "numeric",
|
|
85257
|
+
field: "total",
|
|
85258
|
+
quantity: t("the member count", "il numero di membri"),
|
|
85259
|
+
label: t("Members", "Membri"),
|
|
85260
|
+
icon: "sigma"
|
|
85261
|
+
}
|
|
85262
|
+
]
|
|
85263
|
+
},
|
|
84842
85264
|
"humidity-sensor": {
|
|
84843
85265
|
scope: "device",
|
|
84844
85266
|
noun: t("Humidity", "Umidità"),
|
|
@@ -84872,7 +85294,6 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84872
85294
|
field: "value",
|
|
84873
85295
|
quantity: t("the reading", "il valore"),
|
|
84874
85296
|
label: t("Reading", "Valore"),
|
|
84875
|
-
unitField: "unit",
|
|
84876
85297
|
icon: "gauge"
|
|
84877
85298
|
}]
|
|
84878
85299
|
},
|
|
@@ -85008,7 +85429,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
85008
85429
|
field: "temperature",
|
|
85009
85430
|
quantity: t("the outdoor temperature", "la temperatura esterna"),
|
|
85010
85431
|
label: t("Temperature", "Temperatura"),
|
|
85011
|
-
|
|
85432
|
+
unit: "°C",
|
|
85012
85433
|
icon: "thermometer"
|
|
85013
85434
|
},
|
|
85014
85435
|
{
|
|
@@ -85024,7 +85445,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
85024
85445
|
field: "windSpeed",
|
|
85025
85446
|
quantity: t("the wind speed", "la velocità del vento"),
|
|
85026
85447
|
label: t("Wind", "Vento"),
|
|
85027
|
-
|
|
85448
|
+
unit: "m/s",
|
|
85028
85449
|
icon: "wind"
|
|
85029
85450
|
},
|
|
85030
85451
|
{
|
|
@@ -85032,7 +85453,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
85032
85453
|
field: "pressure",
|
|
85033
85454
|
quantity: t("the air pressure", "la pressione atmosferica"),
|
|
85034
85455
|
label: t("Pressure", "Pressione"),
|
|
85035
|
-
|
|
85456
|
+
unit: "hPa",
|
|
85036
85457
|
icon: "gauge"
|
|
85037
85458
|
}
|
|
85038
85459
|
]
|
|
@@ -86511,6 +86932,16 @@ Object.freeze({
|
|
|
86511
86932
|
form: "single",
|
|
86512
86933
|
optional: false
|
|
86513
86934
|
}],
|
|
86935
|
+
"groupCommands.getStatus": [{
|
|
86936
|
+
name: "deviceId",
|
|
86937
|
+
form: "single",
|
|
86938
|
+
optional: false
|
|
86939
|
+
}],
|
|
86940
|
+
"groupStatus.getStatus": [{
|
|
86941
|
+
name: "deviceId",
|
|
86942
|
+
form: "single",
|
|
86943
|
+
optional: false
|
|
86944
|
+
}],
|
|
86514
86945
|
"heatingValve.getStatus": [{
|
|
86515
86946
|
name: "deviceId",
|
|
86516
86947
|
form: "single",
|
|
@@ -88495,6 +88926,8 @@ new Map(Object.entries({
|
|
|
88495
88926
|
"detection-blind": "device-events",
|
|
88496
88927
|
"motion-noisy": "device-events",
|
|
88497
88928
|
"motion-calm": "device-events",
|
|
88929
|
+
"package-llm-silent": "device-events",
|
|
88930
|
+
"package-llm-answered": "device-events",
|
|
88498
88931
|
"recording-stalled": "device-events",
|
|
88499
88932
|
"recording-healthy": "device-events",
|
|
88500
88933
|
"recording-degraded": "device-events",
|
|
@@ -88578,6 +89011,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
|
|
|
88578
89011
|
label: "Motion without a subject",
|
|
88579
89012
|
kinds: ["motion-noisy", "motion-calm"]
|
|
88580
89013
|
},
|
|
89014
|
+
{
|
|
89015
|
+
id: "package-llm",
|
|
89016
|
+
family: "device-events",
|
|
89017
|
+
label: "Package confirm",
|
|
89018
|
+
kinds: ["package-llm-silent", "package-llm-answered"]
|
|
89019
|
+
},
|
|
88581
89020
|
{
|
|
88582
89021
|
id: "recording",
|
|
88583
89022
|
family: "device-events",
|
|
@@ -88759,6 +89198,8 @@ var DEVICE_EVENTS = [
|
|
|
88759
89198
|
"detection-blind",
|
|
88760
89199
|
"motion-noisy",
|
|
88761
89200
|
"motion-calm",
|
|
89201
|
+
"package-llm-silent",
|
|
89202
|
+
"package-llm-answered",
|
|
88762
89203
|
"recording-stalled",
|
|
88763
89204
|
"recording-healthy",
|
|
88764
89205
|
"recording-degraded",
|
|
@@ -89027,6 +89468,15 @@ new Map([
|
|
|
89027
89468
|
snapshotLabel: "Cameras with constant motion now",
|
|
89028
89469
|
snapshotSection: null
|
|
89029
89470
|
},
|
|
89471
|
+
{
|
|
89472
|
+
id: "package-llm-confirm",
|
|
89473
|
+
family: "device-events",
|
|
89474
|
+
label: "Package confirm (not answering / answering again)",
|
|
89475
|
+
bad: ["package-llm-silent"],
|
|
89476
|
+
recovery: ["package-llm-answered"],
|
|
89477
|
+
snapshotLabel: "Cameras whose package confirm is not answering",
|
|
89478
|
+
snapshotSection: null
|
|
89479
|
+
},
|
|
89030
89480
|
{
|
|
89031
89481
|
id: "recording-health",
|
|
89032
89482
|
family: "device-events",
|