@camstack/addon-provider-enpal 0.1.22 → 0.1.23
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 +1663 -207
- package/dist/addon.mjs +1663 -207
- package/package.json +2 -2
package/dist/addon.js
CHANGED
|
@@ -3,7 +3,7 @@ let node_child_process = require("node:child_process");
|
|
|
3
3
|
let node_fs = require("node:fs");
|
|
4
4
|
let node_path = require("node:path");
|
|
5
5
|
let node_url = require("node:url");
|
|
6
|
-
//#region ../types/dist/event-category-
|
|
6
|
+
//#region ../types/dist/event-category-Dhcd0TRH.mjs
|
|
7
7
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
8
8
|
EventCategory["SystemBoot"] = "system.boot";
|
|
9
9
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -277,6 +277,18 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
277
277
|
EventCategory["StorageLocationCritical"] = "storage.location.critical";
|
|
278
278
|
/** Recovery from low/critical on a storage location. */
|
|
279
279
|
EventCategory["StorageLocationOk"] = "storage.location.ok";
|
|
280
|
+
/**
|
|
281
|
+
* A `drain` location's regular progress ping (#538) — location id + name,
|
|
282
|
+
* bytes remaining, the observed cede rate and the estimated empty date, or
|
|
283
|
+
* `null` fields when the occupancy read that sweep failed (D393: never
|
|
284
|
+
* folded to 0). Cadence is the named constant
|
|
285
|
+
* `DRAIN_PROGRESS_EVENT_INTERVAL_MS` (15 min) plus once on drain start — no
|
|
286
|
+
* operator knob. Telemetry (D8): a lost tick is a stale progress bar the
|
|
287
|
+
* next sweep corrects.
|
|
288
|
+
*/
|
|
289
|
+
EventCategory["StorageDrainProgress"] = "storage.drain.progress";
|
|
290
|
+
/** Fires once when a draining location reaches zero evictable bytes. */
|
|
291
|
+
EventCategory["StorageDrainComplete"] = "storage.drain.complete";
|
|
280
292
|
EventCategory["RecordingSegmentWritten"] = "recording.segment.written";
|
|
281
293
|
EventCategory["RecordingPolicyFallback"] = "recording.policy.fallback";
|
|
282
294
|
EventCategory["RecordingRetentionCompleted"] = "recording.retention.completed";
|
|
@@ -815,7 +827,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
815
827
|
return EventCategory;
|
|
816
828
|
}({});
|
|
817
829
|
//#endregion
|
|
818
|
-
//#region ../types/dist/composed-stable-id-
|
|
830
|
+
//#region ../types/dist/composed-stable-id-RvQIEpqg.mjs
|
|
819
831
|
/**
|
|
820
832
|
import { errMsg } from '@camstack/types'
|
|
821
833
|
* Extract a human-readable message from an unknown error value.
|
|
@@ -897,6 +909,9 @@ var DeviceType = /* @__PURE__ */ function(DeviceType) {
|
|
|
897
909
|
/** Weather provider (HA `weather.*`). Tier-3, low MVP priority.
|
|
898
910
|
* `weather` cap. */
|
|
899
911
|
DeviceType["Weather"] = "weather";
|
|
912
|
+
/** A physical weather station (Ecowitt outdoor array). `weather-station`
|
|
913
|
+
* cap. Distinct from {@link Weather}, which is a forecast provider. */
|
|
914
|
+
DeviceType["WeatherStation"] = "weather-station";
|
|
900
915
|
/** Robot vacuum (HA `vacuum.*`). Tier-3. `vacuum-control` cap. */
|
|
901
916
|
DeviceType["Vacuum"] = "vacuum";
|
|
902
917
|
/** Robotic lawn mower (HA `lawn_mower.*`). Tier-3.
|
|
@@ -6064,7 +6079,7 @@ var ZodIssueCode = {
|
|
|
6064
6079
|
var ZodFirstPartyTypeKind;
|
|
6065
6080
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
6066
6081
|
//#endregion
|
|
6067
|
-
//#region ../types/dist/sleep-
|
|
6082
|
+
//#region ../types/dist/sleep-CLDVTB5R.mjs
|
|
6068
6083
|
/**
|
|
6069
6084
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
6070
6085
|
* window to float samples (D455).
|
|
@@ -13446,6 +13461,76 @@ var CAP_VOCABULARY_BY_NAME = {
|
|
|
13446
13461
|
en: "Control",
|
|
13447
13462
|
it: "Controllo"
|
|
13448
13463
|
},
|
|
13464
|
+
actions: [
|
|
13465
|
+
{
|
|
13466
|
+
id: "select.next",
|
|
13467
|
+
method: "next",
|
|
13468
|
+
label: {
|
|
13469
|
+
en: "Next option",
|
|
13470
|
+
it: "Opzione successiva"
|
|
13471
|
+
},
|
|
13472
|
+
phrase: {
|
|
13473
|
+
en: "Select the next option on {device}",
|
|
13474
|
+
it: "Seleziona l’opzione successiva su {device}"
|
|
13475
|
+
},
|
|
13476
|
+
icon: "skip-forward",
|
|
13477
|
+
openArgs: [{
|
|
13478
|
+
key: "cycle",
|
|
13479
|
+
label: {
|
|
13480
|
+
en: "Wrap to the first option",
|
|
13481
|
+
it: "Ricomincia dalla prima opzione"
|
|
13482
|
+
},
|
|
13483
|
+
offer: { kind: "boolean" }
|
|
13484
|
+
}]
|
|
13485
|
+
},
|
|
13486
|
+
{
|
|
13487
|
+
id: "select.previous",
|
|
13488
|
+
method: "previous",
|
|
13489
|
+
label: {
|
|
13490
|
+
en: "Previous option",
|
|
13491
|
+
it: "Opzione precedente"
|
|
13492
|
+
},
|
|
13493
|
+
phrase: {
|
|
13494
|
+
en: "Select the previous option on {device}",
|
|
13495
|
+
it: "Seleziona l’opzione precedente su {device}"
|
|
13496
|
+
},
|
|
13497
|
+
icon: "skip-back",
|
|
13498
|
+
openArgs: [{
|
|
13499
|
+
key: "cycle",
|
|
13500
|
+
label: {
|
|
13501
|
+
en: "Wrap to the last option",
|
|
13502
|
+
it: "Ricomincia dall’ultima opzione"
|
|
13503
|
+
},
|
|
13504
|
+
offer: { kind: "boolean" }
|
|
13505
|
+
}]
|
|
13506
|
+
},
|
|
13507
|
+
{
|
|
13508
|
+
id: "select.first",
|
|
13509
|
+
method: "first",
|
|
13510
|
+
label: {
|
|
13511
|
+
en: "First option",
|
|
13512
|
+
it: "Prima opzione"
|
|
13513
|
+
},
|
|
13514
|
+
phrase: {
|
|
13515
|
+
en: "Select the first option on {device}",
|
|
13516
|
+
it: "Seleziona la prima opzione su {device}"
|
|
13517
|
+
},
|
|
13518
|
+
icon: "chevron-first"
|
|
13519
|
+
},
|
|
13520
|
+
{
|
|
13521
|
+
id: "select.last",
|
|
13522
|
+
method: "last",
|
|
13523
|
+
label: {
|
|
13524
|
+
en: "Last option",
|
|
13525
|
+
it: "Ultima opzione"
|
|
13526
|
+
},
|
|
13527
|
+
phrase: {
|
|
13528
|
+
en: "Select the last option on {device}",
|
|
13529
|
+
it: "Seleziona l’ultima opzione su {device}"
|
|
13530
|
+
},
|
|
13531
|
+
icon: "chevron-last"
|
|
13532
|
+
}
|
|
13533
|
+
],
|
|
13449
13534
|
notOperatorFacing: { setValue: "the value shape depends on the control kind (numeric / select / text / datetime) read from status; a typed picker for it is a follow-up of the automations rework" },
|
|
13450
13535
|
state: [{
|
|
13451
13536
|
kind: "value",
|
|
@@ -18592,6 +18677,295 @@ var CAP_VOCABULARY_BY_NAME = {
|
|
|
18592
18677
|
}
|
|
18593
18678
|
]
|
|
18594
18679
|
},
|
|
18680
|
+
"weather-station": {
|
|
18681
|
+
scope: "device",
|
|
18682
|
+
noun: {
|
|
18683
|
+
en: "Weather station",
|
|
18684
|
+
it: "Stazione meteo"
|
|
18685
|
+
},
|
|
18686
|
+
state: [
|
|
18687
|
+
{
|
|
18688
|
+
kind: "numeric",
|
|
18689
|
+
field: "temperature",
|
|
18690
|
+
quantity: {
|
|
18691
|
+
en: "the outdoor temperature",
|
|
18692
|
+
it: "la temperatura esterna"
|
|
18693
|
+
},
|
|
18694
|
+
label: {
|
|
18695
|
+
en: "Temperature",
|
|
18696
|
+
it: "Temperatura"
|
|
18697
|
+
},
|
|
18698
|
+
unit: "°C",
|
|
18699
|
+
icon: "thermometer"
|
|
18700
|
+
},
|
|
18701
|
+
{
|
|
18702
|
+
kind: "numeric",
|
|
18703
|
+
field: "humidity",
|
|
18704
|
+
quantity: {
|
|
18705
|
+
en: "the outdoor humidity",
|
|
18706
|
+
it: "l’umidità esterna"
|
|
18707
|
+
},
|
|
18708
|
+
label: {
|
|
18709
|
+
en: "Humidity",
|
|
18710
|
+
it: "Umidità"
|
|
18711
|
+
},
|
|
18712
|
+
unit: "%",
|
|
18713
|
+
icon: "droplets"
|
|
18714
|
+
},
|
|
18715
|
+
{
|
|
18716
|
+
kind: "numeric",
|
|
18717
|
+
field: "pressure",
|
|
18718
|
+
quantity: {
|
|
18719
|
+
en: "the air pressure",
|
|
18720
|
+
it: "la pressione atmosferica"
|
|
18721
|
+
},
|
|
18722
|
+
label: {
|
|
18723
|
+
en: "Pressure",
|
|
18724
|
+
it: "Pressione"
|
|
18725
|
+
},
|
|
18726
|
+
unit: "hPa",
|
|
18727
|
+
icon: "gauge"
|
|
18728
|
+
},
|
|
18729
|
+
{
|
|
18730
|
+
kind: "numeric",
|
|
18731
|
+
field: "windSpeed",
|
|
18732
|
+
quantity: {
|
|
18733
|
+
en: "the wind speed",
|
|
18734
|
+
it: "la velocità del vento"
|
|
18735
|
+
},
|
|
18736
|
+
label: {
|
|
18737
|
+
en: "Wind",
|
|
18738
|
+
it: "Vento"
|
|
18739
|
+
},
|
|
18740
|
+
unit: "m/s",
|
|
18741
|
+
icon: "wind"
|
|
18742
|
+
},
|
|
18743
|
+
{
|
|
18744
|
+
kind: "numeric",
|
|
18745
|
+
field: "windGust",
|
|
18746
|
+
quantity: {
|
|
18747
|
+
en: "the wind gust",
|
|
18748
|
+
it: "la raffica di vento"
|
|
18749
|
+
},
|
|
18750
|
+
label: {
|
|
18751
|
+
en: "Gust",
|
|
18752
|
+
it: "Raffica"
|
|
18753
|
+
},
|
|
18754
|
+
unit: "m/s",
|
|
18755
|
+
icon: "wind"
|
|
18756
|
+
},
|
|
18757
|
+
{
|
|
18758
|
+
kind: "numeric",
|
|
18759
|
+
field: "windBearing",
|
|
18760
|
+
quantity: {
|
|
18761
|
+
en: "the wind bearing",
|
|
18762
|
+
it: "la direzione del vento"
|
|
18763
|
+
},
|
|
18764
|
+
label: {
|
|
18765
|
+
en: "Wind bearing",
|
|
18766
|
+
it: "Direzione del vento"
|
|
18767
|
+
},
|
|
18768
|
+
unit: "°",
|
|
18769
|
+
icon: "wind"
|
|
18770
|
+
},
|
|
18771
|
+
{
|
|
18772
|
+
kind: "numeric",
|
|
18773
|
+
field: "rainRate",
|
|
18774
|
+
quantity: {
|
|
18775
|
+
en: "the rain rate",
|
|
18776
|
+
it: "l’intensità della pioggia"
|
|
18777
|
+
},
|
|
18778
|
+
label: {
|
|
18779
|
+
en: "Rain rate",
|
|
18780
|
+
it: "Intensità pioggia"
|
|
18781
|
+
},
|
|
18782
|
+
unit: "mm/h",
|
|
18783
|
+
icon: "droplets"
|
|
18784
|
+
},
|
|
18785
|
+
{
|
|
18786
|
+
kind: "numeric",
|
|
18787
|
+
field: "rainDaily",
|
|
18788
|
+
quantity: {
|
|
18789
|
+
en: "the rain today",
|
|
18790
|
+
it: "la pioggia di oggi"
|
|
18791
|
+
},
|
|
18792
|
+
label: {
|
|
18793
|
+
en: "Rain today",
|
|
18794
|
+
it: "Pioggia oggi"
|
|
18795
|
+
},
|
|
18796
|
+
unit: "mm",
|
|
18797
|
+
icon: "droplets"
|
|
18798
|
+
},
|
|
18799
|
+
{
|
|
18800
|
+
kind: "numeric",
|
|
18801
|
+
field: "rainEvent",
|
|
18802
|
+
quantity: {
|
|
18803
|
+
en: "the rain this event",
|
|
18804
|
+
it: "la pioggia di questo evento"
|
|
18805
|
+
},
|
|
18806
|
+
label: {
|
|
18807
|
+
en: "Rain event",
|
|
18808
|
+
it: "Evento di pioggia"
|
|
18809
|
+
},
|
|
18810
|
+
unit: "mm",
|
|
18811
|
+
icon: "droplets"
|
|
18812
|
+
},
|
|
18813
|
+
{
|
|
18814
|
+
kind: "numeric",
|
|
18815
|
+
field: "uv",
|
|
18816
|
+
quantity: {
|
|
18817
|
+
en: "the UV index",
|
|
18818
|
+
it: "l’indice UV"
|
|
18819
|
+
},
|
|
18820
|
+
label: {
|
|
18821
|
+
en: "UV",
|
|
18822
|
+
it: "UV"
|
|
18823
|
+
},
|
|
18824
|
+
unit: "",
|
|
18825
|
+
icon: "cloud-sun"
|
|
18826
|
+
},
|
|
18827
|
+
{
|
|
18828
|
+
kind: "numeric",
|
|
18829
|
+
field: "solarRadiation",
|
|
18830
|
+
quantity: {
|
|
18831
|
+
en: "the solar radiation",
|
|
18832
|
+
it: "la radiazione solare"
|
|
18833
|
+
},
|
|
18834
|
+
label: {
|
|
18835
|
+
en: "Solar",
|
|
18836
|
+
it: "Sole"
|
|
18837
|
+
},
|
|
18838
|
+
unit: "W/m²",
|
|
18839
|
+
icon: "cloud-sun"
|
|
18840
|
+
},
|
|
18841
|
+
{
|
|
18842
|
+
kind: "numeric",
|
|
18843
|
+
field: "dewPoint",
|
|
18844
|
+
quantity: {
|
|
18845
|
+
en: "the dew point",
|
|
18846
|
+
it: "il punto di rugiada"
|
|
18847
|
+
},
|
|
18848
|
+
label: {
|
|
18849
|
+
en: "Dew point",
|
|
18850
|
+
it: "Punto di rugiada"
|
|
18851
|
+
},
|
|
18852
|
+
unit: "°C",
|
|
18853
|
+
icon: "thermometer"
|
|
18854
|
+
},
|
|
18855
|
+
{
|
|
18856
|
+
kind: "numeric",
|
|
18857
|
+
field: "feelsLike",
|
|
18858
|
+
quantity: {
|
|
18859
|
+
en: "the feels-like temperature",
|
|
18860
|
+
it: "la temperatura percepita"
|
|
18861
|
+
},
|
|
18862
|
+
label: {
|
|
18863
|
+
en: "Feels like",
|
|
18864
|
+
it: "Percepita"
|
|
18865
|
+
},
|
|
18866
|
+
unit: "°C",
|
|
18867
|
+
icon: "thermometer"
|
|
18868
|
+
},
|
|
18869
|
+
{
|
|
18870
|
+
kind: "numeric",
|
|
18871
|
+
field: "vpd",
|
|
18872
|
+
quantity: {
|
|
18873
|
+
en: "the vapour-pressure deficit",
|
|
18874
|
+
it: "il deficit di pressione di vapore"
|
|
18875
|
+
},
|
|
18876
|
+
label: {
|
|
18877
|
+
en: "VPD",
|
|
18878
|
+
it: "VPD"
|
|
18879
|
+
},
|
|
18880
|
+
unit: "kPa",
|
|
18881
|
+
icon: "gauge"
|
|
18882
|
+
},
|
|
18883
|
+
{
|
|
18884
|
+
kind: "numeric",
|
|
18885
|
+
field: "windGustMax",
|
|
18886
|
+
quantity: {
|
|
18887
|
+
en: "the highest gust today",
|
|
18888
|
+
it: "la raffica massima di oggi"
|
|
18889
|
+
},
|
|
18890
|
+
label: {
|
|
18891
|
+
en: "Max gust",
|
|
18892
|
+
it: "Raffica max"
|
|
18893
|
+
},
|
|
18894
|
+
unit: "m/s",
|
|
18895
|
+
icon: "wind"
|
|
18896
|
+
},
|
|
18897
|
+
{
|
|
18898
|
+
kind: "numeric",
|
|
18899
|
+
field: "windBearingAvg",
|
|
18900
|
+
quantity: {
|
|
18901
|
+
en: "the average wind bearing",
|
|
18902
|
+
it: "la direzione media del vento"
|
|
18903
|
+
},
|
|
18904
|
+
label: {
|
|
18905
|
+
en: "Avg bearing",
|
|
18906
|
+
it: "Direzione media"
|
|
18907
|
+
},
|
|
18908
|
+
unit: "°",
|
|
18909
|
+
icon: "wind"
|
|
18910
|
+
},
|
|
18911
|
+
{
|
|
18912
|
+
kind: "numeric",
|
|
18913
|
+
field: "rain24h",
|
|
18914
|
+
quantity: {
|
|
18915
|
+
en: "the rain in the last 24 hours",
|
|
18916
|
+
it: "la pioggia delle ultime 24 ore"
|
|
18917
|
+
},
|
|
18918
|
+
label: {
|
|
18919
|
+
en: "Rain 24 h",
|
|
18920
|
+
it: "Pioggia 24 h"
|
|
18921
|
+
},
|
|
18922
|
+
unit: "mm",
|
|
18923
|
+
icon: "droplets"
|
|
18924
|
+
},
|
|
18925
|
+
{
|
|
18926
|
+
kind: "numeric",
|
|
18927
|
+
field: "rainWeekly",
|
|
18928
|
+
quantity: {
|
|
18929
|
+
en: "the rain this week",
|
|
18930
|
+
it: "la pioggia di questa settimana"
|
|
18931
|
+
},
|
|
18932
|
+
label: {
|
|
18933
|
+
en: "Rain week",
|
|
18934
|
+
it: "Pioggia settimana"
|
|
18935
|
+
},
|
|
18936
|
+
unit: "mm",
|
|
18937
|
+
icon: "droplets"
|
|
18938
|
+
},
|
|
18939
|
+
{
|
|
18940
|
+
kind: "numeric",
|
|
18941
|
+
field: "rainMonthly",
|
|
18942
|
+
quantity: {
|
|
18943
|
+
en: "the rain this month",
|
|
18944
|
+
it: "la pioggia di questo mese"
|
|
18945
|
+
},
|
|
18946
|
+
label: {
|
|
18947
|
+
en: "Rain month",
|
|
18948
|
+
it: "Pioggia mese"
|
|
18949
|
+
},
|
|
18950
|
+
unit: "mm",
|
|
18951
|
+
icon: "droplets"
|
|
18952
|
+
},
|
|
18953
|
+
{
|
|
18954
|
+
kind: "numeric",
|
|
18955
|
+
field: "rainYearly",
|
|
18956
|
+
quantity: {
|
|
18957
|
+
en: "the rain this year",
|
|
18958
|
+
it: "la pioggia di quest’anno"
|
|
18959
|
+
},
|
|
18960
|
+
label: {
|
|
18961
|
+
en: "Rain year",
|
|
18962
|
+
it: "Pioggia anno"
|
|
18963
|
+
},
|
|
18964
|
+
unit: "mm",
|
|
18965
|
+
icon: "droplets"
|
|
18966
|
+
}
|
|
18967
|
+
]
|
|
18968
|
+
},
|
|
18595
18969
|
"battery": {
|
|
18596
18970
|
scope: "device",
|
|
18597
18971
|
noun: {
|
|
@@ -18816,6 +19190,30 @@ var CAP_VOCABULARY_BY_NAME = {
|
|
|
18816
19190
|
icon: "wifi-off"
|
|
18817
19191
|
}]
|
|
18818
19192
|
},
|
|
19193
|
+
"error": {
|
|
19194
|
+
scope: "device",
|
|
19195
|
+
noun: {
|
|
19196
|
+
en: "Fault",
|
|
19197
|
+
it: "Guasto"
|
|
19198
|
+
},
|
|
19199
|
+
state: [{
|
|
19200
|
+
kind: "boolean",
|
|
19201
|
+
field: "active",
|
|
19202
|
+
label: {
|
|
19203
|
+
en: "Fault",
|
|
19204
|
+
it: "Guasto"
|
|
19205
|
+
},
|
|
19206
|
+
whenTrue: {
|
|
19207
|
+
en: "When {device} reports a fault",
|
|
19208
|
+
it: "Quando {device} segnala un guasto"
|
|
19209
|
+
},
|
|
19210
|
+
whenFalse: {
|
|
19211
|
+
en: "When the fault of {device} clears",
|
|
19212
|
+
it: "Quando il guasto di {device} si risolve"
|
|
19213
|
+
},
|
|
19214
|
+
icon: "triangle-alert"
|
|
19215
|
+
}]
|
|
19216
|
+
},
|
|
18819
19217
|
"doorbell": {
|
|
18820
19218
|
scope: "device",
|
|
18821
19219
|
noun: {
|
|
@@ -19506,6 +19904,7 @@ var CAP_NAMES = Object.freeze([
|
|
|
19506
19904
|
"embedding-encoder",
|
|
19507
19905
|
"energy-system",
|
|
19508
19906
|
"enum-sensor",
|
|
19907
|
+
"error",
|
|
19509
19908
|
"event-emitter",
|
|
19510
19909
|
"face-gallery",
|
|
19511
19910
|
"failure-contribution",
|
|
@@ -19636,6 +20035,7 @@ var CAP_NAMES = Object.freeze([
|
|
|
19636
20035
|
"viewer-ui",
|
|
19637
20036
|
"water-heater",
|
|
19638
20037
|
"weather",
|
|
20038
|
+
"weather-station",
|
|
19639
20039
|
"webrtc-session",
|
|
19640
20040
|
"zone-analytics",
|
|
19641
20041
|
"zone-rules",
|
|
@@ -19915,6 +20315,18 @@ Object.freeze({
|
|
|
19915
20315
|
"dry"
|
|
19916
20316
|
]
|
|
19917
20317
|
},
|
|
20318
|
+
{
|
|
20319
|
+
"path": "action",
|
|
20320
|
+
"valueType": "enum",
|
|
20321
|
+
"enumValues": [
|
|
20322
|
+
"heating",
|
|
20323
|
+
"cooling",
|
|
20324
|
+
"drying",
|
|
20325
|
+
"fan",
|
|
20326
|
+
"idle",
|
|
20327
|
+
"off"
|
|
20328
|
+
]
|
|
20329
|
+
},
|
|
19918
20330
|
{
|
|
19919
20331
|
"path": "fanMode",
|
|
19920
20332
|
"valueType": "string"
|
|
@@ -20383,6 +20795,29 @@ Object.freeze({
|
|
|
20383
20795
|
"path": "timestamp",
|
|
20384
20796
|
"valueType": "boolean"
|
|
20385
20797
|
}],
|
|
20798
|
+
"error": [
|
|
20799
|
+
{
|
|
20800
|
+
"path": "active",
|
|
20801
|
+
"valueType": "boolean"
|
|
20802
|
+
},
|
|
20803
|
+
{
|
|
20804
|
+
"path": "code",
|
|
20805
|
+
"valueType": "string"
|
|
20806
|
+
},
|
|
20807
|
+
{
|
|
20808
|
+
"path": "label",
|
|
20809
|
+
"valueType": "string"
|
|
20810
|
+
},
|
|
20811
|
+
{
|
|
20812
|
+
"path": "severity",
|
|
20813
|
+
"valueType": "enum",
|
|
20814
|
+
"enumValues": ["warning", "error"]
|
|
20815
|
+
},
|
|
20816
|
+
{
|
|
20817
|
+
"path": "since",
|
|
20818
|
+
"valueType": "number"
|
|
20819
|
+
}
|
|
20820
|
+
],
|
|
20386
20821
|
"event-emitter": [
|
|
20387
20822
|
{
|
|
20388
20823
|
"path": "lastEvent.deviceId",
|
|
@@ -21602,6 +22037,88 @@ Object.freeze({
|
|
|
21602
22037
|
"valueType": "number"
|
|
21603
22038
|
}
|
|
21604
22039
|
],
|
|
22040
|
+
"weather-station": [
|
|
22041
|
+
{
|
|
22042
|
+
"path": "temperature",
|
|
22043
|
+
"valueType": "number"
|
|
22044
|
+
},
|
|
22045
|
+
{
|
|
22046
|
+
"path": "humidity",
|
|
22047
|
+
"valueType": "number"
|
|
22048
|
+
},
|
|
22049
|
+
{
|
|
22050
|
+
"path": "pressure",
|
|
22051
|
+
"valueType": "number"
|
|
22052
|
+
},
|
|
22053
|
+
{
|
|
22054
|
+
"path": "windSpeed",
|
|
22055
|
+
"valueType": "number"
|
|
22056
|
+
},
|
|
22057
|
+
{
|
|
22058
|
+
"path": "windGust",
|
|
22059
|
+
"valueType": "number"
|
|
22060
|
+
},
|
|
22061
|
+
{
|
|
22062
|
+
"path": "windBearing",
|
|
22063
|
+
"valueType": "number"
|
|
22064
|
+
},
|
|
22065
|
+
{
|
|
22066
|
+
"path": "rainRate",
|
|
22067
|
+
"valueType": "number"
|
|
22068
|
+
},
|
|
22069
|
+
{
|
|
22070
|
+
"path": "rainDaily",
|
|
22071
|
+
"valueType": "number"
|
|
22072
|
+
},
|
|
22073
|
+
{
|
|
22074
|
+
"path": "rainEvent",
|
|
22075
|
+
"valueType": "number"
|
|
22076
|
+
},
|
|
22077
|
+
{
|
|
22078
|
+
"path": "uv",
|
|
22079
|
+
"valueType": "number"
|
|
22080
|
+
},
|
|
22081
|
+
{
|
|
22082
|
+
"path": "solarRadiation",
|
|
22083
|
+
"valueType": "number"
|
|
22084
|
+
},
|
|
22085
|
+
{
|
|
22086
|
+
"path": "dewPoint",
|
|
22087
|
+
"valueType": "number"
|
|
22088
|
+
},
|
|
22089
|
+
{
|
|
22090
|
+
"path": "feelsLike",
|
|
22091
|
+
"valueType": "number"
|
|
22092
|
+
},
|
|
22093
|
+
{
|
|
22094
|
+
"path": "vpd",
|
|
22095
|
+
"valueType": "number"
|
|
22096
|
+
},
|
|
22097
|
+
{
|
|
22098
|
+
"path": "windGustMax",
|
|
22099
|
+
"valueType": "number"
|
|
22100
|
+
},
|
|
22101
|
+
{
|
|
22102
|
+
"path": "windBearingAvg",
|
|
22103
|
+
"valueType": "number"
|
|
22104
|
+
},
|
|
22105
|
+
{
|
|
22106
|
+
"path": "rain24h",
|
|
22107
|
+
"valueType": "number"
|
|
22108
|
+
},
|
|
22109
|
+
{
|
|
22110
|
+
"path": "rainWeekly",
|
|
22111
|
+
"valueType": "number"
|
|
22112
|
+
},
|
|
22113
|
+
{
|
|
22114
|
+
"path": "rainMonthly",
|
|
22115
|
+
"valueType": "number"
|
|
22116
|
+
},
|
|
22117
|
+
{
|
|
22118
|
+
"path": "rainYearly",
|
|
22119
|
+
"valueType": "number"
|
|
22120
|
+
}
|
|
22121
|
+
],
|
|
21605
22122
|
"zone-analytics": [
|
|
21606
22123
|
{
|
|
21607
22124
|
"path": "ts",
|
|
@@ -21694,7 +22211,7 @@ Object.freeze({
|
|
|
21694
22211
|
}
|
|
21695
22212
|
});
|
|
21696
22213
|
//#endregion
|
|
21697
|
-
//#region ../types/dist/implemented-methods-
|
|
22214
|
+
//#region ../types/dist/implemented-methods-C5FMXLGP.mjs
|
|
21698
22215
|
/**
|
|
21699
22216
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
21700
22217
|
*
|
|
@@ -48023,69 +48540,6 @@ var EventVocabularyEntrySchema = object({
|
|
|
48023
48540
|
kind: EventVocabularyKindSchema.optional(),
|
|
48024
48541
|
payload: array(EventVocabularyFieldSchema).optional()
|
|
48025
48542
|
});
|
|
48026
|
-
/**
|
|
48027
|
-
* The link an automation made FROM a template carries (#527): which template,
|
|
48028
|
-
* the values the operator filled in, and — when the template has since changed
|
|
48029
|
-
* so that those values no longer fit — the problems that say why.
|
|
48030
|
-
*
|
|
48031
|
-
* It lives inside the recipe (`AutomationRecipe.template`), so the one row in
|
|
48032
|
-
* `core_blocks` stays the one artefact: there is no second store of instances
|
|
48033
|
-
* to drift from the blocks, and deleting the automation deletes the link.
|
|
48034
|
-
* "Convert to a free automation" is dropping this field.
|
|
48035
|
-
*
|
|
48036
|
-
* This file depends on nothing in `recipe.ts`, so the recipe can embed it and
|
|
48037
|
-
* the template engine (`template/automation-template.ts`) can import both.
|
|
48038
|
-
*/
|
|
48039
|
-
/** An `event` input's value: the same three narrowing lists a `device-fired` row takes. */
|
|
48040
|
-
var TemplateEventValueSchema = object({
|
|
48041
|
-
eventIds: array(string().min(1)).min(1).max(64).optional(),
|
|
48042
|
-
sourceIds: array(string().min(1)).min(1).max(64).optional(),
|
|
48043
|
-
kinds: array(EventVocabularyKindSchema).min(1).optional()
|
|
48044
|
-
}).refine((value) => value.eventIds !== void 0 || value.sourceIds !== void 0 || value.kinds !== void 0, { message: "an event names at least one event, part or kind" });
|
|
48045
|
-
/** An `action` input's value: a vocabulary action and its open args. */
|
|
48046
|
-
var TemplateActionValueSchema = object({
|
|
48047
|
-
actionId: string().min(1),
|
|
48048
|
-
args: record(string(), unknown()).optional()
|
|
48049
|
-
});
|
|
48050
|
-
/** The value of one non-group input. Which member is right is the input kind's to judge. */
|
|
48051
|
-
var TemplateScalarValueSchema = union([
|
|
48052
|
-
number$1(),
|
|
48053
|
-
string(),
|
|
48054
|
-
boolean(),
|
|
48055
|
-
array(number$1().int().nonnegative()),
|
|
48056
|
-
TemplateEventValueSchema,
|
|
48057
|
-
TemplateActionValueSchema
|
|
48058
|
-
]);
|
|
48059
|
-
var TemplateInputValueSchema = union([TemplateScalarValueSchema, array(record(string(), TemplateScalarValueSchema))]);
|
|
48060
|
-
/** Input key → value. */
|
|
48061
|
-
var TemplateInputValuesSchema = record(string(), TemplateInputValueSchema);
|
|
48062
|
-
var TemplateInstanceProblemSchema = object({
|
|
48063
|
-
code: _enum([
|
|
48064
|
-
"missing-input",
|
|
48065
|
-
"invalid-input",
|
|
48066
|
-
"invalid-recipe",
|
|
48067
|
-
"missing-template",
|
|
48068
|
-
"edited-by-hand"
|
|
48069
|
-
]),
|
|
48070
|
-
/** Dotted input address (`buttons.2.targets`); absent for a whole-recipe problem. */
|
|
48071
|
-
input: string().optional(),
|
|
48072
|
-
detail: string()
|
|
48073
|
-
});
|
|
48074
|
-
var AutomationTemplateLinkSchema = object({
|
|
48075
|
-
templateId: string().min(1),
|
|
48076
|
-
values: TemplateInputValuesSchema,
|
|
48077
|
-
/**
|
|
48078
|
-
* Fingerprint of the generated code with this literal blanked
|
|
48079
|
-
* (`instanceCodeHash`), stamped by `generateAutomationBlock`. Code that no
|
|
48080
|
-
* longer matches it was edited by hand, and is never regenerated over.
|
|
48081
|
-
*/
|
|
48082
|
-
codeHash: string().optional(),
|
|
48083
|
-
/**
|
|
48084
|
-
* Present when the last re-expansion refused these values. The automation
|
|
48085
|
-
* keeps running the body of its last good expansion; nothing is dropped.
|
|
48086
|
-
*/
|
|
48087
|
-
problems: array(TemplateInstanceProblemSchema).min(1).optional()
|
|
48088
|
-
});
|
|
48089
48543
|
var ExpressionBindingSourceSchema = union([
|
|
48090
48544
|
object({
|
|
48091
48545
|
kind: literal("field").optional(),
|
|
@@ -48121,6 +48575,58 @@ object({
|
|
|
48121
48575
|
path: ["expr"]
|
|
48122
48576
|
});
|
|
48123
48577
|
});
|
|
48578
|
+
Math.PI / 180;
|
|
48579
|
+
/**
|
|
48580
|
+
* WHEN something happens, as data (D983) — the one time vocabulary of the
|
|
48581
|
+
* scheduler and of an automation's schedule leaf. Three shapes, no cron:
|
|
48582
|
+
*
|
|
48583
|
+
* - `clock` — a wall-clock time every day (`07:30`), read in the site's zone;
|
|
48584
|
+
* - `sun` — a sun event (`sunrise`, `sunset`, `dawn`, `dusk`) plus or minus
|
|
48585
|
+
* up to twelve hours, from the site's coordinates;
|
|
48586
|
+
* - `date` — one local date and time (`2026-12-24T18:00`), once.
|
|
48587
|
+
*
|
|
48588
|
+
* A site is a place and its IANA zone ({@link TimeSite}). Every function here
|
|
48589
|
+
* is pure: the zone arithmetic uses `Intl`, no date library.
|
|
48590
|
+
*
|
|
48591
|
+
* Wall-clock honesty across a DST change: a local time that does not exist
|
|
48592
|
+
* (02:30 on the spring-forward day) happens at the first minute that does
|
|
48593
|
+
* (03:00); one that happens twice (02:30 on the fall-back day) happens at its
|
|
48594
|
+
* FIRST occurrence.
|
|
48595
|
+
*/
|
|
48596
|
+
var SunEventSchema = _enum([
|
|
48597
|
+
"sunrise",
|
|
48598
|
+
"sunset",
|
|
48599
|
+
"dawn",
|
|
48600
|
+
"dusk"
|
|
48601
|
+
]);
|
|
48602
|
+
var TimeSpecSchema = discriminatedUnion("kind", [
|
|
48603
|
+
object({
|
|
48604
|
+
kind: literal("clock"),
|
|
48605
|
+
hh: number$1().int().min(0).max(23),
|
|
48606
|
+
mm: number$1().int().min(0).max(59)
|
|
48607
|
+
}),
|
|
48608
|
+
object({
|
|
48609
|
+
kind: literal("sun"),
|
|
48610
|
+
event: SunEventSchema,
|
|
48611
|
+
/** Minutes after the event (negative: before). */
|
|
48612
|
+
offsetMin: number$1().int().min(-720).max(720)
|
|
48613
|
+
}),
|
|
48614
|
+
object({
|
|
48615
|
+
kind: literal("date"),
|
|
48616
|
+
/** `YYYY-MM-DDTHH:mm`, site-local. */
|
|
48617
|
+
local: string().regex(/^(\d{4}-\d{2}-\d{2})T([01]\d|2[0-3]):([0-5]\d)$/, "expected YYYY-MM-DDTHH:mm")
|
|
48618
|
+
})
|
|
48619
|
+
]);
|
|
48620
|
+
/** A day of the week as a schedule names it. */
|
|
48621
|
+
var WeekdayKeySchema = _enum([
|
|
48622
|
+
"mon",
|
|
48623
|
+
"tue",
|
|
48624
|
+
"wed",
|
|
48625
|
+
"thu",
|
|
48626
|
+
"fri",
|
|
48627
|
+
"sat",
|
|
48628
|
+
"sun"
|
|
48629
|
+
]);
|
|
48124
48630
|
/**
|
|
48125
48631
|
* Identity envelope for a device's upstream-system metadata.
|
|
48126
48632
|
*
|
|
@@ -48513,58 +49019,6 @@ function macroOnly(macro) {
|
|
|
48513
49019
|
};
|
|
48514
49020
|
}
|
|
48515
49021
|
}
|
|
48516
|
-
Math.PI / 180;
|
|
48517
|
-
/**
|
|
48518
|
-
* WHEN something happens, as data (D983) — the one time vocabulary of the
|
|
48519
|
-
* scheduler and of an automation's schedule leaf. Three shapes, no cron:
|
|
48520
|
-
*
|
|
48521
|
-
* - `clock` — a wall-clock time every day (`07:30`), read in the site's zone;
|
|
48522
|
-
* - `sun` — a sun event (`sunrise`, `sunset`, `dawn`, `dusk`) plus or minus
|
|
48523
|
-
* up to twelve hours, from the site's coordinates;
|
|
48524
|
-
* - `date` — one local date and time (`2026-12-24T18:00`), once.
|
|
48525
|
-
*
|
|
48526
|
-
* A site is a place and its IANA zone ({@link TimeSite}). Every function here
|
|
48527
|
-
* is pure: the zone arithmetic uses `Intl`, no date library.
|
|
48528
|
-
*
|
|
48529
|
-
* Wall-clock honesty across a DST change: a local time that does not exist
|
|
48530
|
-
* (02:30 on the spring-forward day) happens at the first minute that does
|
|
48531
|
-
* (03:00); one that happens twice (02:30 on the fall-back day) happens at its
|
|
48532
|
-
* FIRST occurrence.
|
|
48533
|
-
*/
|
|
48534
|
-
var SunEventSchema = _enum([
|
|
48535
|
-
"sunrise",
|
|
48536
|
-
"sunset",
|
|
48537
|
-
"dawn",
|
|
48538
|
-
"dusk"
|
|
48539
|
-
]);
|
|
48540
|
-
var TimeSpecSchema = discriminatedUnion("kind", [
|
|
48541
|
-
object({
|
|
48542
|
-
kind: literal("clock"),
|
|
48543
|
-
hh: number$1().int().min(0).max(23),
|
|
48544
|
-
mm: number$1().int().min(0).max(59)
|
|
48545
|
-
}),
|
|
48546
|
-
object({
|
|
48547
|
-
kind: literal("sun"),
|
|
48548
|
-
event: SunEventSchema,
|
|
48549
|
-
/** Minutes after the event (negative: before). */
|
|
48550
|
-
offsetMin: number$1().int().min(-720).max(720)
|
|
48551
|
-
}),
|
|
48552
|
-
object({
|
|
48553
|
-
kind: literal("date"),
|
|
48554
|
-
/** `YYYY-MM-DDTHH:mm`, site-local. */
|
|
48555
|
-
local: string().regex(/^(\d{4}-\d{2}-\d{2})T([01]\d|2[0-3]):([0-5]\d)$/, "expected YYYY-MM-DDTHH:mm")
|
|
48556
|
-
})
|
|
48557
|
-
]);
|
|
48558
|
-
/** A day of the week as a schedule names it. */
|
|
48559
|
-
var WeekdayKeySchema = _enum([
|
|
48560
|
-
"mon",
|
|
48561
|
-
"tue",
|
|
48562
|
-
"wed",
|
|
48563
|
-
"thu",
|
|
48564
|
-
"fri",
|
|
48565
|
-
"sat",
|
|
48566
|
-
"sun"
|
|
48567
|
-
]);
|
|
48568
49022
|
/**
|
|
48569
49023
|
* Hold semantics — "for N seconds" on a leaf of the `when` tree (#498).
|
|
48570
49024
|
*
|
|
@@ -48821,24 +49275,33 @@ var StationaryPresentLeafSchema = object({
|
|
|
48821
49275
|
* (`kind: 'date'`) is refused: only a clock time or a sun event makes a window
|
|
48822
49276
|
* that repeats every day.
|
|
48823
49277
|
*/
|
|
48824
|
-
var
|
|
48825
|
-
kind: literal("time-is"),
|
|
49278
|
+
var timeIsWindowShape = {
|
|
48826
49279
|
between: object({
|
|
48827
49280
|
from: TimeSpecSchema,
|
|
48828
49281
|
to: TimeSpecSchema
|
|
48829
49282
|
}).optional(),
|
|
48830
49283
|
days: array(WeekdayKeySchema).min(1).max(7).optional()
|
|
48831
|
-
}
|
|
48832
|
-
|
|
49284
|
+
};
|
|
49285
|
+
function timeIsWindowProblems(window, ctx) {
|
|
49286
|
+
if (window.between === void 0 && window.days === void 0) ctx.addIssue({
|
|
48833
49287
|
code: "custom",
|
|
48834
49288
|
message: "a time-is leaf needs a between window, days, or both"
|
|
48835
49289
|
});
|
|
48836
|
-
for (const end of ["from", "to"]) if (
|
|
49290
|
+
for (const end of ["from", "to"]) if (window.between?.[end].kind === "date") ctx.addIssue({
|
|
48837
49291
|
code: "custom",
|
|
48838
49292
|
message: "a one-date time cannot bound a daily window: use a clock time or a sun event",
|
|
48839
49293
|
path: ["between", end]
|
|
48840
49294
|
});
|
|
48841
|
-
}
|
|
49295
|
+
}
|
|
49296
|
+
/**
|
|
49297
|
+
* What a `time-is` leaf holds beside its kind, judged by the leaf's own rules.
|
|
49298
|
+
* A template's time-window input stores exactly this.
|
|
49299
|
+
*/
|
|
49300
|
+
var TimeIsWindowSchema = object(timeIsWindowShape).superRefine(timeIsWindowProblems);
|
|
49301
|
+
var TimeIsLeafSchema = object({
|
|
49302
|
+
kind: literal("time-is"),
|
|
49303
|
+
...timeIsWindowShape
|
|
49304
|
+
}).superRefine(timeIsWindowProblems);
|
|
48842
49305
|
/**
|
|
48843
49306
|
* True for the run that one of the named event leaves started. It reads the
|
|
48844
49307
|
* run, not a device: in the tree it is judged against the leaf that fired, in
|
|
@@ -49046,6 +49509,79 @@ function validateWhenTree(when) {
|
|
|
49046
49509
|
return null;
|
|
49047
49510
|
}
|
|
49048
49511
|
/**
|
|
49512
|
+
* The link an automation made FROM a template carries (#527): which template,
|
|
49513
|
+
* the values the operator filled in, and — when the template has since changed
|
|
49514
|
+
* so that those values no longer fit — the problems that say why.
|
|
49515
|
+
*
|
|
49516
|
+
* It lives inside the recipe (`AutomationRecipe.template`), so the one row in
|
|
49517
|
+
* `core_blocks` stays the one artefact: there is no second store of instances
|
|
49518
|
+
* to drift from the blocks, and deleting the automation deletes the link.
|
|
49519
|
+
* "Convert to a free automation" is dropping this field.
|
|
49520
|
+
*
|
|
49521
|
+
* This file depends on nothing in `recipe.ts`, so the recipe can embed it and
|
|
49522
|
+
* the template engine (`template/automation-template.ts`) can import both.
|
|
49523
|
+
*/
|
|
49524
|
+
/** An `event` input's value: the same three narrowing lists a `device-fired` row takes. */
|
|
49525
|
+
var TemplateEventValueSchema = object({
|
|
49526
|
+
eventIds: array(string().min(1)).min(1).max(64).optional(),
|
|
49527
|
+
sourceIds: array(string().min(1)).min(1).max(64).optional(),
|
|
49528
|
+
kinds: array(EventVocabularyKindSchema).min(1).optional()
|
|
49529
|
+
}).refine((value) => value.eventIds !== void 0 || value.sourceIds !== void 0 || value.kinds !== void 0, { message: "an event names at least one event, part or kind" });
|
|
49530
|
+
/** An `action` input's value: a vocabulary action and its open args. */
|
|
49531
|
+
var TemplateActionValueSchema = object({
|
|
49532
|
+
actionId: string().min(1),
|
|
49533
|
+
args: record(string(), unknown()).optional()
|
|
49534
|
+
});
|
|
49535
|
+
/**
|
|
49536
|
+
* A `time-window` input's value: what a `time-is` leaf holds beside its kind.
|
|
49537
|
+
* "No limit" is the input left without a value, never an empty object.
|
|
49538
|
+
*/
|
|
49539
|
+
var TemplateTimeWindowValueSchema = TimeIsWindowSchema;
|
|
49540
|
+
var TemplateEntriesValueSchema = array(record(string(), unknown()));
|
|
49541
|
+
/** The value of one non-group input. Which member is right is the input kind's to judge. */
|
|
49542
|
+
var TemplateScalarValueSchema = union([
|
|
49543
|
+
number$1(),
|
|
49544
|
+
string(),
|
|
49545
|
+
boolean(),
|
|
49546
|
+
array(number$1().int().nonnegative()),
|
|
49547
|
+
TemplateEventValueSchema,
|
|
49548
|
+
TemplateActionValueSchema,
|
|
49549
|
+
TemplateTimeWindowValueSchema,
|
|
49550
|
+
TemplateEntriesValueSchema
|
|
49551
|
+
]);
|
|
49552
|
+
/** What a group row holds under one key: a value, or the rows of a group it nests. */
|
|
49553
|
+
var TemplateRowValueSchema = union([TemplateScalarValueSchema, array(record(string(), TemplateScalarValueSchema))]);
|
|
49554
|
+
var TemplateInputValueSchema = union([TemplateScalarValueSchema, array(record(string(), TemplateRowValueSchema))]);
|
|
49555
|
+
/** Input key → value. */
|
|
49556
|
+
var TemplateInputValuesSchema = record(string(), TemplateInputValueSchema);
|
|
49557
|
+
var TemplateInstanceProblemSchema = object({
|
|
49558
|
+
code: _enum([
|
|
49559
|
+
"missing-input",
|
|
49560
|
+
"invalid-input",
|
|
49561
|
+
"invalid-recipe",
|
|
49562
|
+
"missing-template",
|
|
49563
|
+
"edited-by-hand"
|
|
49564
|
+
]),
|
|
49565
|
+
/** Dotted input address (`buttons.2.targets`, `buttons.0.commands.1.targets`); absent for a whole-recipe problem. */
|
|
49566
|
+
input: string().optional(),
|
|
49567
|
+
detail: string()
|
|
49568
|
+
});
|
|
49569
|
+
var AutomationTemplateLinkSchema = object({
|
|
49570
|
+
templateId: string().min(1),
|
|
49571
|
+
values: TemplateInputValuesSchema,
|
|
49572
|
+
/**
|
|
49573
|
+
* Fingerprint of the generated code with this literal blanked
|
|
49574
|
+
* (`instanceCodeHash`), stamped by `generateAutomationBlock`. Code that no
|
|
49575
|
+
* longer matches it was edited by hand, and is never regenerated over.
|
|
49576
|
+
*/
|
|
49577
|
+
codeHash: string().optional(),
|
|
49578
|
+
/**
|
|
49579
|
+
* Present when the last re-expansion refused these values. The automation
|
|
49580
|
+
* keeps running the body of its last good expansion; nothing is dropped.
|
|
49581
|
+
*/
|
|
49582
|
+
problems: array(TemplateInstanceProblemSchema).min(1).optional()
|
|
49583
|
+
});
|
|
49584
|
+
/**
|
|
49049
49585
|
* The recipe shape before the single `when` tree: a flat list of triggers
|
|
49050
49586
|
* (OR'd, each an instant) and an optional condition tree. Stored recipes —
|
|
49051
49587
|
* the `AUTOMATION_RECIPE` literal of every block saved so far, and whatever an
|
|
@@ -55023,6 +55559,16 @@ var HvacModeSchema = _enum([
|
|
|
55023
55559
|
var ClimateControlStatusSchema = object({
|
|
55024
55560
|
/** Active HVAC mode. */
|
|
55025
55561
|
mode: HvacModeSchema,
|
|
55562
|
+
/** What the device is doing now (`heating` while the valve is open, `idle`
|
|
55563
|
+
* at setpoint). Absent or null = the device does not say; never a guess (D393). */
|
|
55564
|
+
action: _enum([
|
|
55565
|
+
"heating",
|
|
55566
|
+
"cooling",
|
|
55567
|
+
"drying",
|
|
55568
|
+
"fan",
|
|
55569
|
+
"idle",
|
|
55570
|
+
"off"
|
|
55571
|
+
]).nullable().optional(),
|
|
55026
55572
|
/** Available HVAC modes the device accepts. Subset of HvacMode. */
|
|
55027
55573
|
availableModes: array(HvacModeSchema),
|
|
55028
55574
|
/** Active fan mode (`auto` / `low` / `medium` / `high` / `on` / `off`
|
|
@@ -55076,6 +55622,40 @@ var ClimateControlStatusSchema = object({
|
|
|
55076
55622
|
/** Ms epoch when the slice was last updated (push or command). */
|
|
55077
55623
|
lastFetchedAt: number$1()
|
|
55078
55624
|
});
|
|
55625
|
+
/**
|
|
55626
|
+
* Linked room sensor (Customize): the OPERATOR may replace the thermostat's own
|
|
55627
|
+
* `currentTemp` / `currentHumidity` with a sensor in the room. Never linked on
|
|
55628
|
+
* its own (D356). Once linked it ALWAYS replaces the native value, a null
|
|
55629
|
+
* native included — the operator chose the better reading.
|
|
55630
|
+
*/
|
|
55631
|
+
var CLIMATE_CUSTOMIZE_DEVICE_TYPES = [DeviceType.Climate];
|
|
55632
|
+
function roomSensorTarget(id, path) {
|
|
55633
|
+
return {
|
|
55634
|
+
id,
|
|
55635
|
+
cardinality: "scalar",
|
|
55636
|
+
vocabulary: {
|
|
55637
|
+
cap: "climate-control",
|
|
55638
|
+
stateField: path
|
|
55639
|
+
},
|
|
55640
|
+
deviceTypes: CLIMATE_CUSTOMIZE_DEVICE_TYPES,
|
|
55641
|
+
apply: "replace",
|
|
55642
|
+
path,
|
|
55643
|
+
sources: [{
|
|
55644
|
+
kind: "numeric",
|
|
55645
|
+
transforms: [{ kind: "identity" }]
|
|
55646
|
+
}],
|
|
55647
|
+
sourceReport: { status: "assignment-status" }
|
|
55648
|
+
};
|
|
55649
|
+
}
|
|
55650
|
+
var CLIMATE_CONTROL_TARGETS = [roomSensorTarget("room-temperature", "currentTemp"), roomSensorTarget("room-humidity", "currentHumidity")];
|
|
55651
|
+
var climateControlCustomize = {
|
|
55652
|
+
version: 1,
|
|
55653
|
+
overridable: CLIMATE_CONTROL_TARGETS.map((target) => ({
|
|
55654
|
+
path: target.path,
|
|
55655
|
+
by: target.id
|
|
55656
|
+
})),
|
|
55657
|
+
targets: CLIMATE_CONTROL_TARGETS
|
|
55658
|
+
};
|
|
55079
55659
|
var climateControlCapability = {
|
|
55080
55660
|
name: "climate-control",
|
|
55081
55661
|
scope: "device",
|
|
@@ -55386,6 +55966,7 @@ var climateControlCapability = {
|
|
|
55386
55966
|
* on every push without re-querying the provider.
|
|
55387
55967
|
*/
|
|
55388
55968
|
runtimeState: ClimateControlStatusSchema,
|
|
55969
|
+
customize: climateControlCustomize,
|
|
55389
55970
|
/**
|
|
55390
55971
|
* Runtime-state durability: **session** — as `brightness`; `currentTemp` moves continuously and is re-published on connect.
|
|
55391
55972
|
*
|
|
@@ -56141,13 +56722,14 @@ var connectivityCapability = {
|
|
|
56141
56722
|
* its device tracks consumables registers it; the provider names each item
|
|
56142
56723
|
* verbatim and says which `kind` it is.
|
|
56143
56724
|
*
|
|
56144
|
-
* The admin UI
|
|
56145
|
-
*
|
|
56146
|
-
*
|
|
56725
|
+
* The admin UI shows it in the device card's consumables chip and popover
|
|
56726
|
+
* (kind-aware level, remaining time, "Reset"), for every device bound to this
|
|
56727
|
+
* cap (D1023). It no longer has a section of its own under the hero card
|
|
56728
|
+
* (D915 on that point).
|
|
56147
56729
|
*
|
|
56148
56730
|
* Like `childLayout`, the cap is INERT until a provider sets items: no
|
|
56149
56731
|
* provider populates it by guessing (no HA inference). The UI renders a
|
|
56150
|
-
* "No consumables reported"
|
|
56732
|
+
* "No consumables reported" line when `items` is empty.
|
|
56151
56733
|
*/
|
|
56152
56734
|
/**
|
|
56153
56735
|
* What an item IS, which decides which direction is bad:
|
|
@@ -56234,7 +56816,7 @@ var ConsumablesStatusSchema = object({
|
|
|
56234
56816
|
});
|
|
56235
56817
|
/** Synthesize seed for a link-built status (no native provider).
|
|
56236
56818
|
*
|
|
56237
|
-
*
|
|
56819
|
+
* ! NO LIVE CALLER since 2026-08-08 (device-links deleted; see
|
|
56238
56820
|
* `CapabilityStatusSchema.empty`). The wiring guidance below was written for
|
|
56239
56821
|
* exactly the case the operator is asking about again — a Dreame's HA
|
|
56240
56822
|
* consumable-life sensors — so it is kept for that conversation, not because
|
|
@@ -56338,14 +56920,6 @@ var consumablesCapability = {
|
|
|
56338
56920
|
deviceNative: true,
|
|
56339
56921
|
mode: "singleton",
|
|
56340
56922
|
deviceTypes: Object.values(DeviceType),
|
|
56341
|
-
deviceConfig: { ui: {
|
|
56342
|
-
kind: "widget",
|
|
56343
|
-
widgetId: "host/consumables-panel",
|
|
56344
|
-
tab: "consumables",
|
|
56345
|
-
placement: "hero",
|
|
56346
|
-
label: "Consumables",
|
|
56347
|
-
order: 5
|
|
56348
|
-
} },
|
|
56349
56923
|
methods: {
|
|
56350
56924
|
/** Mark a consumable as replaced — resets its remaining life. Only
|
|
56351
56925
|
* meaningful when the item's `resettable` is true. */
|
|
@@ -56574,20 +57148,95 @@ var ControlSetValueInputSchema = discriminatedUnion("kind", [
|
|
|
56574
57148
|
value: string().min(1)
|
|
56575
57149
|
})
|
|
56576
57150
|
]);
|
|
57151
|
+
/**
|
|
57152
|
+
* `next` / `previous` input (#544, operator scripts driving a selector).
|
|
57153
|
+
* `cycle` is a TOP-LEVEL default so a direct `ctx.api.control.next` call
|
|
57154
|
+
* (which skips the tRPC router's Zod parse) still gets `true` via
|
|
57155
|
+
* `CAP_INPUT_DEFAULTS` — matching HA's own `select_next` / `select_previous`
|
|
57156
|
+
* default.
|
|
57157
|
+
*/
|
|
57158
|
+
var ControlStepInputSchema = object({
|
|
57159
|
+
deviceId: number$1().int().nonnegative(),
|
|
57160
|
+
cycle: boolean().default(true)
|
|
57161
|
+
});
|
|
57162
|
+
/** `first` / `last` input — no `cycle`, there is no boundary to stop at. */
|
|
57163
|
+
var ControlBoundaryInputSchema = object({ deviceId: number$1().int().nonnegative() });
|
|
56577
57164
|
var controlCapability = {
|
|
56578
57165
|
name: "control",
|
|
56579
57166
|
scope: "device",
|
|
56580
57167
|
deviceNative: true,
|
|
56581
57168
|
mode: "singleton",
|
|
56582
57169
|
deviceTypes: [DeviceType.Control],
|
|
56583
|
-
methods: {
|
|
56584
|
-
|
|
56585
|
-
|
|
56586
|
-
|
|
56587
|
-
|
|
56588
|
-
|
|
56589
|
-
|
|
56590
|
-
|
|
57170
|
+
methods: {
|
|
57171
|
+
setValue: method(object({
|
|
57172
|
+
deviceId: number$1().int().nonnegative(),
|
|
57173
|
+
control: ControlSetValueInputSchema
|
|
57174
|
+
}), _void(), {
|
|
57175
|
+
kind: "mutation",
|
|
57176
|
+
auth: "protected",
|
|
57177
|
+
notOperatorFacing: "the value shape depends on the control kind (numeric / select / text / datetime) read from status; a typed picker for it is a follow-up of the automations rework"
|
|
57178
|
+
}),
|
|
57179
|
+
/**
|
|
57180
|
+
* Select one step forward through `options` (#544). `providerOptional`
|
|
57181
|
+
* (hence `optionalMethod`): only a `kind: 'select'` provider implements
|
|
57182
|
+
* it — the stepping math is NOT re-derived per provider, it is the one
|
|
57183
|
+
* shared helper `selectNavigationMethods` (`control-select-navigation.ts`)
|
|
57184
|
+
* every select-kind driver spreads in.
|
|
57185
|
+
*/
|
|
57186
|
+
next: optionalMethod(ControlStepInputSchema, _void(), {
|
|
57187
|
+
kind: "mutation",
|
|
57188
|
+
auth: "protected",
|
|
57189
|
+
actions: [{
|
|
57190
|
+
id: "select.next",
|
|
57191
|
+
label: t("Next option", "Opzione successiva"),
|
|
57192
|
+
phrase: t("Select the next option on {device}", "Seleziona l’opzione successiva su {device}"),
|
|
57193
|
+
icon: "skip-forward",
|
|
57194
|
+
openArgs: [{
|
|
57195
|
+
key: "cycle",
|
|
57196
|
+
label: t("Wrap to the first option", "Ricomincia dalla prima opzione"),
|
|
57197
|
+
offer: { kind: "boolean" }
|
|
57198
|
+
}]
|
|
57199
|
+
}]
|
|
57200
|
+
}),
|
|
57201
|
+
/** Select one step backward through `options` (#544) — mirrors `next`. */
|
|
57202
|
+
previous: optionalMethod(ControlStepInputSchema, _void(), {
|
|
57203
|
+
kind: "mutation",
|
|
57204
|
+
auth: "protected",
|
|
57205
|
+
actions: [{
|
|
57206
|
+
id: "select.previous",
|
|
57207
|
+
label: t("Previous option", "Opzione precedente"),
|
|
57208
|
+
phrase: t("Select the previous option on {device}", "Seleziona l’opzione precedente su {device}"),
|
|
57209
|
+
icon: "skip-back",
|
|
57210
|
+
openArgs: [{
|
|
57211
|
+
key: "cycle",
|
|
57212
|
+
label: t("Wrap to the last option", "Ricomincia dall’ultima opzione"),
|
|
57213
|
+
offer: { kind: "boolean" }
|
|
57214
|
+
}]
|
|
57215
|
+
}]
|
|
57216
|
+
}),
|
|
57217
|
+
/** Select the first entry of `options` (#544). */
|
|
57218
|
+
first: optionalMethod(ControlBoundaryInputSchema, _void(), {
|
|
57219
|
+
kind: "mutation",
|
|
57220
|
+
auth: "protected",
|
|
57221
|
+
actions: [{
|
|
57222
|
+
id: "select.first",
|
|
57223
|
+
label: t("First option", "Prima opzione"),
|
|
57224
|
+
phrase: t("Select the first option on {device}", "Seleziona la prima opzione su {device}"),
|
|
57225
|
+
icon: "chevron-first"
|
|
57226
|
+
}]
|
|
57227
|
+
}),
|
|
57228
|
+
/** Select the last entry of `options` (#544). */
|
|
57229
|
+
last: optionalMethod(ControlBoundaryInputSchema, _void(), {
|
|
57230
|
+
kind: "mutation",
|
|
57231
|
+
auth: "protected",
|
|
57232
|
+
actions: [{
|
|
57233
|
+
id: "select.last",
|
|
57234
|
+
label: t("Last option", "Ultima opzione"),
|
|
57235
|
+
phrase: t("Select the last option on {device}", "Seleziona l’ultima opzione su {device}"),
|
|
57236
|
+
icon: "chevron-last"
|
|
57237
|
+
}]
|
|
57238
|
+
})
|
|
57239
|
+
},
|
|
56591
57240
|
status: {
|
|
56592
57241
|
schema: ControlStatusSchema,
|
|
56593
57242
|
kind: "push"
|
|
@@ -57564,7 +58213,7 @@ var mediaPlayerCapability = {
|
|
|
57564
58213
|
]
|
|
57565
58214
|
}
|
|
57566
58215
|
};
|
|
57567
|
-
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Climate, DeviceType.EventEmitter, DeviceType.Camera, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.PetFountain, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer, DeviceType.Gateway, DeviceType.HeatPump, DeviceType.EnergySystem, DeviceType.Camera, DeviceType.Fan, DeviceType.Fan, DeviceType.Fan, DeviceType.Fan, DeviceType.Fan, DeviceType.Fan, DeviceType.Fan, DeviceType.Fan, DeviceType.Fan, DeviceType.Fan, DeviceType.Lock, DeviceType.Camera, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Gateway, DeviceType.Camera, DeviceType.Sensor, DeviceType.MediaPlayer, DeviceType.Vacuum, DeviceType.Generic, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.PetFountain, DeviceType.Fan, DeviceType.Humidifier, DeviceType.Climate, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.PetFeeder, DeviceType.MediaPlayer;
|
|
58216
|
+
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Climate, DeviceType.EventEmitter, DeviceType.Climate, DeviceType.Climate, DeviceType.Camera, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.WeatherStation, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.PetFountain, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer, DeviceType.Gateway, DeviceType.HeatPump, DeviceType.EnergySystem, DeviceType.Camera, DeviceType.Fan, DeviceType.Fan, DeviceType.Fan, DeviceType.Fan, DeviceType.Fan, DeviceType.Fan, DeviceType.Fan, DeviceType.Fan, DeviceType.Fan, DeviceType.Fan, DeviceType.Lock, DeviceType.Camera, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Gateway, DeviceType.Camera, DeviceType.Sensor, DeviceType.MediaPlayer, DeviceType.Vacuum, DeviceType.Generic, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.PetFountain, DeviceType.Fan, DeviceType.Humidifier, DeviceType.Climate, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.PetFeeder, DeviceType.MediaPlayer, DeviceType.WeatherStation, DeviceType.WeatherStation, DeviceType.WeatherStation, DeviceType.WeatherStation, DeviceType.WeatherStation, DeviceType.WeatherStation, DeviceType.WeatherStation, DeviceType.WeatherStation, DeviceType.WeatherStation, DeviceType.WeatherStation, DeviceType.WeatherStation, DeviceType.WeatherStation, DeviceType.WeatherStation, DeviceType.WeatherStation, DeviceType.WeatherStation, DeviceType.WeatherStation, DeviceType.WeatherStation, DeviceType.WeatherStation, DeviceType.WeatherStation, DeviceType.WeatherStation;
|
|
57568
58217
|
var NUMBER$1 = {
|
|
57569
58218
|
kind: "fixed",
|
|
57570
58219
|
result: ["number"]
|
|
@@ -63133,6 +63782,10 @@ method(object({
|
|
|
63133
63782
|
* system did not report is `null`, never `0` (D393).
|
|
63134
63783
|
*
|
|
63135
63784
|
* Signs, all in watts:
|
|
63785
|
+
* - The branches are DISJOINT: `house` is the consumption EXCLUDING the heat pump
|
|
63786
|
+
* whenever `heatPump` is reported, so solar + grid import + storage discharge =
|
|
63787
|
+
* house + heatPump + grid export + storage charge. A provider whose meter totals
|
|
63788
|
+
* include the pump subtracts it; when it cannot, `house` is null (D393).
|
|
63136
63789
|
* - `solar.powerW`, `house.powerW`, `heatPump.powerW` are magnitudes (≥ 0);
|
|
63137
63790
|
* - `grid.powerW` is + importing, − exporting;
|
|
63138
63791
|
* - `storage.powerW` is + charging, − discharging.
|
|
@@ -63372,6 +64025,85 @@ var enumSensorCapability = {
|
|
|
63372
64025
|
}]
|
|
63373
64026
|
}
|
|
63374
64027
|
};
|
|
64028
|
+
/** How loudly a fault wants the operator. Both tiers raise the attention event. */
|
|
64029
|
+
var DeviceErrorSeveritySchema = _enum(["warning", "error"]);
|
|
64030
|
+
/** One fault of a device that can raise several at once. */
|
|
64031
|
+
var DeviceFaultSchema = object({
|
|
64032
|
+
/** The device's own code, as the vendor names it. */
|
|
64033
|
+
code: string(),
|
|
64034
|
+
/** Already translated by the provider (it owns the vendor vocabulary). */
|
|
64035
|
+
label: string(),
|
|
64036
|
+
severity: DeviceErrorSeveritySchema
|
|
64037
|
+
});
|
|
64038
|
+
/**
|
|
64039
|
+
* The fault a device reports right now. One slice per device.
|
|
64040
|
+
*
|
|
64041
|
+
* `active` is tri-state: `null` is "the provider has not read it yet" and is
|
|
64042
|
+
* never drawn as "no fault" nor as a fault (D315, D393). The provider filters
|
|
64043
|
+
* what is not a fault (a completion or reminder code) BEFORE it writes `true`.
|
|
64044
|
+
*
|
|
64045
|
+
* The cap's name is the key a template reads (`{{ alias.error.label }}`, D1021).
|
|
64046
|
+
*/
|
|
64047
|
+
var ErrorStatusSchema = object({
|
|
64048
|
+
active: boolean().nullable(),
|
|
64049
|
+
/** The code of the principal fault; `null` when none (or unknown). */
|
|
64050
|
+
code: string().nullable(),
|
|
64051
|
+
/** The principal fault's words, provider-translated; `null` when none. */
|
|
64052
|
+
label: string().nullable(),
|
|
64053
|
+
severity: DeviceErrorSeveritySchema,
|
|
64054
|
+
/** Ms epoch the current fault started; `null` when none or not known. */
|
|
64055
|
+
since: number$1().nullable(),
|
|
64056
|
+
/** Every fault, for a device that raises several. The principal is the first. */
|
|
64057
|
+
faults: array(DeviceFaultSchema).optional(),
|
|
64058
|
+
/** Ms epoch of the last read the provider made of the fault. */
|
|
64059
|
+
lastFetchedAt: number$1()
|
|
64060
|
+
});
|
|
64061
|
+
/** The slice before the provider has read anything: unknown, not "fine". */
|
|
64062
|
+
var ERROR_STATUS_COLD = {
|
|
64063
|
+
active: null,
|
|
64064
|
+
code: null,
|
|
64065
|
+
label: null,
|
|
64066
|
+
severity: "error",
|
|
64067
|
+
since: null,
|
|
64068
|
+
lastFetchedAt: 0
|
|
64069
|
+
};
|
|
64070
|
+
var errorCapability = {
|
|
64071
|
+
name: "error",
|
|
64072
|
+
scope: "device",
|
|
64073
|
+
deviceNative: true,
|
|
64074
|
+
mode: "singleton",
|
|
64075
|
+
methods: {},
|
|
64076
|
+
status: {
|
|
64077
|
+
schema: ErrorStatusSchema,
|
|
64078
|
+
kind: "push",
|
|
64079
|
+
empty: ERROR_STATUS_COLD
|
|
64080
|
+
},
|
|
64081
|
+
runtimeState: ErrorStatusSchema,
|
|
64082
|
+
/**
|
|
64083
|
+
* Runtime-state durability: **restored** — the previous observation is what
|
|
64084
|
+
* lets the first reading after a restart be a COMPARISON: a fault that was
|
|
64085
|
+
* already open must not announce itself a second time.
|
|
64086
|
+
*
|
|
64087
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
64088
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
64089
|
+
*/
|
|
64090
|
+
durability: "restored",
|
|
64091
|
+
volatileStateFields: ["lastFetchedAt"],
|
|
64092
|
+
/** The fault itself is carried by the attention alerts; no series is recorded. */
|
|
64093
|
+
history: "none",
|
|
64094
|
+
vocabulary: {
|
|
64095
|
+
noun: t("Fault", "Guasto"),
|
|
64096
|
+
order: 5265,
|
|
64097
|
+
state: [{
|
|
64098
|
+
kind: "boolean",
|
|
64099
|
+
field: "active",
|
|
64100
|
+
label: t("Fault", "Guasto"),
|
|
64101
|
+
whenTrue: t("When {device} reports a fault", "Quando {device} segnala un guasto"),
|
|
64102
|
+
whenFalse: t("When the fault of {device} clears", "Quando il guasto di {device} si risolve"),
|
|
64103
|
+
icon: "triangle-alert"
|
|
64104
|
+
}]
|
|
64105
|
+
}
|
|
64106
|
+
};
|
|
63375
64107
|
var IdentitySchema = object({
|
|
63376
64108
|
id: string(),
|
|
63377
64109
|
name: string(),
|
|
@@ -63386,7 +64118,19 @@ var IdentitySampleInfoSchema = object({
|
|
|
63386
64118
|
source: _enum(["detected", "photo"]),
|
|
63387
64119
|
addedAt: number$1().int(),
|
|
63388
64120
|
deviceId: number$1().int().optional(),
|
|
63389
|
-
base64: string().optional()
|
|
64121
|
+
base64: string().optional(),
|
|
64122
|
+
/**
|
|
64123
|
+
* The sample's own crop, when it has one. The bytes stay on the event-media
|
|
64124
|
+
* plane — this list does not inline them.
|
|
64125
|
+
*/
|
|
64126
|
+
mediaId: number$1().int().optional(),
|
|
64127
|
+
/**
|
|
64128
|
+
* The source face's key frame (or the photo the sample was cut from), when
|
|
64129
|
+
* the sample has no crop of its own. Draw {@link faceBbox} on it.
|
|
64130
|
+
*/
|
|
64131
|
+
keyFrameMediaId: number$1().int().optional(),
|
|
64132
|
+
/** The face box on {@link keyFrameMediaId}, pixel space. */
|
|
64133
|
+
faceBbox: BoundingBoxSchema.optional()
|
|
63390
64134
|
});
|
|
63391
64135
|
/**
|
|
63392
64136
|
* One enrolled sample, judged against the gallery it lives in.
|
|
@@ -63601,6 +64345,12 @@ includeCrops: boolean().optional() }).optional(), array(IdentitySchema).readonly
|
|
|
63601
64345
|
}), _void(), {
|
|
63602
64346
|
kind: "mutation",
|
|
63603
64347
|
auth: "admin"
|
|
64348
|
+
}), method(object({
|
|
64349
|
+
sampleId: string().min(1),
|
|
64350
|
+
toIdentityId: string().min(1)
|
|
64351
|
+
}), _void(), {
|
|
64352
|
+
kind: "mutation",
|
|
64353
|
+
auth: "admin"
|
|
63604
64354
|
}), method(object({
|
|
63605
64355
|
/**
|
|
63606
64356
|
* Restrict to ONE camera. Absent keeps the cluster-wide gallery view.
|
|
@@ -65838,7 +66588,7 @@ var HeroSceneSchema = object({
|
|
|
65838
66588
|
/** 0..1: volume, cover position, cycle progress. */
|
|
65839
66589
|
level: number$1().min(0).max(1).nullable()
|
|
65840
66590
|
});
|
|
65841
|
-
DeviceType.Camera, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.HeatPump, DeviceType.EnergySystem, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.PetFountain, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer, DeviceType.Gateway;
|
|
66591
|
+
DeviceType.Camera, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.HeatPump, DeviceType.EnergySystem, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.WeatherStation, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.PetFountain, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer, DeviceType.Gateway;
|
|
65842
66592
|
DeviceRole.Siren, DeviceRole.Floodlight, DeviceRole.Spotlight, DeviceRole.PirSensor, DeviceRole.Chime, DeviceRole.Autotrack, DeviceRole.Nightvision, DeviceRole.PrivacyMask, DeviceRole.Doorbell, DeviceRole.CoverBlind, DeviceRole.CoverShutter, DeviceRole.CoverAwning, DeviceRole.CoverCurtain, DeviceRole.CoverGarage, DeviceRole.CoverGate, DeviceRole.CoverDoor, DeviceRole.CoverWindow, DeviceRole.BinaryHelper, DeviceRole.Outlet, DeviceRole.SwitchHeater, DeviceRole.SwitchFan, DeviceRole.SwitchLight, DeviceRole.ClimateAc, DeviceRole.ClimateThermostat, DeviceRole.ClimateFloor, DeviceRole.ClimateRadiator, DeviceRole.ClimateHeater, DeviceRole.ClimateHeatPumpCircuit, DeviceRole.MotionSensor, DeviceRole.ContactSensor, DeviceRole.LeakSensor, DeviceRole.SmokeSensor, DeviceRole.COSensor, DeviceRole.GasSensor, DeviceRole.TamperSensor, DeviceRole.VibrationSensor, DeviceRole.ConnectivitySensor, DeviceRole.SoundSensor, DeviceRole.BinarySensor, DeviceRole.TemperatureSensor, DeviceRole.HumiditySensor, DeviceRole.AmbientLightSensor, DeviceRole.PressureSensor, DeviceRole.WindSensor, DeviceRole.RainSensor, DeviceRole.UvSensor, DeviceRole.SolarRadiationSensor, DeviceRole.SoilMoistureSensor, DeviceRole.PowerSensor, DeviceRole.EnergySensor, DeviceRole.VoltageSensor, DeviceRole.CurrentSensor, DeviceRole.AirQualitySensor, DeviceRole.BatterySensor, DeviceRole.NumericSensor, DeviceRole.EnumSensor, DeviceRole.DateTimeSensor, DeviceRole.GenericSensor, DeviceRole.NumericControl, DeviceRole.SelectControl, DeviceRole.TextControl, DeviceRole.DateTimeControl, DeviceRole.MobilePushNotifier, DeviceRole.MessagingNotifier, DeviceRole.EmailNotifier, DeviceRole.GenericNotifier, DeviceRole.IrTransmitter;
|
|
65843
66593
|
var HeroRowIdSchema = _enum([
|
|
65844
66594
|
"progress",
|
|
@@ -77863,6 +78613,8 @@ var NcSystemEventKindSchema = _enum([
|
|
|
77863
78613
|
"storage-location-low",
|
|
77864
78614
|
"storage-location-critical",
|
|
77865
78615
|
"storage-location-ok",
|
|
78616
|
+
"storage-drain-progress",
|
|
78617
|
+
"storage-drain-complete",
|
|
77866
78618
|
"addon-crash-loop",
|
|
77867
78619
|
"addon-update-available",
|
|
77868
78620
|
"server-update-available",
|
|
@@ -82305,7 +83057,19 @@ var VehicleSampleInfoSchema = object({
|
|
|
82305
83057
|
score: number$1(),
|
|
82306
83058
|
addedAt: number$1().int(),
|
|
82307
83059
|
deviceId: number$1().int().optional(),
|
|
82308
|
-
base64: string().optional()
|
|
83060
|
+
base64: string().optional(),
|
|
83061
|
+
/**
|
|
83062
|
+
* The sample's own crop, when it has one. Prefer this over {@link base64}:
|
|
83063
|
+
* the bytes are on the event-media plane (`/m/<mediaId>`), never inlined.
|
|
83064
|
+
*/
|
|
83065
|
+
mediaId: number$1().int().optional(),
|
|
83066
|
+
/**
|
|
83067
|
+
* The source plate's key frame, when the sample has no crop of its own.
|
|
83068
|
+
* Draw {@link plateBbox} on it. Absent when {@link mediaId} is set.
|
|
83069
|
+
*/
|
|
83070
|
+
keyFrameMediaId: number$1().int().optional(),
|
|
83071
|
+
/** The plate box on {@link keyFrameMediaId}, pixel space. */
|
|
83072
|
+
plateBbox: BoundingBoxSchema.optional()
|
|
82309
83073
|
});
|
|
82310
83074
|
var PlateInfoSchema = object({
|
|
82311
83075
|
plateId: string(),
|
|
@@ -82335,7 +83099,17 @@ var PlateInfoSchema = object({
|
|
|
82335
83099
|
* and `searchPlates` inline the crop only when their `includeCrops` input is
|
|
82336
83100
|
* left at its `true` default.
|
|
82337
83101
|
*/
|
|
82338
|
-
cropUrl: string().optional()
|
|
83102
|
+
cropUrl: string().optional(),
|
|
83103
|
+
/**
|
|
83104
|
+
* Why {@link cropUrl} is absent. One of `no-frame-handle`,
|
|
83105
|
+
* `live-capture-missed`, `live-capture-threw`, `no-key-frame`,
|
|
83106
|
+
* `derive-not-wired`, `subject-moved`, `temporal-skew`, `key-frame-absent`,
|
|
83107
|
+
* `bad-frame-size`, `decode-empty`, `derive-threw`, `derive-returned-null`,
|
|
83108
|
+
* `put-failed`. A crossing vehicle whose live capture missed is
|
|
83109
|
+
* `subject-moved`: the key frame is a different instant, and the crop is
|
|
83110
|
+
* legitimately absent.
|
|
83111
|
+
*/
|
|
83112
|
+
cropMissReason: string().optional()
|
|
82339
83113
|
});
|
|
82340
83114
|
/**
|
|
82341
83115
|
* One gallery media row: what the crop is, how big it is, and WHERE its bytes
|
|
@@ -82435,6 +83209,12 @@ includeCrops: boolean().optional() }).optional(), array(VehicleSchema).readonly(
|
|
|
82435
83209
|
}), _void(), {
|
|
82436
83210
|
kind: "mutation",
|
|
82437
83211
|
auth: "admin"
|
|
83212
|
+
}), method(object({
|
|
83213
|
+
sampleId: string().min(1),
|
|
83214
|
+
toVehicleId: string().min(1)
|
|
83215
|
+
}), _void(), {
|
|
83216
|
+
kind: "mutation",
|
|
83217
|
+
auth: "admin"
|
|
82438
83218
|
}), method(object({
|
|
82439
83219
|
plateId: string(),
|
|
82440
83220
|
vehicleId: string()
|
|
@@ -86263,7 +87043,10 @@ object({
|
|
|
86263
87043
|
value: boolean(),
|
|
86264
87044
|
at: number$1()
|
|
86265
87045
|
}).nullable(),
|
|
86266
|
-
/**
|
|
87046
|
+
/**
|
|
87047
|
+
* Retired: a sent source is never a state (an infrared set cannot report its
|
|
87048
|
+
* input). Kept only so records written before parse; nothing writes or reads it.
|
|
87049
|
+
*/
|
|
86267
87050
|
source: object({
|
|
86268
87051
|
name: string(),
|
|
86269
87052
|
at: number$1()
|
|
@@ -89892,31 +90675,57 @@ var TemplateSelectOptionSchema = object({
|
|
|
89892
90675
|
value: string().min(1),
|
|
89893
90676
|
label: string().min(1).max(80)
|
|
89894
90677
|
});
|
|
90678
|
+
var SelectInputSchema = object({
|
|
90679
|
+
kind: literal("select"),
|
|
90680
|
+
...inputBase,
|
|
90681
|
+
options: array(TemplateSelectOptionSchema).min(1).max(50),
|
|
90682
|
+
default: string().optional()
|
|
90683
|
+
});
|
|
90684
|
+
var BooleanInputSchema = object({
|
|
90685
|
+
kind: literal("boolean"),
|
|
90686
|
+
...inputBase,
|
|
90687
|
+
default: boolean().optional()
|
|
90688
|
+
});
|
|
90689
|
+
/** A limit on when the automation may run; only a `gate` binding reads it. */
|
|
90690
|
+
var TimeWindowInputSchema = object({
|
|
90691
|
+
kind: literal("time-window"),
|
|
90692
|
+
...inputBase
|
|
90693
|
+
});
|
|
89895
90694
|
var TemplateScalarInputSchema = discriminatedUnion("kind", [
|
|
90695
|
+
object({
|
|
90696
|
+
kind: literal("entries"),
|
|
90697
|
+
...inputBase,
|
|
90698
|
+
entry: _enum(["trigger", "step"]),
|
|
90699
|
+
allow: array(string().min(1)).min(1).max(10),
|
|
90700
|
+
maxItems: number$1().int().min(1).max(20).optional()
|
|
90701
|
+
}),
|
|
89896
90702
|
DeviceInputSchema,
|
|
89897
90703
|
EventInputSchema,
|
|
89898
90704
|
ActionInputSchema$1,
|
|
89899
90705
|
NumberInputSchema,
|
|
89900
90706
|
DurationInputSchema,
|
|
89901
90707
|
TextInputSchema,
|
|
89902
|
-
|
|
89903
|
-
|
|
89904
|
-
|
|
89905
|
-
options: array(TemplateSelectOptionSchema).min(1).max(50),
|
|
89906
|
-
default: string().optional()
|
|
89907
|
-
}),
|
|
89908
|
-
object({
|
|
89909
|
-
kind: literal("boolean"),
|
|
89910
|
-
...inputBase,
|
|
89911
|
-
default: boolean().optional()
|
|
89912
|
-
})
|
|
90708
|
+
SelectInputSchema,
|
|
90709
|
+
BooleanInputSchema,
|
|
90710
|
+
TimeWindowInputSchema
|
|
89913
90711
|
]);
|
|
89914
|
-
var
|
|
90712
|
+
var groupBase = {
|
|
89915
90713
|
kind: literal("group"),
|
|
89916
90714
|
...inputBase,
|
|
89917
|
-
|
|
90715
|
+
/** What one row is, in the singular and lower case ("button"): "Add button". */
|
|
90716
|
+
rowLabel: string().min(1).max(40).optional(),
|
|
89918
90717
|
minRows: number$1().int().min(0).max(20).optional(),
|
|
89919
90718
|
maxRows: number$1().int().min(1).max(20).optional()
|
|
90719
|
+
};
|
|
90720
|
+
/** A group inside a group row: its rows hold values only, never another group. */
|
|
90721
|
+
var NestedGroupInputSchema = object({
|
|
90722
|
+
...groupBase,
|
|
90723
|
+
inputs: array(TemplateScalarInputSchema).min(1).max(10)
|
|
90724
|
+
});
|
|
90725
|
+
var TemplateRowInputSchema = discriminatedUnion("kind", [...TemplateScalarInputSchema.options, NestedGroupInputSchema]);
|
|
90726
|
+
var GroupInputSchema = object({
|
|
90727
|
+
...groupBase,
|
|
90728
|
+
inputs: array(TemplateRowInputSchema).min(1).max(10)
|
|
89920
90729
|
});
|
|
89921
90730
|
var TemplateInputSchema = discriminatedUnion("kind", [...TemplateScalarInputSchema.options, GroupInputSchema]);
|
|
89922
90731
|
var TemplatePathSchema = array(union([string().min(1), number$1().int().nonnegative()])).max(24);
|
|
@@ -89927,41 +90736,154 @@ var TemplateValueBindingSchema = object({
|
|
|
89927
90736
|
/** A device value written as a step target (`{ kind: 'devices', ids }`). */
|
|
89928
90737
|
as: literal("target").optional()
|
|
89929
90738
|
});
|
|
89930
|
-
var
|
|
90739
|
+
var TemplateRowIdBindingSchema = object({
|
|
89931
90740
|
kind: literal("row-id"),
|
|
89932
90741
|
path: TemplatePathSchema
|
|
89933
|
-
})
|
|
89934
|
-
|
|
89935
|
-
|
|
90742
|
+
});
|
|
90743
|
+
/**
|
|
90744
|
+
* Appends an `entries` input's elements, verbatim, to the list at `path`. In a
|
|
90745
|
+
* row's bindings `input` is the row's own entries input and `path` is from the
|
|
90746
|
+
* row's item; at the top level, with `in`, it appends the `input` entries of
|
|
90747
|
+
* EVERY row of the group `in` (all buttons' triggers into one `when`), and
|
|
90748
|
+
* without `in` it appends a top-level entries input.
|
|
90749
|
+
*/
|
|
90750
|
+
var TemplateEntriesBindingSchema = object({
|
|
90751
|
+
kind: literal("entries"),
|
|
89936
90752
|
input: inputKey,
|
|
89937
|
-
/** The list in the body the rows are appended to. */
|
|
89938
90753
|
path: TemplatePathSchema,
|
|
89939
|
-
|
|
89940
|
-
|
|
89941
|
-
|
|
89942
|
-
|
|
89943
|
-
|
|
89944
|
-
|
|
89945
|
-
|
|
89946
|
-
|
|
89947
|
-
|
|
90754
|
+
in: inputKey.optional()
|
|
90755
|
+
});
|
|
90756
|
+
/** What fills the item of a row that holds values only. */
|
|
90757
|
+
var TemplateLeafRowBindingSchema = discriminatedUnion("kind", [TemplateValueBindingSchema, TemplateRowIdBindingSchema]);
|
|
90758
|
+
var TemplateRowItemBindingSchema = discriminatedUnion("kind", [
|
|
90759
|
+
TemplateValueBindingSchema,
|
|
90760
|
+
TemplateEntriesBindingSchema,
|
|
90761
|
+
TemplateRowIdBindingSchema,
|
|
90762
|
+
object({
|
|
90763
|
+
kind: literal("row-ids"),
|
|
90764
|
+
/** The nested group whose rows are named. */
|
|
90765
|
+
input: inputKey,
|
|
90766
|
+
path: TemplatePathSchema
|
|
90767
|
+
}),
|
|
90768
|
+
object({
|
|
90769
|
+
kind: literal("rows"),
|
|
90770
|
+
/** The nested group, declared by the parent row's group. */
|
|
90771
|
+
input: inputKey,
|
|
90772
|
+
/** The list the nested rows are appended to, from the parent row's item. */
|
|
90773
|
+
path: TemplatePathSchema,
|
|
90774
|
+
item: unknown(),
|
|
90775
|
+
bindings: array(TemplateLeafRowBindingSchema).max(40)
|
|
90776
|
+
})
|
|
90777
|
+
]);
|
|
90778
|
+
var TemplateBindingSchema = discriminatedUnion("kind", [
|
|
90779
|
+
TemplateValueBindingSchema,
|
|
90780
|
+
TemplateEntriesBindingSchema,
|
|
90781
|
+
object({
|
|
90782
|
+
kind: literal("rows"),
|
|
90783
|
+
input: inputKey,
|
|
90784
|
+
/**
|
|
90785
|
+
* A group the rows of `input` hold: the binding then appends one item per
|
|
90786
|
+
* NESTED row of every row, and its bindings read the nested row.
|
|
90787
|
+
*/
|
|
90788
|
+
nested: inputKey.optional(),
|
|
90789
|
+
/** The list in the body the rows are appended to. */
|
|
90790
|
+
path: TemplatePathSchema,
|
|
90791
|
+
/** The JSON copied once per row. */
|
|
90792
|
+
item: unknown(),
|
|
90793
|
+
bindings: array(TemplateRowItemBindingSchema).max(40)
|
|
90794
|
+
}),
|
|
90795
|
+
object({
|
|
90796
|
+
kind: literal("gate"),
|
|
90797
|
+
/** A top-level `time-window` input. */
|
|
90798
|
+
input: inputKey,
|
|
90799
|
+
path: TemplatePathSchema
|
|
90800
|
+
})
|
|
90801
|
+
]);
|
|
90802
|
+
/** Twice-declared keys and event / action inputs that read no device beside them. */
|
|
90803
|
+
function levelProblems(inputs, path, inRow = false) {
|
|
90804
|
+
const issues = [];
|
|
90805
|
+
const seen = /* @__PURE__ */ new Set();
|
|
90806
|
+
for (const input of inputs) {
|
|
90807
|
+
if (seen.has(input.key)) issues.push({
|
|
89948
90808
|
message: `input "${input.key}" is declared twice`,
|
|
89949
|
-
path
|
|
90809
|
+
path
|
|
89950
90810
|
});
|
|
89951
|
-
|
|
89952
|
-
|
|
89953
|
-
|
|
89954
|
-
|
|
89955
|
-
|
|
89956
|
-
|
|
89957
|
-
|
|
89958
|
-
|
|
89959
|
-
|
|
89960
|
-
|
|
89961
|
-
|
|
90811
|
+
seen.add(input.key);
|
|
90812
|
+
if (input.kind === "group") {
|
|
90813
|
+
issues.push(...levelProblems(input.inputs, path, true));
|
|
90814
|
+
continue;
|
|
90815
|
+
}
|
|
90816
|
+
if (input.kind === "time-window" && inRow) issues.push({
|
|
90817
|
+
message: `time window "${input.key}" limits the whole automation: it is not a row input`,
|
|
90818
|
+
path
|
|
90819
|
+
});
|
|
90820
|
+
if (input.kind !== "event" && input.kind !== "action") continue;
|
|
90821
|
+
if (input.deviceInput === void 0) continue;
|
|
90822
|
+
const device = inputs.find((sibling) => sibling.key === input.deviceInput);
|
|
90823
|
+
if (device === void 0 || device.kind !== "device") issues.push({
|
|
90824
|
+
message: `"${input.key}" reads the device input "${input.deviceInput}", which is not a device input beside it`,
|
|
90825
|
+
path
|
|
90826
|
+
});
|
|
90827
|
+
}
|
|
90828
|
+
return issues;
|
|
90829
|
+
}
|
|
90830
|
+
function nestedGroupOf(group, key) {
|
|
90831
|
+
const found = group.inputs.find((input) => input.key === key);
|
|
90832
|
+
return found !== void 0 && found.kind === "group" ? found : void 0;
|
|
90833
|
+
}
|
|
90834
|
+
function leafBindingProblems(bindings, owner) {
|
|
90835
|
+
const issues = [];
|
|
90836
|
+
for (const row of bindings) {
|
|
90837
|
+
if (row.kind === "row-id") continue;
|
|
90838
|
+
if (row.kind === "value") {
|
|
90839
|
+
const input = owner.inputs.find((i) => i.key === row.input);
|
|
90840
|
+
if (input === void 0) issues.push(`row binding names "${row.input}", which group "${owner.key}" does not declare`);
|
|
90841
|
+
else if (input.kind === "group") issues.push(`group "${input.key}" is bound with rows, not a value`);
|
|
90842
|
+
else if (input.kind === "entries") issues.push(`entries "${input.key}" are bound with entries, not a value`);
|
|
90843
|
+
continue;
|
|
90844
|
+
}
|
|
90845
|
+
const nested = owner.inputs.find((i) => i.key === row.input);
|
|
90846
|
+
if (row.kind === "entries") {
|
|
90847
|
+
if (nested === void 0 || nested.kind !== "entries") issues.push(`"${row.input}" is not an entries input inside "${owner.key}"`);
|
|
90848
|
+
continue;
|
|
90849
|
+
}
|
|
90850
|
+
if (row.kind === "row-ids") {
|
|
90851
|
+
if (nested === void 0 || nested.kind !== "group" && nested.kind !== "entries") issues.push(`"${row.input}" is not a group or entries input inside "${owner.key}"`);
|
|
90852
|
+
continue;
|
|
89962
90853
|
}
|
|
90854
|
+
if (nested === void 0 || nested.kind !== "group") {
|
|
90855
|
+
issues.push(`"${row.input}" is not a group inside "${owner.key}"`);
|
|
90856
|
+
continue;
|
|
90857
|
+
}
|
|
90858
|
+
issues.push(...leafBindingProblems(row.bindings, nested));
|
|
90859
|
+
}
|
|
90860
|
+
return issues;
|
|
90861
|
+
}
|
|
90862
|
+
function rowsBindingProblems(binding, group) {
|
|
90863
|
+
if (binding.nested === void 0) return leafBindingProblems(binding.bindings, group);
|
|
90864
|
+
const nested = nestedGroupOf(group, binding.nested);
|
|
90865
|
+
if (nested === void 0) return [`"${binding.nested}" is not a group inside "${group.key}"`];
|
|
90866
|
+
return leafBindingProblems(binding.bindings, nested);
|
|
90867
|
+
}
|
|
90868
|
+
function bindingProblems(payload, ctx) {
|
|
90869
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
90870
|
+
for (const input of payload.inputs) byKey.set(input.key, input);
|
|
90871
|
+
for (const issue of levelProblems(payload.inputs, ["inputs"])) ctx.addIssue({
|
|
90872
|
+
code: "custom",
|
|
90873
|
+
message: issue.message,
|
|
90874
|
+
path: [...issue.path]
|
|
89963
90875
|
});
|
|
89964
90876
|
payload.bindings.forEach((binding, index) => {
|
|
90877
|
+
if (binding.kind === "entries" && binding.in !== void 0) {
|
|
90878
|
+
const group = byKey.get(binding.in);
|
|
90879
|
+
const entries = group !== void 0 && group.kind === "group" ? group.inputs.find((i) => i.key === binding.input) : void 0;
|
|
90880
|
+
if (entries === void 0 || entries.kind !== "entries") ctx.addIssue({
|
|
90881
|
+
code: "custom",
|
|
90882
|
+
message: `"${binding.input}" is not an entries input inside the group "${binding.in}"`,
|
|
90883
|
+
path: ["bindings", index]
|
|
90884
|
+
});
|
|
90885
|
+
return;
|
|
90886
|
+
}
|
|
89965
90887
|
const input = byKey.get(binding.input);
|
|
89966
90888
|
if (input === void 0) {
|
|
89967
90889
|
ctx.addIssue({
|
|
@@ -89976,6 +90898,18 @@ function bindingProblems(payload, ctx) {
|
|
|
89976
90898
|
message: `group "${input.key}" is bound with rows, not a value`,
|
|
89977
90899
|
path: ["bindings", index]
|
|
89978
90900
|
});
|
|
90901
|
+
if (binding.kind === "entries" !== (input.kind === "entries") && binding.kind !== "rows") {
|
|
90902
|
+
if (binding.kind === "entries" || binding.kind === "value") ctx.addIssue({
|
|
90903
|
+
code: "custom",
|
|
90904
|
+
message: binding.kind === "entries" ? `entries bindings read an entries input: "${input.key}" is ${input.kind}` : `entries "${input.key}" are bound with entries, not a value`,
|
|
90905
|
+
path: ["bindings", index]
|
|
90906
|
+
});
|
|
90907
|
+
}
|
|
90908
|
+
if (binding.kind === "gate" !== (input.kind === "time-window")) ctx.addIssue({
|
|
90909
|
+
code: "custom",
|
|
90910
|
+
message: `a gate reads a time window and a time window is bound with a gate: "${input.key}" is ${input.kind}`,
|
|
90911
|
+
path: ["bindings", index]
|
|
90912
|
+
});
|
|
89979
90913
|
if (binding.kind === "rows") {
|
|
89980
90914
|
if (input.kind !== "group") {
|
|
89981
90915
|
ctx.addIssue({
|
|
@@ -89985,9 +90919,9 @@ function bindingProblems(payload, ctx) {
|
|
|
89985
90919
|
});
|
|
89986
90920
|
return;
|
|
89987
90921
|
}
|
|
89988
|
-
for (const
|
|
90922
|
+
for (const message of rowsBindingProblems(binding, input)) ctx.addIssue({
|
|
89989
90923
|
code: "custom",
|
|
89990
|
-
message
|
|
90924
|
+
message,
|
|
89991
90925
|
path: ["bindings", index]
|
|
89992
90926
|
});
|
|
89993
90927
|
}
|
|
@@ -90166,6 +91100,17 @@ var TerminalOutputEventSchema = discriminatedUnion("kind", [object({
|
|
|
90166
91100
|
exitCode: number$1().int(),
|
|
90167
91101
|
signal: number$1().int().optional()
|
|
90168
91102
|
})]);
|
|
91103
|
+
var ServerShellRefusalSchema = object({
|
|
91104
|
+
code: literal("server-shell-disabled"),
|
|
91105
|
+
nodeId: string(),
|
|
91106
|
+
message: string()
|
|
91107
|
+
});
|
|
91108
|
+
var ServerShellStatusSchema = object({
|
|
91109
|
+
nodeId: string(),
|
|
91110
|
+
enabled: boolean(),
|
|
91111
|
+
idleMinutes: number$1().int().positive(),
|
|
91112
|
+
refusal: ServerShellRefusalSchema.nullable()
|
|
91113
|
+
});
|
|
90169
91114
|
var TerminalOutputBatchSchema = object({
|
|
90170
91115
|
cursor: number$1().int().nonnegative(),
|
|
90171
91116
|
reset: boolean(),
|
|
@@ -90178,7 +91123,7 @@ method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }),
|
|
|
90178
91123
|
}), TerminalInstanceInfoSchema, {
|
|
90179
91124
|
kind: "mutation",
|
|
90180
91125
|
auth: "admin"
|
|
90181
|
-
}), method(_void(), array(TerminalSessionInfoSchema).readonly(), { auth: "admin" }), method(object({
|
|
91126
|
+
}), method(_void(), array(TerminalSessionInfoSchema).readonly(), { auth: "admin" }), method(_void(), ServerShellStatusSchema, { auth: "admin" }), method(object({
|
|
90182
91127
|
profileId: string(),
|
|
90183
91128
|
cols: number$1().int().positive(),
|
|
90184
91129
|
rows: number$1().int().positive(),
|
|
@@ -90188,7 +91133,8 @@ method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }),
|
|
|
90188
91133
|
environment: array(string().max(4096)).max(64).optional()
|
|
90189
91134
|
}), TerminalSessionInfoSchema, {
|
|
90190
91135
|
kind: "mutation",
|
|
90191
|
-
auth: "admin"
|
|
91136
|
+
auth: "admin",
|
|
91137
|
+
caller: "required"
|
|
90192
91138
|
}), method(object({
|
|
90193
91139
|
sessionId: string(),
|
|
90194
91140
|
cols: number$1().int().positive(),
|
|
@@ -90209,6 +91155,7 @@ method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }),
|
|
|
90209
91155
|
}), TerminalOutputBatchSchema, {
|
|
90210
91156
|
kind: "mutation",
|
|
90211
91157
|
auth: "admin",
|
|
91158
|
+
caller: "required",
|
|
90212
91159
|
timeoutMs: 15e3
|
|
90213
91160
|
}), method(object({
|
|
90214
91161
|
sessionId: string(),
|
|
@@ -90218,7 +91165,8 @@ method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }),
|
|
|
90218
91165
|
auth: "admin"
|
|
90219
91166
|
}), method(object({ sessionId: string() }), _void(), {
|
|
90220
91167
|
kind: "mutation",
|
|
90221
|
-
auth: "admin"
|
|
91168
|
+
auth: "admin",
|
|
91169
|
+
caller: "required"
|
|
90222
91170
|
}), NOT_A_DEVICE.CLUSTER;
|
|
90223
91171
|
/**
|
|
90224
91172
|
* toast — system-scoped singleton capability that streams toast
|
|
@@ -92172,6 +93120,265 @@ var weatherCapability = {
|
|
|
92172
93120
|
]
|
|
92173
93121
|
}
|
|
92174
93122
|
};
|
|
93123
|
+
var WeatherStationStatusSchema = object({
|
|
93124
|
+
temperature: number$1().nullable().default(null).meta(readingMeta("temperature", { precision: 1 })),
|
|
93125
|
+
humidity: number$1().min(0).max(100).nullable().default(null).meta(readingMeta("humidity")),
|
|
93126
|
+
pressure: number$1().nullable().default(null).meta(readingMeta("pressure")),
|
|
93127
|
+
windSpeed: number$1().nullable().default(null).meta(readingMeta("speed")),
|
|
93128
|
+
windGust: number$1().nullable().default(null).meta(readingMeta("speed")),
|
|
93129
|
+
windBearing: number$1().nullable().default(null).meta(readingMeta("angle")),
|
|
93130
|
+
rainRate: number$1().nullable().default(null).meta(readingMeta("precipitation-rate", { precision: 1 })),
|
|
93131
|
+
rainDaily: number$1().nullable().default(null).meta(readingMeta("precipitation", { precision: 1 })),
|
|
93132
|
+
rainEvent: number$1().nullable().default(null).meta(readingMeta("precipitation", { precision: 1 })),
|
|
93133
|
+
uv: number$1().nullable().default(null).meta(readingMeta("index", { precision: 1 })),
|
|
93134
|
+
solarRadiation: number$1().nullable().default(null).meta(readingMeta("irradiance")),
|
|
93135
|
+
dewPoint: number$1().nullable().default(null).meta(readingMeta("temperature", { precision: 1 })),
|
|
93136
|
+
/** Apparent ("feels like") temperature. */
|
|
93137
|
+
feelsLike: number$1().nullable().default(null).meta(readingMeta("temperature", { precision: 1 })),
|
|
93138
|
+
/** Vapour-pressure deficit, stored in kPa (the unit stations and growers read it in). */
|
|
93139
|
+
vpd: number$1().nullable().default(null).meta(readingMeta("none", { precision: 2 })),
|
|
93140
|
+
/** Highest wind gust since local midnight. */
|
|
93141
|
+
windGustMax: number$1().nullable().default(null).meta(readingMeta("speed")),
|
|
93142
|
+
/** Wind bearing averaged over the station's own window. */
|
|
93143
|
+
windBearingAvg: number$1().nullable().default(null).meta(readingMeta("angle")),
|
|
93144
|
+
rain24h: number$1().nullable().default(null).meta(readingMeta("precipitation", { precision: 1 })),
|
|
93145
|
+
rainWeekly: number$1().nullable().default(null).meta(readingMeta("precipitation", { precision: 1 })),
|
|
93146
|
+
rainMonthly: number$1().nullable().default(null).meta(readingMeta("precipitation", { precision: 1 })),
|
|
93147
|
+
rainYearly: number$1().nullable().default(null).meta(readingMeta("precipitation", { precision: 1 }))
|
|
93148
|
+
}).extend({
|
|
93149
|
+
/** Ms epoch of the poll that produced this slice. 0 before the first one. */
|
|
93150
|
+
lastFetchedAt: number$1() });
|
|
93151
|
+
var numeric$2 = (field, quantity, label, unit, icon) => ({
|
|
93152
|
+
kind: "numeric",
|
|
93153
|
+
field,
|
|
93154
|
+
quantity,
|
|
93155
|
+
label,
|
|
93156
|
+
unit,
|
|
93157
|
+
icon
|
|
93158
|
+
});
|
|
93159
|
+
/** Every reading of the station with the unit a Customize source must carry ('' = dimensionless). */
|
|
93160
|
+
var STATION_FIELD_UNITS = {
|
|
93161
|
+
temperature: "°C",
|
|
93162
|
+
humidity: "%",
|
|
93163
|
+
pressure: "hPa",
|
|
93164
|
+
windSpeed: "m/s",
|
|
93165
|
+
windGust: "m/s",
|
|
93166
|
+
windBearing: "°",
|
|
93167
|
+
rainRate: "mm/h",
|
|
93168
|
+
rainDaily: "mm",
|
|
93169
|
+
rainEvent: "mm",
|
|
93170
|
+
uv: "",
|
|
93171
|
+
solarRadiation: "W/m²",
|
|
93172
|
+
dewPoint: "°C",
|
|
93173
|
+
feelsLike: "°C",
|
|
93174
|
+
vpd: "kPa",
|
|
93175
|
+
windGustMax: "m/s",
|
|
93176
|
+
windBearingAvg: "°",
|
|
93177
|
+
rain24h: "mm",
|
|
93178
|
+
rainWeekly: "mm",
|
|
93179
|
+
rainMonthly: "mm",
|
|
93180
|
+
rainYearly: "mm"
|
|
93181
|
+
};
|
|
93182
|
+
function isStationField(key) {
|
|
93183
|
+
return Object.prototype.hasOwnProperty.call(STATION_FIELD_UNITS, key);
|
|
93184
|
+
}
|
|
93185
|
+
var STATION_FIELDS = Object.keys(STATION_FIELD_UNITS).filter(isStationField);
|
|
93186
|
+
/**
|
|
93187
|
+
* One scalar target per reading, `apply: 'add'` and listed in `overridable` by its own id
|
|
93188
|
+
* (the running-state / climate-control mechanism, D984 / D990): a station that reports a
|
|
93189
|
+
* reading natively keeps it until the operator assigns another device to that ONE field,
|
|
93190
|
+
* and a device with no `weather-station` slice becomes one from the sources picked. On an
|
|
93191
|
+
* add, every other reading is absent from the claim and the schema defaults it to null
|
|
93192
|
+
* (a missing sensor is never 0, D393) — the fan-control precedent, never a cross-field companion
|
|
93193
|
+
* (the scalar merge treats a companion as owned by its target).
|
|
93194
|
+
*/
|
|
93195
|
+
function stationTarget(field) {
|
|
93196
|
+
const unit = STATION_FIELD_UNITS[field];
|
|
93197
|
+
return {
|
|
93198
|
+
id: field,
|
|
93199
|
+
cardinality: "scalar",
|
|
93200
|
+
vocabulary: {
|
|
93201
|
+
cap: "weather-station",
|
|
93202
|
+
stateField: field
|
|
93203
|
+
},
|
|
93204
|
+
deviceTypes: [DeviceType.WeatherStation],
|
|
93205
|
+
apply: "add",
|
|
93206
|
+
path: field,
|
|
93207
|
+
sources: [{
|
|
93208
|
+
kind: "numeric",
|
|
93209
|
+
...unit.length > 0 ? { requiredUnit: unit } : {},
|
|
93210
|
+
transforms: [{ kind: "identity" }]
|
|
93211
|
+
}],
|
|
93212
|
+
companions: [{
|
|
93213
|
+
kind: "clock",
|
|
93214
|
+
path: "lastFetchedAt",
|
|
93215
|
+
when: "add"
|
|
93216
|
+
}],
|
|
93217
|
+
sourceReport: { status: "assignment-status" }
|
|
93218
|
+
};
|
|
93219
|
+
}
|
|
93220
|
+
var weatherStationCustomize = {
|
|
93221
|
+
version: 1,
|
|
93222
|
+
overridable: STATION_FIELDS.map((field) => ({
|
|
93223
|
+
path: field,
|
|
93224
|
+
by: field
|
|
93225
|
+
})),
|
|
93226
|
+
targets: STATION_FIELDS.map(stationTarget)
|
|
93227
|
+
};
|
|
93228
|
+
var weatherStationCapability = {
|
|
93229
|
+
name: "weather-station",
|
|
93230
|
+
scope: "device",
|
|
93231
|
+
deviceNative: true,
|
|
93232
|
+
mode: "singleton",
|
|
93233
|
+
deviceTypes: [DeviceType.WeatherStation],
|
|
93234
|
+
methods: {},
|
|
93235
|
+
status: {
|
|
93236
|
+
schema: WeatherStationStatusSchema,
|
|
93237
|
+
kind: "push"
|
|
93238
|
+
},
|
|
93239
|
+
runtimeState: WeatherStationStatusSchema,
|
|
93240
|
+
/**
|
|
93241
|
+
* History (D850): the station records its own readings. Rain totals that
|
|
93242
|
+
* reset (event, day, week, month, year) and the sliding 24 h total are
|
|
93243
|
+
* levels, so `gauge`; `counter` is for a monotonic meter only.
|
|
93244
|
+
*/
|
|
93245
|
+
history: { fields: {
|
|
93246
|
+
temperature: {
|
|
93247
|
+
kind: "gauge",
|
|
93248
|
+
unit: "°C",
|
|
93249
|
+
deadband: .1
|
|
93250
|
+
},
|
|
93251
|
+
humidity: {
|
|
93252
|
+
kind: "gauge",
|
|
93253
|
+
unit: "%",
|
|
93254
|
+
deadband: 1
|
|
93255
|
+
},
|
|
93256
|
+
pressure: {
|
|
93257
|
+
kind: "gauge",
|
|
93258
|
+
unit: "hPa",
|
|
93259
|
+
deadband: .2
|
|
93260
|
+
},
|
|
93261
|
+
windSpeed: {
|
|
93262
|
+
kind: "gauge",
|
|
93263
|
+
unit: "m/s",
|
|
93264
|
+
deadband: .2
|
|
93265
|
+
},
|
|
93266
|
+
windGust: {
|
|
93267
|
+
kind: "gauge",
|
|
93268
|
+
unit: "m/s",
|
|
93269
|
+
deadband: .2
|
|
93270
|
+
},
|
|
93271
|
+
windBearing: {
|
|
93272
|
+
kind: "gauge",
|
|
93273
|
+
unit: "°",
|
|
93274
|
+
deadband: 5
|
|
93275
|
+
},
|
|
93276
|
+
rainRate: {
|
|
93277
|
+
kind: "gauge",
|
|
93278
|
+
unit: "mm/h",
|
|
93279
|
+
deadband: .1
|
|
93280
|
+
},
|
|
93281
|
+
rainDaily: {
|
|
93282
|
+
kind: "gauge",
|
|
93283
|
+
unit: "mm",
|
|
93284
|
+
deadband: .1
|
|
93285
|
+
},
|
|
93286
|
+
rainEvent: {
|
|
93287
|
+
kind: "gauge",
|
|
93288
|
+
unit: "mm",
|
|
93289
|
+
deadband: .1
|
|
93290
|
+
},
|
|
93291
|
+
uv: {
|
|
93292
|
+
kind: "gauge",
|
|
93293
|
+
unit: "index",
|
|
93294
|
+
deadband: .1
|
|
93295
|
+
},
|
|
93296
|
+
solarRadiation: {
|
|
93297
|
+
kind: "gauge",
|
|
93298
|
+
unit: "W/m²",
|
|
93299
|
+
deadband: 5
|
|
93300
|
+
},
|
|
93301
|
+
dewPoint: {
|
|
93302
|
+
kind: "gauge",
|
|
93303
|
+
unit: "°C",
|
|
93304
|
+
deadband: .1
|
|
93305
|
+
},
|
|
93306
|
+
feelsLike: {
|
|
93307
|
+
kind: "gauge",
|
|
93308
|
+
unit: "°C",
|
|
93309
|
+
deadband: .1
|
|
93310
|
+
},
|
|
93311
|
+
vpd: {
|
|
93312
|
+
kind: "gauge",
|
|
93313
|
+
unit: "kPa",
|
|
93314
|
+
deadband: .05
|
|
93315
|
+
},
|
|
93316
|
+
windGustMax: {
|
|
93317
|
+
kind: "gauge",
|
|
93318
|
+
unit: "m/s",
|
|
93319
|
+
deadband: .2
|
|
93320
|
+
},
|
|
93321
|
+
windBearingAvg: {
|
|
93322
|
+
kind: "gauge",
|
|
93323
|
+
unit: "°",
|
|
93324
|
+
deadband: 5
|
|
93325
|
+
},
|
|
93326
|
+
rain24h: {
|
|
93327
|
+
kind: "gauge",
|
|
93328
|
+
unit: "mm",
|
|
93329
|
+
deadband: .1
|
|
93330
|
+
},
|
|
93331
|
+
rainWeekly: {
|
|
93332
|
+
kind: "gauge",
|
|
93333
|
+
unit: "mm",
|
|
93334
|
+
deadband: .1
|
|
93335
|
+
},
|
|
93336
|
+
rainMonthly: {
|
|
93337
|
+
kind: "gauge",
|
|
93338
|
+
unit: "mm",
|
|
93339
|
+
deadband: .1
|
|
93340
|
+
},
|
|
93341
|
+
rainYearly: {
|
|
93342
|
+
kind: "gauge",
|
|
93343
|
+
unit: "mm",
|
|
93344
|
+
deadband: .1
|
|
93345
|
+
}
|
|
93346
|
+
} },
|
|
93347
|
+
customize: weatherStationCustomize,
|
|
93348
|
+
/** The poll clock is written but is no reason to commit a row. */
|
|
93349
|
+
volatileStateFields: ["lastFetchedAt"],
|
|
93350
|
+
/**
|
|
93351
|
+
* Runtime-state durability: **session** — a station reading is stale the
|
|
93352
|
+
* moment the hub is down; the provider re-reads on the next poll.
|
|
93353
|
+
*/
|
|
93354
|
+
durability: "session",
|
|
93355
|
+
vocabulary: {
|
|
93356
|
+
noun: t("Weather station", "Stazione meteo"),
|
|
93357
|
+
order: 5235,
|
|
93358
|
+
state: [
|
|
93359
|
+
numeric$2("temperature", t("the outdoor temperature", "la temperatura esterna"), t("Temperature", "Temperatura"), "°C", "thermometer"),
|
|
93360
|
+
numeric$2("humidity", t("the outdoor humidity", "l’umidità esterna"), t("Humidity", "Umidità"), "%", "droplets"),
|
|
93361
|
+
numeric$2("pressure", t("the air pressure", "la pressione atmosferica"), t("Pressure", "Pressione"), "hPa", "gauge"),
|
|
93362
|
+
numeric$2("windSpeed", t("the wind speed", "la velocità del vento"), t("Wind", "Vento"), "m/s", "wind"),
|
|
93363
|
+
numeric$2("windGust", t("the wind gust", "la raffica di vento"), t("Gust", "Raffica"), "m/s", "wind"),
|
|
93364
|
+
numeric$2("windBearing", t("the wind bearing", "la direzione del vento"), t("Wind bearing", "Direzione del vento"), "°", "wind"),
|
|
93365
|
+
numeric$2("rainRate", t("the rain rate", "l’intensità della pioggia"), t("Rain rate", "Intensità pioggia"), "mm/h", "droplets"),
|
|
93366
|
+
numeric$2("rainDaily", t("the rain today", "la pioggia di oggi"), t("Rain today", "Pioggia oggi"), "mm", "droplets"),
|
|
93367
|
+
numeric$2("rainEvent", t("the rain this event", "la pioggia di questo evento"), t("Rain event", "Evento di pioggia"), "mm", "droplets"),
|
|
93368
|
+
numeric$2("uv", t("the UV index", "l’indice UV"), t("UV", "UV"), "", "cloud-sun"),
|
|
93369
|
+
numeric$2("solarRadiation", t("the solar radiation", "la radiazione solare"), t("Solar", "Sole"), "W/m²", "cloud-sun"),
|
|
93370
|
+
numeric$2("dewPoint", t("the dew point", "il punto di rugiada"), t("Dew point", "Punto di rugiada"), "°C", "thermometer"),
|
|
93371
|
+
numeric$2("feelsLike", t("the feels-like temperature", "la temperatura percepita"), t("Feels like", "Percepita"), "°C", "thermometer"),
|
|
93372
|
+
numeric$2("vpd", t("the vapour-pressure deficit", "il deficit di pressione di vapore"), t("VPD", "VPD"), "kPa", "gauge"),
|
|
93373
|
+
numeric$2("windGustMax", t("the highest gust today", "la raffica massima di oggi"), t("Max gust", "Raffica max"), "m/s", "wind"),
|
|
93374
|
+
numeric$2("windBearingAvg", t("the average wind bearing", "la direzione media del vento"), t("Avg bearing", "Direzione media"), "°", "wind"),
|
|
93375
|
+
numeric$2("rain24h", t("the rain in the last 24 hours", "la pioggia delle ultime 24 ore"), t("Rain 24 h", "Pioggia 24 h"), "mm", "droplets"),
|
|
93376
|
+
numeric$2("rainWeekly", t("the rain this week", "la pioggia di questa settimana"), t("Rain week", "Pioggia settimana"), "mm", "droplets"),
|
|
93377
|
+
numeric$2("rainMonthly", t("the rain this month", "la pioggia di questo mese"), t("Rain month", "Pioggia mese"), "mm", "droplets"),
|
|
93378
|
+
numeric$2("rainYearly", t("the rain this year", "la pioggia di quest’anno"), t("Rain year", "Pioggia anno"), "mm", "droplets")
|
|
93379
|
+
]
|
|
93380
|
+
}
|
|
93381
|
+
};
|
|
92175
93382
|
/**
|
|
92176
93383
|
* Optional client-side hints sent at session creation to help the provider
|
|
92177
93384
|
* pick the best native source. All fields optional — a viewer that knows
|
|
@@ -93737,6 +94944,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
93737
94944
|
doorbell: doorbellCapability,
|
|
93738
94945
|
energySystem: energySystemCapability,
|
|
93739
94946
|
enumSensor: enumSensorCapability,
|
|
94947
|
+
error: errorCapability,
|
|
93740
94948
|
eventEmitter: eventEmitterCapability,
|
|
93741
94949
|
fanControl: fanControlCapability,
|
|
93742
94950
|
featureProbe: featureProbeCapability,
|
|
@@ -93793,10 +95001,59 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
93793
95001
|
vibration: vibrationCapability,
|
|
93794
95002
|
waterHeater: waterHeaterCapability,
|
|
93795
95003
|
weather: weatherCapability,
|
|
95004
|
+
weatherStation: weatherStationCapability,
|
|
93796
95005
|
zoneAnalytics: zoneAnalyticsCapability,
|
|
93797
95006
|
zoneRules: zoneRulesCapability,
|
|
93798
95007
|
zones: zonesCapability
|
|
93799
95008
|
};
|
|
95009
|
+
/**
|
|
95010
|
+
* The edge between two readings, or `null` for no edge.
|
|
95011
|
+
*
|
|
95012
|
+
* - `null`/cold → `true` is a START (a fault already open at boot is one);
|
|
95013
|
+
* - `true` → `false` is a RESOLVE;
|
|
95014
|
+
* - an UNKNOWN reading (`active: null`) is never an edge, in either direction —
|
|
95015
|
+
* a failed read must neither raise nor close an episode (D393, D49);
|
|
95016
|
+
* - `true` → `true` is the same episode, whatever the code did.
|
|
95017
|
+
*/
|
|
95018
|
+
function deviceErrorEdge(previous, next) {
|
|
95019
|
+
if (next.active === true && previous?.active !== true) return "start";
|
|
95020
|
+
if (next.active === false && previous?.active === true) return "resolve";
|
|
95021
|
+
return null;
|
|
95022
|
+
}
|
|
95023
|
+
function deviceErrorAlertId(deviceId) {
|
|
95024
|
+
return `device-error:${String(deviceId)}`;
|
|
95025
|
+
}
|
|
95026
|
+
/** The alert that opens an episode. `since` is the fault's own start, else `now`. */
|
|
95027
|
+
function buildDeviceErrorAlert(deviceId, deviceName, status, now) {
|
|
95028
|
+
const label = status.label ?? status.code ?? "Fault";
|
|
95029
|
+
const startedAt = status.since ?? now;
|
|
95030
|
+
const alertId = deviceErrorAlertId(deviceId);
|
|
95031
|
+
return {
|
|
95032
|
+
id: alertId,
|
|
95033
|
+
category: "device.error",
|
|
95034
|
+
severity: "critical",
|
|
95035
|
+
title: `${deviceName}: ${label}`,
|
|
95036
|
+
message: `${deviceName} reports a fault: ${label}.`,
|
|
95037
|
+
action: {
|
|
95038
|
+
label: "Open device",
|
|
95039
|
+
href: `/devices/${String(deviceId)}`,
|
|
95040
|
+
navigation: "app"
|
|
95041
|
+
},
|
|
95042
|
+
status: "active",
|
|
95043
|
+
read: false,
|
|
95044
|
+
createdAt: now,
|
|
95045
|
+
updatedAt: now,
|
|
95046
|
+
source: {
|
|
95047
|
+
type: "device",
|
|
95048
|
+
id: String(deviceId)
|
|
95049
|
+
},
|
|
95050
|
+
metadata: {
|
|
95051
|
+
episodeId: `${alertId}@${String(startedAt)}`,
|
|
95052
|
+
code: status.code,
|
|
95053
|
+
deviceSeverity: status.severity
|
|
95054
|
+
}
|
|
95055
|
+
};
|
|
95056
|
+
}
|
|
93800
95057
|
var BaseDevice = class {
|
|
93801
95058
|
id;
|
|
93802
95059
|
stableId;
|
|
@@ -94096,6 +95353,68 @@ var BaseDevice = class {
|
|
|
94096
95353
|
} catch (err) {}
|
|
94097
95354
|
}
|
|
94098
95355
|
/**
|
|
95356
|
+
* Declare that this device can report a fault (the `error` cap). The slice
|
|
95357
|
+
* starts UNKNOWN — a restored slice is kept, so a fault that was open before
|
|
95358
|
+
* a restart is compared, not announced again.
|
|
95359
|
+
*/
|
|
95360
|
+
registerErrorCap() {
|
|
95361
|
+
this.ctx.registerNativeCap?.(errorCapability, {});
|
|
95362
|
+
if (this.runtimeState.getCapState(errorCapability.name) === void 0) this.setCapSlice(errorCapability, ERROR_STATUS_COLD);
|
|
95363
|
+
}
|
|
95364
|
+
/**
|
|
95365
|
+
* Publish the device's fault. The slice is written; on an EDGE (a fault
|
|
95366
|
+
* starts, or one resolves) an attention episode opens or closes through the
|
|
95367
|
+
* alerts cap, which the notification center announces as
|
|
95368
|
+
* `device-attention-required` / `-resolved`. An unknown reading is never an
|
|
95369
|
+
* edge. No rule exists by default: it notifies when the operator makes one.
|
|
95370
|
+
*/
|
|
95371
|
+
async publishError(reading) {
|
|
95372
|
+
const previous = this.getCapSlice(errorCapability);
|
|
95373
|
+
if (reading.active === null && previous !== null && previous.active !== null) return;
|
|
95374
|
+
const now = Date.now();
|
|
95375
|
+
const edge = deviceErrorEdge(previous, reading);
|
|
95376
|
+
const next = edge === "start" && reading.since === null ? {
|
|
95377
|
+
...reading,
|
|
95378
|
+
since: now
|
|
95379
|
+
} : reading;
|
|
95380
|
+
this.setCapSlice(errorCapability, next);
|
|
95381
|
+
if (edge === null) return;
|
|
95382
|
+
const alerts = this.ctx.api.alerts;
|
|
95383
|
+
if (alerts === void 0) {
|
|
95384
|
+
this.ctx.logger.warn("device error: attention event skipped — alerts capability missing", {
|
|
95385
|
+
tags: { deviceId: this.id },
|
|
95386
|
+
meta: { edge }
|
|
95387
|
+
});
|
|
95388
|
+
return;
|
|
95389
|
+
}
|
|
95390
|
+
try {
|
|
95391
|
+
if (edge === "start") await alerts.emit.mutate(buildDeviceErrorAlert(this.id, this.name, next, now));
|
|
95392
|
+
else await alerts.update.mutate({
|
|
95393
|
+
alertId: deviceErrorAlertId(this.id),
|
|
95394
|
+
patch: {
|
|
95395
|
+
status: "completed",
|
|
95396
|
+
read: true,
|
|
95397
|
+
updatedAt: now
|
|
95398
|
+
}
|
|
95399
|
+
});
|
|
95400
|
+
this.ctx.logger.info(`device error: ${edge === "start" ? "raised" : "resolved"}`, {
|
|
95401
|
+
tags: { deviceId: this.id },
|
|
95402
|
+
meta: {
|
|
95403
|
+
code: next.code,
|
|
95404
|
+
label: next.label
|
|
95405
|
+
}
|
|
95406
|
+
});
|
|
95407
|
+
} catch (err) {
|
|
95408
|
+
this.ctx.logger.warn("device error: attention event failed", {
|
|
95409
|
+
tags: { deviceId: this.id },
|
|
95410
|
+
meta: {
|
|
95411
|
+
edge,
|
|
95412
|
+
error: errMsg(err)
|
|
95413
|
+
}
|
|
95414
|
+
});
|
|
95415
|
+
}
|
|
95416
|
+
}
|
|
95417
|
+
/**
|
|
94099
95418
|
* Typed read-through to a cap-keyed runtime-state slice. Drivers
|
|
94100
95419
|
* call `this.getCapSlice(batteryCapability)` and the return type
|
|
94101
95420
|
* is inferred from the cap's `runtimeState` Zod schema — no string
|
|
@@ -95043,7 +96362,7 @@ var BaseDeviceProvider = class extends BaseAddon {
|
|
|
95043
96362
|
}
|
|
95044
96363
|
};
|
|
95045
96364
|
DeviceType.HeatPump;
|
|
95046
|
-
DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.HeatPump, DeviceType.EnergySystem, DeviceType.Camera, DeviceType.Switch, DeviceType.Siren, DeviceType.Light, DeviceType.Fan, DeviceType.Sensor, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.PetFountain, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer, DeviceType.Gateway;
|
|
96365
|
+
DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.HeatPump, DeviceType.EnergySystem, DeviceType.Camera, DeviceType.Switch, DeviceType.Siren, DeviceType.Light, DeviceType.Fan, DeviceType.Sensor, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.WeatherStation, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.PetFountain, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer, DeviceType.Gateway;
|
|
95047
96366
|
new Set(Object.values(DeviceType));
|
|
95048
96367
|
/** Parses the raw slice with the cap's own schema; `undefined` when it does not parse. */
|
|
95049
96368
|
function contribution(cap, schema, build) {
|
|
@@ -96412,6 +97731,17 @@ var SENSORS_FAMILY_CONTRIBUTIONS = {
|
|
|
96412
97731
|
doorbell: doorbellContribution,
|
|
96413
97732
|
meter: meterContribution,
|
|
96414
97733
|
weather: weatherContribution,
|
|
97734
|
+
"weather-station": contribution("weather-station", WeatherStationStatusSchema, (slice) => {
|
|
97735
|
+
if (slice === void 0 || slice.temperature === null) return { reading: reading("weather", "unknown") };
|
|
97736
|
+
const celsius = `${number(slice.temperature)}°C`;
|
|
97737
|
+
const facts = [fact("reading", "thermometer", t(celsius, celsius), "primary")];
|
|
97738
|
+
if (slice.humidity !== null) facts.push(fact("reading", "droplets", t(`${Math.round(slice.humidity)}%`, `${Math.round(slice.humidity)}%`)));
|
|
97739
|
+
if (slice.windSpeed !== null) facts.push(fact("reading", "wind", t(`${number(slice.windSpeed)} m/s`, `${number(slice.windSpeed)} m/s`)));
|
|
97740
|
+
return {
|
|
97741
|
+
reading: reading("weather", "on", false, t(celsius, celsius)),
|
|
97742
|
+
facts
|
|
97743
|
+
};
|
|
97744
|
+
}),
|
|
96415
97745
|
update: updateContribution,
|
|
96416
97746
|
image: imageContribution,
|
|
96417
97747
|
button: buttonContribution,
|
|
@@ -97088,7 +98418,7 @@ var HEAT_PUMP_FAMILY_CONTRIBUTIONS = { "heat-pump-status": contribution("heat-pu
|
|
|
97088
98418
|
...Object.values(CLIMATE_FAMILY_CONTRIBUTIONS),
|
|
97089
98419
|
...Object.values(HEAT_PUMP_FAMILY_CONTRIBUTIONS)
|
|
97090
98420
|
];
|
|
97091
|
-
DeviceType.Camera, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.HeatPump, DeviceType.EnergySystem, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.PetFountain, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer, DeviceType.Gateway;
|
|
98421
|
+
DeviceType.Camera, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.HeatPump, DeviceType.EnergySystem, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.WeatherStation, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.PetFountain, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer, DeviceType.Gateway;
|
|
97092
98422
|
/**
|
|
97093
98423
|
* Who looks like what (D1023). One look per {@link DeviceType}, refined by a
|
|
97094
98424
|
* {@link DeviceRole} where the role changes how the device reads (a leak
|
|
@@ -97732,7 +99062,7 @@ lookOf({
|
|
|
97732
99062
|
standby: MUTED
|
|
97733
99063
|
});
|
|
97734
99064
|
DeviceType.Climate;
|
|
97735
|
-
DeviceType.Camera, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.HeatPump, DeviceType.EnergySystem, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.PetFountain, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer, DeviceType.Gateway;
|
|
99065
|
+
DeviceType.Camera, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.HeatPump, DeviceType.EnergySystem, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.WeatherStation, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.PetFountain, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer, DeviceType.Gateway;
|
|
97736
99066
|
DeviceRole.Siren, DeviceRole.Floodlight, DeviceRole.Spotlight, DeviceRole.PirSensor, DeviceRole.Chime, DeviceRole.Autotrack, DeviceRole.Nightvision, DeviceRole.PrivacyMask, DeviceRole.Doorbell, DeviceRole.CoverBlind, DeviceRole.CoverShutter, DeviceRole.CoverAwning, DeviceRole.CoverCurtain, DeviceRole.CoverGarage, DeviceRole.CoverGate, DeviceRole.CoverDoor, DeviceRole.CoverWindow, DeviceRole.BinaryHelper, DeviceRole.Outlet, DeviceRole.SwitchHeater, DeviceRole.SwitchFan, DeviceRole.SwitchLight, DeviceRole.ClimateAc, DeviceRole.ClimateThermostat, DeviceRole.ClimateFloor, DeviceRole.ClimateRadiator, DeviceRole.ClimateHeater, DeviceRole.ClimateHeatPumpCircuit, DeviceRole.MotionSensor, DeviceRole.ContactSensor, DeviceRole.LeakSensor, DeviceRole.SmokeSensor, DeviceRole.COSensor, DeviceRole.GasSensor, DeviceRole.TamperSensor, DeviceRole.VibrationSensor, DeviceRole.ConnectivitySensor, DeviceRole.SoundSensor, DeviceRole.BinarySensor, DeviceRole.TemperatureSensor, DeviceRole.HumiditySensor, DeviceRole.AmbientLightSensor, DeviceRole.PressureSensor, DeviceRole.WindSensor, DeviceRole.RainSensor, DeviceRole.UvSensor, DeviceRole.SolarRadiationSensor, DeviceRole.SoilMoistureSensor, DeviceRole.PowerSensor, DeviceRole.EnergySensor, DeviceRole.VoltageSensor, DeviceRole.CurrentSensor, DeviceRole.AirQualitySensor, DeviceRole.BatterySensor, DeviceRole.NumericSensor, DeviceRole.EnumSensor, DeviceRole.DateTimeSensor, DeviceRole.GenericSensor, DeviceRole.NumericControl, DeviceRole.SelectControl, DeviceRole.TextControl, DeviceRole.DateTimeControl, DeviceRole.MobilePushNotifier, DeviceRole.MessagingNotifier, DeviceRole.EmailNotifier, DeviceRole.GenericNotifier, DeviceRole.IrTransmitter;
|
|
97737
99067
|
Object.freeze({
|
|
97738
99068
|
"accessories.getStatus": {
|
|
@@ -99037,6 +100367,13 @@ Object.freeze({
|
|
|
99037
100367
|
access: "view",
|
|
99038
100368
|
role: "viewer"
|
|
99039
100369
|
},
|
|
100370
|
+
"control.first": {
|
|
100371
|
+
capName: "control",
|
|
100372
|
+
capScope: "device",
|
|
100373
|
+
addonId: null,
|
|
100374
|
+
access: "create",
|
|
100375
|
+
role: "viewer"
|
|
100376
|
+
},
|
|
99040
100377
|
"control.getStatus": {
|
|
99041
100378
|
capName: "control",
|
|
99042
100379
|
capScope: "device",
|
|
@@ -99044,6 +100381,27 @@ Object.freeze({
|
|
|
99044
100381
|
access: "view",
|
|
99045
100382
|
role: "viewer"
|
|
99046
100383
|
},
|
|
100384
|
+
"control.last": {
|
|
100385
|
+
capName: "control",
|
|
100386
|
+
capScope: "device",
|
|
100387
|
+
addonId: null,
|
|
100388
|
+
access: "create",
|
|
100389
|
+
role: "viewer"
|
|
100390
|
+
},
|
|
100391
|
+
"control.next": {
|
|
100392
|
+
capName: "control",
|
|
100393
|
+
capScope: "device",
|
|
100394
|
+
addonId: null,
|
|
100395
|
+
access: "create",
|
|
100396
|
+
role: "viewer"
|
|
100397
|
+
},
|
|
100398
|
+
"control.previous": {
|
|
100399
|
+
capName: "control",
|
|
100400
|
+
capScope: "device",
|
|
100401
|
+
addonId: null,
|
|
100402
|
+
access: "create",
|
|
100403
|
+
role: "viewer"
|
|
100404
|
+
},
|
|
99047
100405
|
"control.setValue": {
|
|
99048
100406
|
capName: "control",
|
|
99049
100407
|
capScope: "device",
|
|
@@ -100997,6 +102355,13 @@ Object.freeze({
|
|
|
100997
102355
|
access: "view",
|
|
100998
102356
|
role: "viewer"
|
|
100999
102357
|
},
|
|
102358
|
+
"error.getStatus": {
|
|
102359
|
+
capName: "error",
|
|
102360
|
+
capScope: "device",
|
|
102361
|
+
addonId: null,
|
|
102362
|
+
access: "view",
|
|
102363
|
+
role: "viewer"
|
|
102364
|
+
},
|
|
101000
102365
|
"eventEmitter.getStatus": {
|
|
101001
102366
|
capName: "event-emitter",
|
|
101002
102367
|
capScope: "device",
|
|
@@ -101081,6 +102446,13 @@ Object.freeze({
|
|
|
101081
102446
|
access: "view",
|
|
101082
102447
|
role: "feature:face-assignment"
|
|
101083
102448
|
},
|
|
102449
|
+
"faceGallery.moveIdentitySample": {
|
|
102450
|
+
capName: "face-gallery",
|
|
102451
|
+
capScope: "system",
|
|
102452
|
+
addonId: null,
|
|
102453
|
+
access: "create",
|
|
102454
|
+
role: "feature:face-assignment"
|
|
102455
|
+
},
|
|
101084
102456
|
"faceGallery.removeSample": {
|
|
101085
102457
|
capName: "face-gallery",
|
|
101086
102458
|
capScope: "system",
|
|
@@ -105001,6 +106373,13 @@ Object.freeze({
|
|
|
105001
106373
|
access: "view",
|
|
105002
106374
|
role: "feature:plate-assignment"
|
|
105003
106375
|
},
|
|
106376
|
+
"plateGallery.moveVehicleSample": {
|
|
106377
|
+
capName: "plate-gallery",
|
|
106378
|
+
capScope: "system",
|
|
106379
|
+
addonId: null,
|
|
106380
|
+
access: "create",
|
|
106381
|
+
role: "feature:plate-assignment"
|
|
106382
|
+
},
|
|
105004
106383
|
"plateGallery.removeVehicleSample": {
|
|
105005
106384
|
capName: "plate-gallery",
|
|
105006
106385
|
capScope: "system",
|
|
@@ -107255,6 +108634,13 @@ Object.freeze({
|
|
|
107255
108634
|
access: "create",
|
|
107256
108635
|
role: "admin"
|
|
107257
108636
|
},
|
|
108637
|
+
"terminalSession.serverShellStatus": {
|
|
108638
|
+
capName: "terminal-session",
|
|
108639
|
+
capScope: "system",
|
|
108640
|
+
addonId: null,
|
|
108641
|
+
access: "view",
|
|
108642
|
+
role: "admin"
|
|
108643
|
+
},
|
|
107258
108644
|
"terminalSession.writeInput": {
|
|
107259
108645
|
capName: "terminal-session",
|
|
107260
108646
|
capScope: "system",
|
|
@@ -107990,6 +109376,13 @@ Object.freeze({
|
|
|
107990
109376
|
access: "view",
|
|
107991
109377
|
role: "viewer"
|
|
107992
109378
|
},
|
|
109379
|
+
"weatherStation.getStatus": {
|
|
109380
|
+
capName: "weather-station",
|
|
109381
|
+
capScope: "device",
|
|
109382
|
+
addonId: null,
|
|
109383
|
+
access: "view",
|
|
109384
|
+
role: "viewer"
|
|
109385
|
+
},
|
|
107993
109386
|
"webrtcSession.addIceCandidate": {
|
|
107994
109387
|
capName: "webrtc-session",
|
|
107995
109388
|
capScope: "device",
|
|
@@ -108203,7 +109596,7 @@ function offered(received) {
|
|
|
108203
109596
|
};
|
|
108204
109597
|
}
|
|
108205
109598
|
offered(HA_AS), withheld(HOMEKIT_REASON), withheld(ALEXA_REASON), withheld(GOOGLE_REASON), withheld(MATTER_REASON);
|
|
108206
|
-
DeviceType.Camera, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Climate, DeviceType.HeatPump, DeviceType.EnergySystem, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.PetFountain, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer, DeviceType.Gateway;
|
|
109599
|
+
DeviceType.Camera, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Climate, DeviceType.HeatPump, DeviceType.EnergySystem, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.WeatherStation, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.PetFountain, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer, DeviceType.Gateway;
|
|
108207
109600
|
DeviceRole.Siren, DeviceRole.Floodlight, DeviceRole.Spotlight, DeviceRole.PirSensor, DeviceRole.Chime, DeviceRole.Autotrack, DeviceRole.Nightvision, DeviceRole.PrivacyMask, DeviceRole.Doorbell, DeviceRole.CoverBlind, DeviceRole.CoverShutter, DeviceRole.CoverAwning, DeviceRole.CoverCurtain, DeviceRole.CoverGarage, DeviceRole.CoverGate, DeviceRole.CoverDoor, DeviceRole.CoverWindow, DeviceRole.BinaryHelper, DeviceRole.Outlet, DeviceRole.SwitchHeater, DeviceRole.SwitchFan, DeviceRole.SwitchLight, DeviceRole.ClimateAc, DeviceRole.ClimateThermostat, DeviceRole.ClimateFloor, DeviceRole.ClimateRadiator, DeviceRole.ClimateHeater, DeviceRole.ClimateHeatPumpCircuit, DeviceRole.MotionSensor, DeviceRole.ContactSensor, DeviceRole.LeakSensor, DeviceRole.SmokeSensor, DeviceRole.COSensor, DeviceRole.GasSensor, DeviceRole.TamperSensor, DeviceRole.VibrationSensor, DeviceRole.ConnectivitySensor, DeviceRole.SoundSensor, DeviceRole.BinarySensor, DeviceRole.TemperatureSensor, DeviceRole.HumiditySensor, DeviceRole.AmbientLightSensor, DeviceRole.PressureSensor, DeviceRole.WindSensor, DeviceRole.RainSensor, DeviceRole.UvSensor, DeviceRole.SolarRadiationSensor, DeviceRole.SoilMoistureSensor, DeviceRole.PowerSensor, DeviceRole.EnergySensor, DeviceRole.VoltageSensor, DeviceRole.CurrentSensor, DeviceRole.AirQualitySensor, DeviceRole.BatterySensor, DeviceRole.NumericSensor, DeviceRole.EnumSensor, DeviceRole.DateTimeSensor, DeviceRole.GenericSensor, DeviceRole.NumericControl, DeviceRole.SelectControl, DeviceRole.TextControl, DeviceRole.DateTimeControl, DeviceRole.MobilePushNotifier, DeviceRole.MessagingNotifier, DeviceRole.EmailNotifier, DeviceRole.GenericNotifier, DeviceRole.IrTransmitter;
|
|
108208
109601
|
new Set(Object.values(DeviceType));
|
|
108209
109602
|
new Set(Object.values(DeviceRole));
|
|
@@ -108542,11 +109935,31 @@ Object.freeze({
|
|
|
108542
109935
|
form: "single",
|
|
108543
109936
|
optional: false
|
|
108544
109937
|
}],
|
|
109938
|
+
"control.first": [{
|
|
109939
|
+
name: "deviceId",
|
|
109940
|
+
form: "single",
|
|
109941
|
+
optional: false
|
|
109942
|
+
}],
|
|
108545
109943
|
"control.getStatus": [{
|
|
108546
109944
|
name: "deviceId",
|
|
108547
109945
|
form: "single",
|
|
108548
109946
|
optional: false
|
|
108549
109947
|
}],
|
|
109948
|
+
"control.last": [{
|
|
109949
|
+
name: "deviceId",
|
|
109950
|
+
form: "single",
|
|
109951
|
+
optional: false
|
|
109952
|
+
}],
|
|
109953
|
+
"control.next": [{
|
|
109954
|
+
name: "deviceId",
|
|
109955
|
+
form: "single",
|
|
109956
|
+
optional: false
|
|
109957
|
+
}],
|
|
109958
|
+
"control.previous": [{
|
|
109959
|
+
name: "deviceId",
|
|
109960
|
+
form: "single",
|
|
109961
|
+
optional: false
|
|
109962
|
+
}],
|
|
108550
109963
|
"control.setValue": [{
|
|
108551
109964
|
name: "deviceId",
|
|
108552
109965
|
form: "single",
|
|
@@ -109171,6 +110584,11 @@ Object.freeze({
|
|
|
109171
110584
|
form: "single",
|
|
109172
110585
|
optional: false
|
|
109173
110586
|
}],
|
|
110587
|
+
"error.getStatus": [{
|
|
110588
|
+
name: "deviceId",
|
|
110589
|
+
form: "single",
|
|
110590
|
+
optional: false
|
|
110591
|
+
}],
|
|
109174
110592
|
"eventEmitter.getStatus": [{
|
|
109175
110593
|
name: "deviceId",
|
|
109176
110594
|
form: "single",
|
|
@@ -111212,6 +112630,11 @@ Object.freeze({
|
|
|
111212
112630
|
form: "single",
|
|
111213
112631
|
optional: false
|
|
111214
112632
|
}],
|
|
112633
|
+
"weatherStation.getStatus": [{
|
|
112634
|
+
name: "deviceId",
|
|
112635
|
+
form: "single",
|
|
112636
|
+
optional: false
|
|
112637
|
+
}],
|
|
111215
112638
|
"webrtcSession.addIceCandidate": [{
|
|
111216
112639
|
name: "deviceId",
|
|
111217
112640
|
form: "single",
|
|
@@ -111448,6 +112871,8 @@ new Map(Object.entries({
|
|
|
111448
112871
|
"storage-location-low": "system",
|
|
111449
112872
|
"storage-location-critical": "system",
|
|
111450
112873
|
"storage-location-ok": "system",
|
|
112874
|
+
"storage-drain-progress": "system",
|
|
112875
|
+
"storage-drain-complete": "system",
|
|
111451
112876
|
"alarm-triggered": "alarm",
|
|
111452
112877
|
"alarm-armed": "alarm",
|
|
111453
112878
|
"alarm-disarmed": "alarm",
|
|
@@ -111583,6 +113008,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
|
|
|
111583
113008
|
"storage-location-ok"
|
|
111584
113009
|
]
|
|
111585
113010
|
},
|
|
113011
|
+
{
|
|
113012
|
+
id: "storage-drain",
|
|
113013
|
+
family: "system",
|
|
113014
|
+
label: "Storage drain progress",
|
|
113015
|
+
kinds: ["storage-drain-progress", "storage-drain-complete"]
|
|
113016
|
+
},
|
|
111586
113017
|
{
|
|
111587
113018
|
id: "alerts",
|
|
111588
113019
|
family: "system",
|
|
@@ -111777,6 +113208,7 @@ var ALERT_EPISODE = [
|
|
|
111777
113208
|
"alert-error",
|
|
111778
113209
|
"alert-critical-resolved"
|
|
111779
113210
|
];
|
|
113211
|
+
var STORAGE_DRAIN = ["storage-drain-progress", "storage-drain-complete"];
|
|
111780
113212
|
var DEVICE_ATTENTION = ["device-attention-required", "device-attention-resolved"];
|
|
111781
113213
|
var UPDATES = [
|
|
111782
113214
|
"addon-update-available",
|
|
@@ -111988,6 +113420,7 @@ var STATE_SUMMARY_VARS = [
|
|
|
111988
113420
|
[...RULE_TEXT],
|
|
111989
113421
|
[...RULE_TEXT],
|
|
111990
113422
|
[...RULE_TEXT],
|
|
113423
|
+
[...RULE_TEXT],
|
|
111991
113424
|
[...RULE_BODY_ONLY],
|
|
111992
113425
|
[...RULE_TEXT],
|
|
111993
113426
|
([...RULE_TEXT], [...DEVICE_EVENTS]),
|
|
@@ -112000,8 +113433,16 @@ var STATE_SUMMARY_VARS = [
|
|
|
112000
113433
|
([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
|
|
112001
113434
|
([...RULE_TEXT], [...CONSUMABLE]),
|
|
112002
113435
|
[...RULE_TEXT],
|
|
112003
|
-
([...RULE_TEXT], [
|
|
112004
|
-
|
|
113436
|
+
([...RULE_TEXT], [
|
|
113437
|
+
...UPDATES,
|
|
113438
|
+
...STORAGE_DRAIN,
|
|
113439
|
+
...ALERT_EPISODE
|
|
113440
|
+
]),
|
|
113441
|
+
([...RULE_TEXT], [
|
|
113442
|
+
...UPDATES,
|
|
113443
|
+
...STORAGE_DRAIN,
|
|
113444
|
+
...ALERT_EPISODE
|
|
113445
|
+
]),
|
|
112005
113446
|
[...RULE_TEXT],
|
|
112006
113447
|
[...RULE_TEXT],
|
|
112007
113448
|
[...RULE_TEXT],
|
|
@@ -112015,6 +113456,9 @@ var STATE_SUMMARY_VARS = [
|
|
|
112015
113456
|
[...RULE_TEXT],
|
|
112016
113457
|
[...RULE_TEXT],
|
|
112017
113458
|
[...RULE_TEXT],
|
|
113459
|
+
([...RULE_TEXT], [...STORAGE_DRAIN]),
|
|
113460
|
+
([...RULE_TEXT], [...STORAGE_DRAIN]),
|
|
113461
|
+
[...RULE_TEXT],
|
|
112018
113462
|
[...RULE_TEXT],
|
|
112019
113463
|
[...RULE_TEXT],
|
|
112020
113464
|
[...RULE_TEXT],
|
|
@@ -113790,6 +115234,17 @@ function present(part) {
|
|
|
113790
115234
|
return Object.values(part).some((v) => v !== null) ? part : null;
|
|
113791
115235
|
}
|
|
113792
115236
|
/**
|
|
115237
|
+
* A house reading without the heat pump, from Enpal's total that includes it. Both known:
|
|
115238
|
+
* the difference, floored at 0. No pump in the system: the total as reported. A pump that
|
|
115239
|
+
* exists but whose reading is unknown makes the result unknown, never the inflated total.
|
|
115240
|
+
*/
|
|
115241
|
+
function withoutPump(total, pump, hasPump) {
|
|
115242
|
+
if (total === null) return null;
|
|
115243
|
+
if (!hasPump) return total;
|
|
115244
|
+
if (pump === null) return null;
|
|
115245
|
+
return Math.max(0, total - pump);
|
|
115246
|
+
}
|
|
115247
|
+
/**
|
|
113793
115248
|
* The grid power, + import / − export, from the two halves the catalog splits it into.
|
|
113794
115249
|
* With both halves known it is their difference. With one half only, it is that half
|
|
113795
115250
|
* while it flows: a zero import with no export reading cannot say whether the house
|
|
@@ -113819,16 +115274,17 @@ function computeEnergySystemStatus(snapshot, options, now) {
|
|
|
113819
115274
|
importTodayKwh: read.numeric("grid-import-day"),
|
|
113820
115275
|
exportTodayKwh: read.numeric("grid-export-day")
|
|
113821
115276
|
};
|
|
113822
|
-
const house = {
|
|
113823
|
-
powerW: read.power("house"),
|
|
113824
|
-
energyKwh: read.energy("house"),
|
|
113825
|
-
todayKwh: read.numeric("house-energy-day")
|
|
113826
|
-
};
|
|
113827
115277
|
const heatPump = {
|
|
113828
115278
|
powerW: read.power("heatpump"),
|
|
113829
115279
|
energyKwh: read.energy("heatpump"),
|
|
113830
115280
|
todayKwh: null
|
|
113831
115281
|
};
|
|
115282
|
+
const hasPump = present(heatPump) !== null;
|
|
115283
|
+
const house = {
|
|
115284
|
+
powerW: withoutPump(read.power("house"), heatPump.powerW, hasPump),
|
|
115285
|
+
energyKwh: withoutPump(read.energy("house"), heatPump.energyKwh, hasPump),
|
|
115286
|
+
todayKwh: hasPump ? null : read.numeric("house-energy-day")
|
|
115287
|
+
};
|
|
113832
115288
|
const storage = {
|
|
113833
115289
|
stateOfChargePct: read.numeric("battery"),
|
|
113834
115290
|
storedKwh: read.numeric("battery-stored-energy"),
|