@camstack/addon-provider-wyze 0.2.158 → 0.2.159
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +18 -0
- package/dist/addon.js +959 -509
- package/dist/addon.mjs +959 -509
- package/package.json +4 -2
package/dist/addon.js
CHANGED
|
@@ -31,7 +31,7 @@ let net = require("net");
|
|
|
31
31
|
net = __toESM(net, 1);
|
|
32
32
|
let node_child_process = require("node:child_process");
|
|
33
33
|
let node_tls = require("node:tls");
|
|
34
|
-
//#region ../types/dist/event-category-
|
|
34
|
+
//#region ../types/dist/event-category-CT-hz5Rb.mjs
|
|
35
35
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
36
36
|
EventCategory["SystemBoot"] = "system.boot";
|
|
37
37
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -357,6 +357,14 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
357
357
|
/** The recovery edge of {@link PipelineMotionNoisy}: the motion fell back, or a detection arrived. */
|
|
358
358
|
EventCategory["PipelineMotionCalm"] = "pipeline.motion-calm";
|
|
359
359
|
/**
|
|
360
|
+
* A camera's package LLM confirm has failed closed three times in a row
|
|
361
|
+
* (D931, 2026-10-26). One edge per camera until
|
|
362
|
+
* {@link PipelinePackageLlmAnswered}.
|
|
363
|
+
*/
|
|
364
|
+
EventCategory["PipelinePackageLlmSilent"] = "pipeline.package-llm-silent";
|
|
365
|
+
/** The recovery edge of {@link PipelinePackageLlmSilent}: a confirm returned yes or no. */
|
|
366
|
+
EventCategory["PipelinePackageLlmAnswered"] = "pipeline.package-llm-answered";
|
|
367
|
+
/**
|
|
360
368
|
* Per-camera pipeline config was mutated by the orchestrator
|
|
361
369
|
* (a settings change via `setAgentInferenceDevices` /
|
|
362
370
|
* `setCameraStepToggle` / `setCameraStepSettings`). Orchestrator
|
|
@@ -5466,7 +5474,7 @@ var ZodIssueCode = {
|
|
|
5466
5474
|
var ZodFirstPartyTypeKind;
|
|
5467
5475
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5468
5476
|
//#endregion
|
|
5469
|
-
//#region ../types/dist/sleep-
|
|
5477
|
+
//#region ../types/dist/sleep-bykKrTgu.mjs
|
|
5470
5478
|
/**
|
|
5471
5479
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5472
5480
|
* window to float samples (D455).
|
|
@@ -8020,6 +8028,99 @@ var RecordKindDeclarationSchema = object({
|
|
|
8020
8028
|
}).strict();
|
|
8021
8029
|
/** The kind names: lower-case, dash separated, short enough for an index name. */
|
|
8022
8030
|
var RecordKindNameSchema = string().regex(/^[a-z][a-z0-9-]{0,47}$/);
|
|
8031
|
+
var READING_QUANTITIES = [
|
|
8032
|
+
"temperature",
|
|
8033
|
+
"pressure",
|
|
8034
|
+
"speed",
|
|
8035
|
+
"precipitation",
|
|
8036
|
+
"precipitation-rate",
|
|
8037
|
+
"length",
|
|
8038
|
+
"area",
|
|
8039
|
+
"illuminance",
|
|
8040
|
+
"irradiance",
|
|
8041
|
+
"power",
|
|
8042
|
+
"energy",
|
|
8043
|
+
"voltage",
|
|
8044
|
+
"current",
|
|
8045
|
+
"apparent-power",
|
|
8046
|
+
"humidity",
|
|
8047
|
+
"percentage",
|
|
8048
|
+
"concentration-volume",
|
|
8049
|
+
"concentration-mass",
|
|
8050
|
+
"concentration-ppb",
|
|
8051
|
+
"volume",
|
|
8052
|
+
"duration",
|
|
8053
|
+
"duration-ms",
|
|
8054
|
+
"information",
|
|
8055
|
+
"sound-level",
|
|
8056
|
+
"signal-level",
|
|
8057
|
+
"colour-temperature",
|
|
8058
|
+
"angle",
|
|
8059
|
+
"bitrate",
|
|
8060
|
+
"rate",
|
|
8061
|
+
"mass",
|
|
8062
|
+
"index",
|
|
8063
|
+
"ratio",
|
|
8064
|
+
"count",
|
|
8065
|
+
"none",
|
|
8066
|
+
"device"
|
|
8067
|
+
];
|
|
8068
|
+
var ReadingQuantitySchema = _enum(READING_QUANTITIES);
|
|
8069
|
+
new Set(READING_QUANTITIES);
|
|
8070
|
+
/**
|
|
8071
|
+
* Stored unit symbol for a quantity. `none` means the number is dimensionless
|
|
8072
|
+
* (or an index / ratio / count). `device` means the cap has no single unit.
|
|
8073
|
+
*/
|
|
8074
|
+
var QUANTITY_BASE = {
|
|
8075
|
+
temperature: "°C",
|
|
8076
|
+
pressure: "hPa",
|
|
8077
|
+
speed: "m/s",
|
|
8078
|
+
precipitation: "mm",
|
|
8079
|
+
"precipitation-rate": "mm/h",
|
|
8080
|
+
length: "m",
|
|
8081
|
+
area: "m²",
|
|
8082
|
+
illuminance: "lx",
|
|
8083
|
+
irradiance: "W/m²",
|
|
8084
|
+
power: "W",
|
|
8085
|
+
energy: "kWh",
|
|
8086
|
+
voltage: "V",
|
|
8087
|
+
current: "A",
|
|
8088
|
+
"apparent-power": "VA",
|
|
8089
|
+
humidity: "%",
|
|
8090
|
+
percentage: "%",
|
|
8091
|
+
"concentration-volume": "ppm",
|
|
8092
|
+
"concentration-mass": "µg/m³",
|
|
8093
|
+
"concentration-ppb": "ppb",
|
|
8094
|
+
volume: "L",
|
|
8095
|
+
duration: "s",
|
|
8096
|
+
"duration-ms": "ms",
|
|
8097
|
+
information: "B",
|
|
8098
|
+
"sound-level": "dBFS",
|
|
8099
|
+
"signal-level": "dBm",
|
|
8100
|
+
"colour-temperature": "mired",
|
|
8101
|
+
angle: "°",
|
|
8102
|
+
bitrate: "kbps",
|
|
8103
|
+
rate: "fps",
|
|
8104
|
+
mass: "kg",
|
|
8105
|
+
index: "none",
|
|
8106
|
+
ratio: "none",
|
|
8107
|
+
count: "none",
|
|
8108
|
+
none: "none",
|
|
8109
|
+
device: "device"
|
|
8110
|
+
};
|
|
8111
|
+
/** The stored unit, or `undefined` when the quantity has no unit symbol. */
|
|
8112
|
+
function baseUnitOf(quantity) {
|
|
8113
|
+
const symbol = QUANTITY_BASE[quantity];
|
|
8114
|
+
if (symbol === "none" || symbol === "device") return void 0;
|
|
8115
|
+
return symbol;
|
|
8116
|
+
}
|
|
8117
|
+
function readingMeta(quantity, extras) {
|
|
8118
|
+
return {
|
|
8119
|
+
quantity,
|
|
8120
|
+
...extras?.precision !== void 0 ? { precision: extras.precision } : {},
|
|
8121
|
+
...extras?.label !== void 0 ? { label: extras.label } : {}
|
|
8122
|
+
};
|
|
8123
|
+
}
|
|
8023
8124
|
/** Shared Zod schemas used across streaming capabilities. */
|
|
8024
8125
|
var CamProfileSchema = _enum([
|
|
8025
8126
|
"high",
|
|
@@ -8047,8 +8148,8 @@ var CamStreamKindSchema = _enum([
|
|
|
8047
8148
|
"derived"
|
|
8048
8149
|
]);
|
|
8049
8150
|
var CamStreamResolutionSchema = object({
|
|
8050
|
-
width: number().int().positive(),
|
|
8051
|
-
height: number().int().positive()
|
|
8151
|
+
width: number().int().positive().meta(readingMeta("none")),
|
|
8152
|
+
height: number().int().positive().meta(readingMeta("none"))
|
|
8052
8153
|
});
|
|
8053
8154
|
var CameraStreamSchema = object({
|
|
8054
8155
|
/** Stable, provider-assigned id unique within the (deviceId) scope. */
|
|
@@ -8566,6 +8667,8 @@ var CAP_NAMES = Object.freeze([
|
|
|
8566
8667
|
"filesystem-browse",
|
|
8567
8668
|
"flood",
|
|
8568
8669
|
"gas",
|
|
8670
|
+
"group-commands",
|
|
8671
|
+
"group-status",
|
|
8569
8672
|
"heating-valve",
|
|
8570
8673
|
"humidifier",
|
|
8571
8674
|
"humidity-sensor",
|
|
@@ -8695,14 +8798,6 @@ Object.freeze({
|
|
|
8695
8798
|
{
|
|
8696
8799
|
"path": "aqi",
|
|
8697
8800
|
"valueType": "number"
|
|
8698
|
-
},
|
|
8699
|
-
{
|
|
8700
|
-
"path": "unit",
|
|
8701
|
-
"valueType": "string"
|
|
8702
|
-
},
|
|
8703
|
-
{
|
|
8704
|
-
"path": "precision",
|
|
8705
|
-
"valueType": "number"
|
|
8706
8801
|
}
|
|
8707
8802
|
],
|
|
8708
8803
|
"alarm-panel": [
|
|
@@ -8738,20 +8833,10 @@ Object.freeze({
|
|
|
8738
8833
|
"valueType": "boolean"
|
|
8739
8834
|
}
|
|
8740
8835
|
],
|
|
8741
|
-
"ambient-light-sensor": [
|
|
8742
|
-
|
|
8743
|
-
|
|
8744
|
-
|
|
8745
|
-
},
|
|
8746
|
-
{
|
|
8747
|
-
"path": "unit",
|
|
8748
|
-
"valueType": "string"
|
|
8749
|
-
},
|
|
8750
|
-
{
|
|
8751
|
-
"path": "precision",
|
|
8752
|
-
"valueType": "number"
|
|
8753
|
-
}
|
|
8754
|
-
],
|
|
8836
|
+
"ambient-light-sensor": [{
|
|
8837
|
+
"path": "lux",
|
|
8838
|
+
"valueType": "number"
|
|
8839
|
+
}],
|
|
8755
8840
|
"audio-metrics": [
|
|
8756
8841
|
{
|
|
8757
8842
|
"path": "ts",
|
|
@@ -8831,6 +8916,10 @@ Object.freeze({
|
|
|
8831
8916
|
"path": "lastUpdated",
|
|
8832
8917
|
"valueType": "number"
|
|
8833
8918
|
},
|
|
8919
|
+
{
|
|
8920
|
+
"path": "volts",
|
|
8921
|
+
"valueType": "number"
|
|
8922
|
+
},
|
|
8834
8923
|
{
|
|
8835
8924
|
"path": "lastContactAt",
|
|
8836
8925
|
"valueType": "number"
|
|
@@ -9073,10 +9162,6 @@ Object.freeze({
|
|
|
9073
9162
|
"datetime"
|
|
9074
9163
|
]
|
|
9075
9164
|
},
|
|
9076
|
-
{
|
|
9077
|
-
"path": "unit",
|
|
9078
|
-
"valueType": "string"
|
|
9079
|
-
},
|
|
9080
9165
|
{
|
|
9081
9166
|
"path": "min",
|
|
9082
9167
|
"valueType": "number"
|
|
@@ -9088,19 +9173,6 @@ Object.freeze({
|
|
|
9088
9173
|
{
|
|
9089
9174
|
"path": "step",
|
|
9090
9175
|
"valueType": "number"
|
|
9091
|
-
},
|
|
9092
|
-
{
|
|
9093
|
-
"path": "precision",
|
|
9094
|
-
"valueType": "number"
|
|
9095
|
-
},
|
|
9096
|
-
{
|
|
9097
|
-
"path": "format",
|
|
9098
|
-
"valueType": "enum",
|
|
9099
|
-
"enumValues": [
|
|
9100
|
-
"date",
|
|
9101
|
-
"time",
|
|
9102
|
-
"datetime"
|
|
9103
|
-
]
|
|
9104
9176
|
}
|
|
9105
9177
|
],
|
|
9106
9178
|
"cover": [
|
|
@@ -9341,13 +9413,8 @@ Object.freeze({
|
|
|
9341
9413
|
"path": "value",
|
|
9342
9414
|
"valueType": "string"
|
|
9343
9415
|
}, {
|
|
9344
|
-
"path": "
|
|
9345
|
-
"valueType": "
|
|
9346
|
-
"enumValues": [
|
|
9347
|
-
"date",
|
|
9348
|
-
"time",
|
|
9349
|
-
"datetime"
|
|
9350
|
-
]
|
|
9416
|
+
"path": "timestamp",
|
|
9417
|
+
"valueType": "boolean"
|
|
9351
9418
|
}],
|
|
9352
9419
|
"event-emitter": [
|
|
9353
9420
|
{
|
|
@@ -9420,6 +9487,20 @@ Object.freeze({
|
|
|
9420
9487
|
"path": "detected",
|
|
9421
9488
|
"valueType": "boolean"
|
|
9422
9489
|
}],
|
|
9490
|
+
"group-status": [
|
|
9491
|
+
{
|
|
9492
|
+
"path": "included",
|
|
9493
|
+
"valueType": "number"
|
|
9494
|
+
},
|
|
9495
|
+
{
|
|
9496
|
+
"path": "excluded",
|
|
9497
|
+
"valueType": "number"
|
|
9498
|
+
},
|
|
9499
|
+
{
|
|
9500
|
+
"path": "total",
|
|
9501
|
+
"valueType": "number"
|
|
9502
|
+
}
|
|
9503
|
+
],
|
|
9423
9504
|
"heating-valve": [{
|
|
9424
9505
|
"path": "position",
|
|
9425
9506
|
"valueType": "number"
|
|
@@ -9454,20 +9535,10 @@ Object.freeze({
|
|
|
9454
9535
|
"valueType": "number"
|
|
9455
9536
|
}
|
|
9456
9537
|
],
|
|
9457
|
-
"humidity-sensor": [
|
|
9458
|
-
|
|
9459
|
-
|
|
9460
|
-
|
|
9461
|
-
},
|
|
9462
|
-
{
|
|
9463
|
-
"path": "unit",
|
|
9464
|
-
"valueType": "string"
|
|
9465
|
-
},
|
|
9466
|
-
{
|
|
9467
|
-
"path": "precision",
|
|
9468
|
-
"valueType": "number"
|
|
9469
|
-
}
|
|
9470
|
-
],
|
|
9538
|
+
"humidity-sensor": [{
|
|
9539
|
+
"path": "percent",
|
|
9540
|
+
"valueType": "number"
|
|
9541
|
+
}],
|
|
9471
9542
|
"image": [{
|
|
9472
9543
|
"path": "url",
|
|
9473
9544
|
"valueType": "string"
|
|
@@ -9806,20 +9877,10 @@ Object.freeze({
|
|
|
9806
9877
|
"valueType": "boolean"
|
|
9807
9878
|
}
|
|
9808
9879
|
],
|
|
9809
|
-
"numeric-sensor": [
|
|
9810
|
-
|
|
9811
|
-
|
|
9812
|
-
|
|
9813
|
-
},
|
|
9814
|
-
{
|
|
9815
|
-
"path": "unit",
|
|
9816
|
-
"valueType": "string"
|
|
9817
|
-
},
|
|
9818
|
-
{
|
|
9819
|
-
"path": "precision",
|
|
9820
|
-
"valueType": "number"
|
|
9821
|
-
}
|
|
9822
|
-
],
|
|
9880
|
+
"numeric-sensor": [{
|
|
9881
|
+
"path": "value",
|
|
9882
|
+
"valueType": "number"
|
|
9883
|
+
}],
|
|
9823
9884
|
"pet-feeder": [
|
|
9824
9885
|
{
|
|
9825
9886
|
"path": "foodLevel",
|
|
@@ -9911,14 +9972,6 @@ Object.freeze({
|
|
|
9911
9972
|
{
|
|
9912
9973
|
"path": "powerFactor",
|
|
9913
9974
|
"valueType": "number"
|
|
9914
|
-
},
|
|
9915
|
-
{
|
|
9916
|
-
"path": "unit",
|
|
9917
|
-
"valueType": "string"
|
|
9918
|
-
},
|
|
9919
|
-
{
|
|
9920
|
-
"path": "precision",
|
|
9921
|
-
"valueType": "number"
|
|
9922
9975
|
}
|
|
9923
9976
|
],
|
|
9924
9977
|
"presence": [
|
|
@@ -9947,20 +10000,10 @@ Object.freeze({
|
|
|
9947
10000
|
"valueType": "number"
|
|
9948
10001
|
}
|
|
9949
10002
|
],
|
|
9950
|
-
"pressure-sensor": [
|
|
9951
|
-
|
|
9952
|
-
|
|
9953
|
-
|
|
9954
|
-
},
|
|
9955
|
-
{
|
|
9956
|
-
"path": "unit",
|
|
9957
|
-
"valueType": "string"
|
|
9958
|
-
},
|
|
9959
|
-
{
|
|
9960
|
-
"path": "precision",
|
|
9961
|
-
"valueType": "number"
|
|
9962
|
-
}
|
|
9963
|
-
],
|
|
10003
|
+
"pressure-sensor": [{
|
|
10004
|
+
"path": "hpa",
|
|
10005
|
+
"valueType": "number"
|
|
10006
|
+
}],
|
|
9964
10007
|
"privacy-mask": [{
|
|
9965
10008
|
"path": "enabled",
|
|
9966
10009
|
"valueType": "boolean"
|
|
@@ -10271,20 +10314,10 @@ Object.freeze({
|
|
|
10271
10314
|
"path": "tampered",
|
|
10272
10315
|
"valueType": "boolean"
|
|
10273
10316
|
}],
|
|
10274
|
-
"temperature-sensor": [
|
|
10275
|
-
|
|
10276
|
-
|
|
10277
|
-
|
|
10278
|
-
},
|
|
10279
|
-
{
|
|
10280
|
-
"path": "unit",
|
|
10281
|
-
"valueType": "string"
|
|
10282
|
-
},
|
|
10283
|
-
{
|
|
10284
|
-
"path": "precision",
|
|
10285
|
-
"valueType": "number"
|
|
10286
|
-
}
|
|
10287
|
-
],
|
|
10317
|
+
"temperature-sensor": [{
|
|
10318
|
+
"path": "celsius",
|
|
10319
|
+
"valueType": "number"
|
|
10320
|
+
}],
|
|
10288
10321
|
"update": [
|
|
10289
10322
|
{
|
|
10290
10323
|
"path": "currentVersion",
|
|
@@ -10395,10 +10428,6 @@ Object.freeze({
|
|
|
10395
10428
|
"path": "temperature",
|
|
10396
10429
|
"valueType": "number"
|
|
10397
10430
|
},
|
|
10398
|
-
{
|
|
10399
|
-
"path": "temperatureUnit",
|
|
10400
|
-
"valueType": "string"
|
|
10401
|
-
},
|
|
10402
10431
|
{
|
|
10403
10432
|
"path": "humidity",
|
|
10404
10433
|
"valueType": "number"
|
|
@@ -10407,18 +10436,10 @@ Object.freeze({
|
|
|
10407
10436
|
"path": "pressure",
|
|
10408
10437
|
"valueType": "number"
|
|
10409
10438
|
},
|
|
10410
|
-
{
|
|
10411
|
-
"path": "pressureUnit",
|
|
10412
|
-
"valueType": "string"
|
|
10413
|
-
},
|
|
10414
10439
|
{
|
|
10415
10440
|
"path": "windSpeed",
|
|
10416
10441
|
"valueType": "number"
|
|
10417
10442
|
},
|
|
10418
|
-
{
|
|
10419
|
-
"path": "windSpeedUnit",
|
|
10420
|
-
"valueType": "string"
|
|
10421
|
-
},
|
|
10422
10443
|
{
|
|
10423
10444
|
"path": "windBearing",
|
|
10424
10445
|
"valueType": "number"
|
|
@@ -10835,7 +10856,7 @@ function errMsg(err) {
|
|
|
10835
10856
|
return String(err);
|
|
10836
10857
|
}
|
|
10837
10858
|
//#endregion
|
|
10838
|
-
//#region ../types/dist/composition-
|
|
10859
|
+
//#region ../types/dist/composition-OhpuespA.mjs
|
|
10839
10860
|
/**
|
|
10840
10861
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
10841
10862
|
*
|
|
@@ -11590,15 +11611,74 @@ function validateExpressionSource(src) {
|
|
|
11590
11611
|
}
|
|
11591
11612
|
return null;
|
|
11592
11613
|
}
|
|
11593
|
-
/**
|
|
11594
|
-
|
|
11595
|
-
|
|
11596
|
-
|
|
11614
|
+
/**
|
|
11615
|
+
* A composition source identity: `(addonId, stableId)`, never a numeric device
|
|
11616
|
+
* id. Split out so helper schemas can name it without a cycle through
|
|
11617
|
+
* `composition.ts` (D659).
|
|
11618
|
+
*/
|
|
11597
11619
|
var CompositionSourceRefSchema = object({
|
|
11598
11620
|
/** The owning addon; `stableId` is unique only within it. */
|
|
11599
11621
|
addonId: string().min(1),
|
|
11600
11622
|
stableId: string().min(1)
|
|
11601
11623
|
});
|
|
11624
|
+
var GROUP_TEMPLATE_IDS = [
|
|
11625
|
+
"temperature",
|
|
11626
|
+
"humidity",
|
|
11627
|
+
"pressure",
|
|
11628
|
+
"illuminance",
|
|
11629
|
+
"power",
|
|
11630
|
+
"energy",
|
|
11631
|
+
"battery",
|
|
11632
|
+
"numeric",
|
|
11633
|
+
"motion",
|
|
11634
|
+
"contact",
|
|
11635
|
+
"leak",
|
|
11636
|
+
"smoke",
|
|
11637
|
+
"occupancy",
|
|
11638
|
+
"binary",
|
|
11639
|
+
"switch",
|
|
11640
|
+
"light"
|
|
11641
|
+
];
|
|
11642
|
+
var NUMERIC_AGGREGATES = [
|
|
11643
|
+
"mean",
|
|
11644
|
+
"median",
|
|
11645
|
+
"min",
|
|
11646
|
+
"max",
|
|
11647
|
+
"sum"
|
|
11648
|
+
];
|
|
11649
|
+
var BINARY_AGGREGATES = ["any", "all"];
|
|
11650
|
+
/** How an actuator group decides it is on. Unknown members never count as off. */
|
|
11651
|
+
var ACTIVE_CRITERIA = ["at-least-one", "all"];
|
|
11652
|
+
var AGGREGATE_REDUCERS = [
|
|
11653
|
+
"mean",
|
|
11654
|
+
"median",
|
|
11655
|
+
"min",
|
|
11656
|
+
"max",
|
|
11657
|
+
"sum",
|
|
11658
|
+
"any",
|
|
11659
|
+
"all"
|
|
11660
|
+
];
|
|
11661
|
+
var GroupTemplateIdSchema = _enum(GROUP_TEMPLATE_IDS);
|
|
11662
|
+
var AggregateReducerSchema = _enum(AGGREGATE_REDUCERS);
|
|
11663
|
+
var ActiveCriterionSchema = _enum(ACTIVE_CRITERIA);
|
|
11664
|
+
/** One member. The field is stored so occupancy can name motion or binary. */
|
|
11665
|
+
var HelperMemberSchema = object({
|
|
11666
|
+
source: CompositionSourceRefSchema,
|
|
11667
|
+
cap: string().min(1),
|
|
11668
|
+
fieldPath: string().min(1)
|
|
11669
|
+
});
|
|
11670
|
+
var HelperSpecSchema = discriminatedUnion("kind", [object({
|
|
11671
|
+
kind: literal("group"),
|
|
11672
|
+
templateId: GroupTemplateIdSchema,
|
|
11673
|
+
aggregate: AggregateReducerSchema,
|
|
11674
|
+
members: array(HelperMemberSchema).min(1).max(64),
|
|
11675
|
+
/** Actuator groups only. Readings leave this unset. */
|
|
11676
|
+
active: ActiveCriterionSchema.optional()
|
|
11677
|
+
})]);
|
|
11678
|
+
/** A composed device's stableId is this prefix plus the block id. */
|
|
11679
|
+
var COMPOSED_DEVICE_STABLE_ID_PREFIX = "composed-";
|
|
11680
|
+
/** Longest snippet a `code` source may carry (slice 4). */
|
|
11681
|
+
var MAX_COMPOSITION_CODE_LENGTH = 2e4;
|
|
11602
11682
|
/** One field of one capability of one source device. */
|
|
11603
11683
|
var CompositionFieldReadSchema = object({
|
|
11604
11684
|
source: CompositionSourceRefSchema,
|
|
@@ -11642,7 +11722,33 @@ var CompositionCodeSourceSchema = object({
|
|
|
11642
11722
|
var CompositionFieldSourceSchema = discriminatedUnion("kind", [
|
|
11643
11723
|
CompositionFromSourceSchema,
|
|
11644
11724
|
CompositionExpressionSourceSchema,
|
|
11645
|
-
CompositionCodeSourceSchema
|
|
11725
|
+
CompositionCodeSourceSchema,
|
|
11726
|
+
object({
|
|
11727
|
+
kind: literal("aggregate"),
|
|
11728
|
+
reducer: _enum([
|
|
11729
|
+
"mean",
|
|
11730
|
+
"median",
|
|
11731
|
+
"min",
|
|
11732
|
+
"max",
|
|
11733
|
+
"sum",
|
|
11734
|
+
"any",
|
|
11735
|
+
"all"
|
|
11736
|
+
]),
|
|
11737
|
+
reads: array(CompositionFieldReadSchema).min(1).max(64),
|
|
11738
|
+
/** `value` is the reading; the others are the member counts. */
|
|
11739
|
+
publish: _enum([
|
|
11740
|
+
"value",
|
|
11741
|
+
"included",
|
|
11742
|
+
"excluded",
|
|
11743
|
+
"total"
|
|
11744
|
+
]),
|
|
11745
|
+
/** What a `value` publish does when nobody is included. Counts ignore this. */
|
|
11746
|
+
empty: _enum([
|
|
11747
|
+
"null",
|
|
11748
|
+
"omit",
|
|
11749
|
+
"offline"
|
|
11750
|
+
])
|
|
11751
|
+
})
|
|
11646
11752
|
]);
|
|
11647
11753
|
var CompositionCommandTargetSchema = discriminatedUnion("kind", [object({
|
|
11648
11754
|
kind: literal("forward"),
|
|
@@ -11688,7 +11794,13 @@ var CompositionSchema = object({
|
|
|
11688
11794
|
kind: literal("existing"),
|
|
11689
11795
|
device: CompositionSourceRefSchema
|
|
11690
11796
|
})]),
|
|
11691
|
-
features: array(CompositionFeatureSchema).min(1).max(16)
|
|
11797
|
+
features: array(CompositionFeatureSchema).min(1).max(16),
|
|
11798
|
+
/**
|
|
11799
|
+
* Present when the block is a helper template. Absent on a free
|
|
11800
|
+
* composition (the room example, device 4603). The editor reads this,
|
|
11801
|
+
* never the compiled features.
|
|
11802
|
+
*/
|
|
11803
|
+
helper: HelperSpecSchema.optional()
|
|
11692
11804
|
}).superRefine((composition, ctx) => {
|
|
11693
11805
|
const seen = /* @__PURE__ */ new Set();
|
|
11694
11806
|
composition.features.forEach((feature, index) => {
|
|
@@ -17916,7 +18028,11 @@ var CompositionProblemSchema = object({
|
|
|
17916
18028
|
"item-field-reserved",
|
|
17917
18029
|
"target-missing",
|
|
17918
18030
|
"target-unreadable",
|
|
17919
|
-
"not-replaceable"
|
|
18031
|
+
"not-replaceable",
|
|
18032
|
+
"native-capability-replace",
|
|
18033
|
+
"mixed-quantity",
|
|
18034
|
+
"helper-mismatch",
|
|
18035
|
+
"member-constraint"
|
|
17920
18036
|
]),
|
|
17921
18037
|
path: string(),
|
|
17922
18038
|
message: string()
|
|
@@ -17937,7 +18053,8 @@ var CompositionUnavailableModeSchema = _enum([
|
|
|
17937
18053
|
"null",
|
|
17938
18054
|
"offline",
|
|
17939
18055
|
"unknown",
|
|
17940
|
-
"release"
|
|
18056
|
+
"release",
|
|
18057
|
+
"omit"
|
|
17941
18058
|
]);
|
|
17942
18059
|
/**
|
|
17943
18060
|
* `derived` reads a source · `clock` reads only `now`, recomputed when a sibling
|
|
@@ -17974,9 +18091,11 @@ var CompositionFieldPlanSchema = object({
|
|
|
17974
18091
|
reads: array(CompositionFieldReadSchema)
|
|
17975
18092
|
});
|
|
17976
18093
|
/**
|
|
17977
|
-
* What a feature does to its target (D663): `new` builds a capability on a
|
|
17978
|
-
* device; on an existing device it `add`s a capability the device lacks
|
|
17979
|
-
*
|
|
18094
|
+
* What a feature does to its target (D663, D944): `new` builds a capability on a
|
|
18095
|
+
* new device; on an existing device it `add`s a capability the device lacks.
|
|
18096
|
+
* Replacing a capability the device already serves is refused
|
|
18097
|
+
* (`native-capability-replace`), not planned. `replace` remains on the claim
|
|
18098
|
+
* wire for a claim the hub already holds.
|
|
17980
18099
|
*/
|
|
17981
18100
|
var CompositionFeatureModeSchema = _enum([
|
|
17982
18101
|
"new",
|
|
@@ -18149,6 +18268,275 @@ Object.freeze({
|
|
|
18149
18268
|
result: ["number", "null"]
|
|
18150
18269
|
}
|
|
18151
18270
|
});
|
|
18271
|
+
/**
|
|
18272
|
+
* One catalog row per base reading a group helper can build (D944 §3).
|
|
18273
|
+
* Data, not a form default written into the block.
|
|
18274
|
+
*/
|
|
18275
|
+
var NOW = {
|
|
18276
|
+
fieldPath: "lastFetchedAt",
|
|
18277
|
+
expr: "now"
|
|
18278
|
+
};
|
|
18279
|
+
var CHANGED = {
|
|
18280
|
+
fieldPath: "lastChangedAt",
|
|
18281
|
+
expr: "now"
|
|
18282
|
+
};
|
|
18283
|
+
function numeric(input) {
|
|
18284
|
+
return {
|
|
18285
|
+
...input,
|
|
18286
|
+
family: "numeric",
|
|
18287
|
+
deviceType: DeviceType.Sensor,
|
|
18288
|
+
memberDeviceType: DeviceType.Sensor,
|
|
18289
|
+
commandCaps: [],
|
|
18290
|
+
baseUnit: baseUnitOf(input.quantity),
|
|
18291
|
+
aggregates: NUMERIC_AGGREGATES,
|
|
18292
|
+
accept: [{
|
|
18293
|
+
cap: input.outputCap,
|
|
18294
|
+
fieldPath: input.outputField
|
|
18295
|
+
}]
|
|
18296
|
+
};
|
|
18297
|
+
}
|
|
18298
|
+
function binary(input) {
|
|
18299
|
+
return {
|
|
18300
|
+
...input,
|
|
18301
|
+
family: "binary",
|
|
18302
|
+
deviceType: DeviceType.Sensor,
|
|
18303
|
+
memberDeviceType: DeviceType.Sensor,
|
|
18304
|
+
commandCaps: [],
|
|
18305
|
+
quantity: "none",
|
|
18306
|
+
baseUnit: void 0,
|
|
18307
|
+
aggregates: BINARY_AGGREGATES,
|
|
18308
|
+
empty: "offline"
|
|
18309
|
+
};
|
|
18310
|
+
}
|
|
18311
|
+
var GROUP_TEMPLATES = [
|
|
18312
|
+
numeric({
|
|
18313
|
+
id: "temperature",
|
|
18314
|
+
summary: "Mean, median, min, max or sum of temperatures. Offline and unknown members are left out, never read as 0 °C.",
|
|
18315
|
+
role: DeviceRole.TemperatureSensor,
|
|
18316
|
+
outputCap: "temperature-sensor",
|
|
18317
|
+
outputField: "celsius",
|
|
18318
|
+
quantity: "temperature",
|
|
18319
|
+
defaultAggregate: "mean",
|
|
18320
|
+
empty: "null",
|
|
18321
|
+
companions: [NOW]
|
|
18322
|
+
}),
|
|
18323
|
+
numeric({
|
|
18324
|
+
id: "humidity",
|
|
18325
|
+
summary: "Humidity in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
18326
|
+
role: DeviceRole.HumiditySensor,
|
|
18327
|
+
outputCap: "humidity-sensor",
|
|
18328
|
+
outputField: "percent",
|
|
18329
|
+
quantity: "humidity",
|
|
18330
|
+
defaultAggregate: "mean",
|
|
18331
|
+
empty: "null",
|
|
18332
|
+
companions: [NOW]
|
|
18333
|
+
}),
|
|
18334
|
+
numeric({
|
|
18335
|
+
id: "pressure",
|
|
18336
|
+
summary: "Pressure in hectopascals. Offline and unknown members are left out, never read as 0 hPa.",
|
|
18337
|
+
role: DeviceRole.PressureSensor,
|
|
18338
|
+
outputCap: "pressure-sensor",
|
|
18339
|
+
outputField: "hpa",
|
|
18340
|
+
quantity: "pressure",
|
|
18341
|
+
defaultAggregate: "mean",
|
|
18342
|
+
empty: "null",
|
|
18343
|
+
companions: [NOW]
|
|
18344
|
+
}),
|
|
18345
|
+
numeric({
|
|
18346
|
+
id: "illuminance",
|
|
18347
|
+
summary: "Illuminance in lux. Offline and unknown members are left out, never read as 0 lx.",
|
|
18348
|
+
role: DeviceRole.AmbientLightSensor,
|
|
18349
|
+
outputCap: "ambient-light-sensor",
|
|
18350
|
+
outputField: "lux",
|
|
18351
|
+
quantity: "illuminance",
|
|
18352
|
+
defaultAggregate: "mean",
|
|
18353
|
+
empty: "null",
|
|
18354
|
+
companions: [NOW]
|
|
18355
|
+
}),
|
|
18356
|
+
numeric({
|
|
18357
|
+
id: "power",
|
|
18358
|
+
summary: "Power in watts, summed by default. Nobody reporting omits the key rather than writing 0 W.",
|
|
18359
|
+
role: DeviceRole.PowerSensor,
|
|
18360
|
+
outputCap: "power-meter",
|
|
18361
|
+
outputField: "watts",
|
|
18362
|
+
quantity: "power",
|
|
18363
|
+
defaultAggregate: "sum",
|
|
18364
|
+
empty: "omit",
|
|
18365
|
+
companions: [NOW]
|
|
18366
|
+
}),
|
|
18367
|
+
numeric({
|
|
18368
|
+
id: "energy",
|
|
18369
|
+
summary: "Energy in kilowatt-hours, summed by default. Nobody reporting omits the key rather than writing 0 kWh.",
|
|
18370
|
+
role: DeviceRole.EnergySensor,
|
|
18371
|
+
outputCap: "power-meter",
|
|
18372
|
+
outputField: "kwhTotal",
|
|
18373
|
+
quantity: "energy",
|
|
18374
|
+
defaultAggregate: "sum",
|
|
18375
|
+
empty: "omit",
|
|
18376
|
+
companions: [NOW]
|
|
18377
|
+
}),
|
|
18378
|
+
numeric({
|
|
18379
|
+
id: "battery",
|
|
18380
|
+
summary: "Battery charge in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
18381
|
+
role: DeviceRole.BatterySensor,
|
|
18382
|
+
outputCap: "battery",
|
|
18383
|
+
outputField: "percentage",
|
|
18384
|
+
quantity: "percentage",
|
|
18385
|
+
defaultAggregate: "mean",
|
|
18386
|
+
empty: "null",
|
|
18387
|
+
companions: [
|
|
18388
|
+
{
|
|
18389
|
+
fieldPath: "charging",
|
|
18390
|
+
expr: "\"unknown\""
|
|
18391
|
+
},
|
|
18392
|
+
{
|
|
18393
|
+
fieldPath: "sleeping",
|
|
18394
|
+
expr: "false"
|
|
18395
|
+
},
|
|
18396
|
+
{
|
|
18397
|
+
fieldPath: "lastUpdated",
|
|
18398
|
+
expr: "now"
|
|
18399
|
+
}
|
|
18400
|
+
]
|
|
18401
|
+
}),
|
|
18402
|
+
numeric({
|
|
18403
|
+
id: "numeric",
|
|
18404
|
+
summary: "A numeric reading in the members’ shared quantity. Mixed quantities are refused. Nobody reporting publishes null, not 0.",
|
|
18405
|
+
role: DeviceRole.NumericSensor,
|
|
18406
|
+
outputCap: "numeric-sensor",
|
|
18407
|
+
outputField: "value",
|
|
18408
|
+
quantity: "device",
|
|
18409
|
+
defaultAggregate: "mean",
|
|
18410
|
+
empty: "null",
|
|
18411
|
+
companions: [NOW]
|
|
18412
|
+
}),
|
|
18413
|
+
binary({
|
|
18414
|
+
id: "motion",
|
|
18415
|
+
summary: "Any or all motion. Offline and unknown members are left out, never read as off. Nobody reporting takes the device offline.",
|
|
18416
|
+
role: DeviceRole.MotionSensor,
|
|
18417
|
+
outputCap: "motion",
|
|
18418
|
+
outputField: "detected",
|
|
18419
|
+
defaultAggregate: "any",
|
|
18420
|
+
accept: [{
|
|
18421
|
+
cap: "motion",
|
|
18422
|
+
fieldPath: "detected"
|
|
18423
|
+
}],
|
|
18424
|
+
companions: [{
|
|
18425
|
+
fieldPath: "lastDetectedAt",
|
|
18426
|
+
expr: "null"
|
|
18427
|
+
}, {
|
|
18428
|
+
fieldPath: "autoClearAfterMs",
|
|
18429
|
+
expr: "null"
|
|
18430
|
+
}]
|
|
18431
|
+
}),
|
|
18432
|
+
binary({
|
|
18433
|
+
id: "contact",
|
|
18434
|
+
summary: "Any or all open contacts. Offline and unknown members are left out, never read as closed.",
|
|
18435
|
+
role: DeviceRole.ContactSensor,
|
|
18436
|
+
outputCap: "contact",
|
|
18437
|
+
outputField: "entryOpen",
|
|
18438
|
+
defaultAggregate: "any",
|
|
18439
|
+
accept: [{
|
|
18440
|
+
cap: "contact",
|
|
18441
|
+
fieldPath: "entryOpen"
|
|
18442
|
+
}],
|
|
18443
|
+
companions: [CHANGED]
|
|
18444
|
+
}),
|
|
18445
|
+
binary({
|
|
18446
|
+
id: "leak",
|
|
18447
|
+
summary: "Any or all leak detections. Offline and unknown members are left out, never read as dry.",
|
|
18448
|
+
role: DeviceRole.LeakSensor,
|
|
18449
|
+
outputCap: "flood",
|
|
18450
|
+
outputField: "flooded",
|
|
18451
|
+
defaultAggregate: "any",
|
|
18452
|
+
accept: [{
|
|
18453
|
+
cap: "flood",
|
|
18454
|
+
fieldPath: "flooded"
|
|
18455
|
+
}],
|
|
18456
|
+
companions: [CHANGED]
|
|
18457
|
+
}),
|
|
18458
|
+
binary({
|
|
18459
|
+
id: "smoke",
|
|
18460
|
+
summary: "Any or all smoke detections. Offline and unknown members are left out, never read as clear.",
|
|
18461
|
+
role: DeviceRole.SmokeSensor,
|
|
18462
|
+
outputCap: "smoke",
|
|
18463
|
+
outputField: "detected",
|
|
18464
|
+
defaultAggregate: "any",
|
|
18465
|
+
accept: [{
|
|
18466
|
+
cap: "smoke",
|
|
18467
|
+
fieldPath: "detected"
|
|
18468
|
+
}],
|
|
18469
|
+
companions: [CHANGED]
|
|
18470
|
+
}),
|
|
18471
|
+
binary({
|
|
18472
|
+
id: "occupancy",
|
|
18473
|
+
summary: "Any or all of motion or binary sensors, published as a binary. Presence zones are not aggregated. Nobody reporting is offline, not off.",
|
|
18474
|
+
role: DeviceRole.BinarySensor,
|
|
18475
|
+
outputCap: "binary",
|
|
18476
|
+
outputField: "on",
|
|
18477
|
+
defaultAggregate: "any",
|
|
18478
|
+
accept: [{
|
|
18479
|
+
cap: "motion",
|
|
18480
|
+
fieldPath: "detected"
|
|
18481
|
+
}, {
|
|
18482
|
+
cap: "binary",
|
|
18483
|
+
fieldPath: "on"
|
|
18484
|
+
}],
|
|
18485
|
+
companions: [CHANGED]
|
|
18486
|
+
}),
|
|
18487
|
+
binary({
|
|
18488
|
+
id: "binary",
|
|
18489
|
+
summary: "Any or all generic binary sensors. Offline and unknown members are left out, never read as off.",
|
|
18490
|
+
role: DeviceRole.BinarySensor,
|
|
18491
|
+
outputCap: "binary",
|
|
18492
|
+
outputField: "on",
|
|
18493
|
+
defaultAggregate: "any",
|
|
18494
|
+
accept: [{
|
|
18495
|
+
cap: "binary",
|
|
18496
|
+
fieldPath: "on"
|
|
18497
|
+
}],
|
|
18498
|
+
companions: [CHANGED]
|
|
18499
|
+
}),
|
|
18500
|
+
actuator({
|
|
18501
|
+
id: "switch",
|
|
18502
|
+
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.",
|
|
18503
|
+
deviceType: DeviceType.Switch,
|
|
18504
|
+
outputCap: "switch",
|
|
18505
|
+
commandCaps: ["switch"]
|
|
18506
|
+
}),
|
|
18507
|
+
actuator({
|
|
18508
|
+
id: "light",
|
|
18509
|
+
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.",
|
|
18510
|
+
deviceType: DeviceType.Light,
|
|
18511
|
+
outputCap: "switch",
|
|
18512
|
+
commandCaps: [
|
|
18513
|
+
"switch",
|
|
18514
|
+
"brightness",
|
|
18515
|
+
"color"
|
|
18516
|
+
]
|
|
18517
|
+
})
|
|
18518
|
+
];
|
|
18519
|
+
function actuator(input) {
|
|
18520
|
+
return {
|
|
18521
|
+
...input,
|
|
18522
|
+
family: "actuator",
|
|
18523
|
+
role: void 0,
|
|
18524
|
+
memberDeviceType: input.deviceType,
|
|
18525
|
+
outputField: "on",
|
|
18526
|
+
quantity: "none",
|
|
18527
|
+
baseUnit: void 0,
|
|
18528
|
+
aggregates: BINARY_AGGREGATES,
|
|
18529
|
+
defaultAggregate: "any",
|
|
18530
|
+
empty: "offline",
|
|
18531
|
+
accept: [{
|
|
18532
|
+
cap: "switch",
|
|
18533
|
+
fieldPath: "on"
|
|
18534
|
+
}],
|
|
18535
|
+
companions: [CHANGED]
|
|
18536
|
+
};
|
|
18537
|
+
}
|
|
18538
|
+
new Map(GROUP_TEMPLATES.map((template) => [template.id, template]));
|
|
18539
|
+
DeviceFeature.LightColorRgb, DeviceFeature.LightColorHsv, DeviceFeature.LightColorMired;
|
|
18152
18540
|
`${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
|
|
18153
18541
|
/**
|
|
18154
18542
|
* What a composition may BUILD on a device type (G2, D676): the caps a new
|
|
@@ -19862,12 +20250,12 @@ method(object({ deviceId: number().int().nonnegative() }), DeviceAdminLinkSchema
|
|
|
19862
20250
|
* providers detect renames by matching `uniqueId` and patch `id`
|
|
19863
20251
|
* in-place so dispatch keeps working.
|
|
19864
20252
|
*
|
|
19865
|
-
* **
|
|
19866
|
-
*
|
|
19867
|
-
*
|
|
19868
|
-
*
|
|
19869
|
-
* (`ha-domain-mapping`)
|
|
19870
|
-
* stored after that point.
|
|
20253
|
+
* **Display unit and precision are NOT stored here.** They are a read-time
|
|
20254
|
+
* preference (D944). A polymorphic reading stores its `quantity` here once,
|
|
20255
|
+
* at adopt, and a date/time value stores `dateTimeShape` the same way —
|
|
20256
|
+
* neither is repeated on each sample. The `device_class` tag is an
|
|
20257
|
+
* HA-specific input consumed at the discovery boundary (`ha-domain-mapping`)
|
|
20258
|
+
* to derive the CamStack `DeviceRole`; it is never stored after that point.
|
|
19871
20259
|
*
|
|
19872
20260
|
* The `raw` escape hatch carries provider-specific attributes that don't
|
|
19873
20261
|
* fit the structured slots (HA `attributes` whitelist, Reolink `deviceCache`
|
|
@@ -19881,6 +20269,14 @@ var SourceInfoSchema = object({
|
|
|
19881
20269
|
/** Immutable upstream identifier when available (HA `unique_id`, … ).
|
|
19882
20270
|
* Used to detect rename when `id` changes. */
|
|
19883
20271
|
uniqueId: string().optional(),
|
|
20272
|
+
/** Quantity of a polymorphic reading, written once at adopt (D944). */
|
|
20273
|
+
quantity: ReadingQuantitySchema.optional(),
|
|
20274
|
+
/** Date / time / datetime shape of a string reading, written once at adopt. */
|
|
20275
|
+
dateTimeShape: _enum([
|
|
20276
|
+
"date",
|
|
20277
|
+
"time",
|
|
20278
|
+
"datetime"
|
|
20279
|
+
]).optional(),
|
|
19884
20280
|
/** Provider-specific extras that don't fit the structured slots.
|
|
19885
20281
|
* Whitelist what goes here per provider — do NOT dump entire HA
|
|
19886
20282
|
* attribute blobs (would explode the meta JSON column). */
|
|
@@ -41002,7 +41398,8 @@ method(object({
|
|
|
41002
41398
|
"enum"
|
|
41003
41399
|
]),
|
|
41004
41400
|
enumValues: array(string()).optional(),
|
|
41005
|
-
item: boolean().optional()
|
|
41401
|
+
item: boolean().optional(),
|
|
41402
|
+
quantity: ReadingQuantitySchema.optional()
|
|
41006
41403
|
})).readonly(),
|
|
41007
41404
|
itemArray: object({
|
|
41008
41405
|
path: string(),
|
|
@@ -44846,8 +45243,8 @@ var MaskPolygonShapeSchema = object({
|
|
|
44846
45243
|
/** Boolean cell grid — row-major, length === gridWidth*gridHeight. */
|
|
44847
45244
|
var MaskGridShapeSchema = object({
|
|
44848
45245
|
kind: literal("grid"),
|
|
44849
|
-
gridWidth: number(),
|
|
44850
|
-
gridHeight: number(),
|
|
45246
|
+
gridWidth: number().meta(readingMeta("none")),
|
|
45247
|
+
gridHeight: number().meta(readingMeta("none")),
|
|
44851
45248
|
cells: array(boolean())
|
|
44852
45249
|
});
|
|
44853
45250
|
discriminatedUnion("kind", [
|
|
@@ -44959,6 +45356,8 @@ var NcSystemEventKindSchema = _enum([
|
|
|
44959
45356
|
"detection-blind",
|
|
44960
45357
|
"motion-noisy",
|
|
44961
45358
|
"motion-calm",
|
|
45359
|
+
"package-llm-silent",
|
|
45360
|
+
"package-llm-answered",
|
|
44962
45361
|
"recording-stalled",
|
|
44963
45362
|
"recording-healthy",
|
|
44964
45363
|
"recording-degraded",
|
|
@@ -56154,6 +56553,28 @@ var PackageVersionInfoSchema = object({
|
|
|
56154
56553
|
deprecated: string().optional(),
|
|
56155
56554
|
distTags: array(string()).readonly()
|
|
56156
56555
|
});
|
|
56556
|
+
/**
|
|
56557
|
+
* One published document. `ok` is markdown from the registry. `missing` means
|
|
56558
|
+
* the registry answered and the file was not there. `error` is a registry or
|
|
56559
|
+
* tarball failure — never an empty string standing in for either.
|
|
56560
|
+
*/
|
|
56561
|
+
var PackageDocBodySchema = discriminatedUnion("status", [
|
|
56562
|
+
object({
|
|
56563
|
+
status: literal("ok"),
|
|
56564
|
+
markdown: string()
|
|
56565
|
+
}),
|
|
56566
|
+
object({ status: literal("missing") }),
|
|
56567
|
+
object({
|
|
56568
|
+
status: literal("error"),
|
|
56569
|
+
message: string()
|
|
56570
|
+
})
|
|
56571
|
+
]);
|
|
56572
|
+
var PackageDocsSchema = object({
|
|
56573
|
+
name: string(),
|
|
56574
|
+
version: string(),
|
|
56575
|
+
readme: PackageDocBodySchema,
|
|
56576
|
+
changelog: PackageDocBodySchema
|
|
56577
|
+
});
|
|
56157
56578
|
var SearchResultSchema = object({
|
|
56158
56579
|
name: string(),
|
|
56159
56580
|
version: string(),
|
|
@@ -56372,7 +56793,10 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
|
|
|
56372
56793
|
}), object({ success: literal(true) }), {
|
|
56373
56794
|
kind: "mutation",
|
|
56374
56795
|
auth: "admin"
|
|
56375
|
-
}), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({
|
|
56796
|
+
}), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({
|
|
56797
|
+
name: string().min(1),
|
|
56798
|
+
version: string().min(1).optional()
|
|
56799
|
+
}), PackageDocsSchema, { auth: "admin" }), method(object({ addonId: string() }), RestartAddonResultSchema, {
|
|
56376
56800
|
kind: "mutation",
|
|
56377
56801
|
auth: "admin"
|
|
56378
56802
|
}), method(object({ packageName: string() }), object({ success: literal(true) }), {
|
|
@@ -56431,27 +56855,17 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
|
|
|
56431
56855
|
*/
|
|
56432
56856
|
var AirQualitySensorStatusSchema = object({
|
|
56433
56857
|
/** Carbon dioxide concentration in ppm. */
|
|
56434
|
-
co2Ppm: number().min(0).optional(),
|
|
56858
|
+
co2Ppm: number().min(0).optional().meta(readingMeta("concentration-volume")),
|
|
56435
56859
|
/** Total volatile organic compounds in ppb. */
|
|
56436
|
-
vocPpb: number().min(0).optional(),
|
|
56860
|
+
vocPpb: number().min(0).optional().meta(readingMeta("concentration-ppb")),
|
|
56437
56861
|
/** Particulate matter ≤ 2.5 μm in µg/m³. */
|
|
56438
|
-
pm25: number().min(0).optional(),
|
|
56862
|
+
pm25: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
56439
56863
|
/** Particulate matter ≤ 10 μm in µg/m³. */
|
|
56440
|
-
pm10: number().min(0).optional(),
|
|
56864
|
+
pm10: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
56441
56865
|
/** Composite AQI value (typically 0..500). */
|
|
56442
|
-
aqi: number().optional(),
|
|
56866
|
+
aqi: number().optional().meta(readingMeta("index")),
|
|
56443
56867
|
/** Ms epoch when the slice was last updated. */
|
|
56444
|
-
lastFetchedAt: number()
|
|
56445
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
56446
|
-
* `attributes.unit_of_measurement` → 'ppm' / 'ppb' / 'µg/m³'). Each
|
|
56447
|
-
* upstream `sensor.*` entity surfaces ONE device_class, so one unit
|
|
56448
|
-
* per slice is unambiguous. */
|
|
56449
|
-
unit: string().optional(),
|
|
56450
|
-
/** Suggested decimal places for numeric display.
|
|
56451
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
56452
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
56453
|
-
* auto-formatting when absent. */
|
|
56454
|
-
precision: number().int().min(0).max(10).optional()
|
|
56868
|
+
lastFetchedAt: number()
|
|
56455
56869
|
});
|
|
56456
56870
|
var airQualitySensorCapability = {
|
|
56457
56871
|
name: "air-quality-sensor",
|
|
@@ -56488,12 +56902,12 @@ var airQualitySensorCapability = {
|
|
|
56488
56902
|
},
|
|
56489
56903
|
pm25: {
|
|
56490
56904
|
kind: "gauge",
|
|
56491
|
-
unit: "
|
|
56905
|
+
unit: "µg/m³",
|
|
56492
56906
|
deadband: 1
|
|
56493
56907
|
},
|
|
56494
56908
|
pm10: {
|
|
56495
56909
|
kind: "gauge",
|
|
56496
|
-
unit: "
|
|
56910
|
+
unit: "µg/m³",
|
|
56497
56911
|
deadband: 1
|
|
56498
56912
|
},
|
|
56499
56913
|
aqi: {
|
|
@@ -56511,22 +56925,13 @@ var airQualitySensorCapability = {
|
|
|
56511
56925
|
* entries with `device_class: illuminance`.
|
|
56512
56926
|
*/
|
|
56513
56927
|
var AmbientLightSensorStatusSchema = object({
|
|
56514
|
-
/** Current illuminance in lux (lx). */
|
|
56515
|
-
lux: number().min(0).meta({
|
|
56516
|
-
|
|
56928
|
+
/** Current illuminance in lux (lx). `null` when the sample was refused (D393). */
|
|
56929
|
+
lux: number().min(0).nullable().meta(readingMeta("illuminance", {
|
|
56930
|
+
precision: 0,
|
|
56517
56931
|
label: "Illuminance"
|
|
56518
|
-
}),
|
|
56932
|
+
})),
|
|
56519
56933
|
/** Ms epoch when the slice was last updated. */
|
|
56520
|
-
lastFetchedAt: number()
|
|
56521
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
56522
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
56523
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
56524
|
-
unit: string().optional(),
|
|
56525
|
-
/** Suggested decimal places for numeric display.
|
|
56526
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
56527
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
56528
|
-
* auto-formatting when absent. */
|
|
56529
|
-
precision: number().int().min(0).max(10).optional()
|
|
56934
|
+
lastFetchedAt: number()
|
|
56530
56935
|
});
|
|
56531
56936
|
var ambientLightSensorCapability = {
|
|
56532
56937
|
name: "ambient-light-sensor",
|
|
@@ -56558,12 +56963,7 @@ var ambientLightSensorCapability = {
|
|
|
56558
56963
|
} } },
|
|
56559
56964
|
/** Clock fields: written, but excluded from the compare that decides
|
|
56560
56965
|
* whether persisting is worth a SQLite commit. */
|
|
56561
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
56562
|
-
customize: {
|
|
56563
|
-
version: 1,
|
|
56564
|
-
advanced: "derive",
|
|
56565
|
-
targets: []
|
|
56566
|
-
}
|
|
56966
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
56567
56967
|
};
|
|
56568
56968
|
/**
|
|
56569
56969
|
* Per-class audio metrics aggregated over a sliding window.
|
|
@@ -56790,10 +57190,7 @@ var BatteryStatusSchema = object({
|
|
|
56790
57190
|
* Consumers must SKIP a null rather than coerce it — `battery-band` already
|
|
56791
57191
|
* declines to band a non-finite reading, which is the correct shape.
|
|
56792
57192
|
*/
|
|
56793
|
-
percentage: number().min(0).max(100).nullable().meta({
|
|
56794
|
-
unit: "%",
|
|
56795
|
-
label: "Charge"
|
|
56796
|
-
}),
|
|
57193
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage", { label: "Charge" })),
|
|
56797
57194
|
/**
|
|
56798
57195
|
* Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
|
|
56799
57196
|
* Reolink-specific for the Solar Panel 2 accessory (will become
|
|
@@ -56820,7 +57217,14 @@ var BatteryStatusSchema = object({
|
|
|
56820
57217
|
*/
|
|
56821
57218
|
sleeping: boolean().meta({ label: "Sleeping" }),
|
|
56822
57219
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
56823
|
-
lastUpdated: number(),
|
|
57220
|
+
lastUpdated: number().meta(readingMeta("none")),
|
|
57221
|
+
/**
|
|
57222
|
+
* Battery voltage in volts, for a cell the firmware reports as voltage
|
|
57223
|
+
* rather than a percentage (Ecowitt capacitor packs). Absent on cameras
|
|
57224
|
+
* that only report charge. A second reading on this cap, not a second
|
|
57225
|
+
* `numeric-sensor` on the same device.
|
|
57226
|
+
*/
|
|
57227
|
+
volts: number().nullable().optional().meta(readingMeta("voltage", { label: "Voltage" })),
|
|
56824
57228
|
/**
|
|
56825
57229
|
* Ms epoch of the last time the device PROVED it was reachable — a
|
|
56826
57230
|
* completed firmware round-trip, an observed wake, or an inbound push
|
|
@@ -56872,7 +57276,6 @@ var BATTERY_DEVICE_TYPES = [
|
|
|
56872
57276
|
/** Generic Customize target for the percentage reading (D936). */
|
|
56873
57277
|
var batteryCustomize = {
|
|
56874
57278
|
version: 1,
|
|
56875
|
-
advanced: "derive",
|
|
56876
57279
|
targets: [{
|
|
56877
57280
|
id: "percentage",
|
|
56878
57281
|
cardinality: "scalar",
|
|
@@ -56881,7 +57284,7 @@ var batteryCustomize = {
|
|
|
56881
57284
|
stateField: "percentage"
|
|
56882
57285
|
},
|
|
56883
57286
|
deviceTypes: BATTERY_DEVICE_TYPES,
|
|
56884
|
-
apply: "add
|
|
57287
|
+
apply: "add",
|
|
56885
57288
|
path: "percentage",
|
|
56886
57289
|
sources: [{
|
|
56887
57290
|
kind: "field",
|
|
@@ -57002,10 +57405,16 @@ onStatusChanged: { data: object({
|
|
|
57002
57405
|
/**
|
|
57003
57406
|
* History (D850): recorded series. The generic capture replaces the `battery` series of `pipeline-analytics:stats-5m`.
|
|
57004
57407
|
*/
|
|
57005
|
-
history: { fields: {
|
|
57006
|
-
|
|
57007
|
-
|
|
57008
|
-
|
|
57408
|
+
history: { fields: {
|
|
57409
|
+
percentage: {
|
|
57410
|
+
kind: "gauge",
|
|
57411
|
+
unit: "%"
|
|
57412
|
+
},
|
|
57413
|
+
volts: {
|
|
57414
|
+
kind: "gauge",
|
|
57415
|
+
unit: "V"
|
|
57416
|
+
}
|
|
57417
|
+
} },
|
|
57009
57418
|
customize: batteryCustomize,
|
|
57010
57419
|
/** Clock fields: written, but excluded from the compare that decides
|
|
57011
57420
|
* whether persisting is worth a SQLite commit. */
|
|
@@ -57052,12 +57461,7 @@ var binaryCapability = {
|
|
|
57052
57461
|
history: { fields: { on: { kind: "boolean" } } },
|
|
57053
57462
|
/** Clock fields: written, but excluded from the compare that decides
|
|
57054
57463
|
* whether persisting is worth a SQLite commit. */
|
|
57055
|
-
volatileStateFields: ["lastChangedAt"]
|
|
57056
|
-
customize: {
|
|
57057
|
-
version: 1,
|
|
57058
|
-
advanced: "derive",
|
|
57059
|
-
targets: []
|
|
57060
|
-
}
|
|
57464
|
+
volatileStateFields: ["lastChangedAt"]
|
|
57061
57465
|
};
|
|
57062
57466
|
/**
|
|
57063
57467
|
* Dimmable-light brightness control. Co-exists with `switch` on the
|
|
@@ -57073,7 +57477,7 @@ var binaryCapability = {
|
|
|
57073
57477
|
*/
|
|
57074
57478
|
var BrightnessStatusSchema = object({
|
|
57075
57479
|
/** Current level as 0..100 inclusive. Firmware-reported. */
|
|
57076
|
-
percentage: number().min(0).max(100),
|
|
57480
|
+
percentage: number().min(0).max(100).meta(readingMeta("percentage")),
|
|
57077
57481
|
/** Ms epoch of the last operator-driven change. Useful for UI freshness. */
|
|
57078
57482
|
lastChangedAt: number()
|
|
57079
57483
|
});
|
|
@@ -57527,21 +57931,21 @@ var ClimateControlStatusSchema = object({
|
|
|
57527
57931
|
/** Single setpoint in Celsius. Used by single-target modes
|
|
57528
57932
|
* (heat / cool / dry). Null when the device is in a range mode
|
|
57529
57933
|
* (`heat_cool`) or has no setpoint at all (`fan_only`/`off`). */
|
|
57530
|
-
target: number().nullable(),
|
|
57934
|
+
target: number().nullable().meta(readingMeta("temperature")),
|
|
57531
57935
|
/** Upper bound of the dual setpoint in Celsius. Populated only
|
|
57532
57936
|
* in `heat_cool` mode. */
|
|
57533
|
-
targetHigh: number().nullable(),
|
|
57937
|
+
targetHigh: number().nullable().meta(readingMeta("temperature")),
|
|
57534
57938
|
/** Lower bound of the dual setpoint in Celsius. Populated only
|
|
57535
57939
|
* in `heat_cool` mode. */
|
|
57536
|
-
targetLow: number().nullable(),
|
|
57940
|
+
targetLow: number().nullable().meta(readingMeta("temperature")),
|
|
57537
57941
|
/** Target relative humidity (0..100). Null when the device has no
|
|
57538
57942
|
* humidity control. */
|
|
57539
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
57943
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
57540
57944
|
/** Current measured temperature in Celsius. Read-only — pushed by
|
|
57541
57945
|
* the device's internal sensor. */
|
|
57542
|
-
currentTemp: number().nullable(),
|
|
57946
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
57543
57947
|
/** Current measured relative humidity (0..100). Read-only. */
|
|
57544
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
57948
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
57545
57949
|
/** Vertical louver swing on/off. Null when the device has no vertical
|
|
57546
57950
|
* swing surface (gate with `DeviceFeature.ClimateSwingVertical`). */
|
|
57547
57951
|
swingVertical: boolean().nullable(),
|
|
@@ -57549,11 +57953,11 @@ var ClimateControlStatusSchema = object({
|
|
|
57549
57953
|
* horizontal swing surface (gate with `DeviceFeature.ClimateSwingHorizontal`). */
|
|
57550
57954
|
swingHorizontal: boolean().nullable(),
|
|
57551
57955
|
/** Lowest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
57552
|
-
minTemp: number().nullable().optional(),
|
|
57956
|
+
minTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
57553
57957
|
/** Highest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
57554
|
-
maxTemp: number().nullable().optional(),
|
|
57958
|
+
maxTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
57555
57959
|
/** Setpoint granularity, Celsius (0.5, 1). Absent / null = not reported. */
|
|
57556
|
-
tempStep: number().positive().nullable().optional(),
|
|
57960
|
+
tempStep: number().positive().nullable().optional().meta(readingMeta("temperature")),
|
|
57557
57961
|
/** Ms epoch when the slice was last updated (push or command). */
|
|
57558
57962
|
lastFetchedAt: number()
|
|
57559
57963
|
});
|
|
@@ -57695,17 +58099,17 @@ var climateControlCapability = {
|
|
|
57695
58099
|
* modes to expose in the picker without a slice fetch.
|
|
57696
58100
|
*/
|
|
57697
58101
|
var RgbTripletSchema = object({
|
|
57698
|
-
r: number().int().min(0).max(255),
|
|
57699
|
-
g: number().int().min(0).max(255),
|
|
57700
|
-
b: number().int().min(0).max(255)
|
|
58102
|
+
r: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
58103
|
+
g: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
58104
|
+
b: number().int().min(0).max(255).meta(readingMeta("none"))
|
|
57701
58105
|
});
|
|
57702
58106
|
var HsvTripletSchema = object({
|
|
57703
58107
|
/** Hue in degrees, 0..360. */
|
|
57704
|
-
h: number().min(0).max(360),
|
|
58108
|
+
h: number().min(0).max(360).meta(readingMeta("none")),
|
|
57705
58109
|
/** Saturation as 0..100 inclusive. */
|
|
57706
|
-
s: number().min(0).max(100),
|
|
58110
|
+
s: number().min(0).max(100).meta(readingMeta("none")),
|
|
57707
58111
|
/** Value/brightness as 0..100 inclusive. */
|
|
57708
|
-
v: number().min(0).max(100)
|
|
58112
|
+
v: number().min(0).max(100).meta(readingMeta("none"))
|
|
57709
58113
|
});
|
|
57710
58114
|
var ColorInputSchema = discriminatedUnion("mode", [
|
|
57711
58115
|
object({
|
|
@@ -57734,7 +58138,7 @@ var ColorStatusSchema = object({
|
|
|
57734
58138
|
/** Populated when `mode === 'hsv'`. */
|
|
57735
58139
|
hsv: HsvTripletSchema.optional(),
|
|
57736
58140
|
/** Populated when `mode === 'mired'`. */
|
|
57737
|
-
mireds: number().int().optional(),
|
|
58141
|
+
mireds: number().int().optional().meta(readingMeta("colour-temperature")),
|
|
57738
58142
|
/** Ms epoch of the last operator-driven change. */
|
|
57739
58143
|
lastChangedAt: number()
|
|
57740
58144
|
});
|
|
@@ -57937,18 +58341,12 @@ _enum([
|
|
|
57937
58341
|
"empty",
|
|
57938
58342
|
"full"
|
|
57939
58343
|
]);
|
|
57940
|
-
/**
|
|
57941
|
-
|
|
57942
|
-
|
|
57943
|
-
"days",
|
|
57944
|
-
"hours",
|
|
57945
|
-
"cycles"
|
|
57946
|
-
]);
|
|
57947
|
-
/** Remaining life as a COUNT, not a percentage (the PetKit desiccant reports
|
|
57948
|
-
* days). `value` null = unknown (D393). */
|
|
58344
|
+
/** Whether `remaining.value` is a duration in seconds or a dimensionless count. */
|
|
58345
|
+
var ConsumableRemainingKindSchema = _enum(["duration", "count"]);
|
|
58346
|
+
/** Remaining life. `value` null = unknown (D393). Duration is seconds. */
|
|
57949
58347
|
var ConsumableRemainingSchema = object({
|
|
57950
|
-
value: number().min(0).nullable(),
|
|
57951
|
-
|
|
58348
|
+
value: number().min(0).nullable().meta(readingMeta("device")),
|
|
58349
|
+
kind: ConsumableRemainingKindSchema
|
|
57952
58350
|
});
|
|
57953
58351
|
/** A single consumable item. Either a continuous `level` (remaining
|
|
57954
58352
|
* life %, or fill % for a `supply` / `waste` item) or a discrete `status`
|
|
@@ -57961,7 +58359,7 @@ var ConsumableItemSchema = object({
|
|
|
57961
58359
|
/** Display name. */
|
|
57962
58360
|
label: string().min(1),
|
|
57963
58361
|
/** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
|
|
57964
|
-
level: number().min(0).max(100).nullable(),
|
|
58362
|
+
level: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
57965
58363
|
/** The provider's discrete verdict when known (binary mode). */
|
|
57966
58364
|
status: ConsumableStatusSchema.nullable(),
|
|
57967
58365
|
/** What the item is — decides whether low or full is bad. Absent = `wear`. */
|
|
@@ -58043,8 +58441,8 @@ var consumablesCustomize = {
|
|
|
58043
58441
|
transforms: [{ kind: "identity" }]
|
|
58044
58442
|
}],
|
|
58045
58443
|
literals: [{
|
|
58046
|
-
path: "remaining.
|
|
58047
|
-
values: [...
|
|
58444
|
+
path: "remaining.kind",
|
|
58445
|
+
values: [...ConsumableRemainingKindSchema.options]
|
|
58048
58446
|
}]
|
|
58049
58447
|
},
|
|
58050
58448
|
{
|
|
@@ -58173,7 +58571,6 @@ reset: method(object({
|
|
|
58173
58571
|
},
|
|
58174
58572
|
"remaining.value": {
|
|
58175
58573
|
kind: "gauge",
|
|
58176
|
-
unitFrom: "remaining.unit",
|
|
58177
58574
|
deadband: 1,
|
|
58178
58575
|
displayName: "Remaining"
|
|
58179
58576
|
}
|
|
@@ -58243,10 +58640,9 @@ var contactCapability = {
|
|
|
58243
58640
|
* (empty array for the other kinds). It lives in the slice because
|
|
58244
58641
|
* HA `select.*` entities may update their options at runtime.
|
|
58245
58642
|
*
|
|
58246
|
-
*
|
|
58247
|
-
*
|
|
58248
|
-
*
|
|
58249
|
-
* push — consistent with `options` and the sensor-unit approach.
|
|
58643
|
+
* Numeric `min` / `max` / `step` live in the slice and share the device
|
|
58644
|
+
* quantity (`SourceInfo.quantity`, D944). Display precision is a read-time
|
|
58645
|
+
* preference. A datetime control's shape is `SourceInfo.dateTimeShape`.
|
|
58250
58646
|
*/
|
|
58251
58647
|
var ControlStatusSchema = object({
|
|
58252
58648
|
kind: _enum([
|
|
@@ -58258,39 +58654,17 @@ var ControlStatusSchema = object({
|
|
|
58258
58654
|
/** Current value. Numeric kind → number; select/text/datetime → string.
|
|
58259
58655
|
* Datetime values are ISO 8601 strings (full timestamp, date-only,
|
|
58260
58656
|
* or time-only — HA accepts all three forms). */
|
|
58261
|
-
value: union([number(), string()]),
|
|
58657
|
+
value: union([number().meta(readingMeta("device")), string()]),
|
|
58262
58658
|
/** Acceptable values when `kind === 'select'`. Empty for other kinds. */
|
|
58263
58659
|
options: array(string()),
|
|
58264
58660
|
/** Ms epoch when the slice was last updated. */
|
|
58265
58661
|
lastChangedAt: number(),
|
|
58266
|
-
/**
|
|
58267
|
-
|
|
58268
|
-
|
|
58269
|
-
|
|
58270
|
-
/**
|
|
58271
|
-
|
|
58272
|
-
min: number().optional(),
|
|
58273
|
-
/** Maximum allowed value. Populated live from HA `attributes.max`.
|
|
58274
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
58275
|
-
max: number().optional(),
|
|
58276
|
-
/** Step increment. Populated live from HA `attributes.step`.
|
|
58277
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
58278
|
-
step: number().optional(),
|
|
58279
|
-
/** Suggested decimal places for numeric display. Populated live from HA
|
|
58280
|
-
* `attributes.suggested_display_precision`, or derived from `step` when the
|
|
58281
|
-
* HA attribute is absent. Meaningful for `kind === 'numeric'`; absent for
|
|
58282
|
-
* other kinds. Falls back to auto-formatting when absent. */
|
|
58283
|
-
precision: number().int().min(0).max(10).optional(),
|
|
58284
|
-
/** Date-picker granularity for `kind === 'datetime'`. 'date' → date-only,
|
|
58285
|
-
* 'time' → time-only, 'datetime' → full timestamp. Absent for other kinds
|
|
58286
|
-
* (UI defaults to 'datetime'). Derived live from the device's HA domain
|
|
58287
|
-
* (date.* / time.* / datetime.*) or, for input_datetime, from the entity's
|
|
58288
|
-
* `has_date`/`has_time` attributes on each push. */
|
|
58289
|
-
format: _enum([
|
|
58290
|
-
"date",
|
|
58291
|
-
"time",
|
|
58292
|
-
"datetime"
|
|
58293
|
-
]).optional()
|
|
58662
|
+
/** Minimum allowed value, in the device quantity's base unit. */
|
|
58663
|
+
min: number().optional().meta(readingMeta("device")),
|
|
58664
|
+
/** Maximum allowed value, in the device quantity's base unit. */
|
|
58665
|
+
max: number().optional().meta(readingMeta("device")),
|
|
58666
|
+
/** Step increment, in the device quantity's base unit. */
|
|
58667
|
+
step: number().optional().meta(readingMeta("device"))
|
|
58294
58668
|
});
|
|
58295
58669
|
var ControlSetValueInputSchema = discriminatedUnion("kind", [
|
|
58296
58670
|
object({
|
|
@@ -58356,9 +58730,9 @@ var CoverStatusSchema = object({
|
|
|
58356
58730
|
]),
|
|
58357
58731
|
/** 0 = fully closed, 100 = fully open. Null when the device has
|
|
58358
58732
|
* no intermediate position surface. */
|
|
58359
|
-
position: number().min(0).max(100).nullable(),
|
|
58733
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58360
58734
|
/** 0 = closed slats, 100 = open slats. Null when no tilt support. */
|
|
58361
|
-
tiltPosition: number().min(0).max(100).nullable(),
|
|
58735
|
+
tiltPosition: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58362
58736
|
/** Ms epoch when the slice was last updated. */
|
|
58363
58737
|
lastChangedAt: number()
|
|
58364
58738
|
});
|
|
@@ -58461,9 +58835,9 @@ var NormalizedRangeSchema$1 = object({
|
|
|
58461
58835
|
var DayNightStatusSchema = object({
|
|
58462
58836
|
mode: DayNightModeSchema,
|
|
58463
58837
|
/** IR-cut trigger sensitivity, NORMALIZED 0–100 (higher = switches to night sooner). */
|
|
58464
|
-
sensitivity: number().optional(),
|
|
58838
|
+
sensitivity: number().optional().meta(readingMeta("none")),
|
|
58465
58839
|
/** Delay before the IR-cut filter flips, in seconds. */
|
|
58466
|
-
switchDelaySec: number().optional(),
|
|
58840
|
+
switchDelaySec: number().optional().meta(readingMeta("duration")),
|
|
58467
58841
|
lastFetchedAt: number()
|
|
58468
58842
|
});
|
|
58469
58843
|
/**
|
|
@@ -58681,11 +59055,11 @@ var DishwasherStatusSchema = object({
|
|
|
58681
59055
|
/** Feature keys of the programs the appliance currently offers — drives the UI selector. */
|
|
58682
59056
|
availablePrograms: array(string()),
|
|
58683
59057
|
/** Seconds remaining on the active cycle, or null when not running / not known. */
|
|
58684
|
-
remainingSeconds: number().int().nonnegative().nullable(),
|
|
59058
|
+
remainingSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
58685
59059
|
/** Seconds the delayed start is set to (time until the cycle starts), or null. */
|
|
58686
|
-
delayedStartSeconds: number().int().nonnegative().nullable(),
|
|
59060
|
+
delayedStartSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
58687
59061
|
/** Cycle completion 0..100, or null when not applicable. */
|
|
58688
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
59062
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58689
59063
|
/** True when the door is reported open; null when the door state is not known. */
|
|
58690
59064
|
doorOpen: boolean().nullable(),
|
|
58691
59065
|
/** True when the door is latched (locked) during a cycle; null when not reported. */
|
|
@@ -58709,7 +59083,7 @@ var DishwasherStatusSchema = object({
|
|
|
58709
59083
|
/** True while the machine-care (descaling / cleaning-program) reminder is raised; false when clear; null when not reported. */
|
|
58710
59084
|
machineCareDue: boolean().nullable(),
|
|
58711
59085
|
/** Program runs left before the machine-care reminder is due; null when the appliance does not say. */
|
|
58712
|
-
machineCareRemainingRuns: number().int().nonnegative().nullable(),
|
|
59086
|
+
machineCareRemainingRuns: number().int().nonnegative().nullable().meta(readingMeta("count")),
|
|
58713
59087
|
/** Option states: null when the appliance does not expose the option or has not said. */
|
|
58714
59088
|
halfLoad: boolean().nullable(),
|
|
58715
59089
|
hygienePlus: boolean().nullable(),
|
|
@@ -58724,7 +59098,7 @@ var DishwasherStatusSchema = object({
|
|
|
58724
59098
|
/** Feature keys of the events currently raised (salt low, rinse aid low, program finished, …). */
|
|
58725
59099
|
activeEvents: array(string()),
|
|
58726
59100
|
/** Numeric error code when the appliance reports one; null otherwise. */
|
|
58727
|
-
errorCode: number().nullable(),
|
|
59101
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
58728
59102
|
/** Name of the raised alert-level event while the appliance is in error; null otherwise. */
|
|
58729
59103
|
errorLabel: string().nullable(),
|
|
58730
59104
|
/** Ms epoch of the last value received from the appliance; 0 = never. */
|
|
@@ -58955,7 +59329,7 @@ var DoorbellStatusSchema = object({
|
|
|
58955
59329
|
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
58956
59330
|
lastPressedAt: number().nullable(),
|
|
58957
59331
|
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
58958
|
-
pressCountSinceStart: number()
|
|
59332
|
+
pressCountSinceStart: number().meta(readingMeta("count"))
|
|
58959
59333
|
});
|
|
58960
59334
|
var DoorbellPressEventSchema = object({
|
|
58961
59335
|
deviceId: number(),
|
|
@@ -59020,17 +59394,7 @@ onPressed: {
|
|
|
59020
59394
|
history: "none",
|
|
59021
59395
|
customize: doorbellCustomize
|
|
59022
59396
|
};
|
|
59023
|
-
|
|
59024
|
-
* Enum-state sensor — a string value picked from a finite option set.
|
|
59025
|
-
* Drives HA `sensor` entries with `state_class: enum` (HVAC action
|
|
59026
|
-
* states, weather conditions, contact-source channels, mode strings).
|
|
59027
|
-
* The option set is stable across observations; it is persisted in the
|
|
59028
|
-
* device config blob (via the control slice at adoption) and is NOT
|
|
59029
|
-
* stored in `sourceInfo`.
|
|
59030
|
-
*/
|
|
59031
|
-
/** Locale-render shape for an ISO `value` carried by a `DateTimeSensor`-role
|
|
59032
|
-
* enum sensor: `date` (date-only), `time` (time-only), `datetime` (both). */
|
|
59033
|
-
var EnumSensorDateTimeFormatSchema = _enum([
|
|
59397
|
+
_enum([
|
|
59034
59398
|
"date",
|
|
59035
59399
|
"time",
|
|
59036
59400
|
"datetime"
|
|
@@ -59038,12 +59402,11 @@ var EnumSensorDateTimeFormatSchema = _enum([
|
|
|
59038
59402
|
var EnumSensorStatusSchema = object({
|
|
59039
59403
|
value: string(),
|
|
59040
59404
|
/**
|
|
59041
|
-
* Set
|
|
59042
|
-
* as
|
|
59043
|
-
*
|
|
59044
|
-
* a time-only sensor → `'time'`.
|
|
59405
|
+
* Set when `value` is a timestamp rather than an enum state, so history
|
|
59406
|
+
* does not learn ISO strings as states. The display shape (date / time /
|
|
59407
|
+
* datetime) lives on `SourceInfo.dateTimeShape`, written once at adopt.
|
|
59045
59408
|
*/
|
|
59046
|
-
|
|
59409
|
+
timestamp: boolean().optional(),
|
|
59047
59410
|
/** Ms epoch when the slice was last updated. */
|
|
59048
59411
|
lastFetchedAt: number()
|
|
59049
59412
|
});
|
|
@@ -59070,11 +59433,11 @@ var enumSensorCapability = {
|
|
|
59070
59433
|
* History (D850): the value as an `enum` series (an appliance's program or
|
|
59071
59434
|
* operation state, an HVAC action). The option set is per device, so the
|
|
59072
59435
|
* value list is LEARNED as values are first seen (bounded). A sensor with a
|
|
59073
|
-
* `
|
|
59436
|
+
* `timestamp` carries a clock, not a state, and is not recorded.
|
|
59074
59437
|
*/
|
|
59075
59438
|
history: { fields: { value: {
|
|
59076
59439
|
kind: "enum",
|
|
59077
|
-
skipWhenSet: "
|
|
59440
|
+
skipWhenSet: "timestamp"
|
|
59078
59441
|
} } },
|
|
59079
59442
|
/** Clock fields: written, but excluded from the compare that decides
|
|
59080
59443
|
* whether persisting is worth a SQLite commit. */
|
|
@@ -59094,13 +59457,13 @@ var EventFireSchema = object({
|
|
|
59094
59457
|
deviceId: number(),
|
|
59095
59458
|
eventType: string(),
|
|
59096
59459
|
data: record(string(), unknown()).nullable(),
|
|
59097
|
-
timestamp: number(),
|
|
59098
|
-
seq: number()
|
|
59460
|
+
timestamp: number().meta(readingMeta("none")),
|
|
59461
|
+
seq: number().meta(readingMeta("count"))
|
|
59099
59462
|
});
|
|
59100
59463
|
var EventEmitterStatusSchema = object({
|
|
59101
59464
|
eventTypes: array(string()),
|
|
59102
59465
|
lastEvent: EventFireSchema.nullable(),
|
|
59103
|
-
eventCountSinceStart: number()
|
|
59466
|
+
eventCountSinceStart: number().meta(readingMeta("count"))
|
|
59104
59467
|
});
|
|
59105
59468
|
var eventEmitterCapability = {
|
|
59106
59469
|
name: "event-emitter",
|
|
@@ -59513,10 +59876,10 @@ var FanDirectionSchema = _enum(["forward", "reverse"]);
|
|
|
59513
59876
|
var FanControlStatusSchema = object({
|
|
59514
59877
|
/** Active speed as 0..100 inclusive. Null when the device has no
|
|
59515
59878
|
* speed surface (single-speed fan). */
|
|
59516
|
-
percentage: number().min(0).max(100).nullable(),
|
|
59879
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59517
59880
|
/** Speed granularity the device accepts (HA `percentage_step`, e.g. 25 for
|
|
59518
59881
|
* a 4-speed fan). Absent when unknown — the UI then falls back to step 1. */
|
|
59519
|
-
percentageStep: number().positive().optional(),
|
|
59882
|
+
percentageStep: number().positive().optional().meta(readingMeta("percentage")),
|
|
59520
59883
|
/** Active preset mode (`auto` / `quiet` / `turbo` / vendor-specific)
|
|
59521
59884
|
* — empty string when no preset is active or supported. */
|
|
59522
59885
|
preset: string(),
|
|
@@ -59637,7 +60000,7 @@ var FeatureProbeStatusSchema = object({
|
|
|
59637
60000
|
/** Camera/firmware model string. `null` when the firmware doesn't expose it. */
|
|
59638
60001
|
model: string().nullable(),
|
|
59639
60002
|
/** Channel count for NVR/Hub devices; `1` for standalone cameras; `null` pre-probe. */
|
|
59640
|
-
channelCount: number().nullable(),
|
|
60003
|
+
channelCount: number().nullable().meta(readingMeta("count")),
|
|
59641
60004
|
/**
|
|
59642
60005
|
* Ms epoch of the last SUCCESSFUL probe. `0` before the first probe
|
|
59643
60006
|
* completes — drivers' `getAccessoryChildren()` should treat zero as
|
|
@@ -59760,9 +60123,91 @@ var gasCapability = {
|
|
|
59760
60123
|
* whether persisting is worth a SQLite commit. */
|
|
59761
60124
|
volatileStateFields: ["lastChangedAt"]
|
|
59762
60125
|
};
|
|
60126
|
+
var GroupCommandsSchema = object({
|
|
60127
|
+
/** One row per member that has been commanded. A later command replaces that member's row. */
|
|
60128
|
+
results: array(object({
|
|
60129
|
+
deviceId: number().int().nonnegative(),
|
|
60130
|
+
cap: string().min(1),
|
|
60131
|
+
method: string().min(1),
|
|
60132
|
+
ok: boolean(),
|
|
60133
|
+
error: string().optional(),
|
|
60134
|
+
/** Ms epoch of the attempt. */
|
|
60135
|
+
at: number()
|
|
60136
|
+
})) });
|
|
60137
|
+
var groupCommandsCapability = {
|
|
60138
|
+
name: "group-commands",
|
|
60139
|
+
scope: "device",
|
|
60140
|
+
deviceNative: true,
|
|
60141
|
+
mode: "singleton",
|
|
60142
|
+
deviceTypes: [DeviceType.Switch, DeviceType.Light],
|
|
60143
|
+
methods: {},
|
|
60144
|
+
status: {
|
|
60145
|
+
schema: GroupCommandsSchema,
|
|
60146
|
+
kind: "push"
|
|
60147
|
+
},
|
|
60148
|
+
runtimeState: GroupCommandsSchema,
|
|
60149
|
+
/**
|
|
60150
|
+
* Runtime-state durability: **session** — the last attempt. A restored
|
|
60151
|
+
* failure would outlive the command that caused it.
|
|
60152
|
+
*
|
|
60153
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
60154
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
60155
|
+
*/
|
|
60156
|
+
durability: "session",
|
|
60157
|
+
history: "none"
|
|
60158
|
+
};
|
|
60159
|
+
/**
|
|
60160
|
+
* How many members of a helper group answered (D944). Counts are integers,
|
|
60161
|
+
* not measurements: zero included is a real count, never a stand-in reading.
|
|
60162
|
+
* The reading itself stays on the output capability. History is none — the
|
|
60163
|
+
* series that later statistics read is the output cap's own history block.
|
|
60164
|
+
*/
|
|
60165
|
+
var GroupStatusSchema = object({
|
|
60166
|
+
/** Members whose current value entered the aggregate. */
|
|
60167
|
+
included: number().int().nonnegative().meta(readingMeta("count", {
|
|
60168
|
+
precision: 0,
|
|
60169
|
+
label: "Reporting"
|
|
60170
|
+
})),
|
|
60171
|
+
/** Members left out: offline, unknown, or not a finite reading (D393). */
|
|
60172
|
+
excluded: number().int().nonnegative().meta(readingMeta("count", {
|
|
60173
|
+
precision: 0,
|
|
60174
|
+
label: "Excluded"
|
|
60175
|
+
})),
|
|
60176
|
+
/** `included` + `excluded`. */
|
|
60177
|
+
total: number().int().nonnegative().meta(readingMeta("count", {
|
|
60178
|
+
precision: 0,
|
|
60179
|
+
label: "Members"
|
|
60180
|
+
}))
|
|
60181
|
+
});
|
|
60182
|
+
var groupStatusCapability = {
|
|
60183
|
+
name: "group-status",
|
|
60184
|
+
scope: "device",
|
|
60185
|
+
deviceNative: true,
|
|
60186
|
+
mode: "singleton",
|
|
60187
|
+
deviceTypes: [
|
|
60188
|
+
DeviceType.Sensor,
|
|
60189
|
+
DeviceType.Switch,
|
|
60190
|
+
DeviceType.Light
|
|
60191
|
+
],
|
|
60192
|
+
methods: {},
|
|
60193
|
+
status: {
|
|
60194
|
+
schema: GroupStatusSchema,
|
|
60195
|
+
kind: "push"
|
|
60196
|
+
},
|
|
60197
|
+
runtimeState: GroupStatusSchema,
|
|
60198
|
+
/**
|
|
60199
|
+
* Runtime-state durability: **session** — recomputed from members on the
|
|
60200
|
+
* next source event; a restored count would outlive the readings it named.
|
|
60201
|
+
*
|
|
60202
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
60203
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
60204
|
+
*/
|
|
60205
|
+
durability: "session",
|
|
60206
|
+
history: "none"
|
|
60207
|
+
};
|
|
59763
60208
|
var HeatingValveStatusSchema = object({
|
|
59764
60209
|
/** Radiator valve opening 0 (closed) .. 100 (open). Null = not yet known. */
|
|
59765
|
-
position: number().min(0).max(100).nullable(),
|
|
60210
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59766
60211
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
59767
60212
|
lastFetchedAt: number()
|
|
59768
60213
|
});
|
|
@@ -59805,9 +60250,9 @@ var HumidifierStatusSchema = object({
|
|
|
59805
60250
|
/** Whether the humidifier is currently on. */
|
|
59806
60251
|
on: boolean(),
|
|
59807
60252
|
/** Current measured relative humidity (0..100). Null when not reported. */
|
|
59808
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
60253
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
59809
60254
|
/** Target relative humidity (0..100). Null when no setpoint surface. */
|
|
59810
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
60255
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
59811
60256
|
/** Active mode (`auto` / `normal` / `baby` / vendor). Null when the
|
|
59812
60257
|
* device has no mode surface. */
|
|
59813
60258
|
mode: string().nullable(),
|
|
@@ -59817,9 +60262,9 @@ var HumidifierStatusSchema = object({
|
|
|
59817
60262
|
* `idle` / `off`). Null when the device doesn't report it. */
|
|
59818
60263
|
action: string().nullable(),
|
|
59819
60264
|
/** HA `min_humidity` attribute. Null → UI uses 0. */
|
|
59820
|
-
minHumidity: number().nullable(),
|
|
60265
|
+
minHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
59821
60266
|
/** HA `max_humidity` attribute. Null → UI uses 100. */
|
|
59822
|
-
maxHumidity: number().nullable(),
|
|
60267
|
+
maxHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
59823
60268
|
/** Ms epoch when the slice was last updated. */
|
|
59824
60269
|
lastChangedAt: number()
|
|
59825
60270
|
});
|
|
@@ -59889,22 +60334,13 @@ var humidifierCapability = {
|
|
|
59889
60334
|
* `sourceInfo`.
|
|
59890
60335
|
*/
|
|
59891
60336
|
var HumiditySensorStatusSchema = object({
|
|
59892
|
-
/** Current relative humidity, 0..100. */
|
|
59893
|
-
percent: number().min(0).max(100).meta({
|
|
59894
|
-
|
|
60337
|
+
/** Current relative humidity, 0..100. `null` when the sample was refused (D393). */
|
|
60338
|
+
percent: number().min(0).max(100).nullable().meta(readingMeta("humidity", {
|
|
60339
|
+
precision: 0,
|
|
59895
60340
|
label: "Humidity"
|
|
59896
|
-
}),
|
|
60341
|
+
})),
|
|
59897
60342
|
/** Ms epoch when the slice was last updated. */
|
|
59898
|
-
lastFetchedAt: number()
|
|
59899
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
59900
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
59901
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
59902
|
-
unit: string().optional(),
|
|
59903
|
-
/** Suggested decimal places for numeric display.
|
|
59904
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
59905
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
59906
|
-
* auto-formatting when absent. */
|
|
59907
|
-
precision: number().int().min(0).max(10).optional()
|
|
60343
|
+
lastFetchedAt: number()
|
|
59908
60344
|
});
|
|
59909
60345
|
var humiditySensorCapability = {
|
|
59910
60346
|
name: "humidity-sensor",
|
|
@@ -59935,12 +60371,7 @@ var humiditySensorCapability = {
|
|
|
59935
60371
|
} } },
|
|
59936
60372
|
/** Clock fields: written, but excluded from the compare that decides
|
|
59937
60373
|
* whether persisting is worth a SQLite commit. */
|
|
59938
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
59939
|
-
customize: {
|
|
59940
|
-
version: 1,
|
|
59941
|
-
advanced: "derive",
|
|
59942
|
-
targets: []
|
|
59943
|
-
}
|
|
60374
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
59944
60375
|
};
|
|
59945
60376
|
/**
|
|
59946
60377
|
* Image display cap. Models a single still image exposed by an integration —
|
|
@@ -59961,7 +60392,7 @@ var ImageStatusSchema = object({
|
|
|
59961
60392
|
* entity exposes no `entity_picture` (yet). */
|
|
59962
60393
|
url: string().nullable(),
|
|
59963
60394
|
/** Ms epoch of the upstream last-updated timestamp. Null at cold-start. */
|
|
59964
|
-
lastUpdated: number().nullable()
|
|
60395
|
+
lastUpdated: number().nullable().meta(readingMeta("none"))
|
|
59965
60396
|
});
|
|
59966
60397
|
var imageCapability = {
|
|
59967
60398
|
name: "image",
|
|
@@ -60049,19 +60480,19 @@ var NormalizedRangeSchema = object({
|
|
|
60049
60480
|
*/
|
|
60050
60481
|
var ImageSettingsStatusSchema = object({
|
|
60051
60482
|
/** Normalized 0–100. */
|
|
60052
|
-
brightness: number().optional(),
|
|
60483
|
+
brightness: number().optional().meta(readingMeta("none")),
|
|
60053
60484
|
/** Normalized 0–100. */
|
|
60054
|
-
contrast: number().optional(),
|
|
60485
|
+
contrast: number().optional().meta(readingMeta("none")),
|
|
60055
60486
|
/** Normalized 0–100. */
|
|
60056
|
-
saturation: number().optional(),
|
|
60487
|
+
saturation: number().optional().meta(readingMeta("none")),
|
|
60057
60488
|
/** Normalized 0–100. */
|
|
60058
|
-
sharpness: number().optional(),
|
|
60489
|
+
sharpness: number().optional().meta(readingMeta("none")),
|
|
60059
60490
|
mirror: boolean().optional(),
|
|
60060
60491
|
flip: boolean().optional(),
|
|
60061
60492
|
rotate: ImageRotateSchema.optional(),
|
|
60062
60493
|
whiteBalance: WhiteBalanceModeSchema.optional(),
|
|
60063
60494
|
/** Manual white-balance warmth, NORMALIZED 0–100. Meaningful only when `whiteBalance === 'manual'`. */
|
|
60064
|
-
warmth: number().optional(),
|
|
60495
|
+
warmth: number().optional().meta(readingMeta("none")),
|
|
60065
60496
|
exposureMode: ExposureModeSchema.optional(),
|
|
60066
60497
|
backlightMode: BacklightModeSchema.optional(),
|
|
60067
60498
|
lastFetchedAt: number()
|
|
@@ -60340,10 +60771,10 @@ var IntercomAbilitySchema = object({
|
|
|
60340
60771
|
/** Codecs accepted by firmware, in preference order. Driver-authored strings. */
|
|
60341
60772
|
codecs: array(string()),
|
|
60342
60773
|
/** Sample rate (Hz) the firmware expects. Reolink typical: 16000. */
|
|
60343
|
-
sampleRate: number(),
|
|
60774
|
+
sampleRate: number().meta(readingMeta("none")),
|
|
60344
60775
|
duplex: _enum(["half", "full"]),
|
|
60345
60776
|
/** Max in-flight audio backlog before drop (ms). Server uses this to bound latency. */
|
|
60346
|
-
maxBacklogMs: number()
|
|
60777
|
+
maxBacklogMs: number().meta(readingMeta("duration-ms"))
|
|
60347
60778
|
});
|
|
60348
60779
|
var IntercomStatusSchema = object({
|
|
60349
60780
|
/** True while a talk session is open. */
|
|
@@ -60570,13 +61001,13 @@ var LawnMowerControlStatusSchema = object({
|
|
|
60570
61001
|
activity: LawnMowerActivitySchema,
|
|
60571
61002
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
60572
61003
|
* reading. */
|
|
60573
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
61004
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
60574
61005
|
/** 0..100 mowing-completion percentage of the current task, or null when no
|
|
60575
61006
|
* task is active / progress is unavailable. */
|
|
60576
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
61007
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
60577
61008
|
/** Current device/event code (dynamic — mostly status, sometimes an error),
|
|
60578
61009
|
* or null when unknown. */
|
|
60579
|
-
currentCode: number().nullable(),
|
|
61010
|
+
currentCode: number().nullable().meta(readingMeta("none")),
|
|
60580
61011
|
/** Human label for {@link currentCode}, or null when undecodable. */
|
|
60581
61012
|
currentCodeLabel: string().nullable(),
|
|
60582
61013
|
/** Severity of {@link currentCode}. `error` (and often `warning`) warrants UI
|
|
@@ -61109,7 +61540,7 @@ var MediaPlayerStatusSchema = object({
|
|
|
61109
61540
|
state: MediaPlayerStateSchema,
|
|
61110
61541
|
/** Volume as 0..100 inclusive. Null when the device has no volume
|
|
61111
61542
|
* surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
|
|
61112
|
-
volumeLevel: number().min(0).max(100).nullable(),
|
|
61543
|
+
volumeLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61113
61544
|
/** Mute toggle distinct from volume=0. Null when no mute surface.
|
|
61114
61545
|
* Pair with `DeviceFeature.MediaPlayerMute`. */
|
|
61115
61546
|
isMuted: boolean().nullable(),
|
|
@@ -61122,10 +61553,10 @@ var MediaPlayerStatusSchema = object({
|
|
|
61122
61553
|
currentMedia: MediaInfoSchema.nullable(),
|
|
61123
61554
|
/** Current playback position in ms. Null when not seekable or
|
|
61124
61555
|
* nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
|
|
61125
|
-
positionMs: number().int().nonnegative().nullable(),
|
|
61556
|
+
positionMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
61126
61557
|
/** Total duration of the current media in ms. Null when unknown
|
|
61127
61558
|
* (live stream) or nothing is playing. */
|
|
61128
|
-
durationMs: number().int().nonnegative().nullable(),
|
|
61559
|
+
durationMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
61129
61560
|
/** Shuffle toggle. Null when no shuffle surface.
|
|
61130
61561
|
* Pair with `DeviceFeature.MediaPlayerShuffle`. */
|
|
61131
61562
|
shuffle: boolean().nullable(),
|
|
@@ -61434,7 +61865,7 @@ var motionCustomize = {
|
|
|
61434
61865
|
eventName: "onMotionChanged"
|
|
61435
61866
|
},
|
|
61436
61867
|
deviceTypes: [DeviceType.Camera],
|
|
61437
|
-
apply: "
|
|
61868
|
+
apply: "add",
|
|
61438
61869
|
applyAuthority: {
|
|
61439
61870
|
kind: "camera-sensors",
|
|
61440
61871
|
timeoutField: "motionCooldownMs"
|
|
@@ -61506,7 +61937,7 @@ var MotionStatusSchema = object({
|
|
|
61506
61937
|
* it, every provider seeded it at boot, and every session left it
|
|
61507
61938
|
* `detected: true` after its detach.
|
|
61508
61939
|
*/
|
|
61509
|
-
autoClearAfterMs: number().nullable()
|
|
61940
|
+
autoClearAfterMs: number().nullable().meta(readingMeta("duration-ms"))
|
|
61510
61941
|
});
|
|
61511
61942
|
/**
|
|
61512
61943
|
* Payload of `motion.onMotionChanged` event + the corresponding bus
|
|
@@ -61543,12 +61974,18 @@ var motionCapability = {
|
|
|
61543
61974
|
methods: {
|
|
61544
61975
|
/**
|
|
61545
61976
|
* Pull the current motion state synchronously. Convenience shortcut
|
|
61546
|
-
* for consumers that don't need the full status object
|
|
61547
|
-
*
|
|
61548
|
-
* `getStatus` once the auto-injected status surface lands in every
|
|
61549
|
-
* consumer.
|
|
61977
|
+
* for consumers that don't need the full status object. A composed
|
|
61978
|
+
* group answers from its slice (D944): unknown throws, it is not off.
|
|
61550
61979
|
*/
|
|
61551
61980
|
isDetected: method(object({ deviceId: number() }), boolean()) },
|
|
61981
|
+
/**
|
|
61982
|
+
* A composed motion group serves `isDetected` from `detected` (D944).
|
|
61983
|
+
* Without this the cap stays uncomposable (`has-commands`).
|
|
61984
|
+
*/
|
|
61985
|
+
composedMethods: { isDetected: {
|
|
61986
|
+
kind: "slice",
|
|
61987
|
+
field: "detected"
|
|
61988
|
+
} },
|
|
61552
61989
|
events: {
|
|
61553
61990
|
/**
|
|
61554
61991
|
* Fires every time the runner transitions a camera between
|
|
@@ -61688,7 +62125,7 @@ var MotionZoneRegionSchema = object({
|
|
|
61688
62125
|
* the grid region(s). */
|
|
61689
62126
|
var MotionZoneStatusSchema = object({
|
|
61690
62127
|
enabled: boolean(),
|
|
61691
|
-
sensitivity: number(),
|
|
62128
|
+
sensitivity: number().meta(readingMeta("none")),
|
|
61692
62129
|
/** Grid region(s). Today exactly one `grid` shape. */
|
|
61693
62130
|
regions: array(MotionZoneRegionSchema),
|
|
61694
62131
|
lastFetchedAt: number()
|
|
@@ -62058,7 +62495,7 @@ var NavigationStatusSchema = object({
|
|
|
62058
62495
|
following: boolean(),
|
|
62059
62496
|
flash: boolean(),
|
|
62060
62497
|
lightMode: NavigationLightModeSchema,
|
|
62061
|
-
lightLevel: number().min(40).max(100),
|
|
62498
|
+
lightLevel: number().min(40).max(100).meta(readingMeta("none")),
|
|
62062
62499
|
/** Ms epoch when the slice was last updated. */
|
|
62063
62500
|
lastChangedAt: number()
|
|
62064
62501
|
});
|
|
@@ -62192,13 +62629,13 @@ var NetworkLinkStatusSchema = object({
|
|
|
62192
62629
|
* one whose reading has not landed must not be drawn at 0 %. Consumers
|
|
62193
62630
|
* SKIP a null rather than coerce it.
|
|
62194
62631
|
*/
|
|
62195
|
-
signalPercent: number().min(0).max(100).nullable(),
|
|
62632
|
+
signalPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
62196
62633
|
/** Raw received signal strength in dBm, when the firmware reports one. */
|
|
62197
|
-
rssiDbm: number().optional(),
|
|
62634
|
+
rssiDbm: number().optional().meta(readingMeta("signal-level")),
|
|
62198
62635
|
/** Network name of a wireless link, when the firmware reports it. */
|
|
62199
62636
|
ssid: string().optional(),
|
|
62200
62637
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
62201
|
-
lastUpdated: number()
|
|
62638
|
+
lastUpdated: number().meta(readingMeta("none"))
|
|
62202
62639
|
});
|
|
62203
62640
|
var networkLinkCapability = {
|
|
62204
62641
|
name: "network-link",
|
|
@@ -62583,7 +63020,7 @@ var NotifierStatusSchema = object({
|
|
|
62583
63020
|
lastError: string().nullable(),
|
|
62584
63021
|
/** Number of deliveries currently buffered server-side (rate-limited
|
|
62585
63022
|
* notifiers may queue). 0 when the provider sends synchronously. */
|
|
62586
|
-
queueDepth: number().int().nonnegative(),
|
|
63023
|
+
queueDepth: number().int().nonnegative().meta(readingMeta("count")),
|
|
62587
63024
|
/** Per-feature capability matrix — authoritative source for the
|
|
62588
63025
|
* compose-form field gating. */
|
|
62589
63026
|
supports: NotifierSupportsSchema
|
|
@@ -62675,11 +63112,9 @@ onSent: { data: object({
|
|
|
62675
63112
|
* cap fits (HA `sensor` whose `device_class` we don't have a typed cap
|
|
62676
63113
|
* for: water flow, distance, weight, frequency, signal strength, …).
|
|
62677
63114
|
*
|
|
62678
|
-
* The
|
|
62679
|
-
*
|
|
62680
|
-
*
|
|
62681
|
-
* The UI reads them directly from the slice — they are the single source
|
|
62682
|
-
* of truth for generic numeric rendering and do NOT live on `sourceInfo`.
|
|
63115
|
+
* The quantity is not on this slice. It is chosen when the device is
|
|
63116
|
+
* adopted and stored once on `SourceInfo.quantity` (D944). `value` is in
|
|
63117
|
+
* that quantity's base unit. `null` is a refused sample (D393).
|
|
62683
63118
|
*
|
|
62684
63119
|
* Prefer the typed alternatives (`temperature-sensor`, `humidity-sensor`,
|
|
62685
63120
|
* `ambient-light-sensor`, `pressure-sensor`, `power-meter`,
|
|
@@ -62688,15 +63123,8 @@ onSent: { data: object({
|
|
|
62688
63123
|
* numeric values land here.
|
|
62689
63124
|
*/
|
|
62690
63125
|
var NumericSensorStatusSchema = object({
|
|
62691
|
-
|
|
62692
|
-
|
|
62693
|
-
* Populated live from the upstream source on each state push.
|
|
62694
|
-
* Absent for unitless sensors. */
|
|
62695
|
-
unit: string().optional(),
|
|
62696
|
-
/** Suggested decimal places for numeric display.
|
|
62697
|
-
* Populated live from the upstream source when provided.
|
|
62698
|
-
* Falls back to auto-formatting when absent. */
|
|
62699
|
-
precision: number().int().min(0).max(10).optional(),
|
|
63126
|
+
/** Reading in the device quantity's base unit. `null` when refused (D393). */
|
|
63127
|
+
value: number().nullable().meta(readingMeta("device")),
|
|
62700
63128
|
/** Ms epoch when the slice was last updated. */
|
|
62701
63129
|
lastFetchedAt: number()
|
|
62702
63130
|
});
|
|
@@ -62720,11 +63148,11 @@ var numericSensorCapability = {
|
|
|
62720
63148
|
*/
|
|
62721
63149
|
durability: "restored",
|
|
62722
63150
|
/**
|
|
62723
|
-
* History (D850): recorded series. The unit is
|
|
63151
|
+
* History (D850): recorded series. The unit is the device quantity's base,
|
|
63152
|
+
* resolved when the series is read — the cap has no single unit.
|
|
62724
63153
|
*/
|
|
62725
63154
|
history: { fields: { value: {
|
|
62726
63155
|
kind: "gauge",
|
|
62727
|
-
unitFrom: "unit",
|
|
62728
63156
|
minIntervalMs: 3e4
|
|
62729
63157
|
} } },
|
|
62730
63158
|
/** Clock fields: written, but excluded from the compare that decides
|
|
@@ -63016,23 +63444,26 @@ var PetFeederStatusSchema = object({
|
|
|
63016
63444
|
/** Food currently in the bowl (grams). Null when the device has not
|
|
63017
63445
|
* reported a reading yet. On dual-hopper models this is the combined
|
|
63018
63446
|
* bowl reading; per-hopper levels live in `food1`/`food2`. */
|
|
63019
|
-
foodLevel: number().nullable(),
|
|
63447
|
+
foodLevel: number().nullable().meta(readingMeta("none")),
|
|
63020
63448
|
/** Hopper-1 food level (grams) on dual-hopper feeders; null on
|
|
63021
63449
|
* single-hopper models. */
|
|
63022
|
-
food1: number().nullable(),
|
|
63450
|
+
food1: number().nullable().meta(readingMeta("none")),
|
|
63023
63451
|
/** Hopper-2 food level (grams) on dual-hopper feeders; null on
|
|
63024
63452
|
* single-hopper models. */
|
|
63025
|
-
food2: number().nullable(),
|
|
63453
|
+
food2: number().nullable().meta(readingMeta("none")),
|
|
63026
63454
|
/** Derived low-food flag — mirrors the HA `food_level` binary_sensor
|
|
63027
63455
|
* (`device_class: problem`, on = low). True when the bowl is empty /
|
|
63028
63456
|
* below the feeder's low threshold. */
|
|
63029
63457
|
lowFood: boolean(),
|
|
63030
63458
|
/** Battery charge 0..100 (%). Null on mains-powered models or when the
|
|
63031
63459
|
* device has no battery reading. */
|
|
63032
|
-
batteryPower: number().min(0).max(100).nullable(),
|
|
63033
|
-
/**
|
|
63034
|
-
*
|
|
63035
|
-
|
|
63460
|
+
batteryPower: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
63461
|
+
/**
|
|
63462
|
+
* Desiccant life remaining, stored in seconds (duration base, D944).
|
|
63463
|
+
* Providers convert from the days the feeder reports. Null when the
|
|
63464
|
+
* model has no desiccant sensor.
|
|
63465
|
+
*/
|
|
63466
|
+
desiccantLeftDays: number().nullable().meta(readingMeta("duration")),
|
|
63036
63467
|
/** True while a feed is in progress. */
|
|
63037
63468
|
feeding: boolean(),
|
|
63038
63469
|
/** Decoded connectivity / power status (HA petkit device-status enum).
|
|
@@ -63043,7 +63474,7 @@ var PetFeederStatusSchema = object({
|
|
|
63043
63474
|
* with `errorCode` for consumers that want the raw integer. */
|
|
63044
63475
|
error: string().nullable(),
|
|
63045
63476
|
/** Raw device error code (0 / null = no error). */
|
|
63046
|
-
errorCode: number().nullable(),
|
|
63477
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
63047
63478
|
/** True for D4S/D4SH dual-hopper hardware — gates the per-hopper UI. */
|
|
63048
63479
|
isDualHopper: boolean(),
|
|
63049
63480
|
/** Child-lock (manual-lock) setting — buttons on the unit are disabled. */
|
|
@@ -63053,7 +63484,7 @@ var PetFeederStatusSchema = object({
|
|
|
63053
63484
|
/** Play a chime when dispensing. */
|
|
63054
63485
|
feedSound: boolean(),
|
|
63055
63486
|
/** Speaker / prompt volume level (device-scaled integer). */
|
|
63056
|
-
volume: number(),
|
|
63487
|
+
volume: number().meta(readingMeta("none")),
|
|
63057
63488
|
/** Ms epoch when the slice was last refreshed from the cloud. */
|
|
63058
63489
|
lastFetchedAt: number()
|
|
63059
63490
|
});
|
|
@@ -63172,7 +63603,7 @@ var petFeederCapability = {
|
|
|
63172
63603
|
},
|
|
63173
63604
|
desiccantLeftDays: {
|
|
63174
63605
|
kind: "gauge",
|
|
63175
|
-
unit: "
|
|
63606
|
+
unit: "s"
|
|
63176
63607
|
}
|
|
63177
63608
|
} }
|
|
63178
63609
|
};
|
|
@@ -63573,36 +64004,19 @@ method(_void(), PlatformCapabilitiesSchema), method(_void(), HardwareInfoSchema)
|
|
|
63573
64004
|
*/
|
|
63574
64005
|
var PowerMeterStatusSchema = object({
|
|
63575
64006
|
/** Instantaneous power draw in watts. */
|
|
63576
|
-
watts: number().optional().meta({
|
|
63577
|
-
unit: "W",
|
|
63578
|
-
label: "Power"
|
|
63579
|
-
}),
|
|
64007
|
+
watts: number().optional().meta(readingMeta("power", { label: "Power" })),
|
|
63580
64008
|
/** Cumulative energy in kilowatt-hours since the meter was reset. */
|
|
63581
|
-
kwhTotal: number().optional().meta({
|
|
63582
|
-
unit: "kWh",
|
|
63583
|
-
label: "Energy"
|
|
63584
|
-
}),
|
|
64009
|
+
kwhTotal: number().optional().meta(readingMeta("energy", { label: "Energy" })),
|
|
63585
64010
|
/** Voltage in volts. */
|
|
63586
|
-
volts: number().optional(),
|
|
64011
|
+
volts: number().optional().meta(readingMeta("voltage")),
|
|
63587
64012
|
/** Current in amperes. */
|
|
63588
|
-
amps: number().optional(),
|
|
63589
|
-
/** Apparent power in volt-amperes
|
|
63590
|
-
va: number().optional(),
|
|
64013
|
+
amps: number().optional().meta(readingMeta("current")),
|
|
64014
|
+
/** Apparent power in volt-amperes. */
|
|
64015
|
+
va: number().optional().meta(readingMeta("apparent-power")),
|
|
63591
64016
|
/** Power factor (0..1) if reported. */
|
|
63592
|
-
powerFactor: number().min(0).max(1).optional(),
|
|
64017
|
+
powerFactor: number().min(0).max(1).optional().meta(readingMeta("ratio")),
|
|
63593
64018
|
/** Ms epoch when the slice was last updated. */
|
|
63594
|
-
lastFetchedAt: number()
|
|
63595
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
63596
|
-
* `attributes.unit_of_measurement` → 'V' / 'A' / 'W' / 'kW' / 'kWh').
|
|
63597
|
-
* Each upstream `sensor.*` entity surfaces ONE device_class, so one
|
|
63598
|
-
* unit per slice is unambiguous. The UI prefers this over the role's
|
|
63599
|
-
* canonical unit so a 'kW' / 'Wh' feed renders verbatim. */
|
|
63600
|
-
unit: string().optional(),
|
|
63601
|
-
/** Suggested decimal places for numeric display.
|
|
63602
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
63603
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
63604
|
-
* auto-formatting when absent. */
|
|
63605
|
-
precision: number().int().min(0).max(10).optional()
|
|
64019
|
+
lastFetchedAt: number()
|
|
63606
64020
|
});
|
|
63607
64021
|
var powerMeterCapability = {
|
|
63608
64022
|
name: "power-meter",
|
|
@@ -63666,12 +64080,7 @@ var powerMeterCapability = {
|
|
|
63666
64080
|
} },
|
|
63667
64081
|
/** Clock fields: written, but excluded from the compare that decides
|
|
63668
64082
|
* whether persisting is worth a SQLite commit. */
|
|
63669
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
63670
|
-
customize: {
|
|
63671
|
-
version: 1,
|
|
63672
|
-
advanced: "derive",
|
|
63673
|
-
targets: []
|
|
63674
|
-
}
|
|
64083
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
63675
64084
|
};
|
|
63676
64085
|
/**
|
|
63677
64086
|
* Presence cap. Models HA `person.*` and `device_tracker.*` entities
|
|
@@ -63691,11 +64100,11 @@ var powerMeterCapability = {
|
|
|
63691
64100
|
*/
|
|
63692
64101
|
var GpsLocationSchema = object({
|
|
63693
64102
|
/** Latitude in decimal degrees, -90..90. */
|
|
63694
|
-
latitude: number().min(-90).max(90),
|
|
64103
|
+
latitude: number().min(-90).max(90).meta(readingMeta("angle")),
|
|
63695
64104
|
/** Longitude in decimal degrees, -180..180. */
|
|
63696
|
-
longitude: number().min(-180).max(180),
|
|
64105
|
+
longitude: number().min(-180).max(180).meta(readingMeta("angle")),
|
|
63697
64106
|
/** Reported accuracy in meters (lower = better). */
|
|
63698
|
-
accuracyMeters: number().nonnegative()
|
|
64107
|
+
accuracyMeters: number().nonnegative().meta(readingMeta("length"))
|
|
63699
64108
|
});
|
|
63700
64109
|
var PresenceStatusSchema = object({
|
|
63701
64110
|
/** `home` / `not_home` / any user-defined zone name. */
|
|
@@ -63707,7 +64116,7 @@ var PresenceStatusSchema = object({
|
|
|
63707
64116
|
gps: GpsLocationSchema.nullable(),
|
|
63708
64117
|
/** Optional battery level of the tracking device (0..100). Null
|
|
63709
64118
|
* when not reported. */
|
|
63710
|
-
batteryPercent: number().min(0).max(100).nullable(),
|
|
64119
|
+
batteryPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
63711
64120
|
/** Ms epoch when the slice was last updated. */
|
|
63712
64121
|
lastChangedAt: number()
|
|
63713
64122
|
});
|
|
@@ -63757,19 +64166,10 @@ var presenceCapability = {
|
|
|
63757
64166
|
* `sourceInfo`.
|
|
63758
64167
|
*/
|
|
63759
64168
|
var PressureSensorStatusSchema = object({
|
|
63760
|
-
/** Current pressure in hPa. */
|
|
63761
|
-
hpa: number(),
|
|
64169
|
+
/** Current pressure in hPa. `null` when the sample was refused (D393). */
|
|
64170
|
+
hpa: number().nullable().meta(readingMeta("pressure", { precision: 0 })),
|
|
63762
64171
|
/** Ms epoch when the slice was last updated. */
|
|
63763
|
-
lastFetchedAt: number()
|
|
63764
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
63765
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
63766
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
63767
|
-
unit: string().optional(),
|
|
63768
|
-
/** Suggested decimal places for numeric display.
|
|
63769
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
63770
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
63771
|
-
* auto-formatting when absent. */
|
|
63772
|
-
precision: number().int().min(0).max(10).optional()
|
|
64172
|
+
lastFetchedAt: number()
|
|
63773
64173
|
});
|
|
63774
64174
|
var pressureSensorCapability = {
|
|
63775
64175
|
name: "pressure-sensor",
|
|
@@ -64183,8 +64583,8 @@ DeviceType.Camera, method(PtzMoveCommandSchema.extend({ deviceId: number() }), _
|
|
|
64183
64583
|
}), _void(), { kind: "mutation" });
|
|
64184
64584
|
var PtzAutotrackSettingsSchema = object({
|
|
64185
64585
|
targetType: string().describe("Vendor target string (people/vehicle/pet); empty = camera default"),
|
|
64186
|
-
stopDelaySeconds: number().int().min(0).max(300),
|
|
64187
|
-
disappearDelaySeconds: number().int().min(0).max(300)
|
|
64586
|
+
stopDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration")),
|
|
64587
|
+
disappearDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration"))
|
|
64188
64588
|
});
|
|
64189
64589
|
/**
|
|
64190
64590
|
* One option the camera advertises as a valid `targetType`. Drivers
|
|
@@ -64338,7 +64738,7 @@ var RunningStateStatusSchema = object({
|
|
|
64338
64738
|
/** null = unknown — never coerced to false (D393). */
|
|
64339
64739
|
running: boolean().nullable(),
|
|
64340
64740
|
/** Epoch ms the current boolean began; null while `running` is null. */
|
|
64341
|
-
since: number().nullable(),
|
|
64741
|
+
since: number().nullable().meta(readingMeta("none")),
|
|
64342
64742
|
source: RunningStateSourceSchema.meta({ label: "Source" }),
|
|
64343
64743
|
phase: string().nullable(),
|
|
64344
64744
|
/** null until a reading has been published (D393). */
|
|
@@ -64353,7 +64753,6 @@ var RUNNING_DEVICE_TYPES = Object.values(DeviceType);
|
|
|
64353
64753
|
/** Generic Customize target for the running boolean (D936). */
|
|
64354
64754
|
var runningCustomize = {
|
|
64355
64755
|
version: 1,
|
|
64356
|
-
advanced: "derive",
|
|
64357
64756
|
targets: [{
|
|
64358
64757
|
id: "running",
|
|
64359
64758
|
cardinality: "scalar",
|
|
@@ -64373,7 +64772,7 @@ var runningCustomize = {
|
|
|
64373
64772
|
DeviceType.Thermostat,
|
|
64374
64773
|
DeviceType.PetFeeder
|
|
64375
64774
|
],
|
|
64376
|
-
apply: "add
|
|
64775
|
+
apply: "add",
|
|
64377
64776
|
path: "running",
|
|
64378
64777
|
sources: [
|
|
64379
64778
|
{
|
|
@@ -65637,9 +66036,9 @@ var RecordTriggerSchema = _enum([
|
|
|
65637
66036
|
*/
|
|
65638
66037
|
var RecordWindowSchema = object({
|
|
65639
66038
|
trigger: RecordTriggerSchema,
|
|
65640
|
-
day: number().int().min(0).max(6),
|
|
65641
|
-
startMinute: number().int().min(0).max(1439),
|
|
65642
|
-
endMinute: number().int().min(1).max(1440)
|
|
66039
|
+
day: number().int().min(0).max(6).meta(readingMeta("none")),
|
|
66040
|
+
startMinute: number().int().min(0).max(1439).meta(readingMeta("none")),
|
|
66041
|
+
endMinute: number().int().min(1).max(1440).meta(readingMeta("none"))
|
|
65643
66042
|
});
|
|
65644
66043
|
/** Status of one physical volume, as the camera itself describes it. */
|
|
65645
66044
|
var OnboardStorageVolumeSchema = object({
|
|
@@ -65715,10 +66114,10 @@ var RecordingOnboardStatusSchema = object({
|
|
|
65715
66114
|
/** Master "record to the card at all" switch. */
|
|
65716
66115
|
enabled: boolean().nullable(),
|
|
65717
66116
|
overwriteWhenFull: boolean().nullable(),
|
|
65718
|
-
preRecordSec: number().nullable(),
|
|
65719
|
-
postRecordSec: number().nullable(),
|
|
66117
|
+
preRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
66118
|
+
postRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
65720
66119
|
/** Length of one recorded file, in minutes. */
|
|
65721
|
-
segmentMinutes: number().nullable(),
|
|
66120
|
+
segmentMinutes: number().nullable().meta(readingMeta("none")),
|
|
65722
66121
|
/** The primary track's weekly windows, flattened. */
|
|
65723
66122
|
windows: array(RecordWindowSchema),
|
|
65724
66123
|
/**
|
|
@@ -65734,7 +66133,7 @@ var RecordingOnboardStatusSchema = object({
|
|
|
65734
66133
|
* provider reporting a non-zero count also reports the schedule as not
|
|
65735
66134
|
* writable.
|
|
65736
66135
|
*/
|
|
65737
|
-
unreadableWindows: number(),
|
|
66136
|
+
unreadableWindows: number().meta(readingMeta("count")),
|
|
65738
66137
|
/**
|
|
65739
66138
|
* The camera is scheduled to record and has NO usable storage.
|
|
65740
66139
|
*
|
|
@@ -66579,7 +66978,7 @@ var CamStreamDescriptorSchema = object({
|
|
|
66579
66978
|
url: string().optional(),
|
|
66580
66979
|
codec: string().optional(),
|
|
66581
66980
|
resolution: CamStreamResolutionSchema.optional(),
|
|
66582
|
-
fps: number().positive().optional(),
|
|
66981
|
+
fps: number().positive().optional().meta(readingMeta("rate")),
|
|
66583
66982
|
label: string().optional(),
|
|
66584
66983
|
/** Device-level features (e.g. `battery-operated`) — drives broker policy. */
|
|
66585
66984
|
deviceFeatures: array(string()).optional(),
|
|
@@ -66666,18 +67065,18 @@ var StreamProfileSchema = _enum([
|
|
|
66666
67065
|
]);
|
|
66667
67066
|
/** The current encoding config of one stream profile. */
|
|
66668
67067
|
var StreamProfileConfigSchema = object({
|
|
66669
|
-
width: number(),
|
|
66670
|
-
height: number(),
|
|
67068
|
+
width: number().meta(readingMeta("none")),
|
|
67069
|
+
height: number().meta(readingMeta("none")),
|
|
66671
67070
|
codec: _enum(["h264", "h265"]),
|
|
66672
|
-
framerate: number(),
|
|
66673
|
-
bitrate: number(),
|
|
67071
|
+
framerate: number().meta(readingMeta("rate")),
|
|
67072
|
+
bitrate: number().meta(readingMeta("bitrate")),
|
|
66674
67073
|
bitrateMode: _enum(["vbr", "cbr"]).optional(),
|
|
66675
67074
|
encoderProfile: _enum([
|
|
66676
67075
|
"high",
|
|
66677
67076
|
"main",
|
|
66678
67077
|
"baseline"
|
|
66679
67078
|
]).optional(),
|
|
66680
|
-
gop: number().optional(),
|
|
67079
|
+
gop: number().optional().meta(readingMeta("none")),
|
|
66681
67080
|
/**
|
|
66682
67081
|
* Whether THIS profile currently carries an audio track. READ-ONLY here.
|
|
66683
67082
|
*
|
|
@@ -66898,12 +67297,7 @@ var switchCapability = {
|
|
|
66898
67297
|
label: "On",
|
|
66899
67298
|
kind: "boolean"
|
|
66900
67299
|
}
|
|
66901
|
-
}] }
|
|
66902
|
-
customize: {
|
|
66903
|
-
version: 1,
|
|
66904
|
-
advanced: "derive",
|
|
66905
|
-
targets: []
|
|
66906
|
-
}
|
|
67300
|
+
}] }
|
|
66907
67301
|
};
|
|
66908
67302
|
/** C0 controls, DEL and the C1 range: none of them belongs in a name. */
|
|
66909
67303
|
function hasControlCharacter(value) {
|
|
@@ -67486,35 +67880,21 @@ var tamperCapability = {
|
|
|
67486
67880
|
* entries with `device_class: temperature` and any future native
|
|
67487
67881
|
* thermometer.
|
|
67488
67882
|
*
|
|
67489
|
-
*
|
|
67490
|
-
*
|
|
67491
|
-
* (climate-control's `currentTemp`, energy analytics) can compose
|
|
67492
|
-
* without per-source unit fixups. The canonical display unit (`°C`) is
|
|
67493
|
-
* a descriptor constant in the UI (ROLE_DESCRIPTOR), not stored in
|
|
67494
|
-
* `sourceInfo`.
|
|
67883
|
+
* The number is Celsius (D944). Providers convert on ingest. A failed
|
|
67884
|
+
* conversion is `null`, never a guess. Display unit is a read-time preference.
|
|
67495
67885
|
*
|
|
67496
67886
|
* Status `lastFetchedAt` lets staleness-aware consumers detect a
|
|
67497
67887
|
* frozen feed (provider hung) distinct from a "temperature hasn't
|
|
67498
67888
|
* changed" steady state.
|
|
67499
67889
|
*/
|
|
67500
67890
|
var TemperatureSensorStatusSchema = object({
|
|
67501
|
-
/** Current temperature in Celsius. */
|
|
67502
|
-
celsius: number().meta({
|
|
67503
|
-
|
|
67891
|
+
/** Current temperature in Celsius. `null` when the sample was refused (D393). */
|
|
67892
|
+
celsius: number().nullable().meta(readingMeta("temperature", {
|
|
67893
|
+
precision: 1,
|
|
67504
67894
|
label: "Temperature"
|
|
67505
|
-
}),
|
|
67895
|
+
})),
|
|
67506
67896
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
67507
|
-
lastFetchedAt: number()
|
|
67508
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
67509
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
67510
|
-
* role's canonical unit, so a Fahrenheit feed renders '°F' not '°C'.
|
|
67511
|
-
* Absent → the UI falls back to the role's canonical unit. */
|
|
67512
|
-
unit: string().optional(),
|
|
67513
|
-
/** Suggested decimal places for numeric display.
|
|
67514
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
67515
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
67516
|
-
* auto-formatting when absent. */
|
|
67517
|
-
precision: number().int().min(0).max(10).optional()
|
|
67897
|
+
lastFetchedAt: number()
|
|
67518
67898
|
});
|
|
67519
67899
|
var temperatureSensorCapability = {
|
|
67520
67900
|
name: "temperature-sensor",
|
|
@@ -67545,12 +67925,7 @@ var temperatureSensorCapability = {
|
|
|
67545
67925
|
} } },
|
|
67546
67926
|
/** Clock fields: written, but excluded from the compare that decides
|
|
67547
67927
|
* whether persisting is worth a SQLite commit. */
|
|
67548
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
67549
|
-
customize: {
|
|
67550
|
-
version: 1,
|
|
67551
|
-
advanced: "derive",
|
|
67552
|
-
targets: []
|
|
67553
|
-
}
|
|
67928
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
67554
67929
|
};
|
|
67555
67930
|
/**
|
|
67556
67931
|
* toast — system-scoped singleton capability that streams toast
|
|
@@ -67833,16 +68208,16 @@ var VacuumControlStatusSchema = object({
|
|
|
67833
68208
|
]),
|
|
67834
68209
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
67835
68210
|
* reading. */
|
|
67836
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
68211
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
67837
68212
|
/** Current fan-speed token (provider-verbatim). Null when unknown or
|
|
67838
68213
|
* the vacuum has no speed control. */
|
|
67839
68214
|
fanSpeed: string().nullable(),
|
|
67840
68215
|
/** Speed tokens the hardware accepts — drives the UI selector. */
|
|
67841
68216
|
availableFanSpeeds: array(string()),
|
|
67842
68217
|
/** 0..100 cleaning-completion percentage of the current task, or null. */
|
|
67843
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
68218
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
67844
68219
|
/** Current error code (0 / null = no error). */
|
|
67845
|
-
errorCode: number().nullable(),
|
|
68220
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
67846
68221
|
/** Human label for {@link errorCode}, or null when none / undecodable. */
|
|
67847
68222
|
errorLabel: string().nullable(),
|
|
67848
68223
|
/** Ms epoch when the slice was last updated. */
|
|
@@ -67920,7 +68295,7 @@ var ValveStatusSchema = object({
|
|
|
67920
68295
|
]),
|
|
67921
68296
|
/** 0 = fully closed, 100 = fully open. Null when the device has no
|
|
67922
68297
|
* intermediate position surface. */
|
|
67923
|
-
position: number().min(0).max(100).nullable(),
|
|
68298
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
67924
68299
|
/** Ms epoch when the slice was last updated. */
|
|
67925
68300
|
lastChangedAt: number()
|
|
67926
68301
|
});
|
|
@@ -68028,9 +68403,9 @@ var vibrationCapability = {
|
|
|
68028
68403
|
*/
|
|
68029
68404
|
var WaterHeaterStatusSchema = object({
|
|
68030
68405
|
/** Current measured temperature. Null when not reported. */
|
|
68031
|
-
currentTemp: number().nullable(),
|
|
68406
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
68032
68407
|
/** Target temperature setpoint. Null when no setpoint surface. */
|
|
68033
|
-
targetTemp: number().nullable(),
|
|
68408
|
+
targetTemp: number().nullable().meta(readingMeta("temperature")),
|
|
68034
68409
|
/** Active operation mode = HA `state` (`eco` / `electric` / `gas` /
|
|
68035
68410
|
* `heat_pump` / `high_demand` / `performance` / `off`). Null when the
|
|
68036
68411
|
* device reports an unknown state. */
|
|
@@ -68041,9 +68416,9 @@ var WaterHeaterStatusSchema = object({
|
|
|
68041
68416
|
* has no away surface. */
|
|
68042
68417
|
away: boolean().nullable(),
|
|
68043
68418
|
/** HA `min_temp` attribute. Null when not reported. */
|
|
68044
|
-
minTemp: number().nullable(),
|
|
68419
|
+
minTemp: number().nullable().meta(readingMeta("temperature")),
|
|
68045
68420
|
/** HA `max_temp` attribute. Null when not reported. */
|
|
68046
|
-
maxTemp: number().nullable(),
|
|
68421
|
+
maxTemp: number().nullable().meta(readingMeta("temperature")),
|
|
68047
68422
|
/** Ms epoch when the slice was last updated. */
|
|
68048
68423
|
lastChangedAt: number()
|
|
68049
68424
|
});
|
|
@@ -68128,25 +68503,18 @@ var waterHeaterCapability = {
|
|
|
68128
68503
|
* Forecast deferred — current conditions only for v1.
|
|
68129
68504
|
*/
|
|
68130
68505
|
var WeatherStatusSchema = object({
|
|
68131
|
-
/** Verbatim
|
|
68132
|
-
* when no condition has been reported yet. */
|
|
68506
|
+
/** Verbatim condition state (`sunny`, `cloudy`, `rainy`, …). Null when none yet. */
|
|
68133
68507
|
condition: string().nullable(),
|
|
68134
|
-
/** Current temperature in
|
|
68135
|
-
temperature: number().nullable(),
|
|
68136
|
-
/** Temperature unit string (e.g. `°C` / `°F`). Null when not provided. */
|
|
68137
|
-
temperatureUnit: string().nullable(),
|
|
68508
|
+
/** Current temperature in Celsius. Null when not provided or refused. */
|
|
68509
|
+
temperature: number().nullable().meta(readingMeta("temperature", { precision: 1 })),
|
|
68138
68510
|
/** Relative humidity (0..100). Null when not provided. */
|
|
68139
|
-
humidity: number().min(0).max(100).nullable(),
|
|
68140
|
-
/** Barometric pressure in
|
|
68141
|
-
pressure: number().nullable(),
|
|
68142
|
-
/**
|
|
68143
|
-
|
|
68144
|
-
/** Wind speed in the reported unit. Null when not provided. */
|
|
68145
|
-
windSpeed: number().nullable(),
|
|
68146
|
-
/** Wind-speed unit string (e.g. `km/h` / `mph`). Null when not provided. */
|
|
68147
|
-
windSpeedUnit: string().nullable(),
|
|
68511
|
+
humidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
68512
|
+
/** Barometric pressure in hPa. Null when not provided or refused. */
|
|
68513
|
+
pressure: number().nullable().meta(readingMeta("pressure")),
|
|
68514
|
+
/** Wind speed in metres per second. Null when not provided or refused. */
|
|
68515
|
+
windSpeed: number().nullable().meta(readingMeta("speed")),
|
|
68148
68516
|
/** Wind bearing in degrees (0..360, meteorological). Null when not provided. */
|
|
68149
|
-
windBearing: number().nullable(),
|
|
68517
|
+
windBearing: number().nullable().meta(readingMeta("angle")),
|
|
68150
68518
|
/** Ms epoch when the slice was last updated. */
|
|
68151
68519
|
lastFetchedAt: number()
|
|
68152
68520
|
});
|
|
@@ -68174,12 +68542,12 @@ var weatherCapability = {
|
|
|
68174
68542
|
*/
|
|
68175
68543
|
durability: "session",
|
|
68176
68544
|
/**
|
|
68177
|
-
* History (D850): recorded series.
|
|
68545
|
+
* History (D850): recorded series. Numbers are the quantity base (D944).
|
|
68178
68546
|
*/
|
|
68179
68547
|
history: { fields: {
|
|
68180
68548
|
temperature: {
|
|
68181
68549
|
kind: "gauge",
|
|
68182
|
-
|
|
68550
|
+
unit: "°C",
|
|
68183
68551
|
deadband: .2
|
|
68184
68552
|
},
|
|
68185
68553
|
humidity: {
|
|
@@ -68189,12 +68557,12 @@ var weatherCapability = {
|
|
|
68189
68557
|
},
|
|
68190
68558
|
pressure: {
|
|
68191
68559
|
kind: "gauge",
|
|
68192
|
-
|
|
68560
|
+
unit: "hPa",
|
|
68193
68561
|
deadband: .5
|
|
68194
68562
|
},
|
|
68195
68563
|
windSpeed: {
|
|
68196
68564
|
kind: "gauge",
|
|
68197
|
-
|
|
68565
|
+
unit: "m/s",
|
|
68198
68566
|
deadband: .5
|
|
68199
68567
|
}
|
|
68200
68568
|
} }
|
|
@@ -69425,6 +69793,8 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
69425
69793
|
featureProbe: featureProbeCapability,
|
|
69426
69794
|
flood: floodCapability,
|
|
69427
69795
|
gas: gasCapability,
|
|
69796
|
+
groupCommands: groupCommandsCapability,
|
|
69797
|
+
groupStatus: groupStatusCapability,
|
|
69428
69798
|
heatingValve: heatingValveCapability,
|
|
69429
69799
|
humidifier: humidifierCapability,
|
|
69430
69800
|
humiditySensor: humiditySensorCapability,
|
|
@@ -70801,6 +71171,13 @@ Object.freeze({
|
|
|
70801
71171
|
access: "view",
|
|
70802
71172
|
role: "admin"
|
|
70803
71173
|
},
|
|
71174
|
+
"addons.getPackageDocs": {
|
|
71175
|
+
capName: "addons",
|
|
71176
|
+
capScope: "system",
|
|
71177
|
+
addonId: null,
|
|
71178
|
+
access: "view",
|
|
71179
|
+
role: "admin"
|
|
71180
|
+
},
|
|
70804
71181
|
"addons.getVersions": {
|
|
70805
71182
|
capName: "addons",
|
|
70806
71183
|
capScope: "system",
|
|
@@ -73909,6 +74286,20 @@ Object.freeze({
|
|
|
73909
74286
|
access: "view",
|
|
73910
74287
|
role: "viewer"
|
|
73911
74288
|
},
|
|
74289
|
+
"groupCommands.getStatus": {
|
|
74290
|
+
capName: "group-commands",
|
|
74291
|
+
capScope: "device",
|
|
74292
|
+
addonId: null,
|
|
74293
|
+
access: "view",
|
|
74294
|
+
role: "viewer"
|
|
74295
|
+
},
|
|
74296
|
+
"groupStatus.getStatus": {
|
|
74297
|
+
capName: "group-status",
|
|
74298
|
+
capScope: "device",
|
|
74299
|
+
addonId: null,
|
|
74300
|
+
access: "view",
|
|
74301
|
+
role: "viewer"
|
|
74302
|
+
},
|
|
73912
74303
|
"heatingValve.getStatus": {
|
|
73913
74304
|
capName: "heating-valve",
|
|
73914
74305
|
capScope: "device",
|
|
@@ -83731,6 +84122,37 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83731
84122
|
icon: "flame"
|
|
83732
84123
|
}]
|
|
83733
84124
|
},
|
|
84125
|
+
"group-commands": {
|
|
84126
|
+
scope: "device",
|
|
84127
|
+
noun: t("Group command", "Comando di gruppo")
|
|
84128
|
+
},
|
|
84129
|
+
"group-status": {
|
|
84130
|
+
scope: "device",
|
|
84131
|
+
noun: t("Group", "Gruppo"),
|
|
84132
|
+
state: [
|
|
84133
|
+
{
|
|
84134
|
+
kind: "numeric",
|
|
84135
|
+
field: "included",
|
|
84136
|
+
quantity: t("the members reporting", "i membri che rispondono"),
|
|
84137
|
+
label: t("Reporting", "Rispondono"),
|
|
84138
|
+
icon: "users"
|
|
84139
|
+
},
|
|
84140
|
+
{
|
|
84141
|
+
kind: "numeric",
|
|
84142
|
+
field: "excluded",
|
|
84143
|
+
quantity: t("the members left out", "i membri esclusi"),
|
|
84144
|
+
label: t("Excluded", "Esclusi"),
|
|
84145
|
+
icon: "users"
|
|
84146
|
+
},
|
|
84147
|
+
{
|
|
84148
|
+
kind: "numeric",
|
|
84149
|
+
field: "total",
|
|
84150
|
+
quantity: t("the member count", "il numero di membri"),
|
|
84151
|
+
label: t("Members", "Membri"),
|
|
84152
|
+
icon: "sigma"
|
|
84153
|
+
}
|
|
84154
|
+
]
|
|
84155
|
+
},
|
|
83734
84156
|
"humidity-sensor": {
|
|
83735
84157
|
scope: "device",
|
|
83736
84158
|
noun: t("Humidity", "Umidità"),
|
|
@@ -83764,7 +84186,6 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83764
84186
|
field: "value",
|
|
83765
84187
|
quantity: t("the reading", "il valore"),
|
|
83766
84188
|
label: t("Reading", "Valore"),
|
|
83767
|
-
unitField: "unit",
|
|
83768
84189
|
icon: "gauge"
|
|
83769
84190
|
}]
|
|
83770
84191
|
},
|
|
@@ -83900,7 +84321,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83900
84321
|
field: "temperature",
|
|
83901
84322
|
quantity: t("the outdoor temperature", "la temperatura esterna"),
|
|
83902
84323
|
label: t("Temperature", "Temperatura"),
|
|
83903
|
-
|
|
84324
|
+
unit: "°C",
|
|
83904
84325
|
icon: "thermometer"
|
|
83905
84326
|
},
|
|
83906
84327
|
{
|
|
@@ -83916,7 +84337,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83916
84337
|
field: "windSpeed",
|
|
83917
84338
|
quantity: t("the wind speed", "la velocità del vento"),
|
|
83918
84339
|
label: t("Wind", "Vento"),
|
|
83919
|
-
|
|
84340
|
+
unit: "m/s",
|
|
83920
84341
|
icon: "wind"
|
|
83921
84342
|
},
|
|
83922
84343
|
{
|
|
@@ -83924,7 +84345,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83924
84345
|
field: "pressure",
|
|
83925
84346
|
quantity: t("the air pressure", "la pressione atmosferica"),
|
|
83926
84347
|
label: t("Pressure", "Pressione"),
|
|
83927
|
-
|
|
84348
|
+
unit: "hPa",
|
|
83928
84349
|
icon: "gauge"
|
|
83929
84350
|
}
|
|
83930
84351
|
]
|
|
@@ -85197,6 +85618,16 @@ Object.freeze({
|
|
|
85197
85618
|
form: "single",
|
|
85198
85619
|
optional: false
|
|
85199
85620
|
}],
|
|
85621
|
+
"groupCommands.getStatus": [{
|
|
85622
|
+
name: "deviceId",
|
|
85623
|
+
form: "single",
|
|
85624
|
+
optional: false
|
|
85625
|
+
}],
|
|
85626
|
+
"groupStatus.getStatus": [{
|
|
85627
|
+
name: "deviceId",
|
|
85628
|
+
form: "single",
|
|
85629
|
+
optional: false
|
|
85630
|
+
}],
|
|
85200
85631
|
"heatingValve.getStatus": [{
|
|
85201
85632
|
name: "deviceId",
|
|
85202
85633
|
form: "single",
|
|
@@ -87181,6 +87612,8 @@ new Map(Object.entries({
|
|
|
87181
87612
|
"detection-blind": "device-events",
|
|
87182
87613
|
"motion-noisy": "device-events",
|
|
87183
87614
|
"motion-calm": "device-events",
|
|
87615
|
+
"package-llm-silent": "device-events",
|
|
87616
|
+
"package-llm-answered": "device-events",
|
|
87184
87617
|
"recording-stalled": "device-events",
|
|
87185
87618
|
"recording-healthy": "device-events",
|
|
87186
87619
|
"recording-degraded": "device-events",
|
|
@@ -87264,6 +87697,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
|
|
|
87264
87697
|
label: "Motion without a subject",
|
|
87265
87698
|
kinds: ["motion-noisy", "motion-calm"]
|
|
87266
87699
|
},
|
|
87700
|
+
{
|
|
87701
|
+
id: "package-llm",
|
|
87702
|
+
family: "device-events",
|
|
87703
|
+
label: "Package confirm",
|
|
87704
|
+
kinds: ["package-llm-silent", "package-llm-answered"]
|
|
87705
|
+
},
|
|
87267
87706
|
{
|
|
87268
87707
|
id: "recording",
|
|
87269
87708
|
family: "device-events",
|
|
@@ -87445,6 +87884,8 @@ var DEVICE_EVENTS = [
|
|
|
87445
87884
|
"detection-blind",
|
|
87446
87885
|
"motion-noisy",
|
|
87447
87886
|
"motion-calm",
|
|
87887
|
+
"package-llm-silent",
|
|
87888
|
+
"package-llm-answered",
|
|
87448
87889
|
"recording-stalled",
|
|
87449
87890
|
"recording-healthy",
|
|
87450
87891
|
"recording-degraded",
|
|
@@ -87713,6 +88154,15 @@ new Map([
|
|
|
87713
88154
|
snapshotLabel: "Cameras with constant motion now",
|
|
87714
88155
|
snapshotSection: null
|
|
87715
88156
|
},
|
|
88157
|
+
{
|
|
88158
|
+
id: "package-llm-confirm",
|
|
88159
|
+
family: "device-events",
|
|
88160
|
+
label: "Package confirm (not answering / answering again)",
|
|
88161
|
+
bad: ["package-llm-silent"],
|
|
88162
|
+
recovery: ["package-llm-answered"],
|
|
88163
|
+
snapshotLabel: "Cameras whose package confirm is not answering",
|
|
88164
|
+
snapshotSection: null
|
|
88165
|
+
},
|
|
87716
88166
|
{
|
|
87717
88167
|
id: "recording-health",
|
|
87718
88168
|
family: "device-events",
|