@camstack/addon-mqtt-broker 1.2.145 → 1.2.147
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 +21 -0
- package/README.md +33 -0
- package/dist/mqtt-broker.addon.js +1366 -447
- package/dist/mqtt-broker.addon.mjs +1366 -447
- package/package.json +4 -2
|
@@ -46,7 +46,7 @@ let node_fs = require("node:fs");
|
|
|
46
46
|
node_fs = __toESM(node_fs);
|
|
47
47
|
let node_path = require("node:path");
|
|
48
48
|
node_path = __toESM(node_path);
|
|
49
|
-
//#region ../types/dist/event-category-
|
|
49
|
+
//#region ../types/dist/event-category-CT-hz5Rb.mjs
|
|
50
50
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
51
51
|
EventCategory["SystemBoot"] = "system.boot";
|
|
52
52
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -372,6 +372,14 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
372
372
|
/** The recovery edge of {@link PipelineMotionNoisy}: the motion fell back, or a detection arrived. */
|
|
373
373
|
EventCategory["PipelineMotionCalm"] = "pipeline.motion-calm";
|
|
374
374
|
/**
|
|
375
|
+
* A camera's package LLM confirm has failed closed three times in a row
|
|
376
|
+
* (D931, 2026-10-26). One edge per camera until
|
|
377
|
+
* {@link PipelinePackageLlmAnswered}.
|
|
378
|
+
*/
|
|
379
|
+
EventCategory["PipelinePackageLlmSilent"] = "pipeline.package-llm-silent";
|
|
380
|
+
/** The recovery edge of {@link PipelinePackageLlmSilent}: a confirm returned yes or no. */
|
|
381
|
+
EventCategory["PipelinePackageLlmAnswered"] = "pipeline.package-llm-answered";
|
|
382
|
+
/**
|
|
375
383
|
* Per-camera pipeline config was mutated by the orchestrator
|
|
376
384
|
* (a settings change via `setAgentInferenceDevices` /
|
|
377
385
|
* `setCameraStepToggle` / `setCameraStepSettings`). Orchestrator
|
|
@@ -5614,7 +5622,7 @@ var ZodIssueCode = {
|
|
|
5614
5622
|
var ZodFirstPartyTypeKind;
|
|
5615
5623
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5616
5624
|
//#endregion
|
|
5617
|
-
//#region ../types/dist/sleep
|
|
5625
|
+
//#region ../types/dist/sleep--jXS9hWo.mjs
|
|
5618
5626
|
/**
|
|
5619
5627
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5620
5628
|
* window to float samples (D455).
|
|
@@ -8356,6 +8364,99 @@ function defineEntryKind(name, spec) {
|
|
|
8356
8364
|
if (defined === void 0) throw new DeclarationRefusedError(`entry kind "${name}" was not built`);
|
|
8357
8365
|
return defined;
|
|
8358
8366
|
}
|
|
8367
|
+
var READING_QUANTITIES = [
|
|
8368
|
+
"temperature",
|
|
8369
|
+
"pressure",
|
|
8370
|
+
"speed",
|
|
8371
|
+
"precipitation",
|
|
8372
|
+
"precipitation-rate",
|
|
8373
|
+
"length",
|
|
8374
|
+
"area",
|
|
8375
|
+
"illuminance",
|
|
8376
|
+
"irradiance",
|
|
8377
|
+
"power",
|
|
8378
|
+
"energy",
|
|
8379
|
+
"voltage",
|
|
8380
|
+
"current",
|
|
8381
|
+
"apparent-power",
|
|
8382
|
+
"humidity",
|
|
8383
|
+
"percentage",
|
|
8384
|
+
"concentration-volume",
|
|
8385
|
+
"concentration-mass",
|
|
8386
|
+
"concentration-ppb",
|
|
8387
|
+
"volume",
|
|
8388
|
+
"duration",
|
|
8389
|
+
"duration-ms",
|
|
8390
|
+
"information",
|
|
8391
|
+
"sound-level",
|
|
8392
|
+
"signal-level",
|
|
8393
|
+
"colour-temperature",
|
|
8394
|
+
"angle",
|
|
8395
|
+
"bitrate",
|
|
8396
|
+
"rate",
|
|
8397
|
+
"mass",
|
|
8398
|
+
"index",
|
|
8399
|
+
"ratio",
|
|
8400
|
+
"count",
|
|
8401
|
+
"none",
|
|
8402
|
+
"device"
|
|
8403
|
+
];
|
|
8404
|
+
var ReadingQuantitySchema = _enum(READING_QUANTITIES);
|
|
8405
|
+
new Set(READING_QUANTITIES);
|
|
8406
|
+
/**
|
|
8407
|
+
* Stored unit symbol for a quantity. `none` means the number is dimensionless
|
|
8408
|
+
* (or an index / ratio / count). `device` means the cap has no single unit.
|
|
8409
|
+
*/
|
|
8410
|
+
var QUANTITY_BASE = {
|
|
8411
|
+
temperature: "°C",
|
|
8412
|
+
pressure: "hPa",
|
|
8413
|
+
speed: "m/s",
|
|
8414
|
+
precipitation: "mm",
|
|
8415
|
+
"precipitation-rate": "mm/h",
|
|
8416
|
+
length: "m",
|
|
8417
|
+
area: "m²",
|
|
8418
|
+
illuminance: "lx",
|
|
8419
|
+
irradiance: "W/m²",
|
|
8420
|
+
power: "W",
|
|
8421
|
+
energy: "kWh",
|
|
8422
|
+
voltage: "V",
|
|
8423
|
+
current: "A",
|
|
8424
|
+
"apparent-power": "VA",
|
|
8425
|
+
humidity: "%",
|
|
8426
|
+
percentage: "%",
|
|
8427
|
+
"concentration-volume": "ppm",
|
|
8428
|
+
"concentration-mass": "µg/m³",
|
|
8429
|
+
"concentration-ppb": "ppb",
|
|
8430
|
+
volume: "L",
|
|
8431
|
+
duration: "s",
|
|
8432
|
+
"duration-ms": "ms",
|
|
8433
|
+
information: "B",
|
|
8434
|
+
"sound-level": "dBFS",
|
|
8435
|
+
"signal-level": "dBm",
|
|
8436
|
+
"colour-temperature": "mired",
|
|
8437
|
+
angle: "°",
|
|
8438
|
+
bitrate: "kbps",
|
|
8439
|
+
rate: "fps",
|
|
8440
|
+
mass: "kg",
|
|
8441
|
+
index: "none",
|
|
8442
|
+
ratio: "none",
|
|
8443
|
+
count: "none",
|
|
8444
|
+
none: "none",
|
|
8445
|
+
device: "device"
|
|
8446
|
+
};
|
|
8447
|
+
/** The stored unit, or `undefined` when the quantity has no unit symbol. */
|
|
8448
|
+
function baseUnitOf(quantity) {
|
|
8449
|
+
const symbol = QUANTITY_BASE[quantity];
|
|
8450
|
+
if (symbol === "none" || symbol === "device") return void 0;
|
|
8451
|
+
return symbol;
|
|
8452
|
+
}
|
|
8453
|
+
function readingMeta(quantity, extras) {
|
|
8454
|
+
return {
|
|
8455
|
+
quantity,
|
|
8456
|
+
...extras?.precision !== void 0 ? { precision: extras.precision } : {},
|
|
8457
|
+
...extras?.label !== void 0 ? { label: extras.label } : {}
|
|
8458
|
+
};
|
|
8459
|
+
}
|
|
8359
8460
|
/** Shared Zod schemas used across streaming capabilities. */
|
|
8360
8461
|
var CamProfileSchema = _enum([
|
|
8361
8462
|
"high",
|
|
@@ -8383,8 +8484,8 @@ var CamStreamKindSchema = _enum([
|
|
|
8383
8484
|
"derived"
|
|
8384
8485
|
]);
|
|
8385
8486
|
var CamStreamResolutionSchema = object({
|
|
8386
|
-
width: number().int().positive(),
|
|
8387
|
-
height: number().int().positive()
|
|
8487
|
+
width: number().int().positive().meta(readingMeta("none")),
|
|
8488
|
+
height: number().int().positive().meta(readingMeta("none"))
|
|
8388
8489
|
});
|
|
8389
8490
|
var CameraStreamSchema = object({
|
|
8390
8491
|
/** Stable, provider-assigned id unique within the (deviceId) scope. */
|
|
@@ -8898,6 +8999,9 @@ var CAP_NAMES = Object.freeze([
|
|
|
8898
8999
|
"filesystem-browse",
|
|
8899
9000
|
"flood",
|
|
8900
9001
|
"gas",
|
|
9002
|
+
"group-active",
|
|
9003
|
+
"group-commands",
|
|
9004
|
+
"group-status",
|
|
8901
9005
|
"heating-valve",
|
|
8902
9006
|
"humidifier",
|
|
8903
9007
|
"humidity-sensor",
|
|
@@ -8918,6 +9022,7 @@ var CAP_NAMES = Object.freeze([
|
|
|
8918
9022
|
"login-method",
|
|
8919
9023
|
"media-player",
|
|
8920
9024
|
"mesh-network",
|
|
9025
|
+
"meter",
|
|
8921
9026
|
"metrics-provider",
|
|
8922
9027
|
"model-convert",
|
|
8923
9028
|
"model-distributor",
|
|
@@ -9027,14 +9132,6 @@ Object.freeze({
|
|
|
9027
9132
|
{
|
|
9028
9133
|
"path": "aqi",
|
|
9029
9134
|
"valueType": "number"
|
|
9030
|
-
},
|
|
9031
|
-
{
|
|
9032
|
-
"path": "unit",
|
|
9033
|
-
"valueType": "string"
|
|
9034
|
-
},
|
|
9035
|
-
{
|
|
9036
|
-
"path": "precision",
|
|
9037
|
-
"valueType": "number"
|
|
9038
9135
|
}
|
|
9039
9136
|
],
|
|
9040
9137
|
"alarm-panel": [
|
|
@@ -9070,20 +9167,10 @@ Object.freeze({
|
|
|
9070
9167
|
"valueType": "boolean"
|
|
9071
9168
|
}
|
|
9072
9169
|
],
|
|
9073
|
-
"ambient-light-sensor": [
|
|
9074
|
-
|
|
9075
|
-
|
|
9076
|
-
|
|
9077
|
-
},
|
|
9078
|
-
{
|
|
9079
|
-
"path": "unit",
|
|
9080
|
-
"valueType": "string"
|
|
9081
|
-
},
|
|
9082
|
-
{
|
|
9083
|
-
"path": "precision",
|
|
9084
|
-
"valueType": "number"
|
|
9085
|
-
}
|
|
9086
|
-
],
|
|
9170
|
+
"ambient-light-sensor": [{
|
|
9171
|
+
"path": "lux",
|
|
9172
|
+
"valueType": "number"
|
|
9173
|
+
}],
|
|
9087
9174
|
"audio-metrics": [
|
|
9088
9175
|
{
|
|
9089
9176
|
"path": "ts",
|
|
@@ -9163,6 +9250,10 @@ Object.freeze({
|
|
|
9163
9250
|
"path": "lastUpdated",
|
|
9164
9251
|
"valueType": "number"
|
|
9165
9252
|
},
|
|
9253
|
+
{
|
|
9254
|
+
"path": "volts",
|
|
9255
|
+
"valueType": "number"
|
|
9256
|
+
},
|
|
9166
9257
|
{
|
|
9167
9258
|
"path": "lastContactAt",
|
|
9168
9259
|
"valueType": "number"
|
|
@@ -9405,10 +9496,6 @@ Object.freeze({
|
|
|
9405
9496
|
"datetime"
|
|
9406
9497
|
]
|
|
9407
9498
|
},
|
|
9408
|
-
{
|
|
9409
|
-
"path": "unit",
|
|
9410
|
-
"valueType": "string"
|
|
9411
|
-
},
|
|
9412
9499
|
{
|
|
9413
9500
|
"path": "min",
|
|
9414
9501
|
"valueType": "number"
|
|
@@ -9420,19 +9507,6 @@ Object.freeze({
|
|
|
9420
9507
|
{
|
|
9421
9508
|
"path": "step",
|
|
9422
9509
|
"valueType": "number"
|
|
9423
|
-
},
|
|
9424
|
-
{
|
|
9425
|
-
"path": "precision",
|
|
9426
|
-
"valueType": "number"
|
|
9427
|
-
},
|
|
9428
|
-
{
|
|
9429
|
-
"path": "format",
|
|
9430
|
-
"valueType": "enum",
|
|
9431
|
-
"enumValues": [
|
|
9432
|
-
"date",
|
|
9433
|
-
"time",
|
|
9434
|
-
"datetime"
|
|
9435
|
-
]
|
|
9436
9510
|
}
|
|
9437
9511
|
],
|
|
9438
9512
|
"cover": [
|
|
@@ -9673,13 +9747,8 @@ Object.freeze({
|
|
|
9673
9747
|
"path": "value",
|
|
9674
9748
|
"valueType": "string"
|
|
9675
9749
|
}, {
|
|
9676
|
-
"path": "
|
|
9677
|
-
"valueType": "
|
|
9678
|
-
"enumValues": [
|
|
9679
|
-
"date",
|
|
9680
|
-
"time",
|
|
9681
|
-
"datetime"
|
|
9682
|
-
]
|
|
9750
|
+
"path": "timestamp",
|
|
9751
|
+
"valueType": "boolean"
|
|
9683
9752
|
}],
|
|
9684
9753
|
"event-emitter": [
|
|
9685
9754
|
{
|
|
@@ -9752,6 +9821,24 @@ Object.freeze({
|
|
|
9752
9821
|
"path": "detected",
|
|
9753
9822
|
"valueType": "boolean"
|
|
9754
9823
|
}],
|
|
9824
|
+
"group-active": [{
|
|
9825
|
+
"path": "active",
|
|
9826
|
+
"valueType": "boolean"
|
|
9827
|
+
}],
|
|
9828
|
+
"group-status": [
|
|
9829
|
+
{
|
|
9830
|
+
"path": "included",
|
|
9831
|
+
"valueType": "number"
|
|
9832
|
+
},
|
|
9833
|
+
{
|
|
9834
|
+
"path": "excluded",
|
|
9835
|
+
"valueType": "number"
|
|
9836
|
+
},
|
|
9837
|
+
{
|
|
9838
|
+
"path": "total",
|
|
9839
|
+
"valueType": "number"
|
|
9840
|
+
}
|
|
9841
|
+
],
|
|
9755
9842
|
"heating-valve": [{
|
|
9756
9843
|
"path": "position",
|
|
9757
9844
|
"valueType": "number"
|
|
@@ -9786,20 +9873,10 @@ Object.freeze({
|
|
|
9786
9873
|
"valueType": "number"
|
|
9787
9874
|
}
|
|
9788
9875
|
],
|
|
9789
|
-
"humidity-sensor": [
|
|
9790
|
-
|
|
9791
|
-
|
|
9792
|
-
|
|
9793
|
-
},
|
|
9794
|
-
{
|
|
9795
|
-
"path": "unit",
|
|
9796
|
-
"valueType": "string"
|
|
9797
|
-
},
|
|
9798
|
-
{
|
|
9799
|
-
"path": "precision",
|
|
9800
|
-
"valueType": "number"
|
|
9801
|
-
}
|
|
9802
|
-
],
|
|
9876
|
+
"humidity-sensor": [{
|
|
9877
|
+
"path": "percent",
|
|
9878
|
+
"valueType": "number"
|
|
9879
|
+
}],
|
|
9803
9880
|
"image": [{
|
|
9804
9881
|
"path": "url",
|
|
9805
9882
|
"valueType": "string"
|
|
@@ -10007,6 +10084,10 @@ Object.freeze({
|
|
|
10007
10084
|
]
|
|
10008
10085
|
}
|
|
10009
10086
|
],
|
|
10087
|
+
"meter": [{
|
|
10088
|
+
"path": "value",
|
|
10089
|
+
"valueType": "number"
|
|
10090
|
+
}],
|
|
10010
10091
|
"motion": [
|
|
10011
10092
|
{
|
|
10012
10093
|
"path": "detected",
|
|
@@ -10138,20 +10219,10 @@ Object.freeze({
|
|
|
10138
10219
|
"valueType": "boolean"
|
|
10139
10220
|
}
|
|
10140
10221
|
],
|
|
10141
|
-
"numeric-sensor": [
|
|
10142
|
-
|
|
10143
|
-
|
|
10144
|
-
|
|
10145
|
-
},
|
|
10146
|
-
{
|
|
10147
|
-
"path": "unit",
|
|
10148
|
-
"valueType": "string"
|
|
10149
|
-
},
|
|
10150
|
-
{
|
|
10151
|
-
"path": "precision",
|
|
10152
|
-
"valueType": "number"
|
|
10153
|
-
}
|
|
10154
|
-
],
|
|
10222
|
+
"numeric-sensor": [{
|
|
10223
|
+
"path": "value",
|
|
10224
|
+
"valueType": "number"
|
|
10225
|
+
}],
|
|
10155
10226
|
"pet-feeder": [
|
|
10156
10227
|
{
|
|
10157
10228
|
"path": "foodLevel",
|
|
@@ -10243,14 +10314,6 @@ Object.freeze({
|
|
|
10243
10314
|
{
|
|
10244
10315
|
"path": "powerFactor",
|
|
10245
10316
|
"valueType": "number"
|
|
10246
|
-
},
|
|
10247
|
-
{
|
|
10248
|
-
"path": "unit",
|
|
10249
|
-
"valueType": "string"
|
|
10250
|
-
},
|
|
10251
|
-
{
|
|
10252
|
-
"path": "precision",
|
|
10253
|
-
"valueType": "number"
|
|
10254
10317
|
}
|
|
10255
10318
|
],
|
|
10256
10319
|
"presence": [
|
|
@@ -10279,20 +10342,10 @@ Object.freeze({
|
|
|
10279
10342
|
"valueType": "number"
|
|
10280
10343
|
}
|
|
10281
10344
|
],
|
|
10282
|
-
"pressure-sensor": [
|
|
10283
|
-
|
|
10284
|
-
|
|
10285
|
-
|
|
10286
|
-
},
|
|
10287
|
-
{
|
|
10288
|
-
"path": "unit",
|
|
10289
|
-
"valueType": "string"
|
|
10290
|
-
},
|
|
10291
|
-
{
|
|
10292
|
-
"path": "precision",
|
|
10293
|
-
"valueType": "number"
|
|
10294
|
-
}
|
|
10295
|
-
],
|
|
10345
|
+
"pressure-sensor": [{
|
|
10346
|
+
"path": "hpa",
|
|
10347
|
+
"valueType": "number"
|
|
10348
|
+
}],
|
|
10296
10349
|
"privacy-mask": [{
|
|
10297
10350
|
"path": "enabled",
|
|
10298
10351
|
"valueType": "boolean"
|
|
@@ -10603,20 +10656,10 @@ Object.freeze({
|
|
|
10603
10656
|
"path": "tampered",
|
|
10604
10657
|
"valueType": "boolean"
|
|
10605
10658
|
}],
|
|
10606
|
-
"temperature-sensor": [
|
|
10607
|
-
|
|
10608
|
-
|
|
10609
|
-
|
|
10610
|
-
},
|
|
10611
|
-
{
|
|
10612
|
-
"path": "unit",
|
|
10613
|
-
"valueType": "string"
|
|
10614
|
-
},
|
|
10615
|
-
{
|
|
10616
|
-
"path": "precision",
|
|
10617
|
-
"valueType": "number"
|
|
10618
|
-
}
|
|
10619
|
-
],
|
|
10659
|
+
"temperature-sensor": [{
|
|
10660
|
+
"path": "celsius",
|
|
10661
|
+
"valueType": "number"
|
|
10662
|
+
}],
|
|
10620
10663
|
"update": [
|
|
10621
10664
|
{
|
|
10622
10665
|
"path": "currentVersion",
|
|
@@ -10727,10 +10770,6 @@ Object.freeze({
|
|
|
10727
10770
|
"path": "temperature",
|
|
10728
10771
|
"valueType": "number"
|
|
10729
10772
|
},
|
|
10730
|
-
{
|
|
10731
|
-
"path": "temperatureUnit",
|
|
10732
|
-
"valueType": "string"
|
|
10733
|
-
},
|
|
10734
10773
|
{
|
|
10735
10774
|
"path": "humidity",
|
|
10736
10775
|
"valueType": "number"
|
|
@@ -10739,18 +10778,10 @@ Object.freeze({
|
|
|
10739
10778
|
"path": "pressure",
|
|
10740
10779
|
"valueType": "number"
|
|
10741
10780
|
},
|
|
10742
|
-
{
|
|
10743
|
-
"path": "pressureUnit",
|
|
10744
|
-
"valueType": "string"
|
|
10745
|
-
},
|
|
10746
10781
|
{
|
|
10747
10782
|
"path": "windSpeed",
|
|
10748
10783
|
"valueType": "number"
|
|
10749
10784
|
},
|
|
10750
|
-
{
|
|
10751
|
-
"path": "windSpeedUnit",
|
|
10752
|
-
"valueType": "string"
|
|
10753
|
-
},
|
|
10754
10785
|
{
|
|
10755
10786
|
"path": "windBearing",
|
|
10756
10787
|
"valueType": "number"
|
|
@@ -10800,7 +10831,7 @@ object({
|
|
|
10800
10831
|
params: record(string(), union([string(), number()])).optional()
|
|
10801
10832
|
});
|
|
10802
10833
|
//#endregion
|
|
10803
|
-
//#region ../types/dist/err-msg-
|
|
10834
|
+
//#region ../types/dist/err-msg-DIorGYeC.mjs
|
|
10804
10835
|
var DeviceType = /* @__PURE__ */ function(DeviceType) {
|
|
10805
10836
|
DeviceType["Camera"] = "camera";
|
|
10806
10837
|
DeviceType["Hub"] = "hub";
|
|
@@ -10894,8 +10925,14 @@ var DeviceType = /* @__PURE__ */ function(DeviceType) {
|
|
|
10894
10925
|
DeviceType["PetFeeder"] = "pet-feeder";
|
|
10895
10926
|
/** Built-in dishwasher — program lifecycle, door / remote-start gates,
|
|
10896
10927
|
* salt and rinse-aid levels. Installed with the `dishwasher` cap.
|
|
10897
|
-
* Sources: native Bosch Home Connect, reusable by similar integrations.
|
|
10928
|
+
* Sources: native Bosch Home Connect, reusable by similar integrations.
|
|
10929
|
+
* A plug-built dishwasher carries running-state and power instead. */
|
|
10898
10930
|
DeviceType["Dishwasher"] = "dishwasher";
|
|
10931
|
+
/** Washing machine. A plug-built one is running while its power stays
|
|
10932
|
+
* above a threshold. No program cap — that surface is the dishwasher's. */
|
|
10933
|
+
DeviceType["Washer"] = "washer";
|
|
10934
|
+
/** Tumble dryer. Same plug-built running surface as {@link Washer}. */
|
|
10935
|
+
DeviceType["Dryer"] = "dryer";
|
|
10899
10936
|
return DeviceType;
|
|
10900
10937
|
}({});
|
|
10901
10938
|
var DeviceFeature = /* @__PURE__ */ function(DeviceFeature) {
|
|
@@ -11143,7 +11180,7 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
|
|
|
11143
11180
|
return DeviceRole;
|
|
11144
11181
|
}({});
|
|
11145
11182
|
//#endregion
|
|
11146
|
-
//#region ../types/dist/composition-
|
|
11183
|
+
//#region ../types/dist/composition-Bb8iwHEJ.mjs
|
|
11147
11184
|
/**
|
|
11148
11185
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
11149
11186
|
*
|
|
@@ -11458,6 +11495,13 @@ var table = {
|
|
|
11458
11495
|
apply: () => {
|
|
11459
11496
|
throw new ExpressionEvalError("latchedAt: stateful evaluation context is required");
|
|
11460
11497
|
}
|
|
11498
|
+
},
|
|
11499
|
+
schmitt: {
|
|
11500
|
+
minArgs: 3,
|
|
11501
|
+
maxArgs: 5,
|
|
11502
|
+
apply: () => {
|
|
11503
|
+
throw new ExpressionEvalError("schmitt: stateful evaluation context is required");
|
|
11504
|
+
}
|
|
11461
11505
|
}
|
|
11462
11506
|
};
|
|
11463
11507
|
Object.freeze(Object.assign(Object.create(null), table));
|
|
@@ -11898,15 +11942,232 @@ function validateExpressionSource(src) {
|
|
|
11898
11942
|
}
|
|
11899
11943
|
return null;
|
|
11900
11944
|
}
|
|
11901
|
-
/**
|
|
11902
|
-
|
|
11903
|
-
|
|
11904
|
-
|
|
11945
|
+
/**
|
|
11946
|
+
* One power reading becomes a washer, dryer or dishwasher (D944 helper).
|
|
11947
|
+
*
|
|
11948
|
+
* Standby of the control board is under 5 W; a motor or a heater is far
|
|
11949
|
+
* above that, so 5 W is the line. A door lock or a short pump spike is not
|
|
11950
|
+
* a cycle, so running starts only after 30 s above the line.
|
|
11951
|
+
*
|
|
11952
|
+
* A wash, dry or dishwasher pause (soak, heat-wait, heater off between
|
|
11953
|
+
* bursts) lasts several minutes. Ending the cycle on the first dip would
|
|
11954
|
+
* report "finished" in the middle of the program, so the stop dwell is
|
|
11955
|
+
* 10 minutes on every type. The number is stored per type so one machine
|
|
11956
|
+
* can move later without moving the others.
|
|
11957
|
+
*/
|
|
11958
|
+
var APPLIANCE_TEMPLATE_ID = "appliance";
|
|
11959
|
+
var APPLIANCE_KINDS = [
|
|
11960
|
+
"washer",
|
|
11961
|
+
"dryer",
|
|
11962
|
+
"dishwasher"
|
|
11963
|
+
];
|
|
11964
|
+
DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher;
|
|
11965
|
+
/**
|
|
11966
|
+
* Statistics and integrals over a history read (D944).
|
|
11967
|
+
*
|
|
11968
|
+
* Pure: the same points always give the same answer, so a restart recomputes
|
|
11969
|
+
* rather than trusting a buffer. A gauge mean is time-weighted (value × ms),
|
|
11970
|
+
* never the mean of the samples. A hole with no held value is not integrated
|
|
11971
|
+
* as zero. A truncated read is not published.
|
|
11972
|
+
*/
|
|
11973
|
+
var STATISTIC_STATS = [
|
|
11974
|
+
"min",
|
|
11975
|
+
"max",
|
|
11976
|
+
"mean",
|
|
11977
|
+
"sum",
|
|
11978
|
+
"count",
|
|
11979
|
+
"change"
|
|
11980
|
+
];
|
|
11981
|
+
/**
|
|
11982
|
+
* The range a statistics or integral helper asks history for (D944).
|
|
11983
|
+
*
|
|
11984
|
+
* Calendar edges are the hub's timezone, never UTC midnight: a day is 23, 24
|
|
11985
|
+
* or 25 hours across a DST change. A tier is eligible only when its retention
|
|
11986
|
+
* is strictly longer than the longest that range can be. Forever qualifies.
|
|
11987
|
+
* Equal to a tier's retention is a refusal, not a short answer.
|
|
11988
|
+
*/
|
|
11989
|
+
var MINUTE_MS = 6e4;
|
|
11990
|
+
var HOUR_MS = 60 * MINUTE_MS;
|
|
11991
|
+
var DAY_MS = 24 * HOUR_MS;
|
|
11992
|
+
var ROLLING_SPANS = [
|
|
11993
|
+
"1h",
|
|
11994
|
+
"24h",
|
|
11995
|
+
"2d",
|
|
11996
|
+
"7d",
|
|
11997
|
+
"30d",
|
|
11998
|
+
"custom"
|
|
11999
|
+
];
|
|
12000
|
+
var CALENDAR_PERIODS = [
|
|
12001
|
+
"today",
|
|
12002
|
+
"yesterday",
|
|
12003
|
+
"this-week",
|
|
12004
|
+
"this-month"
|
|
12005
|
+
];
|
|
12006
|
+
var RESET_PERIODS = [
|
|
12007
|
+
"never",
|
|
12008
|
+
"daily",
|
|
12009
|
+
"weekly",
|
|
12010
|
+
"monthly"
|
|
12011
|
+
];
|
|
12012
|
+
5 * MINUTE_MS;
|
|
12013
|
+
24 * HOUR_MS, 2 * DAY_MS, 7 * DAY_MS, 30 * DAY_MS;
|
|
12014
|
+
7 * DAY_MS, 30 * DAY_MS, 365 * DAY_MS;
|
|
12015
|
+
var rollingWindowObject = object({
|
|
12016
|
+
kind: literal("rolling"),
|
|
12017
|
+
span: _enum(ROLLING_SPANS),
|
|
12018
|
+
customMinutes: number().int().min(5).optional()
|
|
12019
|
+
}).check((payload) => {
|
|
12020
|
+
if (payload.value.span === "custom" && payload.value.customMinutes === void 0) payload.issues.push({
|
|
12021
|
+
code: "custom",
|
|
12022
|
+
message: "a custom range needs a duration in minutes",
|
|
12023
|
+
path: ["customMinutes"],
|
|
12024
|
+
input: payload.value
|
|
12025
|
+
});
|
|
12026
|
+
if (payload.value.span !== "custom" && payload.value.customMinutes !== void 0) payload.issues.push({
|
|
12027
|
+
code: "custom",
|
|
12028
|
+
message: "only a custom range carries a duration",
|
|
12029
|
+
path: ["customMinutes"],
|
|
12030
|
+
input: payload.value
|
|
12031
|
+
});
|
|
12032
|
+
});
|
|
12033
|
+
var RollingWindowSchema = rollingWindowObject;
|
|
12034
|
+
var StatisticWindowSchema = discriminatedUnion("kind", [rollingWindowObject, object({
|
|
12035
|
+
kind: literal("calendar"),
|
|
12036
|
+
period: _enum(CALENDAR_PERIODS)
|
|
12037
|
+
})]);
|
|
12038
|
+
/**
|
|
12039
|
+
* A composition source identity: `(addonId, stableId)`, never a numeric device
|
|
12040
|
+
* id. Split out so helper schemas can name it without a cycle through
|
|
12041
|
+
* `composition.ts` (D659).
|
|
12042
|
+
*/
|
|
11905
12043
|
var CompositionSourceRefSchema = object({
|
|
11906
12044
|
/** The owning addon; `stableId` is unique only within it. */
|
|
11907
12045
|
addonId: string().min(1),
|
|
11908
12046
|
stableId: string().min(1)
|
|
11909
12047
|
});
|
|
12048
|
+
var GROUP_TEMPLATE_IDS = [
|
|
12049
|
+
"temperature",
|
|
12050
|
+
"humidity",
|
|
12051
|
+
"pressure",
|
|
12052
|
+
"illuminance",
|
|
12053
|
+
"power",
|
|
12054
|
+
"energy",
|
|
12055
|
+
"battery",
|
|
12056
|
+
"numeric",
|
|
12057
|
+
"motion",
|
|
12058
|
+
"contact",
|
|
12059
|
+
"leak",
|
|
12060
|
+
"smoke",
|
|
12061
|
+
"occupancy",
|
|
12062
|
+
"binary",
|
|
12063
|
+
"switch",
|
|
12064
|
+
"light",
|
|
12065
|
+
"fan",
|
|
12066
|
+
"cover",
|
|
12067
|
+
"valve",
|
|
12068
|
+
"lock",
|
|
12069
|
+
"media-player",
|
|
12070
|
+
"climate"
|
|
12071
|
+
];
|
|
12072
|
+
var NUMERIC_AGGREGATES = [
|
|
12073
|
+
"mean",
|
|
12074
|
+
"median",
|
|
12075
|
+
"min",
|
|
12076
|
+
"max",
|
|
12077
|
+
"sum"
|
|
12078
|
+
];
|
|
12079
|
+
var BINARY_AGGREGATES = ["any", "all"];
|
|
12080
|
+
/** How an actuator group decides it is on. Unknown members never count as off. */
|
|
12081
|
+
var ACTIVE_CRITERIA = ["at-least-one", "all"];
|
|
12082
|
+
var AGGREGATE_REDUCERS = [
|
|
12083
|
+
"mean",
|
|
12084
|
+
"median",
|
|
12085
|
+
"min",
|
|
12086
|
+
"max",
|
|
12087
|
+
"sum",
|
|
12088
|
+
"any",
|
|
12089
|
+
"all"
|
|
12090
|
+
];
|
|
12091
|
+
var GroupTemplateIdSchema = _enum(GROUP_TEMPLATE_IDS);
|
|
12092
|
+
var AggregateReducerSchema = _enum(AGGREGATE_REDUCERS);
|
|
12093
|
+
var ActiveCriterionSchema = _enum(ACTIVE_CRITERIA);
|
|
12094
|
+
/** One member. The field is stored so occupancy can name motion or binary. */
|
|
12095
|
+
var HelperMemberSchema = object({
|
|
12096
|
+
source: CompositionSourceRefSchema,
|
|
12097
|
+
cap: string().min(1),
|
|
12098
|
+
fieldPath: string().min(1)
|
|
12099
|
+
});
|
|
12100
|
+
var HelperSpecSchema = discriminatedUnion("kind", [
|
|
12101
|
+
object({
|
|
12102
|
+
kind: literal("group"),
|
|
12103
|
+
templateId: GroupTemplateIdSchema,
|
|
12104
|
+
aggregate: AggregateReducerSchema,
|
|
12105
|
+
members: array(HelperMemberSchema).min(1).max(64),
|
|
12106
|
+
/** Actuator groups only. Readings leave this unset. */
|
|
12107
|
+
active: ActiveCriterionSchema.optional()
|
|
12108
|
+
}),
|
|
12109
|
+
object({
|
|
12110
|
+
kind: literal("appliance"),
|
|
12111
|
+
templateId: literal(APPLIANCE_TEMPLATE_ID),
|
|
12112
|
+
appliance: _enum(APPLIANCE_KINDS),
|
|
12113
|
+
thresholdWatts: number().positive(),
|
|
12114
|
+
startDwellMs: number().int().nonnegative(),
|
|
12115
|
+
stopDwellMs: number().int().nonnegative(),
|
|
12116
|
+
member: HelperMemberSchema
|
|
12117
|
+
}),
|
|
12118
|
+
object({
|
|
12119
|
+
kind: literal("statistic"),
|
|
12120
|
+
stat: _enum(STATISTIC_STATS),
|
|
12121
|
+
window: StatisticWindowSchema,
|
|
12122
|
+
source: HelperMemberSchema
|
|
12123
|
+
}),
|
|
12124
|
+
object({
|
|
12125
|
+
kind: literal("integral"),
|
|
12126
|
+
reset: _enum(RESET_PERIODS),
|
|
12127
|
+
output: _enum(["energy", "meter"]),
|
|
12128
|
+
source: HelperMemberSchema
|
|
12129
|
+
}),
|
|
12130
|
+
object({
|
|
12131
|
+
kind: literal("threshold"),
|
|
12132
|
+
source: HelperMemberSchema,
|
|
12133
|
+
high: number(),
|
|
12134
|
+
low: number(),
|
|
12135
|
+
onForMs: number().int().nonnegative(),
|
|
12136
|
+
offForMs: number().int().nonnegative()
|
|
12137
|
+
}),
|
|
12138
|
+
object({
|
|
12139
|
+
kind: literal("arithmetic"),
|
|
12140
|
+
op: _enum([
|
|
12141
|
+
"sum",
|
|
12142
|
+
"difference",
|
|
12143
|
+
"ratio"
|
|
12144
|
+
]),
|
|
12145
|
+
inputs: array(HelperMemberSchema).min(2).max(64)
|
|
12146
|
+
}),
|
|
12147
|
+
object({
|
|
12148
|
+
kind: literal("expression"),
|
|
12149
|
+
expr: string().min(1),
|
|
12150
|
+
inputs: array(object({
|
|
12151
|
+
name: string().min(1),
|
|
12152
|
+
member: HelperMemberSchema
|
|
12153
|
+
})).min(1).max(64),
|
|
12154
|
+
output: _enum(["number", "boolean"])
|
|
12155
|
+
}),
|
|
12156
|
+
object({
|
|
12157
|
+
kind: literal("derivative"),
|
|
12158
|
+
window: RollingWindowSchema,
|
|
12159
|
+
per: _enum([
|
|
12160
|
+
"second",
|
|
12161
|
+
"minute",
|
|
12162
|
+
"hour"
|
|
12163
|
+
]),
|
|
12164
|
+
source: HelperMemberSchema
|
|
12165
|
+
})
|
|
12166
|
+
]);
|
|
12167
|
+
/** A composed device's stableId is this prefix plus the block id. */
|
|
12168
|
+
var COMPOSED_DEVICE_STABLE_ID_PREFIX = "composed-";
|
|
12169
|
+
/** Longest snippet a `code` source may carry (slice 4). */
|
|
12170
|
+
var MAX_COMPOSITION_CODE_LENGTH = 2e4;
|
|
11910
12171
|
/** One field of one capability of one source device. */
|
|
11911
12172
|
var CompositionFieldReadSchema = object({
|
|
11912
12173
|
source: CompositionSourceRefSchema,
|
|
@@ -11950,7 +12211,59 @@ var CompositionCodeSourceSchema = object({
|
|
|
11950
12211
|
var CompositionFieldSourceSchema = discriminatedUnion("kind", [
|
|
11951
12212
|
CompositionFromSourceSchema,
|
|
11952
12213
|
CompositionExpressionSourceSchema,
|
|
11953
|
-
CompositionCodeSourceSchema
|
|
12214
|
+
CompositionCodeSourceSchema,
|
|
12215
|
+
object({
|
|
12216
|
+
kind: literal("aggregate"),
|
|
12217
|
+
reducer: _enum([
|
|
12218
|
+
"mean",
|
|
12219
|
+
"median",
|
|
12220
|
+
"min",
|
|
12221
|
+
"max",
|
|
12222
|
+
"sum",
|
|
12223
|
+
"any",
|
|
12224
|
+
"all"
|
|
12225
|
+
]),
|
|
12226
|
+
reads: array(CompositionFieldReadSchema).min(1).max(64),
|
|
12227
|
+
/**
|
|
12228
|
+
* Set when the reads are an enum state, not a yes/no: the listed states
|
|
12229
|
+
* count as active (a cover is `open`). A state outside the list is inactive;
|
|
12230
|
+
* a read that is not a state at all is left out. Only `any` / `all` use it.
|
|
12231
|
+
*/
|
|
12232
|
+
activeWhen: array(string().min(1)).min(1).optional(),
|
|
12233
|
+
/** `value` is the reading; the others are the member counts. */
|
|
12234
|
+
publish: _enum([
|
|
12235
|
+
"value",
|
|
12236
|
+
"included",
|
|
12237
|
+
"excluded",
|
|
12238
|
+
"total"
|
|
12239
|
+
]),
|
|
12240
|
+
/** What a `value` publish does when nobody is included. Counts ignore this. */
|
|
12241
|
+
empty: _enum([
|
|
12242
|
+
"null",
|
|
12243
|
+
"omit",
|
|
12244
|
+
"offline"
|
|
12245
|
+
])
|
|
12246
|
+
}),
|
|
12247
|
+
object({
|
|
12248
|
+
kind: literal("series"),
|
|
12249
|
+
read: CompositionFieldReadSchema,
|
|
12250
|
+
/** `value` is the statistic or the integral. The others are the gap counts. */
|
|
12251
|
+
publish: _enum([
|
|
12252
|
+
"value",
|
|
12253
|
+
"included",
|
|
12254
|
+
"excluded",
|
|
12255
|
+
"total"
|
|
12256
|
+
]),
|
|
12257
|
+
/**
|
|
12258
|
+
* What an unanswered `value` does. Counts ignore this. `offline` leaves the
|
|
12259
|
+
* device unseeded until history answers, so a restart cannot publish 0.
|
|
12260
|
+
*/
|
|
12261
|
+
empty: _enum([
|
|
12262
|
+
"null",
|
|
12263
|
+
"omit",
|
|
12264
|
+
"offline"
|
|
12265
|
+
])
|
|
12266
|
+
})
|
|
11954
12267
|
]);
|
|
11955
12268
|
var CompositionCommandTargetSchema = discriminatedUnion("kind", [object({
|
|
11956
12269
|
kind: literal("forward"),
|
|
@@ -11996,7 +12309,13 @@ var CompositionSchema = object({
|
|
|
11996
12309
|
kind: literal("existing"),
|
|
11997
12310
|
device: CompositionSourceRefSchema
|
|
11998
12311
|
})]),
|
|
11999
|
-
features: array(CompositionFeatureSchema).min(1).max(16)
|
|
12312
|
+
features: array(CompositionFeatureSchema).min(1).max(16),
|
|
12313
|
+
/**
|
|
12314
|
+
* Present when the block is a helper template. Absent on a free
|
|
12315
|
+
* composition (the room example, device 4603). The editor reads this,
|
|
12316
|
+
* never the compiled features.
|
|
12317
|
+
*/
|
|
12318
|
+
helper: HelperSpecSchema.optional()
|
|
12000
12319
|
}).superRefine((composition, ctx) => {
|
|
12001
12320
|
const seen = /* @__PURE__ */ new Set();
|
|
12002
12321
|
composition.features.forEach((feature, index) => {
|
|
@@ -17103,7 +17422,22 @@ var BrokerProviderInfoSchema = object({
|
|
|
17103
17422
|
*/
|
|
17104
17423
|
interactiveConnectPath: string().min(1).optional(),
|
|
17105
17424
|
/** Relative hub path to disconnect the linked account (same popup pattern). */
|
|
17106
|
-
interactiveDisconnectPath: string().min(1).optional()
|
|
17425
|
+
interactiveDisconnectPath: string().min(1).optional(),
|
|
17426
|
+
/**
|
|
17427
|
+
* The kind signs in through a server-held interactive session instead of
|
|
17428
|
+
* (or before) typed credentials. `basePath` is a hub-relative route set
|
|
17429
|
+
* served by the owning addon (`/addon/<id>/...`) speaking the sign-in
|
|
17430
|
+
* contract: `POST {basePath}/start` (body: the form's settings) answers
|
|
17431
|
+
* `{ sessionId, loginUrl }`; `GET {basePath}/status?sessionId=` answers
|
|
17432
|
+
* `{ phase: 'starting' | 'awaiting-login' | 'captured' | 'error' |
|
|
17433
|
+
* 'cancelled', loginUrl, error }`; `POST {basePath}/commit`
|
|
17434
|
+
* (`{ sessionId, name, brokerId? }`) stores the credentials on a new or
|
|
17435
|
+
* existing broker and answers `{ brokerId }`; `POST {basePath}/cancel`
|
|
17436
|
+
* (`{ sessionId }`) drops the session. The dialog that edits a broker
|
|
17437
|
+
* offers it as the default path; the fields the session fills are
|
|
17438
|
+
* marked `filledBySignIn` in the kind's settings schema.
|
|
17439
|
+
*/
|
|
17440
|
+
signIn: object({ basePath: string().min(1) }).optional()
|
|
17107
17441
|
}))
|
|
17108
17442
|
});
|
|
17109
17443
|
var ListInputSchema = object({
|
|
@@ -18147,7 +18481,12 @@ var CompositionProblemSchema = object({
|
|
|
18147
18481
|
"item-field-reserved",
|
|
18148
18482
|
"target-missing",
|
|
18149
18483
|
"target-unreadable",
|
|
18150
|
-
"not-replaceable"
|
|
18484
|
+
"not-replaceable",
|
|
18485
|
+
"native-capability-replace",
|
|
18486
|
+
"mixed-quantity",
|
|
18487
|
+
"helper-mismatch",
|
|
18488
|
+
"member-constraint",
|
|
18489
|
+
"retention"
|
|
18151
18490
|
]),
|
|
18152
18491
|
path: string(),
|
|
18153
18492
|
message: string()
|
|
@@ -18168,7 +18507,8 @@ var CompositionUnavailableModeSchema = _enum([
|
|
|
18168
18507
|
"null",
|
|
18169
18508
|
"offline",
|
|
18170
18509
|
"unknown",
|
|
18171
|
-
"release"
|
|
18510
|
+
"release",
|
|
18511
|
+
"omit"
|
|
18172
18512
|
]);
|
|
18173
18513
|
/**
|
|
18174
18514
|
* `derived` reads a source · `clock` reads only `now`, recomputed when a sibling
|
|
@@ -18205,9 +18545,11 @@ var CompositionFieldPlanSchema = object({
|
|
|
18205
18545
|
reads: array(CompositionFieldReadSchema)
|
|
18206
18546
|
});
|
|
18207
18547
|
/**
|
|
18208
|
-
* What a feature does to its target (D663): `new` builds a capability on a
|
|
18209
|
-
* device; on an existing device it `add`s a capability the device lacks
|
|
18210
|
-
*
|
|
18548
|
+
* What a feature does to its target (D663, D944): `new` builds a capability on a
|
|
18549
|
+
* new device; on an existing device it `add`s a capability the device lacks.
|
|
18550
|
+
* Replacing a capability the device already serves is refused
|
|
18551
|
+
* (`native-capability-replace`), not planned. `replace` remains on the claim
|
|
18552
|
+
* wire for a claim the hub already holds.
|
|
18211
18553
|
*/
|
|
18212
18554
|
var CompositionFeatureModeSchema = _enum([
|
|
18213
18555
|
"new",
|
|
@@ -18378,8 +18720,392 @@ Object.freeze({
|
|
|
18378
18720
|
latchedAt: {
|
|
18379
18721
|
kind: "fixed",
|
|
18380
18722
|
result: ["number", "null"]
|
|
18723
|
+
},
|
|
18724
|
+
schmitt: {
|
|
18725
|
+
kind: "fixed",
|
|
18726
|
+
result: ["boolean", "null"]
|
|
18381
18727
|
}
|
|
18382
18728
|
});
|
|
18729
|
+
/**
|
|
18730
|
+
* One catalog row per base reading a group helper can build (D944 §3).
|
|
18731
|
+
* Data, not a form default written into the block.
|
|
18732
|
+
*/
|
|
18733
|
+
var NOW$2 = {
|
|
18734
|
+
fieldPath: "lastFetchedAt",
|
|
18735
|
+
expr: "now"
|
|
18736
|
+
};
|
|
18737
|
+
var CHANGED = {
|
|
18738
|
+
fieldPath: "lastChangedAt",
|
|
18739
|
+
expr: "now"
|
|
18740
|
+
};
|
|
18741
|
+
function numeric(input) {
|
|
18742
|
+
return {
|
|
18743
|
+
...input,
|
|
18744
|
+
family: "numeric",
|
|
18745
|
+
deviceType: DeviceType.Sensor,
|
|
18746
|
+
memberDeviceType: DeviceType.Sensor,
|
|
18747
|
+
memberDeviceTypes: [DeviceType.Sensor],
|
|
18748
|
+
activeWhen: void 0,
|
|
18749
|
+
commandCaps: [],
|
|
18750
|
+
baseUnit: baseUnitOf(input.quantity),
|
|
18751
|
+
aggregates: NUMERIC_AGGREGATES,
|
|
18752
|
+
accept: [{
|
|
18753
|
+
cap: input.outputCap,
|
|
18754
|
+
fieldPath: input.outputField
|
|
18755
|
+
}]
|
|
18756
|
+
};
|
|
18757
|
+
}
|
|
18758
|
+
function binary(input) {
|
|
18759
|
+
return {
|
|
18760
|
+
...input,
|
|
18761
|
+
family: "binary",
|
|
18762
|
+
deviceType: DeviceType.Sensor,
|
|
18763
|
+
memberDeviceType: DeviceType.Sensor,
|
|
18764
|
+
memberDeviceTypes: [DeviceType.Sensor],
|
|
18765
|
+
activeWhen: void 0,
|
|
18766
|
+
commandCaps: [],
|
|
18767
|
+
quantity: "none",
|
|
18768
|
+
baseUnit: void 0,
|
|
18769
|
+
aggregates: BINARY_AGGREGATES,
|
|
18770
|
+
empty: "offline"
|
|
18771
|
+
};
|
|
18772
|
+
}
|
|
18773
|
+
var GROUP_TEMPLATES = [
|
|
18774
|
+
numeric({
|
|
18775
|
+
id: "temperature",
|
|
18776
|
+
summary: "Mean, median, min, max or sum of temperatures. Offline and unknown members are left out, never read as 0 °C.",
|
|
18777
|
+
role: DeviceRole.TemperatureSensor,
|
|
18778
|
+
outputCap: "temperature-sensor",
|
|
18779
|
+
outputField: "celsius",
|
|
18780
|
+
quantity: "temperature",
|
|
18781
|
+
defaultAggregate: "mean",
|
|
18782
|
+
empty: "null",
|
|
18783
|
+
companions: [NOW$2]
|
|
18784
|
+
}),
|
|
18785
|
+
numeric({
|
|
18786
|
+
id: "humidity",
|
|
18787
|
+
summary: "Humidity in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
18788
|
+
role: DeviceRole.HumiditySensor,
|
|
18789
|
+
outputCap: "humidity-sensor",
|
|
18790
|
+
outputField: "percent",
|
|
18791
|
+
quantity: "humidity",
|
|
18792
|
+
defaultAggregate: "mean",
|
|
18793
|
+
empty: "null",
|
|
18794
|
+
companions: [NOW$2]
|
|
18795
|
+
}),
|
|
18796
|
+
numeric({
|
|
18797
|
+
id: "pressure",
|
|
18798
|
+
summary: "Pressure in hectopascals. Offline and unknown members are left out, never read as 0 hPa.",
|
|
18799
|
+
role: DeviceRole.PressureSensor,
|
|
18800
|
+
outputCap: "pressure-sensor",
|
|
18801
|
+
outputField: "hpa",
|
|
18802
|
+
quantity: "pressure",
|
|
18803
|
+
defaultAggregate: "mean",
|
|
18804
|
+
empty: "null",
|
|
18805
|
+
companions: [NOW$2]
|
|
18806
|
+
}),
|
|
18807
|
+
numeric({
|
|
18808
|
+
id: "illuminance",
|
|
18809
|
+
summary: "Illuminance in lux. Offline and unknown members are left out, never read as 0 lx.",
|
|
18810
|
+
role: DeviceRole.AmbientLightSensor,
|
|
18811
|
+
outputCap: "ambient-light-sensor",
|
|
18812
|
+
outputField: "lux",
|
|
18813
|
+
quantity: "illuminance",
|
|
18814
|
+
defaultAggregate: "mean",
|
|
18815
|
+
empty: "null",
|
|
18816
|
+
companions: [NOW$2]
|
|
18817
|
+
}),
|
|
18818
|
+
numeric({
|
|
18819
|
+
id: "power",
|
|
18820
|
+
summary: "Power in watts, summed by default. Nobody reporting omits the key rather than writing 0 W.",
|
|
18821
|
+
role: DeviceRole.PowerSensor,
|
|
18822
|
+
outputCap: "power-meter",
|
|
18823
|
+
outputField: "watts",
|
|
18824
|
+
quantity: "power",
|
|
18825
|
+
defaultAggregate: "sum",
|
|
18826
|
+
empty: "omit",
|
|
18827
|
+
companions: [NOW$2]
|
|
18828
|
+
}),
|
|
18829
|
+
numeric({
|
|
18830
|
+
id: "energy",
|
|
18831
|
+
summary: "Energy in kilowatt-hours, summed by default. Nobody reporting omits the key rather than writing 0 kWh.",
|
|
18832
|
+
role: DeviceRole.EnergySensor,
|
|
18833
|
+
outputCap: "power-meter",
|
|
18834
|
+
outputField: "kwhTotal",
|
|
18835
|
+
quantity: "energy",
|
|
18836
|
+
defaultAggregate: "sum",
|
|
18837
|
+
empty: "omit",
|
|
18838
|
+
companions: [NOW$2]
|
|
18839
|
+
}),
|
|
18840
|
+
numeric({
|
|
18841
|
+
id: "battery",
|
|
18842
|
+
summary: "Battery charge in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
18843
|
+
role: DeviceRole.BatterySensor,
|
|
18844
|
+
outputCap: "battery",
|
|
18845
|
+
outputField: "percentage",
|
|
18846
|
+
quantity: "percentage",
|
|
18847
|
+
defaultAggregate: "mean",
|
|
18848
|
+
empty: "null",
|
|
18849
|
+
companions: [
|
|
18850
|
+
{
|
|
18851
|
+
fieldPath: "charging",
|
|
18852
|
+
expr: "\"unknown\""
|
|
18853
|
+
},
|
|
18854
|
+
{
|
|
18855
|
+
fieldPath: "sleeping",
|
|
18856
|
+
expr: "false"
|
|
18857
|
+
},
|
|
18858
|
+
{
|
|
18859
|
+
fieldPath: "lastUpdated",
|
|
18860
|
+
expr: "now"
|
|
18861
|
+
}
|
|
18862
|
+
]
|
|
18863
|
+
}),
|
|
18864
|
+
numeric({
|
|
18865
|
+
id: "numeric",
|
|
18866
|
+
summary: "A numeric reading in the members’ shared quantity. Mixed quantities are refused. Nobody reporting publishes null, not 0.",
|
|
18867
|
+
role: DeviceRole.NumericSensor,
|
|
18868
|
+
outputCap: "numeric-sensor",
|
|
18869
|
+
outputField: "value",
|
|
18870
|
+
quantity: "device",
|
|
18871
|
+
defaultAggregate: "mean",
|
|
18872
|
+
empty: "null",
|
|
18873
|
+
companions: [NOW$2]
|
|
18874
|
+
}),
|
|
18875
|
+
binary({
|
|
18876
|
+
id: "motion",
|
|
18877
|
+
summary: "Any or all motion. Offline and unknown members are left out, never read as off. Nobody reporting takes the device offline.",
|
|
18878
|
+
role: DeviceRole.MotionSensor,
|
|
18879
|
+
outputCap: "motion",
|
|
18880
|
+
outputField: "detected",
|
|
18881
|
+
defaultAggregate: "any",
|
|
18882
|
+
accept: [{
|
|
18883
|
+
cap: "motion",
|
|
18884
|
+
fieldPath: "detected"
|
|
18885
|
+
}],
|
|
18886
|
+
companions: [{
|
|
18887
|
+
fieldPath: "lastDetectedAt",
|
|
18888
|
+
expr: "null"
|
|
18889
|
+
}, {
|
|
18890
|
+
fieldPath: "autoClearAfterMs",
|
|
18891
|
+
expr: "null"
|
|
18892
|
+
}]
|
|
18893
|
+
}),
|
|
18894
|
+
binary({
|
|
18895
|
+
id: "contact",
|
|
18896
|
+
summary: "Any or all open contacts. Offline and unknown members are left out, never read as closed.",
|
|
18897
|
+
role: DeviceRole.ContactSensor,
|
|
18898
|
+
outputCap: "contact",
|
|
18899
|
+
outputField: "entryOpen",
|
|
18900
|
+
defaultAggregate: "any",
|
|
18901
|
+
accept: [{
|
|
18902
|
+
cap: "contact",
|
|
18903
|
+
fieldPath: "entryOpen"
|
|
18904
|
+
}],
|
|
18905
|
+
companions: [CHANGED]
|
|
18906
|
+
}),
|
|
18907
|
+
binary({
|
|
18908
|
+
id: "leak",
|
|
18909
|
+
summary: "Any or all leak detections. Offline and unknown members are left out, never read as dry.",
|
|
18910
|
+
role: DeviceRole.LeakSensor,
|
|
18911
|
+
outputCap: "flood",
|
|
18912
|
+
outputField: "flooded",
|
|
18913
|
+
defaultAggregate: "any",
|
|
18914
|
+
accept: [{
|
|
18915
|
+
cap: "flood",
|
|
18916
|
+
fieldPath: "flooded"
|
|
18917
|
+
}],
|
|
18918
|
+
companions: [CHANGED]
|
|
18919
|
+
}),
|
|
18920
|
+
binary({
|
|
18921
|
+
id: "smoke",
|
|
18922
|
+
summary: "Any or all smoke detections. Offline and unknown members are left out, never read as clear.",
|
|
18923
|
+
role: DeviceRole.SmokeSensor,
|
|
18924
|
+
outputCap: "smoke",
|
|
18925
|
+
outputField: "detected",
|
|
18926
|
+
defaultAggregate: "any",
|
|
18927
|
+
accept: [{
|
|
18928
|
+
cap: "smoke",
|
|
18929
|
+
fieldPath: "detected"
|
|
18930
|
+
}],
|
|
18931
|
+
companions: [CHANGED]
|
|
18932
|
+
}),
|
|
18933
|
+
binary({
|
|
18934
|
+
id: "occupancy",
|
|
18935
|
+
summary: "Any or all of motion or binary sensors, published as a binary. Presence zones are not aggregated. Nobody reporting is offline, not off.",
|
|
18936
|
+
role: DeviceRole.BinarySensor,
|
|
18937
|
+
outputCap: "binary",
|
|
18938
|
+
outputField: "on",
|
|
18939
|
+
defaultAggregate: "any",
|
|
18940
|
+
accept: [{
|
|
18941
|
+
cap: "motion",
|
|
18942
|
+
fieldPath: "detected"
|
|
18943
|
+
}, {
|
|
18944
|
+
cap: "binary",
|
|
18945
|
+
fieldPath: "on"
|
|
18946
|
+
}],
|
|
18947
|
+
companions: [CHANGED]
|
|
18948
|
+
}),
|
|
18949
|
+
binary({
|
|
18950
|
+
id: "binary",
|
|
18951
|
+
summary: "Any or all generic binary sensors. Offline and unknown members are left out, never read as off.",
|
|
18952
|
+
role: DeviceRole.BinarySensor,
|
|
18953
|
+
outputCap: "binary",
|
|
18954
|
+
outputField: "on",
|
|
18955
|
+
defaultAggregate: "any",
|
|
18956
|
+
accept: [{
|
|
18957
|
+
cap: "binary",
|
|
18958
|
+
fieldPath: "on"
|
|
18959
|
+
}],
|
|
18960
|
+
companions: [CHANGED]
|
|
18961
|
+
}),
|
|
18962
|
+
actuator({
|
|
18963
|
+
id: "switch",
|
|
18964
|
+
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.",
|
|
18965
|
+
deviceType: DeviceType.Switch,
|
|
18966
|
+
outputCap: "switch",
|
|
18967
|
+
outputField: "on",
|
|
18968
|
+
member: {
|
|
18969
|
+
cap: "switch",
|
|
18970
|
+
fieldPath: "on"
|
|
18971
|
+
},
|
|
18972
|
+
commandCaps: ["switch"]
|
|
18973
|
+
}),
|
|
18974
|
+
actuator({
|
|
18975
|
+
id: "light",
|
|
18976
|
+
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.",
|
|
18977
|
+
deviceType: DeviceType.Light,
|
|
18978
|
+
outputCap: "switch",
|
|
18979
|
+
outputField: "on",
|
|
18980
|
+
member: {
|
|
18981
|
+
cap: "switch",
|
|
18982
|
+
fieldPath: "on"
|
|
18983
|
+
},
|
|
18984
|
+
commandCaps: [
|
|
18985
|
+
"switch",
|
|
18986
|
+
"brightness",
|
|
18987
|
+
"color"
|
|
18988
|
+
]
|
|
18989
|
+
}),
|
|
18990
|
+
actuator({
|
|
18991
|
+
id: "fan",
|
|
18992
|
+
summary: "On when at least one fan is on, or when all of them are. Speed, preset, direction and oscillation are offered only when every fan has them. A command is not sent to a fan that lacks it.",
|
|
18993
|
+
deviceType: DeviceType.Fan,
|
|
18994
|
+
outputCap: "switch",
|
|
18995
|
+
outputField: "on",
|
|
18996
|
+
member: {
|
|
18997
|
+
cap: "switch",
|
|
18998
|
+
fieldPath: "on"
|
|
18999
|
+
},
|
|
19000
|
+
commandCaps: ["switch", "fan-control"]
|
|
19001
|
+
}),
|
|
19002
|
+
actuator({
|
|
19003
|
+
id: "cover",
|
|
19004
|
+
summary: "Open when at least one cover is open or part-open, or only when all of them are. Position and tilt are offered only when every cover has them. A cover that reports nothing is left out, never read as closed.",
|
|
19005
|
+
deviceType: DeviceType.Cover,
|
|
19006
|
+
outputCap: "group-active",
|
|
19007
|
+
outputField: "active",
|
|
19008
|
+
member: {
|
|
19009
|
+
cap: "cover",
|
|
19010
|
+
fieldPath: "state"
|
|
19011
|
+
},
|
|
19012
|
+
activeWhen: [
|
|
19013
|
+
"open",
|
|
19014
|
+
"opening",
|
|
19015
|
+
"stopped"
|
|
19016
|
+
],
|
|
19017
|
+
commandCaps: ["cover"]
|
|
19018
|
+
}),
|
|
19019
|
+
actuator({
|
|
19020
|
+
id: "valve",
|
|
19021
|
+
summary: "Open when at least one valve is open or part-open, or only when all of them are. Position is offered only when every valve has it. A valve that reports nothing is left out, never read as closed.",
|
|
19022
|
+
deviceType: DeviceType.Valve,
|
|
19023
|
+
outputCap: "group-active",
|
|
19024
|
+
outputField: "active",
|
|
19025
|
+
member: {
|
|
19026
|
+
cap: "valve",
|
|
19027
|
+
fieldPath: "state"
|
|
19028
|
+
},
|
|
19029
|
+
activeWhen: [
|
|
19030
|
+
"open",
|
|
19031
|
+
"opening",
|
|
19032
|
+
"stopped"
|
|
19033
|
+
],
|
|
19034
|
+
commandCaps: ["valve"]
|
|
19035
|
+
}),
|
|
19036
|
+
actuator({
|
|
19037
|
+
id: "lock",
|
|
19038
|
+
summary: "Locked when at least one lock is locked, or only when all of them are. A jammed or moving lock is not locked. Locking is one tap; unlocking the group needs a confirmation every time, and nothing is sent without it.",
|
|
19039
|
+
deviceType: DeviceType.Lock,
|
|
19040
|
+
outputCap: "group-active",
|
|
19041
|
+
outputField: "active",
|
|
19042
|
+
member: {
|
|
19043
|
+
cap: "lock-control",
|
|
19044
|
+
fieldPath: "state"
|
|
19045
|
+
},
|
|
19046
|
+
activeWhen: ["locked"],
|
|
19047
|
+
commandCaps: ["lock-control"]
|
|
19048
|
+
}),
|
|
19049
|
+
actuator({
|
|
19050
|
+
id: "media-player",
|
|
19051
|
+
summary: "Playing when at least one player is playing, or only when all of them are. Volume is offered only when every player has it. A player that reports nothing is left out, never read as stopped.",
|
|
19052
|
+
deviceType: DeviceType.MediaPlayer,
|
|
19053
|
+
outputCap: "group-active",
|
|
19054
|
+
outputField: "active",
|
|
19055
|
+
member: {
|
|
19056
|
+
cap: "media-player",
|
|
19057
|
+
fieldPath: "state"
|
|
19058
|
+
},
|
|
19059
|
+
activeWhen: ["playing", "buffering"],
|
|
19060
|
+
commandCaps: ["media-player"]
|
|
19061
|
+
}),
|
|
19062
|
+
actuator({
|
|
19063
|
+
id: "climate",
|
|
19064
|
+
summary: "Running when at least one thermostat or air conditioner is not off, or only when all of them are. Target temperature and fan are offered only when every device has them. A device that reports nothing is left out, never read as off.",
|
|
19065
|
+
deviceType: DeviceType.Thermostat,
|
|
19066
|
+
memberDeviceTypes: [DeviceType.Thermostat, DeviceType.Climate],
|
|
19067
|
+
outputCap: "group-active",
|
|
19068
|
+
outputField: "active",
|
|
19069
|
+
member: {
|
|
19070
|
+
cap: "climate-control",
|
|
19071
|
+
fieldPath: "mode"
|
|
19072
|
+
},
|
|
19073
|
+
activeWhen: [
|
|
19074
|
+
"heat",
|
|
19075
|
+
"cool",
|
|
19076
|
+
"auto",
|
|
19077
|
+
"heat_cool",
|
|
19078
|
+
"fan_only",
|
|
19079
|
+
"dry"
|
|
19080
|
+
],
|
|
19081
|
+
commandCaps: ["climate-control"]
|
|
19082
|
+
})
|
|
19083
|
+
];
|
|
19084
|
+
function actuator(input) {
|
|
19085
|
+
return {
|
|
19086
|
+
id: input.id,
|
|
19087
|
+
summary: input.summary,
|
|
19088
|
+
deviceType: input.deviceType,
|
|
19089
|
+
outputCap: input.outputCap,
|
|
19090
|
+
outputField: input.outputField,
|
|
19091
|
+
commandCaps: input.commandCaps,
|
|
19092
|
+
family: "actuator",
|
|
19093
|
+
role: void 0,
|
|
19094
|
+
memberDeviceType: input.deviceType,
|
|
19095
|
+
memberDeviceTypes: input.memberDeviceTypes ?? [input.deviceType],
|
|
19096
|
+
activeWhen: input.activeWhen,
|
|
19097
|
+
quantity: "none",
|
|
19098
|
+
baseUnit: void 0,
|
|
19099
|
+
aggregates: BINARY_AGGREGATES,
|
|
19100
|
+
defaultAggregate: "any",
|
|
19101
|
+
empty: "offline",
|
|
19102
|
+
accept: [input.member],
|
|
19103
|
+
companions: [CHANGED]
|
|
19104
|
+
};
|
|
19105
|
+
}
|
|
19106
|
+
new Map(GROUP_TEMPLATES.map((template) => [template.id, template]));
|
|
19107
|
+
DeviceFeature.LightColorRgb, DeviceFeature.LightColorHsv, DeviceFeature.LightColorMired;
|
|
19108
|
+
DeviceType.Camera;
|
|
18383
19109
|
`${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
|
|
18384
19110
|
/**
|
|
18385
19111
|
* What a composition may BUILD on a device type (G2, D676): the caps a new
|
|
@@ -20093,12 +20819,12 @@ method(object({ deviceId: number().int().nonnegative() }), DeviceAdminLinkSchema
|
|
|
20093
20819
|
* providers detect renames by matching `uniqueId` and patch `id`
|
|
20094
20820
|
* in-place so dispatch keeps working.
|
|
20095
20821
|
*
|
|
20096
|
-
* **
|
|
20097
|
-
*
|
|
20098
|
-
*
|
|
20099
|
-
*
|
|
20100
|
-
* (`ha-domain-mapping`)
|
|
20101
|
-
* stored after that point.
|
|
20822
|
+
* **Display unit and precision are NOT stored here.** They are a read-time
|
|
20823
|
+
* preference (D944). A polymorphic reading stores its `quantity` here once,
|
|
20824
|
+
* at adopt, and a date/time value stores `dateTimeShape` the same way —
|
|
20825
|
+
* neither is repeated on each sample. The `device_class` tag is an
|
|
20826
|
+
* HA-specific input consumed at the discovery boundary (`ha-domain-mapping`)
|
|
20827
|
+
* to derive the CamStack `DeviceRole`; it is never stored after that point.
|
|
20102
20828
|
*
|
|
20103
20829
|
* The `raw` escape hatch carries provider-specific attributes that don't
|
|
20104
20830
|
* fit the structured slots (HA `attributes` whitelist, Reolink `deviceCache`
|
|
@@ -20112,6 +20838,14 @@ var SourceInfoSchema = object({
|
|
|
20112
20838
|
/** Immutable upstream identifier when available (HA `unique_id`, … ).
|
|
20113
20839
|
* Used to detect rename when `id` changes. */
|
|
20114
20840
|
uniqueId: string().optional(),
|
|
20841
|
+
/** Quantity of a polymorphic reading, written once at adopt (D944). */
|
|
20842
|
+
quantity: ReadingQuantitySchema.optional(),
|
|
20843
|
+
/** Date / time / datetime shape of a string reading, written once at adopt. */
|
|
20844
|
+
dateTimeShape: _enum([
|
|
20845
|
+
"date",
|
|
20846
|
+
"time",
|
|
20847
|
+
"datetime"
|
|
20848
|
+
]).optional(),
|
|
20115
20849
|
/** Provider-specific extras that don't fit the structured slots.
|
|
20116
20850
|
* Whitelist what goes here per provider — do NOT dump entire HA
|
|
20117
20851
|
* attribute blobs (would explode the meta JSON column). */
|
|
@@ -41024,7 +41758,8 @@ method(object({
|
|
|
41024
41758
|
"enum"
|
|
41025
41759
|
]),
|
|
41026
41760
|
enumValues: array(string()).optional(),
|
|
41027
|
-
item: boolean().optional()
|
|
41761
|
+
item: boolean().optional(),
|
|
41762
|
+
quantity: ReadingQuantitySchema.optional()
|
|
41028
41763
|
})).readonly(),
|
|
41029
41764
|
itemArray: object({
|
|
41030
41765
|
path: string(),
|
|
@@ -43404,7 +44139,7 @@ var NetworkAccessStatusSchema = object({
|
|
|
43404
44139
|
});
|
|
43405
44140
|
/**
|
|
43406
44141
|
* Optional, richer endpoint shape returned by providers that expose
|
|
43407
|
-
* MORE than one ingress concurrently (Tailscale
|
|
44142
|
+
* MORE than one ingress concurrently (Tailscale Funnel with mixed
|
|
43408
44143
|
* serve+funnel rules, future ngrok multi-tunnel, …). Each entry carries
|
|
43409
44144
|
* the originating provider config (mode + sourcePort) so the
|
|
43410
44145
|
* orchestrator UI can label rows distinctly. Providers that expose only
|
|
@@ -44843,8 +45578,8 @@ var MaskPolygonShapeSchema = object({
|
|
|
44843
45578
|
/** Boolean cell grid — row-major, length === gridWidth*gridHeight. */
|
|
44844
45579
|
var MaskGridShapeSchema = object({
|
|
44845
45580
|
kind: literal("grid"),
|
|
44846
|
-
gridWidth: number(),
|
|
44847
|
-
gridHeight: number(),
|
|
45581
|
+
gridWidth: number().meta(readingMeta("none")),
|
|
45582
|
+
gridHeight: number().meta(readingMeta("none")),
|
|
44848
45583
|
cells: array(boolean())
|
|
44849
45584
|
});
|
|
44850
45585
|
discriminatedUnion("kind", [
|
|
@@ -44956,6 +45691,8 @@ var NcSystemEventKindSchema = _enum([
|
|
|
44956
45691
|
"detection-blind",
|
|
44957
45692
|
"motion-noisy",
|
|
44958
45693
|
"motion-calm",
|
|
45694
|
+
"package-llm-silent",
|
|
45695
|
+
"package-llm-answered",
|
|
44959
45696
|
"recording-stalled",
|
|
44960
45697
|
"recording-healthy",
|
|
44961
45698
|
"recording-degraded",
|
|
@@ -46045,7 +46782,20 @@ var NcRuleInputSchema = object({
|
|
|
46045
46782
|
* save by the hub's grouping guard). `.optional()`, never `.default()`: the addon cap
|
|
46046
46783
|
* path does not run Zod defaults.
|
|
46047
46784
|
*/
|
|
46048
|
-
groupingSec: number().int().min(5).max(60).optional()
|
|
46785
|
+
groupingSec: number().int().min(5).max(60).optional(),
|
|
46786
|
+
/**
|
|
46787
|
+
* ASK ME TO CONFIRM DETECTIONS (#243): a DETECTION notification of this rule
|
|
46788
|
+
* carries "Correct" / "Wrong" buttons (and, where the channel has room, a
|
|
46789
|
+
* "Wrong, it is a <class>" choice). A tap marks the track for retraining, the
|
|
46790
|
+
* same mark the Library writes, and records whose notification it was and
|
|
46791
|
+
* when. A channel with no buttons gets the same two choices as links.
|
|
46792
|
+
*
|
|
46793
|
+
* `.optional()`, never `.default()` (a Zod default does not run on the addon
|
|
46794
|
+
* cap path): absent and `false` both mean off, which is what every rule
|
|
46795
|
+
* authored before this field meant. An editor turns it off by writing
|
|
46796
|
+
* `false`, so it needs no `clear` key.
|
|
46797
|
+
*/
|
|
46798
|
+
askVerdict: boolean().optional()
|
|
46049
46799
|
});
|
|
46050
46800
|
/**
|
|
46051
46801
|
* Partial patch for `updateRule` — any subset of the input fields, plus the
|
|
@@ -55970,6 +56720,28 @@ var PackageVersionInfoSchema = object({
|
|
|
55970
56720
|
deprecated: string().optional(),
|
|
55971
56721
|
distTags: array(string()).readonly()
|
|
55972
56722
|
});
|
|
56723
|
+
/**
|
|
56724
|
+
* One published document. `ok` is markdown from the registry. `missing` means
|
|
56725
|
+
* the registry answered and the file was not there. `error` is a registry or
|
|
56726
|
+
* tarball failure — never an empty string standing in for either.
|
|
56727
|
+
*/
|
|
56728
|
+
var PackageDocBodySchema = discriminatedUnion("status", [
|
|
56729
|
+
object({
|
|
56730
|
+
status: literal("ok"),
|
|
56731
|
+
markdown: string()
|
|
56732
|
+
}),
|
|
56733
|
+
object({ status: literal("missing") }),
|
|
56734
|
+
object({
|
|
56735
|
+
status: literal("error"),
|
|
56736
|
+
message: string()
|
|
56737
|
+
})
|
|
56738
|
+
]);
|
|
56739
|
+
var PackageDocsSchema = object({
|
|
56740
|
+
name: string(),
|
|
56741
|
+
version: string(),
|
|
56742
|
+
readme: PackageDocBodySchema,
|
|
56743
|
+
changelog: PackageDocBodySchema
|
|
56744
|
+
});
|
|
55973
56745
|
var SearchResultSchema = object({
|
|
55974
56746
|
name: string(),
|
|
55975
56747
|
version: string(),
|
|
@@ -56188,7 +56960,10 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
|
|
|
56188
56960
|
}), object({ success: literal(true) }), {
|
|
56189
56961
|
kind: "mutation",
|
|
56190
56962
|
auth: "admin"
|
|
56191
|
-
}), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({
|
|
56963
|
+
}), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({
|
|
56964
|
+
name: string().min(1),
|
|
56965
|
+
version: string().min(1).optional()
|
|
56966
|
+
}), PackageDocsSchema, { auth: "admin" }), method(object({ addonId: string() }), RestartAddonResultSchema, {
|
|
56192
56967
|
kind: "mutation",
|
|
56193
56968
|
auth: "admin"
|
|
56194
56969
|
}), method(object({ packageName: string() }), object({ success: literal(true) }), {
|
|
@@ -56238,46 +57013,27 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
|
|
|
56238
57013
|
}), LogStreamEntrySchema, { kind: "subscription" });
|
|
56239
57014
|
object({
|
|
56240
57015
|
/** Carbon dioxide concentration in ppm. */
|
|
56241
|
-
co2Ppm: number().min(0).optional(),
|
|
57016
|
+
co2Ppm: number().min(0).optional().meta(readingMeta("concentration-volume")),
|
|
56242
57017
|
/** Total volatile organic compounds in ppb. */
|
|
56243
|
-
vocPpb: number().min(0).optional(),
|
|
57018
|
+
vocPpb: number().min(0).optional().meta(readingMeta("concentration-ppb")),
|
|
56244
57019
|
/** Particulate matter ≤ 2.5 μm in µg/m³. */
|
|
56245
|
-
pm25: number().min(0).optional(),
|
|
57020
|
+
pm25: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
56246
57021
|
/** Particulate matter ≤ 10 μm in µg/m³. */
|
|
56247
|
-
pm10: number().min(0).optional(),
|
|
57022
|
+
pm10: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
56248
57023
|
/** Composite AQI value (typically 0..500). */
|
|
56249
|
-
aqi: number().optional(),
|
|
57024
|
+
aqi: number().optional().meta(readingMeta("index")),
|
|
56250
57025
|
/** Ms epoch when the slice was last updated. */
|
|
56251
|
-
lastFetchedAt: number()
|
|
56252
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
56253
|
-
* `attributes.unit_of_measurement` → 'ppm' / 'ppb' / 'µg/m³'). Each
|
|
56254
|
-
* upstream `sensor.*` entity surfaces ONE device_class, so one unit
|
|
56255
|
-
* per slice is unambiguous. */
|
|
56256
|
-
unit: string().optional(),
|
|
56257
|
-
/** Suggested decimal places for numeric display.
|
|
56258
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
56259
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
56260
|
-
* auto-formatting when absent. */
|
|
56261
|
-
precision: number().int().min(0).max(10).optional()
|
|
57026
|
+
lastFetchedAt: number()
|
|
56262
57027
|
});
|
|
56263
57028
|
DeviceType.Sensor;
|
|
56264
57029
|
object({
|
|
56265
|
-
/** Current illuminance in lux (lx). */
|
|
56266
|
-
lux: number().min(0).meta({
|
|
56267
|
-
|
|
57030
|
+
/** Current illuminance in lux (lx). `null` when the sample was refused (D393). */
|
|
57031
|
+
lux: number().min(0).nullable().meta(readingMeta("illuminance", {
|
|
57032
|
+
precision: 0,
|
|
56268
57033
|
label: "Illuminance"
|
|
56269
|
-
}),
|
|
57034
|
+
})),
|
|
56270
57035
|
/** Ms epoch when the slice was last updated. */
|
|
56271
|
-
lastFetchedAt: number()
|
|
56272
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
56273
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
56274
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
56275
|
-
unit: string().optional(),
|
|
56276
|
-
/** Suggested decimal places for numeric display.
|
|
56277
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
56278
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
56279
|
-
* auto-formatting when absent. */
|
|
56280
|
-
precision: number().int().min(0).max(10).optional()
|
|
57036
|
+
lastFetchedAt: number()
|
|
56281
57037
|
});
|
|
56282
57038
|
DeviceType.Sensor;
|
|
56283
57039
|
/**
|
|
@@ -56422,10 +57178,7 @@ var BatteryStatusSchema = object({
|
|
|
56422
57178
|
* Consumers must SKIP a null rather than coerce it — `battery-band` already
|
|
56423
57179
|
* declines to band a non-finite reading, which is the correct shape.
|
|
56424
57180
|
*/
|
|
56425
|
-
percentage: number().min(0).max(100).nullable().meta({
|
|
56426
|
-
unit: "%",
|
|
56427
|
-
label: "Charge"
|
|
56428
|
-
}),
|
|
57181
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage", { label: "Charge" })),
|
|
56429
57182
|
/**
|
|
56430
57183
|
* Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
|
|
56431
57184
|
* Reolink-specific for the Solar Panel 2 accessory (will become
|
|
@@ -56452,7 +57205,14 @@ var BatteryStatusSchema = object({
|
|
|
56452
57205
|
*/
|
|
56453
57206
|
sleeping: boolean().meta({ label: "Sleeping" }),
|
|
56454
57207
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
56455
|
-
lastUpdated: number(),
|
|
57208
|
+
lastUpdated: number().meta(readingMeta("none")),
|
|
57209
|
+
/**
|
|
57210
|
+
* Battery voltage in volts, for a cell the firmware reports as voltage
|
|
57211
|
+
* rather than a percentage (Ecowitt capacitor packs). Absent on cameras
|
|
57212
|
+
* that only report charge. A second reading on this cap, not a second
|
|
57213
|
+
* `numeric-sensor` on the same device.
|
|
57214
|
+
*/
|
|
57215
|
+
volts: number().nullable().optional().meta(readingMeta("voltage", { label: "Voltage" })),
|
|
56456
57216
|
/**
|
|
56457
57217
|
* Ms epoch of the last time the device PROVED it was reachable — a
|
|
56458
57218
|
* completed firmware round-trip, an observed wake, or an inbound push
|
|
@@ -56492,7 +57252,7 @@ var BatteryStatusSchema = object({
|
|
|
56492
57252
|
*/
|
|
56493
57253
|
binary: boolean().optional().meta({ label: "Binary indicator" })
|
|
56494
57254
|
});
|
|
56495
|
-
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat;
|
|
57255
|
+
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.EventEmitter;
|
|
56496
57256
|
method(object({
|
|
56497
57257
|
deviceId: number(),
|
|
56498
57258
|
/** Bound on the wait. Sensible range 3000–10000ms. */
|
|
@@ -56512,7 +57272,7 @@ object({
|
|
|
56512
57272
|
DeviceType.Sensor;
|
|
56513
57273
|
object({
|
|
56514
57274
|
/** Current level as 0..100 inclusive. Firmware-reported. */
|
|
56515
|
-
percentage: number().min(0).max(100),
|
|
57275
|
+
percentage: number().min(0).max(100).meta(readingMeta("percentage")),
|
|
56516
57276
|
/** Ms epoch of the last operator-driven change. Useful for UI freshness. */
|
|
56517
57277
|
lastChangedAt: number()
|
|
56518
57278
|
});
|
|
@@ -56897,21 +57657,21 @@ object({
|
|
|
56897
57657
|
/** Single setpoint in Celsius. Used by single-target modes
|
|
56898
57658
|
* (heat / cool / dry). Null when the device is in a range mode
|
|
56899
57659
|
* (`heat_cool`) or has no setpoint at all (`fan_only`/`off`). */
|
|
56900
|
-
target: number().nullable(),
|
|
57660
|
+
target: number().nullable().meta(readingMeta("temperature")),
|
|
56901
57661
|
/** Upper bound of the dual setpoint in Celsius. Populated only
|
|
56902
57662
|
* in `heat_cool` mode. */
|
|
56903
|
-
targetHigh: number().nullable(),
|
|
57663
|
+
targetHigh: number().nullable().meta(readingMeta("temperature")),
|
|
56904
57664
|
/** Lower bound of the dual setpoint in Celsius. Populated only
|
|
56905
57665
|
* in `heat_cool` mode. */
|
|
56906
|
-
targetLow: number().nullable(),
|
|
57666
|
+
targetLow: number().nullable().meta(readingMeta("temperature")),
|
|
56907
57667
|
/** Target relative humidity (0..100). Null when the device has no
|
|
56908
57668
|
* humidity control. */
|
|
56909
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
57669
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
56910
57670
|
/** Current measured temperature in Celsius. Read-only — pushed by
|
|
56911
57671
|
* the device's internal sensor. */
|
|
56912
|
-
currentTemp: number().nullable(),
|
|
57672
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
56913
57673
|
/** Current measured relative humidity (0..100). Read-only. */
|
|
56914
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
57674
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
56915
57675
|
/** Vertical louver swing on/off. Null when the device has no vertical
|
|
56916
57676
|
* swing surface (gate with `DeviceFeature.ClimateSwingVertical`). */
|
|
56917
57677
|
swingVertical: boolean().nullable(),
|
|
@@ -56919,11 +57679,11 @@ object({
|
|
|
56919
57679
|
* horizontal swing surface (gate with `DeviceFeature.ClimateSwingHorizontal`). */
|
|
56920
57680
|
swingHorizontal: boolean().nullable(),
|
|
56921
57681
|
/** Lowest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
56922
|
-
minTemp: number().nullable().optional(),
|
|
57682
|
+
minTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
56923
57683
|
/** Highest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
56924
|
-
maxTemp: number().nullable().optional(),
|
|
57684
|
+
maxTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
56925
57685
|
/** Setpoint granularity, Celsius (0.5, 1). Absent / null = not reported. */
|
|
56926
|
-
tempStep: number().positive().nullable().optional(),
|
|
57686
|
+
tempStep: number().positive().nullable().optional().meta(readingMeta("temperature")),
|
|
56927
57687
|
/** Ms epoch when the slice was last updated (push or command). */
|
|
56928
57688
|
lastFetchedAt: number()
|
|
56929
57689
|
});
|
|
@@ -57002,17 +57762,17 @@ DeviceType.Thermostat, DeviceType.Climate, method(object({
|
|
|
57002
57762
|
* modes to expose in the picker without a slice fetch.
|
|
57003
57763
|
*/
|
|
57004
57764
|
var RgbTripletSchema = object({
|
|
57005
|
-
r: number().int().min(0).max(255),
|
|
57006
|
-
g: number().int().min(0).max(255),
|
|
57007
|
-
b: number().int().min(0).max(255)
|
|
57765
|
+
r: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
57766
|
+
g: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
57767
|
+
b: number().int().min(0).max(255).meta(readingMeta("none"))
|
|
57008
57768
|
});
|
|
57009
57769
|
var HsvTripletSchema = object({
|
|
57010
57770
|
/** Hue in degrees, 0..360. */
|
|
57011
|
-
h: number().min(0).max(360),
|
|
57771
|
+
h: number().min(0).max(360).meta(readingMeta("none")),
|
|
57012
57772
|
/** Saturation as 0..100 inclusive. */
|
|
57013
|
-
s: number().min(0).max(100),
|
|
57773
|
+
s: number().min(0).max(100).meta(readingMeta("none")),
|
|
57014
57774
|
/** Value/brightness as 0..100 inclusive. */
|
|
57015
|
-
v: number().min(0).max(100)
|
|
57775
|
+
v: number().min(0).max(100).meta(readingMeta("none"))
|
|
57016
57776
|
});
|
|
57017
57777
|
var ColorInputSchema = discriminatedUnion("mode", [
|
|
57018
57778
|
object({
|
|
@@ -57041,7 +57801,7 @@ object({
|
|
|
57041
57801
|
/** Populated when `mode === 'hsv'`. */
|
|
57042
57802
|
hsv: HsvTripletSchema.optional(),
|
|
57043
57803
|
/** Populated when `mode === 'mired'`. */
|
|
57044
|
-
mireds: number().int().optional(),
|
|
57804
|
+
mireds: number().int().optional().meta(readingMeta("colour-temperature")),
|
|
57045
57805
|
/** Ms epoch of the last operator-driven change. */
|
|
57046
57806
|
lastChangedAt: number()
|
|
57047
57807
|
});
|
|
@@ -57165,18 +57925,12 @@ _enum([
|
|
|
57165
57925
|
"empty",
|
|
57166
57926
|
"full"
|
|
57167
57927
|
]);
|
|
57168
|
-
/**
|
|
57169
|
-
|
|
57170
|
-
|
|
57171
|
-
"days",
|
|
57172
|
-
"hours",
|
|
57173
|
-
"cycles"
|
|
57174
|
-
]);
|
|
57175
|
-
/** Remaining life as a COUNT, not a percentage (the PetKit desiccant reports
|
|
57176
|
-
* days). `value` null = unknown (D393). */
|
|
57928
|
+
/** Whether `remaining.value` is a duration in seconds or a dimensionless count. */
|
|
57929
|
+
var ConsumableRemainingKindSchema = _enum(["duration", "count"]);
|
|
57930
|
+
/** Remaining life. `value` null = unknown (D393). Duration is seconds. */
|
|
57177
57931
|
var ConsumableRemainingSchema = object({
|
|
57178
|
-
value: number().min(0).nullable(),
|
|
57179
|
-
|
|
57932
|
+
value: number().min(0).nullable().meta(readingMeta("device")),
|
|
57933
|
+
kind: ConsumableRemainingKindSchema
|
|
57180
57934
|
});
|
|
57181
57935
|
var ConsumablesStatusSchema = object({
|
|
57182
57936
|
items: array(object({
|
|
@@ -57185,7 +57939,7 @@ var ConsumablesStatusSchema = object({
|
|
|
57185
57939
|
/** Display name. */
|
|
57186
57940
|
label: string().min(1),
|
|
57187
57941
|
/** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
|
|
57188
|
-
level: number().min(0).max(100).nullable(),
|
|
57942
|
+
level: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
57189
57943
|
/** The provider's discrete verdict when known (binary mode). */
|
|
57190
57944
|
status: ConsumableStatusSchema.nullable(),
|
|
57191
57945
|
/** What the item is — decides whether low or full is bad. Absent = `wear`. */
|
|
@@ -57202,7 +57956,7 @@ var ConsumablesStatusSchema = object({
|
|
|
57202
57956
|
})),
|
|
57203
57957
|
lastChangedAt: number()
|
|
57204
57958
|
});
|
|
57205
|
-
Object.values(DeviceType), [...
|
|
57959
|
+
Object.values(DeviceType), [...ConsumableRemainingKindSchema.options], [...ConsumableStatusSchema.options], [...ConsumableKindSchema.options], [...ConsumableFormSchema.options];
|
|
57206
57960
|
Object.values(DeviceType), method(object({
|
|
57207
57961
|
deviceId: number().int().nonnegative(),
|
|
57208
57962
|
key: string().min(1)
|
|
@@ -57227,39 +57981,17 @@ object({
|
|
|
57227
57981
|
/** Current value. Numeric kind → number; select/text/datetime → string.
|
|
57228
57982
|
* Datetime values are ISO 8601 strings (full timestamp, date-only,
|
|
57229
57983
|
* or time-only — HA accepts all three forms). */
|
|
57230
|
-
value: union([number(), string()]),
|
|
57984
|
+
value: union([number().meta(readingMeta("device")), string()]),
|
|
57231
57985
|
/** Acceptable values when `kind === 'select'`. Empty for other kinds. */
|
|
57232
57986
|
options: array(string()),
|
|
57233
57987
|
/** Ms epoch when the slice was last updated. */
|
|
57234
57988
|
lastChangedAt: number(),
|
|
57235
|
-
/**
|
|
57236
|
-
|
|
57237
|
-
|
|
57238
|
-
|
|
57239
|
-
/**
|
|
57240
|
-
|
|
57241
|
-
min: number().optional(),
|
|
57242
|
-
/** Maximum allowed value. Populated live from HA `attributes.max`.
|
|
57243
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
57244
|
-
max: number().optional(),
|
|
57245
|
-
/** Step increment. Populated live from HA `attributes.step`.
|
|
57246
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
57247
|
-
step: number().optional(),
|
|
57248
|
-
/** Suggested decimal places for numeric display. Populated live from HA
|
|
57249
|
-
* `attributes.suggested_display_precision`, or derived from `step` when the
|
|
57250
|
-
* HA attribute is absent. Meaningful for `kind === 'numeric'`; absent for
|
|
57251
|
-
* other kinds. Falls back to auto-formatting when absent. */
|
|
57252
|
-
precision: number().int().min(0).max(10).optional(),
|
|
57253
|
-
/** Date-picker granularity for `kind === 'datetime'`. 'date' → date-only,
|
|
57254
|
-
* 'time' → time-only, 'datetime' → full timestamp. Absent for other kinds
|
|
57255
|
-
* (UI defaults to 'datetime'). Derived live from the device's HA domain
|
|
57256
|
-
* (date.* / time.* / datetime.*) or, for input_datetime, from the entity's
|
|
57257
|
-
* `has_date`/`has_time` attributes on each push. */
|
|
57258
|
-
format: _enum([
|
|
57259
|
-
"date",
|
|
57260
|
-
"time",
|
|
57261
|
-
"datetime"
|
|
57262
|
-
]).optional()
|
|
57989
|
+
/** Minimum allowed value, in the device quantity's base unit. */
|
|
57990
|
+
min: number().optional().meta(readingMeta("device")),
|
|
57991
|
+
/** Maximum allowed value, in the device quantity's base unit. */
|
|
57992
|
+
max: number().optional().meta(readingMeta("device")),
|
|
57993
|
+
/** Step increment, in the device quantity's base unit. */
|
|
57994
|
+
step: number().optional().meta(readingMeta("device"))
|
|
57263
57995
|
});
|
|
57264
57996
|
var ControlSetValueInputSchema = discriminatedUnion("kind", [
|
|
57265
57997
|
object({
|
|
@@ -57297,9 +58029,9 @@ object({
|
|
|
57297
58029
|
]),
|
|
57298
58030
|
/** 0 = fully closed, 100 = fully open. Null when the device has
|
|
57299
58031
|
* no intermediate position surface. */
|
|
57300
|
-
position: number().min(0).max(100).nullable(),
|
|
58032
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
57301
58033
|
/** 0 = closed slats, 100 = open slats. Null when no tilt support. */
|
|
57302
|
-
tiltPosition: number().min(0).max(100).nullable(),
|
|
58034
|
+
tiltPosition: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
57303
58035
|
/** Ms epoch when the slice was last updated. */
|
|
57304
58036
|
lastChangedAt: number()
|
|
57305
58037
|
});
|
|
@@ -57357,9 +58089,9 @@ var NormalizedRangeSchema$1 = object({
|
|
|
57357
58089
|
object({
|
|
57358
58090
|
mode: DayNightModeSchema,
|
|
57359
58091
|
/** IR-cut trigger sensitivity, NORMALIZED 0–100 (higher = switches to night sooner). */
|
|
57360
|
-
sensitivity: number().optional(),
|
|
58092
|
+
sensitivity: number().optional().meta(readingMeta("none")),
|
|
57361
58093
|
/** Delay before the IR-cut filter flips, in seconds. */
|
|
57362
|
-
switchDelaySec: number().optional(),
|
|
58094
|
+
switchDelaySec: number().optional().meta(readingMeta("duration")),
|
|
57363
58095
|
lastFetchedAt: number()
|
|
57364
58096
|
});
|
|
57365
58097
|
/**
|
|
@@ -57514,11 +58246,11 @@ object({
|
|
|
57514
58246
|
/** Feature keys of the programs the appliance currently offers — drives the UI selector. */
|
|
57515
58247
|
availablePrograms: array(string()),
|
|
57516
58248
|
/** Seconds remaining on the active cycle, or null when not running / not known. */
|
|
57517
|
-
remainingSeconds: number().int().nonnegative().nullable(),
|
|
58249
|
+
remainingSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
57518
58250
|
/** Seconds the delayed start is set to (time until the cycle starts), or null. */
|
|
57519
|
-
delayedStartSeconds: number().int().nonnegative().nullable(),
|
|
58251
|
+
delayedStartSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
57520
58252
|
/** Cycle completion 0..100, or null when not applicable. */
|
|
57521
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
58253
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
57522
58254
|
/** True when the door is reported open; null when the door state is not known. */
|
|
57523
58255
|
doorOpen: boolean().nullable(),
|
|
57524
58256
|
/** True when the door is latched (locked) during a cycle; null when not reported. */
|
|
@@ -57542,7 +58274,7 @@ object({
|
|
|
57542
58274
|
/** True while the machine-care (descaling / cleaning-program) reminder is raised; false when clear; null when not reported. */
|
|
57543
58275
|
machineCareDue: boolean().nullable(),
|
|
57544
58276
|
/** Program runs left before the machine-care reminder is due; null when the appliance does not say. */
|
|
57545
|
-
machineCareRemainingRuns: number().int().nonnegative().nullable(),
|
|
58277
|
+
machineCareRemainingRuns: number().int().nonnegative().nullable().meta(readingMeta("count")),
|
|
57546
58278
|
/** Option states: null when the appliance does not expose the option or has not said. */
|
|
57547
58279
|
halfLoad: boolean().nullable(),
|
|
57548
58280
|
hygienePlus: boolean().nullable(),
|
|
@@ -57557,7 +58289,7 @@ object({
|
|
|
57557
58289
|
/** Feature keys of the events currently raised (salt low, rinse aid low, program finished, …). */
|
|
57558
58290
|
activeEvents: array(string()),
|
|
57559
58291
|
/** Numeric error code when the appliance reports one; null otherwise. */
|
|
57560
|
-
errorCode: number().nullable(),
|
|
58292
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
57561
58293
|
/** Name of the raised alert-level event while the appliance is in error; null otherwise. */
|
|
57562
58294
|
errorLabel: string().nullable(),
|
|
57563
58295
|
/** Ms epoch of the last value received from the appliance; 0 = never. */
|
|
@@ -57703,24 +58435,14 @@ object({
|
|
|
57703
58435
|
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
57704
58436
|
lastPressedAt: number().nullable(),
|
|
57705
58437
|
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
57706
|
-
pressCountSinceStart: number()
|
|
58438
|
+
pressCountSinceStart: number().meta(readingMeta("count"))
|
|
57707
58439
|
});
|
|
57708
58440
|
object({
|
|
57709
58441
|
deviceId: number(),
|
|
57710
58442
|
timestamp: number()
|
|
57711
58443
|
});
|
|
57712
58444
|
DeviceType.Button, DeviceType.Camera;
|
|
57713
|
-
|
|
57714
|
-
* Enum-state sensor — a string value picked from a finite option set.
|
|
57715
|
-
* Drives HA `sensor` entries with `state_class: enum` (HVAC action
|
|
57716
|
-
* states, weather conditions, contact-source channels, mode strings).
|
|
57717
|
-
* The option set is stable across observations; it is persisted in the
|
|
57718
|
-
* device config blob (via the control slice at adoption) and is NOT
|
|
57719
|
-
* stored in `sourceInfo`.
|
|
57720
|
-
*/
|
|
57721
|
-
/** Locale-render shape for an ISO `value` carried by a `DateTimeSensor`-role
|
|
57722
|
-
* enum sensor: `date` (date-only), `time` (time-only), `datetime` (both). */
|
|
57723
|
-
var EnumSensorDateTimeFormatSchema = _enum([
|
|
58445
|
+
_enum([
|
|
57724
58446
|
"date",
|
|
57725
58447
|
"time",
|
|
57726
58448
|
"datetime"
|
|
@@ -57728,12 +58450,11 @@ var EnumSensorDateTimeFormatSchema = _enum([
|
|
|
57728
58450
|
object({
|
|
57729
58451
|
value: string(),
|
|
57730
58452
|
/**
|
|
57731
|
-
* Set
|
|
57732
|
-
* as
|
|
57733
|
-
*
|
|
57734
|
-
* a time-only sensor → `'time'`.
|
|
58453
|
+
* Set when `value` is a timestamp rather than an enum state, so history
|
|
58454
|
+
* does not learn ISO strings as states. The display shape (date / time /
|
|
58455
|
+
* datetime) lives on `SourceInfo.dateTimeShape`, written once at adopt.
|
|
57735
58456
|
*/
|
|
57736
|
-
|
|
58457
|
+
timestamp: boolean().optional(),
|
|
57737
58458
|
/** Ms epoch when the slice was last updated. */
|
|
57738
58459
|
lastFetchedAt: number()
|
|
57739
58460
|
});
|
|
@@ -57752,13 +58473,13 @@ var EventFireSchema = object({
|
|
|
57752
58473
|
deviceId: number(),
|
|
57753
58474
|
eventType: string(),
|
|
57754
58475
|
data: record(string(), unknown()).nullable(),
|
|
57755
|
-
timestamp: number(),
|
|
57756
|
-
seq: number()
|
|
58476
|
+
timestamp: number().meta(readingMeta("none")),
|
|
58477
|
+
seq: number().meta(readingMeta("count"))
|
|
57757
58478
|
});
|
|
57758
58479
|
object({
|
|
57759
58480
|
eventTypes: array(string()),
|
|
57760
58481
|
lastEvent: EventFireSchema.nullable(),
|
|
57761
|
-
eventCountSinceStart: number()
|
|
58482
|
+
eventCountSinceStart: number().meta(readingMeta("count"))
|
|
57762
58483
|
});
|
|
57763
58484
|
DeviceType.EventEmitter;
|
|
57764
58485
|
var IdentitySchema = object({
|
|
@@ -58147,10 +58868,10 @@ var FanDirectionSchema = _enum(["forward", "reverse"]);
|
|
|
58147
58868
|
object({
|
|
58148
58869
|
/** Active speed as 0..100 inclusive. Null when the device has no
|
|
58149
58870
|
* speed surface (single-speed fan). */
|
|
58150
|
-
percentage: number().min(0).max(100).nullable(),
|
|
58871
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58151
58872
|
/** Speed granularity the device accepts (HA `percentage_step`, e.g. 25 for
|
|
58152
58873
|
* a 4-speed fan). Absent when unknown — the UI then falls back to step 1. */
|
|
58153
|
-
percentageStep: number().positive().optional(),
|
|
58874
|
+
percentageStep: number().positive().optional().meta(readingMeta("percentage")),
|
|
58154
58875
|
/** Active preset mode (`auto` / `quiet` / `turbo` / vendor-specific)
|
|
58155
58876
|
* — empty string when no preset is active or supported. */
|
|
58156
58877
|
preset: string(),
|
|
@@ -58232,7 +58953,7 @@ var FeatureProbeStatusSchema = object({
|
|
|
58232
58953
|
/** Camera/firmware model string. `null` when the firmware doesn't expose it. */
|
|
58233
58954
|
model: string().nullable(),
|
|
58234
58955
|
/** Channel count for NVR/Hub devices; `1` for standalone cameras; `null` pre-probe. */
|
|
58235
|
-
channelCount: number().nullable(),
|
|
58956
|
+
channelCount: number().nullable().meta(readingMeta("count")),
|
|
58236
58957
|
/**
|
|
58237
58958
|
* Ms epoch of the last SUCCESSFUL probe. `0` before the first probe
|
|
58238
58959
|
* completes — drivers' `getAccessoryChildren()` should treat zero as
|
|
@@ -58264,9 +58985,45 @@ object({
|
|
|
58264
58985
|
lastChangedAt: number()
|
|
58265
58986
|
});
|
|
58266
58987
|
DeviceType.Sensor;
|
|
58988
|
+
object({
|
|
58989
|
+
/** One row per member that has been commanded. A later command replaces that member's row. */
|
|
58990
|
+
results: array(object({
|
|
58991
|
+
deviceId: number().int().nonnegative(),
|
|
58992
|
+
cap: string().min(1),
|
|
58993
|
+
method: string().min(1),
|
|
58994
|
+
ok: boolean(),
|
|
58995
|
+
error: string().optional(),
|
|
58996
|
+
/** Ms epoch of the attempt. */
|
|
58997
|
+
at: number()
|
|
58998
|
+
})) });
|
|
58999
|
+
DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Cover, DeviceType.Valve, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.Thermostat, DeviceType.Climate;
|
|
59000
|
+
object({
|
|
59001
|
+
active: boolean().meta({ label: "Active" }),
|
|
59002
|
+
/** Ms epoch when the slice was last updated. */
|
|
59003
|
+
lastChangedAt: number()
|
|
59004
|
+
});
|
|
59005
|
+
DeviceType.Cover, DeviceType.Valve, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.Climate, DeviceType.Thermostat;
|
|
59006
|
+
object({
|
|
59007
|
+
/** Members whose current value entered the aggregate. */
|
|
59008
|
+
included: number().int().nonnegative().meta(readingMeta("count", {
|
|
59009
|
+
precision: 0,
|
|
59010
|
+
label: "Reporting"
|
|
59011
|
+
})),
|
|
59012
|
+
/** Members left out: offline, unknown, or not a finite reading (D393). */
|
|
59013
|
+
excluded: number().int().nonnegative().meta(readingMeta("count", {
|
|
59014
|
+
precision: 0,
|
|
59015
|
+
label: "Excluded"
|
|
59016
|
+
})),
|
|
59017
|
+
/** `included` + `excluded`. */
|
|
59018
|
+
total: number().int().nonnegative().meta(readingMeta("count", {
|
|
59019
|
+
precision: 0,
|
|
59020
|
+
label: "Members"
|
|
59021
|
+
}))
|
|
59022
|
+
});
|
|
59023
|
+
DeviceType.Sensor, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Cover, DeviceType.Valve, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.Thermostat, DeviceType.Climate;
|
|
58267
59024
|
object({
|
|
58268
59025
|
/** Radiator valve opening 0 (closed) .. 100 (open). Null = not yet known. */
|
|
58269
|
-
position: number().min(0).max(100).nullable(),
|
|
59026
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58270
59027
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
58271
59028
|
lastFetchedAt: number()
|
|
58272
59029
|
});
|
|
@@ -58275,9 +59032,9 @@ object({
|
|
|
58275
59032
|
/** Whether the humidifier is currently on. */
|
|
58276
59033
|
on: boolean(),
|
|
58277
59034
|
/** Current measured relative humidity (0..100). Null when not reported. */
|
|
58278
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
59035
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
58279
59036
|
/** Target relative humidity (0..100). Null when no setpoint surface. */
|
|
58280
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
59037
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
58281
59038
|
/** Active mode (`auto` / `normal` / `baby` / vendor). Null when the
|
|
58282
59039
|
* device has no mode surface. */
|
|
58283
59040
|
mode: string().nullable(),
|
|
@@ -58287,9 +59044,9 @@ object({
|
|
|
58287
59044
|
* `idle` / `off`). Null when the device doesn't report it. */
|
|
58288
59045
|
action: string().nullable(),
|
|
58289
59046
|
/** HA `min_humidity` attribute. Null → UI uses 0. */
|
|
58290
|
-
minHumidity: number().nullable(),
|
|
59047
|
+
minHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
58291
59048
|
/** HA `max_humidity` attribute. Null → UI uses 100. */
|
|
58292
|
-
maxHumidity: number().nullable(),
|
|
59049
|
+
maxHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
58293
59050
|
/** Ms epoch when the slice was last updated. */
|
|
58294
59051
|
lastChangedAt: number()
|
|
58295
59052
|
});
|
|
@@ -58313,22 +59070,13 @@ DeviceType.Humidifier, method(object({
|
|
|
58313
59070
|
auth: "protected"
|
|
58314
59071
|
});
|
|
58315
59072
|
object({
|
|
58316
|
-
/** Current relative humidity, 0..100. */
|
|
58317
|
-
percent: number().min(0).max(100).meta({
|
|
58318
|
-
|
|
59073
|
+
/** Current relative humidity, 0..100. `null` when the sample was refused (D393). */
|
|
59074
|
+
percent: number().min(0).max(100).nullable().meta(readingMeta("humidity", {
|
|
59075
|
+
precision: 0,
|
|
58319
59076
|
label: "Humidity"
|
|
58320
|
-
}),
|
|
59077
|
+
})),
|
|
58321
59078
|
/** Ms epoch when the slice was last updated. */
|
|
58322
|
-
lastFetchedAt: number()
|
|
58323
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
58324
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
58325
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
58326
|
-
unit: string().optional(),
|
|
58327
|
-
/** Suggested decimal places for numeric display.
|
|
58328
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
58329
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
58330
|
-
* auto-formatting when absent. */
|
|
58331
|
-
precision: number().int().min(0).max(10).optional()
|
|
59079
|
+
lastFetchedAt: number()
|
|
58332
59080
|
});
|
|
58333
59081
|
DeviceType.Sensor, DeviceType.Thermostat;
|
|
58334
59082
|
object({
|
|
@@ -58336,7 +59084,7 @@ object({
|
|
|
58336
59084
|
* entity exposes no `entity_picture` (yet). */
|
|
58337
59085
|
url: string().nullable(),
|
|
58338
59086
|
/** Ms epoch of the upstream last-updated timestamp. Null at cold-start. */
|
|
58339
|
-
lastUpdated: number().nullable()
|
|
59087
|
+
lastUpdated: number().nullable().meta(readingMeta("none"))
|
|
58340
59088
|
});
|
|
58341
59089
|
DeviceType.Image;
|
|
58342
59090
|
/**
|
|
@@ -58392,19 +59140,19 @@ var NormalizedRangeSchema = object({
|
|
|
58392
59140
|
});
|
|
58393
59141
|
object({
|
|
58394
59142
|
/** Normalized 0–100. */
|
|
58395
|
-
brightness: number().optional(),
|
|
59143
|
+
brightness: number().optional().meta(readingMeta("none")),
|
|
58396
59144
|
/** Normalized 0–100. */
|
|
58397
|
-
contrast: number().optional(),
|
|
59145
|
+
contrast: number().optional().meta(readingMeta("none")),
|
|
58398
59146
|
/** Normalized 0–100. */
|
|
58399
|
-
saturation: number().optional(),
|
|
59147
|
+
saturation: number().optional().meta(readingMeta("none")),
|
|
58400
59148
|
/** Normalized 0–100. */
|
|
58401
|
-
sharpness: number().optional(),
|
|
59149
|
+
sharpness: number().optional().meta(readingMeta("none")),
|
|
58402
59150
|
mirror: boolean().optional(),
|
|
58403
59151
|
flip: boolean().optional(),
|
|
58404
59152
|
rotate: ImageRotateSchema.optional(),
|
|
58405
59153
|
whiteBalance: WhiteBalanceModeSchema.optional(),
|
|
58406
59154
|
/** Manual white-balance warmth, NORMALIZED 0–100. Meaningful only when `whiteBalance === 'manual'`. */
|
|
58407
|
-
warmth: number().optional(),
|
|
59155
|
+
warmth: number().optional().meta(readingMeta("none")),
|
|
58408
59156
|
exposureMode: ExposureModeSchema.optional(),
|
|
58409
59157
|
backlightMode: BacklightModeSchema.optional(),
|
|
58410
59158
|
lastFetchedAt: number()
|
|
@@ -58649,10 +59397,10 @@ var IntercomAbilitySchema = object({
|
|
|
58649
59397
|
/** Codecs accepted by firmware, in preference order. Driver-authored strings. */
|
|
58650
59398
|
codecs: array(string()),
|
|
58651
59399
|
/** Sample rate (Hz) the firmware expects. Reolink typical: 16000. */
|
|
58652
|
-
sampleRate: number(),
|
|
59400
|
+
sampleRate: number().meta(readingMeta("none")),
|
|
58653
59401
|
duplex: _enum(["half", "full"]),
|
|
58654
59402
|
/** Max in-flight audio backlog before drop (ms). Server uses this to bound latency. */
|
|
58655
|
-
maxBacklogMs: number()
|
|
59403
|
+
maxBacklogMs: number().meta(readingMeta("duration-ms"))
|
|
58656
59404
|
});
|
|
58657
59405
|
var IntercomStatusSchema = object({
|
|
58658
59406
|
/** True while a talk session is open. */
|
|
@@ -58763,13 +59511,13 @@ object({
|
|
|
58763
59511
|
activity: LawnMowerActivitySchema,
|
|
58764
59512
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
58765
59513
|
* reading. */
|
|
58766
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
59514
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58767
59515
|
/** 0..100 mowing-completion percentage of the current task, or null when no
|
|
58768
59516
|
* task is active / progress is unavailable. */
|
|
58769
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
59517
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58770
59518
|
/** Current device/event code (dynamic — mostly status, sometimes an error),
|
|
58771
59519
|
* or null when unknown. */
|
|
58772
|
-
currentCode: number().nullable(),
|
|
59520
|
+
currentCode: number().nullable().meta(readingMeta("none")),
|
|
58773
59521
|
/** Human label for {@link currentCode}, or null when undecodable. */
|
|
58774
59522
|
currentCodeLabel: string().nullable(),
|
|
58775
59523
|
/** Severity of {@link currentCode}. `error` (and often `warning`) warrants UI
|
|
@@ -59179,7 +59927,14 @@ DeviceType.Lock, method(object({
|
|
|
59179
59927
|
auth: "protected"
|
|
59180
59928
|
}), method(object({
|
|
59181
59929
|
deviceId: number().int().nonnegative(),
|
|
59182
|
-
code: string().min(1).optional()
|
|
59930
|
+
code: string().min(1).optional(),
|
|
59931
|
+
/**
|
|
59932
|
+
* Honoured by a helper lock GROUP only (D944): unlocking several doors
|
|
59933
|
+
* with one call is refused unless the caller says it was confirmed. A
|
|
59934
|
+
* single lock ignores it. The refusal lives in the callee, so no
|
|
59935
|
+
* automation or API caller reaches the doors by skipping a dialog.
|
|
59936
|
+
*/
|
|
59937
|
+
confirm: boolean().optional()
|
|
59183
59938
|
}), _void(), {
|
|
59184
59939
|
kind: "mutation",
|
|
59185
59940
|
auth: "protected"
|
|
@@ -59187,6 +59942,11 @@ DeviceType.Lock, method(object({
|
|
|
59187
59942
|
kind: "mutation",
|
|
59188
59943
|
auth: "protected"
|
|
59189
59944
|
});
|
|
59945
|
+
object({
|
|
59946
|
+
value: number().nullable().meta(readingMeta("device", { label: "Total" })),
|
|
59947
|
+
lastFetchedAt: number()
|
|
59948
|
+
});
|
|
59949
|
+
DeviceType.Sensor;
|
|
59190
59950
|
/**
|
|
59191
59951
|
* Media-player cap. Models HA `media_player.*` (Sonos, Chromecast,
|
|
59192
59952
|
* Apple TV, Spotify, Roku, generic OTT receivers, …) on
|
|
@@ -59231,7 +59991,7 @@ object({
|
|
|
59231
59991
|
state: MediaPlayerStateSchema,
|
|
59232
59992
|
/** Volume as 0..100 inclusive. Null when the device has no volume
|
|
59233
59993
|
* surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
|
|
59234
|
-
volumeLevel: number().min(0).max(100).nullable(),
|
|
59994
|
+
volumeLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59235
59995
|
/** Mute toggle distinct from volume=0. Null when no mute surface.
|
|
59236
59996
|
* Pair with `DeviceFeature.MediaPlayerMute`. */
|
|
59237
59997
|
isMuted: boolean().nullable(),
|
|
@@ -59244,10 +60004,10 @@ object({
|
|
|
59244
60004
|
currentMedia: MediaInfoSchema.nullable(),
|
|
59245
60005
|
/** Current playback position in ms. Null when not seekable or
|
|
59246
60006
|
* nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
|
|
59247
|
-
positionMs: number().int().nonnegative().nullable(),
|
|
60007
|
+
positionMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
59248
60008
|
/** Total duration of the current media in ms. Null when unknown
|
|
59249
60009
|
* (live stream) or nothing is playing. */
|
|
59250
|
-
durationMs: number().int().nonnegative().nullable(),
|
|
60010
|
+
durationMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
59251
60011
|
/** Shuffle toggle. Null when no shuffle surface.
|
|
59252
60012
|
* Pair with `DeviceFeature.MediaPlayerShuffle`. */
|
|
59253
60013
|
shuffle: boolean().nullable(),
|
|
@@ -59547,7 +60307,7 @@ object({
|
|
|
59547
60307
|
* it, every provider seeded it at boot, and every session left it
|
|
59548
60308
|
* `detected: true` after its detach.
|
|
59549
60309
|
*/
|
|
59550
|
-
autoClearAfterMs: number().nullable()
|
|
60310
|
+
autoClearAfterMs: number().nullable().meta(readingMeta("duration-ms"))
|
|
59551
60311
|
});
|
|
59552
60312
|
/**
|
|
59553
60313
|
* Payload of `motion.onMotionChanged` event + the corresponding bus
|
|
@@ -59597,7 +60357,7 @@ var MotionZoneRegionSchema = object({
|
|
|
59597
60357
|
});
|
|
59598
60358
|
object({
|
|
59599
60359
|
enabled: boolean(),
|
|
59600
|
-
sensitivity: number(),
|
|
60360
|
+
sensitivity: number().meta(readingMeta("none")),
|
|
59601
60361
|
/** Grid region(s). Today exactly one `grid` shape. */
|
|
59602
60362
|
regions: array(MotionZoneRegionSchema),
|
|
59603
60363
|
lastFetchedAt: number()
|
|
@@ -59901,7 +60661,7 @@ var NavigationStatusSchema = object({
|
|
|
59901
60661
|
following: boolean(),
|
|
59902
60662
|
flash: boolean(),
|
|
59903
60663
|
lightMode: NavigationLightModeSchema,
|
|
59904
|
-
lightLevel: number().min(40).max(100),
|
|
60664
|
+
lightLevel: number().min(40).max(100).meta(readingMeta("none")),
|
|
59905
60665
|
/** Ms epoch when the slice was last updated. */
|
|
59906
60666
|
lastChangedAt: number()
|
|
59907
60667
|
});
|
|
@@ -59947,13 +60707,13 @@ var NetworkLinkStatusSchema = object({
|
|
|
59947
60707
|
* one whose reading has not landed must not be drawn at 0 %. Consumers
|
|
59948
60708
|
* SKIP a null rather than coerce it.
|
|
59949
60709
|
*/
|
|
59950
|
-
signalPercent: number().min(0).max(100).nullable(),
|
|
60710
|
+
signalPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59951
60711
|
/** Raw received signal strength in dBm, when the firmware reports one. */
|
|
59952
|
-
rssiDbm: number().optional(),
|
|
60712
|
+
rssiDbm: number().optional().meta(readingMeta("signal-level")),
|
|
59953
60713
|
/** Network name of a wireless link, when the firmware reports it. */
|
|
59954
60714
|
ssid: string().optional(),
|
|
59955
60715
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
59956
|
-
lastUpdated: number()
|
|
60716
|
+
lastUpdated: number().meta(readingMeta("none"))
|
|
59957
60717
|
});
|
|
59958
60718
|
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.Light, DeviceType.Lock, DeviceType.Siren, object({
|
|
59959
60719
|
deviceId: number(),
|
|
@@ -60272,7 +61032,7 @@ object({
|
|
|
60272
61032
|
lastError: string().nullable(),
|
|
60273
61033
|
/** Number of deliveries currently buffered server-side (rate-limited
|
|
60274
61034
|
* notifiers may queue). 0 when the provider sends synchronously. */
|
|
60275
|
-
queueDepth: number().int().nonnegative(),
|
|
61035
|
+
queueDepth: number().int().nonnegative().meta(readingMeta("count")),
|
|
60276
61036
|
/** Per-feature capability matrix — authoritative source for the
|
|
60277
61037
|
* compose-form field gating. */
|
|
60278
61038
|
supports: NotifierSupportsSchema
|
|
@@ -60322,15 +61082,8 @@ DeviceType.Notifier, method(NotifierSendInputSchema, NotifierSendResultSchema, {
|
|
|
60322
61082
|
acceptedAt: number()
|
|
60323
61083
|
});
|
|
60324
61084
|
object({
|
|
60325
|
-
|
|
60326
|
-
|
|
60327
|
-
* Populated live from the upstream source on each state push.
|
|
60328
|
-
* Absent for unitless sensors. */
|
|
60329
|
-
unit: string().optional(),
|
|
60330
|
-
/** Suggested decimal places for numeric display.
|
|
60331
|
-
* Populated live from the upstream source when provided.
|
|
60332
|
-
* Falls back to auto-formatting when absent. */
|
|
60333
|
-
precision: number().int().min(0).max(10).optional(),
|
|
61085
|
+
/** Reading in the device quantity's base unit. `null` when refused (D393). */
|
|
61086
|
+
value: number().nullable().meta(readingMeta("device")),
|
|
60334
61087
|
/** Ms epoch when the slice was last updated. */
|
|
60335
61088
|
lastFetchedAt: number()
|
|
60336
61089
|
});
|
|
@@ -60620,23 +61373,26 @@ object({
|
|
|
60620
61373
|
/** Food currently in the bowl (grams). Null when the device has not
|
|
60621
61374
|
* reported a reading yet. On dual-hopper models this is the combined
|
|
60622
61375
|
* bowl reading; per-hopper levels live in `food1`/`food2`. */
|
|
60623
|
-
foodLevel: number().nullable(),
|
|
61376
|
+
foodLevel: number().nullable().meta(readingMeta("none")),
|
|
60624
61377
|
/** Hopper-1 food level (grams) on dual-hopper feeders; null on
|
|
60625
61378
|
* single-hopper models. */
|
|
60626
|
-
food1: number().nullable(),
|
|
61379
|
+
food1: number().nullable().meta(readingMeta("none")),
|
|
60627
61380
|
/** Hopper-2 food level (grams) on dual-hopper feeders; null on
|
|
60628
61381
|
* single-hopper models. */
|
|
60629
|
-
food2: number().nullable(),
|
|
61382
|
+
food2: number().nullable().meta(readingMeta("none")),
|
|
60630
61383
|
/** Derived low-food flag — mirrors the HA `food_level` binary_sensor
|
|
60631
61384
|
* (`device_class: problem`, on = low). True when the bowl is empty /
|
|
60632
61385
|
* below the feeder's low threshold. */
|
|
60633
61386
|
lowFood: boolean(),
|
|
60634
61387
|
/** Battery charge 0..100 (%). Null on mains-powered models or when the
|
|
60635
61388
|
* device has no battery reading. */
|
|
60636
|
-
batteryPower: number().min(0).max(100).nullable(),
|
|
60637
|
-
/**
|
|
60638
|
-
*
|
|
60639
|
-
|
|
61389
|
+
batteryPower: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61390
|
+
/**
|
|
61391
|
+
* Desiccant life remaining, stored in seconds (duration base, D944).
|
|
61392
|
+
* Providers convert from the days the feeder reports. Null when the
|
|
61393
|
+
* model has no desiccant sensor.
|
|
61394
|
+
*/
|
|
61395
|
+
desiccantLeftDays: number().nullable().meta(readingMeta("duration")),
|
|
60640
61396
|
/** True while a feed is in progress. */
|
|
60641
61397
|
feeding: boolean(),
|
|
60642
61398
|
/** Decoded connectivity / power status (HA petkit device-status enum).
|
|
@@ -60647,7 +61403,7 @@ object({
|
|
|
60647
61403
|
* with `errorCode` for consumers that want the raw integer. */
|
|
60648
61404
|
error: string().nullable(),
|
|
60649
61405
|
/** Raw device error code (0 / null = no error). */
|
|
60650
|
-
errorCode: number().nullable(),
|
|
61406
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
60651
61407
|
/** True for D4S/D4SH dual-hopper hardware — gates the per-hopper UI. */
|
|
60652
61408
|
isDualHopper: boolean(),
|
|
60653
61409
|
/** Child-lock (manual-lock) setting — buttons on the unit are disabled. */
|
|
@@ -60657,7 +61413,7 @@ object({
|
|
|
60657
61413
|
/** Play a chime when dispensing. */
|
|
60658
61414
|
feedSound: boolean(),
|
|
60659
61415
|
/** Speaker / prompt volume level (device-scaled integer). */
|
|
60660
|
-
volume: number(),
|
|
61416
|
+
volume: number().meta(readingMeta("none")),
|
|
60661
61417
|
/** Ms epoch when the slice was last refreshed from the cloud. */
|
|
60662
61418
|
lastFetchedAt: number()
|
|
60663
61419
|
});
|
|
@@ -61094,38 +61850,37 @@ method(_void(), PlatformCapabilitiesSchema), method(_void(), HardwareInfoSchema)
|
|
|
61094
61850
|
});
|
|
61095
61851
|
object({
|
|
61096
61852
|
/** Instantaneous power draw in watts. */
|
|
61097
|
-
watts: number().optional().meta({
|
|
61098
|
-
unit: "W",
|
|
61099
|
-
label: "Power"
|
|
61100
|
-
}),
|
|
61853
|
+
watts: number().optional().meta(readingMeta("power", { label: "Power" })),
|
|
61101
61854
|
/** Cumulative energy in kilowatt-hours since the meter was reset. */
|
|
61102
|
-
kwhTotal: number().optional().meta({
|
|
61103
|
-
unit: "kWh",
|
|
61104
|
-
label: "Energy"
|
|
61105
|
-
}),
|
|
61855
|
+
kwhTotal: number().optional().meta(readingMeta("energy", { label: "Energy" })),
|
|
61106
61856
|
/** Voltage in volts. */
|
|
61107
|
-
volts: number().optional(),
|
|
61857
|
+
volts: number().optional().meta(readingMeta("voltage", { label: "Voltage" })),
|
|
61108
61858
|
/** Current in amperes. */
|
|
61109
|
-
amps: number().optional(),
|
|
61110
|
-
/** Apparent power in volt-amperes
|
|
61111
|
-
va: number().optional(),
|
|
61859
|
+
amps: number().optional().meta(readingMeta("current", { label: "Current" })),
|
|
61860
|
+
/** Apparent power in volt-amperes. */
|
|
61861
|
+
va: number().optional().meta(readingMeta("apparent-power")),
|
|
61112
61862
|
/** Power factor (0..1) if reported. */
|
|
61113
|
-
powerFactor: number().min(0).max(1).optional(),
|
|
61863
|
+
powerFactor: number().min(0).max(1).optional().meta(readingMeta("ratio")),
|
|
61114
61864
|
/** Ms epoch when the slice was last updated. */
|
|
61115
|
-
lastFetchedAt: number()
|
|
61116
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
61117
|
-
* `attributes.unit_of_measurement` → 'V' / 'A' / 'W' / 'kW' / 'kWh').
|
|
61118
|
-
* Each upstream `sensor.*` entity surfaces ONE device_class, so one
|
|
61119
|
-
* unit per slice is unambiguous. The UI prefers this over the role's
|
|
61120
|
-
* canonical unit so a 'kW' / 'Wh' feed renders verbatim. */
|
|
61121
|
-
unit: string().optional(),
|
|
61122
|
-
/** Suggested decimal places for numeric display.
|
|
61123
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
61124
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
61125
|
-
* auto-formatting when absent. */
|
|
61126
|
-
precision: number().int().min(0).max(10).optional()
|
|
61865
|
+
lastFetchedAt: number()
|
|
61127
61866
|
});
|
|
61128
|
-
|
|
61867
|
+
[
|
|
61868
|
+
DeviceType.Sensor,
|
|
61869
|
+
DeviceType.Switch,
|
|
61870
|
+
DeviceType.Light,
|
|
61871
|
+
DeviceType.Fan,
|
|
61872
|
+
DeviceType.Climate,
|
|
61873
|
+
DeviceType.Thermostat,
|
|
61874
|
+
DeviceType.Humidifier,
|
|
61875
|
+
DeviceType.WaterHeater,
|
|
61876
|
+
DeviceType.MediaPlayer,
|
|
61877
|
+
DeviceType.Washer,
|
|
61878
|
+
DeviceType.Dryer,
|
|
61879
|
+
DeviceType.Dishwasher,
|
|
61880
|
+
DeviceType.Vacuum,
|
|
61881
|
+
DeviceType.LawnMower,
|
|
61882
|
+
DeviceType.PetFeeder
|
|
61883
|
+
].filter((type) => type !== DeviceType.Sensor);
|
|
61129
61884
|
/**
|
|
61130
61885
|
* Presence cap. Models HA `person.*` and `device_tracker.*` entities
|
|
61131
61886
|
* on `DeviceType.Presence`. Read-only — no setters: presence is
|
|
@@ -61144,11 +61899,11 @@ DeviceType.Sensor;
|
|
|
61144
61899
|
*/
|
|
61145
61900
|
var GpsLocationSchema = object({
|
|
61146
61901
|
/** Latitude in decimal degrees, -90..90. */
|
|
61147
|
-
latitude: number().min(-90).max(90),
|
|
61902
|
+
latitude: number().min(-90).max(90).meta(readingMeta("angle")),
|
|
61148
61903
|
/** Longitude in decimal degrees, -180..180. */
|
|
61149
|
-
longitude: number().min(-180).max(180),
|
|
61904
|
+
longitude: number().min(-180).max(180).meta(readingMeta("angle")),
|
|
61150
61905
|
/** Reported accuracy in meters (lower = better). */
|
|
61151
|
-
accuracyMeters: number().nonnegative()
|
|
61906
|
+
accuracyMeters: number().nonnegative().meta(readingMeta("length"))
|
|
61152
61907
|
});
|
|
61153
61908
|
object({
|
|
61154
61909
|
/** `home` / `not_home` / any user-defined zone name. */
|
|
@@ -61160,25 +61915,16 @@ object({
|
|
|
61160
61915
|
gps: GpsLocationSchema.nullable(),
|
|
61161
61916
|
/** Optional battery level of the tracking device (0..100). Null
|
|
61162
61917
|
* when not reported. */
|
|
61163
|
-
batteryPercent: number().min(0).max(100).nullable(),
|
|
61918
|
+
batteryPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61164
61919
|
/** Ms epoch when the slice was last updated. */
|
|
61165
61920
|
lastChangedAt: number()
|
|
61166
61921
|
});
|
|
61167
61922
|
DeviceType.Presence;
|
|
61168
61923
|
object({
|
|
61169
|
-
/** Current pressure in hPa. */
|
|
61170
|
-
hpa: number(),
|
|
61924
|
+
/** Current pressure in hPa. `null` when the sample was refused (D393). */
|
|
61925
|
+
hpa: number().nullable().meta(readingMeta("pressure", { precision: 0 })),
|
|
61171
61926
|
/** Ms epoch when the slice was last updated. */
|
|
61172
|
-
lastFetchedAt: number()
|
|
61173
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
61174
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
61175
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
61176
|
-
unit: string().optional(),
|
|
61177
|
-
/** Suggested decimal places for numeric display.
|
|
61178
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
61179
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
61180
|
-
* auto-formatting when absent. */
|
|
61181
|
-
precision: number().int().min(0).max(10).optional()
|
|
61927
|
+
lastFetchedAt: number()
|
|
61182
61928
|
});
|
|
61183
61929
|
DeviceType.Sensor;
|
|
61184
61930
|
/**
|
|
@@ -61511,8 +62257,8 @@ DeviceType.Camera, method(PtzMoveCommandSchema.extend({ deviceId: number() }), _
|
|
|
61511
62257
|
}), _void(), { kind: "mutation" });
|
|
61512
62258
|
var PtzAutotrackSettingsSchema = object({
|
|
61513
62259
|
targetType: string().describe("Vendor target string (people/vehicle/pet); empty = camera default"),
|
|
61514
|
-
stopDelaySeconds: number().int().min(0).max(300),
|
|
61515
|
-
disappearDelaySeconds: number().int().min(0).max(300)
|
|
62260
|
+
stopDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration")),
|
|
62261
|
+
disappearDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration"))
|
|
61516
62262
|
});
|
|
61517
62263
|
/**
|
|
61518
62264
|
* One option the camera advertises as a valid `targetType`. Drivers
|
|
@@ -61569,7 +62315,7 @@ object({
|
|
|
61569
62315
|
/** null = unknown — never coerced to false (D393). */
|
|
61570
62316
|
running: boolean().nullable(),
|
|
61571
62317
|
/** Epoch ms the current boolean began; null while `running` is null. */
|
|
61572
|
-
since: number().nullable(),
|
|
62318
|
+
since: number().nullable().meta(readingMeta("none")),
|
|
61573
62319
|
source: RunningStateSourceSchema.meta({ label: "Source" }),
|
|
61574
62320
|
phase: string().nullable(),
|
|
61575
62321
|
/** null until a reading has been published (D393). */
|
|
@@ -61581,7 +62327,7 @@ object({
|
|
|
61581
62327
|
phase: string().nullable()
|
|
61582
62328
|
});
|
|
61583
62329
|
Object.values(DeviceType);
|
|
61584
|
-
DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
|
|
62330
|
+
DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
|
|
61585
62331
|
DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch, method(object({ deviceId: number().int().nonnegative() }), object({ success: literal(true) }), {
|
|
61586
62332
|
kind: "mutation",
|
|
61587
62333
|
auth: "admin"
|
|
@@ -62767,9 +63513,9 @@ var RecordTriggerSchema = _enum([
|
|
|
62767
63513
|
*/
|
|
62768
63514
|
var RecordWindowSchema = object({
|
|
62769
63515
|
trigger: RecordTriggerSchema,
|
|
62770
|
-
day: number().int().min(0).max(6),
|
|
62771
|
-
startMinute: number().int().min(0).max(1439),
|
|
62772
|
-
endMinute: number().int().min(1).max(1440)
|
|
63516
|
+
day: number().int().min(0).max(6).meta(readingMeta("none")),
|
|
63517
|
+
startMinute: number().int().min(0).max(1439).meta(readingMeta("none")),
|
|
63518
|
+
endMinute: number().int().min(1).max(1440).meta(readingMeta("none"))
|
|
62773
63519
|
});
|
|
62774
63520
|
/** Status of one physical volume, as the camera itself describes it. */
|
|
62775
63521
|
var OnboardStorageVolumeSchema = object({
|
|
@@ -62838,10 +63584,10 @@ object({
|
|
|
62838
63584
|
/** Master "record to the card at all" switch. */
|
|
62839
63585
|
enabled: boolean().nullable(),
|
|
62840
63586
|
overwriteWhenFull: boolean().nullable(),
|
|
62841
|
-
preRecordSec: number().nullable(),
|
|
62842
|
-
postRecordSec: number().nullable(),
|
|
63587
|
+
preRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
63588
|
+
postRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
62843
63589
|
/** Length of one recorded file, in minutes. */
|
|
62844
|
-
segmentMinutes: number().nullable(),
|
|
63590
|
+
segmentMinutes: number().nullable().meta(readingMeta("none")),
|
|
62845
63591
|
/** The primary track's weekly windows, flattened. */
|
|
62846
63592
|
windows: array(RecordWindowSchema),
|
|
62847
63593
|
/**
|
|
@@ -62857,7 +63603,7 @@ object({
|
|
|
62857
63603
|
* provider reporting a non-zero count also reports the schedule as not
|
|
62858
63604
|
* writable.
|
|
62859
63605
|
*/
|
|
62860
|
-
unreadableWindows: number(),
|
|
63606
|
+
unreadableWindows: number().meta(readingMeta("count")),
|
|
62861
63607
|
/**
|
|
62862
63608
|
* The camera is scheduled to record and has NO usable storage.
|
|
62863
63609
|
*
|
|
@@ -63494,7 +64240,7 @@ var CamStreamDescriptorSchema = object({
|
|
|
63494
64240
|
url: string().optional(),
|
|
63495
64241
|
codec: string().optional(),
|
|
63496
64242
|
resolution: CamStreamResolutionSchema.optional(),
|
|
63497
|
-
fps: number().positive().optional(),
|
|
64243
|
+
fps: number().positive().optional().meta(readingMeta("rate")),
|
|
63498
64244
|
label: string().optional(),
|
|
63499
64245
|
/** Device-level features (e.g. `battery-operated`) — drives broker policy. */
|
|
63500
64246
|
deviceFeatures: array(string()).optional(),
|
|
@@ -63524,18 +64270,18 @@ var StreamProfileSchema = _enum([
|
|
|
63524
64270
|
]);
|
|
63525
64271
|
/** The current encoding config of one stream profile. */
|
|
63526
64272
|
var StreamProfileConfigSchema = object({
|
|
63527
|
-
width: number(),
|
|
63528
|
-
height: number(),
|
|
64273
|
+
width: number().meta(readingMeta("none")),
|
|
64274
|
+
height: number().meta(readingMeta("none")),
|
|
63529
64275
|
codec: _enum(["h264", "h265"]),
|
|
63530
|
-
framerate: number(),
|
|
63531
|
-
bitrate: number(),
|
|
64276
|
+
framerate: number().meta(readingMeta("rate")),
|
|
64277
|
+
bitrate: number().meta(readingMeta("bitrate")),
|
|
63532
64278
|
bitrateMode: _enum(["vbr", "cbr"]).optional(),
|
|
63533
64279
|
encoderProfile: _enum([
|
|
63534
64280
|
"high",
|
|
63535
64281
|
"main",
|
|
63536
64282
|
"baseline"
|
|
63537
64283
|
]).optional(),
|
|
63538
|
-
gop: number().optional(),
|
|
64284
|
+
gop: number().optional().meta(readingMeta("none")),
|
|
63539
64285
|
/**
|
|
63540
64286
|
* Whether THIS profile currently carries an audio track. READ-ONLY here.
|
|
63541
64287
|
*
|
|
@@ -63620,7 +64366,7 @@ object({
|
|
|
63620
64366
|
/** Ms epoch of the last state change. Useful for UI "X minutes ago". */
|
|
63621
64367
|
lastChangedAt: number()
|
|
63622
64368
|
});
|
|
63623
|
-
DeviceType.Switch, DeviceType.Siren, DeviceType.Light, method(object({
|
|
64369
|
+
DeviceType.Switch, DeviceType.Siren, DeviceType.Light, DeviceType.Fan, method(object({
|
|
63624
64370
|
deviceId: number(),
|
|
63625
64371
|
on: boolean()
|
|
63626
64372
|
}), _void(), {
|
|
@@ -64178,23 +64924,13 @@ object({
|
|
|
64178
64924
|
});
|
|
64179
64925
|
DeviceType.Sensor;
|
|
64180
64926
|
object({
|
|
64181
|
-
/** Current temperature in Celsius. */
|
|
64182
|
-
celsius: number().meta({
|
|
64183
|
-
|
|
64927
|
+
/** Current temperature in Celsius. `null` when the sample was refused (D393). */
|
|
64928
|
+
celsius: number().nullable().meta(readingMeta("temperature", {
|
|
64929
|
+
precision: 1,
|
|
64184
64930
|
label: "Temperature"
|
|
64185
|
-
}),
|
|
64931
|
+
})),
|
|
64186
64932
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
64187
|
-
lastFetchedAt: number()
|
|
64188
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
64189
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
64190
|
-
* role's canonical unit, so a Fahrenheit feed renders '°F' not '°C'.
|
|
64191
|
-
* Absent → the UI falls back to the role's canonical unit. */
|
|
64192
|
-
unit: string().optional(),
|
|
64193
|
-
/** Suggested decimal places for numeric display.
|
|
64194
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
64195
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
64196
|
-
* auto-formatting when absent. */
|
|
64197
|
-
precision: number().int().min(0).max(10).optional()
|
|
64933
|
+
lastFetchedAt: number()
|
|
64198
64934
|
});
|
|
64199
64935
|
DeviceType.Sensor, DeviceType.Thermostat;
|
|
64200
64936
|
/**
|
|
@@ -64446,16 +65182,16 @@ object({
|
|
|
64446
65182
|
]),
|
|
64447
65183
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
64448
65184
|
* reading. */
|
|
64449
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
65185
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
64450
65186
|
/** Current fan-speed token (provider-verbatim). Null when unknown or
|
|
64451
65187
|
* the vacuum has no speed control. */
|
|
64452
65188
|
fanSpeed: string().nullable(),
|
|
64453
65189
|
/** Speed tokens the hardware accepts — drives the UI selector. */
|
|
64454
65190
|
availableFanSpeeds: array(string()),
|
|
64455
65191
|
/** 0..100 cleaning-completion percentage of the current task, or null. */
|
|
64456
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
65192
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
64457
65193
|
/** Current error code (0 / null = no error). */
|
|
64458
|
-
errorCode: number().nullable(),
|
|
65194
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
64459
65195
|
/** Human label for {@link errorCode}, or null when none / undecodable. */
|
|
64460
65196
|
errorLabel: string().nullable(),
|
|
64461
65197
|
/** Ms epoch when the slice was last updated. */
|
|
@@ -64494,7 +65230,7 @@ object({
|
|
|
64494
65230
|
]),
|
|
64495
65231
|
/** 0 = fully closed, 100 = fully open. Null when the device has no
|
|
64496
65232
|
* intermediate position surface. */
|
|
64497
|
-
position: number().min(0).max(100).nullable(),
|
|
65233
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
64498
65234
|
/** Ms epoch when the slice was last updated. */
|
|
64499
65235
|
lastChangedAt: number()
|
|
64500
65236
|
});
|
|
@@ -64522,9 +65258,9 @@ object({
|
|
|
64522
65258
|
DeviceType.Sensor;
|
|
64523
65259
|
object({
|
|
64524
65260
|
/** Current measured temperature. Null when not reported. */
|
|
64525
|
-
currentTemp: number().nullable(),
|
|
65261
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
64526
65262
|
/** Target temperature setpoint. Null when no setpoint surface. */
|
|
64527
|
-
targetTemp: number().nullable(),
|
|
65263
|
+
targetTemp: number().nullable().meta(readingMeta("temperature")),
|
|
64528
65264
|
/** Active operation mode = HA `state` (`eco` / `electric` / `gas` /
|
|
64529
65265
|
* `heat_pump` / `high_demand` / `performance` / `off`). Null when the
|
|
64530
65266
|
* device reports an unknown state. */
|
|
@@ -64535,9 +65271,9 @@ object({
|
|
|
64535
65271
|
* has no away surface. */
|
|
64536
65272
|
away: boolean().nullable(),
|
|
64537
65273
|
/** HA `min_temp` attribute. Null when not reported. */
|
|
64538
|
-
minTemp: number().nullable(),
|
|
65274
|
+
minTemp: number().nullable().meta(readingMeta("temperature")),
|
|
64539
65275
|
/** HA `max_temp` attribute. Null when not reported. */
|
|
64540
|
-
maxTemp: number().nullable(),
|
|
65276
|
+
maxTemp: number().nullable().meta(readingMeta("temperature")),
|
|
64541
65277
|
/** Ms epoch when the slice was last updated. */
|
|
64542
65278
|
lastChangedAt: number()
|
|
64543
65279
|
});
|
|
@@ -64561,25 +65297,18 @@ DeviceType.WaterHeater, method(object({
|
|
|
64561
65297
|
auth: "protected"
|
|
64562
65298
|
});
|
|
64563
65299
|
object({
|
|
64564
|
-
/** Verbatim
|
|
64565
|
-
* when no condition has been reported yet. */
|
|
65300
|
+
/** Verbatim condition state (`sunny`, `cloudy`, `rainy`, …). Null when none yet. */
|
|
64566
65301
|
condition: string().nullable(),
|
|
64567
|
-
/** Current temperature in
|
|
64568
|
-
temperature: number().nullable(),
|
|
64569
|
-
/** Temperature unit string (e.g. `°C` / `°F`). Null when not provided. */
|
|
64570
|
-
temperatureUnit: string().nullable(),
|
|
65302
|
+
/** Current temperature in Celsius. Null when not provided or refused. */
|
|
65303
|
+
temperature: number().nullable().meta(readingMeta("temperature", { precision: 1 })),
|
|
64571
65304
|
/** Relative humidity (0..100). Null when not provided. */
|
|
64572
|
-
humidity: number().min(0).max(100).nullable(),
|
|
64573
|
-
/** Barometric pressure in
|
|
64574
|
-
pressure: number().nullable(),
|
|
64575
|
-
/**
|
|
64576
|
-
|
|
64577
|
-
/** Wind speed in the reported unit. Null when not provided. */
|
|
64578
|
-
windSpeed: number().nullable(),
|
|
64579
|
-
/** Wind-speed unit string (e.g. `km/h` / `mph`). Null when not provided. */
|
|
64580
|
-
windSpeedUnit: string().nullable(),
|
|
65305
|
+
humidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
65306
|
+
/** Barometric pressure in hPa. Null when not provided or refused. */
|
|
65307
|
+
pressure: number().nullable().meta(readingMeta("pressure")),
|
|
65308
|
+
/** Wind speed in metres per second. Null when not provided or refused. */
|
|
65309
|
+
windSpeed: number().nullable().meta(readingMeta("speed")),
|
|
64581
65310
|
/** Wind bearing in degrees (0..360, meteorological). Null when not provided. */
|
|
64582
|
-
windBearing: number().nullable(),
|
|
65311
|
+
windBearing: number().nullable().meta(readingMeta("angle")),
|
|
64583
65312
|
/** Ms epoch when the slice was last updated. */
|
|
64584
65313
|
lastFetchedAt: number()
|
|
64585
65314
|
});
|
|
@@ -65329,8 +66058,9 @@ method(object({}), array(TrainingBaseModelSchema).readonly(), { auth: "admin" })
|
|
|
65329
66058
|
kind: "mutation",
|
|
65330
66059
|
auth: "admin"
|
|
65331
66060
|
});
|
|
66061
|
+
DeviceFeature.FanSpeed, DeviceFeature.FanPreset, DeviceFeature.FanDirection, DeviceFeature.FanOscillating, DeviceFeature.CoverPositionable, DeviceFeature.CoverTilt, DeviceFeature.ValvePositionable, DeviceFeature.MediaPlayerVolume, DeviceFeature.ClimateFanMode;
|
|
65332
66062
|
SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
|
|
65333
|
-
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.Dishwasher, DeviceType.Camera, DeviceType.Camera, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
|
|
66063
|
+
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.EventEmitter, DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer, DeviceType.Camera, DeviceType.Camera, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
|
|
65334
66064
|
String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
|
|
65335
66065
|
DeviceRole.BinarySensor, DeviceRole.MotionSensor;
|
|
65336
66066
|
new Set(CAP_NAMES);
|
|
@@ -65383,7 +66113,7 @@ var AccessoryKind = {
|
|
|
65383
66113
|
PrivacyMask: DeviceRole.PrivacyMask
|
|
65384
66114
|
};
|
|
65385
66115
|
AccessoryKind.Siren, AccessoryKind.Floodlight, AccessoryKind.Spotlight, AccessoryKind.PirSensor, AccessoryKind.Chime, AccessoryKind.Autotrack, AccessoryKind.Nightvision, AccessoryKind.PrivacyMask;
|
|
65386
|
-
DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Camera, DeviceType.Hub, DeviceType.Switch, DeviceType.Siren, DeviceType.Light, DeviceType.Fan, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.Dishwasher;
|
|
66116
|
+
DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Camera, DeviceType.Hub, DeviceType.Switch, DeviceType.Siren, DeviceType.Light, DeviceType.Fan, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer;
|
|
65387
66117
|
new Set(Object.values(DeviceType));
|
|
65388
66118
|
Object.freeze({
|
|
65389
66119
|
"accessories.getStatus": {
|
|
@@ -65491,6 +66221,13 @@ Object.freeze({
|
|
|
65491
66221
|
access: "view",
|
|
65492
66222
|
role: "admin"
|
|
65493
66223
|
},
|
|
66224
|
+
"addons.getPackageDocs": {
|
|
66225
|
+
capName: "addons",
|
|
66226
|
+
capScope: "system",
|
|
66227
|
+
addonId: null,
|
|
66228
|
+
access: "view",
|
|
66229
|
+
role: "admin"
|
|
66230
|
+
},
|
|
65494
66231
|
"addons.getVersions": {
|
|
65495
66232
|
capName: "addons",
|
|
65496
66233
|
capScope: "system",
|
|
@@ -68599,6 +69336,27 @@ Object.freeze({
|
|
|
68599
69336
|
access: "view",
|
|
68600
69337
|
role: "viewer"
|
|
68601
69338
|
},
|
|
69339
|
+
"groupActive.getStatus": {
|
|
69340
|
+
capName: "group-active",
|
|
69341
|
+
capScope: "device",
|
|
69342
|
+
addonId: null,
|
|
69343
|
+
access: "view",
|
|
69344
|
+
role: "viewer"
|
|
69345
|
+
},
|
|
69346
|
+
"groupCommands.getStatus": {
|
|
69347
|
+
capName: "group-commands",
|
|
69348
|
+
capScope: "device",
|
|
69349
|
+
addonId: null,
|
|
69350
|
+
access: "view",
|
|
69351
|
+
role: "viewer"
|
|
69352
|
+
},
|
|
69353
|
+
"groupStatus.getStatus": {
|
|
69354
|
+
capName: "group-status",
|
|
69355
|
+
capScope: "device",
|
|
69356
|
+
addonId: null,
|
|
69357
|
+
access: "view",
|
|
69358
|
+
role: "viewer"
|
|
69359
|
+
},
|
|
68602
69360
|
"heatingValve.getStatus": {
|
|
68603
69361
|
capName: "heating-valve",
|
|
68604
69362
|
capScope: "device",
|
|
@@ -69551,6 +70309,13 @@ Object.freeze({
|
|
|
69551
70309
|
access: "create",
|
|
69552
70310
|
role: "admin"
|
|
69553
70311
|
},
|
|
70312
|
+
"meter.getStatus": {
|
|
70313
|
+
capName: "meter",
|
|
70314
|
+
capScope: "device",
|
|
70315
|
+
addonId: null,
|
|
70316
|
+
access: "view",
|
|
70317
|
+
role: "viewer"
|
|
70318
|
+
},
|
|
69554
70319
|
"metricsProvider.collectSnapshot": {
|
|
69555
70320
|
capName: "metrics-provider",
|
|
69556
70321
|
capScope: "system",
|
|
@@ -77649,7 +78414,39 @@ var APPLIANCE_CAP_VOCABULARY = {
|
|
|
77649
78414
|
phrase: t("When {device} finishes", "Quando {device} finisce"),
|
|
77650
78415
|
icon: "square"
|
|
77651
78416
|
}
|
|
77652
|
-
}
|
|
78417
|
+
},
|
|
78418
|
+
overrides: { byType: {
|
|
78419
|
+
[DeviceType.Washer]: {
|
|
78420
|
+
state: { running: {
|
|
78421
|
+
whenTrue: t("When the washing machine starts", "Quando la lavatrice inizia"),
|
|
78422
|
+
whenFalse: t("When the washing machine has finished", "Quando la lavatrice ha finito")
|
|
78423
|
+
} },
|
|
78424
|
+
events: {
|
|
78425
|
+
onStarted: { phrase: t("When the washing machine starts", "Quando la lavatrice inizia") },
|
|
78426
|
+
onFinished: { phrase: t("When the washing machine has finished", "Quando la lavatrice ha finito") }
|
|
78427
|
+
}
|
|
78428
|
+
},
|
|
78429
|
+
[DeviceType.Dryer]: {
|
|
78430
|
+
state: { running: {
|
|
78431
|
+
whenTrue: t("When the dryer starts", "Quando l'asciugatrice inizia"),
|
|
78432
|
+
whenFalse: t("When the dryer has finished", "Quando l'asciugatrice ha finito")
|
|
78433
|
+
} },
|
|
78434
|
+
events: {
|
|
78435
|
+
onStarted: { phrase: t("When the dryer starts", "Quando l'asciugatrice inizia") },
|
|
78436
|
+
onFinished: { phrase: t("When the dryer has finished", "Quando l'asciugatrice ha finito") }
|
|
78437
|
+
}
|
|
78438
|
+
},
|
|
78439
|
+
[DeviceType.Dishwasher]: {
|
|
78440
|
+
state: { running: {
|
|
78441
|
+
whenTrue: t("When the dishwasher starts", "Quando la lavastoviglie inizia"),
|
|
78442
|
+
whenFalse: t("When the dishwasher has finished", "Quando la lavastoviglie ha finito")
|
|
78443
|
+
} },
|
|
78444
|
+
events: {
|
|
78445
|
+
onStarted: { phrase: t("When the dishwasher starts", "Quando la lavastoviglie inizia") },
|
|
78446
|
+
onFinished: { phrase: t("When the dishwasher has finished", "Quando la lavastoviglie ha finito") }
|
|
78447
|
+
}
|
|
78448
|
+
}
|
|
78449
|
+
} }
|
|
77653
78450
|
},
|
|
77654
78451
|
update: {
|
|
77655
78452
|
scope: "device",
|
|
@@ -78421,6 +79218,41 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78421
79218
|
icon: "flame"
|
|
78422
79219
|
}]
|
|
78423
79220
|
},
|
|
79221
|
+
"group-active": {
|
|
79222
|
+
scope: "device",
|
|
79223
|
+
noun: t("Group state", "Stato del gruppo")
|
|
79224
|
+
},
|
|
79225
|
+
"group-commands": {
|
|
79226
|
+
scope: "device",
|
|
79227
|
+
noun: t("Group command", "Comando di gruppo")
|
|
79228
|
+
},
|
|
79229
|
+
"group-status": {
|
|
79230
|
+
scope: "device",
|
|
79231
|
+
noun: t("Group", "Gruppo"),
|
|
79232
|
+
state: [
|
|
79233
|
+
{
|
|
79234
|
+
kind: "numeric",
|
|
79235
|
+
field: "included",
|
|
79236
|
+
quantity: t("the members reporting", "i membri che rispondono"),
|
|
79237
|
+
label: t("Reporting", "Rispondono"),
|
|
79238
|
+
icon: "users"
|
|
79239
|
+
},
|
|
79240
|
+
{
|
|
79241
|
+
kind: "numeric",
|
|
79242
|
+
field: "excluded",
|
|
79243
|
+
quantity: t("the members left out", "i membri esclusi"),
|
|
79244
|
+
label: t("Excluded", "Esclusi"),
|
|
79245
|
+
icon: "users"
|
|
79246
|
+
},
|
|
79247
|
+
{
|
|
79248
|
+
kind: "numeric",
|
|
79249
|
+
field: "total",
|
|
79250
|
+
quantity: t("the member count", "il numero di membri"),
|
|
79251
|
+
label: t("Members", "Membri"),
|
|
79252
|
+
icon: "sigma"
|
|
79253
|
+
}
|
|
79254
|
+
]
|
|
79255
|
+
},
|
|
78424
79256
|
"humidity-sensor": {
|
|
78425
79257
|
scope: "device",
|
|
78426
79258
|
noun: t("Humidity", "Umidità"),
|
|
@@ -78446,6 +79278,17 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78446
79278
|
}],
|
|
78447
79279
|
events: { onMotionChanged: { notOperatorFacing: "the `detected` state trigger phrases both edges, from the mirror that survives a dropped event (D49)" } }
|
|
78448
79280
|
},
|
|
79281
|
+
meter: {
|
|
79282
|
+
scope: "device",
|
|
79283
|
+
noun: t("Meter", "Contatore"),
|
|
79284
|
+
state: [{
|
|
79285
|
+
kind: "numeric",
|
|
79286
|
+
field: "value",
|
|
79287
|
+
quantity: t("the total", "il totale"),
|
|
79288
|
+
label: t("Total", "Totale"),
|
|
79289
|
+
icon: "gauge"
|
|
79290
|
+
}]
|
|
79291
|
+
},
|
|
78449
79292
|
"numeric-sensor": {
|
|
78450
79293
|
scope: "device",
|
|
78451
79294
|
noun: t("Sensor", "Sensore"),
|
|
@@ -78454,7 +79297,6 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78454
79297
|
field: "value",
|
|
78455
79298
|
quantity: t("the reading", "il valore"),
|
|
78456
79299
|
label: t("Reading", "Valore"),
|
|
78457
|
-
unitField: "unit",
|
|
78458
79300
|
icon: "gauge"
|
|
78459
79301
|
}]
|
|
78460
79302
|
},
|
|
@@ -78590,7 +79432,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78590
79432
|
field: "temperature",
|
|
78591
79433
|
quantity: t("the outdoor temperature", "la temperatura esterna"),
|
|
78592
79434
|
label: t("Temperature", "Temperatura"),
|
|
78593
|
-
|
|
79435
|
+
unit: "°C",
|
|
78594
79436
|
icon: "thermometer"
|
|
78595
79437
|
},
|
|
78596
79438
|
{
|
|
@@ -78606,7 +79448,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78606
79448
|
field: "windSpeed",
|
|
78607
79449
|
quantity: t("the wind speed", "la velocità del vento"),
|
|
78608
79450
|
label: t("Wind", "Vento"),
|
|
78609
|
-
|
|
79451
|
+
unit: "m/s",
|
|
78610
79452
|
icon: "wind"
|
|
78611
79453
|
},
|
|
78612
79454
|
{
|
|
@@ -78614,7 +79456,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78614
79456
|
field: "pressure",
|
|
78615
79457
|
quantity: t("the air pressure", "la pressione atmosferica"),
|
|
78616
79458
|
label: t("Pressure", "Pressione"),
|
|
78617
|
-
|
|
79459
|
+
unit: "hPa",
|
|
78618
79460
|
icon: "gauge"
|
|
78619
79461
|
}
|
|
78620
79462
|
]
|
|
@@ -78919,8 +79761,47 @@ function projectAction(cap, action) {
|
|
|
78919
79761
|
};
|
|
78920
79762
|
}
|
|
78921
79763
|
Object.entries(CAP_VOCABULARY_BY_NAME).flatMap(([cap, entry]) => entry.scope === "device" ? (entry.actions ?? []).map((a) => projectAction(cap, a)) : []);
|
|
78922
|
-
DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.Dishwasher;
|
|
79764
|
+
DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer;
|
|
78923
79765
|
DeviceFeature.BatteryOperated;
|
|
79766
|
+
DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher;
|
|
79767
|
+
var HA_AS = "a power sensor (device_class power). Home Assistant has no laundry domain. running-state stays unexported until a null reading can be published as unavailable.";
|
|
79768
|
+
var HOMEKIT_REASON = "HomeKit has no laundry-appliance service. The export tab would pair an accessory with nothing on it: running-state is withheld until a null reading can be unavailable, and power is not a HomeKit service this export honours.";
|
|
79769
|
+
var ALEXA_REASON = "Alexa has no laundry category in this export, and neither power nor running has an Alexa interface.";
|
|
79770
|
+
var GOOGLE_REASON = "Google WASHER, DRYER and DISHWASHER require RunCycle. A power threshold is not that trait, and this export does not publish RunCycle.";
|
|
79771
|
+
var MATTER_REASON = "No Matter export is built. The closest device types are Laundry Washer (0x0073) and Laundry Dryer (0x0074); a power threshold is not the Laundry Washer Mode cluster.";
|
|
79772
|
+
function withheld(reason) {
|
|
79773
|
+
return {
|
|
79774
|
+
[DeviceType.Washer]: {
|
|
79775
|
+
exported: false,
|
|
79776
|
+
reason
|
|
79777
|
+
},
|
|
79778
|
+
[DeviceType.Dryer]: {
|
|
79779
|
+
exported: false,
|
|
79780
|
+
reason
|
|
79781
|
+
},
|
|
79782
|
+
[DeviceType.Dishwasher]: {
|
|
79783
|
+
exported: false,
|
|
79784
|
+
reason
|
|
79785
|
+
}
|
|
79786
|
+
};
|
|
79787
|
+
}
|
|
79788
|
+
function offered(received) {
|
|
79789
|
+
return {
|
|
79790
|
+
[DeviceType.Washer]: {
|
|
79791
|
+
exported: true,
|
|
79792
|
+
as: received
|
|
79793
|
+
},
|
|
79794
|
+
[DeviceType.Dryer]: {
|
|
79795
|
+
exported: true,
|
|
79796
|
+
as: received
|
|
79797
|
+
},
|
|
79798
|
+
[DeviceType.Dishwasher]: {
|
|
79799
|
+
exported: true,
|
|
79800
|
+
as: received
|
|
79801
|
+
}
|
|
79802
|
+
};
|
|
79803
|
+
}
|
|
79804
|
+
offered(HA_AS), withheld(HOMEKIT_REASON), withheld(ALEXA_REASON), withheld(GOOGLE_REASON), withheld(MATTER_REASON);
|
|
78924
79805
|
Object.freeze({
|
|
78925
79806
|
"accessories.getStatus": [{
|
|
78926
79807
|
name: "deviceId",
|
|
@@ -79887,6 +80768,21 @@ Object.freeze({
|
|
|
79887
80768
|
form: "single",
|
|
79888
80769
|
optional: false
|
|
79889
80770
|
}],
|
|
80771
|
+
"groupActive.getStatus": [{
|
|
80772
|
+
name: "deviceId",
|
|
80773
|
+
form: "single",
|
|
80774
|
+
optional: false
|
|
80775
|
+
}],
|
|
80776
|
+
"groupCommands.getStatus": [{
|
|
80777
|
+
name: "deviceId",
|
|
80778
|
+
form: "single",
|
|
80779
|
+
optional: false
|
|
80780
|
+
}],
|
|
80781
|
+
"groupStatus.getStatus": [{
|
|
80782
|
+
name: "deviceId",
|
|
80783
|
+
form: "single",
|
|
80784
|
+
optional: false
|
|
80785
|
+
}],
|
|
79890
80786
|
"heatingValve.getStatus": [{
|
|
79891
80787
|
name: "deviceId",
|
|
79892
80788
|
form: "single",
|
|
@@ -80087,6 +80983,11 @@ Object.freeze({
|
|
|
80087
80983
|
form: "single",
|
|
80088
80984
|
optional: false
|
|
80089
80985
|
}],
|
|
80986
|
+
"meter.getStatus": [{
|
|
80987
|
+
name: "deviceId",
|
|
80988
|
+
form: "single",
|
|
80989
|
+
optional: false
|
|
80990
|
+
}],
|
|
80090
80991
|
"motion.getStatus": [{
|
|
80091
80992
|
name: "deviceId",
|
|
80092
80993
|
form: "single",
|
|
@@ -81694,7 +82595,6 @@ Object.freeze({
|
|
|
81694
82595
|
"network-access": "ingress",
|
|
81695
82596
|
"smtp-provider": "email"
|
|
81696
82597
|
});
|
|
81697
|
-
DeviceType.Camera;
|
|
81698
82598
|
/**
|
|
81699
82599
|
* A saved Customize assignment (D936). The schema is the type: callers use
|
|
81700
82600
|
* `z.infer`, they do not restate the shape.
|
|
@@ -81871,6 +82771,8 @@ new Map(Object.entries({
|
|
|
81871
82771
|
"detection-blind": "device-events",
|
|
81872
82772
|
"motion-noisy": "device-events",
|
|
81873
82773
|
"motion-calm": "device-events",
|
|
82774
|
+
"package-llm-silent": "device-events",
|
|
82775
|
+
"package-llm-answered": "device-events",
|
|
81874
82776
|
"recording-stalled": "device-events",
|
|
81875
82777
|
"recording-healthy": "device-events",
|
|
81876
82778
|
"recording-degraded": "device-events",
|
|
@@ -81954,6 +82856,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
|
|
|
81954
82856
|
label: "Motion without a subject",
|
|
81955
82857
|
kinds: ["motion-noisy", "motion-calm"]
|
|
81956
82858
|
},
|
|
82859
|
+
{
|
|
82860
|
+
id: "package-llm",
|
|
82861
|
+
family: "device-events",
|
|
82862
|
+
label: "Package confirm",
|
|
82863
|
+
kinds: ["package-llm-silent", "package-llm-answered"]
|
|
82864
|
+
},
|
|
81957
82865
|
{
|
|
81958
82866
|
id: "recording",
|
|
81959
82867
|
family: "device-events",
|
|
@@ -82135,6 +83043,8 @@ var DEVICE_EVENTS = [
|
|
|
82135
83043
|
"detection-blind",
|
|
82136
83044
|
"motion-noisy",
|
|
82137
83045
|
"motion-calm",
|
|
83046
|
+
"package-llm-silent",
|
|
83047
|
+
"package-llm-answered",
|
|
82138
83048
|
"recording-stalled",
|
|
82139
83049
|
"recording-healthy",
|
|
82140
83050
|
"recording-degraded",
|
|
@@ -82403,6 +83313,15 @@ new Map([
|
|
|
82403
83313
|
snapshotLabel: "Cameras with constant motion now",
|
|
82404
83314
|
snapshotSection: null
|
|
82405
83315
|
},
|
|
83316
|
+
{
|
|
83317
|
+
id: "package-llm-confirm",
|
|
83318
|
+
family: "device-events",
|
|
83319
|
+
label: "Package confirm (not answering / answering again)",
|
|
83320
|
+
bad: ["package-llm-silent"],
|
|
83321
|
+
recovery: ["package-llm-answered"],
|
|
83322
|
+
snapshotLabel: "Cameras whose package confirm is not answering",
|
|
83323
|
+
snapshotSection: null
|
|
83324
|
+
},
|
|
82406
83325
|
{
|
|
82407
83326
|
id: "recording-health",
|
|
82408
83327
|
family: "device-events",
|