@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
|
@@ -30,7 +30,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
30
30
|
}) : target, mod));
|
|
31
31
|
//#endregion
|
|
32
32
|
let node_crypto = require("node:crypto");
|
|
33
|
-
//#region ../types/dist/event-category-
|
|
33
|
+
//#region ../types/dist/event-category-CT-hz5Rb.mjs
|
|
34
34
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
35
35
|
EventCategory["SystemBoot"] = "system.boot";
|
|
36
36
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -356,6 +356,14 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
356
356
|
/** The recovery edge of {@link PipelineMotionNoisy}: the motion fell back, or a detection arrived. */
|
|
357
357
|
EventCategory["PipelineMotionCalm"] = "pipeline.motion-calm";
|
|
358
358
|
/**
|
|
359
|
+
* A camera's package LLM confirm has failed closed three times in a row
|
|
360
|
+
* (D931, 2026-10-26). One edge per camera until
|
|
361
|
+
* {@link PipelinePackageLlmAnswered}.
|
|
362
|
+
*/
|
|
363
|
+
EventCategory["PipelinePackageLlmSilent"] = "pipeline.package-llm-silent";
|
|
364
|
+
/** The recovery edge of {@link PipelinePackageLlmSilent}: a confirm returned yes or no. */
|
|
365
|
+
EventCategory["PipelinePackageLlmAnswered"] = "pipeline.package-llm-answered";
|
|
366
|
+
/**
|
|
359
367
|
* Per-camera pipeline config was mutated by the orchestrator
|
|
360
368
|
* (a settings change via `setAgentInferenceDevices` /
|
|
361
369
|
* `setCameraStepToggle` / `setCameraStepSettings`). Orchestrator
|
|
@@ -5663,7 +5671,7 @@ var ZodIssueCode = {
|
|
|
5663
5671
|
var ZodFirstPartyTypeKind;
|
|
5664
5672
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5665
5673
|
//#endregion
|
|
5666
|
-
//#region ../types/dist/sleep-
|
|
5674
|
+
//#region ../types/dist/sleep-bykKrTgu.mjs
|
|
5667
5675
|
/**
|
|
5668
5676
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5669
5677
|
* window to float samples (D455).
|
|
@@ -8363,6 +8371,99 @@ function defineRecordKinds(specs) {
|
|
|
8363
8371
|
}
|
|
8364
8372
|
return out;
|
|
8365
8373
|
}
|
|
8374
|
+
var READING_QUANTITIES = [
|
|
8375
|
+
"temperature",
|
|
8376
|
+
"pressure",
|
|
8377
|
+
"speed",
|
|
8378
|
+
"precipitation",
|
|
8379
|
+
"precipitation-rate",
|
|
8380
|
+
"length",
|
|
8381
|
+
"area",
|
|
8382
|
+
"illuminance",
|
|
8383
|
+
"irradiance",
|
|
8384
|
+
"power",
|
|
8385
|
+
"energy",
|
|
8386
|
+
"voltage",
|
|
8387
|
+
"current",
|
|
8388
|
+
"apparent-power",
|
|
8389
|
+
"humidity",
|
|
8390
|
+
"percentage",
|
|
8391
|
+
"concentration-volume",
|
|
8392
|
+
"concentration-mass",
|
|
8393
|
+
"concentration-ppb",
|
|
8394
|
+
"volume",
|
|
8395
|
+
"duration",
|
|
8396
|
+
"duration-ms",
|
|
8397
|
+
"information",
|
|
8398
|
+
"sound-level",
|
|
8399
|
+
"signal-level",
|
|
8400
|
+
"colour-temperature",
|
|
8401
|
+
"angle",
|
|
8402
|
+
"bitrate",
|
|
8403
|
+
"rate",
|
|
8404
|
+
"mass",
|
|
8405
|
+
"index",
|
|
8406
|
+
"ratio",
|
|
8407
|
+
"count",
|
|
8408
|
+
"none",
|
|
8409
|
+
"device"
|
|
8410
|
+
];
|
|
8411
|
+
var ReadingQuantitySchema = _enum(READING_QUANTITIES);
|
|
8412
|
+
new Set(READING_QUANTITIES);
|
|
8413
|
+
/**
|
|
8414
|
+
* Stored unit symbol for a quantity. `none` means the number is dimensionless
|
|
8415
|
+
* (or an index / ratio / count). `device` means the cap has no single unit.
|
|
8416
|
+
*/
|
|
8417
|
+
var QUANTITY_BASE = {
|
|
8418
|
+
temperature: "°C",
|
|
8419
|
+
pressure: "hPa",
|
|
8420
|
+
speed: "m/s",
|
|
8421
|
+
precipitation: "mm",
|
|
8422
|
+
"precipitation-rate": "mm/h",
|
|
8423
|
+
length: "m",
|
|
8424
|
+
area: "m²",
|
|
8425
|
+
illuminance: "lx",
|
|
8426
|
+
irradiance: "W/m²",
|
|
8427
|
+
power: "W",
|
|
8428
|
+
energy: "kWh",
|
|
8429
|
+
voltage: "V",
|
|
8430
|
+
current: "A",
|
|
8431
|
+
"apparent-power": "VA",
|
|
8432
|
+
humidity: "%",
|
|
8433
|
+
percentage: "%",
|
|
8434
|
+
"concentration-volume": "ppm",
|
|
8435
|
+
"concentration-mass": "µg/m³",
|
|
8436
|
+
"concentration-ppb": "ppb",
|
|
8437
|
+
volume: "L",
|
|
8438
|
+
duration: "s",
|
|
8439
|
+
"duration-ms": "ms",
|
|
8440
|
+
information: "B",
|
|
8441
|
+
"sound-level": "dBFS",
|
|
8442
|
+
"signal-level": "dBm",
|
|
8443
|
+
"colour-temperature": "mired",
|
|
8444
|
+
angle: "°",
|
|
8445
|
+
bitrate: "kbps",
|
|
8446
|
+
rate: "fps",
|
|
8447
|
+
mass: "kg",
|
|
8448
|
+
index: "none",
|
|
8449
|
+
ratio: "none",
|
|
8450
|
+
count: "none",
|
|
8451
|
+
none: "none",
|
|
8452
|
+
device: "device"
|
|
8453
|
+
};
|
|
8454
|
+
/** The stored unit, or `undefined` when the quantity has no unit symbol. */
|
|
8455
|
+
function baseUnitOf(quantity) {
|
|
8456
|
+
const symbol = QUANTITY_BASE[quantity];
|
|
8457
|
+
if (symbol === "none" || symbol === "device") return void 0;
|
|
8458
|
+
return symbol;
|
|
8459
|
+
}
|
|
8460
|
+
function readingMeta(quantity, extras) {
|
|
8461
|
+
return {
|
|
8462
|
+
quantity,
|
|
8463
|
+
...extras?.precision !== void 0 ? { precision: extras.precision } : {},
|
|
8464
|
+
...extras?.label !== void 0 ? { label: extras.label } : {}
|
|
8465
|
+
};
|
|
8466
|
+
}
|
|
8366
8467
|
/** Shared Zod schemas used across streaming capabilities. */
|
|
8367
8468
|
var CamProfileSchema = _enum([
|
|
8368
8469
|
"high",
|
|
@@ -8390,8 +8491,8 @@ var CamStreamKindSchema = _enum([
|
|
|
8390
8491
|
"derived"
|
|
8391
8492
|
]);
|
|
8392
8493
|
var CamStreamResolutionSchema = object({
|
|
8393
|
-
width: number().int().positive(),
|
|
8394
|
-
height: number().int().positive()
|
|
8494
|
+
width: number().int().positive().meta(readingMeta("none")),
|
|
8495
|
+
height: number().int().positive().meta(readingMeta("none"))
|
|
8395
8496
|
});
|
|
8396
8497
|
var CameraStreamSchema = object({
|
|
8397
8498
|
/** Stable, provider-assigned id unique within the (deviceId) scope. */
|
|
@@ -8991,6 +9092,8 @@ var CAP_NAMES = Object.freeze([
|
|
|
8991
9092
|
"filesystem-browse",
|
|
8992
9093
|
"flood",
|
|
8993
9094
|
"gas",
|
|
9095
|
+
"group-commands",
|
|
9096
|
+
"group-status",
|
|
8994
9097
|
"heating-valve",
|
|
8995
9098
|
"humidifier",
|
|
8996
9099
|
"humidity-sensor",
|
|
@@ -9120,14 +9223,6 @@ Object.freeze({
|
|
|
9120
9223
|
{
|
|
9121
9224
|
"path": "aqi",
|
|
9122
9225
|
"valueType": "number"
|
|
9123
|
-
},
|
|
9124
|
-
{
|
|
9125
|
-
"path": "unit",
|
|
9126
|
-
"valueType": "string"
|
|
9127
|
-
},
|
|
9128
|
-
{
|
|
9129
|
-
"path": "precision",
|
|
9130
|
-
"valueType": "number"
|
|
9131
9226
|
}
|
|
9132
9227
|
],
|
|
9133
9228
|
"alarm-panel": [
|
|
@@ -9163,20 +9258,10 @@ Object.freeze({
|
|
|
9163
9258
|
"valueType": "boolean"
|
|
9164
9259
|
}
|
|
9165
9260
|
],
|
|
9166
|
-
"ambient-light-sensor": [
|
|
9167
|
-
|
|
9168
|
-
|
|
9169
|
-
|
|
9170
|
-
},
|
|
9171
|
-
{
|
|
9172
|
-
"path": "unit",
|
|
9173
|
-
"valueType": "string"
|
|
9174
|
-
},
|
|
9175
|
-
{
|
|
9176
|
-
"path": "precision",
|
|
9177
|
-
"valueType": "number"
|
|
9178
|
-
}
|
|
9179
|
-
],
|
|
9261
|
+
"ambient-light-sensor": [{
|
|
9262
|
+
"path": "lux",
|
|
9263
|
+
"valueType": "number"
|
|
9264
|
+
}],
|
|
9180
9265
|
"audio-metrics": [
|
|
9181
9266
|
{
|
|
9182
9267
|
"path": "ts",
|
|
@@ -9256,6 +9341,10 @@ Object.freeze({
|
|
|
9256
9341
|
"path": "lastUpdated",
|
|
9257
9342
|
"valueType": "number"
|
|
9258
9343
|
},
|
|
9344
|
+
{
|
|
9345
|
+
"path": "volts",
|
|
9346
|
+
"valueType": "number"
|
|
9347
|
+
},
|
|
9259
9348
|
{
|
|
9260
9349
|
"path": "lastContactAt",
|
|
9261
9350
|
"valueType": "number"
|
|
@@ -9498,10 +9587,6 @@ Object.freeze({
|
|
|
9498
9587
|
"datetime"
|
|
9499
9588
|
]
|
|
9500
9589
|
},
|
|
9501
|
-
{
|
|
9502
|
-
"path": "unit",
|
|
9503
|
-
"valueType": "string"
|
|
9504
|
-
},
|
|
9505
9590
|
{
|
|
9506
9591
|
"path": "min",
|
|
9507
9592
|
"valueType": "number"
|
|
@@ -9513,19 +9598,6 @@ Object.freeze({
|
|
|
9513
9598
|
{
|
|
9514
9599
|
"path": "step",
|
|
9515
9600
|
"valueType": "number"
|
|
9516
|
-
},
|
|
9517
|
-
{
|
|
9518
|
-
"path": "precision",
|
|
9519
|
-
"valueType": "number"
|
|
9520
|
-
},
|
|
9521
|
-
{
|
|
9522
|
-
"path": "format",
|
|
9523
|
-
"valueType": "enum",
|
|
9524
|
-
"enumValues": [
|
|
9525
|
-
"date",
|
|
9526
|
-
"time",
|
|
9527
|
-
"datetime"
|
|
9528
|
-
]
|
|
9529
9601
|
}
|
|
9530
9602
|
],
|
|
9531
9603
|
"cover": [
|
|
@@ -9766,13 +9838,8 @@ Object.freeze({
|
|
|
9766
9838
|
"path": "value",
|
|
9767
9839
|
"valueType": "string"
|
|
9768
9840
|
}, {
|
|
9769
|
-
"path": "
|
|
9770
|
-
"valueType": "
|
|
9771
|
-
"enumValues": [
|
|
9772
|
-
"date",
|
|
9773
|
-
"time",
|
|
9774
|
-
"datetime"
|
|
9775
|
-
]
|
|
9841
|
+
"path": "timestamp",
|
|
9842
|
+
"valueType": "boolean"
|
|
9776
9843
|
}],
|
|
9777
9844
|
"event-emitter": [
|
|
9778
9845
|
{
|
|
@@ -9845,6 +9912,20 @@ Object.freeze({
|
|
|
9845
9912
|
"path": "detected",
|
|
9846
9913
|
"valueType": "boolean"
|
|
9847
9914
|
}],
|
|
9915
|
+
"group-status": [
|
|
9916
|
+
{
|
|
9917
|
+
"path": "included",
|
|
9918
|
+
"valueType": "number"
|
|
9919
|
+
},
|
|
9920
|
+
{
|
|
9921
|
+
"path": "excluded",
|
|
9922
|
+
"valueType": "number"
|
|
9923
|
+
},
|
|
9924
|
+
{
|
|
9925
|
+
"path": "total",
|
|
9926
|
+
"valueType": "number"
|
|
9927
|
+
}
|
|
9928
|
+
],
|
|
9848
9929
|
"heating-valve": [{
|
|
9849
9930
|
"path": "position",
|
|
9850
9931
|
"valueType": "number"
|
|
@@ -9879,20 +9960,10 @@ Object.freeze({
|
|
|
9879
9960
|
"valueType": "number"
|
|
9880
9961
|
}
|
|
9881
9962
|
],
|
|
9882
|
-
"humidity-sensor": [
|
|
9883
|
-
|
|
9884
|
-
|
|
9885
|
-
|
|
9886
|
-
},
|
|
9887
|
-
{
|
|
9888
|
-
"path": "unit",
|
|
9889
|
-
"valueType": "string"
|
|
9890
|
-
},
|
|
9891
|
-
{
|
|
9892
|
-
"path": "precision",
|
|
9893
|
-
"valueType": "number"
|
|
9894
|
-
}
|
|
9895
|
-
],
|
|
9963
|
+
"humidity-sensor": [{
|
|
9964
|
+
"path": "percent",
|
|
9965
|
+
"valueType": "number"
|
|
9966
|
+
}],
|
|
9896
9967
|
"image": [{
|
|
9897
9968
|
"path": "url",
|
|
9898
9969
|
"valueType": "string"
|
|
@@ -10231,20 +10302,10 @@ Object.freeze({
|
|
|
10231
10302
|
"valueType": "boolean"
|
|
10232
10303
|
}
|
|
10233
10304
|
],
|
|
10234
|
-
"numeric-sensor": [
|
|
10235
|
-
|
|
10236
|
-
|
|
10237
|
-
|
|
10238
|
-
},
|
|
10239
|
-
{
|
|
10240
|
-
"path": "unit",
|
|
10241
|
-
"valueType": "string"
|
|
10242
|
-
},
|
|
10243
|
-
{
|
|
10244
|
-
"path": "precision",
|
|
10245
|
-
"valueType": "number"
|
|
10246
|
-
}
|
|
10247
|
-
],
|
|
10305
|
+
"numeric-sensor": [{
|
|
10306
|
+
"path": "value",
|
|
10307
|
+
"valueType": "number"
|
|
10308
|
+
}],
|
|
10248
10309
|
"pet-feeder": [
|
|
10249
10310
|
{
|
|
10250
10311
|
"path": "foodLevel",
|
|
@@ -10336,14 +10397,6 @@ Object.freeze({
|
|
|
10336
10397
|
{
|
|
10337
10398
|
"path": "powerFactor",
|
|
10338
10399
|
"valueType": "number"
|
|
10339
|
-
},
|
|
10340
|
-
{
|
|
10341
|
-
"path": "unit",
|
|
10342
|
-
"valueType": "string"
|
|
10343
|
-
},
|
|
10344
|
-
{
|
|
10345
|
-
"path": "precision",
|
|
10346
|
-
"valueType": "number"
|
|
10347
10400
|
}
|
|
10348
10401
|
],
|
|
10349
10402
|
"presence": [
|
|
@@ -10372,20 +10425,10 @@ Object.freeze({
|
|
|
10372
10425
|
"valueType": "number"
|
|
10373
10426
|
}
|
|
10374
10427
|
],
|
|
10375
|
-
"pressure-sensor": [
|
|
10376
|
-
|
|
10377
|
-
|
|
10378
|
-
|
|
10379
|
-
},
|
|
10380
|
-
{
|
|
10381
|
-
"path": "unit",
|
|
10382
|
-
"valueType": "string"
|
|
10383
|
-
},
|
|
10384
|
-
{
|
|
10385
|
-
"path": "precision",
|
|
10386
|
-
"valueType": "number"
|
|
10387
|
-
}
|
|
10388
|
-
],
|
|
10428
|
+
"pressure-sensor": [{
|
|
10429
|
+
"path": "hpa",
|
|
10430
|
+
"valueType": "number"
|
|
10431
|
+
}],
|
|
10389
10432
|
"privacy-mask": [{
|
|
10390
10433
|
"path": "enabled",
|
|
10391
10434
|
"valueType": "boolean"
|
|
@@ -10696,20 +10739,10 @@ Object.freeze({
|
|
|
10696
10739
|
"path": "tampered",
|
|
10697
10740
|
"valueType": "boolean"
|
|
10698
10741
|
}],
|
|
10699
|
-
"temperature-sensor": [
|
|
10700
|
-
|
|
10701
|
-
|
|
10702
|
-
|
|
10703
|
-
},
|
|
10704
|
-
{
|
|
10705
|
-
"path": "unit",
|
|
10706
|
-
"valueType": "string"
|
|
10707
|
-
},
|
|
10708
|
-
{
|
|
10709
|
-
"path": "precision",
|
|
10710
|
-
"valueType": "number"
|
|
10711
|
-
}
|
|
10712
|
-
],
|
|
10742
|
+
"temperature-sensor": [{
|
|
10743
|
+
"path": "celsius",
|
|
10744
|
+
"valueType": "number"
|
|
10745
|
+
}],
|
|
10713
10746
|
"update": [
|
|
10714
10747
|
{
|
|
10715
10748
|
"path": "currentVersion",
|
|
@@ -10820,10 +10853,6 @@ Object.freeze({
|
|
|
10820
10853
|
"path": "temperature",
|
|
10821
10854
|
"valueType": "number"
|
|
10822
10855
|
},
|
|
10823
|
-
{
|
|
10824
|
-
"path": "temperatureUnit",
|
|
10825
|
-
"valueType": "string"
|
|
10826
|
-
},
|
|
10827
10856
|
{
|
|
10828
10857
|
"path": "humidity",
|
|
10829
10858
|
"valueType": "number"
|
|
@@ -10832,18 +10861,10 @@ Object.freeze({
|
|
|
10832
10861
|
"path": "pressure",
|
|
10833
10862
|
"valueType": "number"
|
|
10834
10863
|
},
|
|
10835
|
-
{
|
|
10836
|
-
"path": "pressureUnit",
|
|
10837
|
-
"valueType": "string"
|
|
10838
|
-
},
|
|
10839
10864
|
{
|
|
10840
10865
|
"path": "windSpeed",
|
|
10841
10866
|
"valueType": "number"
|
|
10842
10867
|
},
|
|
10843
|
-
{
|
|
10844
|
-
"path": "windSpeedUnit",
|
|
10845
|
-
"valueType": "string"
|
|
10846
|
-
},
|
|
10847
10868
|
{
|
|
10848
10869
|
"path": "windBearing",
|
|
10849
10870
|
"valueType": "number"
|
|
@@ -10895,7 +10916,7 @@ Object.freeze({
|
|
|
10895
10916
|
* can answer "may a rule actuate this?" without importing the schema barrel
|
|
10896
10917
|
* (~144MB RSS per runner, D28).
|
|
10897
10918
|
*
|
|
10898
|
-
* Coverage:
|
|
10919
|
+
* Coverage: 93 device-scoped capabilities.
|
|
10899
10920
|
*/
|
|
10900
10921
|
var DEVICE_SCOPED_CAPS = new Set([
|
|
10901
10922
|
"accessories",
|
|
@@ -10936,6 +10957,8 @@ var DEVICE_SCOPED_CAPS = new Set([
|
|
|
10936
10957
|
"feature-probe",
|
|
10937
10958
|
"flood",
|
|
10938
10959
|
"gas",
|
|
10960
|
+
"group-commands",
|
|
10961
|
+
"group-status",
|
|
10939
10962
|
"heating-valve",
|
|
10940
10963
|
"humidifier",
|
|
10941
10964
|
"humidity-sensor",
|
|
@@ -11387,7 +11410,7 @@ function errMsg(err) {
|
|
|
11387
11410
|
return String(err);
|
|
11388
11411
|
}
|
|
11389
11412
|
//#endregion
|
|
11390
|
-
//#region ../types/dist/composition-
|
|
11413
|
+
//#region ../types/dist/composition-OhpuespA.mjs
|
|
11391
11414
|
/**
|
|
11392
11415
|
* Deterministic SHA-256 hash of an arbitrary serialisable value. The
|
|
11393
11416
|
* canonical form sorts object keys alphabetically at every depth so two
|
|
@@ -12302,15 +12325,74 @@ function validateExpressionSource(src) {
|
|
|
12302
12325
|
}
|
|
12303
12326
|
return null;
|
|
12304
12327
|
}
|
|
12305
|
-
/**
|
|
12306
|
-
|
|
12307
|
-
|
|
12308
|
-
|
|
12328
|
+
/**
|
|
12329
|
+
* A composition source identity: `(addonId, stableId)`, never a numeric device
|
|
12330
|
+
* id. Split out so helper schemas can name it without a cycle through
|
|
12331
|
+
* `composition.ts` (D659).
|
|
12332
|
+
*/
|
|
12309
12333
|
var CompositionSourceRefSchema = object({
|
|
12310
12334
|
/** The owning addon; `stableId` is unique only within it. */
|
|
12311
12335
|
addonId: string().min(1),
|
|
12312
12336
|
stableId: string().min(1)
|
|
12313
12337
|
});
|
|
12338
|
+
var GROUP_TEMPLATE_IDS = [
|
|
12339
|
+
"temperature",
|
|
12340
|
+
"humidity",
|
|
12341
|
+
"pressure",
|
|
12342
|
+
"illuminance",
|
|
12343
|
+
"power",
|
|
12344
|
+
"energy",
|
|
12345
|
+
"battery",
|
|
12346
|
+
"numeric",
|
|
12347
|
+
"motion",
|
|
12348
|
+
"contact",
|
|
12349
|
+
"leak",
|
|
12350
|
+
"smoke",
|
|
12351
|
+
"occupancy",
|
|
12352
|
+
"binary",
|
|
12353
|
+
"switch",
|
|
12354
|
+
"light"
|
|
12355
|
+
];
|
|
12356
|
+
var NUMERIC_AGGREGATES = [
|
|
12357
|
+
"mean",
|
|
12358
|
+
"median",
|
|
12359
|
+
"min",
|
|
12360
|
+
"max",
|
|
12361
|
+
"sum"
|
|
12362
|
+
];
|
|
12363
|
+
var BINARY_AGGREGATES = ["any", "all"];
|
|
12364
|
+
/** How an actuator group decides it is on. Unknown members never count as off. */
|
|
12365
|
+
var ACTIVE_CRITERIA = ["at-least-one", "all"];
|
|
12366
|
+
var AGGREGATE_REDUCERS = [
|
|
12367
|
+
"mean",
|
|
12368
|
+
"median",
|
|
12369
|
+
"min",
|
|
12370
|
+
"max",
|
|
12371
|
+
"sum",
|
|
12372
|
+
"any",
|
|
12373
|
+
"all"
|
|
12374
|
+
];
|
|
12375
|
+
var GroupTemplateIdSchema = _enum(GROUP_TEMPLATE_IDS);
|
|
12376
|
+
var AggregateReducerSchema = _enum(AGGREGATE_REDUCERS);
|
|
12377
|
+
var ActiveCriterionSchema = _enum(ACTIVE_CRITERIA);
|
|
12378
|
+
/** One member. The field is stored so occupancy can name motion or binary. */
|
|
12379
|
+
var HelperMemberSchema = object({
|
|
12380
|
+
source: CompositionSourceRefSchema,
|
|
12381
|
+
cap: string().min(1),
|
|
12382
|
+
fieldPath: string().min(1)
|
|
12383
|
+
});
|
|
12384
|
+
var HelperSpecSchema = discriminatedUnion("kind", [object({
|
|
12385
|
+
kind: literal("group"),
|
|
12386
|
+
templateId: GroupTemplateIdSchema,
|
|
12387
|
+
aggregate: AggregateReducerSchema,
|
|
12388
|
+
members: array(HelperMemberSchema).min(1).max(64),
|
|
12389
|
+
/** Actuator groups only. Readings leave this unset. */
|
|
12390
|
+
active: ActiveCriterionSchema.optional()
|
|
12391
|
+
})]);
|
|
12392
|
+
/** A composed device's stableId is this prefix plus the block id. */
|
|
12393
|
+
var COMPOSED_DEVICE_STABLE_ID_PREFIX = "composed-";
|
|
12394
|
+
/** Longest snippet a `code` source may carry (slice 4). */
|
|
12395
|
+
var MAX_COMPOSITION_CODE_LENGTH = 2e4;
|
|
12314
12396
|
/** One field of one capability of one source device. */
|
|
12315
12397
|
var CompositionFieldReadSchema = object({
|
|
12316
12398
|
source: CompositionSourceRefSchema,
|
|
@@ -12354,7 +12436,33 @@ var CompositionCodeSourceSchema = object({
|
|
|
12354
12436
|
var CompositionFieldSourceSchema = discriminatedUnion("kind", [
|
|
12355
12437
|
CompositionFromSourceSchema,
|
|
12356
12438
|
CompositionExpressionSourceSchema,
|
|
12357
|
-
CompositionCodeSourceSchema
|
|
12439
|
+
CompositionCodeSourceSchema,
|
|
12440
|
+
object({
|
|
12441
|
+
kind: literal("aggregate"),
|
|
12442
|
+
reducer: _enum([
|
|
12443
|
+
"mean",
|
|
12444
|
+
"median",
|
|
12445
|
+
"min",
|
|
12446
|
+
"max",
|
|
12447
|
+
"sum",
|
|
12448
|
+
"any",
|
|
12449
|
+
"all"
|
|
12450
|
+
]),
|
|
12451
|
+
reads: array(CompositionFieldReadSchema).min(1).max(64),
|
|
12452
|
+
/** `value` is the reading; the others are the member counts. */
|
|
12453
|
+
publish: _enum([
|
|
12454
|
+
"value",
|
|
12455
|
+
"included",
|
|
12456
|
+
"excluded",
|
|
12457
|
+
"total"
|
|
12458
|
+
]),
|
|
12459
|
+
/** What a `value` publish does when nobody is included. Counts ignore this. */
|
|
12460
|
+
empty: _enum([
|
|
12461
|
+
"null",
|
|
12462
|
+
"omit",
|
|
12463
|
+
"offline"
|
|
12464
|
+
])
|
|
12465
|
+
})
|
|
12358
12466
|
]);
|
|
12359
12467
|
var CompositionCommandTargetSchema = discriminatedUnion("kind", [object({
|
|
12360
12468
|
kind: literal("forward"),
|
|
@@ -12400,7 +12508,13 @@ var CompositionSchema = object({
|
|
|
12400
12508
|
kind: literal("existing"),
|
|
12401
12509
|
device: CompositionSourceRefSchema
|
|
12402
12510
|
})]),
|
|
12403
|
-
features: array(CompositionFeatureSchema).min(1).max(16)
|
|
12511
|
+
features: array(CompositionFeatureSchema).min(1).max(16),
|
|
12512
|
+
/**
|
|
12513
|
+
* Present when the block is a helper template. Absent on a free
|
|
12514
|
+
* composition (the room example, device 4603). The editor reads this,
|
|
12515
|
+
* never the compiled features.
|
|
12516
|
+
*/
|
|
12517
|
+
helper: HelperSpecSchema.optional()
|
|
12404
12518
|
}).superRefine((composition, ctx) => {
|
|
12405
12519
|
const seen = /* @__PURE__ */ new Set();
|
|
12406
12520
|
composition.features.forEach((feature, index) => {
|
|
@@ -19391,7 +19505,11 @@ var CompositionProblemSchema = object({
|
|
|
19391
19505
|
"item-field-reserved",
|
|
19392
19506
|
"target-missing",
|
|
19393
19507
|
"target-unreadable",
|
|
19394
|
-
"not-replaceable"
|
|
19508
|
+
"not-replaceable",
|
|
19509
|
+
"native-capability-replace",
|
|
19510
|
+
"mixed-quantity",
|
|
19511
|
+
"helper-mismatch",
|
|
19512
|
+
"member-constraint"
|
|
19395
19513
|
]),
|
|
19396
19514
|
path: string(),
|
|
19397
19515
|
message: string()
|
|
@@ -19412,7 +19530,8 @@ var CompositionUnavailableModeSchema = _enum([
|
|
|
19412
19530
|
"null",
|
|
19413
19531
|
"offline",
|
|
19414
19532
|
"unknown",
|
|
19415
|
-
"release"
|
|
19533
|
+
"release",
|
|
19534
|
+
"omit"
|
|
19416
19535
|
]);
|
|
19417
19536
|
/**
|
|
19418
19537
|
* `derived` reads a source · `clock` reads only `now`, recomputed when a sibling
|
|
@@ -19449,9 +19568,11 @@ var CompositionFieldPlanSchema = object({
|
|
|
19449
19568
|
reads: array(CompositionFieldReadSchema)
|
|
19450
19569
|
});
|
|
19451
19570
|
/**
|
|
19452
|
-
* What a feature does to its target (D663): `new` builds a capability on a
|
|
19453
|
-
* device; on an existing device it `add`s a capability the device lacks
|
|
19454
|
-
*
|
|
19571
|
+
* What a feature does to its target (D663, D944): `new` builds a capability on a
|
|
19572
|
+
* new device; on an existing device it `add`s a capability the device lacks.
|
|
19573
|
+
* Replacing a capability the device already serves is refused
|
|
19574
|
+
* (`native-capability-replace`), not planned. `replace` remains on the claim
|
|
19575
|
+
* wire for a claim the hub already holds.
|
|
19455
19576
|
*/
|
|
19456
19577
|
var CompositionFeatureModeSchema = _enum([
|
|
19457
19578
|
"new",
|
|
@@ -19624,6 +19745,275 @@ Object.freeze({
|
|
|
19624
19745
|
result: ["number", "null"]
|
|
19625
19746
|
}
|
|
19626
19747
|
});
|
|
19748
|
+
/**
|
|
19749
|
+
* One catalog row per base reading a group helper can build (D944 §3).
|
|
19750
|
+
* Data, not a form default written into the block.
|
|
19751
|
+
*/
|
|
19752
|
+
var NOW = {
|
|
19753
|
+
fieldPath: "lastFetchedAt",
|
|
19754
|
+
expr: "now"
|
|
19755
|
+
};
|
|
19756
|
+
var CHANGED = {
|
|
19757
|
+
fieldPath: "lastChangedAt",
|
|
19758
|
+
expr: "now"
|
|
19759
|
+
};
|
|
19760
|
+
function numeric(input) {
|
|
19761
|
+
return {
|
|
19762
|
+
...input,
|
|
19763
|
+
family: "numeric",
|
|
19764
|
+
deviceType: DeviceType.Sensor,
|
|
19765
|
+
memberDeviceType: DeviceType.Sensor,
|
|
19766
|
+
commandCaps: [],
|
|
19767
|
+
baseUnit: baseUnitOf(input.quantity),
|
|
19768
|
+
aggregates: NUMERIC_AGGREGATES,
|
|
19769
|
+
accept: [{
|
|
19770
|
+
cap: input.outputCap,
|
|
19771
|
+
fieldPath: input.outputField
|
|
19772
|
+
}]
|
|
19773
|
+
};
|
|
19774
|
+
}
|
|
19775
|
+
function binary(input) {
|
|
19776
|
+
return {
|
|
19777
|
+
...input,
|
|
19778
|
+
family: "binary",
|
|
19779
|
+
deviceType: DeviceType.Sensor,
|
|
19780
|
+
memberDeviceType: DeviceType.Sensor,
|
|
19781
|
+
commandCaps: [],
|
|
19782
|
+
quantity: "none",
|
|
19783
|
+
baseUnit: void 0,
|
|
19784
|
+
aggregates: BINARY_AGGREGATES,
|
|
19785
|
+
empty: "offline"
|
|
19786
|
+
};
|
|
19787
|
+
}
|
|
19788
|
+
var GROUP_TEMPLATES = [
|
|
19789
|
+
numeric({
|
|
19790
|
+
id: "temperature",
|
|
19791
|
+
summary: "Mean, median, min, max or sum of temperatures. Offline and unknown members are left out, never read as 0 °C.",
|
|
19792
|
+
role: DeviceRole.TemperatureSensor,
|
|
19793
|
+
outputCap: "temperature-sensor",
|
|
19794
|
+
outputField: "celsius",
|
|
19795
|
+
quantity: "temperature",
|
|
19796
|
+
defaultAggregate: "mean",
|
|
19797
|
+
empty: "null",
|
|
19798
|
+
companions: [NOW]
|
|
19799
|
+
}),
|
|
19800
|
+
numeric({
|
|
19801
|
+
id: "humidity",
|
|
19802
|
+
summary: "Humidity in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
19803
|
+
role: DeviceRole.HumiditySensor,
|
|
19804
|
+
outputCap: "humidity-sensor",
|
|
19805
|
+
outputField: "percent",
|
|
19806
|
+
quantity: "humidity",
|
|
19807
|
+
defaultAggregate: "mean",
|
|
19808
|
+
empty: "null",
|
|
19809
|
+
companions: [NOW]
|
|
19810
|
+
}),
|
|
19811
|
+
numeric({
|
|
19812
|
+
id: "pressure",
|
|
19813
|
+
summary: "Pressure in hectopascals. Offline and unknown members are left out, never read as 0 hPa.",
|
|
19814
|
+
role: DeviceRole.PressureSensor,
|
|
19815
|
+
outputCap: "pressure-sensor",
|
|
19816
|
+
outputField: "hpa",
|
|
19817
|
+
quantity: "pressure",
|
|
19818
|
+
defaultAggregate: "mean",
|
|
19819
|
+
empty: "null",
|
|
19820
|
+
companions: [NOW]
|
|
19821
|
+
}),
|
|
19822
|
+
numeric({
|
|
19823
|
+
id: "illuminance",
|
|
19824
|
+
summary: "Illuminance in lux. Offline and unknown members are left out, never read as 0 lx.",
|
|
19825
|
+
role: DeviceRole.AmbientLightSensor,
|
|
19826
|
+
outputCap: "ambient-light-sensor",
|
|
19827
|
+
outputField: "lux",
|
|
19828
|
+
quantity: "illuminance",
|
|
19829
|
+
defaultAggregate: "mean",
|
|
19830
|
+
empty: "null",
|
|
19831
|
+
companions: [NOW]
|
|
19832
|
+
}),
|
|
19833
|
+
numeric({
|
|
19834
|
+
id: "power",
|
|
19835
|
+
summary: "Power in watts, summed by default. Nobody reporting omits the key rather than writing 0 W.",
|
|
19836
|
+
role: DeviceRole.PowerSensor,
|
|
19837
|
+
outputCap: "power-meter",
|
|
19838
|
+
outputField: "watts",
|
|
19839
|
+
quantity: "power",
|
|
19840
|
+
defaultAggregate: "sum",
|
|
19841
|
+
empty: "omit",
|
|
19842
|
+
companions: [NOW]
|
|
19843
|
+
}),
|
|
19844
|
+
numeric({
|
|
19845
|
+
id: "energy",
|
|
19846
|
+
summary: "Energy in kilowatt-hours, summed by default. Nobody reporting omits the key rather than writing 0 kWh.",
|
|
19847
|
+
role: DeviceRole.EnergySensor,
|
|
19848
|
+
outputCap: "power-meter",
|
|
19849
|
+
outputField: "kwhTotal",
|
|
19850
|
+
quantity: "energy",
|
|
19851
|
+
defaultAggregate: "sum",
|
|
19852
|
+
empty: "omit",
|
|
19853
|
+
companions: [NOW]
|
|
19854
|
+
}),
|
|
19855
|
+
numeric({
|
|
19856
|
+
id: "battery",
|
|
19857
|
+
summary: "Battery charge in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
19858
|
+
role: DeviceRole.BatterySensor,
|
|
19859
|
+
outputCap: "battery",
|
|
19860
|
+
outputField: "percentage",
|
|
19861
|
+
quantity: "percentage",
|
|
19862
|
+
defaultAggregate: "mean",
|
|
19863
|
+
empty: "null",
|
|
19864
|
+
companions: [
|
|
19865
|
+
{
|
|
19866
|
+
fieldPath: "charging",
|
|
19867
|
+
expr: "\"unknown\""
|
|
19868
|
+
},
|
|
19869
|
+
{
|
|
19870
|
+
fieldPath: "sleeping",
|
|
19871
|
+
expr: "false"
|
|
19872
|
+
},
|
|
19873
|
+
{
|
|
19874
|
+
fieldPath: "lastUpdated",
|
|
19875
|
+
expr: "now"
|
|
19876
|
+
}
|
|
19877
|
+
]
|
|
19878
|
+
}),
|
|
19879
|
+
numeric({
|
|
19880
|
+
id: "numeric",
|
|
19881
|
+
summary: "A numeric reading in the members’ shared quantity. Mixed quantities are refused. Nobody reporting publishes null, not 0.",
|
|
19882
|
+
role: DeviceRole.NumericSensor,
|
|
19883
|
+
outputCap: "numeric-sensor",
|
|
19884
|
+
outputField: "value",
|
|
19885
|
+
quantity: "device",
|
|
19886
|
+
defaultAggregate: "mean",
|
|
19887
|
+
empty: "null",
|
|
19888
|
+
companions: [NOW]
|
|
19889
|
+
}),
|
|
19890
|
+
binary({
|
|
19891
|
+
id: "motion",
|
|
19892
|
+
summary: "Any or all motion. Offline and unknown members are left out, never read as off. Nobody reporting takes the device offline.",
|
|
19893
|
+
role: DeviceRole.MotionSensor,
|
|
19894
|
+
outputCap: "motion",
|
|
19895
|
+
outputField: "detected",
|
|
19896
|
+
defaultAggregate: "any",
|
|
19897
|
+
accept: [{
|
|
19898
|
+
cap: "motion",
|
|
19899
|
+
fieldPath: "detected"
|
|
19900
|
+
}],
|
|
19901
|
+
companions: [{
|
|
19902
|
+
fieldPath: "lastDetectedAt",
|
|
19903
|
+
expr: "null"
|
|
19904
|
+
}, {
|
|
19905
|
+
fieldPath: "autoClearAfterMs",
|
|
19906
|
+
expr: "null"
|
|
19907
|
+
}]
|
|
19908
|
+
}),
|
|
19909
|
+
binary({
|
|
19910
|
+
id: "contact",
|
|
19911
|
+
summary: "Any or all open contacts. Offline and unknown members are left out, never read as closed.",
|
|
19912
|
+
role: DeviceRole.ContactSensor,
|
|
19913
|
+
outputCap: "contact",
|
|
19914
|
+
outputField: "entryOpen",
|
|
19915
|
+
defaultAggregate: "any",
|
|
19916
|
+
accept: [{
|
|
19917
|
+
cap: "contact",
|
|
19918
|
+
fieldPath: "entryOpen"
|
|
19919
|
+
}],
|
|
19920
|
+
companions: [CHANGED]
|
|
19921
|
+
}),
|
|
19922
|
+
binary({
|
|
19923
|
+
id: "leak",
|
|
19924
|
+
summary: "Any or all leak detections. Offline and unknown members are left out, never read as dry.",
|
|
19925
|
+
role: DeviceRole.LeakSensor,
|
|
19926
|
+
outputCap: "flood",
|
|
19927
|
+
outputField: "flooded",
|
|
19928
|
+
defaultAggregate: "any",
|
|
19929
|
+
accept: [{
|
|
19930
|
+
cap: "flood",
|
|
19931
|
+
fieldPath: "flooded"
|
|
19932
|
+
}],
|
|
19933
|
+
companions: [CHANGED]
|
|
19934
|
+
}),
|
|
19935
|
+
binary({
|
|
19936
|
+
id: "smoke",
|
|
19937
|
+
summary: "Any or all smoke detections. Offline and unknown members are left out, never read as clear.",
|
|
19938
|
+
role: DeviceRole.SmokeSensor,
|
|
19939
|
+
outputCap: "smoke",
|
|
19940
|
+
outputField: "detected",
|
|
19941
|
+
defaultAggregate: "any",
|
|
19942
|
+
accept: [{
|
|
19943
|
+
cap: "smoke",
|
|
19944
|
+
fieldPath: "detected"
|
|
19945
|
+
}],
|
|
19946
|
+
companions: [CHANGED]
|
|
19947
|
+
}),
|
|
19948
|
+
binary({
|
|
19949
|
+
id: "occupancy",
|
|
19950
|
+
summary: "Any or all of motion or binary sensors, published as a binary. Presence zones are not aggregated. Nobody reporting is offline, not off.",
|
|
19951
|
+
role: DeviceRole.BinarySensor,
|
|
19952
|
+
outputCap: "binary",
|
|
19953
|
+
outputField: "on",
|
|
19954
|
+
defaultAggregate: "any",
|
|
19955
|
+
accept: [{
|
|
19956
|
+
cap: "motion",
|
|
19957
|
+
fieldPath: "detected"
|
|
19958
|
+
}, {
|
|
19959
|
+
cap: "binary",
|
|
19960
|
+
fieldPath: "on"
|
|
19961
|
+
}],
|
|
19962
|
+
companions: [CHANGED]
|
|
19963
|
+
}),
|
|
19964
|
+
binary({
|
|
19965
|
+
id: "binary",
|
|
19966
|
+
summary: "Any or all generic binary sensors. Offline and unknown members are left out, never read as off.",
|
|
19967
|
+
role: DeviceRole.BinarySensor,
|
|
19968
|
+
outputCap: "binary",
|
|
19969
|
+
outputField: "on",
|
|
19970
|
+
defaultAggregate: "any",
|
|
19971
|
+
accept: [{
|
|
19972
|
+
cap: "binary",
|
|
19973
|
+
fieldPath: "on"
|
|
19974
|
+
}],
|
|
19975
|
+
companions: [CHANGED]
|
|
19976
|
+
}),
|
|
19977
|
+
actuator({
|
|
19978
|
+
id: "switch",
|
|
19979
|
+
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.",
|
|
19980
|
+
deviceType: DeviceType.Switch,
|
|
19981
|
+
outputCap: "switch",
|
|
19982
|
+
commandCaps: ["switch"]
|
|
19983
|
+
}),
|
|
19984
|
+
actuator({
|
|
19985
|
+
id: "light",
|
|
19986
|
+
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.",
|
|
19987
|
+
deviceType: DeviceType.Light,
|
|
19988
|
+
outputCap: "switch",
|
|
19989
|
+
commandCaps: [
|
|
19990
|
+
"switch",
|
|
19991
|
+
"brightness",
|
|
19992
|
+
"color"
|
|
19993
|
+
]
|
|
19994
|
+
})
|
|
19995
|
+
];
|
|
19996
|
+
function actuator(input) {
|
|
19997
|
+
return {
|
|
19998
|
+
...input,
|
|
19999
|
+
family: "actuator",
|
|
20000
|
+
role: void 0,
|
|
20001
|
+
memberDeviceType: input.deviceType,
|
|
20002
|
+
outputField: "on",
|
|
20003
|
+
quantity: "none",
|
|
20004
|
+
baseUnit: void 0,
|
|
20005
|
+
aggregates: BINARY_AGGREGATES,
|
|
20006
|
+
defaultAggregate: "any",
|
|
20007
|
+
empty: "offline",
|
|
20008
|
+
accept: [{
|
|
20009
|
+
cap: "switch",
|
|
20010
|
+
fieldPath: "on"
|
|
20011
|
+
}],
|
|
20012
|
+
companions: [CHANGED]
|
|
20013
|
+
};
|
|
20014
|
+
}
|
|
20015
|
+
new Map(GROUP_TEMPLATES.map((template) => [template.id, template]));
|
|
20016
|
+
DeviceFeature.LightColorRgb, DeviceFeature.LightColorHsv, DeviceFeature.LightColorMired;
|
|
19627
20017
|
`${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
|
|
19628
20018
|
/**
|
|
19629
20019
|
* What a composition may BUILD on a device type (G2, D676): the caps a new
|
|
@@ -21344,12 +21734,12 @@ method(object({ deviceId: number().int().nonnegative() }), DeviceAdminLinkSchema
|
|
|
21344
21734
|
* providers detect renames by matching `uniqueId` and patch `id`
|
|
21345
21735
|
* in-place so dispatch keeps working.
|
|
21346
21736
|
*
|
|
21347
|
-
* **
|
|
21348
|
-
*
|
|
21349
|
-
*
|
|
21350
|
-
*
|
|
21351
|
-
* (`ha-domain-mapping`)
|
|
21352
|
-
* stored after that point.
|
|
21737
|
+
* **Display unit and precision are NOT stored here.** They are a read-time
|
|
21738
|
+
* preference (D944). A polymorphic reading stores its `quantity` here once,
|
|
21739
|
+
* at adopt, and a date/time value stores `dateTimeShape` the same way —
|
|
21740
|
+
* neither is repeated on each sample. The `device_class` tag is an
|
|
21741
|
+
* HA-specific input consumed at the discovery boundary (`ha-domain-mapping`)
|
|
21742
|
+
* to derive the CamStack `DeviceRole`; it is never stored after that point.
|
|
21353
21743
|
*
|
|
21354
21744
|
* The `raw` escape hatch carries provider-specific attributes that don't
|
|
21355
21745
|
* fit the structured slots (HA `attributes` whitelist, Reolink `deviceCache`
|
|
@@ -21363,6 +21753,14 @@ var SourceInfoSchema = object({
|
|
|
21363
21753
|
/** Immutable upstream identifier when available (HA `unique_id`, … ).
|
|
21364
21754
|
* Used to detect rename when `id` changes. */
|
|
21365
21755
|
uniqueId: string().optional(),
|
|
21756
|
+
/** Quantity of a polymorphic reading, written once at adopt (D944). */
|
|
21757
|
+
quantity: ReadingQuantitySchema.optional(),
|
|
21758
|
+
/** Date / time / datetime shape of a string reading, written once at adopt. */
|
|
21759
|
+
dateTimeShape: _enum([
|
|
21760
|
+
"date",
|
|
21761
|
+
"time",
|
|
21762
|
+
"datetime"
|
|
21763
|
+
]).optional(),
|
|
21366
21764
|
/** Provider-specific extras that don't fit the structured slots.
|
|
21367
21765
|
* Whitelist what goes here per provider — do NOT dump entire HA
|
|
21368
21766
|
* attribute blobs (would explode the meta JSON column). */
|
|
@@ -42390,7 +42788,8 @@ method(object({
|
|
|
42390
42788
|
"enum"
|
|
42391
42789
|
]),
|
|
42392
42790
|
enumValues: array(string()).optional(),
|
|
42393
|
-
item: boolean().optional()
|
|
42791
|
+
item: boolean().optional(),
|
|
42792
|
+
quantity: ReadingQuantitySchema.optional()
|
|
42394
42793
|
})).readonly(),
|
|
42395
42794
|
itemArray: object({
|
|
42396
42795
|
path: string(),
|
|
@@ -46457,8 +46856,8 @@ var MaskPolygonShapeSchema = object({
|
|
|
46457
46856
|
/** Boolean cell grid — row-major, length === gridWidth*gridHeight. */
|
|
46458
46857
|
var MaskGridShapeSchema = object({
|
|
46459
46858
|
kind: literal("grid"),
|
|
46460
|
-
gridWidth: number(),
|
|
46461
|
-
gridHeight: number(),
|
|
46859
|
+
gridWidth: number().meta(readingMeta("none")),
|
|
46860
|
+
gridHeight: number().meta(readingMeta("none")),
|
|
46462
46861
|
cells: array(boolean())
|
|
46463
46862
|
});
|
|
46464
46863
|
discriminatedUnion("kind", [
|
|
@@ -46570,6 +46969,8 @@ var NcSystemEventKindSchema = _enum([
|
|
|
46570
46969
|
"detection-blind",
|
|
46571
46970
|
"motion-noisy",
|
|
46572
46971
|
"motion-calm",
|
|
46972
|
+
"package-llm-silent",
|
|
46973
|
+
"package-llm-answered",
|
|
46573
46974
|
"recording-stalled",
|
|
46574
46975
|
"recording-healthy",
|
|
46575
46976
|
"recording-degraded",
|
|
@@ -48132,6 +48533,14 @@ var NC_CONDITION_CATALOG = [
|
|
|
48132
48533
|
value: "motion-calm",
|
|
48133
48534
|
label: "Camera motion calm again"
|
|
48134
48535
|
},
|
|
48536
|
+
{
|
|
48537
|
+
value: "package-llm-silent",
|
|
48538
|
+
label: "Package confirm not answering"
|
|
48539
|
+
},
|
|
48540
|
+
{
|
|
48541
|
+
value: "package-llm-answered",
|
|
48542
|
+
label: "Package confirm answering again"
|
|
48543
|
+
},
|
|
48135
48544
|
{
|
|
48136
48545
|
value: "recording-stalled",
|
|
48137
48546
|
label: "Recording stalled"
|
|
@@ -59507,6 +59916,28 @@ var PackageVersionInfoSchema = object({
|
|
|
59507
59916
|
deprecated: string().optional(),
|
|
59508
59917
|
distTags: array(string()).readonly()
|
|
59509
59918
|
});
|
|
59919
|
+
/**
|
|
59920
|
+
* One published document. `ok` is markdown from the registry. `missing` means
|
|
59921
|
+
* the registry answered and the file was not there. `error` is a registry or
|
|
59922
|
+
* tarball failure — never an empty string standing in for either.
|
|
59923
|
+
*/
|
|
59924
|
+
var PackageDocBodySchema = discriminatedUnion("status", [
|
|
59925
|
+
object({
|
|
59926
|
+
status: literal("ok"),
|
|
59927
|
+
markdown: string()
|
|
59928
|
+
}),
|
|
59929
|
+
object({ status: literal("missing") }),
|
|
59930
|
+
object({
|
|
59931
|
+
status: literal("error"),
|
|
59932
|
+
message: string()
|
|
59933
|
+
})
|
|
59934
|
+
]);
|
|
59935
|
+
var PackageDocsSchema = object({
|
|
59936
|
+
name: string(),
|
|
59937
|
+
version: string(),
|
|
59938
|
+
readme: PackageDocBodySchema,
|
|
59939
|
+
changelog: PackageDocBodySchema
|
|
59940
|
+
});
|
|
59510
59941
|
var SearchResultSchema = object({
|
|
59511
59942
|
name: string(),
|
|
59512
59943
|
version: string(),
|
|
@@ -59725,7 +60156,10 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
|
|
|
59725
60156
|
}), object({ success: literal(true) }), {
|
|
59726
60157
|
kind: "mutation",
|
|
59727
60158
|
auth: "admin"
|
|
59728
|
-
}), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({
|
|
60159
|
+
}), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({
|
|
60160
|
+
name: string().min(1),
|
|
60161
|
+
version: string().min(1).optional()
|
|
60162
|
+
}), PackageDocsSchema, { auth: "admin" }), method(object({ addonId: string() }), RestartAddonResultSchema, {
|
|
59729
60163
|
kind: "mutation",
|
|
59730
60164
|
auth: "admin"
|
|
59731
60165
|
}), method(object({ packageName: string() }), object({ success: literal(true) }), {
|
|
@@ -59784,27 +60218,17 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
|
|
|
59784
60218
|
*/
|
|
59785
60219
|
var AirQualitySensorStatusSchema = object({
|
|
59786
60220
|
/** Carbon dioxide concentration in ppm. */
|
|
59787
|
-
co2Ppm: number().min(0).optional(),
|
|
60221
|
+
co2Ppm: number().min(0).optional().meta(readingMeta("concentration-volume")),
|
|
59788
60222
|
/** Total volatile organic compounds in ppb. */
|
|
59789
|
-
vocPpb: number().min(0).optional(),
|
|
60223
|
+
vocPpb: number().min(0).optional().meta(readingMeta("concentration-ppb")),
|
|
59790
60224
|
/** Particulate matter ≤ 2.5 μm in µg/m³. */
|
|
59791
|
-
pm25: number().min(0).optional(),
|
|
60225
|
+
pm25: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
59792
60226
|
/** Particulate matter ≤ 10 μm in µg/m³. */
|
|
59793
|
-
pm10: number().min(0).optional(),
|
|
60227
|
+
pm10: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
59794
60228
|
/** Composite AQI value (typically 0..500). */
|
|
59795
|
-
aqi: number().optional(),
|
|
60229
|
+
aqi: number().optional().meta(readingMeta("index")),
|
|
59796
60230
|
/** Ms epoch when the slice was last updated. */
|
|
59797
|
-
lastFetchedAt: number()
|
|
59798
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
59799
|
-
* `attributes.unit_of_measurement` → 'ppm' / 'ppb' / 'µg/m³'). Each
|
|
59800
|
-
* upstream `sensor.*` entity surfaces ONE device_class, so one unit
|
|
59801
|
-
* per slice is unambiguous. */
|
|
59802
|
-
unit: string().optional(),
|
|
59803
|
-
/** Suggested decimal places for numeric display.
|
|
59804
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
59805
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
59806
|
-
* auto-formatting when absent. */
|
|
59807
|
-
precision: number().int().min(0).max(10).optional()
|
|
60231
|
+
lastFetchedAt: number()
|
|
59808
60232
|
});
|
|
59809
60233
|
var airQualitySensorCapability = {
|
|
59810
60234
|
name: "air-quality-sensor",
|
|
@@ -59841,12 +60265,12 @@ var airQualitySensorCapability = {
|
|
|
59841
60265
|
},
|
|
59842
60266
|
pm25: {
|
|
59843
60267
|
kind: "gauge",
|
|
59844
|
-
unit: "
|
|
60268
|
+
unit: "µg/m³",
|
|
59845
60269
|
deadband: 1
|
|
59846
60270
|
},
|
|
59847
60271
|
pm10: {
|
|
59848
60272
|
kind: "gauge",
|
|
59849
|
-
unit: "
|
|
60273
|
+
unit: "µg/m³",
|
|
59850
60274
|
deadband: 1
|
|
59851
60275
|
},
|
|
59852
60276
|
aqi: {
|
|
@@ -59864,22 +60288,13 @@ var airQualitySensorCapability = {
|
|
|
59864
60288
|
* entries with `device_class: illuminance`.
|
|
59865
60289
|
*/
|
|
59866
60290
|
var AmbientLightSensorStatusSchema = object({
|
|
59867
|
-
/** Current illuminance in lux (lx). */
|
|
59868
|
-
lux: number().min(0).meta({
|
|
59869
|
-
|
|
60291
|
+
/** Current illuminance in lux (lx). `null` when the sample was refused (D393). */
|
|
60292
|
+
lux: number().min(0).nullable().meta(readingMeta("illuminance", {
|
|
60293
|
+
precision: 0,
|
|
59870
60294
|
label: "Illuminance"
|
|
59871
|
-
}),
|
|
60295
|
+
})),
|
|
59872
60296
|
/** Ms epoch when the slice was last updated. */
|
|
59873
|
-
lastFetchedAt: number()
|
|
59874
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
59875
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
59876
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
59877
|
-
unit: string().optional(),
|
|
59878
|
-
/** Suggested decimal places for numeric display.
|
|
59879
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
59880
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
59881
|
-
* auto-formatting when absent. */
|
|
59882
|
-
precision: number().int().min(0).max(10).optional()
|
|
60297
|
+
lastFetchedAt: number()
|
|
59883
60298
|
});
|
|
59884
60299
|
var ambientLightSensorCapability = {
|
|
59885
60300
|
name: "ambient-light-sensor",
|
|
@@ -59911,12 +60326,7 @@ var ambientLightSensorCapability = {
|
|
|
59911
60326
|
} } },
|
|
59912
60327
|
/** Clock fields: written, but excluded from the compare that decides
|
|
59913
60328
|
* whether persisting is worth a SQLite commit. */
|
|
59914
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
59915
|
-
customize: {
|
|
59916
|
-
version: 1,
|
|
59917
|
-
advanced: "derive",
|
|
59918
|
-
targets: []
|
|
59919
|
-
}
|
|
60329
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
59920
60330
|
};
|
|
59921
60331
|
/**
|
|
59922
60332
|
* Per-class audio metrics aggregated over a sliding window.
|
|
@@ -60143,10 +60553,7 @@ var BatteryStatusSchema = object({
|
|
|
60143
60553
|
* Consumers must SKIP a null rather than coerce it — `battery-band` already
|
|
60144
60554
|
* declines to band a non-finite reading, which is the correct shape.
|
|
60145
60555
|
*/
|
|
60146
|
-
percentage: number().min(0).max(100).nullable().meta({
|
|
60147
|
-
unit: "%",
|
|
60148
|
-
label: "Charge"
|
|
60149
|
-
}),
|
|
60556
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage", { label: "Charge" })),
|
|
60150
60557
|
/**
|
|
60151
60558
|
* Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
|
|
60152
60559
|
* Reolink-specific for the Solar Panel 2 accessory (will become
|
|
@@ -60173,7 +60580,14 @@ var BatteryStatusSchema = object({
|
|
|
60173
60580
|
*/
|
|
60174
60581
|
sleeping: boolean().meta({ label: "Sleeping" }),
|
|
60175
60582
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
60176
|
-
lastUpdated: number(),
|
|
60583
|
+
lastUpdated: number().meta(readingMeta("none")),
|
|
60584
|
+
/**
|
|
60585
|
+
* Battery voltage in volts, for a cell the firmware reports as voltage
|
|
60586
|
+
* rather than a percentage (Ecowitt capacitor packs). Absent on cameras
|
|
60587
|
+
* that only report charge. A second reading on this cap, not a second
|
|
60588
|
+
* `numeric-sensor` on the same device.
|
|
60589
|
+
*/
|
|
60590
|
+
volts: number().nullable().optional().meta(readingMeta("voltage", { label: "Voltage" })),
|
|
60177
60591
|
/**
|
|
60178
60592
|
* Ms epoch of the last time the device PROVED it was reachable — a
|
|
60179
60593
|
* completed firmware round-trip, an observed wake, or an inbound push
|
|
@@ -60225,7 +60639,6 @@ var BATTERY_DEVICE_TYPES = [
|
|
|
60225
60639
|
/** Generic Customize target for the percentage reading (D936). */
|
|
60226
60640
|
var batteryCustomize = {
|
|
60227
60641
|
version: 1,
|
|
60228
|
-
advanced: "derive",
|
|
60229
60642
|
targets: [{
|
|
60230
60643
|
id: "percentage",
|
|
60231
60644
|
cardinality: "scalar",
|
|
@@ -60234,7 +60647,7 @@ var batteryCustomize = {
|
|
|
60234
60647
|
stateField: "percentage"
|
|
60235
60648
|
},
|
|
60236
60649
|
deviceTypes: BATTERY_DEVICE_TYPES,
|
|
60237
|
-
apply: "add
|
|
60650
|
+
apply: "add",
|
|
60238
60651
|
path: "percentage",
|
|
60239
60652
|
sources: [{
|
|
60240
60653
|
kind: "field",
|
|
@@ -60355,10 +60768,16 @@ onStatusChanged: { data: object({
|
|
|
60355
60768
|
/**
|
|
60356
60769
|
* History (D850): recorded series. The generic capture replaces the `battery` series of `pipeline-analytics:stats-5m`.
|
|
60357
60770
|
*/
|
|
60358
|
-
history: { fields: {
|
|
60359
|
-
|
|
60360
|
-
|
|
60361
|
-
|
|
60771
|
+
history: { fields: {
|
|
60772
|
+
percentage: {
|
|
60773
|
+
kind: "gauge",
|
|
60774
|
+
unit: "%"
|
|
60775
|
+
},
|
|
60776
|
+
volts: {
|
|
60777
|
+
kind: "gauge",
|
|
60778
|
+
unit: "V"
|
|
60779
|
+
}
|
|
60780
|
+
} },
|
|
60362
60781
|
customize: batteryCustomize,
|
|
60363
60782
|
/** Clock fields: written, but excluded from the compare that decides
|
|
60364
60783
|
* whether persisting is worth a SQLite commit. */
|
|
@@ -60405,12 +60824,7 @@ var binaryCapability = {
|
|
|
60405
60824
|
history: { fields: { on: { kind: "boolean" } } },
|
|
60406
60825
|
/** Clock fields: written, but excluded from the compare that decides
|
|
60407
60826
|
* whether persisting is worth a SQLite commit. */
|
|
60408
|
-
volatileStateFields: ["lastChangedAt"]
|
|
60409
|
-
customize: {
|
|
60410
|
-
version: 1,
|
|
60411
|
-
advanced: "derive",
|
|
60412
|
-
targets: []
|
|
60413
|
-
}
|
|
60827
|
+
volatileStateFields: ["lastChangedAt"]
|
|
60414
60828
|
};
|
|
60415
60829
|
/**
|
|
60416
60830
|
* Dimmable-light brightness control. Co-exists with `switch` on the
|
|
@@ -60426,7 +60840,7 @@ var binaryCapability = {
|
|
|
60426
60840
|
*/
|
|
60427
60841
|
var BrightnessStatusSchema = object({
|
|
60428
60842
|
/** Current level as 0..100 inclusive. Firmware-reported. */
|
|
60429
|
-
percentage: number().min(0).max(100),
|
|
60843
|
+
percentage: number().min(0).max(100).meta(readingMeta("percentage")),
|
|
60430
60844
|
/** Ms epoch of the last operator-driven change. Useful for UI freshness. */
|
|
60431
60845
|
lastChangedAt: number()
|
|
60432
60846
|
});
|
|
@@ -60907,21 +61321,21 @@ var ClimateControlStatusSchema = object({
|
|
|
60907
61321
|
/** Single setpoint in Celsius. Used by single-target modes
|
|
60908
61322
|
* (heat / cool / dry). Null when the device is in a range mode
|
|
60909
61323
|
* (`heat_cool`) or has no setpoint at all (`fan_only`/`off`). */
|
|
60910
|
-
target: number().nullable(),
|
|
61324
|
+
target: number().nullable().meta(readingMeta("temperature")),
|
|
60911
61325
|
/** Upper bound of the dual setpoint in Celsius. Populated only
|
|
60912
61326
|
* in `heat_cool` mode. */
|
|
60913
|
-
targetHigh: number().nullable(),
|
|
61327
|
+
targetHigh: number().nullable().meta(readingMeta("temperature")),
|
|
60914
61328
|
/** Lower bound of the dual setpoint in Celsius. Populated only
|
|
60915
61329
|
* in `heat_cool` mode. */
|
|
60916
|
-
targetLow: number().nullable(),
|
|
61330
|
+
targetLow: number().nullable().meta(readingMeta("temperature")),
|
|
60917
61331
|
/** Target relative humidity (0..100). Null when the device has no
|
|
60918
61332
|
* humidity control. */
|
|
60919
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
61333
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
60920
61334
|
/** Current measured temperature in Celsius. Read-only — pushed by
|
|
60921
61335
|
* the device's internal sensor. */
|
|
60922
|
-
currentTemp: number().nullable(),
|
|
61336
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
60923
61337
|
/** Current measured relative humidity (0..100). Read-only. */
|
|
60924
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
61338
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
60925
61339
|
/** Vertical louver swing on/off. Null when the device has no vertical
|
|
60926
61340
|
* swing surface (gate with `DeviceFeature.ClimateSwingVertical`). */
|
|
60927
61341
|
swingVertical: boolean().nullable(),
|
|
@@ -60929,11 +61343,11 @@ var ClimateControlStatusSchema = object({
|
|
|
60929
61343
|
* horizontal swing surface (gate with `DeviceFeature.ClimateSwingHorizontal`). */
|
|
60930
61344
|
swingHorizontal: boolean().nullable(),
|
|
60931
61345
|
/** Lowest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
60932
|
-
minTemp: number().nullable().optional(),
|
|
61346
|
+
minTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
60933
61347
|
/** Highest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
60934
|
-
maxTemp: number().nullable().optional(),
|
|
61348
|
+
maxTemp: number().nullable().optional().meta(readingMeta("temperature")),
|
|
60935
61349
|
/** Setpoint granularity, Celsius (0.5, 1). Absent / null = not reported. */
|
|
60936
|
-
tempStep: number().positive().nullable().optional(),
|
|
61350
|
+
tempStep: number().positive().nullable().optional().meta(readingMeta("temperature")),
|
|
60937
61351
|
/** Ms epoch when the slice was last updated (push or command). */
|
|
60938
61352
|
lastFetchedAt: number()
|
|
60939
61353
|
});
|
|
@@ -61075,17 +61489,17 @@ var climateControlCapability = {
|
|
|
61075
61489
|
* modes to expose in the picker without a slice fetch.
|
|
61076
61490
|
*/
|
|
61077
61491
|
var RgbTripletSchema = object({
|
|
61078
|
-
r: number().int().min(0).max(255),
|
|
61079
|
-
g: number().int().min(0).max(255),
|
|
61080
|
-
b: number().int().min(0).max(255)
|
|
61492
|
+
r: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
61493
|
+
g: number().int().min(0).max(255).meta(readingMeta("none")),
|
|
61494
|
+
b: number().int().min(0).max(255).meta(readingMeta("none"))
|
|
61081
61495
|
});
|
|
61082
61496
|
var HsvTripletSchema = object({
|
|
61083
61497
|
/** Hue in degrees, 0..360. */
|
|
61084
|
-
h: number().min(0).max(360),
|
|
61498
|
+
h: number().min(0).max(360).meta(readingMeta("none")),
|
|
61085
61499
|
/** Saturation as 0..100 inclusive. */
|
|
61086
|
-
s: number().min(0).max(100),
|
|
61500
|
+
s: number().min(0).max(100).meta(readingMeta("none")),
|
|
61087
61501
|
/** Value/brightness as 0..100 inclusive. */
|
|
61088
|
-
v: number().min(0).max(100)
|
|
61502
|
+
v: number().min(0).max(100).meta(readingMeta("none"))
|
|
61089
61503
|
});
|
|
61090
61504
|
var ColorInputSchema = discriminatedUnion("mode", [
|
|
61091
61505
|
object({
|
|
@@ -61114,7 +61528,7 @@ var ColorStatusSchema = object({
|
|
|
61114
61528
|
/** Populated when `mode === 'hsv'`. */
|
|
61115
61529
|
hsv: HsvTripletSchema.optional(),
|
|
61116
61530
|
/** Populated when `mode === 'mired'`. */
|
|
61117
|
-
mireds: number().int().optional(),
|
|
61531
|
+
mireds: number().int().optional().meta(readingMeta("colour-temperature")),
|
|
61118
61532
|
/** Ms epoch of the last operator-driven change. */
|
|
61119
61533
|
lastChangedAt: number()
|
|
61120
61534
|
});
|
|
@@ -61323,18 +61737,12 @@ var FORM_OF_KIND = {
|
|
|
61323
61737
|
function consumableFormOf(item) {
|
|
61324
61738
|
return item.form ?? FORM_OF_KIND[consumableKindOf(item)];
|
|
61325
61739
|
}
|
|
61326
|
-
/**
|
|
61327
|
-
|
|
61328
|
-
|
|
61329
|
-
"days",
|
|
61330
|
-
"hours",
|
|
61331
|
-
"cycles"
|
|
61332
|
-
]);
|
|
61333
|
-
/** Remaining life as a COUNT, not a percentage (the PetKit desiccant reports
|
|
61334
|
-
* days). `value` null = unknown (D393). */
|
|
61740
|
+
/** Whether `remaining.value` is a duration in seconds or a dimensionless count. */
|
|
61741
|
+
var ConsumableRemainingKindSchema = _enum(["duration", "count"]);
|
|
61742
|
+
/** Remaining life. `value` null = unknown (D393). Duration is seconds. */
|
|
61335
61743
|
var ConsumableRemainingSchema = object({
|
|
61336
|
-
value: number().min(0).nullable(),
|
|
61337
|
-
|
|
61744
|
+
value: number().min(0).nullable().meta(readingMeta("device")),
|
|
61745
|
+
kind: ConsumableRemainingKindSchema
|
|
61338
61746
|
});
|
|
61339
61747
|
/** A single consumable item. Either a continuous `level` (remaining
|
|
61340
61748
|
* life %, or fill % for a `supply` / `waste` item) or a discrete `status`
|
|
@@ -61347,7 +61755,7 @@ var ConsumableItemSchema = object({
|
|
|
61347
61755
|
/** Display name. */
|
|
61348
61756
|
label: string().min(1),
|
|
61349
61757
|
/** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
|
|
61350
|
-
level: number().min(0).max(100).nullable(),
|
|
61758
|
+
level: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61351
61759
|
/** The provider's discrete verdict when known (binary mode). */
|
|
61352
61760
|
status: ConsumableStatusSchema.nullable(),
|
|
61353
61761
|
/** What the item is — decides whether low or full is bad. Absent = `wear`. */
|
|
@@ -61429,8 +61837,8 @@ var consumablesCustomize = {
|
|
|
61429
61837
|
transforms: [{ kind: "identity" }]
|
|
61430
61838
|
}],
|
|
61431
61839
|
literals: [{
|
|
61432
|
-
path: "remaining.
|
|
61433
|
-
values: [...
|
|
61840
|
+
path: "remaining.kind",
|
|
61841
|
+
values: [...ConsumableRemainingKindSchema.options]
|
|
61434
61842
|
}]
|
|
61435
61843
|
},
|
|
61436
61844
|
{
|
|
@@ -61559,7 +61967,6 @@ reset: method(object({
|
|
|
61559
61967
|
},
|
|
61560
61968
|
"remaining.value": {
|
|
61561
61969
|
kind: "gauge",
|
|
61562
|
-
unitFrom: "remaining.unit",
|
|
61563
61970
|
deadband: 1,
|
|
61564
61971
|
displayName: "Remaining"
|
|
61565
61972
|
}
|
|
@@ -61629,10 +62036,9 @@ var contactCapability = {
|
|
|
61629
62036
|
* (empty array for the other kinds). It lives in the slice because
|
|
61630
62037
|
* HA `select.*` entities may update their options at runtime.
|
|
61631
62038
|
*
|
|
61632
|
-
*
|
|
61633
|
-
*
|
|
61634
|
-
*
|
|
61635
|
-
* push — consistent with `options` and the sensor-unit approach.
|
|
62039
|
+
* Numeric `min` / `max` / `step` live in the slice and share the device
|
|
62040
|
+
* quantity (`SourceInfo.quantity`, D944). Display precision is a read-time
|
|
62041
|
+
* preference. A datetime control's shape is `SourceInfo.dateTimeShape`.
|
|
61636
62042
|
*/
|
|
61637
62043
|
var ControlStatusSchema = object({
|
|
61638
62044
|
kind: _enum([
|
|
@@ -61644,39 +62050,17 @@ var ControlStatusSchema = object({
|
|
|
61644
62050
|
/** Current value. Numeric kind → number; select/text/datetime → string.
|
|
61645
62051
|
* Datetime values are ISO 8601 strings (full timestamp, date-only,
|
|
61646
62052
|
* or time-only — HA accepts all three forms). */
|
|
61647
|
-
value: union([number(), string()]),
|
|
62053
|
+
value: union([number().meta(readingMeta("device")), string()]),
|
|
61648
62054
|
/** Acceptable values when `kind === 'select'`. Empty for other kinds. */
|
|
61649
62055
|
options: array(string()),
|
|
61650
62056
|
/** Ms epoch when the slice was last updated. */
|
|
61651
62057
|
lastChangedAt: number(),
|
|
61652
|
-
/**
|
|
61653
|
-
|
|
61654
|
-
|
|
61655
|
-
|
|
61656
|
-
/**
|
|
61657
|
-
|
|
61658
|
-
min: number().optional(),
|
|
61659
|
-
/** Maximum allowed value. Populated live from HA `attributes.max`.
|
|
61660
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
61661
|
-
max: number().optional(),
|
|
61662
|
-
/** Step increment. Populated live from HA `attributes.step`.
|
|
61663
|
-
* Meaningful for `kind === 'numeric'`; absent for other kinds. */
|
|
61664
|
-
step: number().optional(),
|
|
61665
|
-
/** Suggested decimal places for numeric display. Populated live from HA
|
|
61666
|
-
* `attributes.suggested_display_precision`, or derived from `step` when the
|
|
61667
|
-
* HA attribute is absent. Meaningful for `kind === 'numeric'`; absent for
|
|
61668
|
-
* other kinds. Falls back to auto-formatting when absent. */
|
|
61669
|
-
precision: number().int().min(0).max(10).optional(),
|
|
61670
|
-
/** Date-picker granularity for `kind === 'datetime'`. 'date' → date-only,
|
|
61671
|
-
* 'time' → time-only, 'datetime' → full timestamp. Absent for other kinds
|
|
61672
|
-
* (UI defaults to 'datetime'). Derived live from the device's HA domain
|
|
61673
|
-
* (date.* / time.* / datetime.*) or, for input_datetime, from the entity's
|
|
61674
|
-
* `has_date`/`has_time` attributes on each push. */
|
|
61675
|
-
format: _enum([
|
|
61676
|
-
"date",
|
|
61677
|
-
"time",
|
|
61678
|
-
"datetime"
|
|
61679
|
-
]).optional()
|
|
62058
|
+
/** Minimum allowed value, in the device quantity's base unit. */
|
|
62059
|
+
min: number().optional().meta(readingMeta("device")),
|
|
62060
|
+
/** Maximum allowed value, in the device quantity's base unit. */
|
|
62061
|
+
max: number().optional().meta(readingMeta("device")),
|
|
62062
|
+
/** Step increment, in the device quantity's base unit. */
|
|
62063
|
+
step: number().optional().meta(readingMeta("device"))
|
|
61680
62064
|
});
|
|
61681
62065
|
var ControlSetValueInputSchema = discriminatedUnion("kind", [
|
|
61682
62066
|
object({
|
|
@@ -61764,9 +62148,9 @@ var CoverStatusSchema = object({
|
|
|
61764
62148
|
state: CoverStateSchema,
|
|
61765
62149
|
/** 0 = fully closed, 100 = fully open. Null when the device has
|
|
61766
62150
|
* no intermediate position surface. */
|
|
61767
|
-
position: number().min(0).max(100).nullable(),
|
|
62151
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61768
62152
|
/** 0 = closed slats, 100 = open slats. Null when no tilt support. */
|
|
61769
|
-
tiltPosition: number().min(0).max(100).nullable(),
|
|
62153
|
+
tiltPosition: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61770
62154
|
/** Ms epoch when the slice was last updated. */
|
|
61771
62155
|
lastChangedAt: number()
|
|
61772
62156
|
});
|
|
@@ -61869,9 +62253,9 @@ var NormalizedRangeSchema$1 = object({
|
|
|
61869
62253
|
var DayNightStatusSchema = object({
|
|
61870
62254
|
mode: DayNightModeSchema,
|
|
61871
62255
|
/** IR-cut trigger sensitivity, NORMALIZED 0–100 (higher = switches to night sooner). */
|
|
61872
|
-
sensitivity: number().optional(),
|
|
62256
|
+
sensitivity: number().optional().meta(readingMeta("none")),
|
|
61873
62257
|
/** Delay before the IR-cut filter flips, in seconds. */
|
|
61874
|
-
switchDelaySec: number().optional(),
|
|
62258
|
+
switchDelaySec: number().optional().meta(readingMeta("duration")),
|
|
61875
62259
|
lastFetchedAt: number()
|
|
61876
62260
|
});
|
|
61877
62261
|
/**
|
|
@@ -62089,11 +62473,11 @@ var DishwasherStatusSchema = object({
|
|
|
62089
62473
|
/** Feature keys of the programs the appliance currently offers — drives the UI selector. */
|
|
62090
62474
|
availablePrograms: array(string()),
|
|
62091
62475
|
/** Seconds remaining on the active cycle, or null when not running / not known. */
|
|
62092
|
-
remainingSeconds: number().int().nonnegative().nullable(),
|
|
62476
|
+
remainingSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
62093
62477
|
/** Seconds the delayed start is set to (time until the cycle starts), or null. */
|
|
62094
|
-
delayedStartSeconds: number().int().nonnegative().nullable(),
|
|
62478
|
+
delayedStartSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
62095
62479
|
/** Cycle completion 0..100, or null when not applicable. */
|
|
62096
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
62480
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
62097
62481
|
/** True when the door is reported open; null when the door state is not known. */
|
|
62098
62482
|
doorOpen: boolean().nullable(),
|
|
62099
62483
|
/** True when the door is latched (locked) during a cycle; null when not reported. */
|
|
@@ -62117,7 +62501,7 @@ var DishwasherStatusSchema = object({
|
|
|
62117
62501
|
/** True while the machine-care (descaling / cleaning-program) reminder is raised; false when clear; null when not reported. */
|
|
62118
62502
|
machineCareDue: boolean().nullable(),
|
|
62119
62503
|
/** Program runs left before the machine-care reminder is due; null when the appliance does not say. */
|
|
62120
|
-
machineCareRemainingRuns: number().int().nonnegative().nullable(),
|
|
62504
|
+
machineCareRemainingRuns: number().int().nonnegative().nullable().meta(readingMeta("count")),
|
|
62121
62505
|
/** Option states: null when the appliance does not expose the option or has not said. */
|
|
62122
62506
|
halfLoad: boolean().nullable(),
|
|
62123
62507
|
hygienePlus: boolean().nullable(),
|
|
@@ -62132,7 +62516,7 @@ var DishwasherStatusSchema = object({
|
|
|
62132
62516
|
/** Feature keys of the events currently raised (salt low, rinse aid low, program finished, …). */
|
|
62133
62517
|
activeEvents: array(string()),
|
|
62134
62518
|
/** Numeric error code when the appliance reports one; null otherwise. */
|
|
62135
|
-
errorCode: number().nullable(),
|
|
62519
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
62136
62520
|
/** Name of the raised alert-level event while the appliance is in error; null otherwise. */
|
|
62137
62521
|
errorLabel: string().nullable(),
|
|
62138
62522
|
/** Ms epoch of the last value received from the appliance; 0 = never. */
|
|
@@ -62363,7 +62747,7 @@ var DoorbellStatusSchema = object({
|
|
|
62363
62747
|
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
62364
62748
|
lastPressedAt: number().nullable(),
|
|
62365
62749
|
/** Counter since provider start. Resets on reboot. Useful for metrics/debug. */
|
|
62366
|
-
pressCountSinceStart: number()
|
|
62750
|
+
pressCountSinceStart: number().meta(readingMeta("count"))
|
|
62367
62751
|
});
|
|
62368
62752
|
var DoorbellPressEventSchema = object({
|
|
62369
62753
|
deviceId: number(),
|
|
@@ -62428,17 +62812,7 @@ onPressed: {
|
|
|
62428
62812
|
history: "none",
|
|
62429
62813
|
customize: doorbellCustomize
|
|
62430
62814
|
};
|
|
62431
|
-
|
|
62432
|
-
* Enum-state sensor — a string value picked from a finite option set.
|
|
62433
|
-
* Drives HA `sensor` entries with `state_class: enum` (HVAC action
|
|
62434
|
-
* states, weather conditions, contact-source channels, mode strings).
|
|
62435
|
-
* The option set is stable across observations; it is persisted in the
|
|
62436
|
-
* device config blob (via the control slice at adoption) and is NOT
|
|
62437
|
-
* stored in `sourceInfo`.
|
|
62438
|
-
*/
|
|
62439
|
-
/** Locale-render shape for an ISO `value` carried by a `DateTimeSensor`-role
|
|
62440
|
-
* enum sensor: `date` (date-only), `time` (time-only), `datetime` (both). */
|
|
62441
|
-
var EnumSensorDateTimeFormatSchema = _enum([
|
|
62815
|
+
_enum([
|
|
62442
62816
|
"date",
|
|
62443
62817
|
"time",
|
|
62444
62818
|
"datetime"
|
|
@@ -62446,12 +62820,11 @@ var EnumSensorDateTimeFormatSchema = _enum([
|
|
|
62446
62820
|
var EnumSensorStatusSchema = object({
|
|
62447
62821
|
value: string(),
|
|
62448
62822
|
/**
|
|
62449
|
-
* Set
|
|
62450
|
-
* as
|
|
62451
|
-
*
|
|
62452
|
-
* a time-only sensor → `'time'`.
|
|
62823
|
+
* Set when `value` is a timestamp rather than an enum state, so history
|
|
62824
|
+
* does not learn ISO strings as states. The display shape (date / time /
|
|
62825
|
+
* datetime) lives on `SourceInfo.dateTimeShape`, written once at adopt.
|
|
62453
62826
|
*/
|
|
62454
|
-
|
|
62827
|
+
timestamp: boolean().optional(),
|
|
62455
62828
|
/** Ms epoch when the slice was last updated. */
|
|
62456
62829
|
lastFetchedAt: number()
|
|
62457
62830
|
});
|
|
@@ -62478,11 +62851,11 @@ var enumSensorCapability = {
|
|
|
62478
62851
|
* History (D850): the value as an `enum` series (an appliance's program or
|
|
62479
62852
|
* operation state, an HVAC action). The option set is per device, so the
|
|
62480
62853
|
* value list is LEARNED as values are first seen (bounded). A sensor with a
|
|
62481
|
-
* `
|
|
62854
|
+
* `timestamp` carries a clock, not a state, and is not recorded.
|
|
62482
62855
|
*/
|
|
62483
62856
|
history: { fields: { value: {
|
|
62484
62857
|
kind: "enum",
|
|
62485
|
-
skipWhenSet: "
|
|
62858
|
+
skipWhenSet: "timestamp"
|
|
62486
62859
|
} } },
|
|
62487
62860
|
/** Clock fields: written, but excluded from the compare that decides
|
|
62488
62861
|
* whether persisting is worth a SQLite commit. */
|
|
@@ -62502,13 +62875,13 @@ var EventFireSchema = object({
|
|
|
62502
62875
|
deviceId: number(),
|
|
62503
62876
|
eventType: string(),
|
|
62504
62877
|
data: record(string(), unknown()).nullable(),
|
|
62505
|
-
timestamp: number(),
|
|
62506
|
-
seq: number()
|
|
62878
|
+
timestamp: number().meta(readingMeta("none")),
|
|
62879
|
+
seq: number().meta(readingMeta("count"))
|
|
62507
62880
|
});
|
|
62508
62881
|
var EventEmitterStatusSchema = object({
|
|
62509
62882
|
eventTypes: array(string()),
|
|
62510
62883
|
lastEvent: EventFireSchema.nullable(),
|
|
62511
|
-
eventCountSinceStart: number()
|
|
62884
|
+
eventCountSinceStart: number().meta(readingMeta("count"))
|
|
62512
62885
|
});
|
|
62513
62886
|
var eventEmitterCapability = {
|
|
62514
62887
|
name: "event-emitter",
|
|
@@ -62961,10 +63334,10 @@ var FanDirectionSchema = _enum(["forward", "reverse"]);
|
|
|
62961
63334
|
var FanControlStatusSchema = object({
|
|
62962
63335
|
/** Active speed as 0..100 inclusive. Null when the device has no
|
|
62963
63336
|
* speed surface (single-speed fan). */
|
|
62964
|
-
percentage: number().min(0).max(100).nullable(),
|
|
63337
|
+
percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
62965
63338
|
/** Speed granularity the device accepts (HA `percentage_step`, e.g. 25 for
|
|
62966
63339
|
* a 4-speed fan). Absent when unknown — the UI then falls back to step 1. */
|
|
62967
|
-
percentageStep: number().positive().optional(),
|
|
63340
|
+
percentageStep: number().positive().optional().meta(readingMeta("percentage")),
|
|
62968
63341
|
/** Active preset mode (`auto` / `quiet` / `turbo` / vendor-specific)
|
|
62969
63342
|
* — empty string when no preset is active or supported. */
|
|
62970
63343
|
preset: string(),
|
|
@@ -63085,7 +63458,7 @@ var FeatureProbeStatusSchema = object({
|
|
|
63085
63458
|
/** Camera/firmware model string. `null` when the firmware doesn't expose it. */
|
|
63086
63459
|
model: string().nullable(),
|
|
63087
63460
|
/** Channel count for NVR/Hub devices; `1` for standalone cameras; `null` pre-probe. */
|
|
63088
|
-
channelCount: number().nullable(),
|
|
63461
|
+
channelCount: number().nullable().meta(readingMeta("count")),
|
|
63089
63462
|
/**
|
|
63090
63463
|
* Ms epoch of the last SUCCESSFUL probe. `0` before the first probe
|
|
63091
63464
|
* completes — drivers' `getAccessoryChildren()` should treat zero as
|
|
@@ -63208,9 +63581,91 @@ var gasCapability = {
|
|
|
63208
63581
|
* whether persisting is worth a SQLite commit. */
|
|
63209
63582
|
volatileStateFields: ["lastChangedAt"]
|
|
63210
63583
|
};
|
|
63584
|
+
var GroupCommandsSchema = object({
|
|
63585
|
+
/** One row per member that has been commanded. A later command replaces that member's row. */
|
|
63586
|
+
results: array(object({
|
|
63587
|
+
deviceId: number().int().nonnegative(),
|
|
63588
|
+
cap: string().min(1),
|
|
63589
|
+
method: string().min(1),
|
|
63590
|
+
ok: boolean(),
|
|
63591
|
+
error: string().optional(),
|
|
63592
|
+
/** Ms epoch of the attempt. */
|
|
63593
|
+
at: number()
|
|
63594
|
+
})) });
|
|
63595
|
+
var groupCommandsCapability = {
|
|
63596
|
+
name: "group-commands",
|
|
63597
|
+
scope: "device",
|
|
63598
|
+
deviceNative: true,
|
|
63599
|
+
mode: "singleton",
|
|
63600
|
+
deviceTypes: [DeviceType.Switch, DeviceType.Light],
|
|
63601
|
+
methods: {},
|
|
63602
|
+
status: {
|
|
63603
|
+
schema: GroupCommandsSchema,
|
|
63604
|
+
kind: "push"
|
|
63605
|
+
},
|
|
63606
|
+
runtimeState: GroupCommandsSchema,
|
|
63607
|
+
/**
|
|
63608
|
+
* Runtime-state durability: **session** — the last attempt. A restored
|
|
63609
|
+
* failure would outlive the command that caused it.
|
|
63610
|
+
*
|
|
63611
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
63612
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
63613
|
+
*/
|
|
63614
|
+
durability: "session",
|
|
63615
|
+
history: "none"
|
|
63616
|
+
};
|
|
63617
|
+
/**
|
|
63618
|
+
* How many members of a helper group answered (D944). Counts are integers,
|
|
63619
|
+
* not measurements: zero included is a real count, never a stand-in reading.
|
|
63620
|
+
* The reading itself stays on the output capability. History is none — the
|
|
63621
|
+
* series that later statistics read is the output cap's own history block.
|
|
63622
|
+
*/
|
|
63623
|
+
var GroupStatusSchema = object({
|
|
63624
|
+
/** Members whose current value entered the aggregate. */
|
|
63625
|
+
included: number().int().nonnegative().meta(readingMeta("count", {
|
|
63626
|
+
precision: 0,
|
|
63627
|
+
label: "Reporting"
|
|
63628
|
+
})),
|
|
63629
|
+
/** Members left out: offline, unknown, or not a finite reading (D393). */
|
|
63630
|
+
excluded: number().int().nonnegative().meta(readingMeta("count", {
|
|
63631
|
+
precision: 0,
|
|
63632
|
+
label: "Excluded"
|
|
63633
|
+
})),
|
|
63634
|
+
/** `included` + `excluded`. */
|
|
63635
|
+
total: number().int().nonnegative().meta(readingMeta("count", {
|
|
63636
|
+
precision: 0,
|
|
63637
|
+
label: "Members"
|
|
63638
|
+
}))
|
|
63639
|
+
});
|
|
63640
|
+
var groupStatusCapability = {
|
|
63641
|
+
name: "group-status",
|
|
63642
|
+
scope: "device",
|
|
63643
|
+
deviceNative: true,
|
|
63644
|
+
mode: "singleton",
|
|
63645
|
+
deviceTypes: [
|
|
63646
|
+
DeviceType.Sensor,
|
|
63647
|
+
DeviceType.Switch,
|
|
63648
|
+
DeviceType.Light
|
|
63649
|
+
],
|
|
63650
|
+
methods: {},
|
|
63651
|
+
status: {
|
|
63652
|
+
schema: GroupStatusSchema,
|
|
63653
|
+
kind: "push"
|
|
63654
|
+
},
|
|
63655
|
+
runtimeState: GroupStatusSchema,
|
|
63656
|
+
/**
|
|
63657
|
+
* Runtime-state durability: **session** — recomputed from members on the
|
|
63658
|
+
* next source event; a restored count would outlive the readings it named.
|
|
63659
|
+
*
|
|
63660
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
63661
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
63662
|
+
*/
|
|
63663
|
+
durability: "session",
|
|
63664
|
+
history: "none"
|
|
63665
|
+
};
|
|
63211
63666
|
var HeatingValveStatusSchema = object({
|
|
63212
63667
|
/** Radiator valve opening 0 (closed) .. 100 (open). Null = not yet known. */
|
|
63213
|
-
position: number().min(0).max(100).nullable(),
|
|
63668
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
63214
63669
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
63215
63670
|
lastFetchedAt: number()
|
|
63216
63671
|
});
|
|
@@ -63253,9 +63708,9 @@ var HumidifierStatusSchema = object({
|
|
|
63253
63708
|
/** Whether the humidifier is currently on. */
|
|
63254
63709
|
on: boolean(),
|
|
63255
63710
|
/** Current measured relative humidity (0..100). Null when not reported. */
|
|
63256
|
-
currentHumidity: number().min(0).max(100).nullable(),
|
|
63711
|
+
currentHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
63257
63712
|
/** Target relative humidity (0..100). Null when no setpoint surface. */
|
|
63258
|
-
targetHumidity: number().min(0).max(100).nullable(),
|
|
63713
|
+
targetHumidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
63259
63714
|
/** Active mode (`auto` / `normal` / `baby` / vendor). Null when the
|
|
63260
63715
|
* device has no mode surface. */
|
|
63261
63716
|
mode: string().nullable(),
|
|
@@ -63265,9 +63720,9 @@ var HumidifierStatusSchema = object({
|
|
|
63265
63720
|
* `idle` / `off`). Null when the device doesn't report it. */
|
|
63266
63721
|
action: string().nullable(),
|
|
63267
63722
|
/** HA `min_humidity` attribute. Null → UI uses 0. */
|
|
63268
|
-
minHumidity: number().nullable(),
|
|
63723
|
+
minHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
63269
63724
|
/** HA `max_humidity` attribute. Null → UI uses 100. */
|
|
63270
|
-
maxHumidity: number().nullable(),
|
|
63725
|
+
maxHumidity: number().nullable().meta(readingMeta("humidity")),
|
|
63271
63726
|
/** Ms epoch when the slice was last updated. */
|
|
63272
63727
|
lastChangedAt: number()
|
|
63273
63728
|
});
|
|
@@ -63337,22 +63792,13 @@ var humidifierCapability = {
|
|
|
63337
63792
|
* `sourceInfo`.
|
|
63338
63793
|
*/
|
|
63339
63794
|
var HumiditySensorStatusSchema = object({
|
|
63340
|
-
/** Current relative humidity, 0..100. */
|
|
63341
|
-
percent: number().min(0).max(100).meta({
|
|
63342
|
-
|
|
63795
|
+
/** Current relative humidity, 0..100. `null` when the sample was refused (D393). */
|
|
63796
|
+
percent: number().min(0).max(100).nullable().meta(readingMeta("humidity", {
|
|
63797
|
+
precision: 0,
|
|
63343
63798
|
label: "Humidity"
|
|
63344
|
-
}),
|
|
63799
|
+
})),
|
|
63345
63800
|
/** Ms epoch when the slice was last updated. */
|
|
63346
|
-
lastFetchedAt: number()
|
|
63347
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
63348
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
63349
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
63350
|
-
unit: string().optional(),
|
|
63351
|
-
/** Suggested decimal places for numeric display.
|
|
63352
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
63353
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
63354
|
-
* auto-formatting when absent. */
|
|
63355
|
-
precision: number().int().min(0).max(10).optional()
|
|
63801
|
+
lastFetchedAt: number()
|
|
63356
63802
|
});
|
|
63357
63803
|
var humiditySensorCapability = {
|
|
63358
63804
|
name: "humidity-sensor",
|
|
@@ -63383,12 +63829,7 @@ var humiditySensorCapability = {
|
|
|
63383
63829
|
} } },
|
|
63384
63830
|
/** Clock fields: written, but excluded from the compare that decides
|
|
63385
63831
|
* whether persisting is worth a SQLite commit. */
|
|
63386
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
63387
|
-
customize: {
|
|
63388
|
-
version: 1,
|
|
63389
|
-
advanced: "derive",
|
|
63390
|
-
targets: []
|
|
63391
|
-
}
|
|
63832
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
63392
63833
|
};
|
|
63393
63834
|
/**
|
|
63394
63835
|
* Image display cap. Models a single still image exposed by an integration —
|
|
@@ -63409,7 +63850,7 @@ var ImageStatusSchema = object({
|
|
|
63409
63850
|
* entity exposes no `entity_picture` (yet). */
|
|
63410
63851
|
url: string().nullable(),
|
|
63411
63852
|
/** Ms epoch of the upstream last-updated timestamp. Null at cold-start. */
|
|
63412
|
-
lastUpdated: number().nullable()
|
|
63853
|
+
lastUpdated: number().nullable().meta(readingMeta("none"))
|
|
63413
63854
|
});
|
|
63414
63855
|
var imageCapability = {
|
|
63415
63856
|
name: "image",
|
|
@@ -63497,19 +63938,19 @@ var NormalizedRangeSchema = object({
|
|
|
63497
63938
|
*/
|
|
63498
63939
|
var ImageSettingsStatusSchema = object({
|
|
63499
63940
|
/** Normalized 0–100. */
|
|
63500
|
-
brightness: number().optional(),
|
|
63941
|
+
brightness: number().optional().meta(readingMeta("none")),
|
|
63501
63942
|
/** Normalized 0–100. */
|
|
63502
|
-
contrast: number().optional(),
|
|
63943
|
+
contrast: number().optional().meta(readingMeta("none")),
|
|
63503
63944
|
/** Normalized 0–100. */
|
|
63504
|
-
saturation: number().optional(),
|
|
63945
|
+
saturation: number().optional().meta(readingMeta("none")),
|
|
63505
63946
|
/** Normalized 0–100. */
|
|
63506
|
-
sharpness: number().optional(),
|
|
63947
|
+
sharpness: number().optional().meta(readingMeta("none")),
|
|
63507
63948
|
mirror: boolean().optional(),
|
|
63508
63949
|
flip: boolean().optional(),
|
|
63509
63950
|
rotate: ImageRotateSchema.optional(),
|
|
63510
63951
|
whiteBalance: WhiteBalanceModeSchema.optional(),
|
|
63511
63952
|
/** Manual white-balance warmth, NORMALIZED 0–100. Meaningful only when `whiteBalance === 'manual'`. */
|
|
63512
|
-
warmth: number().optional(),
|
|
63953
|
+
warmth: number().optional().meta(readingMeta("none")),
|
|
63513
63954
|
exposureMode: ExposureModeSchema.optional(),
|
|
63514
63955
|
backlightMode: BacklightModeSchema.optional(),
|
|
63515
63956
|
lastFetchedAt: number()
|
|
@@ -63788,10 +64229,10 @@ var IntercomAbilitySchema = object({
|
|
|
63788
64229
|
/** Codecs accepted by firmware, in preference order. Driver-authored strings. */
|
|
63789
64230
|
codecs: array(string()),
|
|
63790
64231
|
/** Sample rate (Hz) the firmware expects. Reolink typical: 16000. */
|
|
63791
|
-
sampleRate: number(),
|
|
64232
|
+
sampleRate: number().meta(readingMeta("none")),
|
|
63792
64233
|
duplex: _enum(["half", "full"]),
|
|
63793
64234
|
/** Max in-flight audio backlog before drop (ms). Server uses this to bound latency. */
|
|
63794
|
-
maxBacklogMs: number()
|
|
64235
|
+
maxBacklogMs: number().meta(readingMeta("duration-ms"))
|
|
63795
64236
|
});
|
|
63796
64237
|
var IntercomStatusSchema = object({
|
|
63797
64238
|
/** True while a talk session is open. */
|
|
@@ -64018,13 +64459,13 @@ var LawnMowerControlStatusSchema = object({
|
|
|
64018
64459
|
activity: LawnMowerActivitySchema,
|
|
64019
64460
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
64020
64461
|
* reading. */
|
|
64021
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
64462
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
64022
64463
|
/** 0..100 mowing-completion percentage of the current task, or null when no
|
|
64023
64464
|
* task is active / progress is unavailable. */
|
|
64024
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
64465
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
64025
64466
|
/** Current device/event code (dynamic — mostly status, sometimes an error),
|
|
64026
64467
|
* or null when unknown. */
|
|
64027
|
-
currentCode: number().nullable(),
|
|
64468
|
+
currentCode: number().nullable().meta(readingMeta("none")),
|
|
64028
64469
|
/** Human label for {@link currentCode}, or null when undecodable. */
|
|
64029
64470
|
currentCodeLabel: string().nullable(),
|
|
64030
64471
|
/** Severity of {@link currentCode}. `error` (and often `warning`) warrants UI
|
|
@@ -64578,7 +65019,7 @@ var MediaPlayerStatusSchema = object({
|
|
|
64578
65019
|
state: MediaPlayerStateSchema,
|
|
64579
65020
|
/** Volume as 0..100 inclusive. Null when the device has no volume
|
|
64580
65021
|
* surface. Pair with `DeviceFeature.MediaPlayerVolume`. */
|
|
64581
|
-
volumeLevel: number().min(0).max(100).nullable(),
|
|
65022
|
+
volumeLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
64582
65023
|
/** Mute toggle distinct from volume=0. Null when no mute surface.
|
|
64583
65024
|
* Pair with `DeviceFeature.MediaPlayerMute`. */
|
|
64584
65025
|
isMuted: boolean().nullable(),
|
|
@@ -64591,10 +65032,10 @@ var MediaPlayerStatusSchema = object({
|
|
|
64591
65032
|
currentMedia: MediaInfoSchema.nullable(),
|
|
64592
65033
|
/** Current playback position in ms. Null when not seekable or
|
|
64593
65034
|
* nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
|
|
64594
|
-
positionMs: number().int().nonnegative().nullable(),
|
|
65035
|
+
positionMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
64595
65036
|
/** Total duration of the current media in ms. Null when unknown
|
|
64596
65037
|
* (live stream) or nothing is playing. */
|
|
64597
|
-
durationMs: number().int().nonnegative().nullable(),
|
|
65038
|
+
durationMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
64598
65039
|
/** Shuffle toggle. Null when no shuffle surface.
|
|
64599
65040
|
* Pair with `DeviceFeature.MediaPlayerShuffle`. */
|
|
64600
65041
|
shuffle: boolean().nullable(),
|
|
@@ -64903,7 +65344,7 @@ var motionCustomize = {
|
|
|
64903
65344
|
eventName: "onMotionChanged"
|
|
64904
65345
|
},
|
|
64905
65346
|
deviceTypes: [DeviceType.Camera],
|
|
64906
|
-
apply: "
|
|
65347
|
+
apply: "add",
|
|
64907
65348
|
applyAuthority: {
|
|
64908
65349
|
kind: "camera-sensors",
|
|
64909
65350
|
timeoutField: "motionCooldownMs"
|
|
@@ -65000,7 +65441,7 @@ var MotionStatusSchema = object({
|
|
|
65000
65441
|
* it, every provider seeded it at boot, and every session left it
|
|
65001
65442
|
* `detected: true` after its detach.
|
|
65002
65443
|
*/
|
|
65003
|
-
autoClearAfterMs: number().nullable()
|
|
65444
|
+
autoClearAfterMs: number().nullable().meta(readingMeta("duration-ms"))
|
|
65004
65445
|
});
|
|
65005
65446
|
/**
|
|
65006
65447
|
* Payload of `motion.onMotionChanged` event + the corresponding bus
|
|
@@ -65037,12 +65478,18 @@ var motionCapability = {
|
|
|
65037
65478
|
methods: {
|
|
65038
65479
|
/**
|
|
65039
65480
|
* Pull the current motion state synchronously. Convenience shortcut
|
|
65040
|
-
* for consumers that don't need the full status object
|
|
65041
|
-
*
|
|
65042
|
-
* `getStatus` once the auto-injected status surface lands in every
|
|
65043
|
-
* consumer.
|
|
65481
|
+
* for consumers that don't need the full status object. A composed
|
|
65482
|
+
* group answers from its slice (D944): unknown throws, it is not off.
|
|
65044
65483
|
*/
|
|
65045
65484
|
isDetected: method(object({ deviceId: number() }), boolean()) },
|
|
65485
|
+
/**
|
|
65486
|
+
* A composed motion group serves `isDetected` from `detected` (D944).
|
|
65487
|
+
* Without this the cap stays uncomposable (`has-commands`).
|
|
65488
|
+
*/
|
|
65489
|
+
composedMethods: { isDetected: {
|
|
65490
|
+
kind: "slice",
|
|
65491
|
+
field: "detected"
|
|
65492
|
+
} },
|
|
65046
65493
|
events: {
|
|
65047
65494
|
/**
|
|
65048
65495
|
* Fires every time the runner transitions a camera between
|
|
@@ -65182,7 +65629,7 @@ var MotionZoneRegionSchema = object({
|
|
|
65182
65629
|
* the grid region(s). */
|
|
65183
65630
|
var MotionZoneStatusSchema = object({
|
|
65184
65631
|
enabled: boolean(),
|
|
65185
|
-
sensitivity: number(),
|
|
65632
|
+
sensitivity: number().meta(readingMeta("none")),
|
|
65186
65633
|
/** Grid region(s). Today exactly one `grid` shape. */
|
|
65187
65634
|
regions: array(MotionZoneRegionSchema),
|
|
65188
65635
|
lastFetchedAt: number()
|
|
@@ -65552,7 +65999,7 @@ var NavigationStatusSchema = object({
|
|
|
65552
65999
|
following: boolean(),
|
|
65553
66000
|
flash: boolean(),
|
|
65554
66001
|
lightMode: NavigationLightModeSchema,
|
|
65555
|
-
lightLevel: number().min(40).max(100),
|
|
66002
|
+
lightLevel: number().min(40).max(100).meta(readingMeta("none")),
|
|
65556
66003
|
/** Ms epoch when the slice was last updated. */
|
|
65557
66004
|
lastChangedAt: number()
|
|
65558
66005
|
});
|
|
@@ -65686,13 +66133,13 @@ var NetworkLinkStatusSchema = object({
|
|
|
65686
66133
|
* one whose reading has not landed must not be drawn at 0 %. Consumers
|
|
65687
66134
|
* SKIP a null rather than coerce it.
|
|
65688
66135
|
*/
|
|
65689
|
-
signalPercent: number().min(0).max(100).nullable(),
|
|
66136
|
+
signalPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
65690
66137
|
/** Raw received signal strength in dBm, when the firmware reports one. */
|
|
65691
|
-
rssiDbm: number().optional(),
|
|
66138
|
+
rssiDbm: number().optional().meta(readingMeta("signal-level")),
|
|
65692
66139
|
/** Network name of a wireless link, when the firmware reports it. */
|
|
65693
66140
|
ssid: string().optional(),
|
|
65694
66141
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
65695
|
-
lastUpdated: number()
|
|
66142
|
+
lastUpdated: number().meta(readingMeta("none"))
|
|
65696
66143
|
});
|
|
65697
66144
|
var networkLinkCapability = {
|
|
65698
66145
|
name: "network-link",
|
|
@@ -66077,7 +66524,7 @@ var NotifierStatusSchema = object({
|
|
|
66077
66524
|
lastError: string().nullable(),
|
|
66078
66525
|
/** Number of deliveries currently buffered server-side (rate-limited
|
|
66079
66526
|
* notifiers may queue). 0 when the provider sends synchronously. */
|
|
66080
|
-
queueDepth: number().int().nonnegative(),
|
|
66527
|
+
queueDepth: number().int().nonnegative().meta(readingMeta("count")),
|
|
66081
66528
|
/** Per-feature capability matrix — authoritative source for the
|
|
66082
66529
|
* compose-form field gating. */
|
|
66083
66530
|
supports: NotifierSupportsSchema
|
|
@@ -66169,11 +66616,9 @@ onSent: { data: object({
|
|
|
66169
66616
|
* cap fits (HA `sensor` whose `device_class` we don't have a typed cap
|
|
66170
66617
|
* for: water flow, distance, weight, frequency, signal strength, …).
|
|
66171
66618
|
*
|
|
66172
|
-
* The
|
|
66173
|
-
*
|
|
66174
|
-
*
|
|
66175
|
-
* The UI reads them directly from the slice — they are the single source
|
|
66176
|
-
* of truth for generic numeric rendering and do NOT live on `sourceInfo`.
|
|
66619
|
+
* The quantity is not on this slice. It is chosen when the device is
|
|
66620
|
+
* adopted and stored once on `SourceInfo.quantity` (D944). `value` is in
|
|
66621
|
+
* that quantity's base unit. `null` is a refused sample (D393).
|
|
66177
66622
|
*
|
|
66178
66623
|
* Prefer the typed alternatives (`temperature-sensor`, `humidity-sensor`,
|
|
66179
66624
|
* `ambient-light-sensor`, `pressure-sensor`, `power-meter`,
|
|
@@ -66182,15 +66627,8 @@ onSent: { data: object({
|
|
|
66182
66627
|
* numeric values land here.
|
|
66183
66628
|
*/
|
|
66184
66629
|
var NumericSensorStatusSchema = object({
|
|
66185
|
-
|
|
66186
|
-
|
|
66187
|
-
* Populated live from the upstream source on each state push.
|
|
66188
|
-
* Absent for unitless sensors. */
|
|
66189
|
-
unit: string().optional(),
|
|
66190
|
-
/** Suggested decimal places for numeric display.
|
|
66191
|
-
* Populated live from the upstream source when provided.
|
|
66192
|
-
* Falls back to auto-formatting when absent. */
|
|
66193
|
-
precision: number().int().min(0).max(10).optional(),
|
|
66630
|
+
/** Reading in the device quantity's base unit. `null` when refused (D393). */
|
|
66631
|
+
value: number().nullable().meta(readingMeta("device")),
|
|
66194
66632
|
/** Ms epoch when the slice was last updated. */
|
|
66195
66633
|
lastFetchedAt: number()
|
|
66196
66634
|
});
|
|
@@ -66214,11 +66652,11 @@ var numericSensorCapability = {
|
|
|
66214
66652
|
*/
|
|
66215
66653
|
durability: "restored",
|
|
66216
66654
|
/**
|
|
66217
|
-
* History (D850): recorded series. The unit is
|
|
66655
|
+
* History (D850): recorded series. The unit is the device quantity's base,
|
|
66656
|
+
* resolved when the series is read — the cap has no single unit.
|
|
66218
66657
|
*/
|
|
66219
66658
|
history: { fields: { value: {
|
|
66220
66659
|
kind: "gauge",
|
|
66221
|
-
unitFrom: "unit",
|
|
66222
66660
|
minIntervalMs: 3e4
|
|
66223
66661
|
} } },
|
|
66224
66662
|
/** Clock fields: written, but excluded from the compare that decides
|
|
@@ -66510,23 +66948,26 @@ var PetFeederStatusSchema = object({
|
|
|
66510
66948
|
/** Food currently in the bowl (grams). Null when the device has not
|
|
66511
66949
|
* reported a reading yet. On dual-hopper models this is the combined
|
|
66512
66950
|
* bowl reading; per-hopper levels live in `food1`/`food2`. */
|
|
66513
|
-
foodLevel: number().nullable(),
|
|
66951
|
+
foodLevel: number().nullable().meta(readingMeta("none")),
|
|
66514
66952
|
/** Hopper-1 food level (grams) on dual-hopper feeders; null on
|
|
66515
66953
|
* single-hopper models. */
|
|
66516
|
-
food1: number().nullable(),
|
|
66954
|
+
food1: number().nullable().meta(readingMeta("none")),
|
|
66517
66955
|
/** Hopper-2 food level (grams) on dual-hopper feeders; null on
|
|
66518
66956
|
* single-hopper models. */
|
|
66519
|
-
food2: number().nullable(),
|
|
66957
|
+
food2: number().nullable().meta(readingMeta("none")),
|
|
66520
66958
|
/** Derived low-food flag — mirrors the HA `food_level` binary_sensor
|
|
66521
66959
|
* (`device_class: problem`, on = low). True when the bowl is empty /
|
|
66522
66960
|
* below the feeder's low threshold. */
|
|
66523
66961
|
lowFood: boolean(),
|
|
66524
66962
|
/** Battery charge 0..100 (%). Null on mains-powered models or when the
|
|
66525
66963
|
* device has no battery reading. */
|
|
66526
|
-
batteryPower: number().min(0).max(100).nullable(),
|
|
66527
|
-
/**
|
|
66528
|
-
*
|
|
66529
|
-
|
|
66964
|
+
batteryPower: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
66965
|
+
/**
|
|
66966
|
+
* Desiccant life remaining, stored in seconds (duration base, D944).
|
|
66967
|
+
* Providers convert from the days the feeder reports. Null when the
|
|
66968
|
+
* model has no desiccant sensor.
|
|
66969
|
+
*/
|
|
66970
|
+
desiccantLeftDays: number().nullable().meta(readingMeta("duration")),
|
|
66530
66971
|
/** True while a feed is in progress. */
|
|
66531
66972
|
feeding: boolean(),
|
|
66532
66973
|
/** Decoded connectivity / power status (HA petkit device-status enum).
|
|
@@ -66537,7 +66978,7 @@ var PetFeederStatusSchema = object({
|
|
|
66537
66978
|
* with `errorCode` for consumers that want the raw integer. */
|
|
66538
66979
|
error: string().nullable(),
|
|
66539
66980
|
/** Raw device error code (0 / null = no error). */
|
|
66540
|
-
errorCode: number().nullable(),
|
|
66981
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
66541
66982
|
/** True for D4S/D4SH dual-hopper hardware — gates the per-hopper UI. */
|
|
66542
66983
|
isDualHopper: boolean(),
|
|
66543
66984
|
/** Child-lock (manual-lock) setting — buttons on the unit are disabled. */
|
|
@@ -66547,7 +66988,7 @@ var PetFeederStatusSchema = object({
|
|
|
66547
66988
|
/** Play a chime when dispensing. */
|
|
66548
66989
|
feedSound: boolean(),
|
|
66549
66990
|
/** Speaker / prompt volume level (device-scaled integer). */
|
|
66550
|
-
volume: number(),
|
|
66991
|
+
volume: number().meta(readingMeta("none")),
|
|
66551
66992
|
/** Ms epoch when the slice was last refreshed from the cloud. */
|
|
66552
66993
|
lastFetchedAt: number()
|
|
66553
66994
|
});
|
|
@@ -66666,7 +67107,7 @@ var petFeederCapability = {
|
|
|
66666
67107
|
},
|
|
66667
67108
|
desiccantLeftDays: {
|
|
66668
67109
|
kind: "gauge",
|
|
66669
|
-
unit: "
|
|
67110
|
+
unit: "s"
|
|
66670
67111
|
}
|
|
66671
67112
|
} }
|
|
66672
67113
|
};
|
|
@@ -67102,36 +67543,19 @@ method(_void(), PlatformCapabilitiesSchema), method(_void(), HardwareInfoSchema)
|
|
|
67102
67543
|
*/
|
|
67103
67544
|
var PowerMeterStatusSchema = object({
|
|
67104
67545
|
/** Instantaneous power draw in watts. */
|
|
67105
|
-
watts: number().optional().meta({
|
|
67106
|
-
unit: "W",
|
|
67107
|
-
label: "Power"
|
|
67108
|
-
}),
|
|
67546
|
+
watts: number().optional().meta(readingMeta("power", { label: "Power" })),
|
|
67109
67547
|
/** Cumulative energy in kilowatt-hours since the meter was reset. */
|
|
67110
|
-
kwhTotal: number().optional().meta({
|
|
67111
|
-
unit: "kWh",
|
|
67112
|
-
label: "Energy"
|
|
67113
|
-
}),
|
|
67548
|
+
kwhTotal: number().optional().meta(readingMeta("energy", { label: "Energy" })),
|
|
67114
67549
|
/** Voltage in volts. */
|
|
67115
|
-
volts: number().optional(),
|
|
67550
|
+
volts: number().optional().meta(readingMeta("voltage")),
|
|
67116
67551
|
/** Current in amperes. */
|
|
67117
|
-
amps: number().optional(),
|
|
67118
|
-
/** Apparent power in volt-amperes
|
|
67119
|
-
va: number().optional(),
|
|
67552
|
+
amps: number().optional().meta(readingMeta("current")),
|
|
67553
|
+
/** Apparent power in volt-amperes. */
|
|
67554
|
+
va: number().optional().meta(readingMeta("apparent-power")),
|
|
67120
67555
|
/** Power factor (0..1) if reported. */
|
|
67121
|
-
powerFactor: number().min(0).max(1).optional(),
|
|
67556
|
+
powerFactor: number().min(0).max(1).optional().meta(readingMeta("ratio")),
|
|
67122
67557
|
/** Ms epoch when the slice was last updated. */
|
|
67123
|
-
lastFetchedAt: number()
|
|
67124
|
-
/** Live display unit of the single metric this slice carries (e.g. HA
|
|
67125
|
-
* `attributes.unit_of_measurement` → 'V' / 'A' / 'W' / 'kW' / 'kWh').
|
|
67126
|
-
* Each upstream `sensor.*` entity surfaces ONE device_class, so one
|
|
67127
|
-
* unit per slice is unambiguous. The UI prefers this over the role's
|
|
67128
|
-
* canonical unit so a 'kW' / 'Wh' feed renders verbatim. */
|
|
67129
|
-
unit: string().optional(),
|
|
67130
|
-
/** Suggested decimal places for numeric display.
|
|
67131
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
67132
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
67133
|
-
* auto-formatting when absent. */
|
|
67134
|
-
precision: number().int().min(0).max(10).optional()
|
|
67558
|
+
lastFetchedAt: number()
|
|
67135
67559
|
});
|
|
67136
67560
|
var powerMeterCapability = {
|
|
67137
67561
|
name: "power-meter",
|
|
@@ -67195,12 +67619,7 @@ var powerMeterCapability = {
|
|
|
67195
67619
|
} },
|
|
67196
67620
|
/** Clock fields: written, but excluded from the compare that decides
|
|
67197
67621
|
* whether persisting is worth a SQLite commit. */
|
|
67198
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
67199
|
-
customize: {
|
|
67200
|
-
version: 1,
|
|
67201
|
-
advanced: "derive",
|
|
67202
|
-
targets: []
|
|
67203
|
-
}
|
|
67622
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
67204
67623
|
};
|
|
67205
67624
|
/**
|
|
67206
67625
|
* Presence cap. Models HA `person.*` and `device_tracker.*` entities
|
|
@@ -67220,11 +67639,11 @@ var powerMeterCapability = {
|
|
|
67220
67639
|
*/
|
|
67221
67640
|
var GpsLocationSchema = object({
|
|
67222
67641
|
/** Latitude in decimal degrees, -90..90. */
|
|
67223
|
-
latitude: number().min(-90).max(90),
|
|
67642
|
+
latitude: number().min(-90).max(90).meta(readingMeta("angle")),
|
|
67224
67643
|
/** Longitude in decimal degrees, -180..180. */
|
|
67225
|
-
longitude: number().min(-180).max(180),
|
|
67644
|
+
longitude: number().min(-180).max(180).meta(readingMeta("angle")),
|
|
67226
67645
|
/** Reported accuracy in meters (lower = better). */
|
|
67227
|
-
accuracyMeters: number().nonnegative()
|
|
67646
|
+
accuracyMeters: number().nonnegative().meta(readingMeta("length"))
|
|
67228
67647
|
});
|
|
67229
67648
|
var PresenceStatusSchema = object({
|
|
67230
67649
|
/** `home` / `not_home` / any user-defined zone name. */
|
|
@@ -67236,7 +67655,7 @@ var PresenceStatusSchema = object({
|
|
|
67236
67655
|
gps: GpsLocationSchema.nullable(),
|
|
67237
67656
|
/** Optional battery level of the tracking device (0..100). Null
|
|
67238
67657
|
* when not reported. */
|
|
67239
|
-
batteryPercent: number().min(0).max(100).nullable(),
|
|
67658
|
+
batteryPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
67240
67659
|
/** Ms epoch when the slice was last updated. */
|
|
67241
67660
|
lastChangedAt: number()
|
|
67242
67661
|
});
|
|
@@ -67286,19 +67705,10 @@ var presenceCapability = {
|
|
|
67286
67705
|
* `sourceInfo`.
|
|
67287
67706
|
*/
|
|
67288
67707
|
var PressureSensorStatusSchema = object({
|
|
67289
|
-
/** Current pressure in hPa. */
|
|
67290
|
-
hpa: number(),
|
|
67708
|
+
/** Current pressure in hPa. `null` when the sample was refused (D393). */
|
|
67709
|
+
hpa: number().nullable().meta(readingMeta("pressure", { precision: 0 })),
|
|
67291
67710
|
/** Ms epoch when the slice was last updated. */
|
|
67292
|
-
lastFetchedAt: number()
|
|
67293
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
67294
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
67295
|
-
* role's canonical unit. Absent → fall back to the canonical unit. */
|
|
67296
|
-
unit: string().optional(),
|
|
67297
|
-
/** Suggested decimal places for numeric display.
|
|
67298
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
67299
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
67300
|
-
* auto-formatting when absent. */
|
|
67301
|
-
precision: number().int().min(0).max(10).optional()
|
|
67711
|
+
lastFetchedAt: number()
|
|
67302
67712
|
});
|
|
67303
67713
|
var pressureSensorCapability = {
|
|
67304
67714
|
name: "pressure-sensor",
|
|
@@ -67712,8 +68122,8 @@ DeviceType.Camera, method(PtzMoveCommandSchema.extend({ deviceId: number() }), _
|
|
|
67712
68122
|
}), _void(), { kind: "mutation" });
|
|
67713
68123
|
var PtzAutotrackSettingsSchema = object({
|
|
67714
68124
|
targetType: string().describe("Vendor target string (people/vehicle/pet); empty = camera default"),
|
|
67715
|
-
stopDelaySeconds: number().int().min(0).max(300),
|
|
67716
|
-
disappearDelaySeconds: number().int().min(0).max(300)
|
|
68125
|
+
stopDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration")),
|
|
68126
|
+
disappearDelaySeconds: number().int().min(0).max(300).meta(readingMeta("duration"))
|
|
67717
68127
|
});
|
|
67718
68128
|
/**
|
|
67719
68129
|
* One option the camera advertises as a valid `targetType`. Drivers
|
|
@@ -67867,7 +68277,7 @@ var RunningStateStatusSchema = object({
|
|
|
67867
68277
|
/** null = unknown — never coerced to false (D393). */
|
|
67868
68278
|
running: boolean().nullable(),
|
|
67869
68279
|
/** Epoch ms the current boolean began; null while `running` is null. */
|
|
67870
|
-
since: number().nullable(),
|
|
68280
|
+
since: number().nullable().meta(readingMeta("none")),
|
|
67871
68281
|
source: RunningStateSourceSchema.meta({ label: "Source" }),
|
|
67872
68282
|
phase: string().nullable(),
|
|
67873
68283
|
/** null until a reading has been published (D393). */
|
|
@@ -67882,7 +68292,6 @@ var RUNNING_DEVICE_TYPES = Object.values(DeviceType);
|
|
|
67882
68292
|
/** Generic Customize target for the running boolean (D936). */
|
|
67883
68293
|
var runningCustomize = {
|
|
67884
68294
|
version: 1,
|
|
67885
|
-
advanced: "derive",
|
|
67886
68295
|
targets: [{
|
|
67887
68296
|
id: "running",
|
|
67888
68297
|
cardinality: "scalar",
|
|
@@ -67902,7 +68311,7 @@ var runningCustomize = {
|
|
|
67902
68311
|
DeviceType.Thermostat,
|
|
67903
68312
|
DeviceType.PetFeeder
|
|
67904
68313
|
],
|
|
67905
|
-
apply: "add
|
|
68314
|
+
apply: "add",
|
|
67906
68315
|
path: "running",
|
|
67907
68316
|
sources: [
|
|
67908
68317
|
{
|
|
@@ -69198,9 +69607,9 @@ var RecordTriggerSchema = _enum([
|
|
|
69198
69607
|
*/
|
|
69199
69608
|
var RecordWindowSchema = object({
|
|
69200
69609
|
trigger: RecordTriggerSchema,
|
|
69201
|
-
day: number().int().min(0).max(6),
|
|
69202
|
-
startMinute: number().int().min(0).max(1439),
|
|
69203
|
-
endMinute: number().int().min(1).max(1440)
|
|
69610
|
+
day: number().int().min(0).max(6).meta(readingMeta("none")),
|
|
69611
|
+
startMinute: number().int().min(0).max(1439).meta(readingMeta("none")),
|
|
69612
|
+
endMinute: number().int().min(1).max(1440).meta(readingMeta("none"))
|
|
69204
69613
|
});
|
|
69205
69614
|
/** Status of one physical volume, as the camera itself describes it. */
|
|
69206
69615
|
var OnboardStorageVolumeSchema = object({
|
|
@@ -69276,10 +69685,10 @@ var RecordingOnboardStatusSchema = object({
|
|
|
69276
69685
|
/** Master "record to the card at all" switch. */
|
|
69277
69686
|
enabled: boolean().nullable(),
|
|
69278
69687
|
overwriteWhenFull: boolean().nullable(),
|
|
69279
|
-
preRecordSec: number().nullable(),
|
|
69280
|
-
postRecordSec: number().nullable(),
|
|
69688
|
+
preRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
69689
|
+
postRecordSec: number().nullable().meta(readingMeta("duration")),
|
|
69281
69690
|
/** Length of one recorded file, in minutes. */
|
|
69282
|
-
segmentMinutes: number().nullable(),
|
|
69691
|
+
segmentMinutes: number().nullable().meta(readingMeta("none")),
|
|
69283
69692
|
/** The primary track's weekly windows, flattened. */
|
|
69284
69693
|
windows: array(RecordWindowSchema),
|
|
69285
69694
|
/**
|
|
@@ -69295,7 +69704,7 @@ var RecordingOnboardStatusSchema = object({
|
|
|
69295
69704
|
* provider reporting a non-zero count also reports the schedule as not
|
|
69296
69705
|
* writable.
|
|
69297
69706
|
*/
|
|
69298
|
-
unreadableWindows: number(),
|
|
69707
|
+
unreadableWindows: number().meta(readingMeta("count")),
|
|
69299
69708
|
/**
|
|
69300
69709
|
* The camera is scheduled to record and has NO usable storage.
|
|
69301
69710
|
*
|
|
@@ -70158,7 +70567,7 @@ var CamStreamDescriptorSchema = object({
|
|
|
70158
70567
|
url: string().optional(),
|
|
70159
70568
|
codec: string().optional(),
|
|
70160
70569
|
resolution: CamStreamResolutionSchema.optional(),
|
|
70161
|
-
fps: number().positive().optional(),
|
|
70570
|
+
fps: number().positive().optional().meta(readingMeta("rate")),
|
|
70162
70571
|
label: string().optional(),
|
|
70163
70572
|
/** Device-level features (e.g. `battery-operated`) — drives broker policy. */
|
|
70164
70573
|
deviceFeatures: array(string()).optional(),
|
|
@@ -70245,18 +70654,18 @@ var StreamProfileSchema = _enum([
|
|
|
70245
70654
|
]);
|
|
70246
70655
|
/** The current encoding config of one stream profile. */
|
|
70247
70656
|
var StreamProfileConfigSchema = object({
|
|
70248
|
-
width: number(),
|
|
70249
|
-
height: number(),
|
|
70657
|
+
width: number().meta(readingMeta("none")),
|
|
70658
|
+
height: number().meta(readingMeta("none")),
|
|
70250
70659
|
codec: _enum(["h264", "h265"]),
|
|
70251
|
-
framerate: number(),
|
|
70252
|
-
bitrate: number(),
|
|
70660
|
+
framerate: number().meta(readingMeta("rate")),
|
|
70661
|
+
bitrate: number().meta(readingMeta("bitrate")),
|
|
70253
70662
|
bitrateMode: _enum(["vbr", "cbr"]).optional(),
|
|
70254
70663
|
encoderProfile: _enum([
|
|
70255
70664
|
"high",
|
|
70256
70665
|
"main",
|
|
70257
70666
|
"baseline"
|
|
70258
70667
|
]).optional(),
|
|
70259
|
-
gop: number().optional(),
|
|
70668
|
+
gop: number().optional().meta(readingMeta("none")),
|
|
70260
70669
|
/**
|
|
70261
70670
|
* Whether THIS profile currently carries an audio track. READ-ONLY here.
|
|
70262
70671
|
*
|
|
@@ -70477,12 +70886,7 @@ var switchCapability = {
|
|
|
70477
70886
|
label: "On",
|
|
70478
70887
|
kind: "boolean"
|
|
70479
70888
|
}
|
|
70480
|
-
}] }
|
|
70481
|
-
customize: {
|
|
70482
|
-
version: 1,
|
|
70483
|
-
advanced: "derive",
|
|
70484
|
-
targets: []
|
|
70485
|
-
}
|
|
70889
|
+
}] }
|
|
70486
70890
|
};
|
|
70487
70891
|
/** C0 controls, DEL and the C1 range: none of them belongs in a name. */
|
|
70488
70892
|
function hasControlCharacter(value) {
|
|
@@ -71065,35 +71469,21 @@ var tamperCapability = {
|
|
|
71065
71469
|
* entries with `device_class: temperature` and any future native
|
|
71066
71470
|
* thermometer.
|
|
71067
71471
|
*
|
|
71068
|
-
*
|
|
71069
|
-
*
|
|
71070
|
-
* (climate-control's `currentTemp`, energy analytics) can compose
|
|
71071
|
-
* without per-source unit fixups. The canonical display unit (`°C`) is
|
|
71072
|
-
* a descriptor constant in the UI (ROLE_DESCRIPTOR), not stored in
|
|
71073
|
-
* `sourceInfo`.
|
|
71472
|
+
* The number is Celsius (D944). Providers convert on ingest. A failed
|
|
71473
|
+
* conversion is `null`, never a guess. Display unit is a read-time preference.
|
|
71074
71474
|
*
|
|
71075
71475
|
* Status `lastFetchedAt` lets staleness-aware consumers detect a
|
|
71076
71476
|
* frozen feed (provider hung) distinct from a "temperature hasn't
|
|
71077
71477
|
* changed" steady state.
|
|
71078
71478
|
*/
|
|
71079
71479
|
var TemperatureSensorStatusSchema = object({
|
|
71080
|
-
/** Current temperature in Celsius. */
|
|
71081
|
-
celsius: number().meta({
|
|
71082
|
-
|
|
71480
|
+
/** Current temperature in Celsius. `null` when the sample was refused (D393). */
|
|
71481
|
+
celsius: number().nullable().meta(readingMeta("temperature", {
|
|
71482
|
+
precision: 1,
|
|
71083
71483
|
label: "Temperature"
|
|
71084
|
-
}),
|
|
71484
|
+
})),
|
|
71085
71485
|
/** Ms epoch when the slice was last updated (push or poll). */
|
|
71086
|
-
lastFetchedAt: number()
|
|
71087
|
-
/** Live display unit from the upstream source (e.g. HA
|
|
71088
|
-
* `attributes.unit_of_measurement`). The UI prefers this over the
|
|
71089
|
-
* role's canonical unit, so a Fahrenheit feed renders '°F' not '°C'.
|
|
71090
|
-
* Absent → the UI falls back to the role's canonical unit. */
|
|
71091
|
-
unit: string().optional(),
|
|
71092
|
-
/** Suggested decimal places for numeric display.
|
|
71093
|
-
* Populated live from the upstream source when provided (e.g. HA
|
|
71094
|
-
* `attributes.suggested_display_precision`). Falls back to
|
|
71095
|
-
* auto-formatting when absent. */
|
|
71096
|
-
precision: number().int().min(0).max(10).optional()
|
|
71486
|
+
lastFetchedAt: number()
|
|
71097
71487
|
});
|
|
71098
71488
|
var temperatureSensorCapability = {
|
|
71099
71489
|
name: "temperature-sensor",
|
|
@@ -71124,12 +71514,7 @@ var temperatureSensorCapability = {
|
|
|
71124
71514
|
} } },
|
|
71125
71515
|
/** Clock fields: written, but excluded from the compare that decides
|
|
71126
71516
|
* whether persisting is worth a SQLite commit. */
|
|
71127
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
71128
|
-
customize: {
|
|
71129
|
-
version: 1,
|
|
71130
|
-
advanced: "derive",
|
|
71131
|
-
targets: []
|
|
71132
|
-
}
|
|
71517
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
71133
71518
|
};
|
|
71134
71519
|
/**
|
|
71135
71520
|
* toast — system-scoped singleton capability that streams toast
|
|
@@ -71412,16 +71797,16 @@ var VacuumControlStatusSchema = object({
|
|
|
71412
71797
|
]),
|
|
71413
71798
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
71414
71799
|
* reading. */
|
|
71415
|
-
batteryLevel: number().min(0).max(100).nullable(),
|
|
71800
|
+
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
71416
71801
|
/** Current fan-speed token (provider-verbatim). Null when unknown or
|
|
71417
71802
|
* the vacuum has no speed control. */
|
|
71418
71803
|
fanSpeed: string().nullable(),
|
|
71419
71804
|
/** Speed tokens the hardware accepts — drives the UI selector. */
|
|
71420
71805
|
availableFanSpeeds: array(string()),
|
|
71421
71806
|
/** 0..100 cleaning-completion percentage of the current task, or null. */
|
|
71422
|
-
progressPercent: number().min(0).max(100).nullable(),
|
|
71807
|
+
progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
71423
71808
|
/** Current error code (0 / null = no error). */
|
|
71424
|
-
errorCode: number().nullable(),
|
|
71809
|
+
errorCode: number().nullable().meta(readingMeta("none")),
|
|
71425
71810
|
/** Human label for {@link errorCode}, or null when none / undecodable. */
|
|
71426
71811
|
errorLabel: string().nullable(),
|
|
71427
71812
|
/** Ms epoch when the slice was last updated. */
|
|
@@ -71499,7 +71884,7 @@ var ValveStatusSchema = object({
|
|
|
71499
71884
|
]),
|
|
71500
71885
|
/** 0 = fully closed, 100 = fully open. Null when the device has no
|
|
71501
71886
|
* intermediate position surface. */
|
|
71502
|
-
position: number().min(0).max(100).nullable(),
|
|
71887
|
+
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
71503
71888
|
/** Ms epoch when the slice was last updated. */
|
|
71504
71889
|
lastChangedAt: number()
|
|
71505
71890
|
});
|
|
@@ -71607,9 +71992,9 @@ var vibrationCapability = {
|
|
|
71607
71992
|
*/
|
|
71608
71993
|
var WaterHeaterStatusSchema = object({
|
|
71609
71994
|
/** Current measured temperature. Null when not reported. */
|
|
71610
|
-
currentTemp: number().nullable(),
|
|
71995
|
+
currentTemp: number().nullable().meta(readingMeta("temperature")),
|
|
71611
71996
|
/** Target temperature setpoint. Null when no setpoint surface. */
|
|
71612
|
-
targetTemp: number().nullable(),
|
|
71997
|
+
targetTemp: number().nullable().meta(readingMeta("temperature")),
|
|
71613
71998
|
/** Active operation mode = HA `state` (`eco` / `electric` / `gas` /
|
|
71614
71999
|
* `heat_pump` / `high_demand` / `performance` / `off`). Null when the
|
|
71615
72000
|
* device reports an unknown state. */
|
|
@@ -71620,9 +72005,9 @@ var WaterHeaterStatusSchema = object({
|
|
|
71620
72005
|
* has no away surface. */
|
|
71621
72006
|
away: boolean().nullable(),
|
|
71622
72007
|
/** HA `min_temp` attribute. Null when not reported. */
|
|
71623
|
-
minTemp: number().nullable(),
|
|
72008
|
+
minTemp: number().nullable().meta(readingMeta("temperature")),
|
|
71624
72009
|
/** HA `max_temp` attribute. Null when not reported. */
|
|
71625
|
-
maxTemp: number().nullable(),
|
|
72010
|
+
maxTemp: number().nullable().meta(readingMeta("temperature")),
|
|
71626
72011
|
/** Ms epoch when the slice was last updated. */
|
|
71627
72012
|
lastChangedAt: number()
|
|
71628
72013
|
});
|
|
@@ -71707,25 +72092,18 @@ var waterHeaterCapability = {
|
|
|
71707
72092
|
* Forecast deferred — current conditions only for v1.
|
|
71708
72093
|
*/
|
|
71709
72094
|
var WeatherStatusSchema = object({
|
|
71710
|
-
/** Verbatim
|
|
71711
|
-
* when no condition has been reported yet. */
|
|
72095
|
+
/** Verbatim condition state (`sunny`, `cloudy`, `rainy`, …). Null when none yet. */
|
|
71712
72096
|
condition: string().nullable(),
|
|
71713
|
-
/** Current temperature in
|
|
71714
|
-
temperature: number().nullable(),
|
|
71715
|
-
/** Temperature unit string (e.g. `°C` / `°F`). Null when not provided. */
|
|
71716
|
-
temperatureUnit: string().nullable(),
|
|
72097
|
+
/** Current temperature in Celsius. Null when not provided or refused. */
|
|
72098
|
+
temperature: number().nullable().meta(readingMeta("temperature", { precision: 1 })),
|
|
71717
72099
|
/** Relative humidity (0..100). Null when not provided. */
|
|
71718
|
-
humidity: number().min(0).max(100).nullable(),
|
|
71719
|
-
/** Barometric pressure in
|
|
71720
|
-
pressure: number().nullable(),
|
|
71721
|
-
/**
|
|
71722
|
-
|
|
71723
|
-
/** Wind speed in the reported unit. Null when not provided. */
|
|
71724
|
-
windSpeed: number().nullable(),
|
|
71725
|
-
/** Wind-speed unit string (e.g. `km/h` / `mph`). Null when not provided. */
|
|
71726
|
-
windSpeedUnit: string().nullable(),
|
|
72100
|
+
humidity: number().min(0).max(100).nullable().meta(readingMeta("humidity")),
|
|
72101
|
+
/** Barometric pressure in hPa. Null when not provided or refused. */
|
|
72102
|
+
pressure: number().nullable().meta(readingMeta("pressure")),
|
|
72103
|
+
/** Wind speed in metres per second. Null when not provided or refused. */
|
|
72104
|
+
windSpeed: number().nullable().meta(readingMeta("speed")),
|
|
71727
72105
|
/** Wind bearing in degrees (0..360, meteorological). Null when not provided. */
|
|
71728
|
-
windBearing: number().nullable(),
|
|
72106
|
+
windBearing: number().nullable().meta(readingMeta("angle")),
|
|
71729
72107
|
/** Ms epoch when the slice was last updated. */
|
|
71730
72108
|
lastFetchedAt: number()
|
|
71731
72109
|
});
|
|
@@ -71753,12 +72131,12 @@ var weatherCapability = {
|
|
|
71753
72131
|
*/
|
|
71754
72132
|
durability: "session",
|
|
71755
72133
|
/**
|
|
71756
|
-
* History (D850): recorded series.
|
|
72134
|
+
* History (D850): recorded series. Numbers are the quantity base (D944).
|
|
71757
72135
|
*/
|
|
71758
72136
|
history: { fields: {
|
|
71759
72137
|
temperature: {
|
|
71760
72138
|
kind: "gauge",
|
|
71761
|
-
|
|
72139
|
+
unit: "°C",
|
|
71762
72140
|
deadband: .2
|
|
71763
72141
|
},
|
|
71764
72142
|
humidity: {
|
|
@@ -71768,12 +72146,12 @@ var weatherCapability = {
|
|
|
71768
72146
|
},
|
|
71769
72147
|
pressure: {
|
|
71770
72148
|
kind: "gauge",
|
|
71771
|
-
|
|
72149
|
+
unit: "hPa",
|
|
71772
72150
|
deadband: .5
|
|
71773
72151
|
},
|
|
71774
72152
|
windSpeed: {
|
|
71775
72153
|
kind: "gauge",
|
|
71776
|
-
|
|
72154
|
+
unit: "m/s",
|
|
71777
72155
|
deadband: .5
|
|
71778
72156
|
}
|
|
71779
72157
|
} }
|
|
@@ -73057,6 +73435,8 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
73057
73435
|
featureProbe: featureProbeCapability,
|
|
73058
73436
|
flood: floodCapability,
|
|
73059
73437
|
gas: gasCapability,
|
|
73438
|
+
groupCommands: groupCommandsCapability,
|
|
73439
|
+
groupStatus: groupStatusCapability,
|
|
73060
73440
|
heatingValve: heatingValveCapability,
|
|
73061
73441
|
humidifier: humidifierCapability,
|
|
73062
73442
|
humiditySensor: humiditySensorCapability,
|
|
@@ -73950,6 +74330,13 @@ Object.freeze({
|
|
|
73950
74330
|
access: "view",
|
|
73951
74331
|
role: "admin"
|
|
73952
74332
|
},
|
|
74333
|
+
"addons.getPackageDocs": {
|
|
74334
|
+
capName: "addons",
|
|
74335
|
+
capScope: "system",
|
|
74336
|
+
addonId: null,
|
|
74337
|
+
access: "view",
|
|
74338
|
+
role: "admin"
|
|
74339
|
+
},
|
|
73953
74340
|
"addons.getVersions": {
|
|
73954
74341
|
capName: "addons",
|
|
73955
74342
|
capScope: "system",
|
|
@@ -77058,6 +77445,20 @@ Object.freeze({
|
|
|
77058
77445
|
access: "view",
|
|
77059
77446
|
role: "viewer"
|
|
77060
77447
|
},
|
|
77448
|
+
"groupCommands.getStatus": {
|
|
77449
|
+
capName: "group-commands",
|
|
77450
|
+
capScope: "device",
|
|
77451
|
+
addonId: null,
|
|
77452
|
+
access: "view",
|
|
77453
|
+
role: "viewer"
|
|
77454
|
+
},
|
|
77455
|
+
"groupStatus.getStatus": {
|
|
77456
|
+
capName: "group-status",
|
|
77457
|
+
capScope: "device",
|
|
77458
|
+
addonId: null,
|
|
77459
|
+
access: "view",
|
|
77460
|
+
role: "viewer"
|
|
77461
|
+
},
|
|
77061
77462
|
"heatingValve.getStatus": {
|
|
77062
77463
|
capName: "heating-valve",
|
|
77063
77464
|
capScope: "device",
|
|
@@ -86880,6 +87281,37 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
86880
87281
|
icon: "flame"
|
|
86881
87282
|
}]
|
|
86882
87283
|
},
|
|
87284
|
+
"group-commands": {
|
|
87285
|
+
scope: "device",
|
|
87286
|
+
noun: t("Group command", "Comando di gruppo")
|
|
87287
|
+
},
|
|
87288
|
+
"group-status": {
|
|
87289
|
+
scope: "device",
|
|
87290
|
+
noun: t("Group", "Gruppo"),
|
|
87291
|
+
state: [
|
|
87292
|
+
{
|
|
87293
|
+
kind: "numeric",
|
|
87294
|
+
field: "included",
|
|
87295
|
+
quantity: t("the members reporting", "i membri che rispondono"),
|
|
87296
|
+
label: t("Reporting", "Rispondono"),
|
|
87297
|
+
icon: "users"
|
|
87298
|
+
},
|
|
87299
|
+
{
|
|
87300
|
+
kind: "numeric",
|
|
87301
|
+
field: "excluded",
|
|
87302
|
+
quantity: t("the members left out", "i membri esclusi"),
|
|
87303
|
+
label: t("Excluded", "Esclusi"),
|
|
87304
|
+
icon: "users"
|
|
87305
|
+
},
|
|
87306
|
+
{
|
|
87307
|
+
kind: "numeric",
|
|
87308
|
+
field: "total",
|
|
87309
|
+
quantity: t("the member count", "il numero di membri"),
|
|
87310
|
+
label: t("Members", "Membri"),
|
|
87311
|
+
icon: "sigma"
|
|
87312
|
+
}
|
|
87313
|
+
]
|
|
87314
|
+
},
|
|
86883
87315
|
"humidity-sensor": {
|
|
86884
87316
|
scope: "device",
|
|
86885
87317
|
noun: t("Humidity", "Umidità"),
|
|
@@ -86913,7 +87345,6 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
86913
87345
|
field: "value",
|
|
86914
87346
|
quantity: t("the reading", "il valore"),
|
|
86915
87347
|
label: t("Reading", "Valore"),
|
|
86916
|
-
unitField: "unit",
|
|
86917
87348
|
icon: "gauge"
|
|
86918
87349
|
}]
|
|
86919
87350
|
},
|
|
@@ -87049,7 +87480,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
87049
87480
|
field: "temperature",
|
|
87050
87481
|
quantity: t("the outdoor temperature", "la temperatura esterna"),
|
|
87051
87482
|
label: t("Temperature", "Temperatura"),
|
|
87052
|
-
|
|
87483
|
+
unit: "°C",
|
|
87053
87484
|
icon: "thermometer"
|
|
87054
87485
|
},
|
|
87055
87486
|
{
|
|
@@ -87065,7 +87496,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
87065
87496
|
field: "windSpeed",
|
|
87066
87497
|
quantity: t("the wind speed", "la velocità del vento"),
|
|
87067
87498
|
label: t("Wind", "Vento"),
|
|
87068
|
-
|
|
87499
|
+
unit: "m/s",
|
|
87069
87500
|
icon: "wind"
|
|
87070
87501
|
},
|
|
87071
87502
|
{
|
|
@@ -87073,7 +87504,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
87073
87504
|
field: "pressure",
|
|
87074
87505
|
quantity: t("the air pressure", "la pressione atmosferica"),
|
|
87075
87506
|
label: t("Pressure", "Pressione"),
|
|
87076
|
-
|
|
87507
|
+
unit: "hPa",
|
|
87077
87508
|
icon: "gauge"
|
|
87078
87509
|
}
|
|
87079
87510
|
]
|
|
@@ -88346,6 +88777,16 @@ Object.freeze({
|
|
|
88346
88777
|
form: "single",
|
|
88347
88778
|
optional: false
|
|
88348
88779
|
}],
|
|
88780
|
+
"groupCommands.getStatus": [{
|
|
88781
|
+
name: "deviceId",
|
|
88782
|
+
form: "single",
|
|
88783
|
+
optional: false
|
|
88784
|
+
}],
|
|
88785
|
+
"groupStatus.getStatus": [{
|
|
88786
|
+
name: "deviceId",
|
|
88787
|
+
form: "single",
|
|
88788
|
+
optional: false
|
|
88789
|
+
}],
|
|
88349
88790
|
"heatingValve.getStatus": [{
|
|
88350
88791
|
name: "deviceId",
|
|
88351
88792
|
form: "single",
|
|
@@ -90491,8 +90932,8 @@ var NC_SYSTEM_EVENT_FILTER_KEYS = [
|
|
|
90491
90932
|
function systemEventFilterApplies(kind, filter) {
|
|
90492
90933
|
if (LEGACY_KINDS_WITHOUT_FILTERS.has(kind)) return false;
|
|
90493
90934
|
switch (filter) {
|
|
90494
|
-
case "deviceIds": return kind.startsWith("device-") || kind.startsWith("stream-") || kind === "detection-blind" || kind.startsWith("motion-") || kind.startsWith("recording-") || kind === "alarm-triggered";
|
|
90495
|
-
case "deviceTypes": return kind.startsWith("device-") || kind === "detection-blind" || kind.startsWith("motion-");
|
|
90935
|
+
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";
|
|
90936
|
+
case "deviceTypes": return kind.startsWith("device-") || kind === "detection-blind" || kind.startsWith("motion-") || kind.startsWith("package-llm-");
|
|
90496
90937
|
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-");
|
|
90497
90938
|
case "packageNames": return kind.endsWith("update-available") || kind === "addon-updated" || kind === "node-updating" || kind === "server-updated";
|
|
90498
90939
|
case "consumableLowPercent": return NC_CONSUMABLE_SYSTEM_EVENT_KINDS.includes(kind);
|
|
@@ -90536,6 +90977,8 @@ var NC_SYSTEM_EVENT_FAMILY = {
|
|
|
90536
90977
|
"detection-blind": "device-events",
|
|
90537
90978
|
"motion-noisy": "device-events",
|
|
90538
90979
|
"motion-calm": "device-events",
|
|
90980
|
+
"package-llm-silent": "device-events",
|
|
90981
|
+
"package-llm-answered": "device-events",
|
|
90539
90982
|
"recording-stalled": "device-events",
|
|
90540
90983
|
"recording-healthy": "device-events",
|
|
90541
90984
|
"recording-degraded": "device-events",
|
|
@@ -90637,6 +91080,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
|
|
|
90637
91080
|
label: "Motion without a subject",
|
|
90638
91081
|
kinds: ["motion-noisy", "motion-calm"]
|
|
90639
91082
|
},
|
|
91083
|
+
{
|
|
91084
|
+
id: "package-llm",
|
|
91085
|
+
family: "device-events",
|
|
91086
|
+
label: "Package confirm",
|
|
91087
|
+
kinds: ["package-llm-silent", "package-llm-answered"]
|
|
91088
|
+
},
|
|
90640
91089
|
{
|
|
90641
91090
|
id: "recording",
|
|
90642
91091
|
family: "device-events",
|
|
@@ -92069,6 +92518,8 @@ var DEVICE_EVENTS = [
|
|
|
92069
92518
|
"detection-blind",
|
|
92070
92519
|
"motion-noisy",
|
|
92071
92520
|
"motion-calm",
|
|
92521
|
+
"package-llm-silent",
|
|
92522
|
+
"package-llm-answered",
|
|
92072
92523
|
"recording-stalled",
|
|
92073
92524
|
"recording-healthy",
|
|
92074
92525
|
"recording-degraded",
|
|
@@ -92672,7 +93123,8 @@ var NC_TEMPLATE_VARS = [
|
|
|
92672
93123
|
systemEventKinds: [
|
|
92673
93124
|
"recording-degraded",
|
|
92674
93125
|
...DEVICE_ATTENTION,
|
|
92675
|
-
...ALERT_EPISODE
|
|
93126
|
+
...ALERT_EPISODE,
|
|
93127
|
+
"package-llm-silent"
|
|
92676
93128
|
]
|
|
92677
93129
|
},
|
|
92678
93130
|
{
|
|
@@ -92765,7 +93217,8 @@ var NC_TEMPLATE_VARS = [
|
|
|
92765
93217
|
systemEventKinds: [
|
|
92766
93218
|
"storage-location-low",
|
|
92767
93219
|
"storage-location-critical",
|
|
92768
|
-
"storage-location-ok"
|
|
93220
|
+
"storage-location-ok",
|
|
93221
|
+
"package-llm-silent"
|
|
92769
93222
|
]
|
|
92770
93223
|
},
|
|
92771
93224
|
{
|
|
@@ -93176,7 +93629,9 @@ var NC_TEMPLATE_HELD_BACK_SYSTEM_EVENT_KINDS = [
|
|
|
93176
93629
|
"device-attention-required",
|
|
93177
93630
|
"device-attention-resolved",
|
|
93178
93631
|
"rule-broken",
|
|
93179
|
-
"rule-repaired"
|
|
93632
|
+
"rule-repaired",
|
|
93633
|
+
"package-llm-silent",
|
|
93634
|
+
"package-llm-answered"
|
|
93180
93635
|
];
|
|
93181
93636
|
/**
|
|
93182
93637
|
* The catalog as `getTemplateCatalog` SERVES it: every descriptor, with the
|
|
@@ -93336,6 +93791,15 @@ var CLASS_BY_KIND = new Map([
|
|
|
93336
93791
|
snapshotLabel: "Cameras with constant motion now",
|
|
93337
93792
|
snapshotSection: null
|
|
93338
93793
|
},
|
|
93794
|
+
{
|
|
93795
|
+
id: "package-llm-confirm",
|
|
93796
|
+
family: "device-events",
|
|
93797
|
+
label: "Package confirm (not answering / answering again)",
|
|
93798
|
+
bad: ["package-llm-silent"],
|
|
93799
|
+
recovery: ["package-llm-answered"],
|
|
93800
|
+
snapshotLabel: "Cameras whose package confirm is not answering",
|
|
93801
|
+
snapshotSection: null
|
|
93802
|
+
},
|
|
93339
93803
|
{
|
|
93340
93804
|
id: "recording-health",
|
|
93341
93805
|
family: "device-events",
|