@camstack/addon-post-analysis 1.2.636 → 1.2.638
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 +22 -0
- package/dist/{clip-model-registry-BV-RBus_.mjs → clip-model-registry-B-Dv5y3Z.mjs} +979 -515
- package/dist/{clip-model-registry-DgRbne5j.js → clip-model-registry-DEcrrqRz.js} +979 -515
- package/dist/embedding-encoder/index.js +1 -1
- package/dist/embedding-encoder/index.mjs +1 -1
- package/dist/pipeline-analytics/_stub.js +2 -2
- package/dist/pipeline-analytics/{_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-Coin4M0B.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-LOOCKNGE.mjs} +2 -2
- package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-D4TYbuPV.mjs +26 -0
- package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-DXlqUmY1.mjs +26 -0
- package/dist/pipeline-analytics/{hostInit-c7viEcQt.mjs → hostInit-C2kfB4nI.mjs} +2 -2
- package/dist/pipeline-analytics/index.js +156 -22
- package/dist/pipeline-analytics/index.mjs +156 -22
- package/dist/pipeline-analytics/remoteEntry.js +1 -1
- package/package.json +4 -2
- package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-j6sD2jfA.mjs +0 -26
- package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-Bcrs7B9G.mjs +0 -26
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createHash } from "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
|
|
@@ -5632,7 +5640,7 @@ var ZodIssueCode = {
|
|
|
5632
5640
|
var ZodFirstPartyTypeKind;
|
|
5633
5641
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5634
5642
|
//#endregion
|
|
5635
|
-
//#region ../types/dist/sleep-
|
|
5643
|
+
//#region ../types/dist/sleep-bykKrTgu.mjs
|
|
5636
5644
|
/**
|
|
5637
5645
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5638
5646
|
* window to float samples (D455).
|
|
@@ -8332,6 +8340,99 @@ function defineRecordKinds(specs) {
|
|
|
8332
8340
|
}
|
|
8333
8341
|
return out;
|
|
8334
8342
|
}
|
|
8343
|
+
var READING_QUANTITIES = [
|
|
8344
|
+
"temperature",
|
|
8345
|
+
"pressure",
|
|
8346
|
+
"speed",
|
|
8347
|
+
"precipitation",
|
|
8348
|
+
"precipitation-rate",
|
|
8349
|
+
"length",
|
|
8350
|
+
"area",
|
|
8351
|
+
"illuminance",
|
|
8352
|
+
"irradiance",
|
|
8353
|
+
"power",
|
|
8354
|
+
"energy",
|
|
8355
|
+
"voltage",
|
|
8356
|
+
"current",
|
|
8357
|
+
"apparent-power",
|
|
8358
|
+
"humidity",
|
|
8359
|
+
"percentage",
|
|
8360
|
+
"concentration-volume",
|
|
8361
|
+
"concentration-mass",
|
|
8362
|
+
"concentration-ppb",
|
|
8363
|
+
"volume",
|
|
8364
|
+
"duration",
|
|
8365
|
+
"duration-ms",
|
|
8366
|
+
"information",
|
|
8367
|
+
"sound-level",
|
|
8368
|
+
"signal-level",
|
|
8369
|
+
"colour-temperature",
|
|
8370
|
+
"angle",
|
|
8371
|
+
"bitrate",
|
|
8372
|
+
"rate",
|
|
8373
|
+
"mass",
|
|
8374
|
+
"index",
|
|
8375
|
+
"ratio",
|
|
8376
|
+
"count",
|
|
8377
|
+
"none",
|
|
8378
|
+
"device"
|
|
8379
|
+
];
|
|
8380
|
+
var ReadingQuantitySchema = _enum(READING_QUANTITIES);
|
|
8381
|
+
new Set(READING_QUANTITIES);
|
|
8382
|
+
/**
|
|
8383
|
+
* Stored unit symbol for a quantity. `none` means the number is dimensionless
|
|
8384
|
+
* (or an index / ratio / count). `device` means the cap has no single unit.
|
|
8385
|
+
*/
|
|
8386
|
+
var QUANTITY_BASE = {
|
|
8387
|
+
temperature: "°C",
|
|
8388
|
+
pressure: "hPa",
|
|
8389
|
+
speed: "m/s",
|
|
8390
|
+
precipitation: "mm",
|
|
8391
|
+
"precipitation-rate": "mm/h",
|
|
8392
|
+
length: "m",
|
|
8393
|
+
area: "m²",
|
|
8394
|
+
illuminance: "lx",
|
|
8395
|
+
irradiance: "W/m²",
|
|
8396
|
+
power: "W",
|
|
8397
|
+
energy: "kWh",
|
|
8398
|
+
voltage: "V",
|
|
8399
|
+
current: "A",
|
|
8400
|
+
"apparent-power": "VA",
|
|
8401
|
+
humidity: "%",
|
|
8402
|
+
percentage: "%",
|
|
8403
|
+
"concentration-volume": "ppm",
|
|
8404
|
+
"concentration-mass": "µg/m³",
|
|
8405
|
+
"concentration-ppb": "ppb",
|
|
8406
|
+
volume: "L",
|
|
8407
|
+
duration: "s",
|
|
8408
|
+
"duration-ms": "ms",
|
|
8409
|
+
information: "B",
|
|
8410
|
+
"sound-level": "dBFS",
|
|
8411
|
+
"signal-level": "dBm",
|
|
8412
|
+
"colour-temperature": "mired",
|
|
8413
|
+
angle: "°",
|
|
8414
|
+
bitrate: "kbps",
|
|
8415
|
+
rate: "fps",
|
|
8416
|
+
mass: "kg",
|
|
8417
|
+
index: "none",
|
|
8418
|
+
ratio: "none",
|
|
8419
|
+
count: "none",
|
|
8420
|
+
none: "none",
|
|
8421
|
+
device: "device"
|
|
8422
|
+
};
|
|
8423
|
+
/** The stored unit, or `undefined` when the quantity has no unit symbol. */
|
|
8424
|
+
function baseUnitOf(quantity) {
|
|
8425
|
+
const symbol = QUANTITY_BASE[quantity];
|
|
8426
|
+
if (symbol === "none" || symbol === "device") return void 0;
|
|
8427
|
+
return symbol;
|
|
8428
|
+
}
|
|
8429
|
+
function readingMeta(quantity, extras) {
|
|
8430
|
+
return {
|
|
8431
|
+
quantity,
|
|
8432
|
+
...extras?.precision !== void 0 ? { precision: extras.precision } : {},
|
|
8433
|
+
...extras?.label !== void 0 ? { label: extras.label } : {}
|
|
8434
|
+
};
|
|
8435
|
+
}
|
|
8335
8436
|
/** Shared Zod schemas used across streaming capabilities. */
|
|
8336
8437
|
var CamProfileSchema = _enum([
|
|
8337
8438
|
"high",
|
|
@@ -8359,8 +8460,8 @@ var CamStreamKindSchema = _enum([
|
|
|
8359
8460
|
"derived"
|
|
8360
8461
|
]);
|
|
8361
8462
|
var CamStreamResolutionSchema = object({
|
|
8362
|
-
width: number().int().positive(),
|
|
8363
|
-
height: number().int().positive()
|
|
8463
|
+
width: number().int().positive().meta(readingMeta("none")),
|
|
8464
|
+
height: number().int().positive().meta(readingMeta("none"))
|
|
8364
8465
|
});
|
|
8365
8466
|
var CameraStreamSchema = object({
|
|
8366
8467
|
/** Stable, provider-assigned id unique within the (deviceId) scope. */
|
|
@@ -8960,6 +9061,8 @@ var CAP_NAMES = Object.freeze([
|
|
|
8960
9061
|
"filesystem-browse",
|
|
8961
9062
|
"flood",
|
|
8962
9063
|
"gas",
|
|
9064
|
+
"group-commands",
|
|
9065
|
+
"group-status",
|
|
8963
9066
|
"heating-valve",
|
|
8964
9067
|
"humidifier",
|
|
8965
9068
|
"humidity-sensor",
|
|
@@ -9089,14 +9192,6 @@ Object.freeze({
|
|
|
9089
9192
|
{
|
|
9090
9193
|
"path": "aqi",
|
|
9091
9194
|
"valueType": "number"
|
|
9092
|
-
},
|
|
9093
|
-
{
|
|
9094
|
-
"path": "unit",
|
|
9095
|
-
"valueType": "string"
|
|
9096
|
-
},
|
|
9097
|
-
{
|
|
9098
|
-
"path": "precision",
|
|
9099
|
-
"valueType": "number"
|
|
9100
9195
|
}
|
|
9101
9196
|
],
|
|
9102
9197
|
"alarm-panel": [
|
|
@@ -9132,20 +9227,10 @@ Object.freeze({
|
|
|
9132
9227
|
"valueType": "boolean"
|
|
9133
9228
|
}
|
|
9134
9229
|
],
|
|
9135
|
-
"ambient-light-sensor": [
|
|
9136
|
-
|
|
9137
|
-
|
|
9138
|
-
|
|
9139
|
-
},
|
|
9140
|
-
{
|
|
9141
|
-
"path": "unit",
|
|
9142
|
-
"valueType": "string"
|
|
9143
|
-
},
|
|
9144
|
-
{
|
|
9145
|
-
"path": "precision",
|
|
9146
|
-
"valueType": "number"
|
|
9147
|
-
}
|
|
9148
|
-
],
|
|
9230
|
+
"ambient-light-sensor": [{
|
|
9231
|
+
"path": "lux",
|
|
9232
|
+
"valueType": "number"
|
|
9233
|
+
}],
|
|
9149
9234
|
"audio-metrics": [
|
|
9150
9235
|
{
|
|
9151
9236
|
"path": "ts",
|
|
@@ -9225,6 +9310,10 @@ Object.freeze({
|
|
|
9225
9310
|
"path": "lastUpdated",
|
|
9226
9311
|
"valueType": "number"
|
|
9227
9312
|
},
|
|
9313
|
+
{
|
|
9314
|
+
"path": "volts",
|
|
9315
|
+
"valueType": "number"
|
|
9316
|
+
},
|
|
9228
9317
|
{
|
|
9229
9318
|
"path": "lastContactAt",
|
|
9230
9319
|
"valueType": "number"
|
|
@@ -9467,10 +9556,6 @@ Object.freeze({
|
|
|
9467
9556
|
"datetime"
|
|
9468
9557
|
]
|
|
9469
9558
|
},
|
|
9470
|
-
{
|
|
9471
|
-
"path": "unit",
|
|
9472
|
-
"valueType": "string"
|
|
9473
|
-
},
|
|
9474
9559
|
{
|
|
9475
9560
|
"path": "min",
|
|
9476
9561
|
"valueType": "number"
|
|
@@ -9482,19 +9567,6 @@ Object.freeze({
|
|
|
9482
9567
|
{
|
|
9483
9568
|
"path": "step",
|
|
9484
9569
|
"valueType": "number"
|
|
9485
|
-
},
|
|
9486
|
-
{
|
|
9487
|
-
"path": "precision",
|
|
9488
|
-
"valueType": "number"
|
|
9489
|
-
},
|
|
9490
|
-
{
|
|
9491
|
-
"path": "format",
|
|
9492
|
-
"valueType": "enum",
|
|
9493
|
-
"enumValues": [
|
|
9494
|
-
"date",
|
|
9495
|
-
"time",
|
|
9496
|
-
"datetime"
|
|
9497
|
-
]
|
|
9498
9570
|
}
|
|
9499
9571
|
],
|
|
9500
9572
|
"cover": [
|
|
@@ -9735,13 +9807,8 @@ Object.freeze({
|
|
|
9735
9807
|
"path": "value",
|
|
9736
9808
|
"valueType": "string"
|
|
9737
9809
|
}, {
|
|
9738
|
-
"path": "
|
|
9739
|
-
"valueType": "
|
|
9740
|
-
"enumValues": [
|
|
9741
|
-
"date",
|
|
9742
|
-
"time",
|
|
9743
|
-
"datetime"
|
|
9744
|
-
]
|
|
9810
|
+
"path": "timestamp",
|
|
9811
|
+
"valueType": "boolean"
|
|
9745
9812
|
}],
|
|
9746
9813
|
"event-emitter": [
|
|
9747
9814
|
{
|
|
@@ -9814,6 +9881,20 @@ Object.freeze({
|
|
|
9814
9881
|
"path": "detected",
|
|
9815
9882
|
"valueType": "boolean"
|
|
9816
9883
|
}],
|
|
9884
|
+
"group-status": [
|
|
9885
|
+
{
|
|
9886
|
+
"path": "included",
|
|
9887
|
+
"valueType": "number"
|
|
9888
|
+
},
|
|
9889
|
+
{
|
|
9890
|
+
"path": "excluded",
|
|
9891
|
+
"valueType": "number"
|
|
9892
|
+
},
|
|
9893
|
+
{
|
|
9894
|
+
"path": "total",
|
|
9895
|
+
"valueType": "number"
|
|
9896
|
+
}
|
|
9897
|
+
],
|
|
9817
9898
|
"heating-valve": [{
|
|
9818
9899
|
"path": "position",
|
|
9819
9900
|
"valueType": "number"
|
|
@@ -9848,20 +9929,10 @@ Object.freeze({
|
|
|
9848
9929
|
"valueType": "number"
|
|
9849
9930
|
}
|
|
9850
9931
|
],
|
|
9851
|
-
"humidity-sensor": [
|
|
9852
|
-
|
|
9853
|
-
|
|
9854
|
-
|
|
9855
|
-
},
|
|
9856
|
-
{
|
|
9857
|
-
"path": "unit",
|
|
9858
|
-
"valueType": "string"
|
|
9859
|
-
},
|
|
9860
|
-
{
|
|
9861
|
-
"path": "precision",
|
|
9862
|
-
"valueType": "number"
|
|
9863
|
-
}
|
|
9864
|
-
],
|
|
9932
|
+
"humidity-sensor": [{
|
|
9933
|
+
"path": "percent",
|
|
9934
|
+
"valueType": "number"
|
|
9935
|
+
}],
|
|
9865
9936
|
"image": [{
|
|
9866
9937
|
"path": "url",
|
|
9867
9938
|
"valueType": "string"
|
|
@@ -10200,20 +10271,10 @@ Object.freeze({
|
|
|
10200
10271
|
"valueType": "boolean"
|
|
10201
10272
|
}
|
|
10202
10273
|
],
|
|
10203
|
-
"numeric-sensor": [
|
|
10204
|
-
|
|
10205
|
-
|
|
10206
|
-
|
|
10207
|
-
},
|
|
10208
|
-
{
|
|
10209
|
-
"path": "unit",
|
|
10210
|
-
"valueType": "string"
|
|
10211
|
-
},
|
|
10212
|
-
{
|
|
10213
|
-
"path": "precision",
|
|
10214
|
-
"valueType": "number"
|
|
10215
|
-
}
|
|
10216
|
-
],
|
|
10274
|
+
"numeric-sensor": [{
|
|
10275
|
+
"path": "value",
|
|
10276
|
+
"valueType": "number"
|
|
10277
|
+
}],
|
|
10217
10278
|
"pet-feeder": [
|
|
10218
10279
|
{
|
|
10219
10280
|
"path": "foodLevel",
|
|
@@ -10305,14 +10366,6 @@ Object.freeze({
|
|
|
10305
10366
|
{
|
|
10306
10367
|
"path": "powerFactor",
|
|
10307
10368
|
"valueType": "number"
|
|
10308
|
-
},
|
|
10309
|
-
{
|
|
10310
|
-
"path": "unit",
|
|
10311
|
-
"valueType": "string"
|
|
10312
|
-
},
|
|
10313
|
-
{
|
|
10314
|
-
"path": "precision",
|
|
10315
|
-
"valueType": "number"
|
|
10316
10369
|
}
|
|
10317
10370
|
],
|
|
10318
10371
|
"presence": [
|
|
@@ -10341,20 +10394,10 @@ Object.freeze({
|
|
|
10341
10394
|
"valueType": "number"
|
|
10342
10395
|
}
|
|
10343
10396
|
],
|
|
10344
|
-
"pressure-sensor": [
|
|
10345
|
-
|
|
10346
|
-
|
|
10347
|
-
|
|
10348
|
-
},
|
|
10349
|
-
{
|
|
10350
|
-
"path": "unit",
|
|
10351
|
-
"valueType": "string"
|
|
10352
|
-
},
|
|
10353
|
-
{
|
|
10354
|
-
"path": "precision",
|
|
10355
|
-
"valueType": "number"
|
|
10356
|
-
}
|
|
10357
|
-
],
|
|
10397
|
+
"pressure-sensor": [{
|
|
10398
|
+
"path": "hpa",
|
|
10399
|
+
"valueType": "number"
|
|
10400
|
+
}],
|
|
10358
10401
|
"privacy-mask": [{
|
|
10359
10402
|
"path": "enabled",
|
|
10360
10403
|
"valueType": "boolean"
|
|
@@ -10665,20 +10708,10 @@ Object.freeze({
|
|
|
10665
10708
|
"path": "tampered",
|
|
10666
10709
|
"valueType": "boolean"
|
|
10667
10710
|
}],
|
|
10668
|
-
"temperature-sensor": [
|
|
10669
|
-
|
|
10670
|
-
|
|
10671
|
-
|
|
10672
|
-
},
|
|
10673
|
-
{
|
|
10674
|
-
"path": "unit",
|
|
10675
|
-
"valueType": "string"
|
|
10676
|
-
},
|
|
10677
|
-
{
|
|
10678
|
-
"path": "precision",
|
|
10679
|
-
"valueType": "number"
|
|
10680
|
-
}
|
|
10681
|
-
],
|
|
10711
|
+
"temperature-sensor": [{
|
|
10712
|
+
"path": "celsius",
|
|
10713
|
+
"valueType": "number"
|
|
10714
|
+
}],
|
|
10682
10715
|
"update": [
|
|
10683
10716
|
{
|
|
10684
10717
|
"path": "currentVersion",
|
|
@@ -10789,10 +10822,6 @@ Object.freeze({
|
|
|
10789
10822
|
"path": "temperature",
|
|
10790
10823
|
"valueType": "number"
|
|
10791
10824
|
},
|
|
10792
|
-
{
|
|
10793
|
-
"path": "temperatureUnit",
|
|
10794
|
-
"valueType": "string"
|
|
10795
|
-
},
|
|
10796
10825
|
{
|
|
10797
10826
|
"path": "humidity",
|
|
10798
10827
|
"valueType": "number"
|
|
@@ -10801,18 +10830,10 @@ Object.freeze({
|
|
|
10801
10830
|
"path": "pressure",
|
|
10802
10831
|
"valueType": "number"
|
|
10803
10832
|
},
|
|
10804
|
-
{
|
|
10805
|
-
"path": "pressureUnit",
|
|
10806
|
-
"valueType": "string"
|
|
10807
|
-
},
|
|
10808
10833
|
{
|
|
10809
10834
|
"path": "windSpeed",
|
|
10810
10835
|
"valueType": "number"
|
|
10811
10836
|
},
|
|
10812
|
-
{
|
|
10813
|
-
"path": "windSpeedUnit",
|
|
10814
|
-
"valueType": "string"
|
|
10815
|
-
},
|
|
10816
10837
|
{
|
|
10817
10838
|
"path": "windBearing",
|
|
10818
10839
|
"valueType": "number"
|
|
@@ -10864,7 +10885,7 @@ Object.freeze({
|
|
|
10864
10885
|
* can answer "may a rule actuate this?" without importing the schema barrel
|
|
10865
10886
|
* (~144MB RSS per runner, D28).
|
|
10866
10887
|
*
|
|
10867
|
-
* Coverage:
|
|
10888
|
+
* Coverage: 93 device-scoped capabilities.
|
|
10868
10889
|
*/
|
|
10869
10890
|
var DEVICE_SCOPED_CAPS = new Set([
|
|
10870
10891
|
"accessories",
|
|
@@ -10905,6 +10926,8 @@ var DEVICE_SCOPED_CAPS = new Set([
|
|
|
10905
10926
|
"feature-probe",
|
|
10906
10927
|
"flood",
|
|
10907
10928
|
"gas",
|
|
10929
|
+
"group-commands",
|
|
10930
|
+
"group-status",
|
|
10908
10931
|
"heating-valve",
|
|
10909
10932
|
"humidifier",
|
|
10910
10933
|
"humidity-sensor",
|
|
@@ -11356,7 +11379,7 @@ function errMsg(err) {
|
|
|
11356
11379
|
return String(err);
|
|
11357
11380
|
}
|
|
11358
11381
|
//#endregion
|
|
11359
|
-
//#region ../types/dist/composition-
|
|
11382
|
+
//#region ../types/dist/composition-OhpuespA.mjs
|
|
11360
11383
|
/**
|
|
11361
11384
|
* Deterministic SHA-256 hash of an arbitrary serialisable value. The
|
|
11362
11385
|
* canonical form sorts object keys alphabetically at every depth so two
|
|
@@ -12271,15 +12294,74 @@ function validateExpressionSource(src) {
|
|
|
12271
12294
|
}
|
|
12272
12295
|
return null;
|
|
12273
12296
|
}
|
|
12274
|
-
/**
|
|
12275
|
-
|
|
12276
|
-
|
|
12277
|
-
|
|
12297
|
+
/**
|
|
12298
|
+
* A composition source identity: `(addonId, stableId)`, never a numeric device
|
|
12299
|
+
* id. Split out so helper schemas can name it without a cycle through
|
|
12300
|
+
* `composition.ts` (D659).
|
|
12301
|
+
*/
|
|
12278
12302
|
var CompositionSourceRefSchema = object({
|
|
12279
12303
|
/** The owning addon; `stableId` is unique only within it. */
|
|
12280
12304
|
addonId: string().min(1),
|
|
12281
12305
|
stableId: string().min(1)
|
|
12282
12306
|
});
|
|
12307
|
+
var GROUP_TEMPLATE_IDS = [
|
|
12308
|
+
"temperature",
|
|
12309
|
+
"humidity",
|
|
12310
|
+
"pressure",
|
|
12311
|
+
"illuminance",
|
|
12312
|
+
"power",
|
|
12313
|
+
"energy",
|
|
12314
|
+
"battery",
|
|
12315
|
+
"numeric",
|
|
12316
|
+
"motion",
|
|
12317
|
+
"contact",
|
|
12318
|
+
"leak",
|
|
12319
|
+
"smoke",
|
|
12320
|
+
"occupancy",
|
|
12321
|
+
"binary",
|
|
12322
|
+
"switch",
|
|
12323
|
+
"light"
|
|
12324
|
+
];
|
|
12325
|
+
var NUMERIC_AGGREGATES = [
|
|
12326
|
+
"mean",
|
|
12327
|
+
"median",
|
|
12328
|
+
"min",
|
|
12329
|
+
"max",
|
|
12330
|
+
"sum"
|
|
12331
|
+
];
|
|
12332
|
+
var BINARY_AGGREGATES = ["any", "all"];
|
|
12333
|
+
/** How an actuator group decides it is on. Unknown members never count as off. */
|
|
12334
|
+
var ACTIVE_CRITERIA = ["at-least-one", "all"];
|
|
12335
|
+
var AGGREGATE_REDUCERS = [
|
|
12336
|
+
"mean",
|
|
12337
|
+
"median",
|
|
12338
|
+
"min",
|
|
12339
|
+
"max",
|
|
12340
|
+
"sum",
|
|
12341
|
+
"any",
|
|
12342
|
+
"all"
|
|
12343
|
+
];
|
|
12344
|
+
var GroupTemplateIdSchema = _enum(GROUP_TEMPLATE_IDS);
|
|
12345
|
+
var AggregateReducerSchema = _enum(AGGREGATE_REDUCERS);
|
|
12346
|
+
var ActiveCriterionSchema = _enum(ACTIVE_CRITERIA);
|
|
12347
|
+
/** One member. The field is stored so occupancy can name motion or binary. */
|
|
12348
|
+
var HelperMemberSchema = object({
|
|
12349
|
+
source: CompositionSourceRefSchema,
|
|
12350
|
+
cap: string().min(1),
|
|
12351
|
+
fieldPath: string().min(1)
|
|
12352
|
+
});
|
|
12353
|
+
var HelperSpecSchema = discriminatedUnion("kind", [object({
|
|
12354
|
+
kind: literal("group"),
|
|
12355
|
+
templateId: GroupTemplateIdSchema,
|
|
12356
|
+
aggregate: AggregateReducerSchema,
|
|
12357
|
+
members: array(HelperMemberSchema).min(1).max(64),
|
|
12358
|
+
/** Actuator groups only. Readings leave this unset. */
|
|
12359
|
+
active: ActiveCriterionSchema.optional()
|
|
12360
|
+
})]);
|
|
12361
|
+
/** A composed device's stableId is this prefix plus the block id. */
|
|
12362
|
+
var COMPOSED_DEVICE_STABLE_ID_PREFIX = "composed-";
|
|
12363
|
+
/** Longest snippet a `code` source may carry (slice 4). */
|
|
12364
|
+
var MAX_COMPOSITION_CODE_LENGTH = 2e4;
|
|
12283
12365
|
/** One field of one capability of one source device. */
|
|
12284
12366
|
var CompositionFieldReadSchema = object({
|
|
12285
12367
|
source: CompositionSourceRefSchema,
|
|
@@ -12323,7 +12405,33 @@ var CompositionCodeSourceSchema = object({
|
|
|
12323
12405
|
var CompositionFieldSourceSchema = discriminatedUnion("kind", [
|
|
12324
12406
|
CompositionFromSourceSchema,
|
|
12325
12407
|
CompositionExpressionSourceSchema,
|
|
12326
|
-
CompositionCodeSourceSchema
|
|
12408
|
+
CompositionCodeSourceSchema,
|
|
12409
|
+
object({
|
|
12410
|
+
kind: literal("aggregate"),
|
|
12411
|
+
reducer: _enum([
|
|
12412
|
+
"mean",
|
|
12413
|
+
"median",
|
|
12414
|
+
"min",
|
|
12415
|
+
"max",
|
|
12416
|
+
"sum",
|
|
12417
|
+
"any",
|
|
12418
|
+
"all"
|
|
12419
|
+
]),
|
|
12420
|
+
reads: array(CompositionFieldReadSchema).min(1).max(64),
|
|
12421
|
+
/** `value` is the reading; the others are the member counts. */
|
|
12422
|
+
publish: _enum([
|
|
12423
|
+
"value",
|
|
12424
|
+
"included",
|
|
12425
|
+
"excluded",
|
|
12426
|
+
"total"
|
|
12427
|
+
]),
|
|
12428
|
+
/** What a `value` publish does when nobody is included. Counts ignore this. */
|
|
12429
|
+
empty: _enum([
|
|
12430
|
+
"null",
|
|
12431
|
+
"omit",
|
|
12432
|
+
"offline"
|
|
12433
|
+
])
|
|
12434
|
+
})
|
|
12327
12435
|
]);
|
|
12328
12436
|
var CompositionCommandTargetSchema = discriminatedUnion("kind", [object({
|
|
12329
12437
|
kind: literal("forward"),
|
|
@@ -12369,7 +12477,13 @@ var CompositionSchema = object({
|
|
|
12369
12477
|
kind: literal("existing"),
|
|
12370
12478
|
device: CompositionSourceRefSchema
|
|
12371
12479
|
})]),
|
|
12372
|
-
features: array(CompositionFeatureSchema).min(1).max(16)
|
|
12480
|
+
features: array(CompositionFeatureSchema).min(1).max(16),
|
|
12481
|
+
/**
|
|
12482
|
+
* Present when the block is a helper template. Absent on a free
|
|
12483
|
+
* composition (the room example, device 4603). The editor reads this,
|
|
12484
|
+
* never the compiled features.
|
|
12485
|
+
*/
|
|
12486
|
+
helper: HelperSpecSchema.optional()
|
|
12373
12487
|
}).superRefine((composition, ctx) => {
|
|
12374
12488
|
const seen = /* @__PURE__ */ new Set();
|
|
12375
12489
|
composition.features.forEach((feature, index) => {
|
|
@@ -19360,7 +19474,11 @@ var CompositionProblemSchema = object({
|
|
|
19360
19474
|
"item-field-reserved",
|
|
19361
19475
|
"target-missing",
|
|
19362
19476
|
"target-unreadable",
|
|
19363
|
-
"not-replaceable"
|
|
19477
|
+
"not-replaceable",
|
|
19478
|
+
"native-capability-replace",
|
|
19479
|
+
"mixed-quantity",
|
|
19480
|
+
"helper-mismatch",
|
|
19481
|
+
"member-constraint"
|
|
19364
19482
|
]),
|
|
19365
19483
|
path: string(),
|
|
19366
19484
|
message: string()
|
|
@@ -19381,7 +19499,8 @@ var CompositionUnavailableModeSchema = _enum([
|
|
|
19381
19499
|
"null",
|
|
19382
19500
|
"offline",
|
|
19383
19501
|
"unknown",
|
|
19384
|
-
"release"
|
|
19502
|
+
"release",
|
|
19503
|
+
"omit"
|
|
19385
19504
|
]);
|
|
19386
19505
|
/**
|
|
19387
19506
|
* `derived` reads a source · `clock` reads only `now`, recomputed when a sibling
|
|
@@ -19418,9 +19537,11 @@ var CompositionFieldPlanSchema = object({
|
|
|
19418
19537
|
reads: array(CompositionFieldReadSchema)
|
|
19419
19538
|
});
|
|
19420
19539
|
/**
|
|
19421
|
-
* What a feature does to its target (D663): `new` builds a capability on a
|
|
19422
|
-
* device; on an existing device it `add`s a capability the device lacks
|
|
19423
|
-
*
|
|
19540
|
+
* What a feature does to its target (D663, D944): `new` builds a capability on a
|
|
19541
|
+
* new device; on an existing device it `add`s a capability the device lacks.
|
|
19542
|
+
* Replacing a capability the device already serves is refused
|
|
19543
|
+
* (`native-capability-replace`), not planned. `replace` remains on the claim
|
|
19544
|
+
* wire for a claim the hub already holds.
|
|
19424
19545
|
*/
|
|
19425
19546
|
var CompositionFeatureModeSchema = _enum([
|
|
19426
19547
|
"new",
|
|
@@ -19593,6 +19714,275 @@ Object.freeze({
|
|
|
19593
19714
|
result: ["number", "null"]
|
|
19594
19715
|
}
|
|
19595
19716
|
});
|
|
19717
|
+
/**
|
|
19718
|
+
* One catalog row per base reading a group helper can build (D944 §3).
|
|
19719
|
+
* Data, not a form default written into the block.
|
|
19720
|
+
*/
|
|
19721
|
+
var NOW = {
|
|
19722
|
+
fieldPath: "lastFetchedAt",
|
|
19723
|
+
expr: "now"
|
|
19724
|
+
};
|
|
19725
|
+
var CHANGED = {
|
|
19726
|
+
fieldPath: "lastChangedAt",
|
|
19727
|
+
expr: "now"
|
|
19728
|
+
};
|
|
19729
|
+
function numeric(input) {
|
|
19730
|
+
return {
|
|
19731
|
+
...input,
|
|
19732
|
+
family: "numeric",
|
|
19733
|
+
deviceType: DeviceType.Sensor,
|
|
19734
|
+
memberDeviceType: DeviceType.Sensor,
|
|
19735
|
+
commandCaps: [],
|
|
19736
|
+
baseUnit: baseUnitOf(input.quantity),
|
|
19737
|
+
aggregates: NUMERIC_AGGREGATES,
|
|
19738
|
+
accept: [{
|
|
19739
|
+
cap: input.outputCap,
|
|
19740
|
+
fieldPath: input.outputField
|
|
19741
|
+
}]
|
|
19742
|
+
};
|
|
19743
|
+
}
|
|
19744
|
+
function binary(input) {
|
|
19745
|
+
return {
|
|
19746
|
+
...input,
|
|
19747
|
+
family: "binary",
|
|
19748
|
+
deviceType: DeviceType.Sensor,
|
|
19749
|
+
memberDeviceType: DeviceType.Sensor,
|
|
19750
|
+
commandCaps: [],
|
|
19751
|
+
quantity: "none",
|
|
19752
|
+
baseUnit: void 0,
|
|
19753
|
+
aggregates: BINARY_AGGREGATES,
|
|
19754
|
+
empty: "offline"
|
|
19755
|
+
};
|
|
19756
|
+
}
|
|
19757
|
+
var GROUP_TEMPLATES = [
|
|
19758
|
+
numeric({
|
|
19759
|
+
id: "temperature",
|
|
19760
|
+
summary: "Mean, median, min, max or sum of temperatures. Offline and unknown members are left out, never read as 0 °C.",
|
|
19761
|
+
role: DeviceRole.TemperatureSensor,
|
|
19762
|
+
outputCap: "temperature-sensor",
|
|
19763
|
+
outputField: "celsius",
|
|
19764
|
+
quantity: "temperature",
|
|
19765
|
+
defaultAggregate: "mean",
|
|
19766
|
+
empty: "null",
|
|
19767
|
+
companions: [NOW]
|
|
19768
|
+
}),
|
|
19769
|
+
numeric({
|
|
19770
|
+
id: "humidity",
|
|
19771
|
+
summary: "Humidity in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
19772
|
+
role: DeviceRole.HumiditySensor,
|
|
19773
|
+
outputCap: "humidity-sensor",
|
|
19774
|
+
outputField: "percent",
|
|
19775
|
+
quantity: "humidity",
|
|
19776
|
+
defaultAggregate: "mean",
|
|
19777
|
+
empty: "null",
|
|
19778
|
+
companions: [NOW]
|
|
19779
|
+
}),
|
|
19780
|
+
numeric({
|
|
19781
|
+
id: "pressure",
|
|
19782
|
+
summary: "Pressure in hectopascals. Offline and unknown members are left out, never read as 0 hPa.",
|
|
19783
|
+
role: DeviceRole.PressureSensor,
|
|
19784
|
+
outputCap: "pressure-sensor",
|
|
19785
|
+
outputField: "hpa",
|
|
19786
|
+
quantity: "pressure",
|
|
19787
|
+
defaultAggregate: "mean",
|
|
19788
|
+
empty: "null",
|
|
19789
|
+
companions: [NOW]
|
|
19790
|
+
}),
|
|
19791
|
+
numeric({
|
|
19792
|
+
id: "illuminance",
|
|
19793
|
+
summary: "Illuminance in lux. Offline and unknown members are left out, never read as 0 lx.",
|
|
19794
|
+
role: DeviceRole.AmbientLightSensor,
|
|
19795
|
+
outputCap: "ambient-light-sensor",
|
|
19796
|
+
outputField: "lux",
|
|
19797
|
+
quantity: "illuminance",
|
|
19798
|
+
defaultAggregate: "mean",
|
|
19799
|
+
empty: "null",
|
|
19800
|
+
companions: [NOW]
|
|
19801
|
+
}),
|
|
19802
|
+
numeric({
|
|
19803
|
+
id: "power",
|
|
19804
|
+
summary: "Power in watts, summed by default. Nobody reporting omits the key rather than writing 0 W.",
|
|
19805
|
+
role: DeviceRole.PowerSensor,
|
|
19806
|
+
outputCap: "power-meter",
|
|
19807
|
+
outputField: "watts",
|
|
19808
|
+
quantity: "power",
|
|
19809
|
+
defaultAggregate: "sum",
|
|
19810
|
+
empty: "omit",
|
|
19811
|
+
companions: [NOW]
|
|
19812
|
+
}),
|
|
19813
|
+
numeric({
|
|
19814
|
+
id: "energy",
|
|
19815
|
+
summary: "Energy in kilowatt-hours, summed by default. Nobody reporting omits the key rather than writing 0 kWh.",
|
|
19816
|
+
role: DeviceRole.EnergySensor,
|
|
19817
|
+
outputCap: "power-meter",
|
|
19818
|
+
outputField: "kwhTotal",
|
|
19819
|
+
quantity: "energy",
|
|
19820
|
+
defaultAggregate: "sum",
|
|
19821
|
+
empty: "omit",
|
|
19822
|
+
companions: [NOW]
|
|
19823
|
+
}),
|
|
19824
|
+
numeric({
|
|
19825
|
+
id: "battery",
|
|
19826
|
+
summary: "Battery charge in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
19827
|
+
role: DeviceRole.BatterySensor,
|
|
19828
|
+
outputCap: "battery",
|
|
19829
|
+
outputField: "percentage",
|
|
19830
|
+
quantity: "percentage",
|
|
19831
|
+
defaultAggregate: "mean",
|
|
19832
|
+
empty: "null",
|
|
19833
|
+
companions: [
|
|
19834
|
+
{
|
|
19835
|
+
fieldPath: "charging",
|
|
19836
|
+
expr: "\"unknown\""
|
|
19837
|
+
},
|
|
19838
|
+
{
|
|
19839
|
+
fieldPath: "sleeping",
|
|
19840
|
+
expr: "false"
|
|
19841
|
+
},
|
|
19842
|
+
{
|
|
19843
|
+
fieldPath: "lastUpdated",
|
|
19844
|
+
expr: "now"
|
|
19845
|
+
}
|
|
19846
|
+
]
|
|
19847
|
+
}),
|
|
19848
|
+
numeric({
|
|
19849
|
+
id: "numeric",
|
|
19850
|
+
summary: "A numeric reading in the members’ shared quantity. Mixed quantities are refused. Nobody reporting publishes null, not 0.",
|
|
19851
|
+
role: DeviceRole.NumericSensor,
|
|
19852
|
+
outputCap: "numeric-sensor",
|
|
19853
|
+
outputField: "value",
|
|
19854
|
+
quantity: "device",
|
|
19855
|
+
defaultAggregate: "mean",
|
|
19856
|
+
empty: "null",
|
|
19857
|
+
companions: [NOW]
|
|
19858
|
+
}),
|
|
19859
|
+
binary({
|
|
19860
|
+
id: "motion",
|
|
19861
|
+
summary: "Any or all motion. Offline and unknown members are left out, never read as off. Nobody reporting takes the device offline.",
|
|
19862
|
+
role: DeviceRole.MotionSensor,
|
|
19863
|
+
outputCap: "motion",
|
|
19864
|
+
outputField: "detected",
|
|
19865
|
+
defaultAggregate: "any",
|
|
19866
|
+
accept: [{
|
|
19867
|
+
cap: "motion",
|
|
19868
|
+
fieldPath: "detected"
|
|
19869
|
+
}],
|
|
19870
|
+
companions: [{
|
|
19871
|
+
fieldPath: "lastDetectedAt",
|
|
19872
|
+
expr: "null"
|
|
19873
|
+
}, {
|
|
19874
|
+
fieldPath: "autoClearAfterMs",
|
|
19875
|
+
expr: "null"
|
|
19876
|
+
}]
|
|
19877
|
+
}),
|
|
19878
|
+
binary({
|
|
19879
|
+
id: "contact",
|
|
19880
|
+
summary: "Any or all open contacts. Offline and unknown members are left out, never read as closed.",
|
|
19881
|
+
role: DeviceRole.ContactSensor,
|
|
19882
|
+
outputCap: "contact",
|
|
19883
|
+
outputField: "entryOpen",
|
|
19884
|
+
defaultAggregate: "any",
|
|
19885
|
+
accept: [{
|
|
19886
|
+
cap: "contact",
|
|
19887
|
+
fieldPath: "entryOpen"
|
|
19888
|
+
}],
|
|
19889
|
+
companions: [CHANGED]
|
|
19890
|
+
}),
|
|
19891
|
+
binary({
|
|
19892
|
+
id: "leak",
|
|
19893
|
+
summary: "Any or all leak detections. Offline and unknown members are left out, never read as dry.",
|
|
19894
|
+
role: DeviceRole.LeakSensor,
|
|
19895
|
+
outputCap: "flood",
|
|
19896
|
+
outputField: "flooded",
|
|
19897
|
+
defaultAggregate: "any",
|
|
19898
|
+
accept: [{
|
|
19899
|
+
cap: "flood",
|
|
19900
|
+
fieldPath: "flooded"
|
|
19901
|
+
}],
|
|
19902
|
+
companions: [CHANGED]
|
|
19903
|
+
}),
|
|
19904
|
+
binary({
|
|
19905
|
+
id: "smoke",
|
|
19906
|
+
summary: "Any or all smoke detections. Offline and unknown members are left out, never read as clear.",
|
|
19907
|
+
role: DeviceRole.SmokeSensor,
|
|
19908
|
+
outputCap: "smoke",
|
|
19909
|
+
outputField: "detected",
|
|
19910
|
+
defaultAggregate: "any",
|
|
19911
|
+
accept: [{
|
|
19912
|
+
cap: "smoke",
|
|
19913
|
+
fieldPath: "detected"
|
|
19914
|
+
}],
|
|
19915
|
+
companions: [CHANGED]
|
|
19916
|
+
}),
|
|
19917
|
+
binary({
|
|
19918
|
+
id: "occupancy",
|
|
19919
|
+
summary: "Any or all of motion or binary sensors, published as a binary. Presence zones are not aggregated. Nobody reporting is offline, not off.",
|
|
19920
|
+
role: DeviceRole.BinarySensor,
|
|
19921
|
+
outputCap: "binary",
|
|
19922
|
+
outputField: "on",
|
|
19923
|
+
defaultAggregate: "any",
|
|
19924
|
+
accept: [{
|
|
19925
|
+
cap: "motion",
|
|
19926
|
+
fieldPath: "detected"
|
|
19927
|
+
}, {
|
|
19928
|
+
cap: "binary",
|
|
19929
|
+
fieldPath: "on"
|
|
19930
|
+
}],
|
|
19931
|
+
companions: [CHANGED]
|
|
19932
|
+
}),
|
|
19933
|
+
binary({
|
|
19934
|
+
id: "binary",
|
|
19935
|
+
summary: "Any or all generic binary sensors. Offline and unknown members are left out, never read as off.",
|
|
19936
|
+
role: DeviceRole.BinarySensor,
|
|
19937
|
+
outputCap: "binary",
|
|
19938
|
+
outputField: "on",
|
|
19939
|
+
defaultAggregate: "any",
|
|
19940
|
+
accept: [{
|
|
19941
|
+
cap: "binary",
|
|
19942
|
+
fieldPath: "on"
|
|
19943
|
+
}],
|
|
19944
|
+
companions: [CHANGED]
|
|
19945
|
+
}),
|
|
19946
|
+
actuator({
|
|
19947
|
+
id: "switch",
|
|
19948
|
+
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.",
|
|
19949
|
+
deviceType: DeviceType.Switch,
|
|
19950
|
+
outputCap: "switch",
|
|
19951
|
+
commandCaps: ["switch"]
|
|
19952
|
+
}),
|
|
19953
|
+
actuator({
|
|
19954
|
+
id: "light",
|
|
19955
|
+
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.",
|
|
19956
|
+
deviceType: DeviceType.Light,
|
|
19957
|
+
outputCap: "switch",
|
|
19958
|
+
commandCaps: [
|
|
19959
|
+
"switch",
|
|
19960
|
+
"brightness",
|
|
19961
|
+
"color"
|
|
19962
|
+
]
|
|
19963
|
+
})
|
|
19964
|
+
];
|
|
19965
|
+
function actuator(input) {
|
|
19966
|
+
return {
|
|
19967
|
+
...input,
|
|
19968
|
+
family: "actuator",
|
|
19969
|
+
role: void 0,
|
|
19970
|
+
memberDeviceType: input.deviceType,
|
|
19971
|
+
outputField: "on",
|
|
19972
|
+
quantity: "none",
|
|
19973
|
+
baseUnit: void 0,
|
|
19974
|
+
aggregates: BINARY_AGGREGATES,
|
|
19975
|
+
defaultAggregate: "any",
|
|
19976
|
+
empty: "offline",
|
|
19977
|
+
accept: [{
|
|
19978
|
+
cap: "switch",
|
|
19979
|
+
fieldPath: "on"
|
|
19980
|
+
}],
|
|
19981
|
+
companions: [CHANGED]
|
|
19982
|
+
};
|
|
19983
|
+
}
|
|
19984
|
+
new Map(GROUP_TEMPLATES.map((template) => [template.id, template]));
|
|
19985
|
+
DeviceFeature.LightColorRgb, DeviceFeature.LightColorHsv, DeviceFeature.LightColorMired;
|
|
19596
19986
|
`${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
|
|
19597
19987
|
/**
|
|
19598
19988
|
* What a composition may BUILD on a device type (G2, D676): the caps a new
|
|
@@ -21313,12 +21703,12 @@ method(object({ deviceId: number().int().nonnegative() }), DeviceAdminLinkSchema
|
|
|
21313
21703
|
* providers detect renames by matching `uniqueId` and patch `id`
|
|
21314
21704
|
* in-place so dispatch keeps working.
|
|
21315
21705
|
*
|
|
21316
|
-
* **
|
|
21317
|
-
*
|
|
21318
|
-
*
|
|
21319
|
-
*
|
|
21320
|
-
* (`ha-domain-mapping`)
|
|
21321
|
-
* stored after that point.
|
|
21706
|
+
* **Display unit and precision are NOT stored here.** They are a read-time
|
|
21707
|
+
* preference (D944). A polymorphic reading stores its `quantity` here once,
|
|
21708
|
+
* at adopt, and a date/time value stores `dateTimeShape` the same way —
|
|
21709
|
+
* neither is repeated on each sample. The `device_class` tag is an
|
|
21710
|
+
* HA-specific input consumed at the discovery boundary (`ha-domain-mapping`)
|
|
21711
|
+
* to derive the CamStack `DeviceRole`; it is never stored after that point.
|
|
21322
21712
|
*
|
|
21323
21713
|
* The `raw` escape hatch carries provider-specific attributes that don't
|
|
21324
21714
|
* fit the structured slots (HA `attributes` whitelist, Reolink `deviceCache`
|
|
@@ -21332,6 +21722,14 @@ var SourceInfoSchema = object({
|
|
|
21332
21722
|
/** Immutable upstream identifier when available (HA `unique_id`, … ).
|
|
21333
21723
|
* Used to detect rename when `id` changes. */
|
|
21334
21724
|
uniqueId: string().optional(),
|
|
21725
|
+
/** Quantity of a polymorphic reading, written once at adopt (D944). */
|
|
21726
|
+
quantity: ReadingQuantitySchema.optional(),
|
|
21727
|
+
/** Date / time / datetime shape of a string reading, written once at adopt. */
|
|
21728
|
+
dateTimeShape: _enum([
|
|
21729
|
+
"date",
|
|
21730
|
+
"time",
|
|
21731
|
+
"datetime"
|
|
21732
|
+
]).optional(),
|
|
21335
21733
|
/** Provider-specific extras that don't fit the structured slots.
|
|
21336
21734
|
* Whitelist what goes here per provider — do NOT dump entire HA
|
|
21337
21735
|
* attribute blobs (would explode the meta JSON column). */
|
|
@@ -42359,7 +42757,8 @@ method(object({
|
|
|
42359
42757
|
"enum"
|
|
42360
42758
|
]),
|
|
42361
42759
|
enumValues: array(string()).optional(),
|
|
42362
|
-
item: boolean().optional()
|
|
42760
|
+
item: boolean().optional(),
|
|
42761
|
+
quantity: ReadingQuantitySchema.optional()
|
|
42363
42762
|
})).readonly(),
|
|
42364
42763
|
itemArray: object({
|
|
42365
42764
|
path: string(),
|
|
@@ -46426,8 +46825,8 @@ var MaskPolygonShapeSchema = object({
|
|
|
46426
46825
|
/** Boolean cell grid — row-major, length === gridWidth*gridHeight. */
|
|
46427
46826
|
var MaskGridShapeSchema = object({
|
|
46428
46827
|
kind: literal("grid"),
|
|
46429
|
-
gridWidth: number(),
|
|
46430
|
-
gridHeight: number(),
|
|
46828
|
+
gridWidth: number().meta(readingMeta("none")),
|
|
46829
|
+
gridHeight: number().meta(readingMeta("none")),
|
|
46431
46830
|
cells: array(boolean())
|
|
46432
46831
|
});
|
|
46433
46832
|
discriminatedUnion("kind", [
|
|
@@ -46539,6 +46938,8 @@ var NcSystemEventKindSchema = _enum([
|
|
|
46539
46938
|
"detection-blind",
|
|
46540
46939
|
"motion-noisy",
|
|
46541
46940
|
"motion-calm",
|
|
46941
|
+
"package-llm-silent",
|
|
46942
|
+
"package-llm-answered",
|
|
46542
46943
|
"recording-stalled",
|
|
46543
46944
|
"recording-healthy",
|
|
46544
46945
|
"recording-degraded",
|
|
@@ -48101,6 +48502,14 @@ var NC_CONDITION_CATALOG = [
|
|
|
48101
48502
|
value: "motion-calm",
|
|
48102
48503
|
label: "Camera motion calm again"
|
|
48103
48504
|
},
|
|
48505
|
+
{
|
|
48506
|
+
value: "package-llm-silent",
|
|
48507
|
+
label: "Package confirm not answering"
|
|
48508
|
+
},
|
|
48509
|
+
{
|
|
48510
|
+
value: "package-llm-answered",
|
|
48511
|
+
label: "Package confirm answering again"
|
|
48512
|
+
},
|
|
48104
48513
|
{
|
|
48105
48514
|
value: "recording-stalled",
|
|
48106
48515
|
label: "Recording stalled"
|
|
@@ -59476,6 +59885,28 @@ var PackageVersionInfoSchema = object({
|
|
|
59476
59885
|
deprecated: string().optional(),
|
|
59477
59886
|
distTags: array(string()).readonly()
|
|
59478
59887
|
});
|
|
59888
|
+
/**
|
|
59889
|
+
* One published document. `ok` is markdown from the registry. `missing` means
|
|
59890
|
+
* the registry answered and the file was not there. `error` is a registry or
|
|
59891
|
+
* tarball failure — never an empty string standing in for either.
|
|
59892
|
+
*/
|
|
59893
|
+
var PackageDocBodySchema = discriminatedUnion("status", [
|
|
59894
|
+
object({
|
|
59895
|
+
status: literal("ok"),
|
|
59896
|
+
markdown: string()
|
|
59897
|
+
}),
|
|
59898
|
+
object({ status: literal("missing") }),
|
|
59899
|
+
object({
|
|
59900
|
+
status: literal("error"),
|
|
59901
|
+
message: string()
|
|
59902
|
+
})
|
|
59903
|
+
]);
|
|
59904
|
+
var PackageDocsSchema = object({
|
|
59905
|
+
name: string(),
|
|
59906
|
+
version: string(),
|
|
59907
|
+
readme: PackageDocBodySchema,
|
|
59908
|
+
changelog: PackageDocBodySchema
|
|
59909
|
+
});
|
|
59479
59910
|
var SearchResultSchema = object({
|
|
59480
59911
|
name: string(),
|
|
59481
59912
|
version: string(),
|
|
@@ -59694,7 +60125,10 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
|
|
|
59694
60125
|
}), object({ success: literal(true) }), {
|
|
59695
60126
|
kind: "mutation",
|
|
59696
60127
|
auth: "admin"
|
|
59697
|
-
}), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({
|
|
60128
|
+
}), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({
|
|
60129
|
+
name: string().min(1),
|
|
60130
|
+
version: string().min(1).optional()
|
|
60131
|
+
}), PackageDocsSchema, { auth: "admin" }), method(object({ addonId: string() }), RestartAddonResultSchema, {
|
|
59698
60132
|
kind: "mutation",
|
|
59699
60133
|
auth: "admin"
|
|
59700
60134
|
}), method(object({ packageName: string() }), object({ success: literal(true) }), {
|
|
@@ -59753,27 +60187,17 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
|
|
|
59753
60187
|
*/
|
|
59754
60188
|
var AirQualitySensorStatusSchema = object({
|
|
59755
60189
|
/** Carbon dioxide concentration in ppm. */
|
|
59756
|
-
co2Ppm: number().min(0).optional(),
|
|
60190
|
+
co2Ppm: number().min(0).optional().meta(readingMeta("concentration-volume")),
|
|
59757
60191
|
/** Total volatile organic compounds in ppb. */
|
|
59758
|
-
vocPpb: number().min(0).optional(),
|
|
60192
|
+
vocPpb: number().min(0).optional().meta(readingMeta("concentration-ppb")),
|
|
59759
60193
|
/** Particulate matter ≤ 2.5 μm in µg/m³. */
|
|
59760
|
-
pm25: number().min(0).optional(),
|
|
60194
|
+
pm25: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
59761
60195
|
/** Particulate matter ≤ 10 μm in µg/m³. */
|
|
59762
|
-
pm10: number().min(0).optional(),
|
|
60196
|
+
pm10: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
59763
60197
|
/** Composite AQI value (typically 0..500). */
|
|
59764
|
-
aqi: number().optional(),
|
|
60198
|
+
aqi: number().optional().meta(readingMeta("index")),
|
|
59765
60199
|
/** Ms epoch when the slice was last updated. */
|
|
59766
|
-
lastFetchedAt: number()
|
|
59767
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
59768
|
-
* `attributes.unit_of_measurement` → 'ppm' / 'ppb' / 'µg/m³'). Each
|
|
59769
|
-
* upstream `sensor.*` entity surfaces ONE device_class, so one unit
|
|
59770
|
-
* per slice is unambiguous. */
|
|
59771
|
-
unit: string().optional(),
|
|
59772
|
-
/** Suggested decimal places for numeric display.
|
|
59773
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
59774
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
59775
|
-
* auto-formatting when absent. */
|
|
59776
|
-
precision: number().int().min(0).max(10).optional()
|
|
60200
|
+
lastFetchedAt: number()
|
|
59777
60201
|
});
|
|
59778
60202
|
var airQualitySensorCapability = {
|
|
59779
60203
|
name: "air-quality-sensor",
|
|
@@ -59810,12 +60234,12 @@ var airQualitySensorCapability = {
|
|
|
59810
60234
|
},
|
|
59811
60235
|
pm25: {
|
|
59812
60236
|
kind: "gauge",
|
|
59813
|
-
unit: "
|
|
60237
|
+
unit: "µg/m³",
|
|
59814
60238
|
deadband: 1
|
|
59815
60239
|
},
|
|
59816
60240
|
pm10: {
|
|
59817
60241
|
kind: "gauge",
|
|
59818
|
-
unit: "
|
|
60242
|
+
unit: "µg/m³",
|
|
59819
60243
|
deadband: 1
|
|
59820
60244
|
},
|
|
59821
60245
|
aqi: {
|
|
@@ -59833,22 +60257,13 @@ var airQualitySensorCapability = {
|
|
|
59833
60257
|
* entries with `device_class: illuminance`.
|
|
59834
60258
|
*/
|
|
59835
60259
|
var AmbientLightSensorStatusSchema = object({
|
|
59836
|
-
/** Current illuminance in lux (lx). */
|
|
59837
|
-
lux: number().min(0).meta({
|
|
59838
|
-
|
|
60260
|
+
/** Current illuminance in lux (lx). `null` when the sample was refused (D393). */
|
|
60261
|
+
lux: number().min(0).nullable().meta(readingMeta("illuminance", {
|
|
60262
|
+
precision: 0,
|
|
59839
60263
|
label: "Illuminance"
|
|
59840
|
-
}),
|
|
60264
|
+
})),
|
|
59841
60265
|
/** Ms epoch when the slice was last updated. */
|
|
59842
|
-
lastFetchedAt: number()
|
|
59843
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
59844
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
59845
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
59846
|
-
unit: string().optional(),
|
|
59847
|
-
/** Suggested decimal places for numeric display.
|
|
59848
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
59849
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
59850
|
-
* auto-formatting when absent. */
|
|
59851
|
-
precision: number().int().min(0).max(10).optional()
|
|
60266
|
+
lastFetchedAt: number()
|
|
59852
60267
|
});
|
|
59853
60268
|
var ambientLightSensorCapability = {
|
|
59854
60269
|
name: "ambient-light-sensor",
|
|
@@ -59880,12 +60295,7 @@ var ambientLightSensorCapability = {
|
|
|
59880
60295
|
} } },
|
|
59881
60296
|
/** Clock fields: written, but excluded from the compare that decides
|
|
59882
60297
|
* whether persisting is worth a SQLite commit. */
|
|
59883
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
59884
|
-
customize: {
|
|
59885
|
-
version: 1,
|
|
59886
|
-
advanced: "derive",
|
|
59887
|
-
targets: []
|
|
59888
|
-
}
|
|
60298
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
59889
60299
|
};
|
|
59890
60300
|
/**
|
|
59891
60301
|
* Per-class audio metrics aggregated over a sliding window.
|
|
@@ -60112,10 +60522,7 @@ var BatteryStatusSchema = object({
|
|
|
60112
60522
|
* Consumers must SKIP a null rather than coerce it — `battery-band` already
|
|
60113
60523
|
* declines to band a non-finite reading, which is the correct shape.
|
|
60114
60524
|
*/
|
|
60115
|
-
percentage: number().min(0).max(100).nullable().meta({
|
|
60116
|
-
unit: "%",
|
|
60117
|
-
label: "Charge"
|
|
60118
|
-
}),
|
|
60525
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage", { label: "Charge" })),
|
|
60119
60526
|
/**
|
|
60120
60527
|
* Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
|
|
60121
60528
|
* Reolink-specific for the Solar Panel 2 accessory (will become
|
|
@@ -60142,7 +60549,14 @@ var BatteryStatusSchema = object({
|
|
|
60142
60549
|
*/
|
|
60143
60550
|
sleeping: boolean().meta({ label: "Sleeping" }),
|
|
60144
60551
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
60145
|
-
lastUpdated: number(),
|
|
60552
|
+
lastUpdated: number().meta(readingMeta("none")),
|
|
60553
|
+
/**
|
|
60554
|
+
* Battery voltage in volts, for a cell the firmware reports as voltage
|
|
60555
|
+
* rather than a percentage (Ecowitt capacitor packs). Absent on cameras
|
|
60556
|
+
* that only report charge. A second reading on this cap, not a second
|
|
60557
|
+
* `numeric-sensor` on the same device.
|
|
60558
|
+
*/
|
|
60559
|
+
volts: number().nullable().optional().meta(readingMeta("voltage", { label: "Voltage" })),
|
|
60146
60560
|
/**
|
|
60147
60561
|
* Ms epoch of the last time the device PROVED it was reachable — a
|
|
60148
60562
|
* completed firmware round-trip, an observed wake, or an inbound push
|
|
@@ -60194,7 +60608,6 @@ var BATTERY_DEVICE_TYPES = [
|
|
|
60194
60608
|
/** Generic Customize target for the percentage reading (D936). */
|
|
60195
60609
|
var batteryCustomize = {
|
|
60196
60610
|
version: 1,
|
|
60197
|
-
advanced: "derive",
|
|
60198
60611
|
targets: [{
|
|
60199
60612
|
id: "percentage",
|
|
60200
60613
|
cardinality: "scalar",
|
|
@@ -60203,7 +60616,7 @@ var batteryCustomize = {
|
|
|
60203
60616
|
stateField: "percentage"
|
|
60204
60617
|
},
|
|
60205
60618
|
deviceTypes: BATTERY_DEVICE_TYPES,
|
|
60206
|
-
apply: "add
|
|
60619
|
+
apply: "add",
|
|
60207
60620
|
path: "percentage",
|
|
60208
60621
|
sources: [{
|
|
60209
60622
|
kind: "field",
|
|
@@ -60324,10 +60737,16 @@ onStatusChanged: { data: object({
|
|
|
60324
60737
|
/**
|
|
60325
60738
|
* History (D850): recorded series. The generic capture replaces the `battery` series of `pipeline-analytics:stats-5m`.
|
|
60326
60739
|
*/
|
|
60327
|
-
history: { fields: {
|
|
60328
|
-
|
|
60329
|
-
|
|
60330
|
-
|
|
60740
|
+
history: { fields: {
|
|
60741
|
+
percentage: {
|
|
60742
|
+
kind: "gauge",
|
|
60743
|
+
unit: "%"
|
|
60744
|
+
},
|
|
60745
|
+
volts: {
|
|
60746
|
+
kind: "gauge",
|
|
60747
|
+
unit: "V"
|
|
60748
|
+
}
|
|
60749
|
+
} },
|
|
60331
60750
|
customize: batteryCustomize,
|
|
60332
60751
|
/** Clock fields: written, but excluded from the compare that decides
|
|
60333
60752
|
* whether persisting is worth a SQLite commit. */
|
|
@@ -60374,12 +60793,7 @@ var binaryCapability = {
|
|
|
60374
60793
|
history: { fields: { on: { kind: "boolean" } } },
|
|
60375
60794
|
/** Clock fields: written, but excluded from the compare that decides
|
|
60376
60795
|
* whether persisting is worth a SQLite commit. */
|
|
60377
|
-
volatileStateFields: ["lastChangedAt"]
|
|
60378
|
-
customize: {
|
|
60379
|
-
version: 1,
|
|
60380
|
-
advanced: "derive",
|
|
60381
|
-
targets: []
|
|
60382
|
-
}
|
|
60796
|
+
volatileStateFields: ["lastChangedAt"]
|
|
60383
60797
|
};
|
|
60384
60798
|
/**
|
|
60385
60799
|
* Dimmable-light brightness control. Co-exists with `switch` on the
|
|
@@ -60395,7 +60809,7 @@ var binaryCapability = {
|
|
|
60395
60809
|
*/
|
|
60396
60810
|
var BrightnessStatusSchema = object({
|
|
60397
60811
|
/** Current level as 0..100 inclusive. Firmware-reported. */
|
|
60398
|
-
percentage: number().min(0).max(100),
|
|
60812
|
+
percentage: number().min(0).max(100).meta(readingMeta("percentage")),
|
|
60399
60813
|
/** Ms epoch of the last operator-driven change. Useful for UI freshness. */
|
|
60400
60814
|
lastChangedAt: number()
|
|
60401
60815
|
});
|
|
@@ -60876,21 +61290,21 @@ var ClimateControlStatusSchema = object({
|
|
|
60876
61290
|
/** Single setpoint in Celsius. Used by single-target modes
|
|
60877
61291
|
* (heat / cool / dry). Null when the device is in a range mode
|
|
60878
61292
|
* (`heat_cool`) or has no setpoint at all (`fan_only`/`off`). */
|
|
60879
|
-
target: number().nullable(),
|
|
61293
|
+
target: number().nullable().meta(readingMeta("temperature")),
|
|
60880
61294
|
/** Upper bound of the dual setpoint in Celsius. Populated only
|
|
60881
61295
|
* in `heat_cool` mode. */
|
|
60882
|
-
targetHigh: number().nullable(),
|
|
61296
|
+
targetHigh: number().nullable().meta(readingMeta("temperature")),
|
|
60883
61297
|
/** Lower bound of the dual setpoint in Celsius. Populated only
|
|
60884
61298
|
* in `heat_cool` mode. */
|
|
60885
|
-
targetLow: number().nullable(),
|
|
61299
|
+
targetLow: number().nullable().meta(readingMeta("temperature")),
|
|
60886
61300
|
/** Target relative humidity (0..100). Null when the device has no
|
|
60887
61301
|
* humidity control. */
|
|
60888
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
61302
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
60889
61303
|
/** Current measured temperature in Celsius. Read-only — pushed by
|
|
60890
61304
|
* the device's internal sensor. */
|
|
60891
|
-
currentTemp: number().nullable(),
|
|
61305
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
60892
61306
|
/** Current measured relative humidity (0..100). Read-only. */
|
|
60893
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
61307
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
60894
61308
|
/** Vertical louver swing on/off. Null when the device has no vertical
|
|
60895
61309
|
* swing surface (gate with `DeviceFeature.ClimateSwingVertical`). */
|
|
60896
61310
|
swingVertical: boolean().nullable(),
|
|
@@ -60898,11 +61312,11 @@ var ClimateControlStatusSchema = object({
|
|
|
60898
61312
|
* horizontal swing surface (gate with `DeviceFeature.ClimateSwingHorizontal`). */
|
|
60899
61313
|
swingHorizontal: boolean().nullable(),
|
|
60900
61314
|
/** Lowest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
60901
|
-
minTemp: number().nullable().optional(),
|
|
61315
|
+
minTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
60902
61316
|
/** Highest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
60903
|
-
maxTemp: number().nullable().optional(),
|
|
61317
|
+
maxTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
60904
61318
|
/** Setpoint granularity, Celsius (0.5, 1). Absent / null = not reported. */
|
|
60905
|
-
tempStep: number().positive().nullable().optional(),
|
|
61319
|
+
tempStep: number().positive().nullable().optional().meta(readingMeta("temperature")),
|
|
60906
61320
|
/** Ms epoch when the slice was last updated (push or command). */
|
|
60907
61321
|
lastFetchedAt: number()
|
|
60908
61322
|
});
|
|
@@ -61044,17 +61458,17 @@ var climateControlCapability = {
|
|
|
61044
61458
|
* modes to expose in the picker without a slice fetch.
|
|
61045
61459
|
*/
|
|
61046
61460
|
var RgbTripletSchema = object({
|
|
61047
|
-
r: number().int().min(0).max(255),
|
|
61048
|
-
g: number().int().min(0).max(255),
|
|
61049
|
-
b: number().int().min(0).max(255)
|
|
61461
|
+
r: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
61462
|
+
g: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
61463
|
+
b: number().int().min(0).max(255).meta(readingMeta("none"))
|
|
61050
61464
|
});
|
|
61051
61465
|
var HsvTripletSchema = object({
|
|
61052
61466
|
/** Hue in degrees, 0..360. */
|
|
61053
|
-
h: number().min(0).max(360),
|
|
61467
|
+
h: number().min(0).max(360).meta(readingMeta("none")),
|
|
61054
61468
|
/** Saturation as 0..100 inclusive. */
|
|
61055
|
-
s: number().min(0).max(100),
|
|
61469
|
+
s: number().min(0).max(100).meta(readingMeta("none")),
|
|
61056
61470
|
/** Value/brightness as 0..100 inclusive. */
|
|
61057
|
-
v: number().min(0).max(100)
|
|
61471
|
+
v: number().min(0).max(100).meta(readingMeta("none"))
|
|
61058
61472
|
});
|
|
61059
61473
|
var ColorInputSchema = discriminatedUnion("mode", [
|
|
61060
61474
|
object({
|
|
@@ -61083,7 +61497,7 @@ var ColorStatusSchema = object({
|
|
|
61083
61497
|
/** Populated when `mode === 'hsv'`. */
|
|
61084
61498
|
hsv: HsvTripletSchema.optional(),
|
|
61085
61499
|
/** Populated when `mode === 'mired'`. */
|
|
61086
|
-
mireds: number().int().optional(),
|
|
61500
|
+
mireds: number().int().optional().meta(readingMeta("colour-temperature")),
|
|
61087
61501
|
/** Ms epoch of the last operator-driven change. */
|
|
61088
61502
|
lastChangedAt: number()
|
|
61089
61503
|
});
|
|
@@ -61292,18 +61706,12 @@ var FORM_OF_KIND = {
|
|
|
61292
61706
|
function consumableFormOf(item) {
|
|
61293
61707
|
return item.form ?? FORM_OF_KIND[consumableKindOf(item)];
|
|
61294
61708
|
}
|
|
61295
|
-
/**
|
|
61296
|
-
|
|
61297
|
-
|
|
61298
|
-
"days",
|
|
61299
|
-
"hours",
|
|
61300
|
-
"cycles"
|
|
61301
|
-
]);
|
|
61302
|
-
/** Remaining life as a COUNT, not a percentage (the PetKit desiccant reports
|
|
61303
|
-
* days). `value` null = unknown (D393). */
|
|
61709
|
+
/** Whether `remaining.value` is a duration in seconds or a dimensionless count. */
|
|
61710
|
+
var ConsumableRemainingKindSchema = _enum(["duration", "count"]);
|
|
61711
|
+
/** Remaining life. `value` null = unknown (D393). Duration is seconds. */
|
|
61304
61712
|
var ConsumableRemainingSchema = object({
|
|
61305
|
-
value: number().min(0).nullable(),
|
|
61306
|
-
|
|
61713
|
+
value: number().min(0).nullable().meta(readingMeta("device")),
|
|
61714
|
+
kind: ConsumableRemainingKindSchema
|
|
61307
61715
|
});
|
|
61308
61716
|
/** A single consumable item. Either a continuous `level` (remaining
|
|
61309
61717
|
* life %, or fill % for a `supply` / `waste` item) or a discrete `status`
|
|
@@ -61316,7 +61724,7 @@ var ConsumableItemSchema = object({
|
|
|
61316
61724
|
/** Display name. */
|
|
61317
61725
|
label: string().min(1),
|
|
61318
61726
|
/** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
|
|
61319
|
-
level: number().min(0).max(100).nullable(),
|
|
61727
|
+
level: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61320
61728
|
/** The provider's discrete verdict when known (binary mode). */
|
|
61321
61729
|
status: ConsumableStatusSchema.nullable(),
|
|
61322
61730
|
/** What the item is — decides whether low or full is bad. Absent = `wear`. */
|
|
@@ -61398,8 +61806,8 @@ var consumablesCustomize = {
|
|
|
61398
61806
|
transforms: [{ kind: "identity" }]
|
|
61399
61807
|
}],
|
|
61400
61808
|
literals: [{
|
|
61401
|
-
path: "remaining.
|
|
61402
|
-
values: [...
|
|
61809
|
+
path: "remaining.kind",
|
|
61810
|
+
values: [...ConsumableRemainingKindSchema.options]
|
|
61403
61811
|
}]
|
|
61404
61812
|
},
|
|
61405
61813
|
{
|
|
@@ -61528,7 +61936,6 @@ reset: method(object({
|
|
|
61528
61936
|
},
|
|
61529
61937
|
"remaining.value": {
|
|
61530
61938
|
kind: "gauge",
|
|
61531
|
-
unitFrom: "remaining.unit",
|
|
61532
61939
|
deadband: 1,
|
|
61533
61940
|
displayName: "Remaining"
|
|
61534
61941
|
}
|
|
@@ -61598,10 +62005,9 @@ var contactCapability = {
|
|
|
61598
62005
|
* (empty array for the other kinds). It lives in the slice because
|
|
61599
62006
|
* HA `select.*` entities may update their options at runtime.
|
|
61600
62007
|
*
|
|
61601
|
-
*
|
|
61602
|
-
*
|
|
61603
|
-
*
|
|
61604
|
-
* push — consistent with `options` and the sensor-unit approach.
|
|
62008
|
+
* Numeric `min` / `max` / `step` live in the slice and share the device
|
|
62009
|
+
* quantity (`SourceInfo.quantity`, D944). Display precision is a read-time
|
|
62010
|
+
* preference. A datetime control's shape is `SourceInfo.dateTimeShape`.
|
|
61605
62011
|
*/
|
|
61606
62012
|
var ControlStatusSchema = object({
|
|
61607
62013
|
kind: _enum([
|
|
@@ -61613,39 +62019,17 @@ var ControlStatusSchema = object({
|
|
|
61613
62019
|
/** Current value. Numeric kind → number; select/text/datetime → string.
|
|
61614
62020
|
* Datetime values are ISO 8601 strings (full timestamp, date-only,
|
|
61615
62021
|
* or time-only — HA accepts all three forms). */
|
|
61616
|
-
value: union([number(), string()]),
|
|
62022
|
+
value: union([number().meta(readingMeta("device")), string()]),
|
|
61617
62023
|
/** Acceptable values when `kind === 'select'`. Empty for other kinds. */
|
|
61618
62024
|
options: array(string()),
|
|
61619
62025
|
/** Ms epoch when the slice was last updated. */
|
|
61620
62026
|
lastChangedAt: number(),
|
|
61621
|
-
/**
|
|
61622
|
-
|
|
61623
|
-
|
|
61624
|
-
|
|
61625
|
-
/**
|
|
61626
|
-
|
|
61627
|
-
min: number().optional(),
|
|
61628
|
-
/** Maximum allowed value. Populated live from HA `attributes.max`.
|
|
61629
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
61630
|
-
max: number().optional(),
|
|
61631
|
-
/** Step increment. Populated live from HA `attributes.step`.
|
|
61632
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
61633
|
-
step: number().optional(),
|
|
61634
|
-
/** Suggested decimal places for numeric display. Populated live from HA
|
|
61635
|
-
* `attributes.suggested_display_precision`, or derived from `step` when the
|
|
61636
|
-
* HA attribute is absent. Meaningful for `kind === 'numeric'`; absent for
|
|
61637
|
-
* other kinds. Falls back to auto-formatting when absent. */
|
|
61638
|
-
precision: number().int().min(0).max(10).optional(),
|
|
61639
|
-
/** Date-picker granularity for `kind === 'datetime'`. 'date' → date-only,
|
|
61640
|
-
* 'time' → time-only, 'datetime' → full timestamp. Absent for other kinds
|
|
61641
|
-
* (UI defaults to 'datetime'). Derived live from the device's HA domain
|
|
61642
|
-
* (date.* / time.* / datetime.*) or, for input_datetime, from the entity's
|
|
61643
|
-
* `has_date`/`has_time` attributes on each push. */
|
|
61644
|
-
format: _enum([
|
|
61645
|
-
"date",
|
|
61646
|
-
"time",
|
|
61647
|
-
"datetime"
|
|
61648
|
-
]).optional()
|
|
62027
|
+
/** Minimum allowed value, in the device quantity's base unit. */
|
|
62028
|
+
min: number().optional().meta(readingMeta("device")),
|
|
62029
|
+
/** Maximum allowed value, in the device quantity's base unit. */
|
|
62030
|
+
max: number().optional().meta(readingMeta("device")),
|
|
62031
|
+
/** Step increment, in the device quantity's base unit. */
|
|
62032
|
+
step: number().optional().meta(readingMeta("device"))
|
|
61649
62033
|
});
|
|
61650
62034
|
var ControlSetValueInputSchema = discriminatedUnion("kind", [
|
|
61651
62035
|
object({
|
|
@@ -61733,9 +62117,9 @@ var CoverStatusSchema = object({
|
|
|
61733
62117
|
state: CoverStateSchema,
|
|
61734
62118
|
/** 0 = fully closed, 100 = fully open. Null when the device has
|
|
61735
62119
|
* no intermediate position surface. */
|
|
61736
|
-
position: number().min(0).max(100).nullable(),
|
|
62120
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61737
62121
|
/** 0 = closed slats, 100 = open slats. Null when no tilt support. */
|
|
61738
|
-
tiltPosition: number().min(0).max(100).nullable(),
|
|
62122
|
+
tiltPosition: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61739
62123
|
/** Ms epoch when the slice was last updated. */
|
|
61740
62124
|
lastChangedAt: number()
|
|
61741
62125
|
});
|
|
@@ -61838,9 +62222,9 @@ var NormalizedRangeSchema$1 = object({
|
|
|
61838
62222
|
var DayNightStatusSchema = object({
|
|
61839
62223
|
mode: DayNightModeSchema,
|
|
61840
62224
|
/** IR-cut trigger sensitivity, NORMALIZED 0–100 (higher = switches to night sooner). */
|
|
61841
|
-
sensitivity: number().optional(),
|
|
62225
|
+
sensitivity: number().optional().meta(readingMeta("none")),
|
|
61842
62226
|
/** Delay before the IR-cut filter flips, in seconds. */
|
|
61843
|
-
switchDelaySec: number().optional(),
|
|
62227
|
+
switchDelaySec: number().optional().meta(readingMeta("duration")),
|
|
61844
62228
|
lastFetchedAt: number()
|
|
61845
62229
|
});
|
|
61846
62230
|
/**
|
|
@@ -62058,11 +62442,11 @@ var DishwasherStatusSchema = object({
|
|
|
62058
62442
|
/** Feature keys of the programs the appliance currently offers — drives the UI selector. */
|
|
62059
62443
|
availablePrograms: array(string()),
|
|
62060
62444
|
/** Seconds remaining on the active cycle, or null when not running / not known. */
|
|
62061
|
-
remainingSeconds: number().int().nonnegative().nullable(),
|
|
62445
|
+
remainingSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
62062
62446
|
/** Seconds the delayed start is set to (time until the cycle starts), or null. */
|
|
62063
|
-
delayedStartSeconds: number().int().nonnegative().nullable(),
|
|
62447
|
+
delayedStartSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
62064
62448
|
/** Cycle completion 0..100, or null when not applicable. */
|
|
62065
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
62449
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
62066
62450
|
/** True when the door is reported open; null when the door state is not known. */
|
|
62067
62451
|
doorOpen: boolean().nullable(),
|
|
62068
62452
|
/** True when the door is latched (locked) during a cycle; null when not reported. */
|
|
@@ -62086,7 +62470,7 @@ var DishwasherStatusSchema = object({
|
|
|
62086
62470
|
/** True while the machine-care (descaling / cleaning-program) reminder is raised; false when clear; null when not reported. */
|
|
62087
62471
|
machineCareDue: boolean().nullable(),
|
|
62088
62472
|
/** Program runs left before the machine-care reminder is due; null when the appliance does not say. */
|
|
62089
|
-
machineCareRemainingRuns: number().int().nonnegative().nullable(),
|
|
62473
|
+
machineCareRemainingRuns: number().int().nonnegative().nullable().meta(readingMeta("count")),
|
|
62090
62474
|
/** Option states: null when the appliance does not expose the option or has not said. */
|
|
62091
62475
|
halfLoad: boolean().nullable(),
|
|
62092
62476
|
hygienePlus: boolean().nullable(),
|
|
@@ -62101,7 +62485,7 @@ var DishwasherStatusSchema = object({
|
|
|
62101
62485
|
/** Feature keys of the events currently raised (salt low, rinse aid low, program finished, …). */
|
|
62102
62486
|
activeEvents: array(string()),
|
|
62103
62487
|
/** Numeric error code when the appliance reports one; null otherwise. */
|
|
62104
|
-
errorCode: number().nullable(),
|
|
62488
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
62105
62489
|
/** Name of the raised alert-level event while the appliance is in error; null otherwise. */
|
|
62106
62490
|
errorLabel: string().nullable(),
|
|
62107
62491
|
/** Ms epoch of the last value received from the appliance; 0 = never. */
|
|
@@ -62332,7 +62716,7 @@ var DoorbellStatusSchema = object({
|
|
|
62332
62716
|
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
62333
62717
|
lastPressedAt: number().nullable(),
|
|
62334
62718
|
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
62335
|
-
pressCountSinceStart: number()
|
|
62719
|
+
pressCountSinceStart: number().meta(readingMeta("count"))
|
|
62336
62720
|
});
|
|
62337
62721
|
var DoorbellPressEventSchema = object({
|
|
62338
62722
|
deviceId: number(),
|
|
@@ -62397,17 +62781,7 @@ onPressed: {
|
|
|
62397
62781
|
history: "none",
|
|
62398
62782
|
customize: doorbellCustomize
|
|
62399
62783
|
};
|
|
62400
|
-
|
|
62401
|
-
* Enum-state sensor — a string value picked from a finite option set.
|
|
62402
|
-
* Drives HA `sensor` entries with `state_class: enum` (HVAC action
|
|
62403
|
-
* states, weather conditions, contact-source channels, mode strings).
|
|
62404
|
-
* The option set is stable across observations; it is persisted in the
|
|
62405
|
-
* device config blob (via the control slice at adoption) and is NOT
|
|
62406
|
-
* stored in `sourceInfo`.
|
|
62407
|
-
*/
|
|
62408
|
-
/** Locale-render shape for an ISO `value` carried by a `DateTimeSensor`-role
|
|
62409
|
-
* enum sensor: `date` (date-only), `time` (time-only), `datetime` (both). */
|
|
62410
|
-
var EnumSensorDateTimeFormatSchema = _enum([
|
|
62784
|
+
_enum([
|
|
62411
62785
|
"date",
|
|
62412
62786
|
"time",
|
|
62413
62787
|
"datetime"
|
|
@@ -62415,12 +62789,11 @@ var EnumSensorDateTimeFormatSchema = _enum([
|
|
|
62415
62789
|
var EnumSensorStatusSchema = object({
|
|
62416
62790
|
value: string(),
|
|
62417
62791
|
/**
|
|
62418
|
-
* Set
|
|
62419
|
-
* as
|
|
62420
|
-
*
|
|
62421
|
-
* a time-only sensor → `'time'`.
|
|
62792
|
+
* Set when `value` is a timestamp rather than an enum state, so history
|
|
62793
|
+
* does not learn ISO strings as states. The display shape (date / time /
|
|
62794
|
+
* datetime) lives on `SourceInfo.dateTimeShape`, written once at adopt.
|
|
62422
62795
|
*/
|
|
62423
|
-
|
|
62796
|
+
timestamp: boolean().optional(),
|
|
62424
62797
|
/** Ms epoch when the slice was last updated. */
|
|
62425
62798
|
lastFetchedAt: number()
|
|
62426
62799
|
});
|
|
@@ -62447,11 +62820,11 @@ var enumSensorCapability = {
|
|
|
62447
62820
|
* History (D850): the value as an `enum` series (an appliance's program or
|
|
62448
62821
|
* operation state, an HVAC action). The option set is per device, so the
|
|
62449
62822
|
* value list is LEARNED as values are first seen (bounded). A sensor with a
|
|
62450
|
-
* `
|
|
62823
|
+
* `timestamp` carries a clock, not a state, and is not recorded.
|
|
62451
62824
|
*/
|
|
62452
62825
|
history: { fields: { value: {
|
|
62453
62826
|
kind: "enum",
|
|
62454
|
-
skipWhenSet: "
|
|
62827
|
+
skipWhenSet: "timestamp"
|
|
62455
62828
|
} } },
|
|
62456
62829
|
/** Clock fields: written, but excluded from the compare that decides
|
|
62457
62830
|
* whether persisting is worth a SQLite commit. */
|
|
@@ -62471,13 +62844,13 @@ var EventFireSchema = object({
|
|
|
62471
62844
|
deviceId: number(),
|
|
62472
62845
|
eventType: string(),
|
|
62473
62846
|
data: record(string(), unknown()).nullable(),
|
|
62474
|
-
timestamp: number(),
|
|
62475
|
-
seq: number()
|
|
62847
|
+
timestamp: number().meta(readingMeta("none")),
|
|
62848
|
+
seq: number().meta(readingMeta("count"))
|
|
62476
62849
|
});
|
|
62477
62850
|
var EventEmitterStatusSchema = object({
|
|
62478
62851
|
eventTypes: array(string()),
|
|
62479
62852
|
lastEvent: EventFireSchema.nullable(),
|
|
62480
|
-
eventCountSinceStart: number()
|
|
62853
|
+
eventCountSinceStart: number().meta(readingMeta("count"))
|
|
62481
62854
|
});
|
|
62482
62855
|
var eventEmitterCapability = {
|
|
62483
62856
|
name: "event-emitter",
|
|
@@ -62930,10 +63303,10 @@ var FanDirectionSchema = _enum(["forward", "reverse"]);
|
|
|
62930
63303
|
var FanControlStatusSchema = object({
|
|
62931
63304
|
/** Active speed as 0..100 inclusive. Null when the device has no
|
|
62932
63305
|
* speed surface (single-speed fan). */
|
|
62933
|
-
percentage: number().min(0).max(100).nullable(),
|
|
63306
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
62934
63307
|
/** Speed granularity the device accepts (HA `percentage_step`, e.g. 25 for
|
|
62935
63308
|
* a 4-speed fan). Absent when unknown — the UI then falls back to step 1. */
|
|
62936
|
-
percentageStep: number().positive().optional(),
|
|
63309
|
+
percentageStep: number().positive().optional().meta(readingMeta("percentage")),
|
|
62937
63310
|
/** Active preset mode (`auto` / `quiet` / `turbo` / vendor-specific)
|
|
62938
63311
|
* — empty string when no preset is active or supported. */
|
|
62939
63312
|
preset: string(),
|
|
@@ -63054,7 +63427,7 @@ var FeatureProbeStatusSchema = object({
|
|
|
63054
63427
|
/** Camera/firmware model string. `null` when the firmware doesn't expose it. */
|
|
63055
63428
|
model: string().nullable(),
|
|
63056
63429
|
/** Channel count for NVR/Hub devices; `1` for standalone cameras; `null` pre-probe. */
|
|
63057
|
-
channelCount: number().nullable(),
|
|
63430
|
+
channelCount: number().nullable().meta(readingMeta("count")),
|
|
63058
63431
|
/**
|
|
63059
63432
|
* Ms epoch of the last SUCCESSFUL probe. `0` before the first probe
|
|
63060
63433
|
* completes — drivers' `getAccessoryChildren()` should treat zero as
|
|
@@ -63177,9 +63550,91 @@ var gasCapability = {
|
|
|
63177
63550
|
* whether persisting is worth a SQLite commit. */
|
|
63178
63551
|
volatileStateFields: ["lastChangedAt"]
|
|
63179
63552
|
};
|
|
63553
|
+
var GroupCommandsSchema = object({
|
|
63554
|
+
/** One row per member that has been commanded. A later command replaces that member's row. */
|
|
63555
|
+
results: array(object({
|
|
63556
|
+
deviceId: number().int().nonnegative(),
|
|
63557
|
+
cap: string().min(1),
|
|
63558
|
+
method: string().min(1),
|
|
63559
|
+
ok: boolean(),
|
|
63560
|
+
error: string().optional(),
|
|
63561
|
+
/** Ms epoch of the attempt. */
|
|
63562
|
+
at: number()
|
|
63563
|
+
})) });
|
|
63564
|
+
var groupCommandsCapability = {
|
|
63565
|
+
name: "group-commands",
|
|
63566
|
+
scope: "device",
|
|
63567
|
+
deviceNative: true,
|
|
63568
|
+
mode: "singleton",
|
|
63569
|
+
deviceTypes: [DeviceType.Switch, DeviceType.Light],
|
|
63570
|
+
methods: {},
|
|
63571
|
+
status: {
|
|
63572
|
+
schema: GroupCommandsSchema,
|
|
63573
|
+
kind: "push"
|
|
63574
|
+
},
|
|
63575
|
+
runtimeState: GroupCommandsSchema,
|
|
63576
|
+
/**
|
|
63577
|
+
* Runtime-state durability: **session** — the last attempt. A restored
|
|
63578
|
+
* failure would outlive the command that caused it.
|
|
63579
|
+
*
|
|
63580
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
63581
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
63582
|
+
*/
|
|
63583
|
+
durability: "session",
|
|
63584
|
+
history: "none"
|
|
63585
|
+
};
|
|
63586
|
+
/**
|
|
63587
|
+
* How many members of a helper group answered (D944). Counts are integers,
|
|
63588
|
+
* not measurements: zero included is a real count, never a stand-in reading.
|
|
63589
|
+
* The reading itself stays on the output capability. History is none — the
|
|
63590
|
+
* series that later statistics read is the output cap's own history block.
|
|
63591
|
+
*/
|
|
63592
|
+
var GroupStatusSchema = object({
|
|
63593
|
+
/** Members whose current value entered the aggregate. */
|
|
63594
|
+
included: number().int().nonnegative().meta(readingMeta("count", {
|
|
63595
|
+
precision: 0,
|
|
63596
|
+
label: "Reporting"
|
|
63597
|
+
})),
|
|
63598
|
+
/** Members left out: offline, unknown, or not a finite reading (D393). */
|
|
63599
|
+
excluded: number().int().nonnegative().meta(readingMeta("count", {
|
|
63600
|
+
precision: 0,
|
|
63601
|
+
label: "Excluded"
|
|
63602
|
+
})),
|
|
63603
|
+
/** `included` + `excluded`. */
|
|
63604
|
+
total: number().int().nonnegative().meta(readingMeta("count", {
|
|
63605
|
+
precision: 0,
|
|
63606
|
+
label: "Members"
|
|
63607
|
+
}))
|
|
63608
|
+
});
|
|
63609
|
+
var groupStatusCapability = {
|
|
63610
|
+
name: "group-status",
|
|
63611
|
+
scope: "device",
|
|
63612
|
+
deviceNative: true,
|
|
63613
|
+
mode: "singleton",
|
|
63614
|
+
deviceTypes: [
|
|
63615
|
+
DeviceType.Sensor,
|
|
63616
|
+
DeviceType.Switch,
|
|
63617
|
+
DeviceType.Light
|
|
63618
|
+
],
|
|
63619
|
+
methods: {},
|
|
63620
|
+
status: {
|
|
63621
|
+
schema: GroupStatusSchema,
|
|
63622
|
+
kind: "push"
|
|
63623
|
+
},
|
|
63624
|
+
runtimeState: GroupStatusSchema,
|
|
63625
|
+
/**
|
|
63626
|
+
* Runtime-state durability: **session** — recomputed from members on the
|
|
63627
|
+
* next source event; a restored count would outlive the readings it named.
|
|
63628
|
+
*
|
|
63629
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
63630
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
63631
|
+
*/
|
|
63632
|
+
durability: "session",
|
|
63633
|
+
history: "none"
|
|
63634
|
+
};
|
|
63180
63635
|
var HeatingValveStatusSchema = object({
|
|
63181
63636
|
/** Radiator valve opening 0 (closed) .. 100 (open). Null = not yet known. */
|
|
63182
|
-
position: number().min(0).max(100).nullable(),
|
|
63637
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
63183
63638
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
63184
63639
|
lastFetchedAt: number()
|
|
63185
63640
|
});
|
|
@@ -63222,9 +63677,9 @@ var HumidifierStatusSchema = object({
|
|
|
63222
63677
|
/** Whether the humidifier is currently on. */
|
|
63223
63678
|
on: boolean(),
|
|
63224
63679
|
/** Current measured relative humidity (0..100). Null when not reported. */
|
|
63225
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
63680
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
63226
63681
|
/** Target relative humidity (0..100). Null when no setpoint surface. */
|
|
63227
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
63682
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
63228
63683
|
/** Active mode (`auto` / `normal` / `baby` / vendor). Null when the
|
|
63229
63684
|
* device has no mode surface. */
|
|
63230
63685
|
mode: string().nullable(),
|
|
@@ -63234,9 +63689,9 @@ var HumidifierStatusSchema = object({
|
|
|
63234
63689
|
* `idle` / `off`). Null when the device doesn't report it. */
|
|
63235
63690
|
action: string().nullable(),
|
|
63236
63691
|
/** HA `min_humidity` attribute. Null → UI uses 0. */
|
|
63237
|
-
minHumidity: number().nullable(),
|
|
63692
|
+
minHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
63238
63693
|
/** HA `max_humidity` attribute. Null → UI uses 100. */
|
|
63239
|
-
maxHumidity: number().nullable(),
|
|
63694
|
+
maxHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
63240
63695
|
/** Ms epoch when the slice was last updated. */
|
|
63241
63696
|
lastChangedAt: number()
|
|
63242
63697
|
});
|
|
@@ -63306,22 +63761,13 @@ var humidifierCapability = {
|
|
|
63306
63761
|
* `sourceInfo`.
|
|
63307
63762
|
*/
|
|
63308
63763
|
var HumiditySensorStatusSchema = object({
|
|
63309
|
-
/** Current relative humidity, 0..100. */
|
|
63310
|
-
percent: number().min(0).max(100).meta({
|
|
63311
|
-
|
|
63764
|
+
/** Current relative humidity, 0..100. `null` when the sample was refused (D393). */
|
|
63765
|
+
percent: number().min(0).max(100).nullable().meta(readingMeta("humidity", {
|
|
63766
|
+
precision: 0,
|
|
63312
63767
|
label: "Humidity"
|
|
63313
|
-
}),
|
|
63768
|
+
})),
|
|
63314
63769
|
/** Ms epoch when the slice was last updated. */
|
|
63315
|
-
lastFetchedAt: number()
|
|
63316
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
63317
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
63318
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
63319
|
-
unit: string().optional(),
|
|
63320
|
-
/** Suggested decimal places for numeric display.
|
|
63321
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
63322
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
63323
|
-
* auto-formatting when absent. */
|
|
63324
|
-
precision: number().int().min(0).max(10).optional()
|
|
63770
|
+
lastFetchedAt: number()
|
|
63325
63771
|
});
|
|
63326
63772
|
var humiditySensorCapability = {
|
|
63327
63773
|
name: "humidity-sensor",
|
|
@@ -63352,12 +63798,7 @@ var humiditySensorCapability = {
|
|
|
63352
63798
|
} } },
|
|
63353
63799
|
/** Clock fields: written, but excluded from the compare that decides
|
|
63354
63800
|
* whether persisting is worth a SQLite commit. */
|
|
63355
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
63356
|
-
customize: {
|
|
63357
|
-
version: 1,
|
|
63358
|
-
advanced: "derive",
|
|
63359
|
-
targets: []
|
|
63360
|
-
}
|
|
63801
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
63361
63802
|
};
|
|
63362
63803
|
/**
|
|
63363
63804
|
* Image display cap. Models a single still image exposed by an integration —
|
|
@@ -63378,7 +63819,7 @@ var ImageStatusSchema = object({
|
|
|
63378
63819
|
* entity exposes no `entity_picture` (yet). */
|
|
63379
63820
|
url: string().nullable(),
|
|
63380
63821
|
/** Ms epoch of the upstream last-updated timestamp. Null at cold-start. */
|
|
63381
|
-
lastUpdated: number().nullable()
|
|
63822
|
+
lastUpdated: number().nullable().meta(readingMeta("none"))
|
|
63382
63823
|
});
|
|
63383
63824
|
var imageCapability = {
|
|
63384
63825
|
name: "image",
|
|
@@ -63466,19 +63907,19 @@ var NormalizedRangeSchema = object({
|
|
|
63466
63907
|
*/
|
|
63467
63908
|
var ImageSettingsStatusSchema = object({
|
|
63468
63909
|
/** Normalized 0–100. */
|
|
63469
|
-
brightness: number().optional(),
|
|
63910
|
+
brightness: number().optional().meta(readingMeta("none")),
|
|
63470
63911
|
/** Normalized 0–100. */
|
|
63471
|
-
contrast: number().optional(),
|
|
63912
|
+
contrast: number().optional().meta(readingMeta("none")),
|
|
63472
63913
|
/** Normalized 0–100. */
|
|
63473
|
-
saturation: number().optional(),
|
|
63914
|
+
saturation: number().optional().meta(readingMeta("none")),
|
|
63474
63915
|
/** Normalized 0–100. */
|
|
63475
|
-
sharpness: number().optional(),
|
|
63916
|
+
sharpness: number().optional().meta(readingMeta("none")),
|
|
63476
63917
|
mirror: boolean().optional(),
|
|
63477
63918
|
flip: boolean().optional(),
|
|
63478
63919
|
rotate: ImageRotateSchema.optional(),
|
|
63479
63920
|
whiteBalance: WhiteBalanceModeSchema.optional(),
|
|
63480
63921
|
/** Manual white-balance warmth, NORMALIZED 0–100. Meaningful only when `whiteBalance === 'manual'`. */
|
|
63481
|
-
warmth: number().optional(),
|
|
63922
|
+
warmth: number().optional().meta(readingMeta("none")),
|
|
63482
63923
|
exposureMode: ExposureModeSchema.optional(),
|
|
63483
63924
|
backlightMode: BacklightModeSchema.optional(),
|
|
63484
63925
|
lastFetchedAt: number()
|
|
@@ -63757,10 +64198,10 @@ var IntercomAbilitySchema = object({
|
|
|
63757
64198
|
/** Codecs accepted by firmware, in preference order. Driver-authored strings. */
|
|
63758
64199
|
codecs: array(string()),
|
|
63759
64200
|
/** Sample rate (Hz) the firmware expects. Reolink typical: 16000. */
|
|
63760
|
-
sampleRate: number(),
|
|
64201
|
+
sampleRate: number().meta(readingMeta("none")),
|
|
63761
64202
|
duplex: _enum(["half", "full"]),
|
|
63762
64203
|
/** Max in-flight audio backlog before drop (ms). Server uses this to bound latency. */
|
|
63763
|
-
maxBacklogMs: number()
|
|
64204
|
+
maxBacklogMs: number().meta(readingMeta("duration-ms"))
|
|
63764
64205
|
});
|
|
63765
64206
|
var IntercomStatusSchema = object({
|
|
63766
64207
|
/** True while a talk session is open. */
|
|
@@ -63987,13 +64428,13 @@ var LawnMowerControlStatusSchema = object({
|
|
|
63987
64428
|
activity: LawnMowerActivitySchema,
|
|
63988
64429
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
63989
64430
|
* reading. */
|
|
63990
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
64431
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
63991
64432
|
/** 0..100 mowing-completion percentage of the current task, or null when no
|
|
63992
64433
|
* task is active / progress is unavailable. */
|
|
63993
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
64434
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
63994
64435
|
/** Current device/event code (dynamic — mostly status, sometimes an error),
|
|
63995
64436
|
* or null when unknown. */
|
|
63996
|
-
currentCode: number().nullable(),
|
|
64437
|
+
currentCode: number().nullable().meta(readingMeta("none")),
|
|
63997
64438
|
/** Human label for {@link currentCode}, or null when undecodable. */
|
|
63998
64439
|
currentCodeLabel: string().nullable(),
|
|
63999
64440
|
/** Severity of {@link currentCode}. `error` (and often `warning`) warrants UI
|
|
@@ -64547,7 +64988,7 @@ var MediaPlayerStatusSchema = object({
|
|
|
64547
64988
|
state: MediaPlayerStateSchema,
|
|
64548
64989
|
/** Volume as 0..100 inclusive. Null when the device has no volume
|
|
64549
64990
|
* surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
|
|
64550
|
-
volumeLevel: number().min(0).max(100).nullable(),
|
|
64991
|
+
volumeLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
64551
64992
|
/** Mute toggle distinct from volume=0. Null when no mute surface.
|
|
64552
64993
|
* Pair with `DeviceFeature.MediaPlayerMute`. */
|
|
64553
64994
|
isMuted: boolean().nullable(),
|
|
@@ -64560,10 +65001,10 @@ var MediaPlayerStatusSchema = object({
|
|
|
64560
65001
|
currentMedia: MediaInfoSchema.nullable(),
|
|
64561
65002
|
/** Current playback position in ms. Null when not seekable or
|
|
64562
65003
|
* nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
|
|
64563
|
-
positionMs: number().int().nonnegative().nullable(),
|
|
65004
|
+
positionMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
64564
65005
|
/** Total duration of the current media in ms. Null when unknown
|
|
64565
65006
|
* (live stream) or nothing is playing. */
|
|
64566
|
-
durationMs: number().int().nonnegative().nullable(),
|
|
65007
|
+
durationMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
64567
65008
|
/** Shuffle toggle. Null when no shuffle surface.
|
|
64568
65009
|
* Pair with `DeviceFeature.MediaPlayerShuffle`. */
|
|
64569
65010
|
shuffle: boolean().nullable(),
|
|
@@ -64872,7 +65313,7 @@ var motionCustomize = {
|
|
|
64872
65313
|
eventName: "onMotionChanged"
|
|
64873
65314
|
},
|
|
64874
65315
|
deviceTypes: [DeviceType.Camera],
|
|
64875
|
-
apply: "
|
|
65316
|
+
apply: "add",
|
|
64876
65317
|
applyAuthority: {
|
|
64877
65318
|
kind: "camera-sensors",
|
|
64878
65319
|
timeoutField: "motionCooldownMs"
|
|
@@ -64969,7 +65410,7 @@ var MotionStatusSchema = object({
|
|
|
64969
65410
|
* it, every provider seeded it at boot, and every session left it
|
|
64970
65411
|
* `detected: true` after its detach.
|
|
64971
65412
|
*/
|
|
64972
|
-
autoClearAfterMs: number().nullable()
|
|
65413
|
+
autoClearAfterMs: number().nullable().meta(readingMeta("duration-ms"))
|
|
64973
65414
|
});
|
|
64974
65415
|
/**
|
|
64975
65416
|
* Payload of `motion.onMotionChanged` event + the corresponding bus
|
|
@@ -65006,12 +65447,18 @@ var motionCapability = {
|
|
|
65006
65447
|
methods: {
|
|
65007
65448
|
/**
|
|
65008
65449
|
* Pull the current motion state synchronously. Convenience shortcut
|
|
65009
|
-
* for consumers that don't need the full status object
|
|
65010
|
-
*
|
|
65011
|
-
* `getStatus` once the auto-injected status surface lands in every
|
|
65012
|
-
* consumer.
|
|
65450
|
+
* for consumers that don't need the full status object. A composed
|
|
65451
|
+
* group answers from its slice (D944): unknown throws, it is not off.
|
|
65013
65452
|
*/
|
|
65014
65453
|
isDetected: method(object({ deviceId: number() }), boolean()) },
|
|
65454
|
+
/**
|
|
65455
|
+
* A composed motion group serves `isDetected` from `detected` (D944).
|
|
65456
|
+
* Without this the cap stays uncomposable (`has-commands`).
|
|
65457
|
+
*/
|
|
65458
|
+
composedMethods: { isDetected: {
|
|
65459
|
+
kind: "slice",
|
|
65460
|
+
field: "detected"
|
|
65461
|
+
} },
|
|
65015
65462
|
events: {
|
|
65016
65463
|
/**
|
|
65017
65464
|
* Fires every time the runner transitions a camera between
|
|
@@ -65151,7 +65598,7 @@ var MotionZoneRegionSchema = object({
|
|
|
65151
65598
|
* the grid region(s). */
|
|
65152
65599
|
var MotionZoneStatusSchema = object({
|
|
65153
65600
|
enabled: boolean(),
|
|
65154
|
-
sensitivity: number(),
|
|
65601
|
+
sensitivity: number().meta(readingMeta("none")),
|
|
65155
65602
|
/** Grid region(s). Today exactly one `grid` shape. */
|
|
65156
65603
|
regions: array(MotionZoneRegionSchema),
|
|
65157
65604
|
lastFetchedAt: number()
|
|
@@ -65521,7 +65968,7 @@ var NavigationStatusSchema = object({
|
|
|
65521
65968
|
following: boolean(),
|
|
65522
65969
|
flash: boolean(),
|
|
65523
65970
|
lightMode: NavigationLightModeSchema,
|
|
65524
|
-
lightLevel: number().min(40).max(100),
|
|
65971
|
+
lightLevel: number().min(40).max(100).meta(readingMeta("none")),
|
|
65525
65972
|
/** Ms epoch when the slice was last updated. */
|
|
65526
65973
|
lastChangedAt: number()
|
|
65527
65974
|
});
|
|
@@ -65655,13 +66102,13 @@ var NetworkLinkStatusSchema = object({
|
|
|
65655
66102
|
* one whose reading has not landed must not be drawn at 0 %. Consumers
|
|
65656
66103
|
* SKIP a null rather than coerce it.
|
|
65657
66104
|
*/
|
|
65658
|
-
signalPercent: number().min(0).max(100).nullable(),
|
|
66105
|
+
signalPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
65659
66106
|
/** Raw received signal strength in dBm, when the firmware reports one. */
|
|
65660
|
-
rssiDbm: number().optional(),
|
|
66107
|
+
rssiDbm: number().optional().meta(readingMeta("signal-level")),
|
|
65661
66108
|
/** Network name of a wireless link, when the firmware reports it. */
|
|
65662
66109
|
ssid: string().optional(),
|
|
65663
66110
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
65664
|
-
lastUpdated: number()
|
|
66111
|
+
lastUpdated: number().meta(readingMeta("none"))
|
|
65665
66112
|
});
|
|
65666
66113
|
var networkLinkCapability = {
|
|
65667
66114
|
name: "network-link",
|
|
@@ -66046,7 +66493,7 @@ var NotifierStatusSchema = object({
|
|
|
66046
66493
|
lastError: string().nullable(),
|
|
66047
66494
|
/** Number of deliveries currently buffered server-side (rate-limited
|
|
66048
66495
|
* notifiers may queue). 0 when the provider sends synchronously. */
|
|
66049
|
-
queueDepth: number().int().nonnegative(),
|
|
66496
|
+
queueDepth: number().int().nonnegative().meta(readingMeta("count")),
|
|
66050
66497
|
/** Per-feature capability matrix — authoritative source for the
|
|
66051
66498
|
* compose-form field gating. */
|
|
66052
66499
|
supports: NotifierSupportsSchema
|
|
@@ -66138,11 +66585,9 @@ onSent: { data: object({
|
|
|
66138
66585
|
* cap fits (HA `sensor` whose `device_class` we don't have a typed cap
|
|
66139
66586
|
* for: water flow, distance, weight, frequency, signal strength, …).
|
|
66140
66587
|
*
|
|
66141
|
-
* The
|
|
66142
|
-
*
|
|
66143
|
-
*
|
|
66144
|
-
* The UI reads them directly from the slice — they are the single source
|
|
66145
|
-
* of truth for generic numeric rendering and do NOT live on `sourceInfo`.
|
|
66588
|
+
* The quantity is not on this slice. It is chosen when the device is
|
|
66589
|
+
* adopted and stored once on `SourceInfo.quantity` (D944). `value` is in
|
|
66590
|
+
* that quantity's base unit. `null` is a refused sample (D393).
|
|
66146
66591
|
*
|
|
66147
66592
|
* Prefer the typed alternatives (`temperature-sensor`, `humidity-sensor`,
|
|
66148
66593
|
* `ambient-light-sensor`, `pressure-sensor`, `power-meter`,
|
|
@@ -66151,15 +66596,8 @@ onSent: { data: object({
|
|
|
66151
66596
|
* numeric values land here.
|
|
66152
66597
|
*/
|
|
66153
66598
|
var NumericSensorStatusSchema = object({
|
|
66154
|
-
|
|
66155
|
-
|
|
66156
|
-
* Populated live from the upstream source on each state push.
|
|
66157
|
-
* Absent for unitless sensors. */
|
|
66158
|
-
unit: string().optional(),
|
|
66159
|
-
/** Suggested decimal places for numeric display.
|
|
66160
|
-
* Populated live from the upstream source when provided.
|
|
66161
|
-
* Falls back to auto-formatting when absent. */
|
|
66162
|
-
precision: number().int().min(0).max(10).optional(),
|
|
66599
|
+
/** Reading in the device quantity's base unit. `null` when refused (D393). */
|
|
66600
|
+
value: number().nullable().meta(readingMeta("device")),
|
|
66163
66601
|
/** Ms epoch when the slice was last updated. */
|
|
66164
66602
|
lastFetchedAt: number()
|
|
66165
66603
|
});
|
|
@@ -66183,11 +66621,11 @@ var numericSensorCapability = {
|
|
|
66183
66621
|
*/
|
|
66184
66622
|
durability: "restored",
|
|
66185
66623
|
/**
|
|
66186
|
-
* History (D850): recorded series. The unit is
|
|
66624
|
+
* History (D850): recorded series. The unit is the device quantity's base,
|
|
66625
|
+
* resolved when the series is read — the cap has no single unit.
|
|
66187
66626
|
*/
|
|
66188
66627
|
history: { fields: { value: {
|
|
66189
66628
|
kind: "gauge",
|
|
66190
|
-
unitFrom: "unit",
|
|
66191
66629
|
minIntervalMs: 3e4
|
|
66192
66630
|
} } },
|
|
66193
66631
|
/** Clock fields: written, but excluded from the compare that decides
|
|
@@ -66479,23 +66917,26 @@ var PetFeederStatusSchema = object({
|
|
|
66479
66917
|
/** Food currently in the bowl (grams). Null when the device has not
|
|
66480
66918
|
* reported a reading yet. On dual-hopper models this is the combined
|
|
66481
66919
|
* bowl reading; per-hopper levels live in `food1`/`food2`. */
|
|
66482
|
-
foodLevel: number().nullable(),
|
|
66920
|
+
foodLevel: number().nullable().meta(readingMeta("none")),
|
|
66483
66921
|
/** Hopper-1 food level (grams) on dual-hopper feeders; null on
|
|
66484
66922
|
* single-hopper models. */
|
|
66485
|
-
food1: number().nullable(),
|
|
66923
|
+
food1: number().nullable().meta(readingMeta("none")),
|
|
66486
66924
|
/** Hopper-2 food level (grams) on dual-hopper feeders; null on
|
|
66487
66925
|
* single-hopper models. */
|
|
66488
|
-
food2: number().nullable(),
|
|
66926
|
+
food2: number().nullable().meta(readingMeta("none")),
|
|
66489
66927
|
/** Derived low-food flag — mirrors the HA `food_level` binary_sensor
|
|
66490
66928
|
* (`device_class: problem`, on = low). True when the bowl is empty /
|
|
66491
66929
|
* below the feeder's low threshold. */
|
|
66492
66930
|
lowFood: boolean(),
|
|
66493
66931
|
/** Battery charge 0..100 (%). Null on mains-powered models or when the
|
|
66494
66932
|
* device has no battery reading. */
|
|
66495
|
-
batteryPower: number().min(0).max(100).nullable(),
|
|
66496
|
-
/**
|
|
66497
|
-
*
|
|
66498
|
-
|
|
66933
|
+
batteryPower: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
66934
|
+
/**
|
|
66935
|
+
* Desiccant life remaining, stored in seconds (duration base, D944).
|
|
66936
|
+
* Providers convert from the days the feeder reports. Null when the
|
|
66937
|
+
* model has no desiccant sensor.
|
|
66938
|
+
*/
|
|
66939
|
+
desiccantLeftDays: number().nullable().meta(readingMeta("duration")),
|
|
66499
66940
|
/** True while a feed is in progress. */
|
|
66500
66941
|
feeding: boolean(),
|
|
66501
66942
|
/** Decoded connectivity / power status (HA petkit device-status enum).
|
|
@@ -66506,7 +66947,7 @@ var PetFeederStatusSchema = object({
|
|
|
66506
66947
|
* with `errorCode` for consumers that want the raw integer. */
|
|
66507
66948
|
error: string().nullable(),
|
|
66508
66949
|
/** Raw device error code (0 / null = no error). */
|
|
66509
|
-
errorCode: number().nullable(),
|
|
66950
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
66510
66951
|
/** True for D4S/D4SH dual-hopper hardware — gates the per-hopper UI. */
|
|
66511
66952
|
isDualHopper: boolean(),
|
|
66512
66953
|
/** Child-lock (manual-lock) setting — buttons on the unit are disabled. */
|
|
@@ -66516,7 +66957,7 @@ var PetFeederStatusSchema = object({
|
|
|
66516
66957
|
/** Play a chime when dispensing. */
|
|
66517
66958
|
feedSound: boolean(),
|
|
66518
66959
|
/** Speaker / prompt volume level (device-scaled integer). */
|
|
66519
|
-
volume: number(),
|
|
66960
|
+
volume: number().meta(readingMeta("none")),
|
|
66520
66961
|
/** Ms epoch when the slice was last refreshed from the cloud. */
|
|
66521
66962
|
lastFetchedAt: number()
|
|
66522
66963
|
});
|
|
@@ -66635,7 +67076,7 @@ var petFeederCapability = {
|
|
|
66635
67076
|
},
|
|
66636
67077
|
desiccantLeftDays: {
|
|
66637
67078
|
kind: "gauge",
|
|
66638
|
-
unit: "
|
|
67079
|
+
unit: "s"
|
|
66639
67080
|
}
|
|
66640
67081
|
} }
|
|
66641
67082
|
};
|
|
@@ -67071,36 +67512,19 @@ method(_void(), PlatformCapabilitiesSchema), method(_void(), HardwareInfoSchema)
|
|
|
67071
67512
|
*/
|
|
67072
67513
|
var PowerMeterStatusSchema = object({
|
|
67073
67514
|
/** Instantaneous power draw in watts. */
|
|
67074
|
-
watts: number().optional().meta({
|
|
67075
|
-
unit: "W",
|
|
67076
|
-
label: "Power"
|
|
67077
|
-
}),
|
|
67515
|
+
watts: number().optional().meta(readingMeta("power", { label: "Power" })),
|
|
67078
67516
|
/** Cumulative energy in kilowatt-hours since the meter was reset. */
|
|
67079
|
-
kwhTotal: number().optional().meta({
|
|
67080
|
-
unit: "kWh",
|
|
67081
|
-
label: "Energy"
|
|
67082
|
-
}),
|
|
67517
|
+
kwhTotal: number().optional().meta(readingMeta("energy", { label: "Energy" })),
|
|
67083
67518
|
/** Voltage in volts. */
|
|
67084
|
-
volts: number().optional(),
|
|
67519
|
+
volts: number().optional().meta(readingMeta("voltage")),
|
|
67085
67520
|
/** Current in amperes. */
|
|
67086
|
-
amps: number().optional(),
|
|
67087
|
-
/** Apparent power in volt-amperes
|
|
67088
|
-
va: number().optional(),
|
|
67521
|
+
amps: number().optional().meta(readingMeta("current")),
|
|
67522
|
+
/** Apparent power in volt-amperes. */
|
|
67523
|
+
va: number().optional().meta(readingMeta("apparent-power")),
|
|
67089
67524
|
/** Power factor (0..1) if reported. */
|
|
67090
|
-
powerFactor: number().min(0).max(1).optional(),
|
|
67525
|
+
powerFactor: number().min(0).max(1).optional().meta(readingMeta("ratio")),
|
|
67091
67526
|
/** Ms epoch when the slice was last updated. */
|
|
67092
|
-
lastFetchedAt: number()
|
|
67093
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
67094
|
-
* `attributes.unit_of_measurement` → 'V' / 'A' / 'W' / 'kW' / 'kWh').
|
|
67095
|
-
* Each upstream `sensor.*` entity surfaces ONE device_class, so one
|
|
67096
|
-
* unit per slice is unambiguous. The UI prefers this over the role's
|
|
67097
|
-
* canonical unit so a 'kW' / 'Wh' feed renders verbatim. */
|
|
67098
|
-
unit: string().optional(),
|
|
67099
|
-
/** Suggested decimal places for numeric display.
|
|
67100
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
67101
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
67102
|
-
* auto-formatting when absent. */
|
|
67103
|
-
precision: number().int().min(0).max(10).optional()
|
|
67527
|
+
lastFetchedAt: number()
|
|
67104
67528
|
});
|
|
67105
67529
|
var powerMeterCapability = {
|
|
67106
67530
|
name: "power-meter",
|
|
@@ -67164,12 +67588,7 @@ var powerMeterCapability = {
|
|
|
67164
67588
|
} },
|
|
67165
67589
|
/** Clock fields: written, but excluded from the compare that decides
|
|
67166
67590
|
* whether persisting is worth a SQLite commit. */
|
|
67167
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
67168
|
-
customize: {
|
|
67169
|
-
version: 1,
|
|
67170
|
-
advanced: "derive",
|
|
67171
|
-
targets: []
|
|
67172
|
-
}
|
|
67591
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
67173
67592
|
};
|
|
67174
67593
|
/**
|
|
67175
67594
|
* Presence cap. Models HA `person.*` and `device_tracker.*` entities
|
|
@@ -67189,11 +67608,11 @@ var powerMeterCapability = {
|
|
|
67189
67608
|
*/
|
|
67190
67609
|
var GpsLocationSchema = object({
|
|
67191
67610
|
/** Latitude in decimal degrees, -90..90. */
|
|
67192
|
-
latitude: number().min(-90).max(90),
|
|
67611
|
+
latitude: number().min(-90).max(90).meta(readingMeta("angle")),
|
|
67193
67612
|
/** Longitude in decimal degrees, -180..180. */
|
|
67194
|
-
longitude: number().min(-180).max(180),
|
|
67613
|
+
longitude: number().min(-180).max(180).meta(readingMeta("angle")),
|
|
67195
67614
|
/** Reported accuracy in meters (lower = better). */
|
|
67196
|
-
accuracyMeters: number().nonnegative()
|
|
67615
|
+
accuracyMeters: number().nonnegative().meta(readingMeta("length"))
|
|
67197
67616
|
});
|
|
67198
67617
|
var PresenceStatusSchema = object({
|
|
67199
67618
|
/** `home` / `not_home` / any user-defined zone name. */
|
|
@@ -67205,7 +67624,7 @@ var PresenceStatusSchema = object({
|
|
|
67205
67624
|
gps: GpsLocationSchema.nullable(),
|
|
67206
67625
|
/** Optional battery level of the tracking device (0..100). Null
|
|
67207
67626
|
* when not reported. */
|
|
67208
|
-
batteryPercent: number().min(0).max(100).nullable(),
|
|
67627
|
+
batteryPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
67209
67628
|
/** Ms epoch when the slice was last updated. */
|
|
67210
67629
|
lastChangedAt: number()
|
|
67211
67630
|
});
|
|
@@ -67255,19 +67674,10 @@ var presenceCapability = {
|
|
|
67255
67674
|
* `sourceInfo`.
|
|
67256
67675
|
*/
|
|
67257
67676
|
var PressureSensorStatusSchema = object({
|
|
67258
|
-
/** Current pressure in hPa. */
|
|
67259
|
-
hpa: number(),
|
|
67677
|
+
/** Current pressure in hPa. `null` when the sample was refused (D393). */
|
|
67678
|
+
hpa: number().nullable().meta(readingMeta("pressure", { precision: 0 })),
|
|
67260
67679
|
/** Ms epoch when the slice was last updated. */
|
|
67261
|
-
lastFetchedAt: number()
|
|
67262
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
67263
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
67264
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
67265
|
-
unit: string().optional(),
|
|
67266
|
-
/** Suggested decimal places for numeric display.
|
|
67267
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
67268
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
67269
|
-
* auto-formatting when absent. */
|
|
67270
|
-
precision: number().int().min(0).max(10).optional()
|
|
67680
|
+
lastFetchedAt: number()
|
|
67271
67681
|
});
|
|
67272
67682
|
var pressureSensorCapability = {
|
|
67273
67683
|
name: "pressure-sensor",
|
|
@@ -67681,8 +68091,8 @@ DeviceType.Camera, method(PtzMoveCommandSchema.extend({ deviceId: number() }), _
|
|
|
67681
68091
|
}), _void(), { kind: "mutation" });
|
|
67682
68092
|
var PtzAutotrackSettingsSchema = object({
|
|
67683
68093
|
targetType: string().describe("Vendor target string (people/vehicle/pet); empty = camera default"),
|
|
67684
|
-
stopDelaySeconds: number().int().min(0).max(300),
|
|
67685
|
-
disappearDelaySeconds: number().int().min(0).max(300)
|
|
68094
|
+
stopDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration")),
|
|
68095
|
+
disappearDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration"))
|
|
67686
68096
|
});
|
|
67687
68097
|
/**
|
|
67688
68098
|
* One option the camera advertises as a valid `targetType`. Drivers
|
|
@@ -67836,7 +68246,7 @@ var RunningStateStatusSchema = object({
|
|
|
67836
68246
|
/** null = unknown — never coerced to false (D393). */
|
|
67837
68247
|
running: boolean().nullable(),
|
|
67838
68248
|
/** Epoch ms the current boolean began; null while `running` is null. */
|
|
67839
|
-
since: number().nullable(),
|
|
68249
|
+
since: number().nullable().meta(readingMeta("none")),
|
|
67840
68250
|
source: RunningStateSourceSchema.meta({ label: "Source" }),
|
|
67841
68251
|
phase: string().nullable(),
|
|
67842
68252
|
/** null until a reading has been published (D393). */
|
|
@@ -67851,7 +68261,6 @@ var RUNNING_DEVICE_TYPES = Object.values(DeviceType);
|
|
|
67851
68261
|
/** Generic Customize target for the running boolean (D936). */
|
|
67852
68262
|
var runningCustomize = {
|
|
67853
68263
|
version: 1,
|
|
67854
|
-
advanced: "derive",
|
|
67855
68264
|
targets: [{
|
|
67856
68265
|
id: "running",
|
|
67857
68266
|
cardinality: "scalar",
|
|
@@ -67871,7 +68280,7 @@ var runningCustomize = {
|
|
|
67871
68280
|
DeviceType.Thermostat,
|
|
67872
68281
|
DeviceType.PetFeeder
|
|
67873
68282
|
],
|
|
67874
|
-
apply: "add
|
|
68283
|
+
apply: "add",
|
|
67875
68284
|
path: "running",
|
|
67876
68285
|
sources: [
|
|
67877
68286
|
{
|
|
@@ -69167,9 +69576,9 @@ var RecordTriggerSchema = _enum([
|
|
|
69167
69576
|
*/
|
|
69168
69577
|
var RecordWindowSchema = object({
|
|
69169
69578
|
trigger: RecordTriggerSchema,
|
|
69170
|
-
day: number().int().min(0).max(6),
|
|
69171
|
-
startMinute: number().int().min(0).max(1439),
|
|
69172
|
-
endMinute: number().int().min(1).max(1440)
|
|
69579
|
+
day: number().int().min(0).max(6).meta(readingMeta("none")),
|
|
69580
|
+
startMinute: number().int().min(0).max(1439).meta(readingMeta("none")),
|
|
69581
|
+
endMinute: number().int().min(1).max(1440).meta(readingMeta("none"))
|
|
69173
69582
|
});
|
|
69174
69583
|
/** Status of one physical volume, as the camera itself describes it. */
|
|
69175
69584
|
var OnboardStorageVolumeSchema = object({
|
|
@@ -69245,10 +69654,10 @@ var RecordingOnboardStatusSchema = object({
|
|
|
69245
69654
|
/** Master "record to the card at all" switch. */
|
|
69246
69655
|
enabled: boolean().nullable(),
|
|
69247
69656
|
overwriteWhenFull: boolean().nullable(),
|
|
69248
|
-
preRecordSec: number().nullable(),
|
|
69249
|
-
postRecordSec: number().nullable(),
|
|
69657
|
+
preRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
69658
|
+
postRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
69250
69659
|
/** Length of one recorded file, in minutes. */
|
|
69251
|
-
segmentMinutes: number().nullable(),
|
|
69660
|
+
segmentMinutes: number().nullable().meta(readingMeta("none")),
|
|
69252
69661
|
/** The primary track's weekly windows, flattened. */
|
|
69253
69662
|
windows: array(RecordWindowSchema),
|
|
69254
69663
|
/**
|
|
@@ -69264,7 +69673,7 @@ var RecordingOnboardStatusSchema = object({
|
|
|
69264
69673
|
* provider reporting a non-zero count also reports the schedule as not
|
|
69265
69674
|
* writable.
|
|
69266
69675
|
*/
|
|
69267
|
-
unreadableWindows: number(),
|
|
69676
|
+
unreadableWindows: number().meta(readingMeta("count")),
|
|
69268
69677
|
/**
|
|
69269
69678
|
* The camera is scheduled to record and has NO usable storage.
|
|
69270
69679
|
*
|
|
@@ -70127,7 +70536,7 @@ var CamStreamDescriptorSchema = object({
|
|
|
70127
70536
|
url: string().optional(),
|
|
70128
70537
|
codec: string().optional(),
|
|
70129
70538
|
resolution: CamStreamResolutionSchema.optional(),
|
|
70130
|
-
fps: number().positive().optional(),
|
|
70539
|
+
fps: number().positive().optional().meta(readingMeta("rate")),
|
|
70131
70540
|
label: string().optional(),
|
|
70132
70541
|
/** Device-level features (e.g. `battery-operated`) — drives broker policy. */
|
|
70133
70542
|
deviceFeatures: array(string()).optional(),
|
|
@@ -70214,18 +70623,18 @@ var StreamProfileSchema = _enum([
|
|
|
70214
70623
|
]);
|
|
70215
70624
|
/** The current encoding config of one stream profile. */
|
|
70216
70625
|
var StreamProfileConfigSchema = object({
|
|
70217
|
-
width: number(),
|
|
70218
|
-
height: number(),
|
|
70626
|
+
width: number().meta(readingMeta("none")),
|
|
70627
|
+
height: number().meta(readingMeta("none")),
|
|
70219
70628
|
codec: _enum(["h264", "h265"]),
|
|
70220
|
-
framerate: number(),
|
|
70221
|
-
bitrate: number(),
|
|
70629
|
+
framerate: number().meta(readingMeta("rate")),
|
|
70630
|
+
bitrate: number().meta(readingMeta("bitrate")),
|
|
70222
70631
|
bitrateMode: _enum(["vbr", "cbr"]).optional(),
|
|
70223
70632
|
encoderProfile: _enum([
|
|
70224
70633
|
"high",
|
|
70225
70634
|
"main",
|
|
70226
70635
|
"baseline"
|
|
70227
70636
|
]).optional(),
|
|
70228
|
-
gop: number().optional(),
|
|
70637
|
+
gop: number().optional().meta(readingMeta("none")),
|
|
70229
70638
|
/**
|
|
70230
70639
|
* Whether THIS profile currently carries an audio track. READ-ONLY here.
|
|
70231
70640
|
*
|
|
@@ -70446,12 +70855,7 @@ var switchCapability = {
|
|
|
70446
70855
|
label: "On",
|
|
70447
70856
|
kind: "boolean"
|
|
70448
70857
|
}
|
|
70449
|
-
}] }
|
|
70450
|
-
customize: {
|
|
70451
|
-
version: 1,
|
|
70452
|
-
advanced: "derive",
|
|
70453
|
-
targets: []
|
|
70454
|
-
}
|
|
70858
|
+
}] }
|
|
70455
70859
|
};
|
|
70456
70860
|
/** C0 controls, DEL and the C1 range: none of them belongs in a name. */
|
|
70457
70861
|
function hasControlCharacter(value) {
|
|
@@ -71034,35 +71438,21 @@ var tamperCapability = {
|
|
|
71034
71438
|
* entries with `device_class: temperature` and any future native
|
|
71035
71439
|
* thermometer.
|
|
71036
71440
|
*
|
|
71037
|
-
*
|
|
71038
|
-
*
|
|
71039
|
-
* (climate-control's `currentTemp`, energy analytics) can compose
|
|
71040
|
-
* without per-source unit fixups. The canonical display unit (`°C`) is
|
|
71041
|
-
* a descriptor constant in the UI (ROLE_DESCRIPTOR), not stored in
|
|
71042
|
-
* `sourceInfo`.
|
|
71441
|
+
* The number is Celsius (D944). Providers convert on ingest. A failed
|
|
71442
|
+
* conversion is `null`, never a guess. Display unit is a read-time preference.
|
|
71043
71443
|
*
|
|
71044
71444
|
* Status `lastFetchedAt` lets staleness-aware consumers detect a
|
|
71045
71445
|
* frozen feed (provider hung) distinct from a "temperature hasn't
|
|
71046
71446
|
* changed" steady state.
|
|
71047
71447
|
*/
|
|
71048
71448
|
var TemperatureSensorStatusSchema = object({
|
|
71049
|
-
/** Current temperature in Celsius. */
|
|
71050
|
-
celsius: number().meta({
|
|
71051
|
-
|
|
71449
|
+
/** Current temperature in Celsius. `null` when the sample was refused (D393). */
|
|
71450
|
+
celsius: number().nullable().meta(readingMeta("temperature", {
|
|
71451
|
+
precision: 1,
|
|
71052
71452
|
label: "Temperature"
|
|
71053
|
-
}),
|
|
71453
|
+
})),
|
|
71054
71454
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
71055
|
-
lastFetchedAt: number()
|
|
71056
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
71057
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
71058
|
-
* role's canonical unit, so a Fahrenheit feed renders '°F' not '°C'.
|
|
71059
|
-
* Absent → the UI falls back to the role's canonical unit. */
|
|
71060
|
-
unit: string().optional(),
|
|
71061
|
-
/** Suggested decimal places for numeric display.
|
|
71062
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
71063
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
71064
|
-
* auto-formatting when absent. */
|
|
71065
|
-
precision: number().int().min(0).max(10).optional()
|
|
71455
|
+
lastFetchedAt: number()
|
|
71066
71456
|
});
|
|
71067
71457
|
var temperatureSensorCapability = {
|
|
71068
71458
|
name: "temperature-sensor",
|
|
@@ -71093,12 +71483,7 @@ var temperatureSensorCapability = {
|
|
|
71093
71483
|
} } },
|
|
71094
71484
|
/** Clock fields: written, but excluded from the compare that decides
|
|
71095
71485
|
* whether persisting is worth a SQLite commit. */
|
|
71096
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
71097
|
-
customize: {
|
|
71098
|
-
version: 1,
|
|
71099
|
-
advanced: "derive",
|
|
71100
|
-
targets: []
|
|
71101
|
-
}
|
|
71486
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
71102
71487
|
};
|
|
71103
71488
|
/**
|
|
71104
71489
|
* toast — system-scoped singleton capability that streams toast
|
|
@@ -71381,16 +71766,16 @@ var VacuumControlStatusSchema = object({
|
|
|
71381
71766
|
]),
|
|
71382
71767
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
71383
71768
|
* reading. */
|
|
71384
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
71769
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
71385
71770
|
/** Current fan-speed token (provider-verbatim). Null when unknown or
|
|
71386
71771
|
* the vacuum has no speed control. */
|
|
71387
71772
|
fanSpeed: string().nullable(),
|
|
71388
71773
|
/** Speed tokens the hardware accepts — drives the UI selector. */
|
|
71389
71774
|
availableFanSpeeds: array(string()),
|
|
71390
71775
|
/** 0..100 cleaning-completion percentage of the current task, or null. */
|
|
71391
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
71776
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
71392
71777
|
/** Current error code (0 / null = no error). */
|
|
71393
|
-
errorCode: number().nullable(),
|
|
71778
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
71394
71779
|
/** Human label for {@link errorCode}, or null when none / undecodable. */
|
|
71395
71780
|
errorLabel: string().nullable(),
|
|
71396
71781
|
/** Ms epoch when the slice was last updated. */
|
|
@@ -71468,7 +71853,7 @@ var ValveStatusSchema = object({
|
|
|
71468
71853
|
]),
|
|
71469
71854
|
/** 0 = fully closed, 100 = fully open. Null when the device has no
|
|
71470
71855
|
* intermediate position surface. */
|
|
71471
|
-
position: number().min(0).max(100).nullable(),
|
|
71856
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
71472
71857
|
/** Ms epoch when the slice was last updated. */
|
|
71473
71858
|
lastChangedAt: number()
|
|
71474
71859
|
});
|
|
@@ -71576,9 +71961,9 @@ var vibrationCapability = {
|
|
|
71576
71961
|
*/
|
|
71577
71962
|
var WaterHeaterStatusSchema = object({
|
|
71578
71963
|
/** Current measured temperature. Null when not reported. */
|
|
71579
|
-
currentTemp: number().nullable(),
|
|
71964
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
71580
71965
|
/** Target temperature setpoint. Null when no setpoint surface. */
|
|
71581
|
-
targetTemp: number().nullable(),
|
|
71966
|
+
targetTemp: number().nullable().meta(readingMeta("temperature")),
|
|
71582
71967
|
/** Active operation mode = HA `state` (`eco` / `electric` / `gas` /
|
|
71583
71968
|
* `heat_pump` / `high_demand` / `performance` / `off`). Null when the
|
|
71584
71969
|
* device reports an unknown state. */
|
|
@@ -71589,9 +71974,9 @@ var WaterHeaterStatusSchema = object({
|
|
|
71589
71974
|
* has no away surface. */
|
|
71590
71975
|
away: boolean().nullable(),
|
|
71591
71976
|
/** HA `min_temp` attribute. Null when not reported. */
|
|
71592
|
-
minTemp: number().nullable(),
|
|
71977
|
+
minTemp: number().nullable().meta(readingMeta("temperature")),
|
|
71593
71978
|
/** HA `max_temp` attribute. Null when not reported. */
|
|
71594
|
-
maxTemp: number().nullable(),
|
|
71979
|
+
maxTemp: number().nullable().meta(readingMeta("temperature")),
|
|
71595
71980
|
/** Ms epoch when the slice was last updated. */
|
|
71596
71981
|
lastChangedAt: number()
|
|
71597
71982
|
});
|
|
@@ -71676,25 +72061,18 @@ var waterHeaterCapability = {
|
|
|
71676
72061
|
* Forecast deferred — current conditions only for v1.
|
|
71677
72062
|
*/
|
|
71678
72063
|
var WeatherStatusSchema = object({
|
|
71679
|
-
/** Verbatim
|
|
71680
|
-
* when no condition has been reported yet. */
|
|
72064
|
+
/** Verbatim condition state (`sunny`, `cloudy`, `rainy`, …). Null when none yet. */
|
|
71681
72065
|
condition: string().nullable(),
|
|
71682
|
-
/** Current temperature in
|
|
71683
|
-
temperature: number().nullable(),
|
|
71684
|
-
/** Temperature unit string (e.g. `°C` / `°F`). Null when not provided. */
|
|
71685
|
-
temperatureUnit: string().nullable(),
|
|
72066
|
+
/** Current temperature in Celsius. Null when not provided or refused. */
|
|
72067
|
+
temperature: number().nullable().meta(readingMeta("temperature", { precision: 1 })),
|
|
71686
72068
|
/** Relative humidity (0..100). Null when not provided. */
|
|
71687
|
-
humidity: number().min(0).max(100).nullable(),
|
|
71688
|
-
/** Barometric pressure in
|
|
71689
|
-
pressure: number().nullable(),
|
|
71690
|
-
/**
|
|
71691
|
-
|
|
71692
|
-
/** Wind speed in the reported unit. Null when not provided. */
|
|
71693
|
-
windSpeed: number().nullable(),
|
|
71694
|
-
/** Wind-speed unit string (e.g. `km/h` / `mph`). Null when not provided. */
|
|
71695
|
-
windSpeedUnit: string().nullable(),
|
|
72069
|
+
humidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
72070
|
+
/** Barometric pressure in hPa. Null when not provided or refused. */
|
|
72071
|
+
pressure: number().nullable().meta(readingMeta("pressure")),
|
|
72072
|
+
/** Wind speed in metres per second. Null when not provided or refused. */
|
|
72073
|
+
windSpeed: number().nullable().meta(readingMeta("speed")),
|
|
71696
72074
|
/** Wind bearing in degrees (0..360, meteorological). Null when not provided. */
|
|
71697
|
-
windBearing: number().nullable(),
|
|
72075
|
+
windBearing: number().nullable().meta(readingMeta("angle")),
|
|
71698
72076
|
/** Ms epoch when the slice was last updated. */
|
|
71699
72077
|
lastFetchedAt: number()
|
|
71700
72078
|
});
|
|
@@ -71722,12 +72100,12 @@ var weatherCapability = {
|
|
|
71722
72100
|
*/
|
|
71723
72101
|
durability: "session",
|
|
71724
72102
|
/**
|
|
71725
|
-
* History (D850): recorded series.
|
|
72103
|
+
* History (D850): recorded series. Numbers are the quantity base (D944).
|
|
71726
72104
|
*/
|
|
71727
72105
|
history: { fields: {
|
|
71728
72106
|
temperature: {
|
|
71729
72107
|
kind: "gauge",
|
|
71730
|
-
|
|
72108
|
+
unit: "°C",
|
|
71731
72109
|
deadband: .2
|
|
71732
72110
|
},
|
|
71733
72111
|
humidity: {
|
|
@@ -71737,12 +72115,12 @@ var weatherCapability = {
|
|
|
71737
72115
|
},
|
|
71738
72116
|
pressure: {
|
|
71739
72117
|
kind: "gauge",
|
|
71740
|
-
|
|
72118
|
+
unit: "hPa",
|
|
71741
72119
|
deadband: .5
|
|
71742
72120
|
},
|
|
71743
72121
|
windSpeed: {
|
|
71744
72122
|
kind: "gauge",
|
|
71745
|
-
|
|
72123
|
+
unit: "m/s",
|
|
71746
72124
|
deadband: .5
|
|
71747
72125
|
}
|
|
71748
72126
|
} }
|
|
@@ -73026,6 +73404,8 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
73026
73404
|
featureProbe: featureProbeCapability,
|
|
73027
73405
|
flood: floodCapability,
|
|
73028
73406
|
gas: gasCapability,
|
|
73407
|
+
groupCommands: groupCommandsCapability,
|
|
73408
|
+
groupStatus: groupStatusCapability,
|
|
73029
73409
|
heatingValve: heatingValveCapability,
|
|
73030
73410
|
humidifier: humidifierCapability,
|
|
73031
73411
|
humiditySensor: humiditySensorCapability,
|
|
@@ -73919,6 +74299,13 @@ Object.freeze({
|
|
|
73919
74299
|
access: "view",
|
|
73920
74300
|
role: "admin"
|
|
73921
74301
|
},
|
|
74302
|
+
"addons.getPackageDocs": {
|
|
74303
|
+
capName: "addons",
|
|
74304
|
+
capScope: "system",
|
|
74305
|
+
addonId: null,
|
|
74306
|
+
access: "view",
|
|
74307
|
+
role: "admin"
|
|
74308
|
+
},
|
|
73922
74309
|
"addons.getVersions": {
|
|
73923
74310
|
capName: "addons",
|
|
73924
74311
|
capScope: "system",
|
|
@@ -77027,6 +77414,20 @@ Object.freeze({
|
|
|
77027
77414
|
access: "view",
|
|
77028
77415
|
role: "viewer"
|
|
77029
77416
|
},
|
|
77417
|
+
"groupCommands.getStatus": {
|
|
77418
|
+
capName: "group-commands",
|
|
77419
|
+
capScope: "device",
|
|
77420
|
+
addonId: null,
|
|
77421
|
+
access: "view",
|
|
77422
|
+
role: "viewer"
|
|
77423
|
+
},
|
|
77424
|
+
"groupStatus.getStatus": {
|
|
77425
|
+
capName: "group-status",
|
|
77426
|
+
capScope: "device",
|
|
77427
|
+
addonId: null,
|
|
77428
|
+
access: "view",
|
|
77429
|
+
role: "viewer"
|
|
77430
|
+
},
|
|
77030
77431
|
"heatingValve.getStatus": {
|
|
77031
77432
|
capName: "heating-valve",
|
|
77032
77433
|
capScope: "device",
|
|
@@ -86849,6 +87250,37 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
86849
87250
|
icon: "flame"
|
|
86850
87251
|
}]
|
|
86851
87252
|
},
|
|
87253
|
+
"group-commands": {
|
|
87254
|
+
scope: "device",
|
|
87255
|
+
noun: t("Group command", "Comando di gruppo")
|
|
87256
|
+
},
|
|
87257
|
+
"group-status": {
|
|
87258
|
+
scope: "device",
|
|
87259
|
+
noun: t("Group", "Gruppo"),
|
|
87260
|
+
state: [
|
|
87261
|
+
{
|
|
87262
|
+
kind: "numeric",
|
|
87263
|
+
field: "included",
|
|
87264
|
+
quantity: t("the members reporting", "i membri che rispondono"),
|
|
87265
|
+
label: t("Reporting", "Rispondono"),
|
|
87266
|
+
icon: "users"
|
|
87267
|
+
},
|
|
87268
|
+
{
|
|
87269
|
+
kind: "numeric",
|
|
87270
|
+
field: "excluded",
|
|
87271
|
+
quantity: t("the members left out", "i membri esclusi"),
|
|
87272
|
+
label: t("Excluded", "Esclusi"),
|
|
87273
|
+
icon: "users"
|
|
87274
|
+
},
|
|
87275
|
+
{
|
|
87276
|
+
kind: "numeric",
|
|
87277
|
+
field: "total",
|
|
87278
|
+
quantity: t("the member count", "il numero di membri"),
|
|
87279
|
+
label: t("Members", "Membri"),
|
|
87280
|
+
icon: "sigma"
|
|
87281
|
+
}
|
|
87282
|
+
]
|
|
87283
|
+
},
|
|
86852
87284
|
"humidity-sensor": {
|
|
86853
87285
|
scope: "device",
|
|
86854
87286
|
noun: t("Humidity", "Umidità"),
|
|
@@ -86882,7 +87314,6 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
86882
87314
|
field: "value",
|
|
86883
87315
|
quantity: t("the reading", "il valore"),
|
|
86884
87316
|
label: t("Reading", "Valore"),
|
|
86885
|
-
unitField: "unit",
|
|
86886
87317
|
icon: "gauge"
|
|
86887
87318
|
}]
|
|
86888
87319
|
},
|
|
@@ -87018,7 +87449,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
87018
87449
|
field: "temperature",
|
|
87019
87450
|
quantity: t("the outdoor temperature", "la temperatura esterna"),
|
|
87020
87451
|
label: t("Temperature", "Temperatura"),
|
|
87021
|
-
|
|
87452
|
+
unit: "°C",
|
|
87022
87453
|
icon: "thermometer"
|
|
87023
87454
|
},
|
|
87024
87455
|
{
|
|
@@ -87034,7 +87465,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
87034
87465
|
field: "windSpeed",
|
|
87035
87466
|
quantity: t("the wind speed", "la velocità del vento"),
|
|
87036
87467
|
label: t("Wind", "Vento"),
|
|
87037
|
-
|
|
87468
|
+
unit: "m/s",
|
|
87038
87469
|
icon: "wind"
|
|
87039
87470
|
},
|
|
87040
87471
|
{
|
|
@@ -87042,7 +87473,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
87042
87473
|
field: "pressure",
|
|
87043
87474
|
quantity: t("the air pressure", "la pressione atmosferica"),
|
|
87044
87475
|
label: t("Pressure", "Pressione"),
|
|
87045
|
-
|
|
87476
|
+
unit: "hPa",
|
|
87046
87477
|
icon: "gauge"
|
|
87047
87478
|
}
|
|
87048
87479
|
]
|
|
@@ -88315,6 +88746,16 @@ Object.freeze({
|
|
|
88315
88746
|
form: "single",
|
|
88316
88747
|
optional: false
|
|
88317
88748
|
}],
|
|
88749
|
+
"groupCommands.getStatus": [{
|
|
88750
|
+
name: "deviceId",
|
|
88751
|
+
form: "single",
|
|
88752
|
+
optional: false
|
|
88753
|
+
}],
|
|
88754
|
+
"groupStatus.getStatus": [{
|
|
88755
|
+
name: "deviceId",
|
|
88756
|
+
form: "single",
|
|
88757
|
+
optional: false
|
|
88758
|
+
}],
|
|
88318
88759
|
"heatingValve.getStatus": [{
|
|
88319
88760
|
name: "deviceId",
|
|
88320
88761
|
form: "single",
|
|
@@ -90460,8 +90901,8 @@ var NC_SYSTEM_EVENT_FILTER_KEYS = [
|
|
|
90460
90901
|
function systemEventFilterApplies(kind, filter) {
|
|
90461
90902
|
if (LEGACY_KINDS_WITHOUT_FILTERS.has(kind)) return false;
|
|
90462
90903
|
switch (filter) {
|
|
90463
|
-
case "deviceIds": return kind.startsWith("device-") || kind.startsWith("stream-") || kind === "detection-blind" || kind.startsWith("motion-") || kind.startsWith("recording-") || kind === "alarm-triggered";
|
|
90464
|
-
case "deviceTypes": return kind.startsWith("device-") || kind === "detection-blind" || kind.startsWith("motion-");
|
|
90904
|
+
case "deviceIds": return kind.startsWith("device-") || kind.startsWith("stream-") || kind === "detection-blind" || kind.startsWith("motion-") || kind.startsWith("package-llm-") || kind.startsWith("recording-") || kind === "alarm-triggered";
|
|
90905
|
+
case "deviceTypes": return kind.startsWith("device-") || kind === "detection-blind" || kind.startsWith("motion-") || kind.startsWith("package-llm-");
|
|
90465
90906
|
case "nodeIds": return kind.startsWith("node-") || kind === "addon-crash-loop" || kind === "addon-update-available" || kind === "addon-updated" || kind === "server-update-available" || kind === "wrapper-update-available" || kind === "server-updated" || kind.startsWith("storage-location-") || kind.startsWith("alert-");
|
|
90466
90907
|
case "packageNames": return kind.endsWith("update-available") || kind === "addon-updated" || kind === "node-updating" || kind === "server-updated";
|
|
90467
90908
|
case "consumableLowPercent": return NC_CONSUMABLE_SYSTEM_EVENT_KINDS.includes(kind);
|
|
@@ -90505,6 +90946,8 @@ var NC_SYSTEM_EVENT_FAMILY = {
|
|
|
90505
90946
|
"detection-blind": "device-events",
|
|
90506
90947
|
"motion-noisy": "device-events",
|
|
90507
90948
|
"motion-calm": "device-events",
|
|
90949
|
+
"package-llm-silent": "device-events",
|
|
90950
|
+
"package-llm-answered": "device-events",
|
|
90508
90951
|
"recording-stalled": "device-events",
|
|
90509
90952
|
"recording-healthy": "device-events",
|
|
90510
90953
|
"recording-degraded": "device-events",
|
|
@@ -90606,6 +91049,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
|
|
|
90606
91049
|
label: "Motion without a subject",
|
|
90607
91050
|
kinds: ["motion-noisy", "motion-calm"]
|
|
90608
91051
|
},
|
|
91052
|
+
{
|
|
91053
|
+
id: "package-llm",
|
|
91054
|
+
family: "device-events",
|
|
91055
|
+
label: "Package confirm",
|
|
91056
|
+
kinds: ["package-llm-silent", "package-llm-answered"]
|
|
91057
|
+
},
|
|
90609
91058
|
{
|
|
90610
91059
|
id: "recording",
|
|
90611
91060
|
family: "device-events",
|
|
@@ -92038,6 +92487,8 @@ var DEVICE_EVENTS = [
|
|
|
92038
92487
|
"detection-blind",
|
|
92039
92488
|
"motion-noisy",
|
|
92040
92489
|
"motion-calm",
|
|
92490
|
+
"package-llm-silent",
|
|
92491
|
+
"package-llm-answered",
|
|
92041
92492
|
"recording-stalled",
|
|
92042
92493
|
"recording-healthy",
|
|
92043
92494
|
"recording-degraded",
|
|
@@ -92641,7 +93092,8 @@ var NC_TEMPLATE_VARS = [
|
|
|
92641
93092
|
systemEventKinds: [
|
|
92642
93093
|
"recording-degraded",
|
|
92643
93094
|
...DEVICE_ATTENTION,
|
|
92644
|
-
...ALERT_EPISODE
|
|
93095
|
+
...ALERT_EPISODE,
|
|
93096
|
+
"package-llm-silent"
|
|
92645
93097
|
]
|
|
92646
93098
|
},
|
|
92647
93099
|
{
|
|
@@ -92734,7 +93186,8 @@ var NC_TEMPLATE_VARS = [
|
|
|
92734
93186
|
systemEventKinds: [
|
|
92735
93187
|
"storage-location-low",
|
|
92736
93188
|
"storage-location-critical",
|
|
92737
|
-
"storage-location-ok"
|
|
93189
|
+
"storage-location-ok",
|
|
93190
|
+
"package-llm-silent"
|
|
92738
93191
|
]
|
|
92739
93192
|
},
|
|
92740
93193
|
{
|
|
@@ -93145,7 +93598,9 @@ var NC_TEMPLATE_HELD_BACK_SYSTEM_EVENT_KINDS = [
|
|
|
93145
93598
|
"device-attention-required",
|
|
93146
93599
|
"device-attention-resolved",
|
|
93147
93600
|
"rule-broken",
|
|
93148
|
-
"rule-repaired"
|
|
93601
|
+
"rule-repaired",
|
|
93602
|
+
"package-llm-silent",
|
|
93603
|
+
"package-llm-answered"
|
|
93149
93604
|
];
|
|
93150
93605
|
/**
|
|
93151
93606
|
* The catalog as `getTemplateCatalog` SERVES it: every descriptor, with the
|
|
@@ -93305,6 +93760,15 @@ var CLASS_BY_KIND = new Map([
|
|
|
93305
93760
|
snapshotLabel: "Cameras with constant motion now",
|
|
93306
93761
|
snapshotSection: null
|
|
93307
93762
|
},
|
|
93763
|
+
{
|
|
93764
|
+
id: "package-llm-confirm",
|
|
93765
|
+
family: "device-events",
|
|
93766
|
+
label: "Package confirm (not answering / answering again)",
|
|
93767
|
+
bad: ["package-llm-silent"],
|
|
93768
|
+
recovery: ["package-llm-answered"],
|
|
93769
|
+
snapshotLabel: "Cameras whose package confirm is not answering",
|
|
93770
|
+
snapshotSection: null
|
|
93771
|
+
},
|
|
93308
93772
|
{
|
|
93309
93773
|
id: "recording-health",
|
|
93310
93774
|
family: "device-events",
|