@camstack/addon-pipeline 1.2.627 → 1.2.629
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +35 -0
- package/dist/audio-analyzer/index.js +3 -3
- package/dist/audio-analyzer/index.mjs +3 -3
- package/dist/{custom-model-catalog-DtxDgB4p.mjs → custom-model-catalog--z5qDAbz.mjs} +2 -2
- package/dist/{custom-model-catalog-rWY1H5Ei.js → custom-model-catalog-DyFqiWQw.js} +2 -2
- package/dist/detection-pipeline/index.js +4 -4
- package/dist/detection-pipeline/index.mjs +4 -4
- package/dist/{dist-CQe330cU.mjs → dist-DkFeDO1Z.mjs} +867 -438
- package/dist/{dist-CcZsLU96.js → dist-vvIUo4Fg.js} +867 -438
- package/dist/{model-catalogs-B43s5kgs.mjs → model-catalogs-DcAtdzQX.mjs} +1 -1
- package/dist/{model-catalogs-BJjn54AQ.js → model-catalogs-dHtp4VIV.js} +1 -1
- package/dist/motion-wasm/index.js +1 -1
- package/dist/motion-wasm/index.mjs +1 -1
- package/dist/{node-XOjWaowO.mjs → node-CT-ETMWK.mjs} +1 -1
- package/dist/{node-Ba3e855X.js → node-j-hM0LYt.js} +1 -1
- package/dist/pipeline-runner/index.js +3 -3
- package/dist/pipeline-runner/index.mjs +3 -3
- package/dist/{process-memory-Dw_mzdZ5.js → process-memory-B9lUUQZw.js} +1 -1
- package/dist/{process-memory-DyYlcpfM.mjs → process-memory-BwZIeAKw.mjs} +1 -1
- package/dist/recorder/index.js +2 -2
- package/dist/recorder/index.mjs +2 -2
- package/dist/{segment-demux-js-qzmsqDt7.js → segment-demux-js-BCBpOp5j.js} +1 -1
- package/dist/{segment-demux-js-BVwtkI0F.mjs → segment-demux-js-CW7aiIml.mjs} +1 -1
- package/dist/stream-broker/_stub.js +2 -2
- package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-CJJ0Dj8s.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-DUUHEAPV.mjs} +2 -2
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BQMKjVwR.mjs +26 -0
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-Ca0Qmh7u.mjs +26 -0
- package/dist/stream-broker/demux-worker-child.js +1 -1
- package/dist/stream-broker/demux-worker-child.mjs +1 -1
- package/dist/stream-broker/{hostInit-BIx670St.mjs → hostInit-BiqKaq23.mjs} +2 -2
- package/dist/stream-broker/index.js +3 -3
- package/dist/stream-broker/index.mjs +3 -3
- package/dist/stream-broker/remoteEntry.js +1 -1
- package/package.json +4 -2
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-D-GlPMcf.mjs +0 -26
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-CEiM-boT.mjs +0 -26
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
let node_crypto = require("node:crypto");
|
|
2
|
-
//#region ../types/dist/event-category-
|
|
2
|
+
//#region ../types/dist/event-category-CT-hz5Rb.mjs
|
|
3
3
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
4
4
|
EventCategory["SystemBoot"] = "system.boot";
|
|
5
5
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -325,6 +325,14 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
325
325
|
/** The recovery edge of {@link PipelineMotionNoisy}: the motion fell back, or a detection arrived. */
|
|
326
326
|
EventCategory["PipelineMotionCalm"] = "pipeline.motion-calm";
|
|
327
327
|
/**
|
|
328
|
+
* A camera's package LLM confirm has failed closed three times in a row
|
|
329
|
+
* (D931, 2026-10-26). One edge per camera until
|
|
330
|
+
* {@link PipelinePackageLlmAnswered}.
|
|
331
|
+
*/
|
|
332
|
+
EventCategory["PipelinePackageLlmSilent"] = "pipeline.package-llm-silent";
|
|
333
|
+
/** The recovery edge of {@link PipelinePackageLlmSilent}: a confirm returned yes or no. */
|
|
334
|
+
EventCategory["PipelinePackageLlmAnswered"] = "pipeline.package-llm-answered";
|
|
335
|
+
/**
|
|
328
336
|
* Per-camera pipeline config was mutated by the orchestrator
|
|
329
337
|
* (a settings change via `setAgentInferenceDevices` /
|
|
330
338
|
* `setCameraStepToggle` / `setCameraStepSettings`). Orchestrator
|
|
@@ -5567,7 +5575,7 @@ var ZodIssueCode = {
|
|
|
5567
5575
|
var ZodFirstPartyTypeKind;
|
|
5568
5576
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5569
5577
|
//#endregion
|
|
5570
|
-
//#region ../types/dist/sleep-
|
|
5578
|
+
//#region ../types/dist/sleep-bykKrTgu.mjs
|
|
5571
5579
|
/**
|
|
5572
5580
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5573
5581
|
* window to float samples (D455).
|
|
@@ -8315,6 +8323,99 @@ function defineRecordKinds(specs) {
|
|
|
8315
8323
|
}
|
|
8316
8324
|
return out;
|
|
8317
8325
|
}
|
|
8326
|
+
var READING_QUANTITIES = [
|
|
8327
|
+
"temperature",
|
|
8328
|
+
"pressure",
|
|
8329
|
+
"speed",
|
|
8330
|
+
"precipitation",
|
|
8331
|
+
"precipitation-rate",
|
|
8332
|
+
"length",
|
|
8333
|
+
"area",
|
|
8334
|
+
"illuminance",
|
|
8335
|
+
"irradiance",
|
|
8336
|
+
"power",
|
|
8337
|
+
"energy",
|
|
8338
|
+
"voltage",
|
|
8339
|
+
"current",
|
|
8340
|
+
"apparent-power",
|
|
8341
|
+
"humidity",
|
|
8342
|
+
"percentage",
|
|
8343
|
+
"concentration-volume",
|
|
8344
|
+
"concentration-mass",
|
|
8345
|
+
"concentration-ppb",
|
|
8346
|
+
"volume",
|
|
8347
|
+
"duration",
|
|
8348
|
+
"duration-ms",
|
|
8349
|
+
"information",
|
|
8350
|
+
"sound-level",
|
|
8351
|
+
"signal-level",
|
|
8352
|
+
"colour-temperature",
|
|
8353
|
+
"angle",
|
|
8354
|
+
"bitrate",
|
|
8355
|
+
"rate",
|
|
8356
|
+
"mass",
|
|
8357
|
+
"index",
|
|
8358
|
+
"ratio",
|
|
8359
|
+
"count",
|
|
8360
|
+
"none",
|
|
8361
|
+
"device"
|
|
8362
|
+
];
|
|
8363
|
+
var ReadingQuantitySchema = _enum(READING_QUANTITIES);
|
|
8364
|
+
new Set(READING_QUANTITIES);
|
|
8365
|
+
/**
|
|
8366
|
+
* Stored unit symbol for a quantity. `none` means the number is dimensionless
|
|
8367
|
+
* (or an index / ratio / count). `device` means the cap has no single unit.
|
|
8368
|
+
*/
|
|
8369
|
+
var QUANTITY_BASE = {
|
|
8370
|
+
temperature: "°C",
|
|
8371
|
+
pressure: "hPa",
|
|
8372
|
+
speed: "m/s",
|
|
8373
|
+
precipitation: "mm",
|
|
8374
|
+
"precipitation-rate": "mm/h",
|
|
8375
|
+
length: "m",
|
|
8376
|
+
area: "m²",
|
|
8377
|
+
illuminance: "lx",
|
|
8378
|
+
irradiance: "W/m²",
|
|
8379
|
+
power: "W",
|
|
8380
|
+
energy: "kWh",
|
|
8381
|
+
voltage: "V",
|
|
8382
|
+
current: "A",
|
|
8383
|
+
"apparent-power": "VA",
|
|
8384
|
+
humidity: "%",
|
|
8385
|
+
percentage: "%",
|
|
8386
|
+
"concentration-volume": "ppm",
|
|
8387
|
+
"concentration-mass": "µg/m³",
|
|
8388
|
+
"concentration-ppb": "ppb",
|
|
8389
|
+
volume: "L",
|
|
8390
|
+
duration: "s",
|
|
8391
|
+
"duration-ms": "ms",
|
|
8392
|
+
information: "B",
|
|
8393
|
+
"sound-level": "dBFS",
|
|
8394
|
+
"signal-level": "dBm",
|
|
8395
|
+
"colour-temperature": "mired",
|
|
8396
|
+
angle: "°",
|
|
8397
|
+
bitrate: "kbps",
|
|
8398
|
+
rate: "fps",
|
|
8399
|
+
mass: "kg",
|
|
8400
|
+
index: "none",
|
|
8401
|
+
ratio: "none",
|
|
8402
|
+
count: "none",
|
|
8403
|
+
none: "none",
|
|
8404
|
+
device: "device"
|
|
8405
|
+
};
|
|
8406
|
+
/** The stored unit, or `undefined` when the quantity has no unit symbol. */
|
|
8407
|
+
function baseUnitOf(quantity) {
|
|
8408
|
+
const symbol = QUANTITY_BASE[quantity];
|
|
8409
|
+
if (symbol === "none" || symbol === "device") return void 0;
|
|
8410
|
+
return symbol;
|
|
8411
|
+
}
|
|
8412
|
+
function readingMeta(quantity, extras) {
|
|
8413
|
+
return {
|
|
8414
|
+
quantity,
|
|
8415
|
+
...extras?.precision !== void 0 ? { precision: extras.precision } : {},
|
|
8416
|
+
...extras?.label !== void 0 ? { label: extras.label } : {}
|
|
8417
|
+
};
|
|
8418
|
+
}
|
|
8318
8419
|
/** Shared Zod schemas used across streaming capabilities. */
|
|
8319
8420
|
var CamProfileSchema = _enum([
|
|
8320
8421
|
"high",
|
|
@@ -8348,8 +8449,8 @@ var CamStreamKindSchema = _enum([
|
|
|
8348
8449
|
"derived"
|
|
8349
8450
|
]);
|
|
8350
8451
|
var CamStreamResolutionSchema = object({
|
|
8351
|
-
width: number().int().positive(),
|
|
8352
|
-
height: number().int().positive()
|
|
8452
|
+
width: number().int().positive().meta(readingMeta("none")),
|
|
8453
|
+
height: number().int().positive().meta(readingMeta("none"))
|
|
8353
8454
|
});
|
|
8354
8455
|
var CameraStreamSchema = object({
|
|
8355
8456
|
/** Stable, provider-assigned id unique within the (deviceId) scope. */
|
|
@@ -9006,6 +9107,8 @@ var CAP_NAMES = Object.freeze([
|
|
|
9006
9107
|
"filesystem-browse",
|
|
9007
9108
|
"flood",
|
|
9008
9109
|
"gas",
|
|
9110
|
+
"group-commands",
|
|
9111
|
+
"group-status",
|
|
9009
9112
|
"heating-valve",
|
|
9010
9113
|
"humidifier",
|
|
9011
9114
|
"humidity-sensor",
|
|
@@ -9135,14 +9238,6 @@ Object.freeze({
|
|
|
9135
9238
|
{
|
|
9136
9239
|
"path": "aqi",
|
|
9137
9240
|
"valueType": "number"
|
|
9138
|
-
},
|
|
9139
|
-
{
|
|
9140
|
-
"path": "unit",
|
|
9141
|
-
"valueType": "string"
|
|
9142
|
-
},
|
|
9143
|
-
{
|
|
9144
|
-
"path": "precision",
|
|
9145
|
-
"valueType": "number"
|
|
9146
9241
|
}
|
|
9147
9242
|
],
|
|
9148
9243
|
"alarm-panel": [
|
|
@@ -9178,20 +9273,10 @@ Object.freeze({
|
|
|
9178
9273
|
"valueType": "boolean"
|
|
9179
9274
|
}
|
|
9180
9275
|
],
|
|
9181
|
-
"ambient-light-sensor": [
|
|
9182
|
-
|
|
9183
|
-
|
|
9184
|
-
|
|
9185
|
-
},
|
|
9186
|
-
{
|
|
9187
|
-
"path": "unit",
|
|
9188
|
-
"valueType": "string"
|
|
9189
|
-
},
|
|
9190
|
-
{
|
|
9191
|
-
"path": "precision",
|
|
9192
|
-
"valueType": "number"
|
|
9193
|
-
}
|
|
9194
|
-
],
|
|
9276
|
+
"ambient-light-sensor": [{
|
|
9277
|
+
"path": "lux",
|
|
9278
|
+
"valueType": "number"
|
|
9279
|
+
}],
|
|
9195
9280
|
"audio-metrics": [
|
|
9196
9281
|
{
|
|
9197
9282
|
"path": "ts",
|
|
@@ -9271,6 +9356,10 @@ Object.freeze({
|
|
|
9271
9356
|
"path": "lastUpdated",
|
|
9272
9357
|
"valueType": "number"
|
|
9273
9358
|
},
|
|
9359
|
+
{
|
|
9360
|
+
"path": "volts",
|
|
9361
|
+
"valueType": "number"
|
|
9362
|
+
},
|
|
9274
9363
|
{
|
|
9275
9364
|
"path": "lastContactAt",
|
|
9276
9365
|
"valueType": "number"
|
|
@@ -9513,10 +9602,6 @@ Object.freeze({
|
|
|
9513
9602
|
"datetime"
|
|
9514
9603
|
]
|
|
9515
9604
|
},
|
|
9516
|
-
{
|
|
9517
|
-
"path": "unit",
|
|
9518
|
-
"valueType": "string"
|
|
9519
|
-
},
|
|
9520
9605
|
{
|
|
9521
9606
|
"path": "min",
|
|
9522
9607
|
"valueType": "number"
|
|
@@ -9528,19 +9613,6 @@ Object.freeze({
|
|
|
9528
9613
|
{
|
|
9529
9614
|
"path": "step",
|
|
9530
9615
|
"valueType": "number"
|
|
9531
|
-
},
|
|
9532
|
-
{
|
|
9533
|
-
"path": "precision",
|
|
9534
|
-
"valueType": "number"
|
|
9535
|
-
},
|
|
9536
|
-
{
|
|
9537
|
-
"path": "format",
|
|
9538
|
-
"valueType": "enum",
|
|
9539
|
-
"enumValues": [
|
|
9540
|
-
"date",
|
|
9541
|
-
"time",
|
|
9542
|
-
"datetime"
|
|
9543
|
-
]
|
|
9544
9616
|
}
|
|
9545
9617
|
],
|
|
9546
9618
|
"cover": [
|
|
@@ -9781,13 +9853,8 @@ Object.freeze({
|
|
|
9781
9853
|
"path": "value",
|
|
9782
9854
|
"valueType": "string"
|
|
9783
9855
|
}, {
|
|
9784
|
-
"path": "
|
|
9785
|
-
"valueType": "
|
|
9786
|
-
"enumValues": [
|
|
9787
|
-
"date",
|
|
9788
|
-
"time",
|
|
9789
|
-
"datetime"
|
|
9790
|
-
]
|
|
9856
|
+
"path": "timestamp",
|
|
9857
|
+
"valueType": "boolean"
|
|
9791
9858
|
}],
|
|
9792
9859
|
"event-emitter": [
|
|
9793
9860
|
{
|
|
@@ -9860,6 +9927,20 @@ Object.freeze({
|
|
|
9860
9927
|
"path": "detected",
|
|
9861
9928
|
"valueType": "boolean"
|
|
9862
9929
|
}],
|
|
9930
|
+
"group-status": [
|
|
9931
|
+
{
|
|
9932
|
+
"path": "included",
|
|
9933
|
+
"valueType": "number"
|
|
9934
|
+
},
|
|
9935
|
+
{
|
|
9936
|
+
"path": "excluded",
|
|
9937
|
+
"valueType": "number"
|
|
9938
|
+
},
|
|
9939
|
+
{
|
|
9940
|
+
"path": "total",
|
|
9941
|
+
"valueType": "number"
|
|
9942
|
+
}
|
|
9943
|
+
],
|
|
9863
9944
|
"heating-valve": [{
|
|
9864
9945
|
"path": "position",
|
|
9865
9946
|
"valueType": "number"
|
|
@@ -9894,20 +9975,10 @@ Object.freeze({
|
|
|
9894
9975
|
"valueType": "number"
|
|
9895
9976
|
}
|
|
9896
9977
|
],
|
|
9897
|
-
"humidity-sensor": [
|
|
9898
|
-
|
|
9899
|
-
|
|
9900
|
-
|
|
9901
|
-
},
|
|
9902
|
-
{
|
|
9903
|
-
"path": "unit",
|
|
9904
|
-
"valueType": "string"
|
|
9905
|
-
},
|
|
9906
|
-
{
|
|
9907
|
-
"path": "precision",
|
|
9908
|
-
"valueType": "number"
|
|
9909
|
-
}
|
|
9910
|
-
],
|
|
9978
|
+
"humidity-sensor": [{
|
|
9979
|
+
"path": "percent",
|
|
9980
|
+
"valueType": "number"
|
|
9981
|
+
}],
|
|
9911
9982
|
"image": [{
|
|
9912
9983
|
"path": "url",
|
|
9913
9984
|
"valueType": "string"
|
|
@@ -10246,20 +10317,10 @@ Object.freeze({
|
|
|
10246
10317
|
"valueType": "boolean"
|
|
10247
10318
|
}
|
|
10248
10319
|
],
|
|
10249
|
-
"numeric-sensor": [
|
|
10250
|
-
|
|
10251
|
-
|
|
10252
|
-
|
|
10253
|
-
},
|
|
10254
|
-
{
|
|
10255
|
-
"path": "unit",
|
|
10256
|
-
"valueType": "string"
|
|
10257
|
-
},
|
|
10258
|
-
{
|
|
10259
|
-
"path": "precision",
|
|
10260
|
-
"valueType": "number"
|
|
10261
|
-
}
|
|
10262
|
-
],
|
|
10320
|
+
"numeric-sensor": [{
|
|
10321
|
+
"path": "value",
|
|
10322
|
+
"valueType": "number"
|
|
10323
|
+
}],
|
|
10263
10324
|
"pet-feeder": [
|
|
10264
10325
|
{
|
|
10265
10326
|
"path": "foodLevel",
|
|
@@ -10351,14 +10412,6 @@ Object.freeze({
|
|
|
10351
10412
|
{
|
|
10352
10413
|
"path": "powerFactor",
|
|
10353
10414
|
"valueType": "number"
|
|
10354
|
-
},
|
|
10355
|
-
{
|
|
10356
|
-
"path": "unit",
|
|
10357
|
-
"valueType": "string"
|
|
10358
|
-
},
|
|
10359
|
-
{
|
|
10360
|
-
"path": "precision",
|
|
10361
|
-
"valueType": "number"
|
|
10362
10415
|
}
|
|
10363
10416
|
],
|
|
10364
10417
|
"presence": [
|
|
@@ -10387,20 +10440,10 @@ Object.freeze({
|
|
|
10387
10440
|
"valueType": "number"
|
|
10388
10441
|
}
|
|
10389
10442
|
],
|
|
10390
|
-
"pressure-sensor": [
|
|
10391
|
-
|
|
10392
|
-
|
|
10393
|
-
|
|
10394
|
-
},
|
|
10395
|
-
{
|
|
10396
|
-
"path": "unit",
|
|
10397
|
-
"valueType": "string"
|
|
10398
|
-
},
|
|
10399
|
-
{
|
|
10400
|
-
"path": "precision",
|
|
10401
|
-
"valueType": "number"
|
|
10402
|
-
}
|
|
10403
|
-
],
|
|
10443
|
+
"pressure-sensor": [{
|
|
10444
|
+
"path": "hpa",
|
|
10445
|
+
"valueType": "number"
|
|
10446
|
+
}],
|
|
10404
10447
|
"privacy-mask": [{
|
|
10405
10448
|
"path": "enabled",
|
|
10406
10449
|
"valueType": "boolean"
|
|
@@ -10711,20 +10754,10 @@ Object.freeze({
|
|
|
10711
10754
|
"path": "tampered",
|
|
10712
10755
|
"valueType": "boolean"
|
|
10713
10756
|
}],
|
|
10714
|
-
"temperature-sensor": [
|
|
10715
|
-
|
|
10716
|
-
|
|
10717
|
-
|
|
10718
|
-
},
|
|
10719
|
-
{
|
|
10720
|
-
"path": "unit",
|
|
10721
|
-
"valueType": "string"
|
|
10722
|
-
},
|
|
10723
|
-
{
|
|
10724
|
-
"path": "precision",
|
|
10725
|
-
"valueType": "number"
|
|
10726
|
-
}
|
|
10727
|
-
],
|
|
10757
|
+
"temperature-sensor": [{
|
|
10758
|
+
"path": "celsius",
|
|
10759
|
+
"valueType": "number"
|
|
10760
|
+
}],
|
|
10728
10761
|
"update": [
|
|
10729
10762
|
{
|
|
10730
10763
|
"path": "currentVersion",
|
|
@@ -10835,10 +10868,6 @@ Object.freeze({
|
|
|
10835
10868
|
"path": "temperature",
|
|
10836
10869
|
"valueType": "number"
|
|
10837
10870
|
},
|
|
10838
|
-
{
|
|
10839
|
-
"path": "temperatureUnit",
|
|
10840
|
-
"valueType": "string"
|
|
10841
|
-
},
|
|
10842
10871
|
{
|
|
10843
10872
|
"path": "humidity",
|
|
10844
10873
|
"valueType": "number"
|
|
@@ -10847,18 +10876,10 @@ Object.freeze({
|
|
|
10847
10876
|
"path": "pressure",
|
|
10848
10877
|
"valueType": "number"
|
|
10849
10878
|
},
|
|
10850
|
-
{
|
|
10851
|
-
"path": "pressureUnit",
|
|
10852
|
-
"valueType": "string"
|
|
10853
|
-
},
|
|
10854
10879
|
{
|
|
10855
10880
|
"path": "windSpeed",
|
|
10856
10881
|
"valueType": "number"
|
|
10857
10882
|
},
|
|
10858
|
-
{
|
|
10859
|
-
"path": "windSpeedUnit",
|
|
10860
|
-
"valueType": "string"
|
|
10861
|
-
},
|
|
10862
10883
|
{
|
|
10863
10884
|
"path": "windBearing",
|
|
10864
10885
|
"valueType": "number"
|
|
@@ -11413,7 +11434,7 @@ function errMsg(err) {
|
|
|
11413
11434
|
return String(err);
|
|
11414
11435
|
}
|
|
11415
11436
|
//#endregion
|
|
11416
|
-
//#region ../types/dist/composition-
|
|
11437
|
+
//#region ../types/dist/composition-OhpuespA.mjs
|
|
11417
11438
|
var AUDIO_ENCODER_BY_CODEC = {
|
|
11418
11439
|
opus: "libopus",
|
|
11419
11440
|
aac: "aac",
|
|
@@ -13004,15 +13025,74 @@ function validateExpressionSource(src) {
|
|
|
13004
13025
|
}
|
|
13005
13026
|
return null;
|
|
13006
13027
|
}
|
|
13007
|
-
/**
|
|
13008
|
-
|
|
13009
|
-
|
|
13010
|
-
|
|
13028
|
+
/**
|
|
13029
|
+
* A composition source identity: `(addonId, stableId)`, never a numeric device
|
|
13030
|
+
* id. Split out so helper schemas can name it without a cycle through
|
|
13031
|
+
* `composition.ts` (D659).
|
|
13032
|
+
*/
|
|
13011
13033
|
var CompositionSourceRefSchema = object({
|
|
13012
13034
|
/** The owning addon; `stableId` is unique only within it. */
|
|
13013
13035
|
addonId: string().min(1),
|
|
13014
13036
|
stableId: string().min(1)
|
|
13015
13037
|
});
|
|
13038
|
+
var GROUP_TEMPLATE_IDS = [
|
|
13039
|
+
"temperature",
|
|
13040
|
+
"humidity",
|
|
13041
|
+
"pressure",
|
|
13042
|
+
"illuminance",
|
|
13043
|
+
"power",
|
|
13044
|
+
"energy",
|
|
13045
|
+
"battery",
|
|
13046
|
+
"numeric",
|
|
13047
|
+
"motion",
|
|
13048
|
+
"contact",
|
|
13049
|
+
"leak",
|
|
13050
|
+
"smoke",
|
|
13051
|
+
"occupancy",
|
|
13052
|
+
"binary",
|
|
13053
|
+
"switch",
|
|
13054
|
+
"light"
|
|
13055
|
+
];
|
|
13056
|
+
var NUMERIC_AGGREGATES = [
|
|
13057
|
+
"mean",
|
|
13058
|
+
"median",
|
|
13059
|
+
"min",
|
|
13060
|
+
"max",
|
|
13061
|
+
"sum"
|
|
13062
|
+
];
|
|
13063
|
+
var BINARY_AGGREGATES = ["any", "all"];
|
|
13064
|
+
/** How an actuator group decides it is on. Unknown members never count as off. */
|
|
13065
|
+
var ACTIVE_CRITERIA = ["at-least-one", "all"];
|
|
13066
|
+
var AGGREGATE_REDUCERS = [
|
|
13067
|
+
"mean",
|
|
13068
|
+
"median",
|
|
13069
|
+
"min",
|
|
13070
|
+
"max",
|
|
13071
|
+
"sum",
|
|
13072
|
+
"any",
|
|
13073
|
+
"all"
|
|
13074
|
+
];
|
|
13075
|
+
var GroupTemplateIdSchema = _enum(GROUP_TEMPLATE_IDS);
|
|
13076
|
+
var AggregateReducerSchema = _enum(AGGREGATE_REDUCERS);
|
|
13077
|
+
var ActiveCriterionSchema = _enum(ACTIVE_CRITERIA);
|
|
13078
|
+
/** One member. The field is stored so occupancy can name motion or binary. */
|
|
13079
|
+
var HelperMemberSchema = object({
|
|
13080
|
+
source: CompositionSourceRefSchema,
|
|
13081
|
+
cap: string().min(1),
|
|
13082
|
+
fieldPath: string().min(1)
|
|
13083
|
+
});
|
|
13084
|
+
var HelperSpecSchema = discriminatedUnion("kind", [object({
|
|
13085
|
+
kind: literal("group"),
|
|
13086
|
+
templateId: GroupTemplateIdSchema,
|
|
13087
|
+
aggregate: AggregateReducerSchema,
|
|
13088
|
+
members: array(HelperMemberSchema).min(1).max(64),
|
|
13089
|
+
/** Actuator groups only. Readings leave this unset. */
|
|
13090
|
+
active: ActiveCriterionSchema.optional()
|
|
13091
|
+
})]);
|
|
13092
|
+
/** A composed device's stableId is this prefix plus the block id. */
|
|
13093
|
+
var COMPOSED_DEVICE_STABLE_ID_PREFIX = "composed-";
|
|
13094
|
+
/** Longest snippet a `code` source may carry (slice 4). */
|
|
13095
|
+
var MAX_COMPOSITION_CODE_LENGTH = 2e4;
|
|
13016
13096
|
/** One field of one capability of one source device. */
|
|
13017
13097
|
var CompositionFieldReadSchema = object({
|
|
13018
13098
|
source: CompositionSourceRefSchema,
|
|
@@ -13056,7 +13136,33 @@ var CompositionCodeSourceSchema = object({
|
|
|
13056
13136
|
var CompositionFieldSourceSchema = discriminatedUnion("kind", [
|
|
13057
13137
|
CompositionFromSourceSchema,
|
|
13058
13138
|
CompositionExpressionSourceSchema,
|
|
13059
|
-
CompositionCodeSourceSchema
|
|
13139
|
+
CompositionCodeSourceSchema,
|
|
13140
|
+
object({
|
|
13141
|
+
kind: literal("aggregate"),
|
|
13142
|
+
reducer: _enum([
|
|
13143
|
+
"mean",
|
|
13144
|
+
"median",
|
|
13145
|
+
"min",
|
|
13146
|
+
"max",
|
|
13147
|
+
"sum",
|
|
13148
|
+
"any",
|
|
13149
|
+
"all"
|
|
13150
|
+
]),
|
|
13151
|
+
reads: array(CompositionFieldReadSchema).min(1).max(64),
|
|
13152
|
+
/** `value` is the reading; the others are the member counts. */
|
|
13153
|
+
publish: _enum([
|
|
13154
|
+
"value",
|
|
13155
|
+
"included",
|
|
13156
|
+
"excluded",
|
|
13157
|
+
"total"
|
|
13158
|
+
]),
|
|
13159
|
+
/** What a `value` publish does when nobody is included. Counts ignore this. */
|
|
13160
|
+
empty: _enum([
|
|
13161
|
+
"null",
|
|
13162
|
+
"omit",
|
|
13163
|
+
"offline"
|
|
13164
|
+
])
|
|
13165
|
+
})
|
|
13060
13166
|
]);
|
|
13061
13167
|
var CompositionCommandTargetSchema = discriminatedUnion("kind", [object({
|
|
13062
13168
|
kind: literal("forward"),
|
|
@@ -13102,7 +13208,13 @@ var CompositionSchema = object({
|
|
|
13102
13208
|
kind: literal("existing"),
|
|
13103
13209
|
device: CompositionSourceRefSchema
|
|
13104
13210
|
})]),
|
|
13105
|
-
features: array(CompositionFeatureSchema).min(1).max(16)
|
|
13211
|
+
features: array(CompositionFeatureSchema).min(1).max(16),
|
|
13212
|
+
/**
|
|
13213
|
+
* Present when the block is a helper template. Absent on a free
|
|
13214
|
+
* composition (the room example, device 4603). The editor reads this,
|
|
13215
|
+
* never the compiled features.
|
|
13216
|
+
*/
|
|
13217
|
+
helper: HelperSpecSchema.optional()
|
|
13106
13218
|
}).superRefine((composition, ctx) => {
|
|
13107
13219
|
const seen = /* @__PURE__ */ new Set();
|
|
13108
13220
|
composition.features.forEach((feature, index) => {
|
|
@@ -21032,7 +21144,11 @@ var CompositionProblemSchema = object({
|
|
|
21032
21144
|
"item-field-reserved",
|
|
21033
21145
|
"target-missing",
|
|
21034
21146
|
"target-unreadable",
|
|
21035
|
-
"not-replaceable"
|
|
21147
|
+
"not-replaceable",
|
|
21148
|
+
"native-capability-replace",
|
|
21149
|
+
"mixed-quantity",
|
|
21150
|
+
"helper-mismatch",
|
|
21151
|
+
"member-constraint"
|
|
21036
21152
|
]),
|
|
21037
21153
|
path: string(),
|
|
21038
21154
|
message: string()
|
|
@@ -21053,7 +21169,8 @@ var CompositionUnavailableModeSchema = _enum([
|
|
|
21053
21169
|
"null",
|
|
21054
21170
|
"offline",
|
|
21055
21171
|
"unknown",
|
|
21056
|
-
"release"
|
|
21172
|
+
"release",
|
|
21173
|
+
"omit"
|
|
21057
21174
|
]);
|
|
21058
21175
|
/**
|
|
21059
21176
|
* `derived` reads a source · `clock` reads only `now`, recomputed when a sibling
|
|
@@ -21090,9 +21207,11 @@ var CompositionFieldPlanSchema = object({
|
|
|
21090
21207
|
reads: array(CompositionFieldReadSchema)
|
|
21091
21208
|
});
|
|
21092
21209
|
/**
|
|
21093
|
-
* What a feature does to its target (D663): `new` builds a capability on a
|
|
21094
|
-
* device; on an existing device it `add`s a capability the device lacks
|
|
21095
|
-
*
|
|
21210
|
+
* What a feature does to its target (D663, D944): `new` builds a capability on a
|
|
21211
|
+
* new device; on an existing device it `add`s a capability the device lacks.
|
|
21212
|
+
* Replacing a capability the device already serves is refused
|
|
21213
|
+
* (`native-capability-replace`), not planned. `replace` remains on the claim
|
|
21214
|
+
* wire for a claim the hub already holds.
|
|
21096
21215
|
*/
|
|
21097
21216
|
var CompositionFeatureModeSchema = _enum([
|
|
21098
21217
|
"new",
|
|
@@ -21265,6 +21384,275 @@ Object.freeze({
|
|
|
21265
21384
|
result: ["number", "null"]
|
|
21266
21385
|
}
|
|
21267
21386
|
});
|
|
21387
|
+
/**
|
|
21388
|
+
* One catalog row per base reading a group helper can build (D944 §3).
|
|
21389
|
+
* Data, not a form default written into the block.
|
|
21390
|
+
*/
|
|
21391
|
+
var NOW = {
|
|
21392
|
+
fieldPath: "lastFetchedAt",
|
|
21393
|
+
expr: "now"
|
|
21394
|
+
};
|
|
21395
|
+
var CHANGED = {
|
|
21396
|
+
fieldPath: "lastChangedAt",
|
|
21397
|
+
expr: "now"
|
|
21398
|
+
};
|
|
21399
|
+
function numeric(input) {
|
|
21400
|
+
return {
|
|
21401
|
+
...input,
|
|
21402
|
+
family: "numeric",
|
|
21403
|
+
deviceType: DeviceType.Sensor,
|
|
21404
|
+
memberDeviceType: DeviceType.Sensor,
|
|
21405
|
+
commandCaps: [],
|
|
21406
|
+
baseUnit: baseUnitOf(input.quantity),
|
|
21407
|
+
aggregates: NUMERIC_AGGREGATES,
|
|
21408
|
+
accept: [{
|
|
21409
|
+
cap: input.outputCap,
|
|
21410
|
+
fieldPath: input.outputField
|
|
21411
|
+
}]
|
|
21412
|
+
};
|
|
21413
|
+
}
|
|
21414
|
+
function binary(input) {
|
|
21415
|
+
return {
|
|
21416
|
+
...input,
|
|
21417
|
+
family: "binary",
|
|
21418
|
+
deviceType: DeviceType.Sensor,
|
|
21419
|
+
memberDeviceType: DeviceType.Sensor,
|
|
21420
|
+
commandCaps: [],
|
|
21421
|
+
quantity: "none",
|
|
21422
|
+
baseUnit: void 0,
|
|
21423
|
+
aggregates: BINARY_AGGREGATES,
|
|
21424
|
+
empty: "offline"
|
|
21425
|
+
};
|
|
21426
|
+
}
|
|
21427
|
+
var GROUP_TEMPLATES = [
|
|
21428
|
+
numeric({
|
|
21429
|
+
id: "temperature",
|
|
21430
|
+
summary: "Mean, median, min, max or sum of temperatures. Offline and unknown members are left out, never read as 0 °C.",
|
|
21431
|
+
role: DeviceRole.TemperatureSensor,
|
|
21432
|
+
outputCap: "temperature-sensor",
|
|
21433
|
+
outputField: "celsius",
|
|
21434
|
+
quantity: "temperature",
|
|
21435
|
+
defaultAggregate: "mean",
|
|
21436
|
+
empty: "null",
|
|
21437
|
+
companions: [NOW]
|
|
21438
|
+
}),
|
|
21439
|
+
numeric({
|
|
21440
|
+
id: "humidity",
|
|
21441
|
+
summary: "Humidity in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
21442
|
+
role: DeviceRole.HumiditySensor,
|
|
21443
|
+
outputCap: "humidity-sensor",
|
|
21444
|
+
outputField: "percent",
|
|
21445
|
+
quantity: "humidity",
|
|
21446
|
+
defaultAggregate: "mean",
|
|
21447
|
+
empty: "null",
|
|
21448
|
+
companions: [NOW]
|
|
21449
|
+
}),
|
|
21450
|
+
numeric({
|
|
21451
|
+
id: "pressure",
|
|
21452
|
+
summary: "Pressure in hectopascals. Offline and unknown members are left out, never read as 0 hPa.",
|
|
21453
|
+
role: DeviceRole.PressureSensor,
|
|
21454
|
+
outputCap: "pressure-sensor",
|
|
21455
|
+
outputField: "hpa",
|
|
21456
|
+
quantity: "pressure",
|
|
21457
|
+
defaultAggregate: "mean",
|
|
21458
|
+
empty: "null",
|
|
21459
|
+
companions: [NOW]
|
|
21460
|
+
}),
|
|
21461
|
+
numeric({
|
|
21462
|
+
id: "illuminance",
|
|
21463
|
+
summary: "Illuminance in lux. Offline and unknown members are left out, never read as 0 lx.",
|
|
21464
|
+
role: DeviceRole.AmbientLightSensor,
|
|
21465
|
+
outputCap: "ambient-light-sensor",
|
|
21466
|
+
outputField: "lux",
|
|
21467
|
+
quantity: "illuminance",
|
|
21468
|
+
defaultAggregate: "mean",
|
|
21469
|
+
empty: "null",
|
|
21470
|
+
companions: [NOW]
|
|
21471
|
+
}),
|
|
21472
|
+
numeric({
|
|
21473
|
+
id: "power",
|
|
21474
|
+
summary: "Power in watts, summed by default. Nobody reporting omits the key rather than writing 0 W.",
|
|
21475
|
+
role: DeviceRole.PowerSensor,
|
|
21476
|
+
outputCap: "power-meter",
|
|
21477
|
+
outputField: "watts",
|
|
21478
|
+
quantity: "power",
|
|
21479
|
+
defaultAggregate: "sum",
|
|
21480
|
+
empty: "omit",
|
|
21481
|
+
companions: [NOW]
|
|
21482
|
+
}),
|
|
21483
|
+
numeric({
|
|
21484
|
+
id: "energy",
|
|
21485
|
+
summary: "Energy in kilowatt-hours, summed by default. Nobody reporting omits the key rather than writing 0 kWh.",
|
|
21486
|
+
role: DeviceRole.EnergySensor,
|
|
21487
|
+
outputCap: "power-meter",
|
|
21488
|
+
outputField: "kwhTotal",
|
|
21489
|
+
quantity: "energy",
|
|
21490
|
+
defaultAggregate: "sum",
|
|
21491
|
+
empty: "omit",
|
|
21492
|
+
companions: [NOW]
|
|
21493
|
+
}),
|
|
21494
|
+
numeric({
|
|
21495
|
+
id: "battery",
|
|
21496
|
+
summary: "Battery charge in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
21497
|
+
role: DeviceRole.BatterySensor,
|
|
21498
|
+
outputCap: "battery",
|
|
21499
|
+
outputField: "percentage",
|
|
21500
|
+
quantity: "percentage",
|
|
21501
|
+
defaultAggregate: "mean",
|
|
21502
|
+
empty: "null",
|
|
21503
|
+
companions: [
|
|
21504
|
+
{
|
|
21505
|
+
fieldPath: "charging",
|
|
21506
|
+
expr: "\"unknown\""
|
|
21507
|
+
},
|
|
21508
|
+
{
|
|
21509
|
+
fieldPath: "sleeping",
|
|
21510
|
+
expr: "false"
|
|
21511
|
+
},
|
|
21512
|
+
{
|
|
21513
|
+
fieldPath: "lastUpdated",
|
|
21514
|
+
expr: "now"
|
|
21515
|
+
}
|
|
21516
|
+
]
|
|
21517
|
+
}),
|
|
21518
|
+
numeric({
|
|
21519
|
+
id: "numeric",
|
|
21520
|
+
summary: "A numeric reading in the members’ shared quantity. Mixed quantities are refused. Nobody reporting publishes null, not 0.",
|
|
21521
|
+
role: DeviceRole.NumericSensor,
|
|
21522
|
+
outputCap: "numeric-sensor",
|
|
21523
|
+
outputField: "value",
|
|
21524
|
+
quantity: "device",
|
|
21525
|
+
defaultAggregate: "mean",
|
|
21526
|
+
empty: "null",
|
|
21527
|
+
companions: [NOW]
|
|
21528
|
+
}),
|
|
21529
|
+
binary({
|
|
21530
|
+
id: "motion",
|
|
21531
|
+
summary: "Any or all motion. Offline and unknown members are left out, never read as off. Nobody reporting takes the device offline.",
|
|
21532
|
+
role: DeviceRole.MotionSensor,
|
|
21533
|
+
outputCap: "motion",
|
|
21534
|
+
outputField: "detected",
|
|
21535
|
+
defaultAggregate: "any",
|
|
21536
|
+
accept: [{
|
|
21537
|
+
cap: "motion",
|
|
21538
|
+
fieldPath: "detected"
|
|
21539
|
+
}],
|
|
21540
|
+
companions: [{
|
|
21541
|
+
fieldPath: "lastDetectedAt",
|
|
21542
|
+
expr: "null"
|
|
21543
|
+
}, {
|
|
21544
|
+
fieldPath: "autoClearAfterMs",
|
|
21545
|
+
expr: "null"
|
|
21546
|
+
}]
|
|
21547
|
+
}),
|
|
21548
|
+
binary({
|
|
21549
|
+
id: "contact",
|
|
21550
|
+
summary: "Any or all open contacts. Offline and unknown members are left out, never read as closed.",
|
|
21551
|
+
role: DeviceRole.ContactSensor,
|
|
21552
|
+
outputCap: "contact",
|
|
21553
|
+
outputField: "entryOpen",
|
|
21554
|
+
defaultAggregate: "any",
|
|
21555
|
+
accept: [{
|
|
21556
|
+
cap: "contact",
|
|
21557
|
+
fieldPath: "entryOpen"
|
|
21558
|
+
}],
|
|
21559
|
+
companions: [CHANGED]
|
|
21560
|
+
}),
|
|
21561
|
+
binary({
|
|
21562
|
+
id: "leak",
|
|
21563
|
+
summary: "Any or all leak detections. Offline and unknown members are left out, never read as dry.",
|
|
21564
|
+
role: DeviceRole.LeakSensor,
|
|
21565
|
+
outputCap: "flood",
|
|
21566
|
+
outputField: "flooded",
|
|
21567
|
+
defaultAggregate: "any",
|
|
21568
|
+
accept: [{
|
|
21569
|
+
cap: "flood",
|
|
21570
|
+
fieldPath: "flooded"
|
|
21571
|
+
}],
|
|
21572
|
+
companions: [CHANGED]
|
|
21573
|
+
}),
|
|
21574
|
+
binary({
|
|
21575
|
+
id: "smoke",
|
|
21576
|
+
summary: "Any or all smoke detections. Offline and unknown members are left out, never read as clear.",
|
|
21577
|
+
role: DeviceRole.SmokeSensor,
|
|
21578
|
+
outputCap: "smoke",
|
|
21579
|
+
outputField: "detected",
|
|
21580
|
+
defaultAggregate: "any",
|
|
21581
|
+
accept: [{
|
|
21582
|
+
cap: "smoke",
|
|
21583
|
+
fieldPath: "detected"
|
|
21584
|
+
}],
|
|
21585
|
+
companions: [CHANGED]
|
|
21586
|
+
}),
|
|
21587
|
+
binary({
|
|
21588
|
+
id: "occupancy",
|
|
21589
|
+
summary: "Any or all of motion or binary sensors, published as a binary. Presence zones are not aggregated. Nobody reporting is offline, not off.",
|
|
21590
|
+
role: DeviceRole.BinarySensor,
|
|
21591
|
+
outputCap: "binary",
|
|
21592
|
+
outputField: "on",
|
|
21593
|
+
defaultAggregate: "any",
|
|
21594
|
+
accept: [{
|
|
21595
|
+
cap: "motion",
|
|
21596
|
+
fieldPath: "detected"
|
|
21597
|
+
}, {
|
|
21598
|
+
cap: "binary",
|
|
21599
|
+
fieldPath: "on"
|
|
21600
|
+
}],
|
|
21601
|
+
companions: [CHANGED]
|
|
21602
|
+
}),
|
|
21603
|
+
binary({
|
|
21604
|
+
id: "binary",
|
|
21605
|
+
summary: "Any or all generic binary sensors. Offline and unknown members are left out, never read as off.",
|
|
21606
|
+
role: DeviceRole.BinarySensor,
|
|
21607
|
+
outputCap: "binary",
|
|
21608
|
+
outputField: "on",
|
|
21609
|
+
defaultAggregate: "any",
|
|
21610
|
+
accept: [{
|
|
21611
|
+
cap: "binary",
|
|
21612
|
+
fieldPath: "on"
|
|
21613
|
+
}],
|
|
21614
|
+
companions: [CHANGED]
|
|
21615
|
+
}),
|
|
21616
|
+
actuator({
|
|
21617
|
+
id: "switch",
|
|
21618
|
+
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.",
|
|
21619
|
+
deviceType: DeviceType.Switch,
|
|
21620
|
+
outputCap: "switch",
|
|
21621
|
+
commandCaps: ["switch"]
|
|
21622
|
+
}),
|
|
21623
|
+
actuator({
|
|
21624
|
+
id: "light",
|
|
21625
|
+
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.",
|
|
21626
|
+
deviceType: DeviceType.Light,
|
|
21627
|
+
outputCap: "switch",
|
|
21628
|
+
commandCaps: [
|
|
21629
|
+
"switch",
|
|
21630
|
+
"brightness",
|
|
21631
|
+
"color"
|
|
21632
|
+
]
|
|
21633
|
+
})
|
|
21634
|
+
];
|
|
21635
|
+
function actuator(input) {
|
|
21636
|
+
return {
|
|
21637
|
+
...input,
|
|
21638
|
+
family: "actuator",
|
|
21639
|
+
role: void 0,
|
|
21640
|
+
memberDeviceType: input.deviceType,
|
|
21641
|
+
outputField: "on",
|
|
21642
|
+
quantity: "none",
|
|
21643
|
+
baseUnit: void 0,
|
|
21644
|
+
aggregates: BINARY_AGGREGATES,
|
|
21645
|
+
defaultAggregate: "any",
|
|
21646
|
+
empty: "offline",
|
|
21647
|
+
accept: [{
|
|
21648
|
+
cap: "switch",
|
|
21649
|
+
fieldPath: "on"
|
|
21650
|
+
}],
|
|
21651
|
+
companions: [CHANGED]
|
|
21652
|
+
};
|
|
21653
|
+
}
|
|
21654
|
+
new Map(GROUP_TEMPLATES.map((template) => [template.id, template]));
|
|
21655
|
+
DeviceFeature.LightColorRgb, DeviceFeature.LightColorHsv, DeviceFeature.LightColorMired;
|
|
21268
21656
|
`${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
|
|
21269
21657
|
/**
|
|
21270
21658
|
* What a composition may BUILD on a device type (G2, D676): the caps a new
|
|
@@ -23009,12 +23397,12 @@ method(object({ deviceId: number().int().nonnegative() }), DeviceAdminLinkSchema
|
|
|
23009
23397
|
* providers detect renames by matching `uniqueId` and patch `id`
|
|
23010
23398
|
* in-place so dispatch keeps working.
|
|
23011
23399
|
*
|
|
23012
|
-
* **
|
|
23013
|
-
*
|
|
23014
|
-
*
|
|
23015
|
-
*
|
|
23016
|
-
* (`ha-domain-mapping`)
|
|
23017
|
-
* stored after that point.
|
|
23400
|
+
* **Display unit and precision are NOT stored here.** They are a read-time
|
|
23401
|
+
* preference (D944). A polymorphic reading stores its `quantity` here once,
|
|
23402
|
+
* at adopt, and a date/time value stores `dateTimeShape` the same way —
|
|
23403
|
+
* neither is repeated on each sample. The `device_class` tag is an
|
|
23404
|
+
* HA-specific input consumed at the discovery boundary (`ha-domain-mapping`)
|
|
23405
|
+
* to derive the CamStack `DeviceRole`; it is never stored after that point.
|
|
23018
23406
|
*
|
|
23019
23407
|
* The `raw` escape hatch carries provider-specific attributes that don't
|
|
23020
23408
|
* fit the structured slots (HA `attributes` whitelist, Reolink `deviceCache`
|
|
@@ -23028,6 +23416,14 @@ var SourceInfoSchema = object({
|
|
|
23028
23416
|
/** Immutable upstream identifier when available (HA `unique_id`, … ).
|
|
23029
23417
|
* Used to detect rename when `id` changes. */
|
|
23030
23418
|
uniqueId: string().optional(),
|
|
23419
|
+
/** Quantity of a polymorphic reading, written once at adopt (D944). */
|
|
23420
|
+
quantity: ReadingQuantitySchema.optional(),
|
|
23421
|
+
/** Date / time / datetime shape of a string reading, written once at adopt. */
|
|
23422
|
+
dateTimeShape: _enum([
|
|
23423
|
+
"date",
|
|
23424
|
+
"time",
|
|
23425
|
+
"datetime"
|
|
23426
|
+
]).optional(),
|
|
23031
23427
|
/** Provider-specific extras that don't fit the structured slots.
|
|
23032
23428
|
* Whitelist what goes here per provider — do NOT dump entire HA
|
|
23033
23429
|
* attribute blobs (would explode the meta JSON column). */
|
|
@@ -43944,7 +44340,8 @@ method(object({
|
|
|
43944
44340
|
"enum"
|
|
43945
44341
|
]),
|
|
43946
44342
|
enumValues: array(string()).optional(),
|
|
43947
|
-
item: boolean().optional()
|
|
44343
|
+
item: boolean().optional(),
|
|
44344
|
+
quantity: ReadingQuantitySchema.optional()
|
|
43948
44345
|
})).readonly(),
|
|
43949
44346
|
itemArray: object({
|
|
43950
44347
|
path: string(),
|
|
@@ -48154,8 +48551,8 @@ var MaskPolygonShapeSchema = object({
|
|
|
48154
48551
|
/** Boolean cell grid — row-major, length === gridWidth*gridHeight. */
|
|
48155
48552
|
var MaskGridShapeSchema = object({
|
|
48156
48553
|
kind: literal("grid"),
|
|
48157
|
-
gridWidth: number(),
|
|
48158
|
-
gridHeight: number(),
|
|
48554
|
+
gridWidth: number().meta(readingMeta("none")),
|
|
48555
|
+
gridHeight: number().meta(readingMeta("none")),
|
|
48159
48556
|
cells: array(boolean())
|
|
48160
48557
|
});
|
|
48161
48558
|
discriminatedUnion("kind", [
|
|
@@ -48267,6 +48664,8 @@ var NcSystemEventKindSchema = _enum([
|
|
|
48267
48664
|
"detection-blind",
|
|
48268
48665
|
"motion-noisy",
|
|
48269
48666
|
"motion-calm",
|
|
48667
|
+
"package-llm-silent",
|
|
48668
|
+
"package-llm-answered",
|
|
48270
48669
|
"recording-stalled",
|
|
48271
48670
|
"recording-healthy",
|
|
48272
48671
|
"recording-degraded",
|
|
@@ -60121,6 +60520,28 @@ var PackageVersionInfoSchema = object({
|
|
|
60121
60520
|
deprecated: string().optional(),
|
|
60122
60521
|
distTags: array(string()).readonly()
|
|
60123
60522
|
});
|
|
60523
|
+
/**
|
|
60524
|
+
* One published document. `ok` is markdown from the registry. `missing` means
|
|
60525
|
+
* the registry answered and the file was not there. `error` is a registry or
|
|
60526
|
+
* tarball failure — never an empty string standing in for either.
|
|
60527
|
+
*/
|
|
60528
|
+
var PackageDocBodySchema = discriminatedUnion("status", [
|
|
60529
|
+
object({
|
|
60530
|
+
status: literal("ok"),
|
|
60531
|
+
markdown: string()
|
|
60532
|
+
}),
|
|
60533
|
+
object({ status: literal("missing") }),
|
|
60534
|
+
object({
|
|
60535
|
+
status: literal("error"),
|
|
60536
|
+
message: string()
|
|
60537
|
+
})
|
|
60538
|
+
]);
|
|
60539
|
+
var PackageDocsSchema = object({
|
|
60540
|
+
name: string(),
|
|
60541
|
+
version: string(),
|
|
60542
|
+
readme: PackageDocBodySchema,
|
|
60543
|
+
changelog: PackageDocBodySchema
|
|
60544
|
+
});
|
|
60124
60545
|
var SearchResultSchema = object({
|
|
60125
60546
|
name: string(),
|
|
60126
60547
|
version: string(),
|
|
@@ -60339,7 +60760,10 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
|
|
|
60339
60760
|
}), object({ success: literal(true) }), {
|
|
60340
60761
|
kind: "mutation",
|
|
60341
60762
|
auth: "admin"
|
|
60342
|
-
}), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({
|
|
60763
|
+
}), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({
|
|
60764
|
+
name: string().min(1),
|
|
60765
|
+
version: string().min(1).optional()
|
|
60766
|
+
}), PackageDocsSchema, { auth: "admin" }), method(object({ addonId: string() }), RestartAddonResultSchema, {
|
|
60343
60767
|
kind: "mutation",
|
|
60344
60768
|
auth: "admin"
|
|
60345
60769
|
}), method(object({ packageName: string() }), object({ success: literal(true) }), {
|
|
@@ -60389,46 +60813,27 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
|
|
|
60389
60813
|
}), LogStreamEntrySchema, { kind: "subscription" });
|
|
60390
60814
|
object({
|
|
60391
60815
|
/** Carbon dioxide concentration in ppm. */
|
|
60392
|
-
co2Ppm: number().min(0).optional(),
|
|
60816
|
+
co2Ppm: number().min(0).optional().meta(readingMeta("concentration-volume")),
|
|
60393
60817
|
/** Total volatile organic compounds in ppb. */
|
|
60394
|
-
vocPpb: number().min(0).optional(),
|
|
60818
|
+
vocPpb: number().min(0).optional().meta(readingMeta("concentration-ppb")),
|
|
60395
60819
|
/** Particulate matter ≤ 2.5 μm in µg/m³. */
|
|
60396
|
-
pm25: number().min(0).optional(),
|
|
60820
|
+
pm25: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
60397
60821
|
/** Particulate matter ≤ 10 μm in µg/m³. */
|
|
60398
|
-
pm10: number().min(0).optional(),
|
|
60822
|
+
pm10: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
60399
60823
|
/** Composite AQI value (typically 0..500). */
|
|
60400
|
-
aqi: number().optional(),
|
|
60824
|
+
aqi: number().optional().meta(readingMeta("index")),
|
|
60401
60825
|
/** Ms epoch when the slice was last updated. */
|
|
60402
|
-
lastFetchedAt: number()
|
|
60403
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
60404
|
-
* `attributes.unit_of_measurement` → 'ppm' / 'ppb' / 'µg/m³'). Each
|
|
60405
|
-
* upstream `sensor.*` entity surfaces ONE device_class, so one unit
|
|
60406
|
-
* per slice is unambiguous. */
|
|
60407
|
-
unit: string().optional(),
|
|
60408
|
-
/** Suggested decimal places for numeric display.
|
|
60409
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
60410
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
60411
|
-
* auto-formatting when absent. */
|
|
60412
|
-
precision: number().int().min(0).max(10).optional()
|
|
60826
|
+
lastFetchedAt: number()
|
|
60413
60827
|
});
|
|
60414
60828
|
DeviceType.Sensor;
|
|
60415
60829
|
object({
|
|
60416
|
-
/** Current illuminance in lux (lx). */
|
|
60417
|
-
lux: number().min(0).meta({
|
|
60418
|
-
|
|
60830
|
+
/** Current illuminance in lux (lx). `null` when the sample was refused (D393). */
|
|
60831
|
+
lux: number().min(0).nullable().meta(readingMeta("illuminance", {
|
|
60832
|
+
precision: 0,
|
|
60419
60833
|
label: "Illuminance"
|
|
60420
|
-
}),
|
|
60834
|
+
})),
|
|
60421
60835
|
/** Ms epoch when the slice was last updated. */
|
|
60422
|
-
lastFetchedAt: number()
|
|
60423
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
60424
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
60425
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
60426
|
-
unit: string().optional(),
|
|
60427
|
-
/** Suggested decimal places for numeric display.
|
|
60428
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
60429
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
60430
|
-
* auto-formatting when absent. */
|
|
60431
|
-
precision: number().int().min(0).max(10).optional()
|
|
60836
|
+
lastFetchedAt: number()
|
|
60432
60837
|
});
|
|
60433
60838
|
DeviceType.Sensor;
|
|
60434
60839
|
/**
|
|
@@ -60573,10 +60978,7 @@ var BatteryStatusSchema = object({
|
|
|
60573
60978
|
* Consumers must SKIP a null rather than coerce it — `battery-band` already
|
|
60574
60979
|
* declines to band a non-finite reading, which is the correct shape.
|
|
60575
60980
|
*/
|
|
60576
|
-
percentage: number().min(0).max(100).nullable().meta({
|
|
60577
|
-
unit: "%",
|
|
60578
|
-
label: "Charge"
|
|
60579
|
-
}),
|
|
60981
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage", { label: "Charge" })),
|
|
60580
60982
|
/**
|
|
60581
60983
|
* Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
|
|
60582
60984
|
* Reolink-specific for the Solar Panel 2 accessory (will become
|
|
@@ -60603,7 +61005,14 @@ var BatteryStatusSchema = object({
|
|
|
60603
61005
|
*/
|
|
60604
61006
|
sleeping: boolean().meta({ label: "Sleeping" }),
|
|
60605
61007
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
60606
|
-
lastUpdated: number(),
|
|
61008
|
+
lastUpdated: number().meta(readingMeta("none")),
|
|
61009
|
+
/**
|
|
61010
|
+
* Battery voltage in volts, for a cell the firmware reports as voltage
|
|
61011
|
+
* rather than a percentage (Ecowitt capacitor packs). Absent on cameras
|
|
61012
|
+
* that only report charge. A second reading on this cap, not a second
|
|
61013
|
+
* `numeric-sensor` on the same device.
|
|
61014
|
+
*/
|
|
61015
|
+
volts: number().nullable().optional().meta(readingMeta("voltage", { label: "Voltage" })),
|
|
60607
61016
|
/**
|
|
60608
61017
|
* Ms epoch of the last time the device PROVED it was reachable — a
|
|
60609
61018
|
* completed firmware round-trip, an observed wake, or an inbound push
|
|
@@ -60655,7 +61064,6 @@ var BATTERY_DEVICE_TYPES = [
|
|
|
60655
61064
|
/** Generic Customize target for the percentage reading (D936). */
|
|
60656
61065
|
var batteryCustomize = {
|
|
60657
61066
|
version: 1,
|
|
60658
|
-
advanced: "derive",
|
|
60659
61067
|
targets: [{
|
|
60660
61068
|
id: "percentage",
|
|
60661
61069
|
cardinality: "scalar",
|
|
@@ -60664,7 +61072,7 @@ var batteryCustomize = {
|
|
|
60664
61072
|
stateField: "percentage"
|
|
60665
61073
|
},
|
|
60666
61074
|
deviceTypes: BATTERY_DEVICE_TYPES,
|
|
60667
|
-
apply: "add
|
|
61075
|
+
apply: "add",
|
|
60668
61076
|
path: "percentage",
|
|
60669
61077
|
sources: [{
|
|
60670
61078
|
kind: "field",
|
|
@@ -60785,10 +61193,16 @@ onStatusChanged: { data: object({
|
|
|
60785
61193
|
/**
|
|
60786
61194
|
* History (D850): recorded series. The generic capture replaces the `battery` series of `pipeline-analytics:stats-5m`.
|
|
60787
61195
|
*/
|
|
60788
|
-
history: { fields: {
|
|
60789
|
-
|
|
60790
|
-
|
|
60791
|
-
|
|
61196
|
+
history: { fields: {
|
|
61197
|
+
percentage: {
|
|
61198
|
+
kind: "gauge",
|
|
61199
|
+
unit: "%"
|
|
61200
|
+
},
|
|
61201
|
+
volts: {
|
|
61202
|
+
kind: "gauge",
|
|
61203
|
+
unit: "V"
|
|
61204
|
+
}
|
|
61205
|
+
} },
|
|
60792
61206
|
customize: batteryCustomize,
|
|
60793
61207
|
/** Clock fields: written, but excluded from the compare that decides
|
|
60794
61208
|
* whether persisting is worth a SQLite commit. */
|
|
@@ -60802,7 +61216,7 @@ object({
|
|
|
60802
61216
|
DeviceType.Sensor;
|
|
60803
61217
|
object({
|
|
60804
61218
|
/** Current level as 0..100 inclusive. Firmware-reported. */
|
|
60805
|
-
percentage: number().min(0).max(100),
|
|
61219
|
+
percentage: number().min(0).max(100).meta(readingMeta("percentage")),
|
|
60806
61220
|
/** Ms epoch of the last operator-driven change. Useful for UI freshness. */
|
|
60807
61221
|
lastChangedAt: number()
|
|
60808
61222
|
});
|
|
@@ -61187,21 +61601,21 @@ object({
|
|
|
61187
61601
|
/** Single setpoint in Celsius. Used by single-target modes
|
|
61188
61602
|
* (heat / cool / dry). Null when the device is in a range mode
|
|
61189
61603
|
* (`heat_cool`) or has no setpoint at all (`fan_only`/`off`). */
|
|
61190
|
-
target: number().nullable(),
|
|
61604
|
+
target: number().nullable().meta(readingMeta("temperature")),
|
|
61191
61605
|
/** Upper bound of the dual setpoint in Celsius. Populated only
|
|
61192
61606
|
* in `heat_cool` mode. */
|
|
61193
|
-
targetHigh: number().nullable(),
|
|
61607
|
+
targetHigh: number().nullable().meta(readingMeta("temperature")),
|
|
61194
61608
|
/** Lower bound of the dual setpoint in Celsius. Populated only
|
|
61195
61609
|
* in `heat_cool` mode. */
|
|
61196
|
-
targetLow: number().nullable(),
|
|
61610
|
+
targetLow: number().nullable().meta(readingMeta("temperature")),
|
|
61197
61611
|
/** Target relative humidity (0..100). Null when the device has no
|
|
61198
61612
|
* humidity control. */
|
|
61199
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
61613
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
61200
61614
|
/** Current measured temperature in Celsius. Read-only — pushed by
|
|
61201
61615
|
* the device's internal sensor. */
|
|
61202
|
-
currentTemp: number().nullable(),
|
|
61616
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
61203
61617
|
/** Current measured relative humidity (0..100). Read-only. */
|
|
61204
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
61618
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
61205
61619
|
/** Vertical louver swing on/off. Null when the device has no vertical
|
|
61206
61620
|
* swing surface (gate with `DeviceFeature.ClimateSwingVertical`). */
|
|
61207
61621
|
swingVertical: boolean().nullable(),
|
|
@@ -61209,11 +61623,11 @@ object({
|
|
|
61209
61623
|
* horizontal swing surface (gate with `DeviceFeature.ClimateSwingHorizontal`). */
|
|
61210
61624
|
swingHorizontal: boolean().nullable(),
|
|
61211
61625
|
/** Lowest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
61212
|
-
minTemp: number().nullable().optional(),
|
|
61626
|
+
minTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
61213
61627
|
/** Highest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
61214
|
-
maxTemp: number().nullable().optional(),
|
|
61628
|
+
maxTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
61215
61629
|
/** Setpoint granularity, Celsius (0.5, 1). Absent / null = not reported. */
|
|
61216
|
-
tempStep: number().positive().nullable().optional(),
|
|
61630
|
+
tempStep: number().positive().nullable().optional().meta(readingMeta("temperature")),
|
|
61217
61631
|
/** Ms epoch when the slice was last updated (push or command). */
|
|
61218
61632
|
lastFetchedAt: number()
|
|
61219
61633
|
});
|
|
@@ -61292,17 +61706,17 @@ DeviceType.Thermostat, DeviceType.Climate, method(object({
|
|
|
61292
61706
|
* modes to expose in the picker without a slice fetch.
|
|
61293
61707
|
*/
|
|
61294
61708
|
var RgbTripletSchema = object({
|
|
61295
|
-
r: number().int().min(0).max(255),
|
|
61296
|
-
g: number().int().min(0).max(255),
|
|
61297
|
-
b: number().int().min(0).max(255)
|
|
61709
|
+
r: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
61710
|
+
g: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
61711
|
+
b: number().int().min(0).max(255).meta(readingMeta("none"))
|
|
61298
61712
|
});
|
|
61299
61713
|
var HsvTripletSchema = object({
|
|
61300
61714
|
/** Hue in degrees, 0..360. */
|
|
61301
|
-
h: number().min(0).max(360),
|
|
61715
|
+
h: number().min(0).max(360).meta(readingMeta("none")),
|
|
61302
61716
|
/** Saturation as 0..100 inclusive. */
|
|
61303
|
-
s: number().min(0).max(100),
|
|
61717
|
+
s: number().min(0).max(100).meta(readingMeta("none")),
|
|
61304
61718
|
/** Value/brightness as 0..100 inclusive. */
|
|
61305
|
-
v: number().min(0).max(100)
|
|
61719
|
+
v: number().min(0).max(100).meta(readingMeta("none"))
|
|
61306
61720
|
});
|
|
61307
61721
|
var ColorInputSchema = discriminatedUnion("mode", [
|
|
61308
61722
|
object({
|
|
@@ -61331,7 +61745,7 @@ object({
|
|
|
61331
61745
|
/** Populated when `mode === 'hsv'`. */
|
|
61332
61746
|
hsv: HsvTripletSchema.optional(),
|
|
61333
61747
|
/** Populated when `mode === 'mired'`. */
|
|
61334
|
-
mireds: number().int().optional(),
|
|
61748
|
+
mireds: number().int().optional().meta(readingMeta("colour-temperature")),
|
|
61335
61749
|
/** Ms epoch of the last operator-driven change. */
|
|
61336
61750
|
lastChangedAt: number()
|
|
61337
61751
|
});
|
|
@@ -61455,18 +61869,12 @@ _enum([
|
|
|
61455
61869
|
"empty",
|
|
61456
61870
|
"full"
|
|
61457
61871
|
]);
|
|
61458
|
-
/**
|
|
61459
|
-
|
|
61460
|
-
|
|
61461
|
-
"days",
|
|
61462
|
-
"hours",
|
|
61463
|
-
"cycles"
|
|
61464
|
-
]);
|
|
61465
|
-
/** Remaining life as a COUNT, not a percentage (the PetKit desiccant reports
|
|
61466
|
-
* days). `value` null = unknown (D393). */
|
|
61872
|
+
/** Whether `remaining.value` is a duration in seconds or a dimensionless count. */
|
|
61873
|
+
var ConsumableRemainingKindSchema = _enum(["duration", "count"]);
|
|
61874
|
+
/** Remaining life. `value` null = unknown (D393). Duration is seconds. */
|
|
61467
61875
|
var ConsumableRemainingSchema = object({
|
|
61468
|
-
value: number().min(0).nullable(),
|
|
61469
|
-
|
|
61876
|
+
value: number().min(0).nullable().meta(readingMeta("device")),
|
|
61877
|
+
kind: ConsumableRemainingKindSchema
|
|
61470
61878
|
});
|
|
61471
61879
|
var ConsumablesStatusSchema = object({
|
|
61472
61880
|
items: array(object({
|
|
@@ -61475,7 +61883,7 @@ var ConsumablesStatusSchema = object({
|
|
|
61475
61883
|
/** Display name. */
|
|
61476
61884
|
label: string().min(1),
|
|
61477
61885
|
/** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
|
|
61478
|
-
level: number().min(0).max(100).nullable(),
|
|
61886
|
+
level: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61479
61887
|
/** The provider's discrete verdict when known (binary mode). */
|
|
61480
61888
|
status: ConsumableStatusSchema.nullable(),
|
|
61481
61889
|
/** What the item is — decides whether low or full is bad. Absent = `wear`. */
|
|
@@ -61492,7 +61900,7 @@ var ConsumablesStatusSchema = object({
|
|
|
61492
61900
|
})),
|
|
61493
61901
|
lastChangedAt: number()
|
|
61494
61902
|
});
|
|
61495
|
-
Object.values(DeviceType), [...
|
|
61903
|
+
Object.values(DeviceType), [...ConsumableRemainingKindSchema.options], [...ConsumableStatusSchema.options], [...ConsumableKindSchema.options], [...ConsumableFormSchema.options];
|
|
61496
61904
|
Object.values(DeviceType), method(object({
|
|
61497
61905
|
deviceId: number().int().nonnegative(),
|
|
61498
61906
|
key: string().min(1)
|
|
@@ -61517,39 +61925,17 @@ object({
|
|
|
61517
61925
|
/** Current value. Numeric kind → number; select/text/datetime → string.
|
|
61518
61926
|
* Datetime values are ISO 8601 strings (full timestamp, date-only,
|
|
61519
61927
|
* or time-only — HA accepts all three forms). */
|
|
61520
|
-
value: union$1([number(), string()]),
|
|
61928
|
+
value: union$1([number().meta(readingMeta("device")), string()]),
|
|
61521
61929
|
/** Acceptable values when `kind === 'select'`. Empty for other kinds. */
|
|
61522
61930
|
options: array(string()),
|
|
61523
61931
|
/** Ms epoch when the slice was last updated. */
|
|
61524
61932
|
lastChangedAt: number(),
|
|
61525
|
-
/**
|
|
61526
|
-
|
|
61527
|
-
|
|
61528
|
-
|
|
61529
|
-
/**
|
|
61530
|
-
|
|
61531
|
-
min: number().optional(),
|
|
61532
|
-
/** Maximum allowed value. Populated live from HA `attributes.max`.
|
|
61533
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
61534
|
-
max: number().optional(),
|
|
61535
|
-
/** Step increment. Populated live from HA `attributes.step`.
|
|
61536
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
61537
|
-
step: number().optional(),
|
|
61538
|
-
/** Suggested decimal places for numeric display. Populated live from HA
|
|
61539
|
-
* `attributes.suggested_display_precision`, or derived from `step` when the
|
|
61540
|
-
* HA attribute is absent. Meaningful for `kind === 'numeric'`; absent for
|
|
61541
|
-
* other kinds. Falls back to auto-formatting when absent. */
|
|
61542
|
-
precision: number().int().min(0).max(10).optional(),
|
|
61543
|
-
/** Date-picker granularity for `kind === 'datetime'`. 'date' → date-only,
|
|
61544
|
-
* 'time' → time-only, 'datetime' → full timestamp. Absent for other kinds
|
|
61545
|
-
* (UI defaults to 'datetime'). Derived live from the device's HA domain
|
|
61546
|
-
* (date.* / time.* / datetime.*) or, for input_datetime, from the entity's
|
|
61547
|
-
* `has_date`/`has_time` attributes on each push. */
|
|
61548
|
-
format: _enum([
|
|
61549
|
-
"date",
|
|
61550
|
-
"time",
|
|
61551
|
-
"datetime"
|
|
61552
|
-
]).optional()
|
|
61933
|
+
/** Minimum allowed value, in the device quantity's base unit. */
|
|
61934
|
+
min: number().optional().meta(readingMeta("device")),
|
|
61935
|
+
/** Maximum allowed value, in the device quantity's base unit. */
|
|
61936
|
+
max: number().optional().meta(readingMeta("device")),
|
|
61937
|
+
/** Step increment, in the device quantity's base unit. */
|
|
61938
|
+
step: number().optional().meta(readingMeta("device"))
|
|
61553
61939
|
});
|
|
61554
61940
|
var ControlSetValueInputSchema = discriminatedUnion("kind", [
|
|
61555
61941
|
object({
|
|
@@ -61587,9 +61973,9 @@ object({
|
|
|
61587
61973
|
]),
|
|
61588
61974
|
/** 0 = fully closed, 100 = fully open. Null when the device has
|
|
61589
61975
|
* no intermediate position surface. */
|
|
61590
|
-
position: number().min(0).max(100).nullable(),
|
|
61976
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61591
61977
|
/** 0 = closed slats, 100 = open slats. Null when no tilt support. */
|
|
61592
|
-
tiltPosition: number().min(0).max(100).nullable(),
|
|
61978
|
+
tiltPosition: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61593
61979
|
/** Ms epoch when the slice was last updated. */
|
|
61594
61980
|
lastChangedAt: number()
|
|
61595
61981
|
});
|
|
@@ -61647,9 +62033,9 @@ var NormalizedRangeSchema$1 = object({
|
|
|
61647
62033
|
object({
|
|
61648
62034
|
mode: DayNightModeSchema,
|
|
61649
62035
|
/** IR-cut trigger sensitivity, NORMALIZED 0–100 (higher = switches to night sooner). */
|
|
61650
|
-
sensitivity: number().optional(),
|
|
62036
|
+
sensitivity: number().optional().meta(readingMeta("none")),
|
|
61651
62037
|
/** Delay before the IR-cut filter flips, in seconds. */
|
|
61652
|
-
switchDelaySec: number().optional(),
|
|
62038
|
+
switchDelaySec: number().optional().meta(readingMeta("duration")),
|
|
61653
62039
|
lastFetchedAt: number()
|
|
61654
62040
|
});
|
|
61655
62041
|
/**
|
|
@@ -61804,11 +62190,11 @@ object({
|
|
|
61804
62190
|
/** Feature keys of the programs the appliance currently offers — drives the UI selector. */
|
|
61805
62191
|
availablePrograms: array(string()),
|
|
61806
62192
|
/** Seconds remaining on the active cycle, or null when not running / not known. */
|
|
61807
|
-
remainingSeconds: number().int().nonnegative().nullable(),
|
|
62193
|
+
remainingSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
61808
62194
|
/** Seconds the delayed start is set to (time until the cycle starts), or null. */
|
|
61809
|
-
delayedStartSeconds: number().int().nonnegative().nullable(),
|
|
62195
|
+
delayedStartSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
61810
62196
|
/** Cycle completion 0..100, or null when not applicable. */
|
|
61811
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
62197
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61812
62198
|
/** True when the door is reported open; null when the door state is not known. */
|
|
61813
62199
|
doorOpen: boolean().nullable(),
|
|
61814
62200
|
/** True when the door is latched (locked) during a cycle; null when not reported. */
|
|
@@ -61832,7 +62218,7 @@ object({
|
|
|
61832
62218
|
/** True while the machine-care (descaling / cleaning-program) reminder is raised; false when clear; null when not reported. */
|
|
61833
62219
|
machineCareDue: boolean().nullable(),
|
|
61834
62220
|
/** Program runs left before the machine-care reminder is due; null when the appliance does not say. */
|
|
61835
|
-
machineCareRemainingRuns: number().int().nonnegative().nullable(),
|
|
62221
|
+
machineCareRemainingRuns: number().int().nonnegative().nullable().meta(readingMeta("count")),
|
|
61836
62222
|
/** Option states: null when the appliance does not expose the option or has not said. */
|
|
61837
62223
|
halfLoad: boolean().nullable(),
|
|
61838
62224
|
hygienePlus: boolean().nullable(),
|
|
@@ -61847,7 +62233,7 @@ object({
|
|
|
61847
62233
|
/** Feature keys of the events currently raised (salt low, rinse aid low, program finished, …). */
|
|
61848
62234
|
activeEvents: array(string()),
|
|
61849
62235
|
/** Numeric error code when the appliance reports one; null otherwise. */
|
|
61850
|
-
errorCode: number().nullable(),
|
|
62236
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
61851
62237
|
/** Name of the raised alert-level event while the appliance is in error; null otherwise. */
|
|
61852
62238
|
errorLabel: string().nullable(),
|
|
61853
62239
|
/** Ms epoch of the last value received from the appliance; 0 = never. */
|
|
@@ -61993,24 +62379,14 @@ object({
|
|
|
61993
62379
|
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
61994
62380
|
lastPressedAt: number().nullable(),
|
|
61995
62381
|
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
61996
|
-
pressCountSinceStart: number()
|
|
62382
|
+
pressCountSinceStart: number().meta(readingMeta("count"))
|
|
61997
62383
|
});
|
|
61998
62384
|
object({
|
|
61999
62385
|
deviceId: number(),
|
|
62000
62386
|
timestamp: number()
|
|
62001
62387
|
});
|
|
62002
62388
|
DeviceType.Button, DeviceType.Camera;
|
|
62003
|
-
|
|
62004
|
-
* Enum-state sensor — a string value picked from a finite option set.
|
|
62005
|
-
* Drives HA `sensor` entries with `state_class: enum` (HVAC action
|
|
62006
|
-
* states, weather conditions, contact-source channels, mode strings).
|
|
62007
|
-
* The option set is stable across observations; it is persisted in the
|
|
62008
|
-
* device config blob (via the control slice at adoption) and is NOT
|
|
62009
|
-
* stored in `sourceInfo`.
|
|
62010
|
-
*/
|
|
62011
|
-
/** Locale-render shape for an ISO `value` carried by a `DateTimeSensor`-role
|
|
62012
|
-
* enum sensor: `date` (date-only), `time` (time-only), `datetime` (both). */
|
|
62013
|
-
var EnumSensorDateTimeFormatSchema = _enum([
|
|
62389
|
+
_enum([
|
|
62014
62390
|
"date",
|
|
62015
62391
|
"time",
|
|
62016
62392
|
"datetime"
|
|
@@ -62018,12 +62394,11 @@ var EnumSensorDateTimeFormatSchema = _enum([
|
|
|
62018
62394
|
object({
|
|
62019
62395
|
value: string(),
|
|
62020
62396
|
/**
|
|
62021
|
-
* Set
|
|
62022
|
-
* as
|
|
62023
|
-
*
|
|
62024
|
-
* a time-only sensor → `'time'`.
|
|
62397
|
+
* Set when `value` is a timestamp rather than an enum state, so history
|
|
62398
|
+
* does not learn ISO strings as states. The display shape (date / time /
|
|
62399
|
+
* datetime) lives on `SourceInfo.dateTimeShape`, written once at adopt.
|
|
62025
62400
|
*/
|
|
62026
|
-
|
|
62401
|
+
timestamp: boolean().optional(),
|
|
62027
62402
|
/** Ms epoch when the slice was last updated. */
|
|
62028
62403
|
lastFetchedAt: number()
|
|
62029
62404
|
});
|
|
@@ -62042,13 +62417,13 @@ var EventFireSchema = object({
|
|
|
62042
62417
|
deviceId: number(),
|
|
62043
62418
|
eventType: string(),
|
|
62044
62419
|
data: record(string(), unknown()).nullable(),
|
|
62045
|
-
timestamp: number(),
|
|
62046
|
-
seq: number()
|
|
62420
|
+
timestamp: number().meta(readingMeta("none")),
|
|
62421
|
+
seq: number().meta(readingMeta("count"))
|
|
62047
62422
|
});
|
|
62048
62423
|
object({
|
|
62049
62424
|
eventTypes: array(string()),
|
|
62050
62425
|
lastEvent: EventFireSchema.nullable(),
|
|
62051
|
-
eventCountSinceStart: number()
|
|
62426
|
+
eventCountSinceStart: number().meta(readingMeta("count"))
|
|
62052
62427
|
});
|
|
62053
62428
|
DeviceType.EventEmitter;
|
|
62054
62429
|
var IdentitySchema = object({
|
|
@@ -62437,10 +62812,10 @@ var FanDirectionSchema = _enum(["forward", "reverse"]);
|
|
|
62437
62812
|
object({
|
|
62438
62813
|
/** Active speed as 0..100 inclusive. Null when the device has no
|
|
62439
62814
|
* speed surface (single-speed fan). */
|
|
62440
|
-
percentage: number().min(0).max(100).nullable(),
|
|
62815
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
62441
62816
|
/** Speed granularity the device accepts (HA `percentage_step`, e.g. 25 for
|
|
62442
62817
|
* a 4-speed fan). Absent when unknown — the UI then falls back to step 1. */
|
|
62443
|
-
percentageStep: number().positive().optional(),
|
|
62818
|
+
percentageStep: number().positive().optional().meta(readingMeta("percentage")),
|
|
62444
62819
|
/** Active preset mode (`auto` / `quiet` / `turbo` / vendor-specific)
|
|
62445
62820
|
* — empty string when no preset is active or supported. */
|
|
62446
62821
|
preset: string(),
|
|
@@ -62522,7 +62897,7 @@ var FeatureProbeStatusSchema = object({
|
|
|
62522
62897
|
/** Camera/firmware model string. `null` when the firmware doesn't expose it. */
|
|
62523
62898
|
model: string().nullable(),
|
|
62524
62899
|
/** Channel count for NVR/Hub devices; `1` for standalone cameras; `null` pre-probe. */
|
|
62525
|
-
channelCount: number().nullable(),
|
|
62900
|
+
channelCount: number().nullable().meta(readingMeta("count")),
|
|
62526
62901
|
/**
|
|
62527
62902
|
* Ms epoch of the last SUCCESSFUL probe. `0` before the first probe
|
|
62528
62903
|
* completes — drivers' `getAccessoryChildren()` should treat zero as
|
|
@@ -62554,9 +62929,39 @@ object({
|
|
|
62554
62929
|
lastChangedAt: number()
|
|
62555
62930
|
});
|
|
62556
62931
|
DeviceType.Sensor;
|
|
62932
|
+
object({
|
|
62933
|
+
/** One row per member that has been commanded. A later command replaces that member's row. */
|
|
62934
|
+
results: array(object({
|
|
62935
|
+
deviceId: number().int().nonnegative(),
|
|
62936
|
+
cap: string().min(1),
|
|
62937
|
+
method: string().min(1),
|
|
62938
|
+
ok: boolean(),
|
|
62939
|
+
error: string().optional(),
|
|
62940
|
+
/** Ms epoch of the attempt. */
|
|
62941
|
+
at: number()
|
|
62942
|
+
})) });
|
|
62943
|
+
DeviceType.Switch, DeviceType.Light;
|
|
62944
|
+
object({
|
|
62945
|
+
/** Members whose current value entered the aggregate. */
|
|
62946
|
+
included: number().int().nonnegative().meta(readingMeta("count", {
|
|
62947
|
+
precision: 0,
|
|
62948
|
+
label: "Reporting"
|
|
62949
|
+
})),
|
|
62950
|
+
/** Members left out: offline, unknown, or not a finite reading (D393). */
|
|
62951
|
+
excluded: number().int().nonnegative().meta(readingMeta("count", {
|
|
62952
|
+
precision: 0,
|
|
62953
|
+
label: "Excluded"
|
|
62954
|
+
})),
|
|
62955
|
+
/** `included` + `excluded`. */
|
|
62956
|
+
total: number().int().nonnegative().meta(readingMeta("count", {
|
|
62957
|
+
precision: 0,
|
|
62958
|
+
label: "Members"
|
|
62959
|
+
}))
|
|
62960
|
+
});
|
|
62961
|
+
DeviceType.Sensor, DeviceType.Switch, DeviceType.Light;
|
|
62557
62962
|
object({
|
|
62558
62963
|
/** Radiator valve opening 0 (closed) .. 100 (open). Null = not yet known. */
|
|
62559
|
-
position: number().min(0).max(100).nullable(),
|
|
62964
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
62560
62965
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
62561
62966
|
lastFetchedAt: number()
|
|
62562
62967
|
});
|
|
@@ -62565,9 +62970,9 @@ object({
|
|
|
62565
62970
|
/** Whether the humidifier is currently on. */
|
|
62566
62971
|
on: boolean(),
|
|
62567
62972
|
/** Current measured relative humidity (0..100). Null when not reported. */
|
|
62568
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
62973
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
62569
62974
|
/** Target relative humidity (0..100). Null when no setpoint surface. */
|
|
62570
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
62975
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
62571
62976
|
/** Active mode (`auto` / `normal` / `baby` / vendor). Null when the
|
|
62572
62977
|
* device has no mode surface. */
|
|
62573
62978
|
mode: string().nullable(),
|
|
@@ -62577,9 +62982,9 @@ object({
|
|
|
62577
62982
|
* `idle` / `off`). Null when the device doesn't report it. */
|
|
62578
62983
|
action: string().nullable(),
|
|
62579
62984
|
/** HA `min_humidity` attribute. Null → UI uses 0. */
|
|
62580
|
-
minHumidity: number().nullable(),
|
|
62985
|
+
minHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
62581
62986
|
/** HA `max_humidity` attribute. Null → UI uses 100. */
|
|
62582
|
-
maxHumidity: number().nullable(),
|
|
62987
|
+
maxHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
62583
62988
|
/** Ms epoch when the slice was last updated. */
|
|
62584
62989
|
lastChangedAt: number()
|
|
62585
62990
|
});
|
|
@@ -62603,22 +63008,13 @@ DeviceType.Humidifier, method(object({
|
|
|
62603
63008
|
auth: "protected"
|
|
62604
63009
|
});
|
|
62605
63010
|
object({
|
|
62606
|
-
/** Current relative humidity, 0..100. */
|
|
62607
|
-
percent: number().min(0).max(100).meta({
|
|
62608
|
-
|
|
63011
|
+
/** Current relative humidity, 0..100. `null` when the sample was refused (D393). */
|
|
63012
|
+
percent: number().min(0).max(100).nullable().meta(readingMeta("humidity", {
|
|
63013
|
+
precision: 0,
|
|
62609
63014
|
label: "Humidity"
|
|
62610
|
-
}),
|
|
63015
|
+
})),
|
|
62611
63016
|
/** Ms epoch when the slice was last updated. */
|
|
62612
|
-
lastFetchedAt: number()
|
|
62613
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
62614
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
62615
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
62616
|
-
unit: string().optional(),
|
|
62617
|
-
/** Suggested decimal places for numeric display.
|
|
62618
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
62619
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
62620
|
-
* auto-formatting when absent. */
|
|
62621
|
-
precision: number().int().min(0).max(10).optional()
|
|
63017
|
+
lastFetchedAt: number()
|
|
62622
63018
|
});
|
|
62623
63019
|
DeviceType.Sensor, DeviceType.Thermostat;
|
|
62624
63020
|
object({
|
|
@@ -62626,7 +63022,7 @@ object({
|
|
|
62626
63022
|
* entity exposes no `entity_picture` (yet). */
|
|
62627
63023
|
url: string().nullable(),
|
|
62628
63024
|
/** Ms epoch of the upstream last-updated timestamp. Null at cold-start. */
|
|
62629
|
-
lastUpdated: number().nullable()
|
|
63025
|
+
lastUpdated: number().nullable().meta(readingMeta("none"))
|
|
62630
63026
|
});
|
|
62631
63027
|
DeviceType.Image;
|
|
62632
63028
|
/**
|
|
@@ -62682,19 +63078,19 @@ var NormalizedRangeSchema = object({
|
|
|
62682
63078
|
});
|
|
62683
63079
|
object({
|
|
62684
63080
|
/** Normalized 0–100. */
|
|
62685
|
-
brightness: number().optional(),
|
|
63081
|
+
brightness: number().optional().meta(readingMeta("none")),
|
|
62686
63082
|
/** Normalized 0–100. */
|
|
62687
|
-
contrast: number().optional(),
|
|
63083
|
+
contrast: number().optional().meta(readingMeta("none")),
|
|
62688
63084
|
/** Normalized 0–100. */
|
|
62689
|
-
saturation: number().optional(),
|
|
63085
|
+
saturation: number().optional().meta(readingMeta("none")),
|
|
62690
63086
|
/** Normalized 0–100. */
|
|
62691
|
-
sharpness: number().optional(),
|
|
63087
|
+
sharpness: number().optional().meta(readingMeta("none")),
|
|
62692
63088
|
mirror: boolean().optional(),
|
|
62693
63089
|
flip: boolean().optional(),
|
|
62694
63090
|
rotate: ImageRotateSchema.optional(),
|
|
62695
63091
|
whiteBalance: WhiteBalanceModeSchema.optional(),
|
|
62696
63092
|
/** Manual white-balance warmth, NORMALIZED 0–100. Meaningful only when `whiteBalance === 'manual'`. */
|
|
62697
|
-
warmth: number().optional(),
|
|
63093
|
+
warmth: number().optional().meta(readingMeta("none")),
|
|
62698
63094
|
exposureMode: ExposureModeSchema.optional(),
|
|
62699
63095
|
backlightMode: BacklightModeSchema.optional(),
|
|
62700
63096
|
lastFetchedAt: number()
|
|
@@ -62939,10 +63335,10 @@ var IntercomAbilitySchema = object({
|
|
|
62939
63335
|
/** Codecs accepted by firmware, in preference order. Driver-authored strings. */
|
|
62940
63336
|
codecs: array(string()),
|
|
62941
63337
|
/** Sample rate (Hz) the firmware expects. Reolink typical: 16000. */
|
|
62942
|
-
sampleRate: number(),
|
|
63338
|
+
sampleRate: number().meta(readingMeta("none")),
|
|
62943
63339
|
duplex: _enum(["half", "full"]),
|
|
62944
63340
|
/** Max in-flight audio backlog before drop (ms). Server uses this to bound latency. */
|
|
62945
|
-
maxBacklogMs: number()
|
|
63341
|
+
maxBacklogMs: number().meta(readingMeta("duration-ms"))
|
|
62946
63342
|
});
|
|
62947
63343
|
var IntercomStatusSchema = object({
|
|
62948
63344
|
/** True while a talk session is open. */
|
|
@@ -63053,13 +63449,13 @@ object({
|
|
|
63053
63449
|
activity: LawnMowerActivitySchema,
|
|
63054
63450
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
63055
63451
|
* reading. */
|
|
63056
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
63452
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
63057
63453
|
/** 0..100 mowing-completion percentage of the current task, or null when no
|
|
63058
63454
|
* task is active / progress is unavailable. */
|
|
63059
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
63455
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
63060
63456
|
/** Current device/event code (dynamic — mostly status, sometimes an error),
|
|
63061
63457
|
* or null when unknown. */
|
|
63062
|
-
currentCode: number().nullable(),
|
|
63458
|
+
currentCode: number().nullable().meta(readingMeta("none")),
|
|
63063
63459
|
/** Human label for {@link currentCode}, or null when undecodable. */
|
|
63064
63460
|
currentCodeLabel: string().nullable(),
|
|
63065
63461
|
/** Severity of {@link currentCode}. `error` (and often `warning`) warrants UI
|
|
@@ -63521,7 +63917,7 @@ object({
|
|
|
63521
63917
|
state: MediaPlayerStateSchema,
|
|
63522
63918
|
/** Volume as 0..100 inclusive. Null when the device has no volume
|
|
63523
63919
|
* surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
|
|
63524
|
-
volumeLevel: number().min(0).max(100).nullable(),
|
|
63920
|
+
volumeLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
63525
63921
|
/** Mute toggle distinct from volume=0. Null when no mute surface.
|
|
63526
63922
|
* Pair with `DeviceFeature.MediaPlayerMute`. */
|
|
63527
63923
|
isMuted: boolean().nullable(),
|
|
@@ -63534,10 +63930,10 @@ object({
|
|
|
63534
63930
|
currentMedia: MediaInfoSchema.nullable(),
|
|
63535
63931
|
/** Current playback position in ms. Null when not seekable or
|
|
63536
63932
|
* nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
|
|
63537
|
-
positionMs: number().int().nonnegative().nullable(),
|
|
63933
|
+
positionMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
63538
63934
|
/** Total duration of the current media in ms. Null when unknown
|
|
63539
63935
|
* (live stream) or nothing is playing. */
|
|
63540
|
-
durationMs: number().int().nonnegative().nullable(),
|
|
63936
|
+
durationMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
63541
63937
|
/** Shuffle toggle. Null when no shuffle surface.
|
|
63542
63938
|
* Pair with `DeviceFeature.MediaPlayerShuffle`. */
|
|
63543
63939
|
shuffle: boolean().nullable(),
|
|
@@ -63837,7 +64233,7 @@ object({
|
|
|
63837
64233
|
* it, every provider seeded it at boot, and every session left it
|
|
63838
64234
|
* `detected: true` after its detach.
|
|
63839
64235
|
*/
|
|
63840
|
-
autoClearAfterMs: number().nullable()
|
|
64236
|
+
autoClearAfterMs: number().nullable().meta(readingMeta("duration-ms"))
|
|
63841
64237
|
});
|
|
63842
64238
|
/**
|
|
63843
64239
|
* Payload of `motion.onMotionChanged` event + the corresponding bus
|
|
@@ -63887,7 +64283,7 @@ var MotionZoneRegionSchema = object({
|
|
|
63887
64283
|
});
|
|
63888
64284
|
object({
|
|
63889
64285
|
enabled: boolean(),
|
|
63890
|
-
sensitivity: number(),
|
|
64286
|
+
sensitivity: number().meta(readingMeta("none")),
|
|
63891
64287
|
/** Grid region(s). Today exactly one `grid` shape. */
|
|
63892
64288
|
regions: array(MotionZoneRegionSchema),
|
|
63893
64289
|
lastFetchedAt: number()
|
|
@@ -64191,7 +64587,7 @@ var NavigationStatusSchema = object({
|
|
|
64191
64587
|
following: boolean(),
|
|
64192
64588
|
flash: boolean(),
|
|
64193
64589
|
lightMode: NavigationLightModeSchema,
|
|
64194
|
-
lightLevel: number().min(40).max(100),
|
|
64590
|
+
lightLevel: number().min(40).max(100).meta(readingMeta("none")),
|
|
64195
64591
|
/** Ms epoch when the slice was last updated. */
|
|
64196
64592
|
lastChangedAt: number()
|
|
64197
64593
|
});
|
|
@@ -64237,13 +64633,13 @@ var NetworkLinkStatusSchema = object({
|
|
|
64237
64633
|
* one whose reading has not landed must not be drawn at 0 %. Consumers
|
|
64238
64634
|
* SKIP a null rather than coerce it.
|
|
64239
64635
|
*/
|
|
64240
|
-
signalPercent: number().min(0).max(100).nullable(),
|
|
64636
|
+
signalPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
64241
64637
|
/** Raw received signal strength in dBm, when the firmware reports one. */
|
|
64242
|
-
rssiDbm: number().optional(),
|
|
64638
|
+
rssiDbm: number().optional().meta(readingMeta("signal-level")),
|
|
64243
64639
|
/** Network name of a wireless link, when the firmware reports it. */
|
|
64244
64640
|
ssid: string().optional(),
|
|
64245
64641
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
64246
|
-
lastUpdated: number()
|
|
64642
|
+
lastUpdated: number().meta(readingMeta("none"))
|
|
64247
64643
|
});
|
|
64248
64644
|
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.Light, DeviceType.Lock, DeviceType.Siren, object({
|
|
64249
64645
|
deviceId: number(),
|
|
@@ -64562,7 +64958,7 @@ object({
|
|
|
64562
64958
|
lastError: string().nullable(),
|
|
64563
64959
|
/** Number of deliveries currently buffered server-side (rate-limited
|
|
64564
64960
|
* notifiers may queue). 0 when the provider sends synchronously. */
|
|
64565
|
-
queueDepth: number().int().nonnegative(),
|
|
64961
|
+
queueDepth: number().int().nonnegative().meta(readingMeta("count")),
|
|
64566
64962
|
/** Per-feature capability matrix — authoritative source for the
|
|
64567
64963
|
* compose-form field gating. */
|
|
64568
64964
|
supports: NotifierSupportsSchema
|
|
@@ -64612,15 +65008,8 @@ DeviceType.Notifier, method(NotifierSendInputSchema, NotifierSendResultSchema, {
|
|
|
64612
65008
|
acceptedAt: number()
|
|
64613
65009
|
});
|
|
64614
65010
|
object({
|
|
64615
|
-
|
|
64616
|
-
|
|
64617
|
-
* Populated live from the upstream source on each state push.
|
|
64618
|
-
* Absent for unitless sensors. */
|
|
64619
|
-
unit: string().optional(),
|
|
64620
|
-
/** Suggested decimal places for numeric display.
|
|
64621
|
-
* Populated live from the upstream source when provided.
|
|
64622
|
-
* Falls back to auto-formatting when absent. */
|
|
64623
|
-
precision: number().int().min(0).max(10).optional(),
|
|
65011
|
+
/** Reading in the device quantity's base unit. `null` when refused (D393). */
|
|
65012
|
+
value: number().nullable().meta(readingMeta("device")),
|
|
64624
65013
|
/** Ms epoch when the slice was last updated. */
|
|
64625
65014
|
lastFetchedAt: number()
|
|
64626
65015
|
});
|
|
@@ -64910,23 +65299,26 @@ object({
|
|
|
64910
65299
|
/** Food currently in the bowl (grams). Null when the device has not
|
|
64911
65300
|
* reported a reading yet. On dual-hopper models this is the combined
|
|
64912
65301
|
* bowl reading; per-hopper levels live in `food1`/`food2`. */
|
|
64913
|
-
foodLevel: number().nullable(),
|
|
65302
|
+
foodLevel: number().nullable().meta(readingMeta("none")),
|
|
64914
65303
|
/** Hopper-1 food level (grams) on dual-hopper feeders; null on
|
|
64915
65304
|
* single-hopper models. */
|
|
64916
|
-
food1: number().nullable(),
|
|
65305
|
+
food1: number().nullable().meta(readingMeta("none")),
|
|
64917
65306
|
/** Hopper-2 food level (grams) on dual-hopper feeders; null on
|
|
64918
65307
|
* single-hopper models. */
|
|
64919
|
-
food2: number().nullable(),
|
|
65308
|
+
food2: number().nullable().meta(readingMeta("none")),
|
|
64920
65309
|
/** Derived low-food flag — mirrors the HA `food_level` binary_sensor
|
|
64921
65310
|
* (`device_class: problem`, on = low). True when the bowl is empty /
|
|
64922
65311
|
* below the feeder's low threshold. */
|
|
64923
65312
|
lowFood: boolean(),
|
|
64924
65313
|
/** Battery charge 0..100 (%). Null on mains-powered models or when the
|
|
64925
65314
|
* device has no battery reading. */
|
|
64926
|
-
batteryPower: number().min(0).max(100).nullable(),
|
|
64927
|
-
/**
|
|
64928
|
-
*
|
|
64929
|
-
|
|
65315
|
+
batteryPower: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
65316
|
+
/**
|
|
65317
|
+
* Desiccant life remaining, stored in seconds (duration base, D944).
|
|
65318
|
+
* Providers convert from the days the feeder reports. Null when the
|
|
65319
|
+
* model has no desiccant sensor.
|
|
65320
|
+
*/
|
|
65321
|
+
desiccantLeftDays: number().nullable().meta(readingMeta("duration")),
|
|
64930
65322
|
/** True while a feed is in progress. */
|
|
64931
65323
|
feeding: boolean(),
|
|
64932
65324
|
/** Decoded connectivity / power status (HA petkit device-status enum).
|
|
@@ -64937,7 +65329,7 @@ object({
|
|
|
64937
65329
|
* with `errorCode` for consumers that want the raw integer. */
|
|
64938
65330
|
error: string().nullable(),
|
|
64939
65331
|
/** Raw device error code (0 / null = no error). */
|
|
64940
|
-
errorCode: number().nullable(),
|
|
65332
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
64941
65333
|
/** True for D4S/D4SH dual-hopper hardware — gates the per-hopper UI. */
|
|
64942
65334
|
isDualHopper: boolean(),
|
|
64943
65335
|
/** Child-lock (manual-lock) setting — buttons on the unit are disabled. */
|
|
@@ -64947,7 +65339,7 @@ object({
|
|
|
64947
65339
|
/** Play a chime when dispensing. */
|
|
64948
65340
|
feedSound: boolean(),
|
|
64949
65341
|
/** Speaker / prompt volume level (device-scaled integer). */
|
|
64950
|
-
volume: number(),
|
|
65342
|
+
volume: number().meta(readingMeta("none")),
|
|
64951
65343
|
/** Ms epoch when the slice was last refreshed from the cloud. */
|
|
64952
65344
|
lastFetchedAt: number()
|
|
64953
65345
|
});
|
|
@@ -65384,36 +65776,19 @@ method(_void(), PlatformCapabilitiesSchema), method(_void(), HardwareInfoSchema)
|
|
|
65384
65776
|
});
|
|
65385
65777
|
object({
|
|
65386
65778
|
/** Instantaneous power draw in watts. */
|
|
65387
|
-
watts: number().optional().meta({
|
|
65388
|
-
unit: "W",
|
|
65389
|
-
label: "Power"
|
|
65390
|
-
}),
|
|
65779
|
+
watts: number().optional().meta(readingMeta("power", { label: "Power" })),
|
|
65391
65780
|
/** Cumulative energy in kilowatt-hours since the meter was reset. */
|
|
65392
|
-
kwhTotal: number().optional().meta({
|
|
65393
|
-
unit: "kWh",
|
|
65394
|
-
label: "Energy"
|
|
65395
|
-
}),
|
|
65781
|
+
kwhTotal: number().optional().meta(readingMeta("energy", { label: "Energy" })),
|
|
65396
65782
|
/** Voltage in volts. */
|
|
65397
|
-
volts: number().optional(),
|
|
65783
|
+
volts: number().optional().meta(readingMeta("voltage")),
|
|
65398
65784
|
/** Current in amperes. */
|
|
65399
|
-
amps: number().optional(),
|
|
65400
|
-
/** Apparent power in volt-amperes
|
|
65401
|
-
va: number().optional(),
|
|
65785
|
+
amps: number().optional().meta(readingMeta("current")),
|
|
65786
|
+
/** Apparent power in volt-amperes. */
|
|
65787
|
+
va: number().optional().meta(readingMeta("apparent-power")),
|
|
65402
65788
|
/** Power factor (0..1) if reported. */
|
|
65403
|
-
powerFactor: number().min(0).max(1).optional(),
|
|
65789
|
+
powerFactor: number().min(0).max(1).optional().meta(readingMeta("ratio")),
|
|
65404
65790
|
/** Ms epoch when the slice was last updated. */
|
|
65405
|
-
lastFetchedAt: number()
|
|
65406
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
65407
|
-
* `attributes.unit_of_measurement` → 'V' / 'A' / 'W' / 'kW' / 'kWh').
|
|
65408
|
-
* Each upstream `sensor.*` entity surfaces ONE device_class, so one
|
|
65409
|
-
* unit per slice is unambiguous. The UI prefers this over the role's
|
|
65410
|
-
* canonical unit so a 'kW' / 'Wh' feed renders verbatim. */
|
|
65411
|
-
unit: string().optional(),
|
|
65412
|
-
/** Suggested decimal places for numeric display.
|
|
65413
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
65414
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
65415
|
-
* auto-formatting when absent. */
|
|
65416
|
-
precision: number().int().min(0).max(10).optional()
|
|
65791
|
+
lastFetchedAt: number()
|
|
65417
65792
|
});
|
|
65418
65793
|
DeviceType.Sensor;
|
|
65419
65794
|
/**
|
|
@@ -65434,11 +65809,11 @@ DeviceType.Sensor;
|
|
|
65434
65809
|
*/
|
|
65435
65810
|
var GpsLocationSchema = object({
|
|
65436
65811
|
/** Latitude in decimal degrees, -90..90. */
|
|
65437
|
-
latitude: number().min(-90).max(90),
|
|
65812
|
+
latitude: number().min(-90).max(90).meta(readingMeta("angle")),
|
|
65438
65813
|
/** Longitude in decimal degrees, -180..180. */
|
|
65439
|
-
longitude: number().min(-180).max(180),
|
|
65814
|
+
longitude: number().min(-180).max(180).meta(readingMeta("angle")),
|
|
65440
65815
|
/** Reported accuracy in meters (lower = better). */
|
|
65441
|
-
accuracyMeters: number().nonnegative()
|
|
65816
|
+
accuracyMeters: number().nonnegative().meta(readingMeta("length"))
|
|
65442
65817
|
});
|
|
65443
65818
|
object({
|
|
65444
65819
|
/** `home` / `not_home` / any user-defined zone name. */
|
|
@@ -65450,25 +65825,16 @@ object({
|
|
|
65450
65825
|
gps: GpsLocationSchema.nullable(),
|
|
65451
65826
|
/** Optional battery level of the tracking device (0..100). Null
|
|
65452
65827
|
* when not reported. */
|
|
65453
|
-
batteryPercent: number().min(0).max(100).nullable(),
|
|
65828
|
+
batteryPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
65454
65829
|
/** Ms epoch when the slice was last updated. */
|
|
65455
65830
|
lastChangedAt: number()
|
|
65456
65831
|
});
|
|
65457
65832
|
DeviceType.Presence;
|
|
65458
65833
|
object({
|
|
65459
|
-
/** Current pressure in hPa. */
|
|
65460
|
-
hpa: number(),
|
|
65834
|
+
/** Current pressure in hPa. `null` when the sample was refused (D393). */
|
|
65835
|
+
hpa: number().nullable().meta(readingMeta("pressure", { precision: 0 })),
|
|
65461
65836
|
/** Ms epoch when the slice was last updated. */
|
|
65462
|
-
lastFetchedAt: number()
|
|
65463
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
65464
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
65465
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
65466
|
-
unit: string().optional(),
|
|
65467
|
-
/** Suggested decimal places for numeric display.
|
|
65468
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
65469
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
65470
|
-
* auto-formatting when absent. */
|
|
65471
|
-
precision: number().int().min(0).max(10).optional()
|
|
65837
|
+
lastFetchedAt: number()
|
|
65472
65838
|
});
|
|
65473
65839
|
DeviceType.Sensor;
|
|
65474
65840
|
/**
|
|
@@ -65801,8 +66167,8 @@ DeviceType.Camera, method(PtzMoveCommandSchema.extend({ deviceId: number() }), _
|
|
|
65801
66167
|
}), _void(), { kind: "mutation" });
|
|
65802
66168
|
var PtzAutotrackSettingsSchema = object({
|
|
65803
66169
|
targetType: string().describe("Vendor target string (people/vehicle/pet); empty = camera default"),
|
|
65804
|
-
stopDelaySeconds: number().int().min(0).max(300),
|
|
65805
|
-
disappearDelaySeconds: number().int().min(0).max(300)
|
|
66170
|
+
stopDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration")),
|
|
66171
|
+
disappearDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration"))
|
|
65806
66172
|
});
|
|
65807
66173
|
/**
|
|
65808
66174
|
* One option the camera advertises as a valid `targetType`. Drivers
|
|
@@ -65859,7 +66225,7 @@ object({
|
|
|
65859
66225
|
/** null = unknown — never coerced to false (D393). */
|
|
65860
66226
|
running: boolean().nullable(),
|
|
65861
66227
|
/** Epoch ms the current boolean began; null while `running` is null. */
|
|
65862
|
-
since: number().nullable(),
|
|
66228
|
+
since: number().nullable().meta(readingMeta("none")),
|
|
65863
66229
|
source: RunningStateSourceSchema.meta({ label: "Source" }),
|
|
65864
66230
|
phase: string().nullable(),
|
|
65865
66231
|
/** null until a reading has been published (D393). */
|
|
@@ -67547,9 +67913,9 @@ var RecordTriggerSchema = _enum([
|
|
|
67547
67913
|
*/
|
|
67548
67914
|
var RecordWindowSchema = object({
|
|
67549
67915
|
trigger: RecordTriggerSchema,
|
|
67550
|
-
day: number().int().min(0).max(6),
|
|
67551
|
-
startMinute: number().int().min(0).max(1439),
|
|
67552
|
-
endMinute: number().int().min(1).max(1440)
|
|
67916
|
+
day: number().int().min(0).max(6).meta(readingMeta("none")),
|
|
67917
|
+
startMinute: number().int().min(0).max(1439).meta(readingMeta("none")),
|
|
67918
|
+
endMinute: number().int().min(1).max(1440).meta(readingMeta("none"))
|
|
67553
67919
|
});
|
|
67554
67920
|
/** Status of one physical volume, as the camera itself describes it. */
|
|
67555
67921
|
var OnboardStorageVolumeSchema = object({
|
|
@@ -67618,10 +67984,10 @@ object({
|
|
|
67618
67984
|
/** Master "record to the card at all" switch. */
|
|
67619
67985
|
enabled: boolean().nullable(),
|
|
67620
67986
|
overwriteWhenFull: boolean().nullable(),
|
|
67621
|
-
preRecordSec: number().nullable(),
|
|
67622
|
-
postRecordSec: number().nullable(),
|
|
67987
|
+
preRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
67988
|
+
postRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
67623
67989
|
/** Length of one recorded file, in minutes. */
|
|
67624
|
-
segmentMinutes: number().nullable(),
|
|
67990
|
+
segmentMinutes: number().nullable().meta(readingMeta("none")),
|
|
67625
67991
|
/** The primary track's weekly windows, flattened. */
|
|
67626
67992
|
windows: array(RecordWindowSchema),
|
|
67627
67993
|
/**
|
|
@@ -67637,7 +68003,7 @@ object({
|
|
|
67637
68003
|
* provider reporting a non-zero count also reports the schedule as not
|
|
67638
68004
|
* writable.
|
|
67639
68005
|
*/
|
|
67640
|
-
unreadableWindows: number(),
|
|
68006
|
+
unreadableWindows: number().meta(readingMeta("count")),
|
|
67641
68007
|
/**
|
|
67642
68008
|
* The camera is scheduled to record and has NO usable storage.
|
|
67643
68009
|
*
|
|
@@ -68308,7 +68674,7 @@ var CamStreamDescriptorSchema = object({
|
|
|
68308
68674
|
url: string().optional(),
|
|
68309
68675
|
codec: string().optional(),
|
|
68310
68676
|
resolution: CamStreamResolutionSchema.optional(),
|
|
68311
|
-
fps: number().positive().optional(),
|
|
68677
|
+
fps: number().positive().optional().meta(readingMeta("rate")),
|
|
68312
68678
|
label: string().optional(),
|
|
68313
68679
|
/** Device-level features (e.g. `battery-operated`) — drives broker policy. */
|
|
68314
68680
|
deviceFeatures: array(string()).optional(),
|
|
@@ -68338,18 +68704,18 @@ var StreamProfileSchema = _enum([
|
|
|
68338
68704
|
]);
|
|
68339
68705
|
/** The current encoding config of one stream profile. */
|
|
68340
68706
|
var StreamProfileConfigSchema = object({
|
|
68341
|
-
width: number(),
|
|
68342
|
-
height: number(),
|
|
68707
|
+
width: number().meta(readingMeta("none")),
|
|
68708
|
+
height: number().meta(readingMeta("none")),
|
|
68343
68709
|
codec: _enum(["h264", "h265"]),
|
|
68344
|
-
framerate: number(),
|
|
68345
|
-
bitrate: number(),
|
|
68710
|
+
framerate: number().meta(readingMeta("rate")),
|
|
68711
|
+
bitrate: number().meta(readingMeta("bitrate")),
|
|
68346
68712
|
bitrateMode: _enum(["vbr", "cbr"]).optional(),
|
|
68347
68713
|
encoderProfile: _enum([
|
|
68348
68714
|
"high",
|
|
68349
68715
|
"main",
|
|
68350
68716
|
"baseline"
|
|
68351
68717
|
]).optional(),
|
|
68352
|
-
gop: number().optional(),
|
|
68718
|
+
gop: number().optional().meta(readingMeta("none")),
|
|
68353
68719
|
/**
|
|
68354
68720
|
* Whether THIS profile currently carries an audio track. READ-ONLY here.
|
|
68355
68721
|
*
|
|
@@ -68992,23 +69358,13 @@ object({
|
|
|
68992
69358
|
});
|
|
68993
69359
|
DeviceType.Sensor;
|
|
68994
69360
|
object({
|
|
68995
|
-
/** Current temperature in Celsius. */
|
|
68996
|
-
celsius: number().meta({
|
|
68997
|
-
|
|
69361
|
+
/** Current temperature in Celsius. `null` when the sample was refused (D393). */
|
|
69362
|
+
celsius: number().nullable().meta(readingMeta("temperature", {
|
|
69363
|
+
precision: 1,
|
|
68998
69364
|
label: "Temperature"
|
|
68999
|
-
}),
|
|
69365
|
+
})),
|
|
69000
69366
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
69001
|
-
lastFetchedAt: number()
|
|
69002
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
69003
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
69004
|
-
* role's canonical unit, so a Fahrenheit feed renders '°F' not '°C'.
|
|
69005
|
-
* Absent → the UI falls back to the role's canonical unit. */
|
|
69006
|
-
unit: string().optional(),
|
|
69007
|
-
/** Suggested decimal places for numeric display.
|
|
69008
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
69009
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
69010
|
-
* auto-formatting when absent. */
|
|
69011
|
-
precision: number().int().min(0).max(10).optional()
|
|
69367
|
+
lastFetchedAt: number()
|
|
69012
69368
|
});
|
|
69013
69369
|
DeviceType.Sensor, DeviceType.Thermostat;
|
|
69014
69370
|
/**
|
|
@@ -69260,16 +69616,16 @@ object({
|
|
|
69260
69616
|
]),
|
|
69261
69617
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
69262
69618
|
* reading. */
|
|
69263
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
69619
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
69264
69620
|
/** Current fan-speed token (provider-verbatim). Null when unknown or
|
|
69265
69621
|
* the vacuum has no speed control. */
|
|
69266
69622
|
fanSpeed: string().nullable(),
|
|
69267
69623
|
/** Speed tokens the hardware accepts — drives the UI selector. */
|
|
69268
69624
|
availableFanSpeeds: array(string()),
|
|
69269
69625
|
/** 0..100 cleaning-completion percentage of the current task, or null. */
|
|
69270
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
69626
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
69271
69627
|
/** Current error code (0 / null = no error). */
|
|
69272
|
-
errorCode: number().nullable(),
|
|
69628
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
69273
69629
|
/** Human label for {@link errorCode}, or null when none / undecodable. */
|
|
69274
69630
|
errorLabel: string().nullable(),
|
|
69275
69631
|
/** Ms epoch when the slice was last updated. */
|
|
@@ -69308,7 +69664,7 @@ object({
|
|
|
69308
69664
|
]),
|
|
69309
69665
|
/** 0 = fully closed, 100 = fully open. Null when the device has no
|
|
69310
69666
|
* intermediate position surface. */
|
|
69311
|
-
position: number().min(0).max(100).nullable(),
|
|
69667
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
69312
69668
|
/** Ms epoch when the slice was last updated. */
|
|
69313
69669
|
lastChangedAt: number()
|
|
69314
69670
|
});
|
|
@@ -69336,9 +69692,9 @@ object({
|
|
|
69336
69692
|
DeviceType.Sensor;
|
|
69337
69693
|
object({
|
|
69338
69694
|
/** Current measured temperature. Null when not reported. */
|
|
69339
|
-
currentTemp: number().nullable(),
|
|
69695
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
69340
69696
|
/** Target temperature setpoint. Null when no setpoint surface. */
|
|
69341
|
-
targetTemp: number().nullable(),
|
|
69697
|
+
targetTemp: number().nullable().meta(readingMeta("temperature")),
|
|
69342
69698
|
/** Active operation mode = HA `state` (`eco` / `electric` / `gas` /
|
|
69343
69699
|
* `heat_pump` / `high_demand` / `performance` / `off`). Null when the
|
|
69344
69700
|
* device reports an unknown state. */
|
|
@@ -69349,9 +69705,9 @@ object({
|
|
|
69349
69705
|
* has no away surface. */
|
|
69350
69706
|
away: boolean().nullable(),
|
|
69351
69707
|
/** HA `min_temp` attribute. Null when not reported. */
|
|
69352
|
-
minTemp: number().nullable(),
|
|
69708
|
+
minTemp: number().nullable().meta(readingMeta("temperature")),
|
|
69353
69709
|
/** HA `max_temp` attribute. Null when not reported. */
|
|
69354
|
-
maxTemp: number().nullable(),
|
|
69710
|
+
maxTemp: number().nullable().meta(readingMeta("temperature")),
|
|
69355
69711
|
/** Ms epoch when the slice was last updated. */
|
|
69356
69712
|
lastChangedAt: number()
|
|
69357
69713
|
});
|
|
@@ -69375,25 +69731,18 @@ DeviceType.WaterHeater, method(object({
|
|
|
69375
69731
|
auth: "protected"
|
|
69376
69732
|
});
|
|
69377
69733
|
object({
|
|
69378
|
-
/** Verbatim
|
|
69379
|
-
* when no condition has been reported yet. */
|
|
69734
|
+
/** Verbatim condition state (`sunny`, `cloudy`, `rainy`, …). Null when none yet. */
|
|
69380
69735
|
condition: string().nullable(),
|
|
69381
|
-
/** Current temperature in
|
|
69382
|
-
temperature: number().nullable(),
|
|
69383
|
-
/** Temperature unit string (e.g. `°C` / `°F`). Null when not provided. */
|
|
69384
|
-
temperatureUnit: string().nullable(),
|
|
69736
|
+
/** Current temperature in Celsius. Null when not provided or refused. */
|
|
69737
|
+
temperature: number().nullable().meta(readingMeta("temperature", { precision: 1 })),
|
|
69385
69738
|
/** Relative humidity (0..100). Null when not provided. */
|
|
69386
|
-
humidity: number().min(0).max(100).nullable(),
|
|
69387
|
-
/** Barometric pressure in
|
|
69388
|
-
pressure: number().nullable(),
|
|
69389
|
-
/**
|
|
69390
|
-
|
|
69391
|
-
/** Wind speed in the reported unit. Null when not provided. */
|
|
69392
|
-
windSpeed: number().nullable(),
|
|
69393
|
-
/** Wind-speed unit string (e.g. `km/h` / `mph`). Null when not provided. */
|
|
69394
|
-
windSpeedUnit: string().nullable(),
|
|
69739
|
+
humidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
69740
|
+
/** Barometric pressure in hPa. Null when not provided or refused. */
|
|
69741
|
+
pressure: number().nullable().meta(readingMeta("pressure")),
|
|
69742
|
+
/** Wind speed in metres per second. Null when not provided or refused. */
|
|
69743
|
+
windSpeed: number().nullable().meta(readingMeta("speed")),
|
|
69395
69744
|
/** Wind bearing in degrees (0..360, meteorological). Null when not provided. */
|
|
69396
|
-
windBearing: number().nullable(),
|
|
69745
|
+
windBearing: number().nullable().meta(readingMeta("angle")),
|
|
69397
69746
|
/** Ms epoch when the slice was last updated. */
|
|
69398
69747
|
lastFetchedAt: number()
|
|
69399
69748
|
});
|
|
@@ -70363,6 +70712,13 @@ Object.freeze({
|
|
|
70363
70712
|
access: "view",
|
|
70364
70713
|
role: "admin"
|
|
70365
70714
|
},
|
|
70715
|
+
"addons.getPackageDocs": {
|
|
70716
|
+
capName: "addons",
|
|
70717
|
+
capScope: "system",
|
|
70718
|
+
addonId: null,
|
|
70719
|
+
access: "view",
|
|
70720
|
+
role: "admin"
|
|
70721
|
+
},
|
|
70366
70722
|
"addons.getVersions": {
|
|
70367
70723
|
capName: "addons",
|
|
70368
70724
|
capScope: "system",
|
|
@@ -73471,6 +73827,20 @@ Object.freeze({
|
|
|
73471
73827
|
access: "view",
|
|
73472
73828
|
role: "viewer"
|
|
73473
73829
|
},
|
|
73830
|
+
"groupCommands.getStatus": {
|
|
73831
|
+
capName: "group-commands",
|
|
73832
|
+
capScope: "device",
|
|
73833
|
+
addonId: null,
|
|
73834
|
+
access: "view",
|
|
73835
|
+
role: "viewer"
|
|
73836
|
+
},
|
|
73837
|
+
"groupStatus.getStatus": {
|
|
73838
|
+
capName: "group-status",
|
|
73839
|
+
capScope: "device",
|
|
73840
|
+
addonId: null,
|
|
73841
|
+
access: "view",
|
|
73842
|
+
role: "viewer"
|
|
73843
|
+
},
|
|
73474
73844
|
"heatingValve.getStatus": {
|
|
73475
73845
|
capName: "heating-valve",
|
|
73476
73846
|
capScope: "device",
|
|
@@ -83293,6 +83663,37 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83293
83663
|
icon: "flame"
|
|
83294
83664
|
}]
|
|
83295
83665
|
},
|
|
83666
|
+
"group-commands": {
|
|
83667
|
+
scope: "device",
|
|
83668
|
+
noun: t("Group command", "Comando di gruppo")
|
|
83669
|
+
},
|
|
83670
|
+
"group-status": {
|
|
83671
|
+
scope: "device",
|
|
83672
|
+
noun: t("Group", "Gruppo"),
|
|
83673
|
+
state: [
|
|
83674
|
+
{
|
|
83675
|
+
kind: "numeric",
|
|
83676
|
+
field: "included",
|
|
83677
|
+
quantity: t("the members reporting", "i membri che rispondono"),
|
|
83678
|
+
label: t("Reporting", "Rispondono"),
|
|
83679
|
+
icon: "users"
|
|
83680
|
+
},
|
|
83681
|
+
{
|
|
83682
|
+
kind: "numeric",
|
|
83683
|
+
field: "excluded",
|
|
83684
|
+
quantity: t("the members left out", "i membri esclusi"),
|
|
83685
|
+
label: t("Excluded", "Esclusi"),
|
|
83686
|
+
icon: "users"
|
|
83687
|
+
},
|
|
83688
|
+
{
|
|
83689
|
+
kind: "numeric",
|
|
83690
|
+
field: "total",
|
|
83691
|
+
quantity: t("the member count", "il numero di membri"),
|
|
83692
|
+
label: t("Members", "Membri"),
|
|
83693
|
+
icon: "sigma"
|
|
83694
|
+
}
|
|
83695
|
+
]
|
|
83696
|
+
},
|
|
83296
83697
|
"humidity-sensor": {
|
|
83297
83698
|
scope: "device",
|
|
83298
83699
|
noun: t("Humidity", "Umidità"),
|
|
@@ -83326,7 +83727,6 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83326
83727
|
field: "value",
|
|
83327
83728
|
quantity: t("the reading", "il valore"),
|
|
83328
83729
|
label: t("Reading", "Valore"),
|
|
83329
|
-
unitField: "unit",
|
|
83330
83730
|
icon: "gauge"
|
|
83331
83731
|
}]
|
|
83332
83732
|
},
|
|
@@ -83462,7 +83862,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83462
83862
|
field: "temperature",
|
|
83463
83863
|
quantity: t("the outdoor temperature", "la temperatura esterna"),
|
|
83464
83864
|
label: t("Temperature", "Temperatura"),
|
|
83465
|
-
|
|
83865
|
+
unit: "°C",
|
|
83466
83866
|
icon: "thermometer"
|
|
83467
83867
|
},
|
|
83468
83868
|
{
|
|
@@ -83478,7 +83878,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83478
83878
|
field: "windSpeed",
|
|
83479
83879
|
quantity: t("the wind speed", "la velocità del vento"),
|
|
83480
83880
|
label: t("Wind", "Vento"),
|
|
83481
|
-
|
|
83881
|
+
unit: "m/s",
|
|
83482
83882
|
icon: "wind"
|
|
83483
83883
|
},
|
|
83484
83884
|
{
|
|
@@ -83486,7 +83886,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83486
83886
|
field: "pressure",
|
|
83487
83887
|
quantity: t("the air pressure", "la pressione atmosferica"),
|
|
83488
83888
|
label: t("Pressure", "Pressione"),
|
|
83489
|
-
|
|
83889
|
+
unit: "hPa",
|
|
83490
83890
|
icon: "gauge"
|
|
83491
83891
|
}
|
|
83492
83892
|
]
|
|
@@ -84759,6 +85159,16 @@ Object.freeze({
|
|
|
84759
85159
|
form: "single",
|
|
84760
85160
|
optional: false
|
|
84761
85161
|
}],
|
|
85162
|
+
"groupCommands.getStatus": [{
|
|
85163
|
+
name: "deviceId",
|
|
85164
|
+
form: "single",
|
|
85165
|
+
optional: false
|
|
85166
|
+
}],
|
|
85167
|
+
"groupStatus.getStatus": [{
|
|
85168
|
+
name: "deviceId",
|
|
85169
|
+
form: "single",
|
|
85170
|
+
optional: false
|
|
85171
|
+
}],
|
|
84762
85172
|
"heatingValve.getStatus": [{
|
|
84763
85173
|
name: "deviceId",
|
|
84764
85174
|
form: "single",
|
|
@@ -86793,6 +87203,8 @@ new Map(Object.entries({
|
|
|
86793
87203
|
"detection-blind": "device-events",
|
|
86794
87204
|
"motion-noisy": "device-events",
|
|
86795
87205
|
"motion-calm": "device-events",
|
|
87206
|
+
"package-llm-silent": "device-events",
|
|
87207
|
+
"package-llm-answered": "device-events",
|
|
86796
87208
|
"recording-stalled": "device-events",
|
|
86797
87209
|
"recording-healthy": "device-events",
|
|
86798
87210
|
"recording-degraded": "device-events",
|
|
@@ -86876,6 +87288,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
|
|
|
86876
87288
|
label: "Motion without a subject",
|
|
86877
87289
|
kinds: ["motion-noisy", "motion-calm"]
|
|
86878
87290
|
},
|
|
87291
|
+
{
|
|
87292
|
+
id: "package-llm",
|
|
87293
|
+
family: "device-events",
|
|
87294
|
+
label: "Package confirm",
|
|
87295
|
+
kinds: ["package-llm-silent", "package-llm-answered"]
|
|
87296
|
+
},
|
|
86879
87297
|
{
|
|
86880
87298
|
id: "recording",
|
|
86881
87299
|
family: "device-events",
|
|
@@ -87057,6 +87475,8 @@ var DEVICE_EVENTS = [
|
|
|
87057
87475
|
"detection-blind",
|
|
87058
87476
|
"motion-noisy",
|
|
87059
87477
|
"motion-calm",
|
|
87478
|
+
"package-llm-silent",
|
|
87479
|
+
"package-llm-answered",
|
|
87060
87480
|
"recording-stalled",
|
|
87061
87481
|
"recording-healthy",
|
|
87062
87482
|
"recording-degraded",
|
|
@@ -87325,6 +87745,15 @@ new Map([
|
|
|
87325
87745
|
snapshotLabel: "Cameras with constant motion now",
|
|
87326
87746
|
snapshotSection: null
|
|
87327
87747
|
},
|
|
87748
|
+
{
|
|
87749
|
+
id: "package-llm-confirm",
|
|
87750
|
+
family: "device-events",
|
|
87751
|
+
label: "Package confirm (not answering / answering again)",
|
|
87752
|
+
bad: ["package-llm-silent"],
|
|
87753
|
+
recovery: ["package-llm-answered"],
|
|
87754
|
+
snapshotLabel: "Cameras whose package confirm is not answering",
|
|
87755
|
+
snapshotSection: null
|
|
87756
|
+
},
|
|
87328
87757
|
{
|
|
87329
87758
|
id: "recording-health",
|
|
87330
87759
|
family: "device-events",
|