@camstack/addon-provider-onvif 1.2.148 → 1.2.150
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 +34 -0
- package/dist/addon.js +1366 -447
- package/dist/addon.mjs +1366 -447
- package/package.json +5 -3
package/dist/addon.js
CHANGED
|
@@ -2,7 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
2
2
|
//#region \0rolldown/runtime.js
|
|
3
3
|
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
|
|
4
4
|
//#endregion
|
|
5
|
-
//#region ../types/dist/event-category-
|
|
5
|
+
//#region ../types/dist/event-category-CT-hz5Rb.mjs
|
|
6
6
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
7
7
|
EventCategory["SystemBoot"] = "system.boot";
|
|
8
8
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -328,6 +328,14 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
328
328
|
/** The recovery edge of {@link PipelineMotionNoisy}: the motion fell back, or a detection arrived. */
|
|
329
329
|
EventCategory["PipelineMotionCalm"] = "pipeline.motion-calm";
|
|
330
330
|
/**
|
|
331
|
+
* A camera's package LLM confirm has failed closed three times in a row
|
|
332
|
+
* (D931, 2026-10-26). One edge per camera until
|
|
333
|
+
* {@link PipelinePackageLlmAnswered}.
|
|
334
|
+
*/
|
|
335
|
+
EventCategory["PipelinePackageLlmSilent"] = "pipeline.package-llm-silent";
|
|
336
|
+
/** The recovery edge of {@link PipelinePackageLlmSilent}: a confirm returned yes or no. */
|
|
337
|
+
EventCategory["PipelinePackageLlmAnswered"] = "pipeline.package-llm-answered";
|
|
338
|
+
/**
|
|
331
339
|
* Per-camera pipeline config was mutated by the orchestrator
|
|
332
340
|
* (a settings change via `setAgentInferenceDevices` /
|
|
333
341
|
* `setCameraStepToggle` / `setCameraStepSettings`). Orchestrator
|
|
@@ -5437,7 +5445,7 @@ var ZodIssueCode = {
|
|
|
5437
5445
|
var ZodFirstPartyTypeKind;
|
|
5438
5446
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5439
5447
|
//#endregion
|
|
5440
|
-
//#region ../types/dist/sleep
|
|
5448
|
+
//#region ../types/dist/sleep--jXS9hWo.mjs
|
|
5441
5449
|
/**
|
|
5442
5450
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5443
5451
|
* window to float samples (D455).
|
|
@@ -7924,6 +7932,99 @@ var RecordKindDeclarationSchema = object({
|
|
|
7924
7932
|
}).strict();
|
|
7925
7933
|
/** The kind names: lower-case, dash separated, short enough for an index name. */
|
|
7926
7934
|
var RecordKindNameSchema = string().regex(/^[a-z][a-z0-9-]{0,47}$/);
|
|
7935
|
+
var READING_QUANTITIES = [
|
|
7936
|
+
"temperature",
|
|
7937
|
+
"pressure",
|
|
7938
|
+
"speed",
|
|
7939
|
+
"precipitation",
|
|
7940
|
+
"precipitation-rate",
|
|
7941
|
+
"length",
|
|
7942
|
+
"area",
|
|
7943
|
+
"illuminance",
|
|
7944
|
+
"irradiance",
|
|
7945
|
+
"power",
|
|
7946
|
+
"energy",
|
|
7947
|
+
"voltage",
|
|
7948
|
+
"current",
|
|
7949
|
+
"apparent-power",
|
|
7950
|
+
"humidity",
|
|
7951
|
+
"percentage",
|
|
7952
|
+
"concentration-volume",
|
|
7953
|
+
"concentration-mass",
|
|
7954
|
+
"concentration-ppb",
|
|
7955
|
+
"volume",
|
|
7956
|
+
"duration",
|
|
7957
|
+
"duration-ms",
|
|
7958
|
+
"information",
|
|
7959
|
+
"sound-level",
|
|
7960
|
+
"signal-level",
|
|
7961
|
+
"colour-temperature",
|
|
7962
|
+
"angle",
|
|
7963
|
+
"bitrate",
|
|
7964
|
+
"rate",
|
|
7965
|
+
"mass",
|
|
7966
|
+
"index",
|
|
7967
|
+
"ratio",
|
|
7968
|
+
"count",
|
|
7969
|
+
"none",
|
|
7970
|
+
"device"
|
|
7971
|
+
];
|
|
7972
|
+
var ReadingQuantitySchema = _enum(READING_QUANTITIES);
|
|
7973
|
+
new Set(READING_QUANTITIES);
|
|
7974
|
+
/**
|
|
7975
|
+
* Stored unit symbol for a quantity. `none` means the number is dimensionless
|
|
7976
|
+
* (or an index / ratio / count). `device` means the cap has no single unit.
|
|
7977
|
+
*/
|
|
7978
|
+
var QUANTITY_BASE = {
|
|
7979
|
+
temperature: "°C",
|
|
7980
|
+
pressure: "hPa",
|
|
7981
|
+
speed: "m/s",
|
|
7982
|
+
precipitation: "mm",
|
|
7983
|
+
"precipitation-rate": "mm/h",
|
|
7984
|
+
length: "m",
|
|
7985
|
+
area: "m²",
|
|
7986
|
+
illuminance: "lx",
|
|
7987
|
+
irradiance: "W/m²",
|
|
7988
|
+
power: "W",
|
|
7989
|
+
energy: "kWh",
|
|
7990
|
+
voltage: "V",
|
|
7991
|
+
current: "A",
|
|
7992
|
+
"apparent-power": "VA",
|
|
7993
|
+
humidity: "%",
|
|
7994
|
+
percentage: "%",
|
|
7995
|
+
"concentration-volume": "ppm",
|
|
7996
|
+
"concentration-mass": "µg/m³",
|
|
7997
|
+
"concentration-ppb": "ppb",
|
|
7998
|
+
volume: "L",
|
|
7999
|
+
duration: "s",
|
|
8000
|
+
"duration-ms": "ms",
|
|
8001
|
+
information: "B",
|
|
8002
|
+
"sound-level": "dBFS",
|
|
8003
|
+
"signal-level": "dBm",
|
|
8004
|
+
"colour-temperature": "mired",
|
|
8005
|
+
angle: "°",
|
|
8006
|
+
bitrate: "kbps",
|
|
8007
|
+
rate: "fps",
|
|
8008
|
+
mass: "kg",
|
|
8009
|
+
index: "none",
|
|
8010
|
+
ratio: "none",
|
|
8011
|
+
count: "none",
|
|
8012
|
+
none: "none",
|
|
8013
|
+
device: "device"
|
|
8014
|
+
};
|
|
8015
|
+
/** The stored unit, or `undefined` when the quantity has no unit symbol. */
|
|
8016
|
+
function baseUnitOf(quantity) {
|
|
8017
|
+
const symbol = QUANTITY_BASE[quantity];
|
|
8018
|
+
if (symbol === "none" || symbol === "device") return void 0;
|
|
8019
|
+
return symbol;
|
|
8020
|
+
}
|
|
8021
|
+
function readingMeta(quantity, extras) {
|
|
8022
|
+
return {
|
|
8023
|
+
quantity,
|
|
8024
|
+
...extras?.precision !== void 0 ? { precision: extras.precision } : {},
|
|
8025
|
+
...extras?.label !== void 0 ? { label: extras.label } : {}
|
|
8026
|
+
};
|
|
8027
|
+
}
|
|
7927
8028
|
/** Shared Zod schemas used across streaming capabilities. */
|
|
7928
8029
|
var CamProfileSchema = _enum([
|
|
7929
8030
|
"high",
|
|
@@ -7951,8 +8052,8 @@ var CamStreamKindSchema = _enum([
|
|
|
7951
8052
|
"derived"
|
|
7952
8053
|
]);
|
|
7953
8054
|
var CamStreamResolutionSchema = object({
|
|
7954
|
-
width: number().int().positive(),
|
|
7955
|
-
height: number().int().positive()
|
|
8055
|
+
width: number().int().positive().meta(readingMeta("none")),
|
|
8056
|
+
height: number().int().positive().meta(readingMeta("none"))
|
|
7956
8057
|
});
|
|
7957
8058
|
var CameraStreamSchema = object({
|
|
7958
8059
|
/** Stable, provider-assigned id unique within the (deviceId) scope. */
|
|
@@ -8466,6 +8567,9 @@ var CAP_NAMES = Object.freeze([
|
|
|
8466
8567
|
"filesystem-browse",
|
|
8467
8568
|
"flood",
|
|
8468
8569
|
"gas",
|
|
8570
|
+
"group-active",
|
|
8571
|
+
"group-commands",
|
|
8572
|
+
"group-status",
|
|
8469
8573
|
"heating-valve",
|
|
8470
8574
|
"humidifier",
|
|
8471
8575
|
"humidity-sensor",
|
|
@@ -8486,6 +8590,7 @@ var CAP_NAMES = Object.freeze([
|
|
|
8486
8590
|
"login-method",
|
|
8487
8591
|
"media-player",
|
|
8488
8592
|
"mesh-network",
|
|
8593
|
+
"meter",
|
|
8489
8594
|
"metrics-provider",
|
|
8490
8595
|
"model-convert",
|
|
8491
8596
|
"model-distributor",
|
|
@@ -8595,14 +8700,6 @@ Object.freeze({
|
|
|
8595
8700
|
{
|
|
8596
8701
|
"path": "aqi",
|
|
8597
8702
|
"valueType": "number"
|
|
8598
|
-
},
|
|
8599
|
-
{
|
|
8600
|
-
"path": "unit",
|
|
8601
|
-
"valueType": "string"
|
|
8602
|
-
},
|
|
8603
|
-
{
|
|
8604
|
-
"path": "precision",
|
|
8605
|
-
"valueType": "number"
|
|
8606
8703
|
}
|
|
8607
8704
|
],
|
|
8608
8705
|
"alarm-panel": [
|
|
@@ -8638,20 +8735,10 @@ Object.freeze({
|
|
|
8638
8735
|
"valueType": "boolean"
|
|
8639
8736
|
}
|
|
8640
8737
|
],
|
|
8641
|
-
"ambient-light-sensor": [
|
|
8642
|
-
|
|
8643
|
-
|
|
8644
|
-
|
|
8645
|
-
},
|
|
8646
|
-
{
|
|
8647
|
-
"path": "unit",
|
|
8648
|
-
"valueType": "string"
|
|
8649
|
-
},
|
|
8650
|
-
{
|
|
8651
|
-
"path": "precision",
|
|
8652
|
-
"valueType": "number"
|
|
8653
|
-
}
|
|
8654
|
-
],
|
|
8738
|
+
"ambient-light-sensor": [{
|
|
8739
|
+
"path": "lux",
|
|
8740
|
+
"valueType": "number"
|
|
8741
|
+
}],
|
|
8655
8742
|
"audio-metrics": [
|
|
8656
8743
|
{
|
|
8657
8744
|
"path": "ts",
|
|
@@ -8731,6 +8818,10 @@ Object.freeze({
|
|
|
8731
8818
|
"path": "lastUpdated",
|
|
8732
8819
|
"valueType": "number"
|
|
8733
8820
|
},
|
|
8821
|
+
{
|
|
8822
|
+
"path": "volts",
|
|
8823
|
+
"valueType": "number"
|
|
8824
|
+
},
|
|
8734
8825
|
{
|
|
8735
8826
|
"path": "lastContactAt",
|
|
8736
8827
|
"valueType": "number"
|
|
@@ -8973,10 +9064,6 @@ Object.freeze({
|
|
|
8973
9064
|
"datetime"
|
|
8974
9065
|
]
|
|
8975
9066
|
},
|
|
8976
|
-
{
|
|
8977
|
-
"path": "unit",
|
|
8978
|
-
"valueType": "string"
|
|
8979
|
-
},
|
|
8980
9067
|
{
|
|
8981
9068
|
"path": "min",
|
|
8982
9069
|
"valueType": "number"
|
|
@@ -8988,19 +9075,6 @@ Object.freeze({
|
|
|
8988
9075
|
{
|
|
8989
9076
|
"path": "step",
|
|
8990
9077
|
"valueType": "number"
|
|
8991
|
-
},
|
|
8992
|
-
{
|
|
8993
|
-
"path": "precision",
|
|
8994
|
-
"valueType": "number"
|
|
8995
|
-
},
|
|
8996
|
-
{
|
|
8997
|
-
"path": "format",
|
|
8998
|
-
"valueType": "enum",
|
|
8999
|
-
"enumValues": [
|
|
9000
|
-
"date",
|
|
9001
|
-
"time",
|
|
9002
|
-
"datetime"
|
|
9003
|
-
]
|
|
9004
9078
|
}
|
|
9005
9079
|
],
|
|
9006
9080
|
"cover": [
|
|
@@ -9241,13 +9315,8 @@ Object.freeze({
|
|
|
9241
9315
|
"path": "value",
|
|
9242
9316
|
"valueType": "string"
|
|
9243
9317
|
}, {
|
|
9244
|
-
"path": "
|
|
9245
|
-
"valueType": "
|
|
9246
|
-
"enumValues": [
|
|
9247
|
-
"date",
|
|
9248
|
-
"time",
|
|
9249
|
-
"datetime"
|
|
9250
|
-
]
|
|
9318
|
+
"path": "timestamp",
|
|
9319
|
+
"valueType": "boolean"
|
|
9251
9320
|
}],
|
|
9252
9321
|
"event-emitter": [
|
|
9253
9322
|
{
|
|
@@ -9320,6 +9389,24 @@ Object.freeze({
|
|
|
9320
9389
|
"path": "detected",
|
|
9321
9390
|
"valueType": "boolean"
|
|
9322
9391
|
}],
|
|
9392
|
+
"group-active": [{
|
|
9393
|
+
"path": "active",
|
|
9394
|
+
"valueType": "boolean"
|
|
9395
|
+
}],
|
|
9396
|
+
"group-status": [
|
|
9397
|
+
{
|
|
9398
|
+
"path": "included",
|
|
9399
|
+
"valueType": "number"
|
|
9400
|
+
},
|
|
9401
|
+
{
|
|
9402
|
+
"path": "excluded",
|
|
9403
|
+
"valueType": "number"
|
|
9404
|
+
},
|
|
9405
|
+
{
|
|
9406
|
+
"path": "total",
|
|
9407
|
+
"valueType": "number"
|
|
9408
|
+
}
|
|
9409
|
+
],
|
|
9323
9410
|
"heating-valve": [{
|
|
9324
9411
|
"path": "position",
|
|
9325
9412
|
"valueType": "number"
|
|
@@ -9354,20 +9441,10 @@ Object.freeze({
|
|
|
9354
9441
|
"valueType": "number"
|
|
9355
9442
|
}
|
|
9356
9443
|
],
|
|
9357
|
-
"humidity-sensor": [
|
|
9358
|
-
|
|
9359
|
-
|
|
9360
|
-
|
|
9361
|
-
},
|
|
9362
|
-
{
|
|
9363
|
-
"path": "unit",
|
|
9364
|
-
"valueType": "string"
|
|
9365
|
-
},
|
|
9366
|
-
{
|
|
9367
|
-
"path": "precision",
|
|
9368
|
-
"valueType": "number"
|
|
9369
|
-
}
|
|
9370
|
-
],
|
|
9444
|
+
"humidity-sensor": [{
|
|
9445
|
+
"path": "percent",
|
|
9446
|
+
"valueType": "number"
|
|
9447
|
+
}],
|
|
9371
9448
|
"image": [{
|
|
9372
9449
|
"path": "url",
|
|
9373
9450
|
"valueType": "string"
|
|
@@ -9575,6 +9652,10 @@ Object.freeze({
|
|
|
9575
9652
|
]
|
|
9576
9653
|
}
|
|
9577
9654
|
],
|
|
9655
|
+
"meter": [{
|
|
9656
|
+
"path": "value",
|
|
9657
|
+
"valueType": "number"
|
|
9658
|
+
}],
|
|
9578
9659
|
"motion": [
|
|
9579
9660
|
{
|
|
9580
9661
|
"path": "detected",
|
|
@@ -9706,20 +9787,10 @@ Object.freeze({
|
|
|
9706
9787
|
"valueType": "boolean"
|
|
9707
9788
|
}
|
|
9708
9789
|
],
|
|
9709
|
-
"numeric-sensor": [
|
|
9710
|
-
|
|
9711
|
-
|
|
9712
|
-
|
|
9713
|
-
},
|
|
9714
|
-
{
|
|
9715
|
-
"path": "unit",
|
|
9716
|
-
"valueType": "string"
|
|
9717
|
-
},
|
|
9718
|
-
{
|
|
9719
|
-
"path": "precision",
|
|
9720
|
-
"valueType": "number"
|
|
9721
|
-
}
|
|
9722
|
-
],
|
|
9790
|
+
"numeric-sensor": [{
|
|
9791
|
+
"path": "value",
|
|
9792
|
+
"valueType": "number"
|
|
9793
|
+
}],
|
|
9723
9794
|
"pet-feeder": [
|
|
9724
9795
|
{
|
|
9725
9796
|
"path": "foodLevel",
|
|
@@ -9811,14 +9882,6 @@ Object.freeze({
|
|
|
9811
9882
|
{
|
|
9812
9883
|
"path": "powerFactor",
|
|
9813
9884
|
"valueType": "number"
|
|
9814
|
-
},
|
|
9815
|
-
{
|
|
9816
|
-
"path": "unit",
|
|
9817
|
-
"valueType": "string"
|
|
9818
|
-
},
|
|
9819
|
-
{
|
|
9820
|
-
"path": "precision",
|
|
9821
|
-
"valueType": "number"
|
|
9822
9885
|
}
|
|
9823
9886
|
],
|
|
9824
9887
|
"presence": [
|
|
@@ -9847,20 +9910,10 @@ Object.freeze({
|
|
|
9847
9910
|
"valueType": "number"
|
|
9848
9911
|
}
|
|
9849
9912
|
],
|
|
9850
|
-
"pressure-sensor": [
|
|
9851
|
-
|
|
9852
|
-
|
|
9853
|
-
|
|
9854
|
-
},
|
|
9855
|
-
{
|
|
9856
|
-
"path": "unit",
|
|
9857
|
-
"valueType": "string"
|
|
9858
|
-
},
|
|
9859
|
-
{
|
|
9860
|
-
"path": "precision",
|
|
9861
|
-
"valueType": "number"
|
|
9862
|
-
}
|
|
9863
|
-
],
|
|
9913
|
+
"pressure-sensor": [{
|
|
9914
|
+
"path": "hpa",
|
|
9915
|
+
"valueType": "number"
|
|
9916
|
+
}],
|
|
9864
9917
|
"privacy-mask": [{
|
|
9865
9918
|
"path": "enabled",
|
|
9866
9919
|
"valueType": "boolean"
|
|
@@ -10171,20 +10224,10 @@ Object.freeze({
|
|
|
10171
10224
|
"path": "tampered",
|
|
10172
10225
|
"valueType": "boolean"
|
|
10173
10226
|
}],
|
|
10174
|
-
"temperature-sensor": [
|
|
10175
|
-
|
|
10176
|
-
|
|
10177
|
-
|
|
10178
|
-
},
|
|
10179
|
-
{
|
|
10180
|
-
"path": "unit",
|
|
10181
|
-
"valueType": "string"
|
|
10182
|
-
},
|
|
10183
|
-
{
|
|
10184
|
-
"path": "precision",
|
|
10185
|
-
"valueType": "number"
|
|
10186
|
-
}
|
|
10187
|
-
],
|
|
10227
|
+
"temperature-sensor": [{
|
|
10228
|
+
"path": "celsius",
|
|
10229
|
+
"valueType": "number"
|
|
10230
|
+
}],
|
|
10188
10231
|
"update": [
|
|
10189
10232
|
{
|
|
10190
10233
|
"path": "currentVersion",
|
|
@@ -10295,10 +10338,6 @@ Object.freeze({
|
|
|
10295
10338
|
"path": "temperature",
|
|
10296
10339
|
"valueType": "number"
|
|
10297
10340
|
},
|
|
10298
|
-
{
|
|
10299
|
-
"path": "temperatureUnit",
|
|
10300
|
-
"valueType": "string"
|
|
10301
|
-
},
|
|
10302
10341
|
{
|
|
10303
10342
|
"path": "humidity",
|
|
10304
10343
|
"valueType": "number"
|
|
@@ -10307,18 +10346,10 @@ Object.freeze({
|
|
|
10307
10346
|
"path": "pressure",
|
|
10308
10347
|
"valueType": "number"
|
|
10309
10348
|
},
|
|
10310
|
-
{
|
|
10311
|
-
"path": "pressureUnit",
|
|
10312
|
-
"valueType": "string"
|
|
10313
|
-
},
|
|
10314
10349
|
{
|
|
10315
10350
|
"path": "windSpeed",
|
|
10316
10351
|
"valueType": "number"
|
|
10317
10352
|
},
|
|
10318
|
-
{
|
|
10319
|
-
"path": "windSpeedUnit",
|
|
10320
|
-
"valueType": "string"
|
|
10321
|
-
},
|
|
10322
10353
|
{
|
|
10323
10354
|
"path": "windBearing",
|
|
10324
10355
|
"valueType": "number"
|
|
@@ -10368,7 +10399,7 @@ object({
|
|
|
10368
10399
|
params: record(string(), union([string(), number()])).optional()
|
|
10369
10400
|
});
|
|
10370
10401
|
//#endregion
|
|
10371
|
-
//#region ../types/dist/err-msg-
|
|
10402
|
+
//#region ../types/dist/err-msg-DIorGYeC.mjs
|
|
10372
10403
|
var DeviceType = /* @__PURE__ */ function(DeviceType) {
|
|
10373
10404
|
DeviceType["Camera"] = "camera";
|
|
10374
10405
|
DeviceType["Hub"] = "hub";
|
|
@@ -10462,8 +10493,14 @@ var DeviceType = /* @__PURE__ */ function(DeviceType) {
|
|
|
10462
10493
|
DeviceType["PetFeeder"] = "pet-feeder";
|
|
10463
10494
|
/** Built-in dishwasher — program lifecycle, door / remote-start gates,
|
|
10464
10495
|
* salt and rinse-aid levels. Installed with the `dishwasher` cap.
|
|
10465
|
-
* Sources: native Bosch Home Connect, reusable by similar integrations.
|
|
10496
|
+
* Sources: native Bosch Home Connect, reusable by similar integrations.
|
|
10497
|
+
* A plug-built dishwasher carries running-state and power instead. */
|
|
10466
10498
|
DeviceType["Dishwasher"] = "dishwasher";
|
|
10499
|
+
/** Washing machine. A plug-built one is running while its power stays
|
|
10500
|
+
* above a threshold. No program cap — that surface is the dishwasher's. */
|
|
10501
|
+
DeviceType["Washer"] = "washer";
|
|
10502
|
+
/** Tumble dryer. Same plug-built running surface as {@link Washer}. */
|
|
10503
|
+
DeviceType["Dryer"] = "dryer";
|
|
10467
10504
|
return DeviceType;
|
|
10468
10505
|
}({});
|
|
10469
10506
|
var DeviceFeature = /* @__PURE__ */ function(DeviceFeature) {
|
|
@@ -10721,7 +10758,7 @@ function errMsg(err) {
|
|
|
10721
10758
|
return String(err);
|
|
10722
10759
|
}
|
|
10723
10760
|
//#endregion
|
|
10724
|
-
//#region ../types/dist/composition-
|
|
10761
|
+
//#region ../types/dist/composition-Bb8iwHEJ.mjs
|
|
10725
10762
|
/**
|
|
10726
10763
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
10727
10764
|
*
|
|
@@ -11036,6 +11073,13 @@ var table = {
|
|
|
11036
11073
|
apply: () => {
|
|
11037
11074
|
throw new ExpressionEvalError("latchedAt: stateful evaluation context is required");
|
|
11038
11075
|
}
|
|
11076
|
+
},
|
|
11077
|
+
schmitt: {
|
|
11078
|
+
minArgs: 3,
|
|
11079
|
+
maxArgs: 5,
|
|
11080
|
+
apply: () => {
|
|
11081
|
+
throw new ExpressionEvalError("schmitt: stateful evaluation context is required");
|
|
11082
|
+
}
|
|
11039
11083
|
}
|
|
11040
11084
|
};
|
|
11041
11085
|
Object.freeze(Object.assign(Object.create(null), table));
|
|
@@ -11476,15 +11520,232 @@ function validateExpressionSource(src) {
|
|
|
11476
11520
|
}
|
|
11477
11521
|
return null;
|
|
11478
11522
|
}
|
|
11479
|
-
/**
|
|
11480
|
-
|
|
11481
|
-
|
|
11482
|
-
|
|
11523
|
+
/**
|
|
11524
|
+
* One power reading becomes a washer, dryer or dishwasher (D944 helper).
|
|
11525
|
+
*
|
|
11526
|
+
* Standby of the control board is under 5 W; a motor or a heater is far
|
|
11527
|
+
* above that, so 5 W is the line. A door lock or a short pump spike is not
|
|
11528
|
+
* a cycle, so running starts only after 30 s above the line.
|
|
11529
|
+
*
|
|
11530
|
+
* A wash, dry or dishwasher pause (soak, heat-wait, heater off between
|
|
11531
|
+
* bursts) lasts several minutes. Ending the cycle on the first dip would
|
|
11532
|
+
* report "finished" in the middle of the program, so the stop dwell is
|
|
11533
|
+
* 10 minutes on every type. The number is stored per type so one machine
|
|
11534
|
+
* can move later without moving the others.
|
|
11535
|
+
*/
|
|
11536
|
+
var APPLIANCE_TEMPLATE_ID = "appliance";
|
|
11537
|
+
var APPLIANCE_KINDS = [
|
|
11538
|
+
"washer",
|
|
11539
|
+
"dryer",
|
|
11540
|
+
"dishwasher"
|
|
11541
|
+
];
|
|
11542
|
+
DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher;
|
|
11543
|
+
/**
|
|
11544
|
+
* Statistics and integrals over a history read (D944).
|
|
11545
|
+
*
|
|
11546
|
+
* Pure: the same points always give the same answer, so a restart recomputes
|
|
11547
|
+
* rather than trusting a buffer. A gauge mean is time-weighted (value × ms),
|
|
11548
|
+
* never the mean of the samples. A hole with no held value is not integrated
|
|
11549
|
+
* as zero. A truncated read is not published.
|
|
11550
|
+
*/
|
|
11551
|
+
var STATISTIC_STATS = [
|
|
11552
|
+
"min",
|
|
11553
|
+
"max",
|
|
11554
|
+
"mean",
|
|
11555
|
+
"sum",
|
|
11556
|
+
"count",
|
|
11557
|
+
"change"
|
|
11558
|
+
];
|
|
11559
|
+
/**
|
|
11560
|
+
* The range a statistics or integral helper asks history for (D944).
|
|
11561
|
+
*
|
|
11562
|
+
* Calendar edges are the hub's timezone, never UTC midnight: a day is 23, 24
|
|
11563
|
+
* or 25 hours across a DST change. A tier is eligible only when its retention
|
|
11564
|
+
* is strictly longer than the longest that range can be. Forever qualifies.
|
|
11565
|
+
* Equal to a tier's retention is a refusal, not a short answer.
|
|
11566
|
+
*/
|
|
11567
|
+
var MINUTE_MS = 6e4;
|
|
11568
|
+
var HOUR_MS = 60 * MINUTE_MS;
|
|
11569
|
+
var DAY_MS = 24 * HOUR_MS;
|
|
11570
|
+
var ROLLING_SPANS = [
|
|
11571
|
+
"1h",
|
|
11572
|
+
"24h",
|
|
11573
|
+
"2d",
|
|
11574
|
+
"7d",
|
|
11575
|
+
"30d",
|
|
11576
|
+
"custom"
|
|
11577
|
+
];
|
|
11578
|
+
var CALENDAR_PERIODS = [
|
|
11579
|
+
"today",
|
|
11580
|
+
"yesterday",
|
|
11581
|
+
"this-week",
|
|
11582
|
+
"this-month"
|
|
11583
|
+
];
|
|
11584
|
+
var RESET_PERIODS = [
|
|
11585
|
+
"never",
|
|
11586
|
+
"daily",
|
|
11587
|
+
"weekly",
|
|
11588
|
+
"monthly"
|
|
11589
|
+
];
|
|
11590
|
+
5 * MINUTE_MS;
|
|
11591
|
+
24 * HOUR_MS, 2 * DAY_MS, 7 * DAY_MS, 30 * DAY_MS;
|
|
11592
|
+
7 * DAY_MS, 30 * DAY_MS, 365 * DAY_MS;
|
|
11593
|
+
var rollingWindowObject = object({
|
|
11594
|
+
kind: literal("rolling"),
|
|
11595
|
+
span: _enum(ROLLING_SPANS),
|
|
11596
|
+
customMinutes: number().int().min(5).optional()
|
|
11597
|
+
}).check((payload) => {
|
|
11598
|
+
if (payload.value.span === "custom" && payload.value.customMinutes === void 0) payload.issues.push({
|
|
11599
|
+
code: "custom",
|
|
11600
|
+
message: "a custom range needs a duration in minutes",
|
|
11601
|
+
path: ["customMinutes"],
|
|
11602
|
+
input: payload.value
|
|
11603
|
+
});
|
|
11604
|
+
if (payload.value.span !== "custom" && payload.value.customMinutes !== void 0) payload.issues.push({
|
|
11605
|
+
code: "custom",
|
|
11606
|
+
message: "only a custom range carries a duration",
|
|
11607
|
+
path: ["customMinutes"],
|
|
11608
|
+
input: payload.value
|
|
11609
|
+
});
|
|
11610
|
+
});
|
|
11611
|
+
var RollingWindowSchema = rollingWindowObject;
|
|
11612
|
+
var StatisticWindowSchema = discriminatedUnion("kind", [rollingWindowObject, object({
|
|
11613
|
+
kind: literal("calendar"),
|
|
11614
|
+
period: _enum(CALENDAR_PERIODS)
|
|
11615
|
+
})]);
|
|
11616
|
+
/**
|
|
11617
|
+
* A composition source identity: `(addonId, stableId)`, never a numeric device
|
|
11618
|
+
* id. Split out so helper schemas can name it without a cycle through
|
|
11619
|
+
* `composition.ts` (D659).
|
|
11620
|
+
*/
|
|
11483
11621
|
var CompositionSourceRefSchema = object({
|
|
11484
11622
|
/** The owning addon; `stableId` is unique only within it. */
|
|
11485
11623
|
addonId: string().min(1),
|
|
11486
11624
|
stableId: string().min(1)
|
|
11487
11625
|
});
|
|
11626
|
+
var GROUP_TEMPLATE_IDS = [
|
|
11627
|
+
"temperature",
|
|
11628
|
+
"humidity",
|
|
11629
|
+
"pressure",
|
|
11630
|
+
"illuminance",
|
|
11631
|
+
"power",
|
|
11632
|
+
"energy",
|
|
11633
|
+
"battery",
|
|
11634
|
+
"numeric",
|
|
11635
|
+
"motion",
|
|
11636
|
+
"contact",
|
|
11637
|
+
"leak",
|
|
11638
|
+
"smoke",
|
|
11639
|
+
"occupancy",
|
|
11640
|
+
"binary",
|
|
11641
|
+
"switch",
|
|
11642
|
+
"light",
|
|
11643
|
+
"fan",
|
|
11644
|
+
"cover",
|
|
11645
|
+
"valve",
|
|
11646
|
+
"lock",
|
|
11647
|
+
"media-player",
|
|
11648
|
+
"climate"
|
|
11649
|
+
];
|
|
11650
|
+
var NUMERIC_AGGREGATES = [
|
|
11651
|
+
"mean",
|
|
11652
|
+
"median",
|
|
11653
|
+
"min",
|
|
11654
|
+
"max",
|
|
11655
|
+
"sum"
|
|
11656
|
+
];
|
|
11657
|
+
var BINARY_AGGREGATES = ["any", "all"];
|
|
11658
|
+
/** How an actuator group decides it is on. Unknown members never count as off. */
|
|
11659
|
+
var ACTIVE_CRITERIA = ["at-least-one", "all"];
|
|
11660
|
+
var AGGREGATE_REDUCERS = [
|
|
11661
|
+
"mean",
|
|
11662
|
+
"median",
|
|
11663
|
+
"min",
|
|
11664
|
+
"max",
|
|
11665
|
+
"sum",
|
|
11666
|
+
"any",
|
|
11667
|
+
"all"
|
|
11668
|
+
];
|
|
11669
|
+
var GroupTemplateIdSchema = _enum(GROUP_TEMPLATE_IDS);
|
|
11670
|
+
var AggregateReducerSchema = _enum(AGGREGATE_REDUCERS);
|
|
11671
|
+
var ActiveCriterionSchema = _enum(ACTIVE_CRITERIA);
|
|
11672
|
+
/** One member. The field is stored so occupancy can name motion or binary. */
|
|
11673
|
+
var HelperMemberSchema = object({
|
|
11674
|
+
source: CompositionSourceRefSchema,
|
|
11675
|
+
cap: string().min(1),
|
|
11676
|
+
fieldPath: string().min(1)
|
|
11677
|
+
});
|
|
11678
|
+
var HelperSpecSchema = discriminatedUnion("kind", [
|
|
11679
|
+
object({
|
|
11680
|
+
kind: literal("group"),
|
|
11681
|
+
templateId: GroupTemplateIdSchema,
|
|
11682
|
+
aggregate: AggregateReducerSchema,
|
|
11683
|
+
members: array(HelperMemberSchema).min(1).max(64),
|
|
11684
|
+
/** Actuator groups only. Readings leave this unset. */
|
|
11685
|
+
active: ActiveCriterionSchema.optional()
|
|
11686
|
+
}),
|
|
11687
|
+
object({
|
|
11688
|
+
kind: literal("appliance"),
|
|
11689
|
+
templateId: literal(APPLIANCE_TEMPLATE_ID),
|
|
11690
|
+
appliance: _enum(APPLIANCE_KINDS),
|
|
11691
|
+
thresholdWatts: number().positive(),
|
|
11692
|
+
startDwellMs: number().int().nonnegative(),
|
|
11693
|
+
stopDwellMs: number().int().nonnegative(),
|
|
11694
|
+
member: HelperMemberSchema
|
|
11695
|
+
}),
|
|
11696
|
+
object({
|
|
11697
|
+
kind: literal("statistic"),
|
|
11698
|
+
stat: _enum(STATISTIC_STATS),
|
|
11699
|
+
window: StatisticWindowSchema,
|
|
11700
|
+
source: HelperMemberSchema
|
|
11701
|
+
}),
|
|
11702
|
+
object({
|
|
11703
|
+
kind: literal("integral"),
|
|
11704
|
+
reset: _enum(RESET_PERIODS),
|
|
11705
|
+
output: _enum(["energy", "meter"]),
|
|
11706
|
+
source: HelperMemberSchema
|
|
11707
|
+
}),
|
|
11708
|
+
object({
|
|
11709
|
+
kind: literal("threshold"),
|
|
11710
|
+
source: HelperMemberSchema,
|
|
11711
|
+
high: number(),
|
|
11712
|
+
low: number(),
|
|
11713
|
+
onForMs: number().int().nonnegative(),
|
|
11714
|
+
offForMs: number().int().nonnegative()
|
|
11715
|
+
}),
|
|
11716
|
+
object({
|
|
11717
|
+
kind: literal("arithmetic"),
|
|
11718
|
+
op: _enum([
|
|
11719
|
+
"sum",
|
|
11720
|
+
"difference",
|
|
11721
|
+
"ratio"
|
|
11722
|
+
]),
|
|
11723
|
+
inputs: array(HelperMemberSchema).min(2).max(64)
|
|
11724
|
+
}),
|
|
11725
|
+
object({
|
|
11726
|
+
kind: literal("expression"),
|
|
11727
|
+
expr: string().min(1),
|
|
11728
|
+
inputs: array(object({
|
|
11729
|
+
name: string().min(1),
|
|
11730
|
+
member: HelperMemberSchema
|
|
11731
|
+
})).min(1).max(64),
|
|
11732
|
+
output: _enum(["number", "boolean"])
|
|
11733
|
+
}),
|
|
11734
|
+
object({
|
|
11735
|
+
kind: literal("derivative"),
|
|
11736
|
+
window: RollingWindowSchema,
|
|
11737
|
+
per: _enum([
|
|
11738
|
+
"second",
|
|
11739
|
+
"minute",
|
|
11740
|
+
"hour"
|
|
11741
|
+
]),
|
|
11742
|
+
source: HelperMemberSchema
|
|
11743
|
+
})
|
|
11744
|
+
]);
|
|
11745
|
+
/** A composed device's stableId is this prefix plus the block id. */
|
|
11746
|
+
var COMPOSED_DEVICE_STABLE_ID_PREFIX = "composed-";
|
|
11747
|
+
/** Longest snippet a `code` source may carry (slice 4). */
|
|
11748
|
+
var MAX_COMPOSITION_CODE_LENGTH = 2e4;
|
|
11488
11749
|
/** One field of one capability of one source device. */
|
|
11489
11750
|
var CompositionFieldReadSchema = object({
|
|
11490
11751
|
source: CompositionSourceRefSchema,
|
|
@@ -11528,7 +11789,59 @@ var CompositionCodeSourceSchema = object({
|
|
|
11528
11789
|
var CompositionFieldSourceSchema = discriminatedUnion("kind", [
|
|
11529
11790
|
CompositionFromSourceSchema,
|
|
11530
11791
|
CompositionExpressionSourceSchema,
|
|
11531
|
-
CompositionCodeSourceSchema
|
|
11792
|
+
CompositionCodeSourceSchema,
|
|
11793
|
+
object({
|
|
11794
|
+
kind: literal("aggregate"),
|
|
11795
|
+
reducer: _enum([
|
|
11796
|
+
"mean",
|
|
11797
|
+
"median",
|
|
11798
|
+
"min",
|
|
11799
|
+
"max",
|
|
11800
|
+
"sum",
|
|
11801
|
+
"any",
|
|
11802
|
+
"all"
|
|
11803
|
+
]),
|
|
11804
|
+
reads: array(CompositionFieldReadSchema).min(1).max(64),
|
|
11805
|
+
/**
|
|
11806
|
+
* Set when the reads are an enum state, not a yes/no: the listed states
|
|
11807
|
+
* count as active (a cover is `open`). A state outside the list is inactive;
|
|
11808
|
+
* a read that is not a state at all is left out. Only `any` / `all` use it.
|
|
11809
|
+
*/
|
|
11810
|
+
activeWhen: array(string().min(1)).min(1).optional(),
|
|
11811
|
+
/** `value` is the reading; the others are the member counts. */
|
|
11812
|
+
publish: _enum([
|
|
11813
|
+
"value",
|
|
11814
|
+
"included",
|
|
11815
|
+
"excluded",
|
|
11816
|
+
"total"
|
|
11817
|
+
]),
|
|
11818
|
+
/** What a `value` publish does when nobody is included. Counts ignore this. */
|
|
11819
|
+
empty: _enum([
|
|
11820
|
+
"null",
|
|
11821
|
+
"omit",
|
|
11822
|
+
"offline"
|
|
11823
|
+
])
|
|
11824
|
+
}),
|
|
11825
|
+
object({
|
|
11826
|
+
kind: literal("series"),
|
|
11827
|
+
read: CompositionFieldReadSchema,
|
|
11828
|
+
/** `value` is the statistic or the integral. The others are the gap counts. */
|
|
11829
|
+
publish: _enum([
|
|
11830
|
+
"value",
|
|
11831
|
+
"included",
|
|
11832
|
+
"excluded",
|
|
11833
|
+
"total"
|
|
11834
|
+
]),
|
|
11835
|
+
/**
|
|
11836
|
+
* What an unanswered `value` does. Counts ignore this. `offline` leaves the
|
|
11837
|
+
* device unseeded until history answers, so a restart cannot publish 0.
|
|
11838
|
+
*/
|
|
11839
|
+
empty: _enum([
|
|
11840
|
+
"null",
|
|
11841
|
+
"omit",
|
|
11842
|
+
"offline"
|
|
11843
|
+
])
|
|
11844
|
+
})
|
|
11532
11845
|
]);
|
|
11533
11846
|
var CompositionCommandTargetSchema = discriminatedUnion("kind", [object({
|
|
11534
11847
|
kind: literal("forward"),
|
|
@@ -11574,7 +11887,13 @@ var CompositionSchema = object({
|
|
|
11574
11887
|
kind: literal("existing"),
|
|
11575
11888
|
device: CompositionSourceRefSchema
|
|
11576
11889
|
})]),
|
|
11577
|
-
features: array(CompositionFeatureSchema).min(1).max(16)
|
|
11890
|
+
features: array(CompositionFeatureSchema).min(1).max(16),
|
|
11891
|
+
/**
|
|
11892
|
+
* Present when the block is a helper template. Absent on a free
|
|
11893
|
+
* composition (the room example, device 4603). The editor reads this,
|
|
11894
|
+
* never the compiled features.
|
|
11895
|
+
*/
|
|
11896
|
+
helper: HelperSpecSchema.optional()
|
|
11578
11897
|
}).superRefine((composition, ctx) => {
|
|
11579
11898
|
const seen = /* @__PURE__ */ new Set();
|
|
11580
11899
|
composition.features.forEach((feature, index) => {
|
|
@@ -16681,7 +17000,22 @@ var BrokerProviderInfoSchema = object({
|
|
|
16681
17000
|
*/
|
|
16682
17001
|
interactiveConnectPath: string().min(1).optional(),
|
|
16683
17002
|
/** Relative hub path to disconnect the linked account (same popup pattern). */
|
|
16684
|
-
interactiveDisconnectPath: string().min(1).optional()
|
|
17003
|
+
interactiveDisconnectPath: string().min(1).optional(),
|
|
17004
|
+
/**
|
|
17005
|
+
* The kind signs in through a server-held interactive session instead of
|
|
17006
|
+
* (or before) typed credentials. `basePath` is a hub-relative route set
|
|
17007
|
+
* served by the owning addon (`/addon/<id>/...`) speaking the sign-in
|
|
17008
|
+
* contract: `POST {basePath}/start` (body: the form's settings) answers
|
|
17009
|
+
* `{ sessionId, loginUrl }`; `GET {basePath}/status?sessionId=` answers
|
|
17010
|
+
* `{ phase: 'starting' | 'awaiting-login' | 'captured' | 'error' |
|
|
17011
|
+
* 'cancelled', loginUrl, error }`; `POST {basePath}/commit`
|
|
17012
|
+
* (`{ sessionId, name, brokerId? }`) stores the credentials on a new or
|
|
17013
|
+
* existing broker and answers `{ brokerId }`; `POST {basePath}/cancel`
|
|
17014
|
+
* (`{ sessionId }`) drops the session. The dialog that edits a broker
|
|
17015
|
+
* offers it as the default path; the fields the session fills are
|
|
17016
|
+
* marked `filledBySignIn` in the kind's settings schema.
|
|
17017
|
+
*/
|
|
17018
|
+
signIn: object({ basePath: string().min(1) }).optional()
|
|
16685
17019
|
}))
|
|
16686
17020
|
});
|
|
16687
17021
|
var ListInputSchema = object({
|
|
@@ -17676,7 +18010,12 @@ var CompositionProblemSchema = object({
|
|
|
17676
18010
|
"item-field-reserved",
|
|
17677
18011
|
"target-missing",
|
|
17678
18012
|
"target-unreadable",
|
|
17679
|
-
"not-replaceable"
|
|
18013
|
+
"not-replaceable",
|
|
18014
|
+
"native-capability-replace",
|
|
18015
|
+
"mixed-quantity",
|
|
18016
|
+
"helper-mismatch",
|
|
18017
|
+
"member-constraint",
|
|
18018
|
+
"retention"
|
|
17680
18019
|
]),
|
|
17681
18020
|
path: string(),
|
|
17682
18021
|
message: string()
|
|
@@ -17697,7 +18036,8 @@ var CompositionUnavailableModeSchema = _enum([
|
|
|
17697
18036
|
"null",
|
|
17698
18037
|
"offline",
|
|
17699
18038
|
"unknown",
|
|
17700
|
-
"release"
|
|
18039
|
+
"release",
|
|
18040
|
+
"omit"
|
|
17701
18041
|
]);
|
|
17702
18042
|
/**
|
|
17703
18043
|
* `derived` reads a source · `clock` reads only `now`, recomputed when a sibling
|
|
@@ -17734,9 +18074,11 @@ var CompositionFieldPlanSchema = object({
|
|
|
17734
18074
|
reads: array(CompositionFieldReadSchema)
|
|
17735
18075
|
});
|
|
17736
18076
|
/**
|
|
17737
|
-
* What a feature does to its target (D663): `new` builds a capability on a
|
|
17738
|
-
* device; on an existing device it `add`s a capability the device lacks
|
|
17739
|
-
*
|
|
18077
|
+
* What a feature does to its target (D663, D944): `new` builds a capability on a
|
|
18078
|
+
* new device; on an existing device it `add`s a capability the device lacks.
|
|
18079
|
+
* Replacing a capability the device already serves is refused
|
|
18080
|
+
* (`native-capability-replace`), not planned. `replace` remains on the claim
|
|
18081
|
+
* wire for a claim the hub already holds.
|
|
17740
18082
|
*/
|
|
17741
18083
|
var CompositionFeatureModeSchema = _enum([
|
|
17742
18084
|
"new",
|
|
@@ -17907,8 +18249,392 @@ Object.freeze({
|
|
|
17907
18249
|
latchedAt: {
|
|
17908
18250
|
kind: "fixed",
|
|
17909
18251
|
result: ["number", "null"]
|
|
18252
|
+
},
|
|
18253
|
+
schmitt: {
|
|
18254
|
+
kind: "fixed",
|
|
18255
|
+
result: ["boolean", "null"]
|
|
17910
18256
|
}
|
|
17911
18257
|
});
|
|
18258
|
+
/**
|
|
18259
|
+
* One catalog row per base reading a group helper can build (D944 §3).
|
|
18260
|
+
* Data, not a form default written into the block.
|
|
18261
|
+
*/
|
|
18262
|
+
var NOW$2 = {
|
|
18263
|
+
fieldPath: "lastFetchedAt",
|
|
18264
|
+
expr: "now"
|
|
18265
|
+
};
|
|
18266
|
+
var CHANGED = {
|
|
18267
|
+
fieldPath: "lastChangedAt",
|
|
18268
|
+
expr: "now"
|
|
18269
|
+
};
|
|
18270
|
+
function numeric(input) {
|
|
18271
|
+
return {
|
|
18272
|
+
...input,
|
|
18273
|
+
family: "numeric",
|
|
18274
|
+
deviceType: DeviceType.Sensor,
|
|
18275
|
+
memberDeviceType: DeviceType.Sensor,
|
|
18276
|
+
memberDeviceTypes: [DeviceType.Sensor],
|
|
18277
|
+
activeWhen: void 0,
|
|
18278
|
+
commandCaps: [],
|
|
18279
|
+
baseUnit: baseUnitOf(input.quantity),
|
|
18280
|
+
aggregates: NUMERIC_AGGREGATES,
|
|
18281
|
+
accept: [{
|
|
18282
|
+
cap: input.outputCap,
|
|
18283
|
+
fieldPath: input.outputField
|
|
18284
|
+
}]
|
|
18285
|
+
};
|
|
18286
|
+
}
|
|
18287
|
+
function binary(input) {
|
|
18288
|
+
return {
|
|
18289
|
+
...input,
|
|
18290
|
+
family: "binary",
|
|
18291
|
+
deviceType: DeviceType.Sensor,
|
|
18292
|
+
memberDeviceType: DeviceType.Sensor,
|
|
18293
|
+
memberDeviceTypes: [DeviceType.Sensor],
|
|
18294
|
+
activeWhen: void 0,
|
|
18295
|
+
commandCaps: [],
|
|
18296
|
+
quantity: "none",
|
|
18297
|
+
baseUnit: void 0,
|
|
18298
|
+
aggregates: BINARY_AGGREGATES,
|
|
18299
|
+
empty: "offline"
|
|
18300
|
+
};
|
|
18301
|
+
}
|
|
18302
|
+
var GROUP_TEMPLATES = [
|
|
18303
|
+
numeric({
|
|
18304
|
+
id: "temperature",
|
|
18305
|
+
summary: "Mean, median, min, max or sum of temperatures. Offline and unknown members are left out, never read as 0 °C.",
|
|
18306
|
+
role: DeviceRole.TemperatureSensor,
|
|
18307
|
+
outputCap: "temperature-sensor",
|
|
18308
|
+
outputField: "celsius",
|
|
18309
|
+
quantity: "temperature",
|
|
18310
|
+
defaultAggregate: "mean",
|
|
18311
|
+
empty: "null",
|
|
18312
|
+
companions: [NOW$2]
|
|
18313
|
+
}),
|
|
18314
|
+
numeric({
|
|
18315
|
+
id: "humidity",
|
|
18316
|
+
summary: "Humidity in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
18317
|
+
role: DeviceRole.HumiditySensor,
|
|
18318
|
+
outputCap: "humidity-sensor",
|
|
18319
|
+
outputField: "percent",
|
|
18320
|
+
quantity: "humidity",
|
|
18321
|
+
defaultAggregate: "mean",
|
|
18322
|
+
empty: "null",
|
|
18323
|
+
companions: [NOW$2]
|
|
18324
|
+
}),
|
|
18325
|
+
numeric({
|
|
18326
|
+
id: "pressure",
|
|
18327
|
+
summary: "Pressure in hectopascals. Offline and unknown members are left out, never read as 0 hPa.",
|
|
18328
|
+
role: DeviceRole.PressureSensor,
|
|
18329
|
+
outputCap: "pressure-sensor",
|
|
18330
|
+
outputField: "hpa",
|
|
18331
|
+
quantity: "pressure",
|
|
18332
|
+
defaultAggregate: "mean",
|
|
18333
|
+
empty: "null",
|
|
18334
|
+
companions: [NOW$2]
|
|
18335
|
+
}),
|
|
18336
|
+
numeric({
|
|
18337
|
+
id: "illuminance",
|
|
18338
|
+
summary: "Illuminance in lux. Offline and unknown members are left out, never read as 0 lx.",
|
|
18339
|
+
role: DeviceRole.AmbientLightSensor,
|
|
18340
|
+
outputCap: "ambient-light-sensor",
|
|
18341
|
+
outputField: "lux",
|
|
18342
|
+
quantity: "illuminance",
|
|
18343
|
+
defaultAggregate: "mean",
|
|
18344
|
+
empty: "null",
|
|
18345
|
+
companions: [NOW$2]
|
|
18346
|
+
}),
|
|
18347
|
+
numeric({
|
|
18348
|
+
id: "power",
|
|
18349
|
+
summary: "Power in watts, summed by default. Nobody reporting omits the key rather than writing 0 W.",
|
|
18350
|
+
role: DeviceRole.PowerSensor,
|
|
18351
|
+
outputCap: "power-meter",
|
|
18352
|
+
outputField: "watts",
|
|
18353
|
+
quantity: "power",
|
|
18354
|
+
defaultAggregate: "sum",
|
|
18355
|
+
empty: "omit",
|
|
18356
|
+
companions: [NOW$2]
|
|
18357
|
+
}),
|
|
18358
|
+
numeric({
|
|
18359
|
+
id: "energy",
|
|
18360
|
+
summary: "Energy in kilowatt-hours, summed by default. Nobody reporting omits the key rather than writing 0 kWh.",
|
|
18361
|
+
role: DeviceRole.EnergySensor,
|
|
18362
|
+
outputCap: "power-meter",
|
|
18363
|
+
outputField: "kwhTotal",
|
|
18364
|
+
quantity: "energy",
|
|
18365
|
+
defaultAggregate: "sum",
|
|
18366
|
+
empty: "omit",
|
|
18367
|
+
companions: [NOW$2]
|
|
18368
|
+
}),
|
|
18369
|
+
numeric({
|
|
18370
|
+
id: "battery",
|
|
18371
|
+
summary: "Battery charge in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
18372
|
+
role: DeviceRole.BatterySensor,
|
|
18373
|
+
outputCap: "battery",
|
|
18374
|
+
outputField: "percentage",
|
|
18375
|
+
quantity: "percentage",
|
|
18376
|
+
defaultAggregate: "mean",
|
|
18377
|
+
empty: "null",
|
|
18378
|
+
companions: [
|
|
18379
|
+
{
|
|
18380
|
+
fieldPath: "charging",
|
|
18381
|
+
expr: "\"unknown\""
|
|
18382
|
+
},
|
|
18383
|
+
{
|
|
18384
|
+
fieldPath: "sleeping",
|
|
18385
|
+
expr: "false"
|
|
18386
|
+
},
|
|
18387
|
+
{
|
|
18388
|
+
fieldPath: "lastUpdated",
|
|
18389
|
+
expr: "now"
|
|
18390
|
+
}
|
|
18391
|
+
]
|
|
18392
|
+
}),
|
|
18393
|
+
numeric({
|
|
18394
|
+
id: "numeric",
|
|
18395
|
+
summary: "A numeric reading in the members’ shared quantity. Mixed quantities are refused. Nobody reporting publishes null, not 0.",
|
|
18396
|
+
role: DeviceRole.NumericSensor,
|
|
18397
|
+
outputCap: "numeric-sensor",
|
|
18398
|
+
outputField: "value",
|
|
18399
|
+
quantity: "device",
|
|
18400
|
+
defaultAggregate: "mean",
|
|
18401
|
+
empty: "null",
|
|
18402
|
+
companions: [NOW$2]
|
|
18403
|
+
}),
|
|
18404
|
+
binary({
|
|
18405
|
+
id: "motion",
|
|
18406
|
+
summary: "Any or all motion. Offline and unknown members are left out, never read as off. Nobody reporting takes the device offline.",
|
|
18407
|
+
role: DeviceRole.MotionSensor,
|
|
18408
|
+
outputCap: "motion",
|
|
18409
|
+
outputField: "detected",
|
|
18410
|
+
defaultAggregate: "any",
|
|
18411
|
+
accept: [{
|
|
18412
|
+
cap: "motion",
|
|
18413
|
+
fieldPath: "detected"
|
|
18414
|
+
}],
|
|
18415
|
+
companions: [{
|
|
18416
|
+
fieldPath: "lastDetectedAt",
|
|
18417
|
+
expr: "null"
|
|
18418
|
+
}, {
|
|
18419
|
+
fieldPath: "autoClearAfterMs",
|
|
18420
|
+
expr: "null"
|
|
18421
|
+
}]
|
|
18422
|
+
}),
|
|
18423
|
+
binary({
|
|
18424
|
+
id: "contact",
|
|
18425
|
+
summary: "Any or all open contacts. Offline and unknown members are left out, never read as closed.",
|
|
18426
|
+
role: DeviceRole.ContactSensor,
|
|
18427
|
+
outputCap: "contact",
|
|
18428
|
+
outputField: "entryOpen",
|
|
18429
|
+
defaultAggregate: "any",
|
|
18430
|
+
accept: [{
|
|
18431
|
+
cap: "contact",
|
|
18432
|
+
fieldPath: "entryOpen"
|
|
18433
|
+
}],
|
|
18434
|
+
companions: [CHANGED]
|
|
18435
|
+
}),
|
|
18436
|
+
binary({
|
|
18437
|
+
id: "leak",
|
|
18438
|
+
summary: "Any or all leak detections. Offline and unknown members are left out, never read as dry.",
|
|
18439
|
+
role: DeviceRole.LeakSensor,
|
|
18440
|
+
outputCap: "flood",
|
|
18441
|
+
outputField: "flooded",
|
|
18442
|
+
defaultAggregate: "any",
|
|
18443
|
+
accept: [{
|
|
18444
|
+
cap: "flood",
|
|
18445
|
+
fieldPath: "flooded"
|
|
18446
|
+
}],
|
|
18447
|
+
companions: [CHANGED]
|
|
18448
|
+
}),
|
|
18449
|
+
binary({
|
|
18450
|
+
id: "smoke",
|
|
18451
|
+
summary: "Any or all smoke detections. Offline and unknown members are left out, never read as clear.",
|
|
18452
|
+
role: DeviceRole.SmokeSensor,
|
|
18453
|
+
outputCap: "smoke",
|
|
18454
|
+
outputField: "detected",
|
|
18455
|
+
defaultAggregate: "any",
|
|
18456
|
+
accept: [{
|
|
18457
|
+
cap: "smoke",
|
|
18458
|
+
fieldPath: "detected"
|
|
18459
|
+
}],
|
|
18460
|
+
companions: [CHANGED]
|
|
18461
|
+
}),
|
|
18462
|
+
binary({
|
|
18463
|
+
id: "occupancy",
|
|
18464
|
+
summary: "Any or all of motion or binary sensors, published as a binary. Presence zones are not aggregated. Nobody reporting is offline, not off.",
|
|
18465
|
+
role: DeviceRole.BinarySensor,
|
|
18466
|
+
outputCap: "binary",
|
|
18467
|
+
outputField: "on",
|
|
18468
|
+
defaultAggregate: "any",
|
|
18469
|
+
accept: [{
|
|
18470
|
+
cap: "motion",
|
|
18471
|
+
fieldPath: "detected"
|
|
18472
|
+
}, {
|
|
18473
|
+
cap: "binary",
|
|
18474
|
+
fieldPath: "on"
|
|
18475
|
+
}],
|
|
18476
|
+
companions: [CHANGED]
|
|
18477
|
+
}),
|
|
18478
|
+
binary({
|
|
18479
|
+
id: "binary",
|
|
18480
|
+
summary: "Any or all generic binary sensors. Offline and unknown members are left out, never read as off.",
|
|
18481
|
+
role: DeviceRole.BinarySensor,
|
|
18482
|
+
outputCap: "binary",
|
|
18483
|
+
outputField: "on",
|
|
18484
|
+
defaultAggregate: "any",
|
|
18485
|
+
accept: [{
|
|
18486
|
+
cap: "binary",
|
|
18487
|
+
fieldPath: "on"
|
|
18488
|
+
}],
|
|
18489
|
+
companions: [CHANGED]
|
|
18490
|
+
}),
|
|
18491
|
+
actuator({
|
|
18492
|
+
id: "switch",
|
|
18493
|
+
summary: "On when at least one switch is on, or when all of them are. Offline and unknown members are left out of that decision, never read as off, and still receive the command.",
|
|
18494
|
+
deviceType: DeviceType.Switch,
|
|
18495
|
+
outputCap: "switch",
|
|
18496
|
+
outputField: "on",
|
|
18497
|
+
member: {
|
|
18498
|
+
cap: "switch",
|
|
18499
|
+
fieldPath: "on"
|
|
18500
|
+
},
|
|
18501
|
+
commandCaps: ["switch"]
|
|
18502
|
+
}),
|
|
18503
|
+
actuator({
|
|
18504
|
+
id: "light",
|
|
18505
|
+
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.",
|
|
18506
|
+
deviceType: DeviceType.Light,
|
|
18507
|
+
outputCap: "switch",
|
|
18508
|
+
outputField: "on",
|
|
18509
|
+
member: {
|
|
18510
|
+
cap: "switch",
|
|
18511
|
+
fieldPath: "on"
|
|
18512
|
+
},
|
|
18513
|
+
commandCaps: [
|
|
18514
|
+
"switch",
|
|
18515
|
+
"brightness",
|
|
18516
|
+
"color"
|
|
18517
|
+
]
|
|
18518
|
+
}),
|
|
18519
|
+
actuator({
|
|
18520
|
+
id: "fan",
|
|
18521
|
+
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.",
|
|
18522
|
+
deviceType: DeviceType.Fan,
|
|
18523
|
+
outputCap: "switch",
|
|
18524
|
+
outputField: "on",
|
|
18525
|
+
member: {
|
|
18526
|
+
cap: "switch",
|
|
18527
|
+
fieldPath: "on"
|
|
18528
|
+
},
|
|
18529
|
+
commandCaps: ["switch", "fan-control"]
|
|
18530
|
+
}),
|
|
18531
|
+
actuator({
|
|
18532
|
+
id: "cover",
|
|
18533
|
+
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.",
|
|
18534
|
+
deviceType: DeviceType.Cover,
|
|
18535
|
+
outputCap: "group-active",
|
|
18536
|
+
outputField: "active",
|
|
18537
|
+
member: {
|
|
18538
|
+
cap: "cover",
|
|
18539
|
+
fieldPath: "state"
|
|
18540
|
+
},
|
|
18541
|
+
activeWhen: [
|
|
18542
|
+
"open",
|
|
18543
|
+
"opening",
|
|
18544
|
+
"stopped"
|
|
18545
|
+
],
|
|
18546
|
+
commandCaps: ["cover"]
|
|
18547
|
+
}),
|
|
18548
|
+
actuator({
|
|
18549
|
+
id: "valve",
|
|
18550
|
+
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.",
|
|
18551
|
+
deviceType: DeviceType.Valve,
|
|
18552
|
+
outputCap: "group-active",
|
|
18553
|
+
outputField: "active",
|
|
18554
|
+
member: {
|
|
18555
|
+
cap: "valve",
|
|
18556
|
+
fieldPath: "state"
|
|
18557
|
+
},
|
|
18558
|
+
activeWhen: [
|
|
18559
|
+
"open",
|
|
18560
|
+
"opening",
|
|
18561
|
+
"stopped"
|
|
18562
|
+
],
|
|
18563
|
+
commandCaps: ["valve"]
|
|
18564
|
+
}),
|
|
18565
|
+
actuator({
|
|
18566
|
+
id: "lock",
|
|
18567
|
+
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.",
|
|
18568
|
+
deviceType: DeviceType.Lock,
|
|
18569
|
+
outputCap: "group-active",
|
|
18570
|
+
outputField: "active",
|
|
18571
|
+
member: {
|
|
18572
|
+
cap: "lock-control",
|
|
18573
|
+
fieldPath: "state"
|
|
18574
|
+
},
|
|
18575
|
+
activeWhen: ["locked"],
|
|
18576
|
+
commandCaps: ["lock-control"]
|
|
18577
|
+
}),
|
|
18578
|
+
actuator({
|
|
18579
|
+
id: "media-player",
|
|
18580
|
+
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.",
|
|
18581
|
+
deviceType: DeviceType.MediaPlayer,
|
|
18582
|
+
outputCap: "group-active",
|
|
18583
|
+
outputField: "active",
|
|
18584
|
+
member: {
|
|
18585
|
+
cap: "media-player",
|
|
18586
|
+
fieldPath: "state"
|
|
18587
|
+
},
|
|
18588
|
+
activeWhen: ["playing", "buffering"],
|
|
18589
|
+
commandCaps: ["media-player"]
|
|
18590
|
+
}),
|
|
18591
|
+
actuator({
|
|
18592
|
+
id: "climate",
|
|
18593
|
+
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.",
|
|
18594
|
+
deviceType: DeviceType.Thermostat,
|
|
18595
|
+
memberDeviceTypes: [DeviceType.Thermostat, DeviceType.Climate],
|
|
18596
|
+
outputCap: "group-active",
|
|
18597
|
+
outputField: "active",
|
|
18598
|
+
member: {
|
|
18599
|
+
cap: "climate-control",
|
|
18600
|
+
fieldPath: "mode"
|
|
18601
|
+
},
|
|
18602
|
+
activeWhen: [
|
|
18603
|
+
"heat",
|
|
18604
|
+
"cool",
|
|
18605
|
+
"auto",
|
|
18606
|
+
"heat_cool",
|
|
18607
|
+
"fan_only",
|
|
18608
|
+
"dry"
|
|
18609
|
+
],
|
|
18610
|
+
commandCaps: ["climate-control"]
|
|
18611
|
+
})
|
|
18612
|
+
];
|
|
18613
|
+
function actuator(input) {
|
|
18614
|
+
return {
|
|
18615
|
+
id: input.id,
|
|
18616
|
+
summary: input.summary,
|
|
18617
|
+
deviceType: input.deviceType,
|
|
18618
|
+
outputCap: input.outputCap,
|
|
18619
|
+
outputField: input.outputField,
|
|
18620
|
+
commandCaps: input.commandCaps,
|
|
18621
|
+
family: "actuator",
|
|
18622
|
+
role: void 0,
|
|
18623
|
+
memberDeviceType: input.deviceType,
|
|
18624
|
+
memberDeviceTypes: input.memberDeviceTypes ?? [input.deviceType],
|
|
18625
|
+
activeWhen: input.activeWhen,
|
|
18626
|
+
quantity: "none",
|
|
18627
|
+
baseUnit: void 0,
|
|
18628
|
+
aggregates: BINARY_AGGREGATES,
|
|
18629
|
+
defaultAggregate: "any",
|
|
18630
|
+
empty: "offline",
|
|
18631
|
+
accept: [input.member],
|
|
18632
|
+
companions: [CHANGED]
|
|
18633
|
+
};
|
|
18634
|
+
}
|
|
18635
|
+
new Map(GROUP_TEMPLATES.map((template) => [template.id, template]));
|
|
18636
|
+
DeviceFeature.LightColorRgb, DeviceFeature.LightColorHsv, DeviceFeature.LightColorMired;
|
|
18637
|
+
DeviceType.Camera;
|
|
17912
18638
|
`${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
|
|
17913
18639
|
/**
|
|
17914
18640
|
* What a composition may BUILD on a device type (G2, D676): the caps a new
|
|
@@ -19735,12 +20461,12 @@ function buildDeviceAdminUrl(parts) {
|
|
|
19735
20461
|
* providers detect renames by matching `uniqueId` and patch `id`
|
|
19736
20462
|
* in-place so dispatch keeps working.
|
|
19737
20463
|
*
|
|
19738
|
-
* **
|
|
19739
|
-
*
|
|
19740
|
-
*
|
|
19741
|
-
*
|
|
19742
|
-
* (`ha-domain-mapping`)
|
|
19743
|
-
* stored after that point.
|
|
20464
|
+
* **Display unit and precision are NOT stored here.** They are a read-time
|
|
20465
|
+
* preference (D944). A polymorphic reading stores its `quantity` here once,
|
|
20466
|
+
* at adopt, and a date/time value stores `dateTimeShape` the same way —
|
|
20467
|
+
* neither is repeated on each sample. The `device_class` tag is an
|
|
20468
|
+
* HA-specific input consumed at the discovery boundary (`ha-domain-mapping`)
|
|
20469
|
+
* to derive the CamStack `DeviceRole`; it is never stored after that point.
|
|
19744
20470
|
*
|
|
19745
20471
|
* The `raw` escape hatch carries provider-specific attributes that don't
|
|
19746
20472
|
* fit the structured slots (HA `attributes` whitelist, Reolink `deviceCache`
|
|
@@ -19754,6 +20480,14 @@ var SourceInfoSchema = object({
|
|
|
19754
20480
|
/** Immutable upstream identifier when available (HA `unique_id`, … ).
|
|
19755
20481
|
* Used to detect rename when `id` changes. */
|
|
19756
20482
|
uniqueId: string().optional(),
|
|
20483
|
+
/** Quantity of a polymorphic reading, written once at adopt (D944). */
|
|
20484
|
+
quantity: ReadingQuantitySchema.optional(),
|
|
20485
|
+
/** Date / time / datetime shape of a string reading, written once at adopt. */
|
|
20486
|
+
dateTimeShape: _enum([
|
|
20487
|
+
"date",
|
|
20488
|
+
"time",
|
|
20489
|
+
"datetime"
|
|
20490
|
+
]).optional(),
|
|
19757
20491
|
/** Provider-specific extras that don't fit the structured slots.
|
|
19758
20492
|
* Whitelist what goes here per provider — do NOT dump entire HA
|
|
19759
20493
|
* attribute blobs (would explode the meta JSON column). */
|
|
@@ -40747,7 +41481,8 @@ method(object({
|
|
|
40747
41481
|
"enum"
|
|
40748
41482
|
]),
|
|
40749
41483
|
enumValues: array(string()).optional(),
|
|
40750
|
-
item: boolean().optional()
|
|
41484
|
+
item: boolean().optional(),
|
|
41485
|
+
quantity: ReadingQuantitySchema.optional()
|
|
40751
41486
|
})).readonly(),
|
|
40752
41487
|
itemArray: object({
|
|
40753
41488
|
path: string(),
|
|
@@ -43108,7 +43843,7 @@ var NetworkAccessStatusSchema = object({
|
|
|
43108
43843
|
});
|
|
43109
43844
|
/**
|
|
43110
43845
|
* Optional, richer endpoint shape returned by providers that expose
|
|
43111
|
-
* MORE than one ingress concurrently (Tailscale
|
|
43846
|
+
* MORE than one ingress concurrently (Tailscale Funnel with mixed
|
|
43112
43847
|
* serve+funnel rules, future ngrok multi-tunnel, …). Each entry carries
|
|
43113
43848
|
* the originating provider config (mode + sourcePort) so the
|
|
43114
43849
|
* orchestrator UI can label rows distinctly. Providers that expose only
|
|
@@ -44547,8 +45282,8 @@ var MaskPolygonShapeSchema = object({
|
|
|
44547
45282
|
/** Boolean cell grid — row-major, length === gridWidth*gridHeight. */
|
|
44548
45283
|
var MaskGridShapeSchema = object({
|
|
44549
45284
|
kind: literal("grid"),
|
|
44550
|
-
gridWidth: number(),
|
|
44551
|
-
gridHeight: number(),
|
|
45285
|
+
gridWidth: number().meta(readingMeta("none")),
|
|
45286
|
+
gridHeight: number().meta(readingMeta("none")),
|
|
44552
45287
|
cells: array(boolean())
|
|
44553
45288
|
});
|
|
44554
45289
|
discriminatedUnion("kind", [
|
|
@@ -44660,6 +45395,8 @@ var NcSystemEventKindSchema = _enum([
|
|
|
44660
45395
|
"detection-blind",
|
|
44661
45396
|
"motion-noisy",
|
|
44662
45397
|
"motion-calm",
|
|
45398
|
+
"package-llm-silent",
|
|
45399
|
+
"package-llm-answered",
|
|
44663
45400
|
"recording-stalled",
|
|
44664
45401
|
"recording-healthy",
|
|
44665
45402
|
"recording-degraded",
|
|
@@ -45749,7 +46486,20 @@ var NcRuleInputSchema = object({
|
|
|
45749
46486
|
* save by the hub's grouping guard). `.optional()`, never `.default()`: the addon cap
|
|
45750
46487
|
* path does not run Zod defaults.
|
|
45751
46488
|
*/
|
|
45752
|
-
groupingSec: number().int().min(5).max(60).optional()
|
|
46489
|
+
groupingSec: number().int().min(5).max(60).optional(),
|
|
46490
|
+
/**
|
|
46491
|
+
* ASK ME TO CONFIRM DETECTIONS (#243): a DETECTION notification of this rule
|
|
46492
|
+
* carries "Correct" / "Wrong" buttons (and, where the channel has room, a
|
|
46493
|
+
* "Wrong, it is a <class>" choice). A tap marks the track for retraining, the
|
|
46494
|
+
* same mark the Library writes, and records whose notification it was and
|
|
46495
|
+
* when. A channel with no buttons gets the same two choices as links.
|
|
46496
|
+
*
|
|
46497
|
+
* `.optional()`, never `.default()` (a Zod default does not run on the addon
|
|
46498
|
+
* cap path): absent and `false` both mean off, which is what every rule
|
|
46499
|
+
* authored before this field meant. An editor turns it off by writing
|
|
46500
|
+
* `false`, so it needs no `clear` key.
|
|
46501
|
+
*/
|
|
46502
|
+
askVerdict: boolean().optional()
|
|
45753
46503
|
});
|
|
45754
46504
|
/**
|
|
45755
46505
|
* Partial patch for `updateRule` — any subset of the input fields, plus the
|
|
@@ -55778,6 +56528,28 @@ var PackageVersionInfoSchema = object({
|
|
|
55778
56528
|
deprecated: string().optional(),
|
|
55779
56529
|
distTags: array(string()).readonly()
|
|
55780
56530
|
});
|
|
56531
|
+
/**
|
|
56532
|
+
* One published document. `ok` is markdown from the registry. `missing` means
|
|
56533
|
+
* the registry answered and the file was not there. `error` is a registry or
|
|
56534
|
+
* tarball failure — never an empty string standing in for either.
|
|
56535
|
+
*/
|
|
56536
|
+
var PackageDocBodySchema = discriminatedUnion("status", [
|
|
56537
|
+
object({
|
|
56538
|
+
status: literal("ok"),
|
|
56539
|
+
markdown: string()
|
|
56540
|
+
}),
|
|
56541
|
+
object({ status: literal("missing") }),
|
|
56542
|
+
object({
|
|
56543
|
+
status: literal("error"),
|
|
56544
|
+
message: string()
|
|
56545
|
+
})
|
|
56546
|
+
]);
|
|
56547
|
+
var PackageDocsSchema = object({
|
|
56548
|
+
name: string(),
|
|
56549
|
+
version: string(),
|
|
56550
|
+
readme: PackageDocBodySchema,
|
|
56551
|
+
changelog: PackageDocBodySchema
|
|
56552
|
+
});
|
|
55781
56553
|
var SearchResultSchema = object({
|
|
55782
56554
|
name: string(),
|
|
55783
56555
|
version: string(),
|
|
@@ -55996,7 +56768,10 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
|
|
|
55996
56768
|
}), object({ success: literal(true) }), {
|
|
55997
56769
|
kind: "mutation",
|
|
55998
56770
|
auth: "admin"
|
|
55999
|
-
}), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({
|
|
56771
|
+
}), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({
|
|
56772
|
+
name: string().min(1),
|
|
56773
|
+
version: string().min(1).optional()
|
|
56774
|
+
}), PackageDocsSchema, { auth: "admin" }), method(object({ addonId: string() }), RestartAddonResultSchema, {
|
|
56000
56775
|
kind: "mutation",
|
|
56001
56776
|
auth: "admin"
|
|
56002
56777
|
}), method(object({ packageName: string() }), object({ success: literal(true) }), {
|
|
@@ -56046,46 +56821,27 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
|
|
|
56046
56821
|
}), LogStreamEntrySchema, { kind: "subscription" });
|
|
56047
56822
|
object({
|
|
56048
56823
|
/** Carbon dioxide concentration in ppm. */
|
|
56049
|
-
co2Ppm: number().min(0).optional(),
|
|
56824
|
+
co2Ppm: number().min(0).optional().meta(readingMeta("concentration-volume")),
|
|
56050
56825
|
/** Total volatile organic compounds in ppb. */
|
|
56051
|
-
vocPpb: number().min(0).optional(),
|
|
56826
|
+
vocPpb: number().min(0).optional().meta(readingMeta("concentration-ppb")),
|
|
56052
56827
|
/** Particulate matter ≤ 2.5 μm in µg/m³. */
|
|
56053
|
-
pm25: number().min(0).optional(),
|
|
56828
|
+
pm25: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
56054
56829
|
/** Particulate matter ≤ 10 μm in µg/m³. */
|
|
56055
|
-
pm10: number().min(0).optional(),
|
|
56830
|
+
pm10: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
56056
56831
|
/** Composite AQI value (typically 0..500). */
|
|
56057
|
-
aqi: number().optional(),
|
|
56832
|
+
aqi: number().optional().meta(readingMeta("index")),
|
|
56058
56833
|
/** Ms epoch when the slice was last updated. */
|
|
56059
|
-
lastFetchedAt: number()
|
|
56060
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
56061
|
-
* `attributes.unit_of_measurement` → 'ppm' / 'ppb' / 'µg/m³'). Each
|
|
56062
|
-
* upstream `sensor.*` entity surfaces ONE device_class, so one unit
|
|
56063
|
-
* per slice is unambiguous. */
|
|
56064
|
-
unit: string().optional(),
|
|
56065
|
-
/** Suggested decimal places for numeric display.
|
|
56066
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
56067
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
56068
|
-
* auto-formatting when absent. */
|
|
56069
|
-
precision: number().int().min(0).max(10).optional()
|
|
56834
|
+
lastFetchedAt: number()
|
|
56070
56835
|
});
|
|
56071
56836
|
DeviceType.Sensor;
|
|
56072
56837
|
object({
|
|
56073
|
-
/** Current illuminance in lux (lx). */
|
|
56074
|
-
lux: number().min(0).meta({
|
|
56075
|
-
|
|
56838
|
+
/** Current illuminance in lux (lx). `null` when the sample was refused (D393). */
|
|
56839
|
+
lux: number().min(0).nullable().meta(readingMeta("illuminance", {
|
|
56840
|
+
precision: 0,
|
|
56076
56841
|
label: "Illuminance"
|
|
56077
|
-
}),
|
|
56842
|
+
})),
|
|
56078
56843
|
/** Ms epoch when the slice was last updated. */
|
|
56079
|
-
lastFetchedAt: number()
|
|
56080
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
56081
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
56082
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
56083
|
-
unit: string().optional(),
|
|
56084
|
-
/** Suggested decimal places for numeric display.
|
|
56085
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
56086
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
56087
|
-
* auto-formatting when absent. */
|
|
56088
|
-
precision: number().int().min(0).max(10).optional()
|
|
56844
|
+
lastFetchedAt: number()
|
|
56089
56845
|
});
|
|
56090
56846
|
DeviceType.Sensor;
|
|
56091
56847
|
/**
|
|
@@ -56230,10 +56986,7 @@ var BatteryStatusSchema = object({
|
|
|
56230
56986
|
* Consumers must SKIP a null rather than coerce it — `battery-band` already
|
|
56231
56987
|
* declines to band a non-finite reading, which is the correct shape.
|
|
56232
56988
|
*/
|
|
56233
|
-
percentage: number().min(0).max(100).nullable().meta({
|
|
56234
|
-
unit: "%",
|
|
56235
|
-
label: "Charge"
|
|
56236
|
-
}),
|
|
56989
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage", { label: "Charge" })),
|
|
56237
56990
|
/**
|
|
56238
56991
|
* Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
|
|
56239
56992
|
* Reolink-specific for the Solar Panel 2 accessory (will become
|
|
@@ -56260,7 +57013,14 @@ var BatteryStatusSchema = object({
|
|
|
56260
57013
|
*/
|
|
56261
57014
|
sleeping: boolean().meta({ label: "Sleeping" }),
|
|
56262
57015
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
56263
|
-
lastUpdated: number(),
|
|
57016
|
+
lastUpdated: number().meta(readingMeta("none")),
|
|
57017
|
+
/**
|
|
57018
|
+
* Battery voltage in volts, for a cell the firmware reports as voltage
|
|
57019
|
+
* rather than a percentage (Ecowitt capacitor packs). Absent on cameras
|
|
57020
|
+
* that only report charge. A second reading on this cap, not a second
|
|
57021
|
+
* `numeric-sensor` on the same device.
|
|
57022
|
+
*/
|
|
57023
|
+
volts: number().nullable().optional().meta(readingMeta("voltage", { label: "Voltage" })),
|
|
56264
57024
|
/**
|
|
56265
57025
|
* Ms epoch of the last time the device PROVED it was reachable — a
|
|
56266
57026
|
* completed firmware round-trip, an observed wake, or an inbound push
|
|
@@ -56300,7 +57060,7 @@ var BatteryStatusSchema = object({
|
|
|
56300
57060
|
*/
|
|
56301
57061
|
binary: boolean().optional().meta({ label: "Binary indicator" })
|
|
56302
57062
|
});
|
|
56303
|
-
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat;
|
|
57063
|
+
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.EventEmitter;
|
|
56304
57064
|
method(object({
|
|
56305
57065
|
deviceId: number(),
|
|
56306
57066
|
/** Bound on the wait. Sensible range 3000–10000ms. */
|
|
@@ -56320,7 +57080,7 @@ object({
|
|
|
56320
57080
|
DeviceType.Sensor;
|
|
56321
57081
|
object({
|
|
56322
57082
|
/** Current level as 0..100 inclusive. Firmware-reported. */
|
|
56323
|
-
percentage: number().min(0).max(100),
|
|
57083
|
+
percentage: number().min(0).max(100).meta(readingMeta("percentage")),
|
|
56324
57084
|
/** Ms epoch of the last operator-driven change. Useful for UI freshness. */
|
|
56325
57085
|
lastChangedAt: number()
|
|
56326
57086
|
});
|
|
@@ -56705,21 +57465,21 @@ object({
|
|
|
56705
57465
|
/** Single setpoint in Celsius. Used by single-target modes
|
|
56706
57466
|
* (heat / cool / dry). Null when the device is in a range mode
|
|
56707
57467
|
* (`heat_cool`) or has no setpoint at all (`fan_only`/`off`). */
|
|
56708
|
-
target: number().nullable(),
|
|
57468
|
+
target: number().nullable().meta(readingMeta("temperature")),
|
|
56709
57469
|
/** Upper bound of the dual setpoint in Celsius. Populated only
|
|
56710
57470
|
* in `heat_cool` mode. */
|
|
56711
|
-
targetHigh: number().nullable(),
|
|
57471
|
+
targetHigh: number().nullable().meta(readingMeta("temperature")),
|
|
56712
57472
|
/** Lower bound of the dual setpoint in Celsius. Populated only
|
|
56713
57473
|
* in `heat_cool` mode. */
|
|
56714
|
-
targetLow: number().nullable(),
|
|
57474
|
+
targetLow: number().nullable().meta(readingMeta("temperature")),
|
|
56715
57475
|
/** Target relative humidity (0..100). Null when the device has no
|
|
56716
57476
|
* humidity control. */
|
|
56717
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
57477
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
56718
57478
|
/** Current measured temperature in Celsius. Read-only — pushed by
|
|
56719
57479
|
* the device's internal sensor. */
|
|
56720
|
-
currentTemp: number().nullable(),
|
|
57480
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
56721
57481
|
/** Current measured relative humidity (0..100). Read-only. */
|
|
56722
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
57482
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
56723
57483
|
/** Vertical louver swing on/off. Null when the device has no vertical
|
|
56724
57484
|
* swing surface (gate with `DeviceFeature.ClimateSwingVertical`). */
|
|
56725
57485
|
swingVertical: boolean().nullable(),
|
|
@@ -56727,11 +57487,11 @@ object({
|
|
|
56727
57487
|
* horizontal swing surface (gate with `DeviceFeature.ClimateSwingHorizontal`). */
|
|
56728
57488
|
swingHorizontal: boolean().nullable(),
|
|
56729
57489
|
/** Lowest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
56730
|
-
minTemp: number().nullable().optional(),
|
|
57490
|
+
minTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
56731
57491
|
/** Highest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
56732
|
-
maxTemp: number().nullable().optional(),
|
|
57492
|
+
maxTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
56733
57493
|
/** Setpoint granularity, Celsius (0.5, 1). Absent / null = not reported. */
|
|
56734
|
-
tempStep: number().positive().nullable().optional(),
|
|
57494
|
+
tempStep: number().positive().nullable().optional().meta(readingMeta("temperature")),
|
|
56735
57495
|
/** Ms epoch when the slice was last updated (push or command). */
|
|
56736
57496
|
lastFetchedAt: number()
|
|
56737
57497
|
});
|
|
@@ -56810,17 +57570,17 @@ DeviceType.Thermostat, DeviceType.Climate, method(object({
|
|
|
56810
57570
|
* modes to expose in the picker without a slice fetch.
|
|
56811
57571
|
*/
|
|
56812
57572
|
var RgbTripletSchema = object({
|
|
56813
|
-
r: number().int().min(0).max(255),
|
|
56814
|
-
g: number().int().min(0).max(255),
|
|
56815
|
-
b: number().int().min(0).max(255)
|
|
57573
|
+
r: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
57574
|
+
g: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
57575
|
+
b: number().int().min(0).max(255).meta(readingMeta("none"))
|
|
56816
57576
|
});
|
|
56817
57577
|
var HsvTripletSchema = object({
|
|
56818
57578
|
/** Hue in degrees, 0..360. */
|
|
56819
|
-
h: number().min(0).max(360),
|
|
57579
|
+
h: number().min(0).max(360).meta(readingMeta("none")),
|
|
56820
57580
|
/** Saturation as 0..100 inclusive. */
|
|
56821
|
-
s: number().min(0).max(100),
|
|
57581
|
+
s: number().min(0).max(100).meta(readingMeta("none")),
|
|
56822
57582
|
/** Value/brightness as 0..100 inclusive. */
|
|
56823
|
-
v: number().min(0).max(100)
|
|
57583
|
+
v: number().min(0).max(100).meta(readingMeta("none"))
|
|
56824
57584
|
});
|
|
56825
57585
|
var ColorInputSchema = discriminatedUnion("mode", [
|
|
56826
57586
|
object({
|
|
@@ -56849,7 +57609,7 @@ object({
|
|
|
56849
57609
|
/** Populated when `mode === 'hsv'`. */
|
|
56850
57610
|
hsv: HsvTripletSchema.optional(),
|
|
56851
57611
|
/** Populated when `mode === 'mired'`. */
|
|
56852
|
-
mireds: number().int().optional(),
|
|
57612
|
+
mireds: number().int().optional().meta(readingMeta("colour-temperature")),
|
|
56853
57613
|
/** Ms epoch of the last operator-driven change. */
|
|
56854
57614
|
lastChangedAt: number()
|
|
56855
57615
|
});
|
|
@@ -56973,18 +57733,12 @@ _enum([
|
|
|
56973
57733
|
"empty",
|
|
56974
57734
|
"full"
|
|
56975
57735
|
]);
|
|
56976
|
-
/**
|
|
56977
|
-
|
|
56978
|
-
|
|
56979
|
-
"days",
|
|
56980
|
-
"hours",
|
|
56981
|
-
"cycles"
|
|
56982
|
-
]);
|
|
56983
|
-
/** Remaining life as a COUNT, not a percentage (the PetKit desiccant reports
|
|
56984
|
-
* days). `value` null = unknown (D393). */
|
|
57736
|
+
/** Whether `remaining.value` is a duration in seconds or a dimensionless count. */
|
|
57737
|
+
var ConsumableRemainingKindSchema = _enum(["duration", "count"]);
|
|
57738
|
+
/** Remaining life. `value` null = unknown (D393). Duration is seconds. */
|
|
56985
57739
|
var ConsumableRemainingSchema = object({
|
|
56986
|
-
value: number().min(0).nullable(),
|
|
56987
|
-
|
|
57740
|
+
value: number().min(0).nullable().meta(readingMeta("device")),
|
|
57741
|
+
kind: ConsumableRemainingKindSchema
|
|
56988
57742
|
});
|
|
56989
57743
|
var ConsumablesStatusSchema = object({
|
|
56990
57744
|
items: array(object({
|
|
@@ -56993,7 +57747,7 @@ var ConsumablesStatusSchema = object({
|
|
|
56993
57747
|
/** Display name. */
|
|
56994
57748
|
label: string().min(1),
|
|
56995
57749
|
/** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
|
|
56996
|
-
level: number().min(0).max(100).nullable(),
|
|
57750
|
+
level: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
56997
57751
|
/** The provider's discrete verdict when known (binary mode). */
|
|
56998
57752
|
status: ConsumableStatusSchema.nullable(),
|
|
56999
57753
|
/** What the item is — decides whether low or full is bad. Absent = `wear`. */
|
|
@@ -57010,7 +57764,7 @@ var ConsumablesStatusSchema = object({
|
|
|
57010
57764
|
})),
|
|
57011
57765
|
lastChangedAt: number()
|
|
57012
57766
|
});
|
|
57013
|
-
Object.values(DeviceType), [...
|
|
57767
|
+
Object.values(DeviceType), [...ConsumableRemainingKindSchema.options], [...ConsumableStatusSchema.options], [...ConsumableKindSchema.options], [...ConsumableFormSchema.options];
|
|
57014
57768
|
Object.values(DeviceType), method(object({
|
|
57015
57769
|
deviceId: number().int().nonnegative(),
|
|
57016
57770
|
key: string().min(1)
|
|
@@ -57035,39 +57789,17 @@ object({
|
|
|
57035
57789
|
/** Current value. Numeric kind → number; select/text/datetime → string.
|
|
57036
57790
|
* Datetime values are ISO 8601 strings (full timestamp, date-only,
|
|
57037
57791
|
* or time-only — HA accepts all three forms). */
|
|
57038
|
-
value: union([number(), string()]),
|
|
57792
|
+
value: union([number().meta(readingMeta("device")), string()]),
|
|
57039
57793
|
/** Acceptable values when `kind === 'select'`. Empty for other kinds. */
|
|
57040
57794
|
options: array(string()),
|
|
57041
57795
|
/** Ms epoch when the slice was last updated. */
|
|
57042
57796
|
lastChangedAt: number(),
|
|
57043
|
-
/**
|
|
57044
|
-
|
|
57045
|
-
|
|
57046
|
-
|
|
57047
|
-
/**
|
|
57048
|
-
|
|
57049
|
-
min: number().optional(),
|
|
57050
|
-
/** Maximum allowed value. Populated live from HA `attributes.max`.
|
|
57051
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
57052
|
-
max: number().optional(),
|
|
57053
|
-
/** Step increment. Populated live from HA `attributes.step`.
|
|
57054
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
57055
|
-
step: number().optional(),
|
|
57056
|
-
/** Suggested decimal places for numeric display. Populated live from HA
|
|
57057
|
-
* `attributes.suggested_display_precision`, or derived from `step` when the
|
|
57058
|
-
* HA attribute is absent. Meaningful for `kind === 'numeric'`; absent for
|
|
57059
|
-
* other kinds. Falls back to auto-formatting when absent. */
|
|
57060
|
-
precision: number().int().min(0).max(10).optional(),
|
|
57061
|
-
/** Date-picker granularity for `kind === 'datetime'`. 'date' → date-only,
|
|
57062
|
-
* 'time' → time-only, 'datetime' → full timestamp. Absent for other kinds
|
|
57063
|
-
* (UI defaults to 'datetime'). Derived live from the device's HA domain
|
|
57064
|
-
* (date.* / time.* / datetime.*) or, for input_datetime, from the entity's
|
|
57065
|
-
* `has_date`/`has_time` attributes on each push. */
|
|
57066
|
-
format: _enum([
|
|
57067
|
-
"date",
|
|
57068
|
-
"time",
|
|
57069
|
-
"datetime"
|
|
57070
|
-
]).optional()
|
|
57797
|
+
/** Minimum allowed value, in the device quantity's base unit. */
|
|
57798
|
+
min: number().optional().meta(readingMeta("device")),
|
|
57799
|
+
/** Maximum allowed value, in the device quantity's base unit. */
|
|
57800
|
+
max: number().optional().meta(readingMeta("device")),
|
|
57801
|
+
/** Step increment, in the device quantity's base unit. */
|
|
57802
|
+
step: number().optional().meta(readingMeta("device"))
|
|
57071
57803
|
});
|
|
57072
57804
|
var ControlSetValueInputSchema = discriminatedUnion("kind", [
|
|
57073
57805
|
object({
|
|
@@ -57105,9 +57837,9 @@ object({
|
|
|
57105
57837
|
]),
|
|
57106
57838
|
/** 0 = fully closed, 100 = fully open. Null when the device has
|
|
57107
57839
|
* no intermediate position surface. */
|
|
57108
|
-
position: number().min(0).max(100).nullable(),
|
|
57840
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
57109
57841
|
/** 0 = closed slats, 100 = open slats. Null when no tilt support. */
|
|
57110
|
-
tiltPosition: number().min(0).max(100).nullable(),
|
|
57842
|
+
tiltPosition: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
57111
57843
|
/** Ms epoch when the slice was last updated. */
|
|
57112
57844
|
lastChangedAt: number()
|
|
57113
57845
|
});
|
|
@@ -57165,9 +57897,9 @@ var NormalizedRangeSchema$1 = object({
|
|
|
57165
57897
|
object({
|
|
57166
57898
|
mode: DayNightModeSchema,
|
|
57167
57899
|
/** IR-cut trigger sensitivity, NORMALIZED 0–100 (higher = switches to night sooner). */
|
|
57168
|
-
sensitivity: number().optional(),
|
|
57900
|
+
sensitivity: number().optional().meta(readingMeta("none")),
|
|
57169
57901
|
/** Delay before the IR-cut filter flips, in seconds. */
|
|
57170
|
-
switchDelaySec: number().optional(),
|
|
57902
|
+
switchDelaySec: number().optional().meta(readingMeta("duration")),
|
|
57171
57903
|
lastFetchedAt: number()
|
|
57172
57904
|
});
|
|
57173
57905
|
/**
|
|
@@ -57322,11 +58054,11 @@ object({
|
|
|
57322
58054
|
/** Feature keys of the programs the appliance currently offers — drives the UI selector. */
|
|
57323
58055
|
availablePrograms: array(string()),
|
|
57324
58056
|
/** Seconds remaining on the active cycle, or null when not running / not known. */
|
|
57325
|
-
remainingSeconds: number().int().nonnegative().nullable(),
|
|
58057
|
+
remainingSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
57326
58058
|
/** Seconds the delayed start is set to (time until the cycle starts), or null. */
|
|
57327
|
-
delayedStartSeconds: number().int().nonnegative().nullable(),
|
|
58059
|
+
delayedStartSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
57328
58060
|
/** Cycle completion 0..100, or null when not applicable. */
|
|
57329
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
58061
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
57330
58062
|
/** True when the door is reported open; null when the door state is not known. */
|
|
57331
58063
|
doorOpen: boolean().nullable(),
|
|
57332
58064
|
/** True when the door is latched (locked) during a cycle; null when not reported. */
|
|
@@ -57350,7 +58082,7 @@ object({
|
|
|
57350
58082
|
/** True while the machine-care (descaling / cleaning-program) reminder is raised; false when clear; null when not reported. */
|
|
57351
58083
|
machineCareDue: boolean().nullable(),
|
|
57352
58084
|
/** Program runs left before the machine-care reminder is due; null when the appliance does not say. */
|
|
57353
|
-
machineCareRemainingRuns: number().int().nonnegative().nullable(),
|
|
58085
|
+
machineCareRemainingRuns: number().int().nonnegative().nullable().meta(readingMeta("count")),
|
|
57354
58086
|
/** Option states: null when the appliance does not expose the option or has not said. */
|
|
57355
58087
|
halfLoad: boolean().nullable(),
|
|
57356
58088
|
hygienePlus: boolean().nullable(),
|
|
@@ -57365,7 +58097,7 @@ object({
|
|
|
57365
58097
|
/** Feature keys of the events currently raised (salt low, rinse aid low, program finished, …). */
|
|
57366
58098
|
activeEvents: array(string()),
|
|
57367
58099
|
/** Numeric error code when the appliance reports one; null otherwise. */
|
|
57368
|
-
errorCode: number().nullable(),
|
|
58100
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
57369
58101
|
/** Name of the raised alert-level event while the appliance is in error; null otherwise. */
|
|
57370
58102
|
errorLabel: string().nullable(),
|
|
57371
58103
|
/** Ms epoch of the last value received from the appliance; 0 = never. */
|
|
@@ -57511,24 +58243,14 @@ object({
|
|
|
57511
58243
|
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
57512
58244
|
lastPressedAt: number().nullable(),
|
|
57513
58245
|
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
57514
|
-
pressCountSinceStart: number()
|
|
58246
|
+
pressCountSinceStart: number().meta(readingMeta("count"))
|
|
57515
58247
|
});
|
|
57516
58248
|
object({
|
|
57517
58249
|
deviceId: number(),
|
|
57518
58250
|
timestamp: number()
|
|
57519
58251
|
});
|
|
57520
58252
|
DeviceType.Button, DeviceType.Camera;
|
|
57521
|
-
|
|
57522
|
-
* Enum-state sensor — a string value picked from a finite option set.
|
|
57523
|
-
* Drives HA `sensor` entries with `state_class: enum` (HVAC action
|
|
57524
|
-
* states, weather conditions, contact-source channels, mode strings).
|
|
57525
|
-
* The option set is stable across observations; it is persisted in the
|
|
57526
|
-
* device config blob (via the control slice at adoption) and is NOT
|
|
57527
|
-
* stored in `sourceInfo`.
|
|
57528
|
-
*/
|
|
57529
|
-
/** Locale-render shape for an ISO `value` carried by a `DateTimeSensor`-role
|
|
57530
|
-
* enum sensor: `date` (date-only), `time` (time-only), `datetime` (both). */
|
|
57531
|
-
var EnumSensorDateTimeFormatSchema = _enum([
|
|
58253
|
+
_enum([
|
|
57532
58254
|
"date",
|
|
57533
58255
|
"time",
|
|
57534
58256
|
"datetime"
|
|
@@ -57536,12 +58258,11 @@ var EnumSensorDateTimeFormatSchema = _enum([
|
|
|
57536
58258
|
object({
|
|
57537
58259
|
value: string(),
|
|
57538
58260
|
/**
|
|
57539
|
-
* Set
|
|
57540
|
-
* as
|
|
57541
|
-
*
|
|
57542
|
-
* a time-only sensor → `'time'`.
|
|
58261
|
+
* Set when `value` is a timestamp rather than an enum state, so history
|
|
58262
|
+
* does not learn ISO strings as states. The display shape (date / time /
|
|
58263
|
+
* datetime) lives on `SourceInfo.dateTimeShape`, written once at adopt.
|
|
57543
58264
|
*/
|
|
57544
|
-
|
|
58265
|
+
timestamp: boolean().optional(),
|
|
57545
58266
|
/** Ms epoch when the slice was last updated. */
|
|
57546
58267
|
lastFetchedAt: number()
|
|
57547
58268
|
});
|
|
@@ -57560,13 +58281,13 @@ var EventFireSchema = object({
|
|
|
57560
58281
|
deviceId: number(),
|
|
57561
58282
|
eventType: string(),
|
|
57562
58283
|
data: record(string(), unknown()).nullable(),
|
|
57563
|
-
timestamp: number(),
|
|
57564
|
-
seq: number()
|
|
58284
|
+
timestamp: number().meta(readingMeta("none")),
|
|
58285
|
+
seq: number().meta(readingMeta("count"))
|
|
57565
58286
|
});
|
|
57566
58287
|
object({
|
|
57567
58288
|
eventTypes: array(string()),
|
|
57568
58289
|
lastEvent: EventFireSchema.nullable(),
|
|
57569
|
-
eventCountSinceStart: number()
|
|
58290
|
+
eventCountSinceStart: number().meta(readingMeta("count"))
|
|
57570
58291
|
});
|
|
57571
58292
|
DeviceType.EventEmitter;
|
|
57572
58293
|
var IdentitySchema = object({
|
|
@@ -57955,10 +58676,10 @@ var FanDirectionSchema = _enum(["forward", "reverse"]);
|
|
|
57955
58676
|
object({
|
|
57956
58677
|
/** Active speed as 0..100 inclusive. Null when the device has no
|
|
57957
58678
|
* speed surface (single-speed fan). */
|
|
57958
|
-
percentage: number().min(0).max(100).nullable(),
|
|
58679
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
57959
58680
|
/** Speed granularity the device accepts (HA `percentage_step`, e.g. 25 for
|
|
57960
58681
|
* a 4-speed fan). Absent when unknown — the UI then falls back to step 1. */
|
|
57961
|
-
percentageStep: number().positive().optional(),
|
|
58682
|
+
percentageStep: number().positive().optional().meta(readingMeta("percentage")),
|
|
57962
58683
|
/** Active preset mode (`auto` / `quiet` / `turbo` / vendor-specific)
|
|
57963
58684
|
* — empty string when no preset is active or supported. */
|
|
57964
58685
|
preset: string(),
|
|
@@ -58040,7 +58761,7 @@ var FeatureProbeStatusSchema = object({
|
|
|
58040
58761
|
/** Camera/firmware model string. `null` when the firmware doesn't expose it. */
|
|
58041
58762
|
model: string().nullable(),
|
|
58042
58763
|
/** Channel count for NVR/Hub devices; `1` for standalone cameras; `null` pre-probe. */
|
|
58043
|
-
channelCount: number().nullable(),
|
|
58764
|
+
channelCount: number().nullable().meta(readingMeta("count")),
|
|
58044
58765
|
/**
|
|
58045
58766
|
* Ms epoch of the last SUCCESSFUL probe. `0` before the first probe
|
|
58046
58767
|
* completes — drivers' `getAccessoryChildren()` should treat zero as
|
|
@@ -58072,9 +58793,45 @@ object({
|
|
|
58072
58793
|
lastChangedAt: number()
|
|
58073
58794
|
});
|
|
58074
58795
|
DeviceType.Sensor;
|
|
58796
|
+
object({
|
|
58797
|
+
/** One row per member that has been commanded. A later command replaces that member's row. */
|
|
58798
|
+
results: array(object({
|
|
58799
|
+
deviceId: number().int().nonnegative(),
|
|
58800
|
+
cap: string().min(1),
|
|
58801
|
+
method: string().min(1),
|
|
58802
|
+
ok: boolean(),
|
|
58803
|
+
error: string().optional(),
|
|
58804
|
+
/** Ms epoch of the attempt. */
|
|
58805
|
+
at: number()
|
|
58806
|
+
})) });
|
|
58807
|
+
DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Cover, DeviceType.Valve, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.Thermostat, DeviceType.Climate;
|
|
58808
|
+
object({
|
|
58809
|
+
active: boolean().meta({ label: "Active" }),
|
|
58810
|
+
/** Ms epoch when the slice was last updated. */
|
|
58811
|
+
lastChangedAt: number()
|
|
58812
|
+
});
|
|
58813
|
+
DeviceType.Cover, DeviceType.Valve, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.Climate, DeviceType.Thermostat;
|
|
58814
|
+
object({
|
|
58815
|
+
/** Members whose current value entered the aggregate. */
|
|
58816
|
+
included: number().int().nonnegative().meta(readingMeta("count", {
|
|
58817
|
+
precision: 0,
|
|
58818
|
+
label: "Reporting"
|
|
58819
|
+
})),
|
|
58820
|
+
/** Members left out: offline, unknown, or not a finite reading (D393). */
|
|
58821
|
+
excluded: number().int().nonnegative().meta(readingMeta("count", {
|
|
58822
|
+
precision: 0,
|
|
58823
|
+
label: "Excluded"
|
|
58824
|
+
})),
|
|
58825
|
+
/** `included` + `excluded`. */
|
|
58826
|
+
total: number().int().nonnegative().meta(readingMeta("count", {
|
|
58827
|
+
precision: 0,
|
|
58828
|
+
label: "Members"
|
|
58829
|
+
}))
|
|
58830
|
+
});
|
|
58831
|
+
DeviceType.Sensor, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Cover, DeviceType.Valve, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.Thermostat, DeviceType.Climate;
|
|
58075
58832
|
object({
|
|
58076
58833
|
/** Radiator valve opening 0 (closed) .. 100 (open). Null = not yet known. */
|
|
58077
|
-
position: number().min(0).max(100).nullable(),
|
|
58834
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58078
58835
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
58079
58836
|
lastFetchedAt: number()
|
|
58080
58837
|
});
|
|
@@ -58083,9 +58840,9 @@ object({
|
|
|
58083
58840
|
/** Whether the humidifier is currently on. */
|
|
58084
58841
|
on: boolean(),
|
|
58085
58842
|
/** Current measured relative humidity (0..100). Null when not reported. */
|
|
58086
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
58843
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
58087
58844
|
/** Target relative humidity (0..100). Null when no setpoint surface. */
|
|
58088
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
58845
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
58089
58846
|
/** Active mode (`auto` / `normal` / `baby` / vendor). Null when the
|
|
58090
58847
|
* device has no mode surface. */
|
|
58091
58848
|
mode: string().nullable(),
|
|
@@ -58095,9 +58852,9 @@ object({
|
|
|
58095
58852
|
* `idle` / `off`). Null when the device doesn't report it. */
|
|
58096
58853
|
action: string().nullable(),
|
|
58097
58854
|
/** HA `min_humidity` attribute. Null → UI uses 0. */
|
|
58098
|
-
minHumidity: number().nullable(),
|
|
58855
|
+
minHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
58099
58856
|
/** HA `max_humidity` attribute. Null → UI uses 100. */
|
|
58100
|
-
maxHumidity: number().nullable(),
|
|
58857
|
+
maxHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
58101
58858
|
/** Ms epoch when the slice was last updated. */
|
|
58102
58859
|
lastChangedAt: number()
|
|
58103
58860
|
});
|
|
@@ -58121,22 +58878,13 @@ DeviceType.Humidifier, method(object({
|
|
|
58121
58878
|
auth: "protected"
|
|
58122
58879
|
});
|
|
58123
58880
|
object({
|
|
58124
|
-
/** Current relative humidity, 0..100. */
|
|
58125
|
-
percent: number().min(0).max(100).meta({
|
|
58126
|
-
|
|
58881
|
+
/** Current relative humidity, 0..100. `null` when the sample was refused (D393). */
|
|
58882
|
+
percent: number().min(0).max(100).nullable().meta(readingMeta("humidity", {
|
|
58883
|
+
precision: 0,
|
|
58127
58884
|
label: "Humidity"
|
|
58128
|
-
}),
|
|
58885
|
+
})),
|
|
58129
58886
|
/** Ms epoch when the slice was last updated. */
|
|
58130
|
-
lastFetchedAt: number()
|
|
58131
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
58132
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
58133
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
58134
|
-
unit: string().optional(),
|
|
58135
|
-
/** Suggested decimal places for numeric display.
|
|
58136
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
58137
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
58138
|
-
* auto-formatting when absent. */
|
|
58139
|
-
precision: number().int().min(0).max(10).optional()
|
|
58887
|
+
lastFetchedAt: number()
|
|
58140
58888
|
});
|
|
58141
58889
|
DeviceType.Sensor, DeviceType.Thermostat;
|
|
58142
58890
|
object({
|
|
@@ -58144,7 +58892,7 @@ object({
|
|
|
58144
58892
|
* entity exposes no `entity_picture` (yet). */
|
|
58145
58893
|
url: string().nullable(),
|
|
58146
58894
|
/** Ms epoch of the upstream last-updated timestamp. Null at cold-start. */
|
|
58147
|
-
lastUpdated: number().nullable()
|
|
58895
|
+
lastUpdated: number().nullable().meta(readingMeta("none"))
|
|
58148
58896
|
});
|
|
58149
58897
|
DeviceType.Image;
|
|
58150
58898
|
/**
|
|
@@ -58200,19 +58948,19 @@ var NormalizedRangeSchema = object({
|
|
|
58200
58948
|
});
|
|
58201
58949
|
object({
|
|
58202
58950
|
/** Normalized 0–100. */
|
|
58203
|
-
brightness: number().optional(),
|
|
58951
|
+
brightness: number().optional().meta(readingMeta("none")),
|
|
58204
58952
|
/** Normalized 0–100. */
|
|
58205
|
-
contrast: number().optional(),
|
|
58953
|
+
contrast: number().optional().meta(readingMeta("none")),
|
|
58206
58954
|
/** Normalized 0–100. */
|
|
58207
|
-
saturation: number().optional(),
|
|
58955
|
+
saturation: number().optional().meta(readingMeta("none")),
|
|
58208
58956
|
/** Normalized 0–100. */
|
|
58209
|
-
sharpness: number().optional(),
|
|
58957
|
+
sharpness: number().optional().meta(readingMeta("none")),
|
|
58210
58958
|
mirror: boolean().optional(),
|
|
58211
58959
|
flip: boolean().optional(),
|
|
58212
58960
|
rotate: ImageRotateSchema.optional(),
|
|
58213
58961
|
whiteBalance: WhiteBalanceModeSchema.optional(),
|
|
58214
58962
|
/** Manual white-balance warmth, NORMALIZED 0–100. Meaningful only when `whiteBalance === 'manual'`. */
|
|
58215
|
-
warmth: number().optional(),
|
|
58963
|
+
warmth: number().optional().meta(readingMeta("none")),
|
|
58216
58964
|
exposureMode: ExposureModeSchema.optional(),
|
|
58217
58965
|
backlightMode: BacklightModeSchema.optional(),
|
|
58218
58966
|
lastFetchedAt: number()
|
|
@@ -58457,10 +59205,10 @@ var IntercomAbilitySchema = object({
|
|
|
58457
59205
|
/** Codecs accepted by firmware, in preference order. Driver-authored strings. */
|
|
58458
59206
|
codecs: array(string()),
|
|
58459
59207
|
/** Sample rate (Hz) the firmware expects. Reolink typical: 16000. */
|
|
58460
|
-
sampleRate: number(),
|
|
59208
|
+
sampleRate: number().meta(readingMeta("none")),
|
|
58461
59209
|
duplex: _enum(["half", "full"]),
|
|
58462
59210
|
/** Max in-flight audio backlog before drop (ms). Server uses this to bound latency. */
|
|
58463
|
-
maxBacklogMs: number()
|
|
59211
|
+
maxBacklogMs: number().meta(readingMeta("duration-ms"))
|
|
58464
59212
|
});
|
|
58465
59213
|
var IntercomStatusSchema = object({
|
|
58466
59214
|
/** True while a talk session is open. */
|
|
@@ -58571,13 +59319,13 @@ object({
|
|
|
58571
59319
|
activity: LawnMowerActivitySchema,
|
|
58572
59320
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
58573
59321
|
* reading. */
|
|
58574
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
59322
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58575
59323
|
/** 0..100 mowing-completion percentage of the current task, or null when no
|
|
58576
59324
|
* task is active / progress is unavailable. */
|
|
58577
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
59325
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
58578
59326
|
/** Current device/event code (dynamic — mostly status, sometimes an error),
|
|
58579
59327
|
* or null when unknown. */
|
|
58580
|
-
currentCode: number().nullable(),
|
|
59328
|
+
currentCode: number().nullable().meta(readingMeta("none")),
|
|
58581
59329
|
/** Human label for {@link currentCode}, or null when undecodable. */
|
|
58582
59330
|
currentCodeLabel: string().nullable(),
|
|
58583
59331
|
/** Severity of {@link currentCode}. `error` (and often `warning`) warrants UI
|
|
@@ -58987,7 +59735,14 @@ DeviceType.Lock, method(object({
|
|
|
58987
59735
|
auth: "protected"
|
|
58988
59736
|
}), method(object({
|
|
58989
59737
|
deviceId: number().int().nonnegative(),
|
|
58990
|
-
code: string().min(1).optional()
|
|
59738
|
+
code: string().min(1).optional(),
|
|
59739
|
+
/**
|
|
59740
|
+
* Honoured by a helper lock GROUP only (D944): unlocking several doors
|
|
59741
|
+
* with one call is refused unless the caller says it was confirmed. A
|
|
59742
|
+
* single lock ignores it. The refusal lives in the callee, so no
|
|
59743
|
+
* automation or API caller reaches the doors by skipping a dialog.
|
|
59744
|
+
*/
|
|
59745
|
+
confirm: boolean().optional()
|
|
58991
59746
|
}), _void(), {
|
|
58992
59747
|
kind: "mutation",
|
|
58993
59748
|
auth: "protected"
|
|
@@ -58995,6 +59750,11 @@ DeviceType.Lock, method(object({
|
|
|
58995
59750
|
kind: "mutation",
|
|
58996
59751
|
auth: "protected"
|
|
58997
59752
|
});
|
|
59753
|
+
object({
|
|
59754
|
+
value: number().nullable().meta(readingMeta("device", { label: "Total" })),
|
|
59755
|
+
lastFetchedAt: number()
|
|
59756
|
+
});
|
|
59757
|
+
DeviceType.Sensor;
|
|
58998
59758
|
/**
|
|
58999
59759
|
* Media-player cap. Models HA `media_player.*` (Sonos, Chromecast,
|
|
59000
59760
|
* Apple TV, Spotify, Roku, generic OTT receivers, …) on
|
|
@@ -59039,7 +59799,7 @@ object({
|
|
|
59039
59799
|
state: MediaPlayerStateSchema,
|
|
59040
59800
|
/** Volume as 0..100 inclusive. Null when the device has no volume
|
|
59041
59801
|
* surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
|
|
59042
|
-
volumeLevel: number().min(0).max(100).nullable(),
|
|
59802
|
+
volumeLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59043
59803
|
/** Mute toggle distinct from volume=0. Null when no mute surface.
|
|
59044
59804
|
* Pair with `DeviceFeature.MediaPlayerMute`. */
|
|
59045
59805
|
isMuted: boolean().nullable(),
|
|
@@ -59052,10 +59812,10 @@ object({
|
|
|
59052
59812
|
currentMedia: MediaInfoSchema.nullable(),
|
|
59053
59813
|
/** Current playback position in ms. Null when not seekable or
|
|
59054
59814
|
* nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
|
|
59055
|
-
positionMs: number().int().nonnegative().nullable(),
|
|
59815
|
+
positionMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
59056
59816
|
/** Total duration of the current media in ms. Null when unknown
|
|
59057
59817
|
* (live stream) or nothing is playing. */
|
|
59058
|
-
durationMs: number().int().nonnegative().nullable(),
|
|
59818
|
+
durationMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
59059
59819
|
/** Shuffle toggle. Null when no shuffle surface.
|
|
59060
59820
|
* Pair with `DeviceFeature.MediaPlayerShuffle`. */
|
|
59061
59821
|
shuffle: boolean().nullable(),
|
|
@@ -59355,7 +60115,7 @@ object({
|
|
|
59355
60115
|
* it, every provider seeded it at boot, and every session left it
|
|
59356
60116
|
* `detected: true` after its detach.
|
|
59357
60117
|
*/
|
|
59358
|
-
autoClearAfterMs: number().nullable()
|
|
60118
|
+
autoClearAfterMs: number().nullable().meta(readingMeta("duration-ms"))
|
|
59359
60119
|
});
|
|
59360
60120
|
/**
|
|
59361
60121
|
* Payload of `motion.onMotionChanged` event + the corresponding bus
|
|
@@ -59405,7 +60165,7 @@ var MotionZoneRegionSchema = object({
|
|
|
59405
60165
|
});
|
|
59406
60166
|
object({
|
|
59407
60167
|
enabled: boolean(),
|
|
59408
|
-
sensitivity: number(),
|
|
60168
|
+
sensitivity: number().meta(readingMeta("none")),
|
|
59409
60169
|
/** Grid region(s). Today exactly one `grid` shape. */
|
|
59410
60170
|
regions: array(MotionZoneRegionSchema),
|
|
59411
60171
|
lastFetchedAt: number()
|
|
@@ -59709,7 +60469,7 @@ var NavigationStatusSchema = object({
|
|
|
59709
60469
|
following: boolean(),
|
|
59710
60470
|
flash: boolean(),
|
|
59711
60471
|
lightMode: NavigationLightModeSchema,
|
|
59712
|
-
lightLevel: number().min(40).max(100),
|
|
60472
|
+
lightLevel: number().min(40).max(100).meta(readingMeta("none")),
|
|
59713
60473
|
/** Ms epoch when the slice was last updated. */
|
|
59714
60474
|
lastChangedAt: number()
|
|
59715
60475
|
});
|
|
@@ -59755,13 +60515,13 @@ var NetworkLinkStatusSchema = object({
|
|
|
59755
60515
|
* one whose reading has not landed must not be drawn at 0 %. Consumers
|
|
59756
60516
|
* SKIP a null rather than coerce it.
|
|
59757
60517
|
*/
|
|
59758
|
-
signalPercent: number().min(0).max(100).nullable(),
|
|
60518
|
+
signalPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59759
60519
|
/** Raw received signal strength in dBm, when the firmware reports one. */
|
|
59760
|
-
rssiDbm: number().optional(),
|
|
60520
|
+
rssiDbm: number().optional().meta(readingMeta("signal-level")),
|
|
59761
60521
|
/** Network name of a wireless link, when the firmware reports it. */
|
|
59762
60522
|
ssid: string().optional(),
|
|
59763
60523
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
59764
|
-
lastUpdated: number()
|
|
60524
|
+
lastUpdated: number().meta(readingMeta("none"))
|
|
59765
60525
|
});
|
|
59766
60526
|
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.Light, DeviceType.Lock, DeviceType.Siren, object({
|
|
59767
60527
|
deviceId: number(),
|
|
@@ -60080,7 +60840,7 @@ object({
|
|
|
60080
60840
|
lastError: string().nullable(),
|
|
60081
60841
|
/** Number of deliveries currently buffered server-side (rate-limited
|
|
60082
60842
|
* notifiers may queue). 0 when the provider sends synchronously. */
|
|
60083
|
-
queueDepth: number().int().nonnegative(),
|
|
60843
|
+
queueDepth: number().int().nonnegative().meta(readingMeta("count")),
|
|
60084
60844
|
/** Per-feature capability matrix — authoritative source for the
|
|
60085
60845
|
* compose-form field gating. */
|
|
60086
60846
|
supports: NotifierSupportsSchema
|
|
@@ -60130,15 +60890,8 @@ DeviceType.Notifier, method(NotifierSendInputSchema, NotifierSendResultSchema, {
|
|
|
60130
60890
|
acceptedAt: number()
|
|
60131
60891
|
});
|
|
60132
60892
|
object({
|
|
60133
|
-
|
|
60134
|
-
|
|
60135
|
-
* Populated live from the upstream source on each state push.
|
|
60136
|
-
* Absent for unitless sensors. */
|
|
60137
|
-
unit: string().optional(),
|
|
60138
|
-
/** Suggested decimal places for numeric display.
|
|
60139
|
-
* Populated live from the upstream source when provided.
|
|
60140
|
-
* Falls back to auto-formatting when absent. */
|
|
60141
|
-
precision: number().int().min(0).max(10).optional(),
|
|
60893
|
+
/** Reading in the device quantity's base unit. `null` when refused (D393). */
|
|
60894
|
+
value: number().nullable().meta(readingMeta("device")),
|
|
60142
60895
|
/** Ms epoch when the slice was last updated. */
|
|
60143
60896
|
lastFetchedAt: number()
|
|
60144
60897
|
});
|
|
@@ -60428,23 +61181,26 @@ object({
|
|
|
60428
61181
|
/** Food currently in the bowl (grams). Null when the device has not
|
|
60429
61182
|
* reported a reading yet. On dual-hopper models this is the combined
|
|
60430
61183
|
* bowl reading; per-hopper levels live in `food1`/`food2`. */
|
|
60431
|
-
foodLevel: number().nullable(),
|
|
61184
|
+
foodLevel: number().nullable().meta(readingMeta("none")),
|
|
60432
61185
|
/** Hopper-1 food level (grams) on dual-hopper feeders; null on
|
|
60433
61186
|
* single-hopper models. */
|
|
60434
|
-
food1: number().nullable(),
|
|
61187
|
+
food1: number().nullable().meta(readingMeta("none")),
|
|
60435
61188
|
/** Hopper-2 food level (grams) on dual-hopper feeders; null on
|
|
60436
61189
|
* single-hopper models. */
|
|
60437
|
-
food2: number().nullable(),
|
|
61190
|
+
food2: number().nullable().meta(readingMeta("none")),
|
|
60438
61191
|
/** Derived low-food flag — mirrors the HA `food_level` binary_sensor
|
|
60439
61192
|
* (`device_class: problem`, on = low). True when the bowl is empty /
|
|
60440
61193
|
* below the feeder's low threshold. */
|
|
60441
61194
|
lowFood: boolean(),
|
|
60442
61195
|
/** Battery charge 0..100 (%). Null on mains-powered models or when the
|
|
60443
61196
|
* device has no battery reading. */
|
|
60444
|
-
batteryPower: number().min(0).max(100).nullable(),
|
|
60445
|
-
/**
|
|
60446
|
-
*
|
|
60447
|
-
|
|
61197
|
+
batteryPower: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61198
|
+
/**
|
|
61199
|
+
* Desiccant life remaining, stored in seconds (duration base, D944).
|
|
61200
|
+
* Providers convert from the days the feeder reports. Null when the
|
|
61201
|
+
* model has no desiccant sensor.
|
|
61202
|
+
*/
|
|
61203
|
+
desiccantLeftDays: number().nullable().meta(readingMeta("duration")),
|
|
60448
61204
|
/** True while a feed is in progress. */
|
|
60449
61205
|
feeding: boolean(),
|
|
60450
61206
|
/** Decoded connectivity / power status (HA petkit device-status enum).
|
|
@@ -60455,7 +61211,7 @@ object({
|
|
|
60455
61211
|
* with `errorCode` for consumers that want the raw integer. */
|
|
60456
61212
|
error: string().nullable(),
|
|
60457
61213
|
/** Raw device error code (0 / null = no error). */
|
|
60458
|
-
errorCode: number().nullable(),
|
|
61214
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
60459
61215
|
/** True for D4S/D4SH dual-hopper hardware — gates the per-hopper UI. */
|
|
60460
61216
|
isDualHopper: boolean(),
|
|
60461
61217
|
/** Child-lock (manual-lock) setting — buttons on the unit are disabled. */
|
|
@@ -60465,7 +61221,7 @@ object({
|
|
|
60465
61221
|
/** Play a chime when dispensing. */
|
|
60466
61222
|
feedSound: boolean(),
|
|
60467
61223
|
/** Speaker / prompt volume level (device-scaled integer). */
|
|
60468
|
-
volume: number(),
|
|
61224
|
+
volume: number().meta(readingMeta("none")),
|
|
60469
61225
|
/** Ms epoch when the slice was last refreshed from the cloud. */
|
|
60470
61226
|
lastFetchedAt: number()
|
|
60471
61227
|
});
|
|
@@ -60902,38 +61658,37 @@ method(_void(), PlatformCapabilitiesSchema), method(_void(), HardwareInfoSchema)
|
|
|
60902
61658
|
});
|
|
60903
61659
|
object({
|
|
60904
61660
|
/** Instantaneous power draw in watts. */
|
|
60905
|
-
watts: number().optional().meta({
|
|
60906
|
-
unit: "W",
|
|
60907
|
-
label: "Power"
|
|
60908
|
-
}),
|
|
61661
|
+
watts: number().optional().meta(readingMeta("power", { label: "Power" })),
|
|
60909
61662
|
/** Cumulative energy in kilowatt-hours since the meter was reset. */
|
|
60910
|
-
kwhTotal: number().optional().meta({
|
|
60911
|
-
unit: "kWh",
|
|
60912
|
-
label: "Energy"
|
|
60913
|
-
}),
|
|
61663
|
+
kwhTotal: number().optional().meta(readingMeta("energy", { label: "Energy" })),
|
|
60914
61664
|
/** Voltage in volts. */
|
|
60915
|
-
volts: number().optional(),
|
|
61665
|
+
volts: number().optional().meta(readingMeta("voltage", { label: "Voltage" })),
|
|
60916
61666
|
/** Current in amperes. */
|
|
60917
|
-
amps: number().optional(),
|
|
60918
|
-
/** Apparent power in volt-amperes
|
|
60919
|
-
va: number().optional(),
|
|
61667
|
+
amps: number().optional().meta(readingMeta("current", { label: "Current" })),
|
|
61668
|
+
/** Apparent power in volt-amperes. */
|
|
61669
|
+
va: number().optional().meta(readingMeta("apparent-power")),
|
|
60920
61670
|
/** Power factor (0..1) if reported. */
|
|
60921
|
-
powerFactor: number().min(0).max(1).optional(),
|
|
61671
|
+
powerFactor: number().min(0).max(1).optional().meta(readingMeta("ratio")),
|
|
60922
61672
|
/** Ms epoch when the slice was last updated. */
|
|
60923
|
-
lastFetchedAt: number()
|
|
60924
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
60925
|
-
* `attributes.unit_of_measurement` → 'V' / 'A' / 'W' / 'kW' / 'kWh').
|
|
60926
|
-
* Each upstream `sensor.*` entity surfaces ONE device_class, so one
|
|
60927
|
-
* unit per slice is unambiguous. The UI prefers this over the role's
|
|
60928
|
-
* canonical unit so a 'kW' / 'Wh' feed renders verbatim. */
|
|
60929
|
-
unit: string().optional(),
|
|
60930
|
-
/** Suggested decimal places for numeric display.
|
|
60931
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
60932
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
60933
|
-
* auto-formatting when absent. */
|
|
60934
|
-
precision: number().int().min(0).max(10).optional()
|
|
61673
|
+
lastFetchedAt: number()
|
|
60935
61674
|
});
|
|
60936
|
-
|
|
61675
|
+
[
|
|
61676
|
+
DeviceType.Sensor,
|
|
61677
|
+
DeviceType.Switch,
|
|
61678
|
+
DeviceType.Light,
|
|
61679
|
+
DeviceType.Fan,
|
|
61680
|
+
DeviceType.Climate,
|
|
61681
|
+
DeviceType.Thermostat,
|
|
61682
|
+
DeviceType.Humidifier,
|
|
61683
|
+
DeviceType.WaterHeater,
|
|
61684
|
+
DeviceType.MediaPlayer,
|
|
61685
|
+
DeviceType.Washer,
|
|
61686
|
+
DeviceType.Dryer,
|
|
61687
|
+
DeviceType.Dishwasher,
|
|
61688
|
+
DeviceType.Vacuum,
|
|
61689
|
+
DeviceType.LawnMower,
|
|
61690
|
+
DeviceType.PetFeeder
|
|
61691
|
+
].filter((type) => type !== DeviceType.Sensor);
|
|
60937
61692
|
/**
|
|
60938
61693
|
* Presence cap. Models HA `person.*` and `device_tracker.*` entities
|
|
60939
61694
|
* on `DeviceType.Presence`. Read-only — no setters: presence is
|
|
@@ -60952,11 +61707,11 @@ DeviceType.Sensor;
|
|
|
60952
61707
|
*/
|
|
60953
61708
|
var GpsLocationSchema = object({
|
|
60954
61709
|
/** Latitude in decimal degrees, -90..90. */
|
|
60955
|
-
latitude: number().min(-90).max(90),
|
|
61710
|
+
latitude: number().min(-90).max(90).meta(readingMeta("angle")),
|
|
60956
61711
|
/** Longitude in decimal degrees, -180..180. */
|
|
60957
|
-
longitude: number().min(-180).max(180),
|
|
61712
|
+
longitude: number().min(-180).max(180).meta(readingMeta("angle")),
|
|
60958
61713
|
/** Reported accuracy in meters (lower = better). */
|
|
60959
|
-
accuracyMeters: number().nonnegative()
|
|
61714
|
+
accuracyMeters: number().nonnegative().meta(readingMeta("length"))
|
|
60960
61715
|
});
|
|
60961
61716
|
object({
|
|
60962
61717
|
/** `home` / `not_home` / any user-defined zone name. */
|
|
@@ -60968,25 +61723,16 @@ object({
|
|
|
60968
61723
|
gps: GpsLocationSchema.nullable(),
|
|
60969
61724
|
/** Optional battery level of the tracking device (0..100). Null
|
|
60970
61725
|
* when not reported. */
|
|
60971
|
-
batteryPercent: number().min(0).max(100).nullable(),
|
|
61726
|
+
batteryPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
60972
61727
|
/** Ms epoch when the slice was last updated. */
|
|
60973
61728
|
lastChangedAt: number()
|
|
60974
61729
|
});
|
|
60975
61730
|
DeviceType.Presence;
|
|
60976
61731
|
object({
|
|
60977
|
-
/** Current pressure in hPa. */
|
|
60978
|
-
hpa: number(),
|
|
61732
|
+
/** Current pressure in hPa. `null` when the sample was refused (D393). */
|
|
61733
|
+
hpa: number().nullable().meta(readingMeta("pressure", { precision: 0 })),
|
|
60979
61734
|
/** Ms epoch when the slice was last updated. */
|
|
60980
|
-
lastFetchedAt: number()
|
|
60981
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
60982
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
60983
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
60984
|
-
unit: string().optional(),
|
|
60985
|
-
/** Suggested decimal places for numeric display.
|
|
60986
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
60987
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
60988
|
-
* auto-formatting when absent. */
|
|
60989
|
-
precision: number().int().min(0).max(10).optional()
|
|
61735
|
+
lastFetchedAt: number()
|
|
60990
61736
|
});
|
|
60991
61737
|
DeviceType.Sensor;
|
|
60992
61738
|
/**
|
|
@@ -61411,8 +62157,8 @@ var ptzCapability = {
|
|
|
61411
62157
|
};
|
|
61412
62158
|
var PtzAutotrackSettingsSchema = object({
|
|
61413
62159
|
targetType: string().describe("Vendor target string (people/vehicle/pet); empty = camera default"),
|
|
61414
|
-
stopDelaySeconds: number().int().min(0).max(300),
|
|
61415
|
-
disappearDelaySeconds: number().int().min(0).max(300)
|
|
62160
|
+
stopDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration")),
|
|
62161
|
+
disappearDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration"))
|
|
61416
62162
|
});
|
|
61417
62163
|
/**
|
|
61418
62164
|
* One option the camera advertises as a valid `targetType`. Drivers
|
|
@@ -61469,7 +62215,7 @@ object({
|
|
|
61469
62215
|
/** null = unknown — never coerced to false (D393). */
|
|
61470
62216
|
running: boolean().nullable(),
|
|
61471
62217
|
/** Epoch ms the current boolean began; null while `running` is null. */
|
|
61472
|
-
since: number().nullable(),
|
|
62218
|
+
since: number().nullable().meta(readingMeta("none")),
|
|
61473
62219
|
source: RunningStateSourceSchema.meta({ label: "Source" }),
|
|
61474
62220
|
phase: string().nullable(),
|
|
61475
62221
|
/** null until a reading has been published (D393). */
|
|
@@ -61481,7 +62227,7 @@ object({
|
|
|
61481
62227
|
phase: string().nullable()
|
|
61482
62228
|
});
|
|
61483
62229
|
Object.values(DeviceType);
|
|
61484
|
-
DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
|
|
62230
|
+
DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
|
|
61485
62231
|
DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch, method(object({ deviceId: number().int().nonnegative() }), object({ success: literal(true) }), {
|
|
61486
62232
|
kind: "mutation",
|
|
61487
62233
|
auth: "admin"
|
|
@@ -62667,9 +63413,9 @@ var RecordTriggerSchema = _enum([
|
|
|
62667
63413
|
*/
|
|
62668
63414
|
var RecordWindowSchema = object({
|
|
62669
63415
|
trigger: RecordTriggerSchema,
|
|
62670
|
-
day: number().int().min(0).max(6),
|
|
62671
|
-
startMinute: number().int().min(0).max(1439),
|
|
62672
|
-
endMinute: number().int().min(1).max(1440)
|
|
63416
|
+
day: number().int().min(0).max(6).meta(readingMeta("none")),
|
|
63417
|
+
startMinute: number().int().min(0).max(1439).meta(readingMeta("none")),
|
|
63418
|
+
endMinute: number().int().min(1).max(1440).meta(readingMeta("none"))
|
|
62673
63419
|
});
|
|
62674
63420
|
/** Status of one physical volume, as the camera itself describes it. */
|
|
62675
63421
|
var OnboardStorageVolumeSchema = object({
|
|
@@ -62738,10 +63484,10 @@ object({
|
|
|
62738
63484
|
/** Master "record to the card at all" switch. */
|
|
62739
63485
|
enabled: boolean().nullable(),
|
|
62740
63486
|
overwriteWhenFull: boolean().nullable(),
|
|
62741
|
-
preRecordSec: number().nullable(),
|
|
62742
|
-
postRecordSec: number().nullable(),
|
|
63487
|
+
preRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
63488
|
+
postRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
62743
63489
|
/** Length of one recorded file, in minutes. */
|
|
62744
|
-
segmentMinutes: number().nullable(),
|
|
63490
|
+
segmentMinutes: number().nullable().meta(readingMeta("none")),
|
|
62745
63491
|
/** The primary track's weekly windows, flattened. */
|
|
62746
63492
|
windows: array(RecordWindowSchema),
|
|
62747
63493
|
/**
|
|
@@ -62757,7 +63503,7 @@ object({
|
|
|
62757
63503
|
* provider reporting a non-zero count also reports the schedule as not
|
|
62758
63504
|
* writable.
|
|
62759
63505
|
*/
|
|
62760
|
-
unreadableWindows: number(),
|
|
63506
|
+
unreadableWindows: number().meta(readingMeta("count")),
|
|
62761
63507
|
/**
|
|
62762
63508
|
* The camera is scheduled to record and has NO usable storage.
|
|
62763
63509
|
*
|
|
@@ -63394,7 +64140,7 @@ var CamStreamDescriptorSchema = object({
|
|
|
63394
64140
|
url: string().optional(),
|
|
63395
64141
|
codec: string().optional(),
|
|
63396
64142
|
resolution: CamStreamResolutionSchema.optional(),
|
|
63397
|
-
fps: number().positive().optional(),
|
|
64143
|
+
fps: number().positive().optional().meta(readingMeta("rate")),
|
|
63398
64144
|
label: string().optional(),
|
|
63399
64145
|
/** Device-level features (e.g. `battery-operated`) — drives broker policy. */
|
|
63400
64146
|
deviceFeatures: array(string()).optional(),
|
|
@@ -63424,18 +64170,18 @@ var StreamProfileSchema = _enum([
|
|
|
63424
64170
|
]);
|
|
63425
64171
|
/** The current encoding config of one stream profile. */
|
|
63426
64172
|
var StreamProfileConfigSchema = object({
|
|
63427
|
-
width: number(),
|
|
63428
|
-
height: number(),
|
|
64173
|
+
width: number().meta(readingMeta("none")),
|
|
64174
|
+
height: number().meta(readingMeta("none")),
|
|
63429
64175
|
codec: _enum(["h264", "h265"]),
|
|
63430
|
-
framerate: number(),
|
|
63431
|
-
bitrate: number(),
|
|
64176
|
+
framerate: number().meta(readingMeta("rate")),
|
|
64177
|
+
bitrate: number().meta(readingMeta("bitrate")),
|
|
63432
64178
|
bitrateMode: _enum(["vbr", "cbr"]).optional(),
|
|
63433
64179
|
encoderProfile: _enum([
|
|
63434
64180
|
"high",
|
|
63435
64181
|
"main",
|
|
63436
64182
|
"baseline"
|
|
63437
64183
|
]).optional(),
|
|
63438
|
-
gop: number().optional(),
|
|
64184
|
+
gop: number().optional().meta(readingMeta("none")),
|
|
63439
64185
|
/**
|
|
63440
64186
|
* Whether THIS profile currently carries an audio track. READ-ONLY here.
|
|
63441
64187
|
*
|
|
@@ -63520,7 +64266,7 @@ object({
|
|
|
63520
64266
|
/** Ms epoch of the last state change. Useful for UI "X minutes ago". */
|
|
63521
64267
|
lastChangedAt: number()
|
|
63522
64268
|
});
|
|
63523
|
-
DeviceType.Switch, DeviceType.Siren, DeviceType.Light, method(object({
|
|
64269
|
+
DeviceType.Switch, DeviceType.Siren, DeviceType.Light, DeviceType.Fan, method(object({
|
|
63524
64270
|
deviceId: number(),
|
|
63525
64271
|
on: boolean()
|
|
63526
64272
|
}), _void(), {
|
|
@@ -64078,23 +64824,13 @@ object({
|
|
|
64078
64824
|
});
|
|
64079
64825
|
DeviceType.Sensor;
|
|
64080
64826
|
object({
|
|
64081
|
-
/** Current temperature in Celsius. */
|
|
64082
|
-
celsius: number().meta({
|
|
64083
|
-
|
|
64827
|
+
/** Current temperature in Celsius. `null` when the sample was refused (D393). */
|
|
64828
|
+
celsius: number().nullable().meta(readingMeta("temperature", {
|
|
64829
|
+
precision: 1,
|
|
64084
64830
|
label: "Temperature"
|
|
64085
|
-
}),
|
|
64831
|
+
})),
|
|
64086
64832
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
64087
|
-
lastFetchedAt: number()
|
|
64088
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
64089
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
64090
|
-
* role's canonical unit, so a Fahrenheit feed renders '°F' not '°C'.
|
|
64091
|
-
* Absent → the UI falls back to the role's canonical unit. */
|
|
64092
|
-
unit: string().optional(),
|
|
64093
|
-
/** Suggested decimal places for numeric display.
|
|
64094
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
64095
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
64096
|
-
* auto-formatting when absent. */
|
|
64097
|
-
precision: number().int().min(0).max(10).optional()
|
|
64833
|
+
lastFetchedAt: number()
|
|
64098
64834
|
});
|
|
64099
64835
|
DeviceType.Sensor, DeviceType.Thermostat;
|
|
64100
64836
|
/**
|
|
@@ -64346,16 +65082,16 @@ object({
|
|
|
64346
65082
|
]),
|
|
64347
65083
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
64348
65084
|
* reading. */
|
|
64349
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
65085
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
64350
65086
|
/** Current fan-speed token (provider-verbatim). Null when unknown or
|
|
64351
65087
|
* the vacuum has no speed control. */
|
|
64352
65088
|
fanSpeed: string().nullable(),
|
|
64353
65089
|
/** Speed tokens the hardware accepts — drives the UI selector. */
|
|
64354
65090
|
availableFanSpeeds: array(string()),
|
|
64355
65091
|
/** 0..100 cleaning-completion percentage of the current task, or null. */
|
|
64356
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
65092
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
64357
65093
|
/** Current error code (0 / null = no error). */
|
|
64358
|
-
errorCode: number().nullable(),
|
|
65094
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
64359
65095
|
/** Human label for {@link errorCode}, or null when none / undecodable. */
|
|
64360
65096
|
errorLabel: string().nullable(),
|
|
64361
65097
|
/** Ms epoch when the slice was last updated. */
|
|
@@ -64394,7 +65130,7 @@ object({
|
|
|
64394
65130
|
]),
|
|
64395
65131
|
/** 0 = fully closed, 100 = fully open. Null when the device has no
|
|
64396
65132
|
* intermediate position surface. */
|
|
64397
|
-
position: number().min(0).max(100).nullable(),
|
|
65133
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
64398
65134
|
/** Ms epoch when the slice was last updated. */
|
|
64399
65135
|
lastChangedAt: number()
|
|
64400
65136
|
});
|
|
@@ -64422,9 +65158,9 @@ object({
|
|
|
64422
65158
|
DeviceType.Sensor;
|
|
64423
65159
|
object({
|
|
64424
65160
|
/** Current measured temperature. Null when not reported. */
|
|
64425
|
-
currentTemp: number().nullable(),
|
|
65161
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
64426
65162
|
/** Target temperature setpoint. Null when no setpoint surface. */
|
|
64427
|
-
targetTemp: number().nullable(),
|
|
65163
|
+
targetTemp: number().nullable().meta(readingMeta("temperature")),
|
|
64428
65164
|
/** Active operation mode = HA `state` (`eco` / `electric` / `gas` /
|
|
64429
65165
|
* `heat_pump` / `high_demand` / `performance` / `off`). Null when the
|
|
64430
65166
|
* device reports an unknown state. */
|
|
@@ -64435,9 +65171,9 @@ object({
|
|
|
64435
65171
|
* has no away surface. */
|
|
64436
65172
|
away: boolean().nullable(),
|
|
64437
65173
|
/** HA `min_temp` attribute. Null when not reported. */
|
|
64438
|
-
minTemp: number().nullable(),
|
|
65174
|
+
minTemp: number().nullable().meta(readingMeta("temperature")),
|
|
64439
65175
|
/** HA `max_temp` attribute. Null when not reported. */
|
|
64440
|
-
maxTemp: number().nullable(),
|
|
65176
|
+
maxTemp: number().nullable().meta(readingMeta("temperature")),
|
|
64441
65177
|
/** Ms epoch when the slice was last updated. */
|
|
64442
65178
|
lastChangedAt: number()
|
|
64443
65179
|
});
|
|
@@ -64461,25 +65197,18 @@ DeviceType.WaterHeater, method(object({
|
|
|
64461
65197
|
auth: "protected"
|
|
64462
65198
|
});
|
|
64463
65199
|
object({
|
|
64464
|
-
/** Verbatim
|
|
64465
|
-
* when no condition has been reported yet. */
|
|
65200
|
+
/** Verbatim condition state (`sunny`, `cloudy`, `rainy`, …). Null when none yet. */
|
|
64466
65201
|
condition: string().nullable(),
|
|
64467
|
-
/** Current temperature in
|
|
64468
|
-
temperature: number().nullable(),
|
|
64469
|
-
/** Temperature unit string (e.g. `°C` / `°F`). Null when not provided. */
|
|
64470
|
-
temperatureUnit: string().nullable(),
|
|
65202
|
+
/** Current temperature in Celsius. Null when not provided or refused. */
|
|
65203
|
+
temperature: number().nullable().meta(readingMeta("temperature", { precision: 1 })),
|
|
64471
65204
|
/** Relative humidity (0..100). Null when not provided. */
|
|
64472
|
-
humidity: number().min(0).max(100).nullable(),
|
|
64473
|
-
/** Barometric pressure in
|
|
64474
|
-
pressure: number().nullable(),
|
|
64475
|
-
/**
|
|
64476
|
-
|
|
64477
|
-
/** Wind speed in the reported unit. Null when not provided. */
|
|
64478
|
-
windSpeed: number().nullable(),
|
|
64479
|
-
/** Wind-speed unit string (e.g. `km/h` / `mph`). Null when not provided. */
|
|
64480
|
-
windSpeedUnit: string().nullable(),
|
|
65205
|
+
humidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
65206
|
+
/** Barometric pressure in hPa. Null when not provided or refused. */
|
|
65207
|
+
pressure: number().nullable().meta(readingMeta("pressure")),
|
|
65208
|
+
/** Wind speed in metres per second. Null when not provided or refused. */
|
|
65209
|
+
windSpeed: number().nullable().meta(readingMeta("speed")),
|
|
64481
65210
|
/** Wind bearing in degrees (0..360, meteorological). Null when not provided. */
|
|
64482
|
-
windBearing: number().nullable(),
|
|
65211
|
+
windBearing: number().nullable().meta(readingMeta("angle")),
|
|
64483
65212
|
/** Ms epoch when the slice was last updated. */
|
|
64484
65213
|
lastFetchedAt: number()
|
|
64485
65214
|
});
|
|
@@ -65229,8 +65958,9 @@ method(object({}), array(TrainingBaseModelSchema).readonly(), { auth: "admin" })
|
|
|
65229
65958
|
kind: "mutation",
|
|
65230
65959
|
auth: "admin"
|
|
65231
65960
|
});
|
|
65961
|
+
DeviceFeature.FanSpeed, DeviceFeature.FanPreset, DeviceFeature.FanDirection, DeviceFeature.FanOscillating, DeviceFeature.CoverPositionable, DeviceFeature.CoverTilt, DeviceFeature.ValvePositionable, DeviceFeature.MediaPlayerVolume, DeviceFeature.ClimateFanMode;
|
|
65232
65962
|
SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
|
|
65233
|
-
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;
|
|
65963
|
+
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;
|
|
65234
65964
|
String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
|
|
65235
65965
|
DeviceRole.BinarySensor, DeviceRole.MotionSensor;
|
|
65236
65966
|
new Set(CAP_NAMES);
|
|
@@ -66108,7 +66838,7 @@ var BaseDeviceProvider = class extends BaseAddon {
|
|
|
66108
66838
|
return toDeviceSummary(device, this.addonId);
|
|
66109
66839
|
}
|
|
66110
66840
|
};
|
|
66111
|
-
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;
|
|
66841
|
+
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;
|
|
66112
66842
|
new Set(Object.values(DeviceType));
|
|
66113
66843
|
Object.freeze({
|
|
66114
66844
|
"accessories.getStatus": {
|
|
@@ -66216,6 +66946,13 @@ Object.freeze({
|
|
|
66216
66946
|
access: "view",
|
|
66217
66947
|
role: "admin"
|
|
66218
66948
|
},
|
|
66949
|
+
"addons.getPackageDocs": {
|
|
66950
|
+
capName: "addons",
|
|
66951
|
+
capScope: "system",
|
|
66952
|
+
addonId: null,
|
|
66953
|
+
access: "view",
|
|
66954
|
+
role: "admin"
|
|
66955
|
+
},
|
|
66219
66956
|
"addons.getVersions": {
|
|
66220
66957
|
capName: "addons",
|
|
66221
66958
|
capScope: "system",
|
|
@@ -69324,6 +70061,27 @@ Object.freeze({
|
|
|
69324
70061
|
access: "view",
|
|
69325
70062
|
role: "viewer"
|
|
69326
70063
|
},
|
|
70064
|
+
"groupActive.getStatus": {
|
|
70065
|
+
capName: "group-active",
|
|
70066
|
+
capScope: "device",
|
|
70067
|
+
addonId: null,
|
|
70068
|
+
access: "view",
|
|
70069
|
+
role: "viewer"
|
|
70070
|
+
},
|
|
70071
|
+
"groupCommands.getStatus": {
|
|
70072
|
+
capName: "group-commands",
|
|
70073
|
+
capScope: "device",
|
|
70074
|
+
addonId: null,
|
|
70075
|
+
access: "view",
|
|
70076
|
+
role: "viewer"
|
|
70077
|
+
},
|
|
70078
|
+
"groupStatus.getStatus": {
|
|
70079
|
+
capName: "group-status",
|
|
70080
|
+
capScope: "device",
|
|
70081
|
+
addonId: null,
|
|
70082
|
+
access: "view",
|
|
70083
|
+
role: "viewer"
|
|
70084
|
+
},
|
|
69327
70085
|
"heatingValve.getStatus": {
|
|
69328
70086
|
capName: "heating-valve",
|
|
69329
70087
|
capScope: "device",
|
|
@@ -70276,6 +71034,13 @@ Object.freeze({
|
|
|
70276
71034
|
access: "create",
|
|
70277
71035
|
role: "admin"
|
|
70278
71036
|
},
|
|
71037
|
+
"meter.getStatus": {
|
|
71038
|
+
capName: "meter",
|
|
71039
|
+
capScope: "device",
|
|
71040
|
+
addonId: null,
|
|
71041
|
+
access: "view",
|
|
71042
|
+
role: "viewer"
|
|
71043
|
+
},
|
|
70279
71044
|
"metricsProvider.collectSnapshot": {
|
|
70280
71045
|
capName: "metrics-provider",
|
|
70281
71046
|
capScope: "system",
|
|
@@ -78374,7 +79139,39 @@ var APPLIANCE_CAP_VOCABULARY = {
|
|
|
78374
79139
|
phrase: t("When {device} finishes", "Quando {device} finisce"),
|
|
78375
79140
|
icon: "square"
|
|
78376
79141
|
}
|
|
78377
|
-
}
|
|
79142
|
+
},
|
|
79143
|
+
overrides: { byType: {
|
|
79144
|
+
[DeviceType.Washer]: {
|
|
79145
|
+
state: { running: {
|
|
79146
|
+
whenTrue: t("When the washing machine starts", "Quando la lavatrice inizia"),
|
|
79147
|
+
whenFalse: t("When the washing machine has finished", "Quando la lavatrice ha finito")
|
|
79148
|
+
} },
|
|
79149
|
+
events: {
|
|
79150
|
+
onStarted: { phrase: t("When the washing machine starts", "Quando la lavatrice inizia") },
|
|
79151
|
+
onFinished: { phrase: t("When the washing machine has finished", "Quando la lavatrice ha finito") }
|
|
79152
|
+
}
|
|
79153
|
+
},
|
|
79154
|
+
[DeviceType.Dryer]: {
|
|
79155
|
+
state: { running: {
|
|
79156
|
+
whenTrue: t("When the dryer starts", "Quando l'asciugatrice inizia"),
|
|
79157
|
+
whenFalse: t("When the dryer has finished", "Quando l'asciugatrice ha finito")
|
|
79158
|
+
} },
|
|
79159
|
+
events: {
|
|
79160
|
+
onStarted: { phrase: t("When the dryer starts", "Quando l'asciugatrice inizia") },
|
|
79161
|
+
onFinished: { phrase: t("When the dryer has finished", "Quando l'asciugatrice ha finito") }
|
|
79162
|
+
}
|
|
79163
|
+
},
|
|
79164
|
+
[DeviceType.Dishwasher]: {
|
|
79165
|
+
state: { running: {
|
|
79166
|
+
whenTrue: t("When the dishwasher starts", "Quando la lavastoviglie inizia"),
|
|
79167
|
+
whenFalse: t("When the dishwasher has finished", "Quando la lavastoviglie ha finito")
|
|
79168
|
+
} },
|
|
79169
|
+
events: {
|
|
79170
|
+
onStarted: { phrase: t("When the dishwasher starts", "Quando la lavastoviglie inizia") },
|
|
79171
|
+
onFinished: { phrase: t("When the dishwasher has finished", "Quando la lavastoviglie ha finito") }
|
|
79172
|
+
}
|
|
79173
|
+
}
|
|
79174
|
+
} }
|
|
78378
79175
|
},
|
|
78379
79176
|
update: {
|
|
78380
79177
|
scope: "device",
|
|
@@ -79146,6 +79943,41 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
79146
79943
|
icon: "flame"
|
|
79147
79944
|
}]
|
|
79148
79945
|
},
|
|
79946
|
+
"group-active": {
|
|
79947
|
+
scope: "device",
|
|
79948
|
+
noun: t("Group state", "Stato del gruppo")
|
|
79949
|
+
},
|
|
79950
|
+
"group-commands": {
|
|
79951
|
+
scope: "device",
|
|
79952
|
+
noun: t("Group command", "Comando di gruppo")
|
|
79953
|
+
},
|
|
79954
|
+
"group-status": {
|
|
79955
|
+
scope: "device",
|
|
79956
|
+
noun: t("Group", "Gruppo"),
|
|
79957
|
+
state: [
|
|
79958
|
+
{
|
|
79959
|
+
kind: "numeric",
|
|
79960
|
+
field: "included",
|
|
79961
|
+
quantity: t("the members reporting", "i membri che rispondono"),
|
|
79962
|
+
label: t("Reporting", "Rispondono"),
|
|
79963
|
+
icon: "users"
|
|
79964
|
+
},
|
|
79965
|
+
{
|
|
79966
|
+
kind: "numeric",
|
|
79967
|
+
field: "excluded",
|
|
79968
|
+
quantity: t("the members left out", "i membri esclusi"),
|
|
79969
|
+
label: t("Excluded", "Esclusi"),
|
|
79970
|
+
icon: "users"
|
|
79971
|
+
},
|
|
79972
|
+
{
|
|
79973
|
+
kind: "numeric",
|
|
79974
|
+
field: "total",
|
|
79975
|
+
quantity: t("the member count", "il numero di membri"),
|
|
79976
|
+
label: t("Members", "Membri"),
|
|
79977
|
+
icon: "sigma"
|
|
79978
|
+
}
|
|
79979
|
+
]
|
|
79980
|
+
},
|
|
79149
79981
|
"humidity-sensor": {
|
|
79150
79982
|
scope: "device",
|
|
79151
79983
|
noun: t("Humidity", "Umidità"),
|
|
@@ -79171,6 +80003,17 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
79171
80003
|
}],
|
|
79172
80004
|
events: { onMotionChanged: { notOperatorFacing: "the `detected` state trigger phrases both edges, from the mirror that survives a dropped event (D49)" } }
|
|
79173
80005
|
},
|
|
80006
|
+
meter: {
|
|
80007
|
+
scope: "device",
|
|
80008
|
+
noun: t("Meter", "Contatore"),
|
|
80009
|
+
state: [{
|
|
80010
|
+
kind: "numeric",
|
|
80011
|
+
field: "value",
|
|
80012
|
+
quantity: t("the total", "il totale"),
|
|
80013
|
+
label: t("Total", "Totale"),
|
|
80014
|
+
icon: "gauge"
|
|
80015
|
+
}]
|
|
80016
|
+
},
|
|
79174
80017
|
"numeric-sensor": {
|
|
79175
80018
|
scope: "device",
|
|
79176
80019
|
noun: t("Sensor", "Sensore"),
|
|
@@ -79179,7 +80022,6 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
79179
80022
|
field: "value",
|
|
79180
80023
|
quantity: t("the reading", "il valore"),
|
|
79181
80024
|
label: t("Reading", "Valore"),
|
|
79182
|
-
unitField: "unit",
|
|
79183
80025
|
icon: "gauge"
|
|
79184
80026
|
}]
|
|
79185
80027
|
},
|
|
@@ -79315,7 +80157,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
79315
80157
|
field: "temperature",
|
|
79316
80158
|
quantity: t("the outdoor temperature", "la temperatura esterna"),
|
|
79317
80159
|
label: t("Temperature", "Temperatura"),
|
|
79318
|
-
|
|
80160
|
+
unit: "°C",
|
|
79319
80161
|
icon: "thermometer"
|
|
79320
80162
|
},
|
|
79321
80163
|
{
|
|
@@ -79331,7 +80173,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
79331
80173
|
field: "windSpeed",
|
|
79332
80174
|
quantity: t("the wind speed", "la velocità del vento"),
|
|
79333
80175
|
label: t("Wind", "Vento"),
|
|
79334
|
-
|
|
80176
|
+
unit: "m/s",
|
|
79335
80177
|
icon: "wind"
|
|
79336
80178
|
},
|
|
79337
80179
|
{
|
|
@@ -79339,7 +80181,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
79339
80181
|
field: "pressure",
|
|
79340
80182
|
quantity: t("the air pressure", "la pressione atmosferica"),
|
|
79341
80183
|
label: t("Pressure", "Pressione"),
|
|
79342
|
-
|
|
80184
|
+
unit: "hPa",
|
|
79343
80185
|
icon: "gauge"
|
|
79344
80186
|
}
|
|
79345
80187
|
]
|
|
@@ -79644,8 +80486,47 @@ function projectAction(cap, action) {
|
|
|
79644
80486
|
};
|
|
79645
80487
|
}
|
|
79646
80488
|
Object.entries(CAP_VOCABULARY_BY_NAME).flatMap(([cap, entry]) => entry.scope === "device" ? (entry.actions ?? []).map((a) => projectAction(cap, a)) : []);
|
|
79647
|
-
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;
|
|
80489
|
+
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;
|
|
79648
80490
|
DeviceFeature.BatteryOperated;
|
|
80491
|
+
DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher;
|
|
80492
|
+
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.";
|
|
80493
|
+
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.";
|
|
80494
|
+
var ALEXA_REASON = "Alexa has no laundry category in this export, and neither power nor running has an Alexa interface.";
|
|
80495
|
+
var GOOGLE_REASON = "Google WASHER, DRYER and DISHWASHER require RunCycle. A power threshold is not that trait, and this export does not publish RunCycle.";
|
|
80496
|
+
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.";
|
|
80497
|
+
function withheld(reason) {
|
|
80498
|
+
return {
|
|
80499
|
+
[DeviceType.Washer]: {
|
|
80500
|
+
exported: false,
|
|
80501
|
+
reason
|
|
80502
|
+
},
|
|
80503
|
+
[DeviceType.Dryer]: {
|
|
80504
|
+
exported: false,
|
|
80505
|
+
reason
|
|
80506
|
+
},
|
|
80507
|
+
[DeviceType.Dishwasher]: {
|
|
80508
|
+
exported: false,
|
|
80509
|
+
reason
|
|
80510
|
+
}
|
|
80511
|
+
};
|
|
80512
|
+
}
|
|
80513
|
+
function offered(received) {
|
|
80514
|
+
return {
|
|
80515
|
+
[DeviceType.Washer]: {
|
|
80516
|
+
exported: true,
|
|
80517
|
+
as: received
|
|
80518
|
+
},
|
|
80519
|
+
[DeviceType.Dryer]: {
|
|
80520
|
+
exported: true,
|
|
80521
|
+
as: received
|
|
80522
|
+
},
|
|
80523
|
+
[DeviceType.Dishwasher]: {
|
|
80524
|
+
exported: true,
|
|
80525
|
+
as: received
|
|
80526
|
+
}
|
|
80527
|
+
};
|
|
80528
|
+
}
|
|
80529
|
+
offered(HA_AS), withheld(HOMEKIT_REASON), withheld(ALEXA_REASON), withheld(GOOGLE_REASON), withheld(MATTER_REASON);
|
|
79649
80530
|
/** Reject after `ms`; always clears its own timer. */
|
|
79650
80531
|
async function withTimeout$1(promise, ms, label) {
|
|
79651
80532
|
let timer;
|
|
@@ -80678,6 +81559,21 @@ Object.freeze({
|
|
|
80678
81559
|
form: "single",
|
|
80679
81560
|
optional: false
|
|
80680
81561
|
}],
|
|
81562
|
+
"groupActive.getStatus": [{
|
|
81563
|
+
name: "deviceId",
|
|
81564
|
+
form: "single",
|
|
81565
|
+
optional: false
|
|
81566
|
+
}],
|
|
81567
|
+
"groupCommands.getStatus": [{
|
|
81568
|
+
name: "deviceId",
|
|
81569
|
+
form: "single",
|
|
81570
|
+
optional: false
|
|
81571
|
+
}],
|
|
81572
|
+
"groupStatus.getStatus": [{
|
|
81573
|
+
name: "deviceId",
|
|
81574
|
+
form: "single",
|
|
81575
|
+
optional: false
|
|
81576
|
+
}],
|
|
80681
81577
|
"heatingValve.getStatus": [{
|
|
80682
81578
|
name: "deviceId",
|
|
80683
81579
|
form: "single",
|
|
@@ -80878,6 +81774,11 @@ Object.freeze({
|
|
|
80878
81774
|
form: "single",
|
|
80879
81775
|
optional: false
|
|
80880
81776
|
}],
|
|
81777
|
+
"meter.getStatus": [{
|
|
81778
|
+
name: "deviceId",
|
|
81779
|
+
form: "single",
|
|
81780
|
+
optional: false
|
|
81781
|
+
}],
|
|
80881
81782
|
"motion.getStatus": [{
|
|
80882
81783
|
name: "deviceId",
|
|
80883
81784
|
form: "single",
|
|
@@ -82485,7 +83386,6 @@ Object.freeze({
|
|
|
82485
83386
|
"network-access": "ingress",
|
|
82486
83387
|
"smtp-provider": "email"
|
|
82487
83388
|
});
|
|
82488
|
-
DeviceType.Camera;
|
|
82489
83389
|
/**
|
|
82490
83390
|
* A saved Customize assignment (D936). The schema is the type: callers use
|
|
82491
83391
|
* `z.infer`, they do not restate the shape.
|
|
@@ -82662,6 +83562,8 @@ new Map(Object.entries({
|
|
|
82662
83562
|
"detection-blind": "device-events",
|
|
82663
83563
|
"motion-noisy": "device-events",
|
|
82664
83564
|
"motion-calm": "device-events",
|
|
83565
|
+
"package-llm-silent": "device-events",
|
|
83566
|
+
"package-llm-answered": "device-events",
|
|
82665
83567
|
"recording-stalled": "device-events",
|
|
82666
83568
|
"recording-healthy": "device-events",
|
|
82667
83569
|
"recording-degraded": "device-events",
|
|
@@ -82745,6 +83647,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
|
|
|
82745
83647
|
label: "Motion without a subject",
|
|
82746
83648
|
kinds: ["motion-noisy", "motion-calm"]
|
|
82747
83649
|
},
|
|
83650
|
+
{
|
|
83651
|
+
id: "package-llm",
|
|
83652
|
+
family: "device-events",
|
|
83653
|
+
label: "Package confirm",
|
|
83654
|
+
kinds: ["package-llm-silent", "package-llm-answered"]
|
|
83655
|
+
},
|
|
82748
83656
|
{
|
|
82749
83657
|
id: "recording",
|
|
82750
83658
|
family: "device-events",
|
|
@@ -82926,6 +83834,8 @@ var DEVICE_EVENTS = [
|
|
|
82926
83834
|
"detection-blind",
|
|
82927
83835
|
"motion-noisy",
|
|
82928
83836
|
"motion-calm",
|
|
83837
|
+
"package-llm-silent",
|
|
83838
|
+
"package-llm-answered",
|
|
82929
83839
|
"recording-stalled",
|
|
82930
83840
|
"recording-healthy",
|
|
82931
83841
|
"recording-degraded",
|
|
@@ -83194,6 +84104,15 @@ new Map([
|
|
|
83194
84104
|
snapshotLabel: "Cameras with constant motion now",
|
|
83195
84105
|
snapshotSection: null
|
|
83196
84106
|
},
|
|
84107
|
+
{
|
|
84108
|
+
id: "package-llm-confirm",
|
|
84109
|
+
family: "device-events",
|
|
84110
|
+
label: "Package confirm (not answering / answering again)",
|
|
84111
|
+
bad: ["package-llm-silent"],
|
|
84112
|
+
recovery: ["package-llm-answered"],
|
|
84113
|
+
snapshotLabel: "Cameras whose package confirm is not answering",
|
|
84114
|
+
snapshotSection: null
|
|
84115
|
+
},
|
|
83197
84116
|
{
|
|
83198
84117
|
id: "recording-health",
|
|
83199
84118
|
family: "device-events",
|