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