@camstack/addon-provider-unifi 0.2.149 → 0.2.150
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/addon.js +843 -241
- package/dist/addon.mjs +843 -241
- package/package.json +1 -1
package/dist/addon.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//#region ../types/dist/event-category-
|
|
1
|
+
//#region ../types/dist/event-category-DmZDPDf_.mjs
|
|
2
2
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
3
3
|
EventCategory["SystemBoot"] = "system.boot";
|
|
4
4
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -625,7 +625,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
625
625
|
* (a track was promoted to a stationary-registry entry) or departs (the
|
|
626
626
|
* object moved / was removed). Telemetry (D8): lossy, drives a UI refresh of
|
|
627
627
|
* the dedicated "Stationary" section — never the live event feed. Payload:
|
|
628
|
-
* `{ deviceId, entryId, className, phase:'appeared'|'departed', timestamp }`.
|
|
628
|
+
* `{ deviceId, entryId, className, phase:'appeared'|'departed', timestamp, observedAt, zones }`.
|
|
629
629
|
*/
|
|
630
630
|
EventCategory["PipelineAnalyticsStationaryChanged"] = "pipeline-analytics.stationary-changed";
|
|
631
631
|
/**
|
|
@@ -763,6 +763,11 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
763
763
|
*/
|
|
764
764
|
EventCategory["AccessoriesChanged"] = "accessories.onAccessoriesChanged";
|
|
765
765
|
/**
|
|
766
|
+
* An action run started or ended. Emitted by the `actions` surface.
|
|
767
|
+
* Payload: `ActionRunChanged` (`{ actionId, runId, isRunning, outcome?, lastRunAt, lastError }`).
|
|
768
|
+
*/
|
|
769
|
+
EventCategory["ActionsRunChanged"] = "actions.onRunChanged";
|
|
770
|
+
/**
|
|
766
771
|
* Progress update from a running model conversion job.
|
|
767
772
|
* Payload: `{ kind: 'model-convert', phase, sessionId?, pct?, detail? }`.
|
|
768
773
|
* Emitted by `addon-model-studio` on the converting node.
|
|
@@ -5441,7 +5446,7 @@ var ZodIssueCode = {
|
|
|
5441
5446
|
var ZodFirstPartyTypeKind;
|
|
5442
5447
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5443
5448
|
//#endregion
|
|
5444
|
-
//#region ../types/dist/sleep
|
|
5449
|
+
//#region ../types/dist/sleep-Crlmu_tO.mjs
|
|
5445
5450
|
/**
|
|
5446
5451
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5447
5452
|
* window to float samples (D455).
|
|
@@ -8561,6 +8566,8 @@ Object.freeze({ "doorbell": "lastPressedAt" });
|
|
|
8561
8566
|
/** Every capability name, so addon code can check a name without the schema graph. */
|
|
8562
8567
|
var CAP_NAMES = Object.freeze([
|
|
8563
8568
|
"accessories",
|
|
8569
|
+
"action-source",
|
|
8570
|
+
"actions",
|
|
8564
8571
|
"addon-pages",
|
|
8565
8572
|
"addon-pages-source",
|
|
8566
8573
|
"addon-routes",
|
|
@@ -8749,11 +8756,11 @@ var CAP_NAMES = Object.freeze([
|
|
|
8749
8756
|
Object.freeze({
|
|
8750
8757
|
"air-quality-sensor": [
|
|
8751
8758
|
{
|
|
8752
|
-
"path": "
|
|
8759
|
+
"path": "co2",
|
|
8753
8760
|
"valueType": "number"
|
|
8754
8761
|
},
|
|
8755
8762
|
{
|
|
8756
|
-
"path": "
|
|
8763
|
+
"path": "voc",
|
|
8757
8764
|
"valueType": "number"
|
|
8758
8765
|
},
|
|
8759
8766
|
{
|
|
@@ -8803,7 +8810,7 @@ Object.freeze({
|
|
|
8803
8810
|
}
|
|
8804
8811
|
],
|
|
8805
8812
|
"ambient-light-sensor": [{
|
|
8806
|
-
"path": "
|
|
8813
|
+
"path": "illuminance",
|
|
8807
8814
|
"valueType": "number"
|
|
8808
8815
|
}],
|
|
8809
8816
|
"audio-metrics": [
|
|
@@ -8864,7 +8871,7 @@ Object.freeze({
|
|
|
8864
8871
|
],
|
|
8865
8872
|
"battery": [
|
|
8866
8873
|
{
|
|
8867
|
-
"path": "
|
|
8874
|
+
"path": "level",
|
|
8868
8875
|
"valueType": "number"
|
|
8869
8876
|
},
|
|
8870
8877
|
{
|
|
@@ -8886,7 +8893,7 @@ Object.freeze({
|
|
|
8886
8893
|
"valueType": "number"
|
|
8887
8894
|
},
|
|
8888
8895
|
{
|
|
8889
|
-
"path": "
|
|
8896
|
+
"path": "voltage",
|
|
8890
8897
|
"valueType": "number"
|
|
8891
8898
|
},
|
|
8892
8899
|
{
|
|
@@ -8907,7 +8914,7 @@ Object.freeze({
|
|
|
8907
8914
|
"valueType": "boolean"
|
|
8908
8915
|
}],
|
|
8909
8916
|
"brightness": [{
|
|
8910
|
-
"path": "
|
|
8917
|
+
"path": "level",
|
|
8911
8918
|
"valueType": "number"
|
|
8912
8919
|
}],
|
|
8913
8920
|
"broker": [{
|
|
@@ -9108,7 +9115,7 @@ Object.freeze({
|
|
|
9108
9115
|
"valueType": "number"
|
|
9109
9116
|
},
|
|
9110
9117
|
{
|
|
9111
|
-
"path": "
|
|
9118
|
+
"path": "colorTemperature",
|
|
9112
9119
|
"valueType": "number"
|
|
9113
9120
|
}
|
|
9114
9121
|
],
|
|
@@ -9287,15 +9294,15 @@ Object.freeze({
|
|
|
9287
9294
|
"valueType": "string"
|
|
9288
9295
|
},
|
|
9289
9296
|
{
|
|
9290
|
-
"path": "
|
|
9297
|
+
"path": "remaining",
|
|
9291
9298
|
"valueType": "number"
|
|
9292
9299
|
},
|
|
9293
9300
|
{
|
|
9294
|
-
"path": "
|
|
9301
|
+
"path": "delayedStart",
|
|
9295
9302
|
"valueType": "number"
|
|
9296
9303
|
},
|
|
9297
9304
|
{
|
|
9298
|
-
"path": "
|
|
9305
|
+
"path": "progress",
|
|
9299
9306
|
"valueType": "number"
|
|
9300
9307
|
},
|
|
9301
9308
|
{
|
|
@@ -9409,7 +9416,7 @@ Object.freeze({
|
|
|
9409
9416
|
],
|
|
9410
9417
|
"fan-control": [
|
|
9411
9418
|
{
|
|
9412
|
-
"path": "
|
|
9419
|
+
"path": "speed",
|
|
9413
9420
|
"valueType": "number"
|
|
9414
9421
|
},
|
|
9415
9422
|
{
|
|
@@ -9509,7 +9516,7 @@ Object.freeze({
|
|
|
9509
9516
|
}
|
|
9510
9517
|
],
|
|
9511
9518
|
"humidity-sensor": [{
|
|
9512
|
-
"path": "
|
|
9519
|
+
"path": "humidity",
|
|
9513
9520
|
"valueType": "number"
|
|
9514
9521
|
}],
|
|
9515
9522
|
"image": [{
|
|
@@ -9619,7 +9626,7 @@ Object.freeze({
|
|
|
9619
9626
|
"valueType": "number"
|
|
9620
9627
|
},
|
|
9621
9628
|
{
|
|
9622
|
-
"path": "
|
|
9629
|
+
"path": "progress",
|
|
9623
9630
|
"valueType": "number"
|
|
9624
9631
|
},
|
|
9625
9632
|
{
|
|
@@ -9698,11 +9705,11 @@ Object.freeze({
|
|
|
9698
9705
|
"valueType": "string"
|
|
9699
9706
|
},
|
|
9700
9707
|
{
|
|
9701
|
-
"path": "
|
|
9708
|
+
"path": "position",
|
|
9702
9709
|
"valueType": "number"
|
|
9703
9710
|
},
|
|
9704
9711
|
{
|
|
9705
|
-
"path": "
|
|
9712
|
+
"path": "duration",
|
|
9706
9713
|
"valueType": "number"
|
|
9707
9714
|
},
|
|
9708
9715
|
{
|
|
@@ -9804,11 +9811,11 @@ Object.freeze({
|
|
|
9804
9811
|
]
|
|
9805
9812
|
},
|
|
9806
9813
|
{
|
|
9807
|
-
"path": "
|
|
9814
|
+
"path": "signal",
|
|
9808
9815
|
"valueType": "number"
|
|
9809
9816
|
},
|
|
9810
9817
|
{
|
|
9811
|
-
"path": "
|
|
9818
|
+
"path": "rssi",
|
|
9812
9819
|
"valueType": "number"
|
|
9813
9820
|
},
|
|
9814
9821
|
{
|
|
@@ -9863,6 +9870,18 @@ Object.freeze({
|
|
|
9863
9870
|
"path": "foodLevel",
|
|
9864
9871
|
"valueType": "number"
|
|
9865
9872
|
},
|
|
9873
|
+
{
|
|
9874
|
+
"path": "bowlFood",
|
|
9875
|
+
"valueType": "number"
|
|
9876
|
+
},
|
|
9877
|
+
{
|
|
9878
|
+
"path": "eating",
|
|
9879
|
+
"valueType": "boolean"
|
|
9880
|
+
},
|
|
9881
|
+
{
|
|
9882
|
+
"path": "supportsMarkRefilled",
|
|
9883
|
+
"valueType": "boolean"
|
|
9884
|
+
},
|
|
9866
9885
|
{
|
|
9867
9886
|
"path": "food1",
|
|
9868
9887
|
"valueType": "number"
|
|
@@ -9927,23 +9946,23 @@ Object.freeze({
|
|
|
9927
9946
|
],
|
|
9928
9947
|
"power-meter": [
|
|
9929
9948
|
{
|
|
9930
|
-
"path": "
|
|
9949
|
+
"path": "power",
|
|
9931
9950
|
"valueType": "number"
|
|
9932
9951
|
},
|
|
9933
9952
|
{
|
|
9934
|
-
"path": "
|
|
9953
|
+
"path": "energy",
|
|
9935
9954
|
"valueType": "number"
|
|
9936
9955
|
},
|
|
9937
9956
|
{
|
|
9938
|
-
"path": "
|
|
9957
|
+
"path": "voltage",
|
|
9939
9958
|
"valueType": "number"
|
|
9940
9959
|
},
|
|
9941
9960
|
{
|
|
9942
|
-
"path": "
|
|
9961
|
+
"path": "current",
|
|
9943
9962
|
"valueType": "number"
|
|
9944
9963
|
},
|
|
9945
9964
|
{
|
|
9946
|
-
"path": "
|
|
9965
|
+
"path": "apparentPower",
|
|
9947
9966
|
"valueType": "number"
|
|
9948
9967
|
},
|
|
9949
9968
|
{
|
|
@@ -9971,14 +9990,10 @@ Object.freeze({
|
|
|
9971
9990
|
{
|
|
9972
9991
|
"path": "gps.accuracyMeters",
|
|
9973
9992
|
"valueType": "number"
|
|
9974
|
-
},
|
|
9975
|
-
{
|
|
9976
|
-
"path": "batteryPercent",
|
|
9977
|
-
"valueType": "number"
|
|
9978
9993
|
}
|
|
9979
9994
|
],
|
|
9980
9995
|
"pressure-sensor": [{
|
|
9981
|
-
"path": "
|
|
9996
|
+
"path": "pressure",
|
|
9982
9997
|
"valueType": "number"
|
|
9983
9998
|
}],
|
|
9984
9999
|
"privacy-mask": [{
|
|
@@ -10292,7 +10307,7 @@ Object.freeze({
|
|
|
10292
10307
|
"valueType": "boolean"
|
|
10293
10308
|
}],
|
|
10294
10309
|
"temperature-sensor": [{
|
|
10295
|
-
"path": "
|
|
10310
|
+
"path": "temperature",
|
|
10296
10311
|
"valueType": "number"
|
|
10297
10312
|
}],
|
|
10298
10313
|
"update": [
|
|
@@ -10340,7 +10355,7 @@ Object.freeze({
|
|
|
10340
10355
|
"valueType": "string"
|
|
10341
10356
|
},
|
|
10342
10357
|
{
|
|
10343
|
-
"path": "
|
|
10358
|
+
"path": "progress",
|
|
10344
10359
|
"valueType": "number"
|
|
10345
10360
|
},
|
|
10346
10361
|
{
|
|
@@ -10839,7 +10854,7 @@ function errMsg(err) {
|
|
|
10839
10854
|
return String(err);
|
|
10840
10855
|
}
|
|
10841
10856
|
//#endregion
|
|
10842
|
-
//#region ../types/dist/composition-
|
|
10857
|
+
//#region ../types/dist/composition-CZImLpOI.mjs
|
|
10843
10858
|
/**
|
|
10844
10859
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
10845
10860
|
*
|
|
@@ -15359,6 +15374,14 @@ var AutomationConditionLeafSchema = object({
|
|
|
15359
15374
|
array(union([string(), number()]))
|
|
15360
15375
|
])
|
|
15361
15376
|
});
|
|
15377
|
+
var AutomationConditionStationaryPresentSchema = object({
|
|
15378
|
+
kind: literal("stationary-present"),
|
|
15379
|
+
deviceId: number().int().nonnegative(),
|
|
15380
|
+
/** Class names; a macro class matches every raw class that maps to it. */
|
|
15381
|
+
classes: array(string().min(1)).min(1).optional(),
|
|
15382
|
+
/** The parked object must be in at least one of these zones. */
|
|
15383
|
+
zones: array(string().min(1)).min(1).optional()
|
|
15384
|
+
});
|
|
15362
15385
|
/**
|
|
15363
15386
|
* The expression leaf, declared as a plain object rather than an intersection
|
|
15364
15387
|
* with {@link ExpressionSourceSchema}: a discriminated union has to be able to
|
|
@@ -15392,7 +15415,8 @@ var AutomationConditionSchema = lazy(() => discriminatedUnion("kind", [
|
|
|
15392
15415
|
child: AutomationConditionSchema
|
|
15393
15416
|
}),
|
|
15394
15417
|
AutomationConditionLeafSchema,
|
|
15395
|
-
AutomationConditionExpressionSchema
|
|
15418
|
+
AutomationConditionExpressionSchema,
|
|
15419
|
+
AutomationConditionStationaryPresentSchema
|
|
15396
15420
|
]));
|
|
15397
15421
|
/**
|
|
15398
15422
|
* What starts a run.
|
|
@@ -15433,7 +15457,34 @@ var AutomationTriggerSchema = discriminatedUnion("kind", [
|
|
|
15433
15457
|
kind: literal("schedule"),
|
|
15434
15458
|
cron: string().min(1).max(120)
|
|
15435
15459
|
}),
|
|
15436
|
-
object({ kind: literal("manual") })
|
|
15460
|
+
object({ kind: literal("manual") }),
|
|
15461
|
+
object({
|
|
15462
|
+
kind: literal("detection"),
|
|
15463
|
+
/** Class names. A macro class (`animal`, `vehicle`, `person`, `package`)
|
|
15464
|
+
* matches every raw class that maps to it; any other name matches
|
|
15465
|
+
* exactly. */
|
|
15466
|
+
classes: array(string().min(1)).min(1),
|
|
15467
|
+
deviceIds: array(number().int().nonnegative()).min(1),
|
|
15468
|
+
/** The track must have visited at least one of these zones. */
|
|
15469
|
+
zones: array(string().min(1)).min(1).optional(),
|
|
15470
|
+
/** Best-so-far confidence the track must reach. */
|
|
15471
|
+
minScore: number().min(0).max(1).optional()
|
|
15472
|
+
}),
|
|
15473
|
+
object({
|
|
15474
|
+
kind: literal("stationary"),
|
|
15475
|
+
deviceIds: array(number().int().nonnegative()).min(1),
|
|
15476
|
+
/** Class names; a macro class matches like the detection trigger. */
|
|
15477
|
+
classes: array(string().min(1)).min(1).optional(),
|
|
15478
|
+
/** The parked object must be in at least one of these zones. */
|
|
15479
|
+
zones: array(string().min(1)).min(1).optional(),
|
|
15480
|
+
/** `appeared`: it became parked. `departed`: the registry retired it.
|
|
15481
|
+
* The vocabulary of `PipelineAnalyticsStationaryChanged`. */
|
|
15482
|
+
phase: _enum(["appeared", "departed"])
|
|
15483
|
+
}),
|
|
15484
|
+
object({
|
|
15485
|
+
kind: literal("interval"),
|
|
15486
|
+
minutes: number().int().min(1).max(1440)
|
|
15487
|
+
})
|
|
15437
15488
|
]);
|
|
15438
15489
|
/**
|
|
15439
15490
|
* One action step.
|
|
@@ -15453,28 +15504,47 @@ var AutomationTriggerSchema = discriminatedUnion("kind", [
|
|
|
15453
15504
|
* is called. The runner still receives a number and is untouched; the
|
|
15454
15505
|
* resolution is the recipe's job, not the runner's.
|
|
15455
15506
|
*/
|
|
15507
|
+
var AutomationWaitStepSchema = object({
|
|
15508
|
+
kind: literal("wait"),
|
|
15509
|
+
seconds: number().min(0).max(300)
|
|
15510
|
+
});
|
|
15511
|
+
var AutomationCapStepSchema = object({
|
|
15512
|
+
kind: literal("cap"),
|
|
15513
|
+
/**
|
|
15514
|
+
* One device, several same-family devices (locks / climate family / …),
|
|
15515
|
+
* or `{ $var }` for the device that triggered the run. An array is
|
|
15516
|
+
* fan-out at codegen — each id gets the same cap.method call.
|
|
15517
|
+
*/
|
|
15518
|
+
deviceId: union([
|
|
15519
|
+
number().int(),
|
|
15520
|
+
array(number().int()).min(1),
|
|
15521
|
+
object({ $var: string().min(1) })
|
|
15522
|
+
]),
|
|
15523
|
+
cap: string().min(1),
|
|
15524
|
+
method: string().min(1),
|
|
15525
|
+
/** Values may carry `{{vars.x}}` slots, or be exactly `{ $var: 'name' }`, which
|
|
15526
|
+
* SUBSTITUTE and do not evaluate (§3.2.3). Anything beyond substitution is
|
|
15527
|
+
* the expression leaf. */
|
|
15528
|
+
args: record(string(), unknown()).optional()
|
|
15529
|
+
});
|
|
15530
|
+
/**
|
|
15531
|
+
* The steps an internal Action may contain: cap and wait, and nothing that can
|
|
15532
|
+
* call back into an Action — so an Action can never reach itself (no cycles).
|
|
15533
|
+
*/
|
|
15534
|
+
var ActionStepSchema = discriminatedUnion("kind", [AutomationWaitStepSchema, AutomationCapStepSchema]);
|
|
15456
15535
|
var AutomationActionSchema = discriminatedUnion("kind", [
|
|
15536
|
+
AutomationWaitStepSchema,
|
|
15537
|
+
AutomationCapStepSchema,
|
|
15457
15538
|
object({
|
|
15458
|
-
kind: literal("
|
|
15459
|
-
|
|
15460
|
-
|
|
15461
|
-
|
|
15462
|
-
|
|
15463
|
-
|
|
15464
|
-
|
|
15465
|
-
|
|
15466
|
-
|
|
15467
|
-
*/
|
|
15468
|
-
deviceId: union([
|
|
15469
|
-
number().int(),
|
|
15470
|
-
array(number().int()).min(1),
|
|
15471
|
-
object({ $var: string().min(1) })
|
|
15472
|
-
]),
|
|
15473
|
-
cap: string().min(1),
|
|
15474
|
-
method: string().min(1),
|
|
15475
|
-
/** Values may carry `{{vars.x}}` slots, which SUBSTITUTE and do not
|
|
15476
|
-
* evaluate (§3.2.3). Anything beyond substitution is the expression leaf. */
|
|
15477
|
-
args: record(string(), unknown()).optional()
|
|
15539
|
+
kind: literal("action"),
|
|
15540
|
+
/** An entry of the `actions` surface (`internal:<uuid>` or `<addonId>:<localId>`). */
|
|
15541
|
+
actionId: string().min(1),
|
|
15542
|
+
/** Values for the action's declared variables; the others take their default. */
|
|
15543
|
+
variables: record(string(), union([
|
|
15544
|
+
string(),
|
|
15545
|
+
number(),
|
|
15546
|
+
boolean()
|
|
15547
|
+
])).optional()
|
|
15478
15548
|
}),
|
|
15479
15549
|
object({
|
|
15480
15550
|
kind: literal("code"),
|
|
@@ -15483,10 +15553,357 @@ var AutomationActionSchema = discriminatedUnion("kind", [
|
|
|
15483
15553
|
code: string().min(1).max(2e4)
|
|
15484
15554
|
})
|
|
15485
15555
|
]);
|
|
15556
|
+
/**
|
|
15557
|
+
* How a trigger that arrives while the automation is busy (or cooling down) is
|
|
15558
|
+
* handled. One of the automation's execution modes, never a property of its
|
|
15559
|
+
* actions. Absent means `single`.
|
|
15560
|
+
*
|
|
15561
|
+
* - `single` — drop the trigger while a run is in progress (traced + logged).
|
|
15562
|
+
* - `restart` — abort the run in progress (at its next step boundary), start fresh.
|
|
15563
|
+
* - `queued` — queue up to `max` triggers, drop the rest (traced).
|
|
15564
|
+
* - `parallel` — up to `max` runs at once, drop the rest (traced).
|
|
15565
|
+
* - `cooldown` — `single`, and no new run until `minutes` after the last run
|
|
15566
|
+
* STARTED; persisted across a restart. A manual trigger bypasses only this
|
|
15567
|
+
* wait, never the single/queued limits.
|
|
15568
|
+
*/
|
|
15569
|
+
var AutomationRunModeSchema = discriminatedUnion("mode", [
|
|
15570
|
+
object({ mode: literal("single") }),
|
|
15571
|
+
object({ mode: literal("restart") }),
|
|
15572
|
+
object({
|
|
15573
|
+
mode: literal("queued"),
|
|
15574
|
+
max: number().int().min(1).max(10)
|
|
15575
|
+
}),
|
|
15576
|
+
object({
|
|
15577
|
+
mode: literal("parallel"),
|
|
15578
|
+
max: number().int().min(1).max(10)
|
|
15579
|
+
}),
|
|
15580
|
+
object({
|
|
15581
|
+
mode: literal("cooldown"),
|
|
15582
|
+
minutes: number().int().min(1).max(1440)
|
|
15583
|
+
})
|
|
15584
|
+
]);
|
|
15486
15585
|
var AutomationRecipeSchema = object({
|
|
15487
15586
|
triggers: array(AutomationTriggerSchema),
|
|
15488
15587
|
conditions: AutomationConditionSchema.optional(),
|
|
15489
|
-
actions: array(AutomationActionSchema)
|
|
15588
|
+
actions: array(AutomationActionSchema),
|
|
15589
|
+
runMode: AutomationRunModeSchema.optional(),
|
|
15590
|
+
/** How many run traces the automation keeps (default {@link DEFAULT_TRACE_KEEP}). */
|
|
15591
|
+
keepTraces: number().int().min(1).max(100).optional()
|
|
15592
|
+
});
|
|
15593
|
+
new Set([
|
|
15594
|
+
{
|
|
15595
|
+
id: "person",
|
|
15596
|
+
name: "Person"
|
|
15597
|
+
},
|
|
15598
|
+
{
|
|
15599
|
+
id: "vehicle",
|
|
15600
|
+
name: "Vehicle"
|
|
15601
|
+
},
|
|
15602
|
+
{
|
|
15603
|
+
id: "animal",
|
|
15604
|
+
name: "Animal"
|
|
15605
|
+
},
|
|
15606
|
+
{
|
|
15607
|
+
id: "package",
|
|
15608
|
+
name: "Package"
|
|
15609
|
+
}
|
|
15610
|
+
].map((l) => l.id));
|
|
15611
|
+
var COCO_TO_MACRO = {
|
|
15612
|
+
mapping: {
|
|
15613
|
+
person: "person",
|
|
15614
|
+
bicycle: "vehicle",
|
|
15615
|
+
car: "vehicle",
|
|
15616
|
+
motorcycle: "vehicle",
|
|
15617
|
+
airplane: "vehicle",
|
|
15618
|
+
bus: "vehicle",
|
|
15619
|
+
train: "vehicle",
|
|
15620
|
+
truck: "vehicle",
|
|
15621
|
+
boat: "vehicle",
|
|
15622
|
+
bird: "animal",
|
|
15623
|
+
cat: "animal",
|
|
15624
|
+
dog: "animal",
|
|
15625
|
+
horse: "animal",
|
|
15626
|
+
sheep: "animal",
|
|
15627
|
+
cow: "animal",
|
|
15628
|
+
elephant: "animal",
|
|
15629
|
+
bear: "animal",
|
|
15630
|
+
zebra: "animal",
|
|
15631
|
+
giraffe: "animal",
|
|
15632
|
+
suitcase: "package",
|
|
15633
|
+
backpack: "package",
|
|
15634
|
+
handbag: "package"
|
|
15635
|
+
},
|
|
15636
|
+
preserveOriginal: false
|
|
15637
|
+
};
|
|
15638
|
+
new Set(Object.values(COCO_TO_MACRO.mapping));
|
|
15639
|
+
/**
|
|
15640
|
+
* Run traces — what an automation (or, later, an Action run) DID, node by node,
|
|
15641
|
+
* so the editor can paint every block green or red with its reason.
|
|
15642
|
+
*
|
|
15643
|
+
* A trace is data, not a log: it covers the WHOLE tree — the trigger stage,
|
|
15644
|
+
* every condition node (containers and leaves, including the ones a
|
|
15645
|
+
* short-circuit never reached), the run-mode verdict and every action step —
|
|
15646
|
+
* each addressed by a stable path (`conditions.0.1`, `actions.2`, or `steps.N`
|
|
15647
|
+
* for an Action run). Skipped
|
|
15648
|
+
* evaluations are traced too, and identical consecutive skips collapse into a
|
|
15649
|
+
* repeat count so a trigger that fails every 5 minutes cannot flush real runs.
|
|
15650
|
+
*
|
|
15651
|
+
* {@link AutomationStepTraceSchema} is deliberately free of automation
|
|
15652
|
+
* vocabulary so an Action run records the same step shape.
|
|
15653
|
+
*/
|
|
15654
|
+
/** A value a trace may show: JSON primitives and short lists, nothing deeper. */
|
|
15655
|
+
var TraceValueSchema = union([
|
|
15656
|
+
string(),
|
|
15657
|
+
number(),
|
|
15658
|
+
boolean(),
|
|
15659
|
+
_null(),
|
|
15660
|
+
array(union([string(), number()]))
|
|
15661
|
+
]);
|
|
15662
|
+
var AutomationRunOutcomeSchema = _enum([
|
|
15663
|
+
"ran",
|
|
15664
|
+
"skipped-trigger",
|
|
15665
|
+
"skipped-conditions",
|
|
15666
|
+
"skipped-cooldown",
|
|
15667
|
+
"skipped-overlap",
|
|
15668
|
+
"failed",
|
|
15669
|
+
"aborted"
|
|
15670
|
+
]);
|
|
15671
|
+
/** `not-evaluated` = a short-circuit never reached the node. */
|
|
15672
|
+
var TraceNodeOutcomeSchema = _enum([
|
|
15673
|
+
"pass",
|
|
15674
|
+
"fail",
|
|
15675
|
+
"not-evaluated"
|
|
15676
|
+
]);
|
|
15677
|
+
var AutomationTriggerTraceSchema = object({
|
|
15678
|
+
kind: string().min(1),
|
|
15679
|
+
outcome: _enum(["pass", "fail"]),
|
|
15680
|
+
/** Why an event was rejected ("class person not in [dog]") or what fired. */
|
|
15681
|
+
reason: string(),
|
|
15682
|
+
/** deviceId, className, trackId, score … — only what the trigger exposes. */
|
|
15683
|
+
vars: record(string(), TraceValueSchema)
|
|
15684
|
+
});
|
|
15685
|
+
var AutomationConditionTraceNodeSchema = object({
|
|
15686
|
+
/** `conditions` for the root, `conditions.<i>` for its i-th child, … */
|
|
15687
|
+
path: string().min(1),
|
|
15688
|
+
kind: _enum([
|
|
15689
|
+
"all",
|
|
15690
|
+
"any",
|
|
15691
|
+
"not",
|
|
15692
|
+
"condition",
|
|
15693
|
+
"expression",
|
|
15694
|
+
"stationary-present"
|
|
15695
|
+
]),
|
|
15696
|
+
outcome: TraceNodeOutcomeSchema,
|
|
15697
|
+
reason: string(),
|
|
15698
|
+
deviceId: number().int().optional(),
|
|
15699
|
+
cap: string().optional(),
|
|
15700
|
+
fieldPath: string().optional(),
|
|
15701
|
+
operator: string().optional(),
|
|
15702
|
+
expected: TraceValueSchema.optional(),
|
|
15703
|
+
/** What the mirror held; `null` when it held nothing (unknown). */
|
|
15704
|
+
observed: TraceValueSchema.optional()
|
|
15705
|
+
});
|
|
15706
|
+
var AutomationRunVerdictSchema = object({
|
|
15707
|
+
mode: AutomationRunModeSchema,
|
|
15708
|
+
decision: _enum([
|
|
15709
|
+
"run",
|
|
15710
|
+
"queued",
|
|
15711
|
+
"restart",
|
|
15712
|
+
"drop",
|
|
15713
|
+
"cooldown",
|
|
15714
|
+
"bypass"
|
|
15715
|
+
]),
|
|
15716
|
+
reason: string()
|
|
15717
|
+
});
|
|
15718
|
+
/** One executed (or not-run) step — shared by automations and Action runs. */
|
|
15719
|
+
var AutomationStepTraceSchema = object({
|
|
15720
|
+
/** `actions.<i>` */
|
|
15721
|
+
path: string().min(1),
|
|
15722
|
+
kind: string().min(1),
|
|
15723
|
+
cap: string().optional(),
|
|
15724
|
+
method: string().optional(),
|
|
15725
|
+
deviceId: number().int().optional(),
|
|
15726
|
+
startedAt: number().optional(),
|
|
15727
|
+
endedAt: number().optional(),
|
|
15728
|
+
outcome: _enum([
|
|
15729
|
+
"ok",
|
|
15730
|
+
"error",
|
|
15731
|
+
"not-run"
|
|
15732
|
+
]),
|
|
15733
|
+
message: string().optional()
|
|
15734
|
+
});
|
|
15735
|
+
var AutomationRunTraceSchema = object({
|
|
15736
|
+
runId: string().min(1),
|
|
15737
|
+
startedAt: number(),
|
|
15738
|
+
endedAt: number(),
|
|
15739
|
+
trigger: AutomationTriggerTraceSchema,
|
|
15740
|
+
conditions: array(AutomationConditionTraceNodeSchema),
|
|
15741
|
+
verdict: AutomationRunVerdictSchema.optional(),
|
|
15742
|
+
steps: array(AutomationStepTraceSchema),
|
|
15743
|
+
outcome: AutomationRunOutcomeSchema,
|
|
15744
|
+
/** How many identical consecutive skips this trace stands for (>= 1). */
|
|
15745
|
+
repeat: number().int().min(1),
|
|
15746
|
+
/** When the latest of those repeats happened. */
|
|
15747
|
+
lastAt: number()
|
|
15748
|
+
});
|
|
15749
|
+
/**
|
|
15750
|
+
* What the hub's `runs` ledger holds for one owner (`automation:<blockId>` or
|
|
15751
|
+
* `action:<actionId>`): the cooldown stamp and the trace ring.
|
|
15752
|
+
*/
|
|
15753
|
+
var AutomationStateDocSchema = object({
|
|
15754
|
+
version: literal(1),
|
|
15755
|
+
lastRunStartedAt: number().nullable(),
|
|
15756
|
+
traces: array(AutomationRunTraceSchema)
|
|
15757
|
+
});
|
|
15758
|
+
/**
|
|
15759
|
+
* Actions — named, runnable things an operator (or an automation) can start,
|
|
15760
|
+
* declared as LIST ENTRIES, never as devices.
|
|
15761
|
+
*
|
|
15762
|
+
* An entry is either **internal** (a short list of cap/wait steps kept in the
|
|
15763
|
+
* hub's `actions` record kind) or declared by an addon through the
|
|
15764
|
+
* `action-source` collection (a Home Assistant script, a scene …). The one
|
|
15765
|
+
* surface the UI and automations talk to is the `actions` cap; it keeps no
|
|
15766
|
+
* catalog of its own (D3) — every `list` asks the providers live.
|
|
15767
|
+
*
|
|
15768
|
+
* This file is the data half: the entry schema, the variables an entry may
|
|
15769
|
+
* declare, and the pure resolution of the values a run was given. It holds no
|
|
15770
|
+
* runtime.
|
|
15771
|
+
*/
|
|
15772
|
+
/** What a variable's value is. `select` takes one of `options`. */
|
|
15773
|
+
var ActionVariableTypeSchema = _enum([
|
|
15774
|
+
"string",
|
|
15775
|
+
"number",
|
|
15776
|
+
"boolean",
|
|
15777
|
+
"select"
|
|
15778
|
+
]);
|
|
15779
|
+
var ACTION_VARIABLE_NAME_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
15780
|
+
var ActionVariableValueSchema = union([
|
|
15781
|
+
string(),
|
|
15782
|
+
number(),
|
|
15783
|
+
boolean()
|
|
15784
|
+
]);
|
|
15785
|
+
/**
|
|
15786
|
+
* One declared variable. Steps reference it as `{ $var: 'name' }` (the whole
|
|
15787
|
+
* value) or `{{vars.name}}` (inside a string) in their args.
|
|
15788
|
+
*/
|
|
15789
|
+
var ActionVariableSchema = object({
|
|
15790
|
+
name: string().regex(ACTION_VARIABLE_NAME_RE),
|
|
15791
|
+
label: string().min(1).max(120).optional(),
|
|
15792
|
+
type: ActionVariableTypeSchema,
|
|
15793
|
+
required: boolean().optional(),
|
|
15794
|
+
default: ActionVariableValueSchema.optional(),
|
|
15795
|
+
/** The allowed values of a `select`. */
|
|
15796
|
+
options: array(string().min(1)).min(1).optional()
|
|
15797
|
+
}).superRefine((v, ctx) => {
|
|
15798
|
+
if (v.type === "select" && v.options === void 0) ctx.addIssue({
|
|
15799
|
+
code: "custom",
|
|
15800
|
+
message: "a select variable needs options",
|
|
15801
|
+
path: ["options"]
|
|
15802
|
+
});
|
|
15803
|
+
if (v.default !== void 0 && variableValueError(v, v.default) !== null) ctx.addIssue({
|
|
15804
|
+
code: "custom",
|
|
15805
|
+
message: variableValueError(v, v.default) ?? "invalid default",
|
|
15806
|
+
path: ["default"]
|
|
15807
|
+
});
|
|
15808
|
+
});
|
|
15809
|
+
/** Why `value` is not a legal value for the variable, or null when it is. */
|
|
15810
|
+
function variableValueError(variable, value) {
|
|
15811
|
+
switch (variable.type) {
|
|
15812
|
+
case "string": return typeof value === "string" ? null : `variable "${variable.name}" must be a string`;
|
|
15813
|
+
case "number": return typeof value === "number" && Number.isFinite(value) ? null : `variable "${variable.name}" must be a number`;
|
|
15814
|
+
case "boolean": return typeof value === "boolean" ? null : `variable "${variable.name}" must be true or false`;
|
|
15815
|
+
case "select": return typeof value === "string" && (variable.options ?? []).includes(value) ? null : `variable "${variable.name}" must be one of ${(variable.options ?? []).join(", ")}`;
|
|
15816
|
+
}
|
|
15817
|
+
}
|
|
15818
|
+
var ActionSourceKindSchema = _enum(["internal", "addon"]);
|
|
15819
|
+
function isInternalActionId(actionId) {
|
|
15820
|
+
return actionId.startsWith("internal:") && actionId.length > 9;
|
|
15821
|
+
}
|
|
15822
|
+
/** The addon behind a `<addonId>:<localId>` id, or null for anything else (internal included). */
|
|
15823
|
+
function addonIdOfActionId(actionId) {
|
|
15824
|
+
if (isInternalActionId(actionId)) return null;
|
|
15825
|
+
const at = actionId.indexOf(":");
|
|
15826
|
+
return at > 0 && at < actionId.length - 1 ? actionId.slice(0, at) : null;
|
|
15827
|
+
}
|
|
15828
|
+
var ActionStatusSchema = object({
|
|
15829
|
+
isRunning: boolean(),
|
|
15830
|
+
/** Ms epoch the latest run STARTED; null when it never ran. */
|
|
15831
|
+
lastRunAt: number().nullable(),
|
|
15832
|
+
/** The latest run's failure; null on success or when it never ran. */
|
|
15833
|
+
lastError: string().nullable()
|
|
15834
|
+
});
|
|
15835
|
+
var ActionEntrySchema = object({
|
|
15836
|
+
/** `internal:<uuid>` or `<addonId>:<localId>`. */
|
|
15837
|
+
id: string().min(3),
|
|
15838
|
+
name: string().min(1).max(120),
|
|
15839
|
+
/** The addon that declared it; `core-blocks` for an internal one. */
|
|
15840
|
+
addonId: string().min(1),
|
|
15841
|
+
source: ActionSourceKindSchema,
|
|
15842
|
+
/** An addon-declared entry is edited where it was declared. */
|
|
15843
|
+
readOnly: boolean(),
|
|
15844
|
+
/** Internal only: cap and wait steps. No action-in-action, so no cycles. */
|
|
15845
|
+
steps: array(ActionStepSchema).min(1).max(50).optional(),
|
|
15846
|
+
variables: array(ActionVariableSchema).max(20).optional(),
|
|
15847
|
+
status: ActionStatusSchema
|
|
15848
|
+
}).superRefine((entry, ctx) => {
|
|
15849
|
+
if (entry.source === "internal") {
|
|
15850
|
+
if (!isInternalActionId(entry.id)) ctx.addIssue({
|
|
15851
|
+
code: "custom",
|
|
15852
|
+
message: "an internal action id is internal:<uuid>",
|
|
15853
|
+
path: ["id"]
|
|
15854
|
+
});
|
|
15855
|
+
return;
|
|
15856
|
+
}
|
|
15857
|
+
if (entry.steps !== void 0) ctx.addIssue({
|
|
15858
|
+
code: "custom",
|
|
15859
|
+
message: "only an internal action carries steps",
|
|
15860
|
+
path: ["steps"]
|
|
15861
|
+
});
|
|
15862
|
+
if (!entry.readOnly) ctx.addIssue({
|
|
15863
|
+
code: "custom",
|
|
15864
|
+
message: "an addon action is read-only here",
|
|
15865
|
+
path: ["readOnly"]
|
|
15866
|
+
});
|
|
15867
|
+
if (addonIdOfActionId(entry.id) === null) ctx.addIssue({
|
|
15868
|
+
code: "custom",
|
|
15869
|
+
message: "an addon action id is <addonId>:<localId>",
|
|
15870
|
+
path: ["id"]
|
|
15871
|
+
});
|
|
15872
|
+
});
|
|
15873
|
+
/** What an operator writes for an internal action. */
|
|
15874
|
+
var ActionInputSchema = object({
|
|
15875
|
+
name: string().min(1).max(120),
|
|
15876
|
+
steps: array(ActionStepSchema).min(1).max(50),
|
|
15877
|
+
variables: array(ActionVariableSchema).max(20).optional()
|
|
15878
|
+
});
|
|
15879
|
+
/** Who started a run. Absent = the operator pressed it. */
|
|
15880
|
+
var ActionRunOriginSchema = object({
|
|
15881
|
+
/** The automation block whose step started it. */
|
|
15882
|
+
blockId: string().min(1).optional() });
|
|
15883
|
+
/** `started` = the caller did not ask to wait. */
|
|
15884
|
+
var ActionRunOutcomeSchema = union([AutomationRunOutcomeSchema, literal("started")]);
|
|
15885
|
+
var ActionRunResultSchema = object({
|
|
15886
|
+
runId: string().min(1),
|
|
15887
|
+
outcome: ActionRunOutcomeSchema,
|
|
15888
|
+
/** Why it did not run, or what failed. */
|
|
15889
|
+
message: string().optional()
|
|
15890
|
+
});
|
|
15891
|
+
_enum([
|
|
15892
|
+
"not-found",
|
|
15893
|
+
"read-only",
|
|
15894
|
+
"invalid-variables",
|
|
15895
|
+
"invalid-steps",
|
|
15896
|
+
"not-linked",
|
|
15897
|
+
"busy"
|
|
15898
|
+
]);
|
|
15899
|
+
object({
|
|
15900
|
+
actionId: string(),
|
|
15901
|
+
runId: string(),
|
|
15902
|
+
isRunning: boolean(),
|
|
15903
|
+
/** Set when the run ended. */
|
|
15904
|
+
outcome: AutomationRunOutcomeSchema.optional(),
|
|
15905
|
+
lastRunAt: number().nullable(),
|
|
15906
|
+
lastError: string().nullable()
|
|
15490
15907
|
});
|
|
15491
15908
|
/**
|
|
15492
15909
|
* `addon-pages` — system-scoped singleton aggregator cap. Public-facing
|
|
@@ -18173,7 +18590,7 @@ var CompositionEventPlanSchema = object({
|
|
|
18173
18590
|
stateField: string(),
|
|
18174
18591
|
fieldKey: string()
|
|
18175
18592
|
});
|
|
18176
|
-
/** One refusal, named (D391). `path` points into the composition, e.g. `features[0].fields.
|
|
18593
|
+
/** One refusal, named (D391). `path` points into the composition, e.g. `features[0].fields.temperature`. */
|
|
18177
18594
|
var CompositionProblemSchema = object({
|
|
18178
18595
|
code: _enum([
|
|
18179
18596
|
"reserved-variant",
|
|
@@ -18492,7 +18909,7 @@ var GROUP_TEMPLATES = [
|
|
|
18492
18909
|
summary: "Mean, median, min, max or sum of temperatures. Offline and unknown members are left out, never read as 0 °C.",
|
|
18493
18910
|
role: DeviceRole.TemperatureSensor,
|
|
18494
18911
|
outputCap: "temperature-sensor",
|
|
18495
|
-
outputField: "
|
|
18912
|
+
outputField: "temperature",
|
|
18496
18913
|
quantity: "temperature",
|
|
18497
18914
|
defaultAggregate: "mean",
|
|
18498
18915
|
empty: "null",
|
|
@@ -18503,7 +18920,7 @@ var GROUP_TEMPLATES = [
|
|
|
18503
18920
|
summary: "Humidity in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
18504
18921
|
role: DeviceRole.HumiditySensor,
|
|
18505
18922
|
outputCap: "humidity-sensor",
|
|
18506
|
-
outputField: "
|
|
18923
|
+
outputField: "humidity",
|
|
18507
18924
|
quantity: "humidity",
|
|
18508
18925
|
defaultAggregate: "mean",
|
|
18509
18926
|
empty: "null",
|
|
@@ -18514,7 +18931,7 @@ var GROUP_TEMPLATES = [
|
|
|
18514
18931
|
summary: "Pressure in hectopascals. Offline and unknown members are left out, never read as 0 hPa.",
|
|
18515
18932
|
role: DeviceRole.PressureSensor,
|
|
18516
18933
|
outputCap: "pressure-sensor",
|
|
18517
|
-
outputField: "
|
|
18934
|
+
outputField: "pressure",
|
|
18518
18935
|
quantity: "pressure",
|
|
18519
18936
|
defaultAggregate: "mean",
|
|
18520
18937
|
empty: "null",
|
|
@@ -18525,7 +18942,7 @@ var GROUP_TEMPLATES = [
|
|
|
18525
18942
|
summary: "Illuminance in lux. Offline and unknown members are left out, never read as 0 lx.",
|
|
18526
18943
|
role: DeviceRole.AmbientLightSensor,
|
|
18527
18944
|
outputCap: "ambient-light-sensor",
|
|
18528
|
-
outputField: "
|
|
18945
|
+
outputField: "illuminance",
|
|
18529
18946
|
quantity: "illuminance",
|
|
18530
18947
|
defaultAggregate: "mean",
|
|
18531
18948
|
empty: "null",
|
|
@@ -18536,7 +18953,7 @@ var GROUP_TEMPLATES = [
|
|
|
18536
18953
|
summary: "Power in watts, summed by default. Nobody reporting omits the key rather than writing 0 W.",
|
|
18537
18954
|
role: DeviceRole.PowerSensor,
|
|
18538
18955
|
outputCap: "power-meter",
|
|
18539
|
-
outputField: "
|
|
18956
|
+
outputField: "power",
|
|
18540
18957
|
quantity: "power",
|
|
18541
18958
|
defaultAggregate: "sum",
|
|
18542
18959
|
empty: "omit",
|
|
@@ -18547,7 +18964,7 @@ var GROUP_TEMPLATES = [
|
|
|
18547
18964
|
summary: "Energy in kilowatt-hours, summed by default. Nobody reporting omits the key rather than writing 0 kWh.",
|
|
18548
18965
|
role: DeviceRole.EnergySensor,
|
|
18549
18966
|
outputCap: "power-meter",
|
|
18550
|
-
outputField: "
|
|
18967
|
+
outputField: "energy",
|
|
18551
18968
|
quantity: "energy",
|
|
18552
18969
|
defaultAggregate: "sum",
|
|
18553
18970
|
empty: "omit",
|
|
@@ -18558,7 +18975,7 @@ var GROUP_TEMPLATES = [
|
|
|
18558
18975
|
summary: "Battery charge in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
18559
18976
|
role: DeviceRole.BatterySensor,
|
|
18560
18977
|
outputCap: "battery",
|
|
18561
|
-
outputField: "
|
|
18978
|
+
outputField: "level",
|
|
18562
18979
|
quantity: "percentage",
|
|
18563
18980
|
defaultAggregate: "mean",
|
|
18564
18981
|
empty: "null",
|
|
@@ -19136,7 +19553,18 @@ method(object({}), object({ blocks: array(CoreBlockSchema) }), { auth: "admin" }
|
|
|
19136
19553
|
kind: "mutation",
|
|
19137
19554
|
auth: "admin",
|
|
19138
19555
|
access: "view"
|
|
19139
|
-
})
|
|
19556
|
+
}), method(object({
|
|
19557
|
+
blockId: string().min(1),
|
|
19558
|
+
trace: AutomationRunTraceSchema.optional(),
|
|
19559
|
+
runStartedAt: number().optional(),
|
|
19560
|
+
keepTraces: number().int().min(1).max(100).optional()
|
|
19561
|
+
}), _void(), {
|
|
19562
|
+
kind: "mutation",
|
|
19563
|
+
auth: "admin"
|
|
19564
|
+
}), method(object({ blockId: string().min(1) }), AutomationStateDocSchema, { auth: "admin" }), method(object({ blockId: string().min(1) }), object({
|
|
19565
|
+
traces: array(AutomationRunTraceSchema),
|
|
19566
|
+
lastError: string().nullable()
|
|
19567
|
+
}), { auth: "admin" });
|
|
19140
19568
|
/**
|
|
19141
19569
|
* `custom-model-registry` — collection cap exposing operator-registered
|
|
19142
19570
|
* custom detection models. Each provider (today: `addon-model-studio`)
|
|
@@ -44534,51 +44962,6 @@ method(object({}), array(TargetKindSchema)), method(object({}), array(TargetSche
|
|
|
44534
44962
|
kind: "mutation",
|
|
44535
44963
|
auth: "admin"
|
|
44536
44964
|
});
|
|
44537
|
-
new Set([
|
|
44538
|
-
{
|
|
44539
|
-
id: "person",
|
|
44540
|
-
name: "Person"
|
|
44541
|
-
},
|
|
44542
|
-
{
|
|
44543
|
-
id: "vehicle",
|
|
44544
|
-
name: "Vehicle"
|
|
44545
|
-
},
|
|
44546
|
-
{
|
|
44547
|
-
id: "animal",
|
|
44548
|
-
name: "Animal"
|
|
44549
|
-
},
|
|
44550
|
-
{
|
|
44551
|
-
id: "package",
|
|
44552
|
-
name: "Package"
|
|
44553
|
-
}
|
|
44554
|
-
].map((l) => l.id));
|
|
44555
|
-
var COCO_TO_MACRO = {
|
|
44556
|
-
mapping: {
|
|
44557
|
-
person: "person",
|
|
44558
|
-
bicycle: "vehicle",
|
|
44559
|
-
car: "vehicle",
|
|
44560
|
-
motorcycle: "vehicle",
|
|
44561
|
-
airplane: "vehicle",
|
|
44562
|
-
bus: "vehicle",
|
|
44563
|
-
train: "vehicle",
|
|
44564
|
-
truck: "vehicle",
|
|
44565
|
-
boat: "vehicle",
|
|
44566
|
-
bird: "animal",
|
|
44567
|
-
cat: "animal",
|
|
44568
|
-
dog: "animal",
|
|
44569
|
-
horse: "animal",
|
|
44570
|
-
sheep: "animal",
|
|
44571
|
-
cow: "animal",
|
|
44572
|
-
elephant: "animal",
|
|
44573
|
-
bear: "animal",
|
|
44574
|
-
zebra: "animal",
|
|
44575
|
-
giraffe: "animal",
|
|
44576
|
-
suitcase: "package",
|
|
44577
|
-
backpack: "package",
|
|
44578
|
-
handbag: "package"
|
|
44579
|
-
},
|
|
44580
|
-
preserveOriginal: false
|
|
44581
|
-
};
|
|
44582
44965
|
var AUDIO_MACRO_LABELS = [
|
|
44583
44966
|
{
|
|
44584
44967
|
id: "speech",
|
|
@@ -57145,9 +57528,9 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
|
|
|
57145
57528
|
*/
|
|
57146
57529
|
var AirQualitySensorStatusSchema = object({
|
|
57147
57530
|
/** Carbon dioxide concentration in ppm. */
|
|
57148
|
-
|
|
57531
|
+
co2: number().min(0).optional().meta(readingMeta("concentration-volume")),
|
|
57149
57532
|
/** Total volatile organic compounds in ppb. */
|
|
57150
|
-
|
|
57533
|
+
voc: number().min(0).optional().meta(readingMeta("concentration-ppb")),
|
|
57151
57534
|
/** Particulate matter ≤ 2.5 μm in µg/m³. */
|
|
57152
57535
|
pm25: number().min(0).optional().meta(readingMeta("concentration-mass")),
|
|
57153
57536
|
/** Particulate matter ≤ 10 μm in µg/m³. */
|
|
@@ -57180,12 +57563,12 @@ var airQualitySensorCapability = {
|
|
|
57180
57563
|
* History (D850): recorded series.
|
|
57181
57564
|
*/
|
|
57182
57565
|
history: { fields: {
|
|
57183
|
-
|
|
57566
|
+
co2: {
|
|
57184
57567
|
kind: "gauge",
|
|
57185
57568
|
unit: "ppm",
|
|
57186
57569
|
deadband: 5
|
|
57187
57570
|
},
|
|
57188
|
-
|
|
57571
|
+
voc: {
|
|
57189
57572
|
kind: "gauge",
|
|
57190
57573
|
unit: "ppb",
|
|
57191
57574
|
deadband: 5
|
|
@@ -57216,7 +57599,7 @@ var airQualitySensorCapability = {
|
|
|
57216
57599
|
*/
|
|
57217
57600
|
var AmbientLightSensorStatusSchema = object({
|
|
57218
57601
|
/** Current illuminance in lux (lx). `null` when the sample was refused (D393). */
|
|
57219
|
-
|
|
57602
|
+
illuminance: number().min(0).nullable().meta(readingMeta("illuminance", {
|
|
57220
57603
|
precision: 0,
|
|
57221
57604
|
label: "Illuminance"
|
|
57222
57605
|
})),
|
|
@@ -57245,7 +57628,7 @@ var ambientLightSensorCapability = {
|
|
|
57245
57628
|
/**
|
|
57246
57629
|
* History (D850): recorded series. Wide range, so a RELATIVE deadband (10 %).
|
|
57247
57630
|
*/
|
|
57248
|
-
history: { fields: {
|
|
57631
|
+
history: { fields: { illuminance: {
|
|
57249
57632
|
kind: "gauge",
|
|
57250
57633
|
unit: "lx",
|
|
57251
57634
|
deadbandPct: 10,
|
|
@@ -57384,6 +57767,84 @@ var audioMetricsCapability = {
|
|
|
57384
57767
|
*/
|
|
57385
57768
|
history: "none"
|
|
57386
57769
|
};
|
|
57770
|
+
method(object({}), array(ActionEntrySchema), { auth: "admin" }), method(object({
|
|
57771
|
+
actionId: string().min(1),
|
|
57772
|
+
variables: record(string(), ActionVariableValueSchema).optional()
|
|
57773
|
+
}), _void(), {
|
|
57774
|
+
kind: "mutation",
|
|
57775
|
+
auth: "admin"
|
|
57776
|
+
}), method(object({ actionId: string().min(1) }), _void(), {
|
|
57777
|
+
kind: "mutation",
|
|
57778
|
+
auth: "admin"
|
|
57779
|
+
});
|
|
57780
|
+
/**
|
|
57781
|
+
* actions — the ONE surface for runnable actions, for the UI and for
|
|
57782
|
+
* automations. Provided by the core-blocks builtin on the hub.
|
|
57783
|
+
*
|
|
57784
|
+
* An action is a LIST ENTRY, not a device (D883): either internal (cap and wait
|
|
57785
|
+
* steps, kept in the hub's `actions` record kind) or declared by an addon over
|
|
57786
|
+
* `action-source`. `list` asks every `action-source` provider LIVE and overlays
|
|
57787
|
+
* the run status from the hub's `runs` ledger; there is no catalog here to
|
|
57788
|
+
* drift (D3).
|
|
57789
|
+
*
|
|
57790
|
+
* **Permissions follow the camera, as linked devices do.** An action is linked
|
|
57791
|
+
* to cameras by the operator (`setLinks`, D356: nothing links itself). A
|
|
57792
|
+
* non-admin may `get` / `run` an action only through a camera they may see that
|
|
57793
|
+
* links it: they name the camera (`deviceId`, a top-level field so the scope
|
|
57794
|
+
* gate sees it) and the provider refuses an action that camera does not link.
|
|
57795
|
+
* An admin, and an in-process caller (an automation block), may run any action.
|
|
57796
|
+
* Every refusal is typed (`[not-linked] …`) and logged.
|
|
57797
|
+
*
|
|
57798
|
+
* A second `run` of an action that is already running is REFUSED — traced and
|
|
57799
|
+
* logged — never queued.
|
|
57800
|
+
*/
|
|
57801
|
+
var ActionIdInput = object({ actionId: string().min(1) });
|
|
57802
|
+
var ActionLinksSchema = object({
|
|
57803
|
+
deviceId: number().int().nonnegative(),
|
|
57804
|
+
actionIds: array(string().min(1)).max(100)
|
|
57805
|
+
});
|
|
57806
|
+
method(object({}), array(ActionEntrySchema), { auth: "admin" }), method(object({
|
|
57807
|
+
actionId: string().min(1),
|
|
57808
|
+
deviceId: number().int().nonnegative().optional()
|
|
57809
|
+
}), object({ action: ActionEntrySchema.nullable() }), {
|
|
57810
|
+
role: "viewer",
|
|
57811
|
+
auth: "protected",
|
|
57812
|
+
kind: "query",
|
|
57813
|
+
caller: "required"
|
|
57814
|
+
}), method(object({
|
|
57815
|
+
actionId: string().min(1),
|
|
57816
|
+
variables: record(string(), ActionVariableValueSchema).optional(),
|
|
57817
|
+
wait: boolean().optional(),
|
|
57818
|
+
origin: ActionRunOriginSchema.optional(),
|
|
57819
|
+
deviceId: number().int().nonnegative().optional()
|
|
57820
|
+
}), ActionRunResultSchema, {
|
|
57821
|
+
role: "viewer",
|
|
57822
|
+
auth: "protected",
|
|
57823
|
+
kind: "mutation",
|
|
57824
|
+
caller: "required"
|
|
57825
|
+
}), method(ActionIdInput, _void(), {
|
|
57826
|
+
kind: "mutation",
|
|
57827
|
+
auth: "admin"
|
|
57828
|
+
}), method(ActionIdInput, object({ traces: array(AutomationRunTraceSchema) }), { auth: "admin" }), method(object({ action: ActionInputSchema }), object({ action: ActionEntrySchema }), {
|
|
57829
|
+
kind: "mutation",
|
|
57830
|
+
auth: "admin"
|
|
57831
|
+
}), method(object({
|
|
57832
|
+
actionId: string().min(1),
|
|
57833
|
+
action: ActionInputSchema.partial()
|
|
57834
|
+
}), object({ action: ActionEntrySchema }), {
|
|
57835
|
+
kind: "mutation",
|
|
57836
|
+
auth: "admin"
|
|
57837
|
+
}), method(ActionIdInput, _void(), {
|
|
57838
|
+
kind: "mutation",
|
|
57839
|
+
auth: "admin"
|
|
57840
|
+
}), method(object({ deviceId: number().int().nonnegative() }), array(ActionEntrySchema), {
|
|
57841
|
+
role: "viewer",
|
|
57842
|
+
auth: "protected",
|
|
57843
|
+
kind: "query"
|
|
57844
|
+
}), method(object({ deviceId: number().int().nonnegative() }), ActionLinksSchema, { auth: "admin" }), method(ActionLinksSchema, ActionLinksSchema, {
|
|
57845
|
+
kind: "mutation",
|
|
57846
|
+
auth: "admin"
|
|
57847
|
+
});
|
|
57387
57848
|
/**
|
|
57388
57849
|
* Automation-control cap. Models HA `automation.*` entities on
|
|
57389
57850
|
* `DeviceType.Automation`. An automation is a trigger+condition+
|
|
@@ -57480,7 +57941,7 @@ var BatteryStatusSchema = object({
|
|
|
57480
57941
|
* Consumers must SKIP a null rather than coerce it — `battery-band` already
|
|
57481
57942
|
* declines to band a non-finite reading, which is the correct shape.
|
|
57482
57943
|
*/
|
|
57483
|
-
|
|
57944
|
+
level: number().min(0).max(100).nullable().meta(readingMeta("percentage", { label: "Charge" })),
|
|
57484
57945
|
/**
|
|
57485
57946
|
* Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
|
|
57486
57947
|
* Reolink-specific for the Solar Panel 2 accessory (will become
|
|
@@ -57490,7 +57951,7 @@ var BatteryStatusSchema = object({
|
|
|
57490
57951
|
* `'unknown'` is the absence of an answer: the provider has not read the
|
|
57491
57952
|
* power fields yet, or the firmware reported neither. Before it existed,
|
|
57492
57953
|
* two unreadable fields produced `'none'`, and a camera nobody had reached
|
|
57493
|
-
* was drawn "on battery alone" — the same D315 defect `
|
|
57954
|
+
* was drawn "on battery alone" — the same D315 defect `level` closed
|
|
57494
57955
|
* by going nullable. Consumers SKIP it (no charger state published, no
|
|
57495
57956
|
* glyph, no HomeKit ChargingState) rather than coerce it either way.
|
|
57496
57957
|
*/
|
|
@@ -57514,7 +57975,7 @@ var BatteryStatusSchema = object({
|
|
|
57514
57975
|
* that only report charge. A second reading on this cap, not a second
|
|
57515
57976
|
* `numeric-sensor` on the same device.
|
|
57516
57977
|
*/
|
|
57517
|
-
|
|
57978
|
+
voltage: number().nullable().optional().meta(readingMeta("voltage", { label: "Voltage" })),
|
|
57518
57979
|
/**
|
|
57519
57980
|
* Ms epoch of the last time the device PROVED it was reachable — a
|
|
57520
57981
|
* completed firmware round-trip, an observed wake, or an inbound push
|
|
@@ -57548,7 +58009,7 @@ var BatteryStatusSchema = object({
|
|
|
57548
58009
|
/**
|
|
57549
58010
|
* True when the source is a BINARY low-battery indicator (HA
|
|
57550
58011
|
* `binary_sensor` device_class=battery / `LOW_BAT`) that has no real
|
|
57551
|
-
* charge level — `
|
|
58012
|
+
* charge level — `level` is then a coarse stand-in (100 = normal,
|
|
57552
58013
|
* sub-threshold = low). UI MUST render "Normal"/"Low" instead of a
|
|
57553
58014
|
* misleading exact percentage. Absent/false → genuine 0–100 % reading.
|
|
57554
58015
|
*/
|
|
@@ -57568,15 +58029,15 @@ var BATTERY_DEVICE_TYPES = [
|
|
|
57568
58029
|
var batteryCustomize = {
|
|
57569
58030
|
version: 1,
|
|
57570
58031
|
targets: [{
|
|
57571
|
-
id: "
|
|
58032
|
+
id: "level",
|
|
57572
58033
|
cardinality: "scalar",
|
|
57573
58034
|
vocabulary: {
|
|
57574
58035
|
cap: "battery",
|
|
57575
|
-
stateField: "
|
|
58036
|
+
stateField: "level"
|
|
57576
58037
|
},
|
|
57577
58038
|
deviceTypes: BATTERY_DEVICE_TYPES,
|
|
57578
58039
|
apply: "add",
|
|
57579
|
-
path: "
|
|
58040
|
+
path: "level",
|
|
57580
58041
|
sources: [{
|
|
57581
58042
|
kind: "field",
|
|
57582
58043
|
valueKinds: ["number", "string"],
|
|
@@ -57670,7 +58131,7 @@ onStatusChanged: { data: object({
|
|
|
57670
58131
|
schema: BatteryStatusSchema,
|
|
57671
58132
|
kind: "push",
|
|
57672
58133
|
empty: {
|
|
57673
|
-
|
|
58134
|
+
level: null,
|
|
57674
58135
|
charging: "unknown",
|
|
57675
58136
|
sleeping: false,
|
|
57676
58137
|
lastUpdated: 0
|
|
@@ -57697,11 +58158,11 @@ onStatusChanged: { data: object({
|
|
|
57697
58158
|
* History (D850): recorded series. The generic capture replaces the `battery` series of `pipeline-analytics:stats-5m`.
|
|
57698
58159
|
*/
|
|
57699
58160
|
history: { fields: {
|
|
57700
|
-
|
|
58161
|
+
level: {
|
|
57701
58162
|
kind: "gauge",
|
|
57702
58163
|
unit: "%"
|
|
57703
58164
|
},
|
|
57704
|
-
|
|
58165
|
+
voltage: {
|
|
57705
58166
|
kind: "gauge",
|
|
57706
58167
|
unit: "V"
|
|
57707
58168
|
}
|
|
@@ -57761,14 +58222,14 @@ var binaryCapability = {
|
|
|
57761
58222
|
* controls to this single-method surface.
|
|
57762
58223
|
*
|
|
57763
58224
|
* The cap is intentionally minimal: a single `setBrightness({deviceId,
|
|
57764
|
-
*
|
|
58225
|
+
* level})` mutation plus the auto-injected `getStatus`. Drivers
|
|
57765
58226
|
* that expose richer controls (color temperature, scenes, schedules)
|
|
57766
58227
|
* should surface those via the device's `getSettingsUISchema()`
|
|
57767
58228
|
* instead of bloating this cap.
|
|
57768
58229
|
*/
|
|
57769
58230
|
var BrightnessStatusSchema = object({
|
|
57770
58231
|
/** Current level as 0..100 inclusive. Firmware-reported. */
|
|
57771
|
-
|
|
58232
|
+
level: number().min(0).max(100).meta(readingMeta("percentage")),
|
|
57772
58233
|
/** Ms epoch of the last operator-driven change. Useful for UI freshness. */
|
|
57773
58234
|
lastChangedAt: number()
|
|
57774
58235
|
});
|
|
@@ -57780,7 +58241,7 @@ var brightnessCapability = {
|
|
|
57780
58241
|
deviceTypes: [DeviceType.Light],
|
|
57781
58242
|
methods: { setBrightness: method(object({
|
|
57782
58243
|
deviceId: number().int().nonnegative(),
|
|
57783
|
-
|
|
58244
|
+
level: number().min(0).max(100)
|
|
57784
58245
|
}), _void(), {
|
|
57785
58246
|
kind: "mutation",
|
|
57786
58247
|
auth: "protected"
|
|
@@ -57793,7 +58254,7 @@ var brightnessCapability = {
|
|
|
57793
58254
|
*/
|
|
57794
58255
|
onBrightnessChanged: { data: object({
|
|
57795
58256
|
deviceId: number(),
|
|
57796
|
-
|
|
58257
|
+
level: number().min(0).max(100),
|
|
57797
58258
|
lastChangedAt: number()
|
|
57798
58259
|
}) } },
|
|
57799
58260
|
status: {
|
|
@@ -57816,7 +58277,7 @@ onBrightnessChanged: { data: object({
|
|
|
57816
58277
|
/**
|
|
57817
58278
|
* History (D850): recorded series. Actuator tier: level keeps every change.
|
|
57818
58279
|
*/
|
|
57819
|
-
history: { fields: {
|
|
58280
|
+
history: { fields: { level: {
|
|
57820
58281
|
kind: "gauge",
|
|
57821
58282
|
unit: "%",
|
|
57822
58283
|
minIntervalMs: 0
|
|
@@ -58430,11 +58891,11 @@ var ColorInputSchema = discriminatedUnion("mode", [
|
|
|
58430
58891
|
}),
|
|
58431
58892
|
object({
|
|
58432
58893
|
mode: literal("mired"),
|
|
58433
|
-
|
|
58894
|
+
colorTemperature: number().int().min(50).max(1e3)
|
|
58434
58895
|
})
|
|
58435
58896
|
]);
|
|
58436
58897
|
var ColorStatusSchema = object({
|
|
58437
|
-
/** Active color mode — which of `rgb` / `hsv` / `
|
|
58898
|
+
/** Active color mode — which of `rgb` / `hsv` / `colorTemperature` reflects
|
|
58438
58899
|
* the bulb's current state. */
|
|
58439
58900
|
mode: _enum([
|
|
58440
58901
|
"rgb",
|
|
@@ -58446,7 +58907,7 @@ var ColorStatusSchema = object({
|
|
|
58446
58907
|
/** Populated when `mode === 'hsv'`. */
|
|
58447
58908
|
hsv: HsvTripletSchema.optional(),
|
|
58448
58909
|
/** Populated when `mode === 'mired'`. */
|
|
58449
|
-
|
|
58910
|
+
colorTemperature: number().int().optional().meta(readingMeta("colour-temperature")),
|
|
58450
58911
|
/** Ms epoch of the last operator-driven change. */
|
|
58451
58912
|
lastChangedAt: number()
|
|
58452
58913
|
});
|
|
@@ -58478,7 +58939,7 @@ onColorChanged: { data: object({
|
|
|
58478
58939
|
]),
|
|
58479
58940
|
rgb: RgbTripletSchema.optional(),
|
|
58480
58941
|
hsv: HsvTripletSchema.optional(),
|
|
58481
|
-
|
|
58942
|
+
colorTemperature: number().int().optional(),
|
|
58482
58943
|
lastChangedAt: number()
|
|
58483
58944
|
}) } },
|
|
58484
58945
|
status: {
|
|
@@ -59355,11 +59816,11 @@ var DishwasherStatusSchema = object({
|
|
|
59355
59816
|
/** Feature keys of the programs the appliance currently offers — drives the UI selector. */
|
|
59356
59817
|
availablePrograms: array(string()),
|
|
59357
59818
|
/** Seconds remaining on the active cycle, or null when not running / not known. */
|
|
59358
|
-
|
|
59819
|
+
remaining: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
59359
59820
|
/** Seconds the delayed start is set to (time until the cycle starts), or null. */
|
|
59360
|
-
|
|
59821
|
+
delayedStart: number().int().nonnegative().nullable().meta(readingMeta("duration")),
|
|
59361
59822
|
/** Cycle completion 0..100, or null when not applicable. */
|
|
59362
|
-
|
|
59823
|
+
progress: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
59363
59824
|
/** True when the door is reported open; null when the door state is not known. */
|
|
59364
59825
|
doorOpen: boolean().nullable(),
|
|
59365
59826
|
/** True when the door is latched (locked) during a cycle; null when not reported. */
|
|
@@ -59578,14 +60039,14 @@ var dishwasherCapability = {
|
|
|
59578
60039
|
runtimeState: DishwasherStatusSchema,
|
|
59579
60040
|
durability: "session",
|
|
59580
60041
|
history: { fields: {
|
|
59581
|
-
|
|
60042
|
+
progress: {
|
|
59582
60043
|
kind: "gauge",
|
|
59583
60044
|
unit: "%",
|
|
59584
60045
|
deadband: 2
|
|
59585
60046
|
},
|
|
59586
60047
|
state: { kind: "enum" },
|
|
59587
60048
|
operationState: { kind: "enum" },
|
|
59588
|
-
|
|
60049
|
+
remaining: {
|
|
59589
60050
|
kind: "gauge",
|
|
59590
60051
|
unit: "s",
|
|
59591
60052
|
minIntervalMs: 6e4
|
|
@@ -60176,7 +60637,7 @@ var FanDirectionSchema = _enum(["forward", "reverse"]);
|
|
|
60176
60637
|
var FanControlStatusSchema = object({
|
|
60177
60638
|
/** Active speed as 0..100 inclusive. Null when the device has no
|
|
60178
60639
|
* speed surface (single-speed fan). */
|
|
60179
|
-
|
|
60640
|
+
speed: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
60180
60641
|
/** Speed granularity the device accepts (HA `percentage_step`, e.g. 25 for
|
|
60181
60642
|
* a 4-speed fan). Absent when unknown — the UI then falls back to step 1. */
|
|
60182
60643
|
percentageStep: number().positive().optional().meta(readingMeta("percentage")),
|
|
@@ -60203,7 +60664,7 @@ var fanControlCapability = {
|
|
|
60203
60664
|
methods: {
|
|
60204
60665
|
setPercentage: method(object({
|
|
60205
60666
|
deviceId: number().int().nonnegative(),
|
|
60206
|
-
|
|
60667
|
+
speed: number().min(0).max(100)
|
|
60207
60668
|
}), _void(), {
|
|
60208
60669
|
kind: "mutation",
|
|
60209
60670
|
auth: "protected"
|
|
@@ -60236,7 +60697,7 @@ var fanControlCapability = {
|
|
|
60236
60697
|
},
|
|
60237
60698
|
/**
|
|
60238
60699
|
* Runtime-state slice — mirrored by the kernel. UI fan speed
|
|
60239
|
-
* sliders read `
|
|
60700
|
+
* sliders read `speed` for live updates.
|
|
60240
60701
|
*/
|
|
60241
60702
|
runtimeState: FanControlStatusSchema,
|
|
60242
60703
|
/**
|
|
@@ -60250,7 +60711,7 @@ var fanControlCapability = {
|
|
|
60250
60711
|
* History (D850): recorded series. Actuator tier: speed keeps every change.
|
|
60251
60712
|
*/
|
|
60252
60713
|
history: { fields: {
|
|
60253
|
-
|
|
60714
|
+
speed: {
|
|
60254
60715
|
kind: "gauge",
|
|
60255
60716
|
unit: "%",
|
|
60256
60717
|
minIntervalMs: 0
|
|
@@ -60695,7 +61156,7 @@ var humidifierCapability = {
|
|
|
60695
61156
|
*/
|
|
60696
61157
|
var HumiditySensorStatusSchema = object({
|
|
60697
61158
|
/** Current relative humidity, 0..100. `null` when the sample was refused (D393). */
|
|
60698
|
-
|
|
61159
|
+
humidity: number().min(0).max(100).nullable().meta(readingMeta("humidity", {
|
|
60699
61160
|
precision: 0,
|
|
60700
61161
|
label: "Humidity"
|
|
60701
61162
|
})),
|
|
@@ -60724,7 +61185,7 @@ var humiditySensorCapability = {
|
|
|
60724
61185
|
/**
|
|
60725
61186
|
* History (D850): recorded series.
|
|
60726
61187
|
*/
|
|
60727
|
-
history: { fields: {
|
|
61188
|
+
history: { fields: { humidity: {
|
|
60728
61189
|
kind: "gauge",
|
|
60729
61190
|
unit: "%",
|
|
60730
61191
|
deadband: .5
|
|
@@ -61364,7 +61825,7 @@ var LawnMowerControlStatusSchema = object({
|
|
|
61364
61825
|
batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61365
61826
|
/** 0..100 mowing-completion percentage of the current task, or null when no
|
|
61366
61827
|
* task is active / progress is unavailable. */
|
|
61367
|
-
|
|
61828
|
+
progress: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
61368
61829
|
/** Current device/event code (dynamic — mostly status, sometimes an error),
|
|
61369
61830
|
* or null when unknown. */
|
|
61370
61831
|
currentCode: number().nullable().meta(readingMeta("none")),
|
|
@@ -61864,7 +62325,7 @@ var lockControlCapability = {
|
|
|
61864
62325
|
volatileStateFields: ["lastChangedAt"]
|
|
61865
62326
|
};
|
|
61866
62327
|
/**
|
|
61867
|
-
* A monotonic total between resets (D944). Energy uses `power-meter.
|
|
62328
|
+
* A monotonic total between resets (D944). Energy uses `power-meter.energy`
|
|
61868
62329
|
* so dashboards keep one series; every other instantaneous reading lands here.
|
|
61869
62330
|
* `value` is the time integral in the source quantity's accumulated base
|
|
61870
62331
|
* (base-unit seconds, or kWh on the power meter). `null` is a gap, never zero.
|
|
@@ -61958,10 +62419,10 @@ var MediaPlayerStatusSchema = object({
|
|
|
61958
62419
|
currentMedia: MediaInfoSchema.nullable(),
|
|
61959
62420
|
/** Current playback position in ms. Null when not seekable or
|
|
61960
62421
|
* nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
|
|
61961
|
-
|
|
62422
|
+
position: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
61962
62423
|
/** Total duration of the current media in ms. Null when unknown
|
|
61963
62424
|
* (live stream) or nothing is playing. */
|
|
61964
|
-
|
|
62425
|
+
duration: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
|
|
61965
62426
|
/** Shuffle toggle. Null when no shuffle surface.
|
|
61966
62427
|
* Pair with `DeviceFeature.MediaPlayerShuffle`. */
|
|
61967
62428
|
shuffle: boolean().nullable(),
|
|
@@ -62000,7 +62461,7 @@ var mediaPlayerCapability = {
|
|
|
62000
62461
|
}),
|
|
62001
62462
|
seek: method(object({
|
|
62002
62463
|
deviceId: number().int().nonnegative(),
|
|
62003
|
-
|
|
62464
|
+
position: number().int().nonnegative()
|
|
62004
62465
|
}), _void(), {
|
|
62005
62466
|
kind: "mutation",
|
|
62006
62467
|
auth: "protected"
|
|
@@ -62072,7 +62533,7 @@ var mediaPlayerCapability = {
|
|
|
62072
62533
|
/**
|
|
62073
62534
|
* History (D850): volume (a level an operator or an automation sets; the
|
|
62074
62535
|
* default 10 s floor folds a slider drag into its end value) and mute.
|
|
62075
|
-
* `
|
|
62536
|
+
* `position` is not recorded: it moves continuously while playing.
|
|
62076
62537
|
*/
|
|
62077
62538
|
history: { fields: {
|
|
62078
62539
|
volumeLevel: {
|
|
@@ -63034,9 +63495,9 @@ var NetworkLinkStatusSchema = object({
|
|
|
63034
63495
|
* one whose reading has not landed must not be drawn at 0 %. Consumers
|
|
63035
63496
|
* SKIP a null rather than coerce it.
|
|
63036
63497
|
*/
|
|
63037
|
-
|
|
63498
|
+
signal: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
63038
63499
|
/** Raw received signal strength in dBm, when the firmware reports one. */
|
|
63039
|
-
|
|
63500
|
+
rssi: number().optional().meta(readingMeta("signal-level")),
|
|
63040
63501
|
/** Network name of a wireless link, when the firmware reports it. */
|
|
63041
63502
|
ssid: string().optional(),
|
|
63042
63503
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
@@ -63072,7 +63533,7 @@ onStatusChanged: { data: object({
|
|
|
63072
63533
|
kind: "push",
|
|
63073
63534
|
empty: {
|
|
63074
63535
|
type: "unknown",
|
|
63075
|
-
|
|
63536
|
+
signal: null,
|
|
63076
63537
|
lastUpdated: 0
|
|
63077
63538
|
}
|
|
63078
63539
|
},
|
|
@@ -63095,13 +63556,13 @@ onStatusChanged: { data: object({
|
|
|
63095
63556
|
* History (D850): recorded series.
|
|
63096
63557
|
*/
|
|
63097
63558
|
history: { fields: {
|
|
63098
|
-
|
|
63559
|
+
signal: {
|
|
63099
63560
|
kind: "gauge",
|
|
63100
63561
|
unit: "%",
|
|
63101
63562
|
deadband: 3,
|
|
63102
63563
|
minIntervalMs: 6e4
|
|
63103
63564
|
},
|
|
63104
|
-
|
|
63565
|
+
rssi: {
|
|
63105
63566
|
kind: "gauge",
|
|
63106
63567
|
unit: "dBm",
|
|
63107
63568
|
deadband: 2,
|
|
@@ -63846,10 +64307,20 @@ var PetFeederDeviceStatusSchema = _enum([
|
|
|
63846
64307
|
]);
|
|
63847
64308
|
var gramsPortion = number().int().min(4).max(200);
|
|
63848
64309
|
var PetFeederStatusSchema = object({
|
|
63849
|
-
/** Food
|
|
63850
|
-
*
|
|
63851
|
-
* bowl
|
|
64310
|
+
/** Food in the TANK (hopper), as the feeder's own sensor reports it
|
|
64311
|
+
* (`state.food`). A coarse level code, not grams — `0` is empty. The
|
|
64312
|
+
* amount in the bowl is `bowlFood`. On dual-hopper models this is the
|
|
64313
|
+
* combined reading; per-hopper levels live in `food1`/`food2`. Null when
|
|
64314
|
+
* the device has not reported yet. */
|
|
63852
64315
|
foodLevel: number().nullable().meta(readingMeta("none")),
|
|
64316
|
+
/** Food in the BOWL as the feeder reports it (`state.bowl`), in the
|
|
64317
|
+
* feeder's own units. Null when the model reports none. */
|
|
64318
|
+
bowlFood: number().nullable().meta(readingMeta("none")),
|
|
64319
|
+
/** True while the pet is eating (`state.eating`). */
|
|
64320
|
+
eating: boolean(),
|
|
64321
|
+
/** Whether `markFoodReplenished` does anything on this model. When false
|
|
64322
|
+
* the client must not offer it. */
|
|
64323
|
+
supportsMarkRefilled: boolean(),
|
|
63853
64324
|
/** Hopper-1 food level (grams) on dual-hopper feeders; null on
|
|
63854
64325
|
* single-hopper models. */
|
|
63855
64326
|
food1: number().nullable().meta(readingMeta("none")),
|
|
@@ -63857,8 +64328,8 @@ var PetFeederStatusSchema = object({
|
|
|
63857
64328
|
* single-hopper models. */
|
|
63858
64329
|
food2: number().nullable().meta(readingMeta("none")),
|
|
63859
64330
|
/** Derived low-food flag — mirrors the HA `food_level` binary_sensor
|
|
63860
|
-
* (`device_class: problem`, on = low). True when the
|
|
63861
|
-
*
|
|
64331
|
+
* (`device_class: problem`, on = low). True when the tank reports empty,
|
|
64332
|
+
* or, on a dual-hopper model, when EITHER hopper is empty. */
|
|
63862
64333
|
lowFood: boolean(),
|
|
63863
64334
|
/** Battery charge 0..100 (%). Null on mains-powered models or when the
|
|
63864
64335
|
* device has no battery reading. */
|
|
@@ -63926,7 +64397,9 @@ var petFeederCapability = {
|
|
|
63926
64397
|
kind: "mutation",
|
|
63927
64398
|
auth: "protected"
|
|
63928
64399
|
}),
|
|
63929
|
-
/**
|
|
64400
|
+
/** Tell the PetKit cloud a hopper was refilled so it stops its low-food
|
|
64401
|
+
* reminders (D4H/D4S/D4SH only — see `supportsMarkRefilled`). It does not
|
|
64402
|
+
* change any sensor reading. */
|
|
63930
64403
|
markFoodReplenished: method(object({ deviceId: number().int().nonnegative() }), _void(), {
|
|
63931
64404
|
kind: "mutation",
|
|
63932
64405
|
auth: "protected"
|
|
@@ -63999,6 +64472,7 @@ var petFeederCapability = {
|
|
|
63999
64472
|
*/
|
|
64000
64473
|
history: { fields: {
|
|
64001
64474
|
foodLevel: { kind: "gauge" },
|
|
64475
|
+
bowlFood: { kind: "gauge" },
|
|
64002
64476
|
food1: { kind: "gauge" },
|
|
64003
64477
|
food2: { kind: "gauge" },
|
|
64004
64478
|
batteryPower: {
|
|
@@ -64408,16 +64882,16 @@ method(_void(), PlatformCapabilitiesSchema), method(_void(), HardwareInfoSchema)
|
|
|
64408
64882
|
* in real-world devices.
|
|
64409
64883
|
*/
|
|
64410
64884
|
var PowerMeterStatusSchema = object({
|
|
64411
|
-
/** Instantaneous power draw
|
|
64412
|
-
|
|
64885
|
+
/** Instantaneous power draw (watts). */
|
|
64886
|
+
power: number().optional().meta(readingMeta("power", { label: "Power" })),
|
|
64413
64887
|
/** Cumulative energy in kilowatt-hours since the meter was reset. */
|
|
64414
|
-
|
|
64415
|
-
/** Voltage
|
|
64416
|
-
|
|
64888
|
+
energy: number().optional().meta(readingMeta("energy", { label: "Energy" })),
|
|
64889
|
+
/** Voltage (volts). */
|
|
64890
|
+
voltage: number().optional().meta(readingMeta("voltage", { label: "Voltage" })),
|
|
64417
64891
|
/** Current in amperes. */
|
|
64418
|
-
|
|
64892
|
+
current: number().optional().meta(readingMeta("current", { label: "Current" })),
|
|
64419
64893
|
/** Apparent power in volt-amperes. */
|
|
64420
|
-
|
|
64894
|
+
apparentPower: number().optional().meta(readingMeta("apparent-power")),
|
|
64421
64895
|
/** Power factor (0..1) if reported. */
|
|
64422
64896
|
powerFactor: number().min(0).max(1).optional().meta(readingMeta("ratio")),
|
|
64423
64897
|
/** Ms epoch when the slice was last updated. */
|
|
@@ -64475,14 +64949,14 @@ function powerTarget(id, unit) {
|
|
|
64475
64949
|
advancedExpression: true
|
|
64476
64950
|
};
|
|
64477
64951
|
}
|
|
64478
|
-
/** "Power and energy" extension:
|
|
64952
|
+
/** "Power and energy" extension: power, energy, voltage and current from other devices (D951). */
|
|
64479
64953
|
var powerMeterCustomize = {
|
|
64480
64954
|
version: 1,
|
|
64481
64955
|
targets: [
|
|
64482
|
-
powerTarget("
|
|
64483
|
-
powerTarget("
|
|
64484
|
-
powerTarget("
|
|
64485
|
-
powerTarget("
|
|
64956
|
+
powerTarget("power", "W"),
|
|
64957
|
+
powerTarget("energy", "kWh"),
|
|
64958
|
+
powerTarget("voltage", "V"),
|
|
64959
|
+
powerTarget("current", "A")
|
|
64486
64960
|
]
|
|
64487
64961
|
};
|
|
64488
64962
|
var powerMeterCapability = {
|
|
@@ -64498,41 +64972,41 @@ var powerMeterCapability = {
|
|
|
64498
64972
|
},
|
|
64499
64973
|
runtimeState: PowerMeterStatusSchema,
|
|
64500
64974
|
/**
|
|
64501
|
-
* Runtime-state durability: **restored** — as `numeric-sensor`; `
|
|
64975
|
+
* Runtime-state durability: **restored** — as `numeric-sensor`; `energy` is an accumulator whose restored value is the baseline.
|
|
64502
64976
|
*
|
|
64503
64977
|
* See `RuntimeStateDurability`. Enforced by
|
|
64504
64978
|
* `scripts/check-runtime-state-durability.ts`.
|
|
64505
64979
|
*/
|
|
64506
64980
|
durability: "restored",
|
|
64507
64981
|
/**
|
|
64508
|
-
* History (D850): recorded series. Gauges are floored at 30 s; `
|
|
64982
|
+
* History (D850): recorded series. Gauges are floored at 30 s; `energy` is the one monotonic meter (counter).
|
|
64509
64983
|
*/
|
|
64510
64984
|
history: { fields: {
|
|
64511
|
-
|
|
64985
|
+
power: {
|
|
64512
64986
|
kind: "gauge",
|
|
64513
64987
|
unit: "W",
|
|
64514
64988
|
deadband: 1,
|
|
64515
64989
|
minIntervalMs: 3e4
|
|
64516
64990
|
},
|
|
64517
|
-
|
|
64991
|
+
energy: {
|
|
64518
64992
|
kind: "counter",
|
|
64519
64993
|
unit: "kWh",
|
|
64520
64994
|
deadband: .01,
|
|
64521
64995
|
minIntervalMs: 6e4
|
|
64522
64996
|
},
|
|
64523
|
-
|
|
64997
|
+
voltage: {
|
|
64524
64998
|
kind: "gauge",
|
|
64525
64999
|
unit: "V",
|
|
64526
65000
|
deadband: 1,
|
|
64527
65001
|
minIntervalMs: 3e4
|
|
64528
65002
|
},
|
|
64529
|
-
|
|
65003
|
+
current: {
|
|
64530
65004
|
kind: "gauge",
|
|
64531
65005
|
unit: "A",
|
|
64532
65006
|
deadband: .05,
|
|
64533
65007
|
minIntervalMs: 3e4
|
|
64534
65008
|
},
|
|
64535
|
-
|
|
65009
|
+
apparentPower: {
|
|
64536
65010
|
kind: "gauge",
|
|
64537
65011
|
unit: "VA",
|
|
64538
65012
|
deadband: 1,
|
|
@@ -64582,9 +65056,6 @@ var PresenceStatusSchema = object({
|
|
|
64582
65056
|
location: string().nullable(),
|
|
64583
65057
|
/** GPS coordinates when available. Null otherwise. */
|
|
64584
65058
|
gps: GpsLocationSchema.nullable(),
|
|
64585
|
-
/** Optional battery level of the tracking device (0..100). Null
|
|
64586
|
-
* when not reported. */
|
|
64587
|
-
batteryPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
64588
65059
|
/** Ms epoch when the slice was last updated. */
|
|
64589
65060
|
lastChangedAt: number()
|
|
64590
65061
|
});
|
|
@@ -64613,14 +65084,7 @@ var presenceCapability = {
|
|
|
64613
65084
|
* `scripts/check-runtime-state-durability.ts`.
|
|
64614
65085
|
*/
|
|
64615
65086
|
durability: "restored",
|
|
64616
|
-
|
|
64617
|
-
* History (D850): recorded series.
|
|
64618
|
-
*/
|
|
64619
|
-
history: { fields: { batteryPercent: {
|
|
64620
|
-
kind: "gauge",
|
|
64621
|
-
unit: "%",
|
|
64622
|
-
deadband: 1
|
|
64623
|
-
} } },
|
|
65087
|
+
history: "none",
|
|
64624
65088
|
/** Clock fields: written, but excluded from the compare that decides
|
|
64625
65089
|
* whether persisting is worth a SQLite commit. */
|
|
64626
65090
|
volatileStateFields: ["lastChangedAt"]
|
|
@@ -64635,7 +65099,7 @@ var presenceCapability = {
|
|
|
64635
65099
|
*/
|
|
64636
65100
|
var PressureSensorStatusSchema = object({
|
|
64637
65101
|
/** Current pressure in hPa. `null` when the sample was refused (D393). */
|
|
64638
|
-
|
|
65102
|
+
pressure: number().nullable().meta(readingMeta("pressure", { precision: 0 })),
|
|
64639
65103
|
/** Ms epoch when the slice was last updated. */
|
|
64640
65104
|
lastFetchedAt: number()
|
|
64641
65105
|
});
|
|
@@ -64661,7 +65125,7 @@ var pressureSensorCapability = {
|
|
|
64661
65125
|
/**
|
|
64662
65126
|
* History (D850): recorded series.
|
|
64663
65127
|
*/
|
|
64664
|
-
history: { fields: {
|
|
65128
|
+
history: { fields: { pressure: {
|
|
64665
65129
|
kind: "gauge",
|
|
64666
65130
|
unit: "hPa",
|
|
64667
65131
|
deadband: .1
|
|
@@ -68360,7 +68824,7 @@ var tamperCapability = {
|
|
|
68360
68824
|
*/
|
|
68361
68825
|
var TemperatureSensorStatusSchema = object({
|
|
68362
68826
|
/** Current temperature in Celsius. `null` when the sample was refused (D393). */
|
|
68363
|
-
|
|
68827
|
+
temperature: number().nullable().meta(readingMeta("temperature", {
|
|
68364
68828
|
precision: 1,
|
|
68365
68829
|
label: "Temperature"
|
|
68366
68830
|
})),
|
|
@@ -68389,7 +68853,7 @@ var temperatureSensorCapability = {
|
|
|
68389
68853
|
/**
|
|
68390
68854
|
* History (D850): recorded series.
|
|
68391
68855
|
*/
|
|
68392
|
-
history: { fields: {
|
|
68856
|
+
history: { fields: { temperature: {
|
|
68393
68857
|
kind: "gauge",
|
|
68394
68858
|
unit: "°C",
|
|
68395
68859
|
deadband: .1
|
|
@@ -68686,7 +69150,7 @@ var VacuumControlStatusSchema = object({
|
|
|
68686
69150
|
/** Speed tokens the hardware accepts — drives the UI selector. */
|
|
68687
69151
|
availableFanSpeeds: array(string()),
|
|
68688
69152
|
/** 0..100 cleaning-completion percentage of the current task, or null. */
|
|
68689
|
-
|
|
69153
|
+
progress: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
68690
69154
|
/** Current error code (0 / null = no error). */
|
|
68691
69155
|
errorCode: number().nullable().meta(readingMeta("none")),
|
|
68692
69156
|
/** Human label for {@link errorCode}, or null when none / undecodable. */
|
|
@@ -70340,7 +70804,7 @@ var BaseDevice = class {
|
|
|
70340
70804
|
* `device-local-state.ts`. Drivers access via:
|
|
70341
70805
|
*
|
|
70342
70806
|
* `this.state.battery.sleeping = true` // patches the battery slice
|
|
70343
|
-
* `const pct = this.state.battery.
|
|
70807
|
+
* `const pct = this.state.battery.level` // reads the battery slice
|
|
70344
70808
|
* `this.state.deviceStatus.online = true` // mirrors `markOnline(true)`
|
|
70345
70809
|
*
|
|
70346
70810
|
* Adding a new cap with `runtimeState:` automatically extends this
|
|
@@ -70380,7 +70844,7 @@ var BaseDevice = class {
|
|
|
70380
70844
|
* shape; drivers don't redeclare it, they just write through.
|
|
70381
70845
|
*
|
|
70382
70846
|
* Read: `this.runtimeState.getCapState('battery')` →
|
|
70383
|
-
* `{
|
|
70847
|
+
* `{level, charging, sleeping, lastUpdated}` for any
|
|
70384
70848
|
* provider that registers `batteryCapability`.
|
|
70385
70849
|
* Write: `this.runtimeState.setCapState('battery', { … })`.
|
|
70386
70850
|
*
|
|
@@ -71554,6 +72018,104 @@ Object.freeze({
|
|
|
71554
72018
|
access: "create",
|
|
71555
72019
|
role: "admin"
|
|
71556
72020
|
},
|
|
72021
|
+
"actions.create": {
|
|
72022
|
+
capName: "actions",
|
|
72023
|
+
capScope: "system",
|
|
72024
|
+
addonId: null,
|
|
72025
|
+
access: "create",
|
|
72026
|
+
role: "admin"
|
|
72027
|
+
},
|
|
72028
|
+
"actions.delete": {
|
|
72029
|
+
capName: "actions",
|
|
72030
|
+
capScope: "system",
|
|
72031
|
+
addonId: null,
|
|
72032
|
+
access: "delete",
|
|
72033
|
+
role: "admin"
|
|
72034
|
+
},
|
|
72035
|
+
"actions.get": {
|
|
72036
|
+
capName: "actions",
|
|
72037
|
+
capScope: "system",
|
|
72038
|
+
addonId: null,
|
|
72039
|
+
access: "view",
|
|
72040
|
+
role: "viewer"
|
|
72041
|
+
},
|
|
72042
|
+
"actions.getLinks": {
|
|
72043
|
+
capName: "actions",
|
|
72044
|
+
capScope: "system",
|
|
72045
|
+
addonId: null,
|
|
72046
|
+
access: "view",
|
|
72047
|
+
role: "admin"
|
|
72048
|
+
},
|
|
72049
|
+
"actions.getTraces": {
|
|
72050
|
+
capName: "actions",
|
|
72051
|
+
capScope: "system",
|
|
72052
|
+
addonId: null,
|
|
72053
|
+
access: "view",
|
|
72054
|
+
role: "admin"
|
|
72055
|
+
},
|
|
72056
|
+
"actions.list": {
|
|
72057
|
+
capName: "actions",
|
|
72058
|
+
capScope: "system",
|
|
72059
|
+
addonId: null,
|
|
72060
|
+
access: "view",
|
|
72061
|
+
role: "admin"
|
|
72062
|
+
},
|
|
72063
|
+
"actions.listForCamera": {
|
|
72064
|
+
capName: "actions",
|
|
72065
|
+
capScope: "system",
|
|
72066
|
+
addonId: null,
|
|
72067
|
+
access: "view",
|
|
72068
|
+
role: "viewer"
|
|
72069
|
+
},
|
|
72070
|
+
"actions.run": {
|
|
72071
|
+
capName: "actions",
|
|
72072
|
+
capScope: "system",
|
|
72073
|
+
addonId: null,
|
|
72074
|
+
access: "create",
|
|
72075
|
+
role: "viewer"
|
|
72076
|
+
},
|
|
72077
|
+
"actions.setLinks": {
|
|
72078
|
+
capName: "actions",
|
|
72079
|
+
capScope: "system",
|
|
72080
|
+
addonId: null,
|
|
72081
|
+
access: "create",
|
|
72082
|
+
role: "admin"
|
|
72083
|
+
},
|
|
72084
|
+
"actions.stop": {
|
|
72085
|
+
capName: "actions",
|
|
72086
|
+
capScope: "system",
|
|
72087
|
+
addonId: null,
|
|
72088
|
+
access: "create",
|
|
72089
|
+
role: "admin"
|
|
72090
|
+
},
|
|
72091
|
+
"actions.update": {
|
|
72092
|
+
capName: "actions",
|
|
72093
|
+
capScope: "system",
|
|
72094
|
+
addonId: null,
|
|
72095
|
+
access: "create",
|
|
72096
|
+
role: "admin"
|
|
72097
|
+
},
|
|
72098
|
+
"actionSource.listActions": {
|
|
72099
|
+
capName: "action-source",
|
|
72100
|
+
capScope: "system",
|
|
72101
|
+
addonId: null,
|
|
72102
|
+
access: "view",
|
|
72103
|
+
role: "admin"
|
|
72104
|
+
},
|
|
72105
|
+
"actionSource.runAction": {
|
|
72106
|
+
capName: "action-source",
|
|
72107
|
+
capScope: "system",
|
|
72108
|
+
addonId: null,
|
|
72109
|
+
access: "create",
|
|
72110
|
+
role: "admin"
|
|
72111
|
+
},
|
|
72112
|
+
"actionSource.stopAction": {
|
|
72113
|
+
capName: "action-source",
|
|
72114
|
+
capScope: "system",
|
|
72115
|
+
addonId: null,
|
|
72116
|
+
access: "create",
|
|
72117
|
+
role: "admin"
|
|
72118
|
+
},
|
|
71557
72119
|
"addonPages.listPages": {
|
|
71558
72120
|
capName: "addon-pages",
|
|
71559
72121
|
capScope: "system",
|
|
@@ -72835,6 +73397,13 @@ Object.freeze({
|
|
|
72835
73397
|
access: "view",
|
|
72836
73398
|
role: "admin"
|
|
72837
73399
|
},
|
|
73400
|
+
"coreBlocks.getAutomationRunState": {
|
|
73401
|
+
capName: "core-blocks",
|
|
73402
|
+
capScope: "system",
|
|
73403
|
+
addonId: null,
|
|
73404
|
+
access: "view",
|
|
73405
|
+
role: "admin"
|
|
73406
|
+
},
|
|
72838
73407
|
"coreBlocks.getBlockSettings": {
|
|
72839
73408
|
capName: "core-blocks",
|
|
72840
73409
|
capScope: "system",
|
|
@@ -72856,6 +73425,13 @@ Object.freeze({
|
|
|
72856
73425
|
access: "view",
|
|
72857
73426
|
role: "admin"
|
|
72858
73427
|
},
|
|
73428
|
+
"coreBlocks.getTraces": {
|
|
73429
|
+
capName: "core-blocks",
|
|
73430
|
+
capScope: "system",
|
|
73431
|
+
addonId: null,
|
|
73432
|
+
access: "view",
|
|
73433
|
+
role: "admin"
|
|
73434
|
+
},
|
|
72859
73435
|
"coreBlocks.getTypeDefs": {
|
|
72860
73436
|
capName: "core-blocks",
|
|
72861
73437
|
capScope: "system",
|
|
@@ -72891,6 +73467,13 @@ Object.freeze({
|
|
|
72891
73467
|
access: "create",
|
|
72892
73468
|
role: "admin"
|
|
72893
73469
|
},
|
|
73470
|
+
"coreBlocks.reportAutomationRun": {
|
|
73471
|
+
capName: "core-blocks",
|
|
73472
|
+
capScope: "system",
|
|
73473
|
+
addonId: null,
|
|
73474
|
+
access: "create",
|
|
73475
|
+
role: "admin"
|
|
73476
|
+
},
|
|
72894
73477
|
"coreBlocks.restart": {
|
|
72895
73478
|
capName: "core-blocks",
|
|
72896
73479
|
capScope: "system",
|
|
@@ -81464,7 +82047,7 @@ var ACTUATOR_CAP_VOCABULARY = {
|
|
|
81464
82047
|
label: t("Full brightness", "Luminosità massima"),
|
|
81465
82048
|
phrase: t("Set {device} to full brightness", "Porta {device} alla massima luminosità"),
|
|
81466
82049
|
icon: "sun",
|
|
81467
|
-
args: {
|
|
82050
|
+
args: { level: 100 }
|
|
81468
82051
|
},
|
|
81469
82052
|
{
|
|
81470
82053
|
id: "brightness.half",
|
|
@@ -81472,7 +82055,7 @@ var ACTUATOR_CAP_VOCABULARY = {
|
|
|
81472
82055
|
label: t("Half brightness", "Luminosità a metà"),
|
|
81473
82056
|
phrase: t("Dim {device} to half", "Abbassa {device} a metà luminosità"),
|
|
81474
82057
|
icon: "sun-dim",
|
|
81475
|
-
args: {
|
|
82058
|
+
args: { level: 50 }
|
|
81476
82059
|
},
|
|
81477
82060
|
{
|
|
81478
82061
|
id: "brightness.off",
|
|
@@ -81480,16 +82063,16 @@ var ACTUATOR_CAP_VOCABULARY = {
|
|
|
81480
82063
|
label: t("Brightness off", "Luminosità a zero"),
|
|
81481
82064
|
phrase: t("Dim {device} to zero", "Abbassa {device} a zero"),
|
|
81482
82065
|
icon: "lightbulb-off",
|
|
81483
|
-
args: {
|
|
82066
|
+
args: { level: 0 }
|
|
81484
82067
|
},
|
|
81485
82068
|
{
|
|
81486
82069
|
id: "brightness.set",
|
|
81487
82070
|
method: "setBrightness",
|
|
81488
82071
|
label: t("Set brightness", "Imposta la luminosità"),
|
|
81489
|
-
phrase: t("Set the brightness of {device} to {
|
|
82072
|
+
phrase: t("Set the brightness of {device} to {level}", "Imposta la luminosità di {device} a {level}"),
|
|
81490
82073
|
icon: "sun-medium",
|
|
81491
82074
|
openArgs: [{
|
|
81492
|
-
key: "
|
|
82075
|
+
key: "level",
|
|
81493
82076
|
label: PERCENT,
|
|
81494
82077
|
offer: {
|
|
81495
82078
|
kind: "number",
|
|
@@ -81503,13 +82086,13 @@ var ACTUATOR_CAP_VOCABULARY = {
|
|
|
81503
82086
|
],
|
|
81504
82087
|
state: [{
|
|
81505
82088
|
kind: "numeric",
|
|
81506
|
-
field: "
|
|
82089
|
+
field: "level",
|
|
81507
82090
|
quantity: t("the brightness", "la luminosità"),
|
|
81508
82091
|
label: t("Brightness", "Luminosità"),
|
|
81509
82092
|
unit: "%",
|
|
81510
82093
|
icon: "sun"
|
|
81511
82094
|
}],
|
|
81512
|
-
events: { onBrightnessChanged: { notOperatorFacing: "the `
|
|
82095
|
+
events: { onBrightnessChanged: { notOperatorFacing: "the `level` state trigger reads the same change" } }
|
|
81513
82096
|
},
|
|
81514
82097
|
color: {
|
|
81515
82098
|
scope: "device",
|
|
@@ -81523,7 +82106,7 @@ var ACTUATOR_CAP_VOCABULARY = {
|
|
|
81523
82106
|
icon: "sun",
|
|
81524
82107
|
args: { color: {
|
|
81525
82108
|
mode: "mired",
|
|
81526
|
-
|
|
82109
|
+
colorTemperature: 370
|
|
81527
82110
|
} }
|
|
81528
82111
|
},
|
|
81529
82112
|
{
|
|
@@ -81534,7 +82117,7 @@ var ACTUATOR_CAP_VOCABULARY = {
|
|
|
81534
82117
|
icon: "snowflake",
|
|
81535
82118
|
args: { color: {
|
|
81536
82119
|
mode: "mired",
|
|
81537
|
-
|
|
82120
|
+
colorTemperature: 200
|
|
81538
82121
|
} }
|
|
81539
82122
|
},
|
|
81540
82123
|
{
|
|
@@ -82148,7 +82731,7 @@ var ACTUATOR_CAP_VOCABULARY = {
|
|
|
82148
82731
|
label: t("Fan off", "Ventilatore spento"),
|
|
82149
82732
|
phrase: t("Stop {device}", "Ferma {device}"),
|
|
82150
82733
|
icon: "power-off",
|
|
82151
|
-
args: {
|
|
82734
|
+
args: { speed: 0 }
|
|
82152
82735
|
},
|
|
82153
82736
|
{
|
|
82154
82737
|
id: "fan.full",
|
|
@@ -82156,16 +82739,16 @@ var ACTUATOR_CAP_VOCABULARY = {
|
|
|
82156
82739
|
label: t("Fan full", "Ventilatore al massimo"),
|
|
82157
82740
|
phrase: t("Run {device} at full speed", "Porta {device} alla massima velocità"),
|
|
82158
82741
|
icon: "fan",
|
|
82159
|
-
args: {
|
|
82742
|
+
args: { speed: 100 }
|
|
82160
82743
|
},
|
|
82161
82744
|
{
|
|
82162
82745
|
id: "fan.speed",
|
|
82163
82746
|
method: "setPercentage",
|
|
82164
82747
|
label: t("Set speed", "Imposta la velocità"),
|
|
82165
|
-
phrase: t("Set the speed of {device} to {
|
|
82748
|
+
phrase: t("Set the speed of {device} to {speed}", "Imposta la velocità di {device} al {speed}"),
|
|
82166
82749
|
icon: "fan",
|
|
82167
82750
|
openArgs: [{
|
|
82168
|
-
key: "
|
|
82751
|
+
key: "speed",
|
|
82169
82752
|
label: t("Speed", "Velocità"),
|
|
82170
82753
|
offer: {
|
|
82171
82754
|
kind: "number",
|
|
@@ -82227,7 +82810,7 @@ var ACTUATOR_CAP_VOCABULARY = {
|
|
|
82227
82810
|
],
|
|
82228
82811
|
state: [{
|
|
82229
82812
|
kind: "numeric",
|
|
82230
|
-
field: "
|
|
82813
|
+
field: "speed",
|
|
82231
82814
|
quantity: t("the speed", "la velocità"),
|
|
82232
82815
|
label: t("Speed", "Velocità"),
|
|
82233
82816
|
unit: "%",
|
|
@@ -83025,7 +83608,7 @@ var APPLIANCE_CAP_VOCABULARY = {
|
|
|
83025
83608
|
},
|
|
83026
83609
|
{
|
|
83027
83610
|
kind: "numeric",
|
|
83028
|
-
field: "
|
|
83611
|
+
field: "progress",
|
|
83029
83612
|
quantity: t("the cycle progress", "l’avanzamento del lavaggio"),
|
|
83030
83613
|
label: t("Progress", "Avanzamento"),
|
|
83031
83614
|
unit: "%",
|
|
@@ -83383,10 +83966,10 @@ var APPLIANCE_CAP_VOCABULARY = {
|
|
|
83383
83966
|
id: "media.seek",
|
|
83384
83967
|
method: "seek",
|
|
83385
83968
|
label: t("Seek", "Vai al punto"),
|
|
83386
|
-
phrase: t("Move {device} to {
|
|
83969
|
+
phrase: t("Move {device} to {position}", "Porta {device} al punto {position}"),
|
|
83387
83970
|
icon: "fast-forward",
|
|
83388
83971
|
openArgs: [{
|
|
83389
|
-
key: "
|
|
83972
|
+
key: "position",
|
|
83390
83973
|
label: t("Position", "Posizione"),
|
|
83391
83974
|
offer: {
|
|
83392
83975
|
kind: "number",
|
|
@@ -84435,7 +85018,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84435
85018
|
state: [
|
|
84436
85019
|
{
|
|
84437
85020
|
kind: "numeric",
|
|
84438
|
-
field: "
|
|
85021
|
+
field: "co2",
|
|
84439
85022
|
quantity: t("the CO₂", "la CO₂"),
|
|
84440
85023
|
label: t("CO₂", "CO₂"),
|
|
84441
85024
|
unit: "ppm",
|
|
@@ -84443,7 +85026,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84443
85026
|
},
|
|
84444
85027
|
{
|
|
84445
85028
|
kind: "numeric",
|
|
84446
|
-
field: "
|
|
85029
|
+
field: "voc",
|
|
84447
85030
|
quantity: t("the VOC level", "il livello di COV"),
|
|
84448
85031
|
label: t("VOC", "COV"),
|
|
84449
85032
|
unit: "ppb",
|
|
@@ -84479,7 +85062,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84479
85062
|
noun: t("Light level", "Luminosità ambiente"),
|
|
84480
85063
|
state: [{
|
|
84481
85064
|
kind: "numeric",
|
|
84482
|
-
field: "
|
|
85065
|
+
field: "illuminance",
|
|
84483
85066
|
quantity: t("the light level", "la luminosità"),
|
|
84484
85067
|
label: t("Illuminance", "Illuminamento"),
|
|
84485
85068
|
unit: "lx",
|
|
@@ -84682,7 +85265,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84682
85265
|
noun: t("Humidity", "Umidità"),
|
|
84683
85266
|
state: [{
|
|
84684
85267
|
kind: "numeric",
|
|
84685
|
-
field: "
|
|
85268
|
+
field: "humidity",
|
|
84686
85269
|
quantity: t("the humidity", "l’umidità"),
|
|
84687
85270
|
label: t("Humidity", "Umidità"),
|
|
84688
85271
|
unit: "%",
|
|
@@ -84730,7 +85313,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84730
85313
|
state: [
|
|
84731
85314
|
{
|
|
84732
85315
|
kind: "numeric",
|
|
84733
|
-
field: "
|
|
85316
|
+
field: "power",
|
|
84734
85317
|
quantity: t("the power draw", "il consumo"),
|
|
84735
85318
|
label: t("Power", "Potenza"),
|
|
84736
85319
|
unit: "W",
|
|
@@ -84738,7 +85321,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84738
85321
|
},
|
|
84739
85322
|
{
|
|
84740
85323
|
kind: "numeric",
|
|
84741
|
-
field: "
|
|
85324
|
+
field: "energy",
|
|
84742
85325
|
quantity: t("the energy used", "l’energia consumata"),
|
|
84743
85326
|
label: t("Energy", "Energia"),
|
|
84744
85327
|
unit: "kWh",
|
|
@@ -84746,7 +85329,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84746
85329
|
},
|
|
84747
85330
|
{
|
|
84748
85331
|
kind: "numeric",
|
|
84749
|
-
field: "
|
|
85332
|
+
field: "voltage",
|
|
84750
85333
|
quantity: t("the voltage", "la tensione"),
|
|
84751
85334
|
label: t("Voltage", "Tensione"),
|
|
84752
85335
|
unit: "V",
|
|
@@ -84754,7 +85337,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84754
85337
|
},
|
|
84755
85338
|
{
|
|
84756
85339
|
kind: "numeric",
|
|
84757
|
-
field: "
|
|
85340
|
+
field: "current",
|
|
84758
85341
|
quantity: t("the current", "la corrente"),
|
|
84759
85342
|
label: t("Current", "Corrente"),
|
|
84760
85343
|
unit: "A",
|
|
@@ -84771,13 +85354,6 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84771
85354
|
label: t("Where", "Posizione"),
|
|
84772
85355
|
phrase: t("When {device} is at {value}", "Quando {device} è in {value}"),
|
|
84773
85356
|
icon: "map-pin"
|
|
84774
|
-
}, {
|
|
84775
|
-
kind: "numeric",
|
|
84776
|
-
field: "batteryPercent",
|
|
84777
|
-
quantity: t("the phone battery", "la batteria del telefono"),
|
|
84778
|
-
label: t("Battery", "Batteria"),
|
|
84779
|
-
unit: "%",
|
|
84780
|
-
icon: "battery"
|
|
84781
85357
|
}]
|
|
84782
85358
|
},
|
|
84783
85359
|
"pressure-sensor": {
|
|
@@ -84785,7 +85361,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84785
85361
|
noun: t("Pressure", "Pressione"),
|
|
84786
85362
|
state: [{
|
|
84787
85363
|
kind: "numeric",
|
|
84788
|
-
field: "
|
|
85364
|
+
field: "pressure",
|
|
84789
85365
|
quantity: t("the pressure", "la pressione"),
|
|
84790
85366
|
label: t("Pressure", "Pressione"),
|
|
84791
85367
|
unit: "hPa",
|
|
@@ -84821,7 +85397,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84821
85397
|
noun: t("Temperature", "Temperatura"),
|
|
84822
85398
|
state: [{
|
|
84823
85399
|
kind: "numeric",
|
|
84824
|
-
field: "
|
|
85400
|
+
field: "temperature",
|
|
84825
85401
|
quantity: t("the temperature", "la temperatura"),
|
|
84826
85402
|
label: t("Temperature", "Temperatura"),
|
|
84827
85403
|
unit: "°C",
|
|
@@ -84892,7 +85468,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84892
85468
|
state: [
|
|
84893
85469
|
{
|
|
84894
85470
|
kind: "numeric",
|
|
84895
|
-
field: "
|
|
85471
|
+
field: "level",
|
|
84896
85472
|
quantity: t("the battery level", "il livello della batteria"),
|
|
84897
85473
|
label: t("Battery", "Batteria"),
|
|
84898
85474
|
unit: "%",
|
|
@@ -84934,7 +85510,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84934
85510
|
icon: "battery-charging"
|
|
84935
85511
|
}
|
|
84936
85512
|
],
|
|
84937
|
-
events: { onStatusChanged: { notOperatorFacing: "the
|
|
85513
|
+
events: { onStatusChanged: { notOperatorFacing: "the level / sleeping / charging state triggers each read one field of this change" } },
|
|
84938
85514
|
extraEvents: [{
|
|
84939
85515
|
category: EventCategory.DeviceAwake,
|
|
84940
85516
|
label: t("Woke up", "Risvegliato"),
|
|
@@ -84952,7 +85528,7 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
84952
85528
|
noun: t("Network link", "Collegamento di rete"),
|
|
84953
85529
|
state: [{
|
|
84954
85530
|
kind: "numeric",
|
|
84955
|
-
field: "
|
|
85531
|
+
field: "signal",
|
|
84956
85532
|
quantity: t("the signal strength", "l’intensità del segnale"),
|
|
84957
85533
|
label: t("Signal", "Segnale"),
|
|
84958
85534
|
unit: "%",
|
|
@@ -85045,6 +85621,8 @@ var ML = "model and training machinery — no device action";
|
|
|
85045
85621
|
var INTERNAL = "internal plumbing between addons — never operator-facing";
|
|
85046
85622
|
/** Every system-scoped cap, with why it is not a device's vocabulary. */
|
|
85047
85623
|
var SYSTEM_CAP_VOCABULARY = {
|
|
85624
|
+
"action-source": system(INTERNAL),
|
|
85625
|
+
actions: system("declared actions — run from the Actions page and from the cameras that link them"),
|
|
85048
85626
|
"addon-pages": system(UI_PLUMBING),
|
|
85049
85627
|
"addon-pages-source": system(UI_PLUMBING),
|
|
85050
85628
|
"addon-routes": system(UI_PLUMBING),
|
|
@@ -85241,6 +85819,31 @@ Object.freeze({
|
|
|
85241
85819
|
form: "single",
|
|
85242
85820
|
optional: false
|
|
85243
85821
|
}],
|
|
85822
|
+
"actions.get": [{
|
|
85823
|
+
name: "deviceId",
|
|
85824
|
+
form: "single",
|
|
85825
|
+
optional: true
|
|
85826
|
+
}],
|
|
85827
|
+
"actions.getLinks": [{
|
|
85828
|
+
name: "deviceId",
|
|
85829
|
+
form: "single",
|
|
85830
|
+
optional: false
|
|
85831
|
+
}],
|
|
85832
|
+
"actions.listForCamera": [{
|
|
85833
|
+
name: "deviceId",
|
|
85834
|
+
form: "single",
|
|
85835
|
+
optional: false
|
|
85836
|
+
}],
|
|
85837
|
+
"actions.run": [{
|
|
85838
|
+
name: "deviceId",
|
|
85839
|
+
form: "single",
|
|
85840
|
+
optional: true
|
|
85841
|
+
}],
|
|
85842
|
+
"actions.setLinks": [{
|
|
85843
|
+
name: "deviceId",
|
|
85844
|
+
form: "single",
|
|
85845
|
+
optional: false
|
|
85846
|
+
}],
|
|
85244
85847
|
"addonSettings.getDeviceSettings": [{
|
|
85245
85848
|
name: "deviceId",
|
|
85246
85849
|
form: "single",
|
|
@@ -89322,6 +89925,7 @@ DEFAULT_NATIVE_LEASE_SETTINGS.activityMs;
|
|
|
89322
89925
|
DEFAULT_NATIVE_LEASE_SETTINGS.tileBudgetMb;
|
|
89323
89926
|
DEFAULT_NATIVE_LEASE_SETTINGS.sceneBudgetMb;
|
|
89324
89927
|
DEFAULT_NATIVE_LEASE_SETTINGS.admission;
|
|
89928
|
+
String.raw`(?<=^|["'(\s>,\[{])`;
|
|
89325
89929
|
var MB = 1024 * 1024;
|
|
89326
89930
|
1024 * MB, 3072 * MB;
|
|
89327
89931
|
//#endregion
|
|
@@ -90085,7 +90689,6 @@ var COLD_PRESENCE = {
|
|
|
90085
90689
|
state: "not_home",
|
|
90086
90690
|
location: null,
|
|
90087
90691
|
gps: null,
|
|
90088
|
-
batteryPercent: null,
|
|
90089
90692
|
lastChangedAt: 0
|
|
90090
90693
|
};
|
|
90091
90694
|
/**
|
|
@@ -90216,7 +90819,7 @@ var UnifiFeatureDevice = class extends BaseDevice {
|
|
|
90216
90819
|
switch (capForMetric(this.metric)) {
|
|
90217
90820
|
case "temperature-sensor":
|
|
90218
90821
|
this.runtimeState.setCapState("temperature-sensor", {
|
|
90219
|
-
|
|
90822
|
+
temperature: infra.cpuTempC ?? 0,
|
|
90220
90823
|
lastFetchedAt: now
|
|
90221
90824
|
});
|
|
90222
90825
|
return;
|
|
@@ -90253,7 +90856,6 @@ var UnifiFeatureDevice = class extends BaseDevice {
|
|
|
90253
90856
|
state: client.connected ? "home" : "not_home",
|
|
90254
90857
|
location: client.ip,
|
|
90255
90858
|
gps: null,
|
|
90256
|
-
batteryPercent: null,
|
|
90257
90859
|
lastChangedAt: Date.now()
|
|
90258
90860
|
};
|
|
90259
90861
|
this.runtimeState.setCapState("presence", status);
|
|
@@ -90293,7 +90895,7 @@ var UnifiFeatureDevice = class extends BaseDevice {
|
|
|
90293
90895
|
switch (capForMetric(this.metric)) {
|
|
90294
90896
|
case "temperature-sensor": {
|
|
90295
90897
|
const COLD = {
|
|
90296
|
-
|
|
90898
|
+
temperature: 0,
|
|
90297
90899
|
lastFetchedAt: 0
|
|
90298
90900
|
};
|
|
90299
90901
|
this.ctx.registerNativeCap(temperatureSensorCapability, { getStatus: async () => this.runtimeState.getCapState("temperature-sensor") ?? COLD });
|