@camstack/addon-provider-rademacher 0.2.147 → 0.2.148
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 +10 -1
- package/README.md +24 -8
- package/dist/addon.js +680 -45
- package/dist/addon.mjs +680 -45
- package/package.json +1 -1
package/dist/addon.mjs
CHANGED
|
@@ -6426,7 +6426,7 @@ var ZodIssueCode = {
|
|
|
6426
6426
|
var ZodFirstPartyTypeKind;
|
|
6427
6427
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
6428
6428
|
//#endregion
|
|
6429
|
-
//#region ../types/dist/sleep
|
|
6429
|
+
//#region ../types/dist/sleep--jXS9hWo.mjs
|
|
6430
6430
|
/**
|
|
6431
6431
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
6432
6432
|
* window to float samples (D455).
|
|
@@ -9619,6 +9619,7 @@ var CAP_NAMES = Object.freeze([
|
|
|
9619
9619
|
"filesystem-browse",
|
|
9620
9620
|
"flood",
|
|
9621
9621
|
"gas",
|
|
9622
|
+
"group-active",
|
|
9622
9623
|
"group-commands",
|
|
9623
9624
|
"group-status",
|
|
9624
9625
|
"heating-valve",
|
|
@@ -9641,6 +9642,7 @@ var CAP_NAMES = Object.freeze([
|
|
|
9641
9642
|
"login-method",
|
|
9642
9643
|
"media-player",
|
|
9643
9644
|
"mesh-network",
|
|
9645
|
+
"meter",
|
|
9644
9646
|
"metrics-provider",
|
|
9645
9647
|
"model-convert",
|
|
9646
9648
|
"model-distributor",
|
|
@@ -10439,6 +10441,10 @@ Object.freeze({
|
|
|
10439
10441
|
"path": "detected",
|
|
10440
10442
|
"valueType": "boolean"
|
|
10441
10443
|
}],
|
|
10444
|
+
"group-active": [{
|
|
10445
|
+
"path": "active",
|
|
10446
|
+
"valueType": "boolean"
|
|
10447
|
+
}],
|
|
10442
10448
|
"group-status": [
|
|
10443
10449
|
{
|
|
10444
10450
|
"path": "included",
|
|
@@ -10698,6 +10704,10 @@ Object.freeze({
|
|
|
10698
10704
|
]
|
|
10699
10705
|
}
|
|
10700
10706
|
],
|
|
10707
|
+
"meter": [{
|
|
10708
|
+
"path": "value",
|
|
10709
|
+
"valueType": "number"
|
|
10710
|
+
}],
|
|
10701
10711
|
"motion": [
|
|
10702
10712
|
{
|
|
10703
10713
|
"path": "detected",
|
|
@@ -11441,7 +11451,7 @@ object({
|
|
|
11441
11451
|
params: record(string(), union([string(), number()])).optional()
|
|
11442
11452
|
});
|
|
11443
11453
|
//#endregion
|
|
11444
|
-
//#region ../types/dist/err-msg-
|
|
11454
|
+
//#region ../types/dist/err-msg-DIorGYeC.mjs
|
|
11445
11455
|
var DeviceType = /* @__PURE__ */ function(DeviceType) {
|
|
11446
11456
|
DeviceType["Camera"] = "camera";
|
|
11447
11457
|
DeviceType["Hub"] = "hub";
|
|
@@ -11535,8 +11545,14 @@ var DeviceType = /* @__PURE__ */ function(DeviceType) {
|
|
|
11535
11545
|
DeviceType["PetFeeder"] = "pet-feeder";
|
|
11536
11546
|
/** Built-in dishwasher — program lifecycle, door / remote-start gates,
|
|
11537
11547
|
* salt and rinse-aid levels. Installed with the `dishwasher` cap.
|
|
11538
|
-
* Sources: native Bosch Home Connect, reusable by similar integrations.
|
|
11548
|
+
* Sources: native Bosch Home Connect, reusable by similar integrations.
|
|
11549
|
+
* A plug-built dishwasher carries running-state and power instead. */
|
|
11539
11550
|
DeviceType["Dishwasher"] = "dishwasher";
|
|
11551
|
+
/** Washing machine. A plug-built one is running while its power stays
|
|
11552
|
+
* above a threshold. No program cap — that surface is the dishwasher's. */
|
|
11553
|
+
DeviceType["Washer"] = "washer";
|
|
11554
|
+
/** Tumble dryer. Same plug-built running surface as {@link Washer}. */
|
|
11555
|
+
DeviceType["Dryer"] = "dryer";
|
|
11540
11556
|
return DeviceType;
|
|
11541
11557
|
}({});
|
|
11542
11558
|
var DeviceFeature = /* @__PURE__ */ function(DeviceFeature) {
|
|
@@ -11794,7 +11810,7 @@ function errMsg(err) {
|
|
|
11794
11810
|
return String(err);
|
|
11795
11811
|
}
|
|
11796
11812
|
//#endregion
|
|
11797
|
-
//#region ../types/dist/composition-
|
|
11813
|
+
//#region ../types/dist/composition-Bb8iwHEJ.mjs
|
|
11798
11814
|
/**
|
|
11799
11815
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
11800
11816
|
*
|
|
@@ -12109,6 +12125,13 @@ var table = {
|
|
|
12109
12125
|
apply: () => {
|
|
12110
12126
|
throw new ExpressionEvalError("latchedAt: stateful evaluation context is required");
|
|
12111
12127
|
}
|
|
12128
|
+
},
|
|
12129
|
+
schmitt: {
|
|
12130
|
+
minArgs: 3,
|
|
12131
|
+
maxArgs: 5,
|
|
12132
|
+
apply: () => {
|
|
12133
|
+
throw new ExpressionEvalError("schmitt: stateful evaluation context is required");
|
|
12134
|
+
}
|
|
12112
12135
|
}
|
|
12113
12136
|
};
|
|
12114
12137
|
Object.freeze(Object.assign(Object.create(null), table));
|
|
@@ -12550,6 +12573,99 @@ function validateExpressionSource(src) {
|
|
|
12550
12573
|
return null;
|
|
12551
12574
|
}
|
|
12552
12575
|
/**
|
|
12576
|
+
* One power reading becomes a washer, dryer or dishwasher (D944 helper).
|
|
12577
|
+
*
|
|
12578
|
+
* Standby of the control board is under 5 W; a motor or a heater is far
|
|
12579
|
+
* above that, so 5 W is the line. A door lock or a short pump spike is not
|
|
12580
|
+
* a cycle, so running starts only after 30 s above the line.
|
|
12581
|
+
*
|
|
12582
|
+
* A wash, dry or dishwasher pause (soak, heat-wait, heater off between
|
|
12583
|
+
* bursts) lasts several minutes. Ending the cycle on the first dip would
|
|
12584
|
+
* report "finished" in the middle of the program, so the stop dwell is
|
|
12585
|
+
* 10 minutes on every type. The number is stored per type so one machine
|
|
12586
|
+
* can move later without moving the others.
|
|
12587
|
+
*/
|
|
12588
|
+
var APPLIANCE_TEMPLATE_ID = "appliance";
|
|
12589
|
+
var APPLIANCE_KINDS = [
|
|
12590
|
+
"washer",
|
|
12591
|
+
"dryer",
|
|
12592
|
+
"dishwasher"
|
|
12593
|
+
];
|
|
12594
|
+
DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher;
|
|
12595
|
+
/**
|
|
12596
|
+
* Statistics and integrals over a history read (D944).
|
|
12597
|
+
*
|
|
12598
|
+
* Pure: the same points always give the same answer, so a restart recomputes
|
|
12599
|
+
* rather than trusting a buffer. A gauge mean is time-weighted (value × ms),
|
|
12600
|
+
* never the mean of the samples. A hole with no held value is not integrated
|
|
12601
|
+
* as zero. A truncated read is not published.
|
|
12602
|
+
*/
|
|
12603
|
+
var STATISTIC_STATS = [
|
|
12604
|
+
"min",
|
|
12605
|
+
"max",
|
|
12606
|
+
"mean",
|
|
12607
|
+
"sum",
|
|
12608
|
+
"count",
|
|
12609
|
+
"change"
|
|
12610
|
+
];
|
|
12611
|
+
/**
|
|
12612
|
+
* The range a statistics or integral helper asks history for (D944).
|
|
12613
|
+
*
|
|
12614
|
+
* Calendar edges are the hub's timezone, never UTC midnight: a day is 23, 24
|
|
12615
|
+
* or 25 hours across a DST change. A tier is eligible only when its retention
|
|
12616
|
+
* is strictly longer than the longest that range can be. Forever qualifies.
|
|
12617
|
+
* Equal to a tier's retention is a refusal, not a short answer.
|
|
12618
|
+
*/
|
|
12619
|
+
var MINUTE_MS = 6e4;
|
|
12620
|
+
var HOUR_MS = 60 * MINUTE_MS;
|
|
12621
|
+
var DAY_MS = 24 * HOUR_MS;
|
|
12622
|
+
var ROLLING_SPANS = [
|
|
12623
|
+
"1h",
|
|
12624
|
+
"24h",
|
|
12625
|
+
"2d",
|
|
12626
|
+
"7d",
|
|
12627
|
+
"30d",
|
|
12628
|
+
"custom"
|
|
12629
|
+
];
|
|
12630
|
+
var CALENDAR_PERIODS = [
|
|
12631
|
+
"today",
|
|
12632
|
+
"yesterday",
|
|
12633
|
+
"this-week",
|
|
12634
|
+
"this-month"
|
|
12635
|
+
];
|
|
12636
|
+
var RESET_PERIODS = [
|
|
12637
|
+
"never",
|
|
12638
|
+
"daily",
|
|
12639
|
+
"weekly",
|
|
12640
|
+
"monthly"
|
|
12641
|
+
];
|
|
12642
|
+
5 * MINUTE_MS;
|
|
12643
|
+
24 * HOUR_MS, 2 * DAY_MS, 7 * DAY_MS, 30 * DAY_MS;
|
|
12644
|
+
7 * DAY_MS, 30 * DAY_MS, 365 * DAY_MS;
|
|
12645
|
+
var rollingWindowObject = object({
|
|
12646
|
+
kind: literal("rolling"),
|
|
12647
|
+
span: _enum(ROLLING_SPANS),
|
|
12648
|
+
customMinutes: number().int().min(5).optional()
|
|
12649
|
+
}).check((payload) => {
|
|
12650
|
+
if (payload.value.span === "custom" && payload.value.customMinutes === void 0) payload.issues.push({
|
|
12651
|
+
code: "custom",
|
|
12652
|
+
message: "a custom range needs a duration in minutes",
|
|
12653
|
+
path: ["customMinutes"],
|
|
12654
|
+
input: payload.value
|
|
12655
|
+
});
|
|
12656
|
+
if (payload.value.span !== "custom" && payload.value.customMinutes !== void 0) payload.issues.push({
|
|
12657
|
+
code: "custom",
|
|
12658
|
+
message: "only a custom range carries a duration",
|
|
12659
|
+
path: ["customMinutes"],
|
|
12660
|
+
input: payload.value
|
|
12661
|
+
});
|
|
12662
|
+
});
|
|
12663
|
+
var RollingWindowSchema = rollingWindowObject;
|
|
12664
|
+
var StatisticWindowSchema = discriminatedUnion("kind", [rollingWindowObject, object({
|
|
12665
|
+
kind: literal("calendar"),
|
|
12666
|
+
period: _enum(CALENDAR_PERIODS)
|
|
12667
|
+
})]);
|
|
12668
|
+
/**
|
|
12553
12669
|
* A composition source identity: `(addonId, stableId)`, never a numeric device
|
|
12554
12670
|
* id. Split out so helper schemas can name it without a cycle through
|
|
12555
12671
|
* `composition.ts` (D659).
|
|
@@ -12575,7 +12691,13 @@ var GROUP_TEMPLATE_IDS = [
|
|
|
12575
12691
|
"occupancy",
|
|
12576
12692
|
"binary",
|
|
12577
12693
|
"switch",
|
|
12578
|
-
"light"
|
|
12694
|
+
"light",
|
|
12695
|
+
"fan",
|
|
12696
|
+
"cover",
|
|
12697
|
+
"valve",
|
|
12698
|
+
"lock",
|
|
12699
|
+
"media-player",
|
|
12700
|
+
"climate"
|
|
12579
12701
|
];
|
|
12580
12702
|
var NUMERIC_AGGREGATES = [
|
|
12581
12703
|
"mean",
|
|
@@ -12605,14 +12727,73 @@ var HelperMemberSchema = object({
|
|
|
12605
12727
|
cap: string().min(1),
|
|
12606
12728
|
fieldPath: string().min(1)
|
|
12607
12729
|
});
|
|
12608
|
-
var HelperSpecSchema = discriminatedUnion("kind", [
|
|
12609
|
-
|
|
12610
|
-
|
|
12611
|
-
|
|
12612
|
-
|
|
12613
|
-
|
|
12614
|
-
|
|
12615
|
-
|
|
12730
|
+
var HelperSpecSchema = discriminatedUnion("kind", [
|
|
12731
|
+
object({
|
|
12732
|
+
kind: literal("group"),
|
|
12733
|
+
templateId: GroupTemplateIdSchema,
|
|
12734
|
+
aggregate: AggregateReducerSchema,
|
|
12735
|
+
members: array(HelperMemberSchema).min(1).max(64),
|
|
12736
|
+
/** Actuator groups only. Readings leave this unset. */
|
|
12737
|
+
active: ActiveCriterionSchema.optional()
|
|
12738
|
+
}),
|
|
12739
|
+
object({
|
|
12740
|
+
kind: literal("appliance"),
|
|
12741
|
+
templateId: literal(APPLIANCE_TEMPLATE_ID),
|
|
12742
|
+
appliance: _enum(APPLIANCE_KINDS),
|
|
12743
|
+
thresholdWatts: number().positive(),
|
|
12744
|
+
startDwellMs: number().int().nonnegative(),
|
|
12745
|
+
stopDwellMs: number().int().nonnegative(),
|
|
12746
|
+
member: HelperMemberSchema
|
|
12747
|
+
}),
|
|
12748
|
+
object({
|
|
12749
|
+
kind: literal("statistic"),
|
|
12750
|
+
stat: _enum(STATISTIC_STATS),
|
|
12751
|
+
window: StatisticWindowSchema,
|
|
12752
|
+
source: HelperMemberSchema
|
|
12753
|
+
}),
|
|
12754
|
+
object({
|
|
12755
|
+
kind: literal("integral"),
|
|
12756
|
+
reset: _enum(RESET_PERIODS),
|
|
12757
|
+
output: _enum(["energy", "meter"]),
|
|
12758
|
+
source: HelperMemberSchema
|
|
12759
|
+
}),
|
|
12760
|
+
object({
|
|
12761
|
+
kind: literal("threshold"),
|
|
12762
|
+
source: HelperMemberSchema,
|
|
12763
|
+
high: number(),
|
|
12764
|
+
low: number(),
|
|
12765
|
+
onForMs: number().int().nonnegative(),
|
|
12766
|
+
offForMs: number().int().nonnegative()
|
|
12767
|
+
}),
|
|
12768
|
+
object({
|
|
12769
|
+
kind: literal("arithmetic"),
|
|
12770
|
+
op: _enum([
|
|
12771
|
+
"sum",
|
|
12772
|
+
"difference",
|
|
12773
|
+
"ratio"
|
|
12774
|
+
]),
|
|
12775
|
+
inputs: array(HelperMemberSchema).min(2).max(64)
|
|
12776
|
+
}),
|
|
12777
|
+
object({
|
|
12778
|
+
kind: literal("expression"),
|
|
12779
|
+
expr: string().min(1),
|
|
12780
|
+
inputs: array(object({
|
|
12781
|
+
name: string().min(1),
|
|
12782
|
+
member: HelperMemberSchema
|
|
12783
|
+
})).min(1).max(64),
|
|
12784
|
+
output: _enum(["number", "boolean"])
|
|
12785
|
+
}),
|
|
12786
|
+
object({
|
|
12787
|
+
kind: literal("derivative"),
|
|
12788
|
+
window: RollingWindowSchema,
|
|
12789
|
+
per: _enum([
|
|
12790
|
+
"second",
|
|
12791
|
+
"minute",
|
|
12792
|
+
"hour"
|
|
12793
|
+
]),
|
|
12794
|
+
source: HelperMemberSchema
|
|
12795
|
+
})
|
|
12796
|
+
]);
|
|
12616
12797
|
/** A composed device's stableId is this prefix plus the block id. */
|
|
12617
12798
|
var COMPOSED_DEVICE_STABLE_ID_PREFIX = "composed-";
|
|
12618
12799
|
/** Longest snippet a `code` source may carry (slice 4). */
|
|
@@ -12673,6 +12854,12 @@ var CompositionFieldSourceSchema = discriminatedUnion("kind", [
|
|
|
12673
12854
|
"all"
|
|
12674
12855
|
]),
|
|
12675
12856
|
reads: array(CompositionFieldReadSchema).min(1).max(64),
|
|
12857
|
+
/**
|
|
12858
|
+
* Set when the reads are an enum state, not a yes/no: the listed states
|
|
12859
|
+
* count as active (a cover is `open`). A state outside the list is inactive;
|
|
12860
|
+
* a read that is not a state at all is left out. Only `any` / `all` use it.
|
|
12861
|
+
*/
|
|
12862
|
+
activeWhen: array(string().min(1)).min(1).optional(),
|
|
12676
12863
|
/** `value` is the reading; the others are the member counts. */
|
|
12677
12864
|
publish: _enum([
|
|
12678
12865
|
"value",
|
|
@@ -12686,6 +12873,26 @@ var CompositionFieldSourceSchema = discriminatedUnion("kind", [
|
|
|
12686
12873
|
"omit",
|
|
12687
12874
|
"offline"
|
|
12688
12875
|
])
|
|
12876
|
+
}),
|
|
12877
|
+
object({
|
|
12878
|
+
kind: literal("series"),
|
|
12879
|
+
read: CompositionFieldReadSchema,
|
|
12880
|
+
/** `value` is the statistic or the integral. The others are the gap counts. */
|
|
12881
|
+
publish: _enum([
|
|
12882
|
+
"value",
|
|
12883
|
+
"included",
|
|
12884
|
+
"excluded",
|
|
12885
|
+
"total"
|
|
12886
|
+
]),
|
|
12887
|
+
/**
|
|
12888
|
+
* What an unanswered `value` does. Counts ignore this. `offline` leaves the
|
|
12889
|
+
* device unseeded until history answers, so a restart cannot publish 0.
|
|
12890
|
+
*/
|
|
12891
|
+
empty: _enum([
|
|
12892
|
+
"null",
|
|
12893
|
+
"omit",
|
|
12894
|
+
"offline"
|
|
12895
|
+
])
|
|
12689
12896
|
})
|
|
12690
12897
|
]);
|
|
12691
12898
|
var CompositionCommandTargetSchema = discriminatedUnion("kind", [object({
|
|
@@ -17845,7 +18052,22 @@ var BrokerProviderInfoSchema = object({
|
|
|
17845
18052
|
*/
|
|
17846
18053
|
interactiveConnectPath: string().min(1).optional(),
|
|
17847
18054
|
/** Relative hub path to disconnect the linked account (same popup pattern). */
|
|
17848
|
-
interactiveDisconnectPath: string().min(1).optional()
|
|
18055
|
+
interactiveDisconnectPath: string().min(1).optional(),
|
|
18056
|
+
/**
|
|
18057
|
+
* The kind signs in through a server-held interactive session instead of
|
|
18058
|
+
* (or before) typed credentials. `basePath` is a hub-relative route set
|
|
18059
|
+
* served by the owning addon (`/addon/<id>/...`) speaking the sign-in
|
|
18060
|
+
* contract: `POST {basePath}/start` (body: the form's settings) answers
|
|
18061
|
+
* `{ sessionId, loginUrl }`; `GET {basePath}/status?sessionId=` answers
|
|
18062
|
+
* `{ phase: 'starting' | 'awaiting-login' | 'captured' | 'error' |
|
|
18063
|
+
* 'cancelled', loginUrl, error }`; `POST {basePath}/commit`
|
|
18064
|
+
* (`{ sessionId, name, brokerId? }`) stores the credentials on a new or
|
|
18065
|
+
* existing broker and answers `{ brokerId }`; `POST {basePath}/cancel`
|
|
18066
|
+
* (`{ sessionId }`) drops the session. The dialog that edits a broker
|
|
18067
|
+
* offers it as the default path; the fields the session fills are
|
|
18068
|
+
* marked `filledBySignIn` in the kind's settings schema.
|
|
18069
|
+
*/
|
|
18070
|
+
signIn: object({ basePath: string().min(1) }).optional()
|
|
17849
18071
|
}))
|
|
17850
18072
|
});
|
|
17851
18073
|
var ListInputSchema = object({
|
|
@@ -18950,7 +19172,8 @@ var CompositionProblemSchema = object({
|
|
|
18950
19172
|
"native-capability-replace",
|
|
18951
19173
|
"mixed-quantity",
|
|
18952
19174
|
"helper-mismatch",
|
|
18953
|
-
"member-constraint"
|
|
19175
|
+
"member-constraint",
|
|
19176
|
+
"retention"
|
|
18954
19177
|
]),
|
|
18955
19178
|
path: string(),
|
|
18956
19179
|
message: string()
|
|
@@ -19184,13 +19407,17 @@ Object.freeze({
|
|
|
19184
19407
|
latchedAt: {
|
|
19185
19408
|
kind: "fixed",
|
|
19186
19409
|
result: ["number", "null"]
|
|
19410
|
+
},
|
|
19411
|
+
schmitt: {
|
|
19412
|
+
kind: "fixed",
|
|
19413
|
+
result: ["boolean", "null"]
|
|
19187
19414
|
}
|
|
19188
19415
|
});
|
|
19189
19416
|
/**
|
|
19190
19417
|
* One catalog row per base reading a group helper can build (D944 §3).
|
|
19191
19418
|
* Data, not a form default written into the block.
|
|
19192
19419
|
*/
|
|
19193
|
-
var NOW = {
|
|
19420
|
+
var NOW$2 = {
|
|
19194
19421
|
fieldPath: "lastFetchedAt",
|
|
19195
19422
|
expr: "now"
|
|
19196
19423
|
};
|
|
@@ -19204,6 +19431,8 @@ function numeric(input) {
|
|
|
19204
19431
|
family: "numeric",
|
|
19205
19432
|
deviceType: DeviceType.Sensor,
|
|
19206
19433
|
memberDeviceType: DeviceType.Sensor,
|
|
19434
|
+
memberDeviceTypes: [DeviceType.Sensor],
|
|
19435
|
+
activeWhen: void 0,
|
|
19207
19436
|
commandCaps: [],
|
|
19208
19437
|
baseUnit: baseUnitOf(input.quantity),
|
|
19209
19438
|
aggregates: NUMERIC_AGGREGATES,
|
|
@@ -19219,6 +19448,8 @@ function binary(input) {
|
|
|
19219
19448
|
family: "binary",
|
|
19220
19449
|
deviceType: DeviceType.Sensor,
|
|
19221
19450
|
memberDeviceType: DeviceType.Sensor,
|
|
19451
|
+
memberDeviceTypes: [DeviceType.Sensor],
|
|
19452
|
+
activeWhen: void 0,
|
|
19222
19453
|
commandCaps: [],
|
|
19223
19454
|
quantity: "none",
|
|
19224
19455
|
baseUnit: void 0,
|
|
@@ -19236,7 +19467,7 @@ var GROUP_TEMPLATES = [
|
|
|
19236
19467
|
quantity: "temperature",
|
|
19237
19468
|
defaultAggregate: "mean",
|
|
19238
19469
|
empty: "null",
|
|
19239
|
-
companions: [NOW]
|
|
19470
|
+
companions: [NOW$2]
|
|
19240
19471
|
}),
|
|
19241
19472
|
numeric({
|
|
19242
19473
|
id: "humidity",
|
|
@@ -19247,7 +19478,7 @@ var GROUP_TEMPLATES = [
|
|
|
19247
19478
|
quantity: "humidity",
|
|
19248
19479
|
defaultAggregate: "mean",
|
|
19249
19480
|
empty: "null",
|
|
19250
|
-
companions: [NOW]
|
|
19481
|
+
companions: [NOW$2]
|
|
19251
19482
|
}),
|
|
19252
19483
|
numeric({
|
|
19253
19484
|
id: "pressure",
|
|
@@ -19258,7 +19489,7 @@ var GROUP_TEMPLATES = [
|
|
|
19258
19489
|
quantity: "pressure",
|
|
19259
19490
|
defaultAggregate: "mean",
|
|
19260
19491
|
empty: "null",
|
|
19261
|
-
companions: [NOW]
|
|
19492
|
+
companions: [NOW$2]
|
|
19262
19493
|
}),
|
|
19263
19494
|
numeric({
|
|
19264
19495
|
id: "illuminance",
|
|
@@ -19269,7 +19500,7 @@ var GROUP_TEMPLATES = [
|
|
|
19269
19500
|
quantity: "illuminance",
|
|
19270
19501
|
defaultAggregate: "mean",
|
|
19271
19502
|
empty: "null",
|
|
19272
|
-
companions: [NOW]
|
|
19503
|
+
companions: [NOW$2]
|
|
19273
19504
|
}),
|
|
19274
19505
|
numeric({
|
|
19275
19506
|
id: "power",
|
|
@@ -19280,7 +19511,7 @@ var GROUP_TEMPLATES = [
|
|
|
19280
19511
|
quantity: "power",
|
|
19281
19512
|
defaultAggregate: "sum",
|
|
19282
19513
|
empty: "omit",
|
|
19283
|
-
companions: [NOW]
|
|
19514
|
+
companions: [NOW$2]
|
|
19284
19515
|
}),
|
|
19285
19516
|
numeric({
|
|
19286
19517
|
id: "energy",
|
|
@@ -19291,7 +19522,7 @@ var GROUP_TEMPLATES = [
|
|
|
19291
19522
|
quantity: "energy",
|
|
19292
19523
|
defaultAggregate: "sum",
|
|
19293
19524
|
empty: "omit",
|
|
19294
|
-
companions: [NOW]
|
|
19525
|
+
companions: [NOW$2]
|
|
19295
19526
|
}),
|
|
19296
19527
|
numeric({
|
|
19297
19528
|
id: "battery",
|
|
@@ -19326,7 +19557,7 @@ var GROUP_TEMPLATES = [
|
|
|
19326
19557
|
quantity: "device",
|
|
19327
19558
|
defaultAggregate: "mean",
|
|
19328
19559
|
empty: "null",
|
|
19329
|
-
companions: [NOW]
|
|
19560
|
+
companions: [NOW$2]
|
|
19330
19561
|
}),
|
|
19331
19562
|
binary({
|
|
19332
19563
|
id: "motion",
|
|
@@ -19420,6 +19651,11 @@ var GROUP_TEMPLATES = [
|
|
|
19420
19651
|
summary: "On when at least one switch is on, or when all of them are. Offline and unknown members are left out of that decision, never read as off, and still receive the command.",
|
|
19421
19652
|
deviceType: DeviceType.Switch,
|
|
19422
19653
|
outputCap: "switch",
|
|
19654
|
+
outputField: "on",
|
|
19655
|
+
member: {
|
|
19656
|
+
cap: "switch",
|
|
19657
|
+
fieldPath: "on"
|
|
19658
|
+
},
|
|
19423
19659
|
commandCaps: ["switch"]
|
|
19424
19660
|
}),
|
|
19425
19661
|
actuator({
|
|
@@ -19427,34 +19663,136 @@ var GROUP_TEMPLATES = [
|
|
|
19427
19663
|
summary: "On when at least one light is on, or when all of them are. Brightness and colour are offered only when every member has them. A command is not sent to a member that lacks it.",
|
|
19428
19664
|
deviceType: DeviceType.Light,
|
|
19429
19665
|
outputCap: "switch",
|
|
19666
|
+
outputField: "on",
|
|
19667
|
+
member: {
|
|
19668
|
+
cap: "switch",
|
|
19669
|
+
fieldPath: "on"
|
|
19670
|
+
},
|
|
19430
19671
|
commandCaps: [
|
|
19431
19672
|
"switch",
|
|
19432
19673
|
"brightness",
|
|
19433
19674
|
"color"
|
|
19434
19675
|
]
|
|
19676
|
+
}),
|
|
19677
|
+
actuator({
|
|
19678
|
+
id: "fan",
|
|
19679
|
+
summary: "On when at least one fan is on, or when all of them are. Speed, preset, direction and oscillation are offered only when every fan has them. A command is not sent to a fan that lacks it.",
|
|
19680
|
+
deviceType: DeviceType.Fan,
|
|
19681
|
+
outputCap: "switch",
|
|
19682
|
+
outputField: "on",
|
|
19683
|
+
member: {
|
|
19684
|
+
cap: "switch",
|
|
19685
|
+
fieldPath: "on"
|
|
19686
|
+
},
|
|
19687
|
+
commandCaps: ["switch", "fan-control"]
|
|
19688
|
+
}),
|
|
19689
|
+
actuator({
|
|
19690
|
+
id: "cover",
|
|
19691
|
+
summary: "Open when at least one cover is open or part-open, or only when all of them are. Position and tilt are offered only when every cover has them. A cover that reports nothing is left out, never read as closed.",
|
|
19692
|
+
deviceType: DeviceType.Cover,
|
|
19693
|
+
outputCap: "group-active",
|
|
19694
|
+
outputField: "active",
|
|
19695
|
+
member: {
|
|
19696
|
+
cap: "cover",
|
|
19697
|
+
fieldPath: "state"
|
|
19698
|
+
},
|
|
19699
|
+
activeWhen: [
|
|
19700
|
+
"open",
|
|
19701
|
+
"opening",
|
|
19702
|
+
"stopped"
|
|
19703
|
+
],
|
|
19704
|
+
commandCaps: ["cover"]
|
|
19705
|
+
}),
|
|
19706
|
+
actuator({
|
|
19707
|
+
id: "valve",
|
|
19708
|
+
summary: "Open when at least one valve is open or part-open, or only when all of them are. Position is offered only when every valve has it. A valve that reports nothing is left out, never read as closed.",
|
|
19709
|
+
deviceType: DeviceType.Valve,
|
|
19710
|
+
outputCap: "group-active",
|
|
19711
|
+
outputField: "active",
|
|
19712
|
+
member: {
|
|
19713
|
+
cap: "valve",
|
|
19714
|
+
fieldPath: "state"
|
|
19715
|
+
},
|
|
19716
|
+
activeWhen: [
|
|
19717
|
+
"open",
|
|
19718
|
+
"opening",
|
|
19719
|
+
"stopped"
|
|
19720
|
+
],
|
|
19721
|
+
commandCaps: ["valve"]
|
|
19722
|
+
}),
|
|
19723
|
+
actuator({
|
|
19724
|
+
id: "lock",
|
|
19725
|
+
summary: "Locked when at least one lock is locked, or only when all of them are. A jammed or moving lock is not locked. Locking is one tap; unlocking the group needs a confirmation every time, and nothing is sent without it.",
|
|
19726
|
+
deviceType: DeviceType.Lock,
|
|
19727
|
+
outputCap: "group-active",
|
|
19728
|
+
outputField: "active",
|
|
19729
|
+
member: {
|
|
19730
|
+
cap: "lock-control",
|
|
19731
|
+
fieldPath: "state"
|
|
19732
|
+
},
|
|
19733
|
+
activeWhen: ["locked"],
|
|
19734
|
+
commandCaps: ["lock-control"]
|
|
19735
|
+
}),
|
|
19736
|
+
actuator({
|
|
19737
|
+
id: "media-player",
|
|
19738
|
+
summary: "Playing when at least one player is playing, or only when all of them are. Volume is offered only when every player has it. A player that reports nothing is left out, never read as stopped.",
|
|
19739
|
+
deviceType: DeviceType.MediaPlayer,
|
|
19740
|
+
outputCap: "group-active",
|
|
19741
|
+
outputField: "active",
|
|
19742
|
+
member: {
|
|
19743
|
+
cap: "media-player",
|
|
19744
|
+
fieldPath: "state"
|
|
19745
|
+
},
|
|
19746
|
+
activeWhen: ["playing", "buffering"],
|
|
19747
|
+
commandCaps: ["media-player"]
|
|
19748
|
+
}),
|
|
19749
|
+
actuator({
|
|
19750
|
+
id: "climate",
|
|
19751
|
+
summary: "Running when at least one thermostat or air conditioner is not off, or only when all of them are. Target temperature and fan are offered only when every device has them. A device that reports nothing is left out, never read as off.",
|
|
19752
|
+
deviceType: DeviceType.Thermostat,
|
|
19753
|
+
memberDeviceTypes: [DeviceType.Thermostat, DeviceType.Climate],
|
|
19754
|
+
outputCap: "group-active",
|
|
19755
|
+
outputField: "active",
|
|
19756
|
+
member: {
|
|
19757
|
+
cap: "climate-control",
|
|
19758
|
+
fieldPath: "mode"
|
|
19759
|
+
},
|
|
19760
|
+
activeWhen: [
|
|
19761
|
+
"heat",
|
|
19762
|
+
"cool",
|
|
19763
|
+
"auto",
|
|
19764
|
+
"heat_cool",
|
|
19765
|
+
"fan_only",
|
|
19766
|
+
"dry"
|
|
19767
|
+
],
|
|
19768
|
+
commandCaps: ["climate-control"]
|
|
19435
19769
|
})
|
|
19436
19770
|
];
|
|
19437
19771
|
function actuator(input) {
|
|
19438
19772
|
return {
|
|
19439
|
-
|
|
19773
|
+
id: input.id,
|
|
19774
|
+
summary: input.summary,
|
|
19775
|
+
deviceType: input.deviceType,
|
|
19776
|
+
outputCap: input.outputCap,
|
|
19777
|
+
outputField: input.outputField,
|
|
19778
|
+
commandCaps: input.commandCaps,
|
|
19440
19779
|
family: "actuator",
|
|
19441
19780
|
role: void 0,
|
|
19442
19781
|
memberDeviceType: input.deviceType,
|
|
19443
|
-
|
|
19782
|
+
memberDeviceTypes: input.memberDeviceTypes ?? [input.deviceType],
|
|
19783
|
+
activeWhen: input.activeWhen,
|
|
19444
19784
|
quantity: "none",
|
|
19445
19785
|
baseUnit: void 0,
|
|
19446
19786
|
aggregates: BINARY_AGGREGATES,
|
|
19447
19787
|
defaultAggregate: "any",
|
|
19448
19788
|
empty: "offline",
|
|
19449
|
-
accept: [
|
|
19450
|
-
cap: "switch",
|
|
19451
|
-
fieldPath: "on"
|
|
19452
|
-
}],
|
|
19789
|
+
accept: [input.member],
|
|
19453
19790
|
companions: [CHANGED]
|
|
19454
19791
|
};
|
|
19455
19792
|
}
|
|
19456
19793
|
new Map(GROUP_TEMPLATES.map((template) => [template.id, template]));
|
|
19457
19794
|
DeviceFeature.LightColorRgb, DeviceFeature.LightColorHsv, DeviceFeature.LightColorMired;
|
|
19795
|
+
DeviceType.Camera;
|
|
19458
19796
|
`${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
|
|
19459
19797
|
/**
|
|
19460
19798
|
* What a composition may BUILD on a device type (G2, D676): the caps a new
|
|
@@ -44774,7 +45112,7 @@ var NetworkAccessStatusSchema = object({
|
|
|
44774
45112
|
});
|
|
44775
45113
|
/**
|
|
44776
45114
|
* Optional, richer endpoint shape returned by providers that expose
|
|
44777
|
-
* MORE than one ingress concurrently (Tailscale
|
|
45115
|
+
* MORE than one ingress concurrently (Tailscale Funnel with mixed
|
|
44778
45116
|
* serve+funnel rules, future ngrok multi-tunnel, …). Each entry carries
|
|
44779
45117
|
* the originating provider config (mode + sourcePort) so the
|
|
44780
45118
|
* orchestrator UI can label rows distinctly. Providers that expose only
|
|
@@ -47461,7 +47799,20 @@ var NcRuleInputSchema = object({
|
|
|
47461
47799
|
* save by the hub's grouping guard). `.optional()`, never `.default()`: the addon cap
|
|
47462
47800
|
* path does not run Zod defaults.
|
|
47463
47801
|
*/
|
|
47464
|
-
groupingSec: number().int().min(5).max(60).optional()
|
|
47802
|
+
groupingSec: number().int().min(5).max(60).optional(),
|
|
47803
|
+
/**
|
|
47804
|
+
* ASK ME TO CONFIRM DETECTIONS (#243): a DETECTION notification of this rule
|
|
47805
|
+
* carries "Correct" / "Wrong" buttons (and, where the channel has room, a
|
|
47806
|
+
* "Wrong, it is a <class>" choice). A tap marks the track for retraining, the
|
|
47807
|
+
* same mark the Library writes, and records whose notification it was and
|
|
47808
|
+
* when. A channel with no buttons gets the same two choices as links.
|
|
47809
|
+
*
|
|
47810
|
+
* `.optional()`, never `.default()` (a Zod default does not run on the addon
|
|
47811
|
+
* cap path): absent and `false` both mean off, which is what every rule
|
|
47812
|
+
* authored before this field meant. An editor turns it off by writing
|
|
47813
|
+
* `false`, so it needs no `clear` key.
|
|
47814
|
+
*/
|
|
47815
|
+
askVerdict: boolean().optional()
|
|
47465
47816
|
});
|
|
47466
47817
|
/**
|
|
47467
47818
|
* Partial patch for `updateRule` — any subset of the input fields, plus the
|
|
@@ -58181,7 +58532,8 @@ var BATTERY_DEVICE_TYPES = [
|
|
|
58181
58532
|
DeviceType.Switch,
|
|
58182
58533
|
DeviceType.PetFeeder,
|
|
58183
58534
|
DeviceType.Container,
|
|
58184
|
-
DeviceType.Thermostat
|
|
58535
|
+
DeviceType.Thermostat,
|
|
58536
|
+
DeviceType.EventEmitter
|
|
58185
58537
|
];
|
|
58186
58538
|
/** Generic Customize target for the percentage reading (D936). */
|
|
58187
58539
|
var batteryCustomize = {
|
|
@@ -61041,7 +61393,17 @@ var groupCommandsCapability = {
|
|
|
61041
61393
|
scope: "device",
|
|
61042
61394
|
deviceNative: true,
|
|
61043
61395
|
mode: "singleton",
|
|
61044
|
-
deviceTypes: [
|
|
61396
|
+
deviceTypes: [
|
|
61397
|
+
DeviceType.Switch,
|
|
61398
|
+
DeviceType.Light,
|
|
61399
|
+
DeviceType.Fan,
|
|
61400
|
+
DeviceType.Cover,
|
|
61401
|
+
DeviceType.Valve,
|
|
61402
|
+
DeviceType.Lock,
|
|
61403
|
+
DeviceType.MediaPlayer,
|
|
61404
|
+
DeviceType.Thermostat,
|
|
61405
|
+
DeviceType.Climate
|
|
61406
|
+
],
|
|
61045
61407
|
methods: {},
|
|
61046
61408
|
status: {
|
|
61047
61409
|
schema: GroupCommandsSchema,
|
|
@@ -61059,6 +61421,49 @@ var groupCommandsCapability = {
|
|
|
61059
61421
|
history: "none"
|
|
61060
61422
|
};
|
|
61061
61423
|
/**
|
|
61424
|
+
* Whether a helper actuator group counts as active (D944): at least one
|
|
61425
|
+
* included member is, or every included member is. What "active" means is the
|
|
61426
|
+
* type's: a cover is open, a lock is locked, a media player is playing, a
|
|
61427
|
+
* climate device is not off. A group of lights, switches and fans reports
|
|
61428
|
+
* `switch.on` instead; this cap is for the types whose own state is not a
|
|
61429
|
+
* yes/no. Unknown members are left out (`group-status` counts them) and an
|
|
61430
|
+
* empty included set takes the device offline, never `active: false`.
|
|
61431
|
+
*/
|
|
61432
|
+
var GroupActiveSchema = object({
|
|
61433
|
+
active: boolean().meta({ label: "Active" }),
|
|
61434
|
+
/** Ms epoch when the slice was last updated. */
|
|
61435
|
+
lastChangedAt: number()
|
|
61436
|
+
});
|
|
61437
|
+
var groupActiveCapability = {
|
|
61438
|
+
name: "group-active",
|
|
61439
|
+
scope: "device",
|
|
61440
|
+
deviceNative: true,
|
|
61441
|
+
mode: "singleton",
|
|
61442
|
+
deviceTypes: [
|
|
61443
|
+
DeviceType.Cover,
|
|
61444
|
+
DeviceType.Valve,
|
|
61445
|
+
DeviceType.Lock,
|
|
61446
|
+
DeviceType.MediaPlayer,
|
|
61447
|
+
DeviceType.Climate,
|
|
61448
|
+
DeviceType.Thermostat
|
|
61449
|
+
],
|
|
61450
|
+
methods: {},
|
|
61451
|
+
status: {
|
|
61452
|
+
schema: GroupActiveSchema,
|
|
61453
|
+
kind: "push"
|
|
61454
|
+
},
|
|
61455
|
+
runtimeState: GroupActiveSchema,
|
|
61456
|
+
/**
|
|
61457
|
+
* Runtime-state durability: **session** — recomputed from the members on the
|
|
61458
|
+
* next source event; a restored value would outlive the members it named.
|
|
61459
|
+
*
|
|
61460
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
61461
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
61462
|
+
*/
|
|
61463
|
+
durability: "session",
|
|
61464
|
+
history: "none"
|
|
61465
|
+
};
|
|
61466
|
+
/**
|
|
61062
61467
|
* How many members of a helper group answered (D944). Counts are integers,
|
|
61063
61468
|
* not measurements: zero included is a real count, never a stand-in reading.
|
|
61064
61469
|
* The reading itself stays on the output capability. History is none — the
|
|
@@ -61089,7 +61494,14 @@ var groupStatusCapability = {
|
|
|
61089
61494
|
deviceTypes: [
|
|
61090
61495
|
DeviceType.Sensor,
|
|
61091
61496
|
DeviceType.Switch,
|
|
61092
|
-
DeviceType.Light
|
|
61497
|
+
DeviceType.Light,
|
|
61498
|
+
DeviceType.Fan,
|
|
61499
|
+
DeviceType.Cover,
|
|
61500
|
+
DeviceType.Valve,
|
|
61501
|
+
DeviceType.Lock,
|
|
61502
|
+
DeviceType.MediaPlayer,
|
|
61503
|
+
DeviceType.Thermostat,
|
|
61504
|
+
DeviceType.Climate
|
|
61093
61505
|
],
|
|
61094
61506
|
methods: {},
|
|
61095
61507
|
status: {
|
|
@@ -62362,7 +62774,14 @@ var lockControlCapability = {
|
|
|
62362
62774
|
}),
|
|
62363
62775
|
unlock: method(object({
|
|
62364
62776
|
deviceId: number().int().nonnegative(),
|
|
62365
|
-
code: string().min(1).optional()
|
|
62777
|
+
code: string().min(1).optional(),
|
|
62778
|
+
/**
|
|
62779
|
+
* Honoured by a helper lock GROUP only (D944): unlocking several doors
|
|
62780
|
+
* with one call is refused unless the caller says it was confirmed. A
|
|
62781
|
+
* single lock ignores it. The refusal lives in the callee, so no
|
|
62782
|
+
* automation or API caller reaches the doors by skipping a dialog.
|
|
62783
|
+
*/
|
|
62784
|
+
confirm: boolean().optional()
|
|
62366
62785
|
}), _void(), {
|
|
62367
62786
|
kind: "mutation",
|
|
62368
62787
|
auth: "protected"
|
|
@@ -62399,6 +62818,44 @@ var lockControlCapability = {
|
|
|
62399
62818
|
volatileStateFields: ["lastChangedAt"]
|
|
62400
62819
|
};
|
|
62401
62820
|
/**
|
|
62821
|
+
* A monotonic total between resets (D944). Energy uses `power-meter.kwhTotal`
|
|
62822
|
+
* so dashboards keep one series; every other instantaneous reading lands here.
|
|
62823
|
+
* `value` is the time integral in the source quantity's accumulated base
|
|
62824
|
+
* (base-unit seconds, or kWh on the power meter). `null` is a gap, never zero.
|
|
62825
|
+
*/
|
|
62826
|
+
var MeterStatusSchema = object({
|
|
62827
|
+
value: number().nullable().meta(readingMeta("device", { label: "Total" })),
|
|
62828
|
+
lastFetchedAt: number()
|
|
62829
|
+
});
|
|
62830
|
+
var meterCapability = {
|
|
62831
|
+
name: "meter",
|
|
62832
|
+
scope: "device",
|
|
62833
|
+
deviceNative: true,
|
|
62834
|
+
mode: "singleton",
|
|
62835
|
+
deviceTypes: [DeviceType.Sensor],
|
|
62836
|
+
methods: {},
|
|
62837
|
+
status: {
|
|
62838
|
+
schema: MeterStatusSchema,
|
|
62839
|
+
kind: "push"
|
|
62840
|
+
},
|
|
62841
|
+
runtimeState: MeterStatusSchema,
|
|
62842
|
+
/**
|
|
62843
|
+
* Runtime-state durability: **restored** — the total is a cache of the
|
|
62844
|
+
* history integral. A restart shows it only until the history pass
|
|
62845
|
+
* recomputes the open period; it is not an in-memory buffer.
|
|
62846
|
+
*
|
|
62847
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
62848
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
62849
|
+
*/
|
|
62850
|
+
durability: "restored",
|
|
62851
|
+
history: { fields: { value: {
|
|
62852
|
+
kind: "counter",
|
|
62853
|
+
deadband: .001,
|
|
62854
|
+
minIntervalMs: 6e4
|
|
62855
|
+
} } },
|
|
62856
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
62857
|
+
};
|
|
62858
|
+
/**
|
|
62402
62859
|
* Media-player cap. Models HA `media_player.*` (Sonos, Chromecast,
|
|
62403
62860
|
* Apple TV, Spotify, Roku, generic OTT receivers, …) on
|
|
62404
62861
|
* `DeviceType.MediaPlayer`. Disjoint from the camera streaming
|
|
@@ -64910,9 +65367,9 @@ var PowerMeterStatusSchema = object({
|
|
|
64910
65367
|
/** Cumulative energy in kilowatt-hours since the meter was reset. */
|
|
64911
65368
|
kwhTotal: number().optional().meta(readingMeta("energy", { label: "Energy" })),
|
|
64912
65369
|
/** Voltage in volts. */
|
|
64913
|
-
volts: number().optional().meta(readingMeta("voltage")),
|
|
65370
|
+
volts: number().optional().meta(readingMeta("voltage", { label: "Voltage" })),
|
|
64914
65371
|
/** Current in amperes. */
|
|
64915
|
-
amps: number().optional().meta(readingMeta("current")),
|
|
65372
|
+
amps: number().optional().meta(readingMeta("current", { label: "Current" })),
|
|
64916
65373
|
/** Apparent power in volt-amperes. */
|
|
64917
65374
|
va: number().optional().meta(readingMeta("apparent-power")),
|
|
64918
65375
|
/** Power factor (0..1) if reported. */
|
|
@@ -64920,12 +65377,74 @@ var PowerMeterStatusSchema = object({
|
|
|
64920
65377
|
/** Ms epoch when the slice was last updated. */
|
|
64921
65378
|
lastFetchedAt: number()
|
|
64922
65379
|
});
|
|
65380
|
+
/**
|
|
65381
|
+
* Loads that draw metered mains power (D951). The reading is a feature of the
|
|
65382
|
+
* device itself — a plug, a lamp, a fan, an air conditioner, a boiler, a
|
|
65383
|
+
* vacuum dock — not a separate sensor beside it. A `Sensor` stays: a clamp
|
|
65384
|
+
* meter or a standalone energy monitor IS the device. Cover, lock, valve,
|
|
65385
|
+
* camera and the like are left out: their draw is not what anyone meters.
|
|
65386
|
+
*/
|
|
65387
|
+
var POWER_METER_DEVICE_TYPES = [
|
|
65388
|
+
DeviceType.Sensor,
|
|
65389
|
+
DeviceType.Switch,
|
|
65390
|
+
DeviceType.Light,
|
|
65391
|
+
DeviceType.Fan,
|
|
65392
|
+
DeviceType.Climate,
|
|
65393
|
+
DeviceType.Thermostat,
|
|
65394
|
+
DeviceType.Humidifier,
|
|
65395
|
+
DeviceType.WaterHeater,
|
|
65396
|
+
DeviceType.MediaPlayer,
|
|
65397
|
+
DeviceType.Washer,
|
|
65398
|
+
DeviceType.Dryer,
|
|
65399
|
+
DeviceType.Dishwasher,
|
|
65400
|
+
DeviceType.Vacuum,
|
|
65401
|
+
DeviceType.LawnMower,
|
|
65402
|
+
DeviceType.PetFeeder
|
|
65403
|
+
];
|
|
65404
|
+
/** Everything but a bare `Sensor`: a sensor that takes its reading from another sensor adds nothing. */
|
|
65405
|
+
var POWER_METER_CUSTOMIZE_DEVICE_TYPES = POWER_METER_DEVICE_TYPES.filter((type) => type !== DeviceType.Sensor);
|
|
65406
|
+
/** One scalar target per reading; each is sourced from a device of its own (D951). */
|
|
65407
|
+
function powerTarget(id, unit) {
|
|
65408
|
+
return {
|
|
65409
|
+
id,
|
|
65410
|
+
cardinality: "scalar",
|
|
65411
|
+
vocabulary: {
|
|
65412
|
+
cap: "power-meter",
|
|
65413
|
+
stateField: id
|
|
65414
|
+
},
|
|
65415
|
+
deviceTypes: POWER_METER_CUSTOMIZE_DEVICE_TYPES,
|
|
65416
|
+
apply: "add",
|
|
65417
|
+
path: id,
|
|
65418
|
+
sources: [{
|
|
65419
|
+
kind: "numeric",
|
|
65420
|
+
requiredUnit: unit,
|
|
65421
|
+
transforms: [{ kind: "identity" }]
|
|
65422
|
+
}],
|
|
65423
|
+
companions: [{
|
|
65424
|
+
kind: "clock",
|
|
65425
|
+
path: "lastFetchedAt",
|
|
65426
|
+
when: "always"
|
|
65427
|
+
}],
|
|
65428
|
+
sourceReport: { status: "assignment-status" },
|
|
65429
|
+
advancedExpression: true
|
|
65430
|
+
};
|
|
65431
|
+
}
|
|
65432
|
+
/** "Power and energy" extension: watts, energy, voltage and current from other devices (D951). */
|
|
65433
|
+
var powerMeterCustomize = {
|
|
65434
|
+
version: 1,
|
|
65435
|
+
targets: [
|
|
65436
|
+
powerTarget("watts", "W"),
|
|
65437
|
+
powerTarget("kwhTotal", "kWh"),
|
|
65438
|
+
powerTarget("volts", "V"),
|
|
65439
|
+
powerTarget("amps", "A")
|
|
65440
|
+
]
|
|
65441
|
+
};
|
|
64923
65442
|
var powerMeterCapability = {
|
|
64924
65443
|
name: "power-meter",
|
|
64925
65444
|
scope: "device",
|
|
64926
65445
|
deviceNative: true,
|
|
64927
65446
|
mode: "singleton",
|
|
64928
|
-
deviceTypes:
|
|
65447
|
+
deviceTypes: POWER_METER_DEVICE_TYPES,
|
|
64929
65448
|
methods: {},
|
|
64930
65449
|
status: {
|
|
64931
65450
|
schema: PowerMeterStatusSchema,
|
|
@@ -64982,7 +65501,8 @@ var powerMeterCapability = {
|
|
|
64982
65501
|
} },
|
|
64983
65502
|
/** Clock fields: written, but excluded from the compare that decides
|
|
64984
65503
|
* whether persisting is worth a SQLite commit. */
|
|
64985
|
-
volatileStateFields: ["lastFetchedAt"]
|
|
65504
|
+
volatileStateFields: ["lastFetchedAt"],
|
|
65505
|
+
customize: powerMeterCustomize
|
|
64986
65506
|
};
|
|
64987
65507
|
/**
|
|
64988
65508
|
* Presence cap. Models HA `person.*` and `device_tracker.*` entities
|
|
@@ -65663,6 +66183,8 @@ var runningCustomize = {
|
|
|
65663
66183
|
stateField: "running"
|
|
65664
66184
|
},
|
|
65665
66185
|
deviceTypes: [
|
|
66186
|
+
DeviceType.Washer,
|
|
66187
|
+
DeviceType.Dryer,
|
|
65666
66188
|
DeviceType.Dishwasher,
|
|
65667
66189
|
DeviceType.Vacuum,
|
|
65668
66190
|
DeviceType.LawnMower,
|
|
@@ -68152,7 +68674,8 @@ var switchCapability = {
|
|
|
68152
68674
|
deviceTypes: [
|
|
68153
68675
|
DeviceType.Switch,
|
|
68154
68676
|
DeviceType.Siren,
|
|
68155
|
-
DeviceType.Light
|
|
68677
|
+
DeviceType.Light,
|
|
68678
|
+
DeviceType.Fan
|
|
68156
68679
|
],
|
|
68157
68680
|
methods: { setState: method(object({
|
|
68158
68681
|
deviceId: number(),
|
|
@@ -70365,8 +70888,9 @@ method(object({}), array(TrainingBaseModelSchema).readonly(), { auth: "admin" })
|
|
|
70365
70888
|
kind: "mutation",
|
|
70366
70889
|
auth: "admin"
|
|
70367
70890
|
});
|
|
70891
|
+
DeviceFeature.FanSpeed, DeviceFeature.FanPreset, DeviceFeature.FanDirection, DeviceFeature.FanOscillating, DeviceFeature.CoverPositionable, DeviceFeature.CoverTilt, DeviceFeature.ValvePositionable, DeviceFeature.MediaPlayerVolume, DeviceFeature.ClimateFanMode;
|
|
70368
70892
|
SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
|
|
70369
|
-
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, 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.Dishwasher, DeviceType.Camera, DeviceType.Camera, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
|
|
70893
|
+
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.EventEmitter, DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, 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.Dishwasher, DeviceType.Washer, DeviceType.Dryer, DeviceType.Camera, DeviceType.Camera, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, 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.Thermostat, 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.Thermostat, 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.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
|
|
70370
70894
|
String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
|
|
70371
70895
|
DeviceRole.BinarySensor, DeviceRole.MotionSensor;
|
|
70372
70896
|
new Set(CAP_NAMES);
|
|
@@ -70695,6 +71219,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
70695
71219
|
featureProbe: featureProbeCapability,
|
|
70696
71220
|
flood: floodCapability,
|
|
70697
71221
|
gas: gasCapability,
|
|
71222
|
+
groupActive: groupActiveCapability,
|
|
70698
71223
|
groupCommands: groupCommandsCapability,
|
|
70699
71224
|
groupStatus: groupStatusCapability,
|
|
70700
71225
|
heatingValve: heatingValveCapability,
|
|
@@ -70706,6 +71231,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
70706
71231
|
lawnMowerControl: lawnMowerControlCapability,
|
|
70707
71232
|
lockControl: lockControlCapability,
|
|
70708
71233
|
mediaPlayer: mediaPlayerCapability,
|
|
71234
|
+
meter: meterCapability,
|
|
70709
71235
|
motion: motionCapability,
|
|
70710
71236
|
motionTrigger: motionTriggerCapability,
|
|
70711
71237
|
motionZones: motionZonesCapability,
|
|
@@ -71965,7 +72491,7 @@ var BaseDeviceProvider = class extends BaseAddon {
|
|
|
71965
72491
|
return toDeviceSummary(device, this.addonId);
|
|
71966
72492
|
}
|
|
71967
72493
|
};
|
|
71968
|
-
DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Camera, DeviceType.Hub, DeviceType.Switch, DeviceType.Siren, DeviceType.Light, DeviceType.Fan, DeviceType.Sensor, DeviceType.Thermostat, 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.Dishwasher;
|
|
72494
|
+
DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Camera, DeviceType.Hub, DeviceType.Switch, DeviceType.Siren, DeviceType.Light, DeviceType.Fan, DeviceType.Sensor, DeviceType.Thermostat, 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.Dishwasher, DeviceType.Washer, DeviceType.Dryer;
|
|
71969
72495
|
new Set(Object.values(DeviceType));
|
|
71970
72496
|
Object.freeze({
|
|
71971
72497
|
"accessories.getStatus": {
|
|
@@ -75188,6 +75714,13 @@ Object.freeze({
|
|
|
75188
75714
|
access: "view",
|
|
75189
75715
|
role: "viewer"
|
|
75190
75716
|
},
|
|
75717
|
+
"groupActive.getStatus": {
|
|
75718
|
+
capName: "group-active",
|
|
75719
|
+
capScope: "device",
|
|
75720
|
+
addonId: null,
|
|
75721
|
+
access: "view",
|
|
75722
|
+
role: "viewer"
|
|
75723
|
+
},
|
|
75191
75724
|
"groupCommands.getStatus": {
|
|
75192
75725
|
capName: "group-commands",
|
|
75193
75726
|
capScope: "device",
|
|
@@ -76154,6 +76687,13 @@ Object.freeze({
|
|
|
76154
76687
|
access: "create",
|
|
76155
76688
|
role: "admin"
|
|
76156
76689
|
},
|
|
76690
|
+
"meter.getStatus": {
|
|
76691
|
+
capName: "meter",
|
|
76692
|
+
capScope: "device",
|
|
76693
|
+
addonId: null,
|
|
76694
|
+
access: "view",
|
|
76695
|
+
role: "viewer"
|
|
76696
|
+
},
|
|
76157
76697
|
"metricsProvider.collectSnapshot": {
|
|
76158
76698
|
capName: "metrics-provider",
|
|
76159
76699
|
capScope: "system",
|
|
@@ -84252,7 +84792,39 @@ var APPLIANCE_CAP_VOCABULARY = {
|
|
|
84252
84792
|
phrase: t("When {device} finishes", "Quando {device} finisce"),
|
|
84253
84793
|
icon: "square"
|
|
84254
84794
|
}
|
|
84255
|
-
}
|
|
84795
|
+
},
|
|
84796
|
+
overrides: { byType: {
|
|
84797
|
+
[DeviceType.Washer]: {
|
|
84798
|
+
state: { running: {
|
|
84799
|
+
whenTrue: t("When the washing machine starts", "Quando la lavatrice inizia"),
|
|
84800
|
+
whenFalse: t("When the washing machine has finished", "Quando la lavatrice ha finito")
|
|
84801
|
+
} },
|
|
84802
|
+
events: {
|
|
84803
|
+
onStarted: { phrase: t("When the washing machine starts", "Quando la lavatrice inizia") },
|
|
84804
|
+
onFinished: { phrase: t("When the washing machine has finished", "Quando la lavatrice ha finito") }
|
|
84805
|
+
}
|
|
84806
|
+
},
|
|
84807
|
+
[DeviceType.Dryer]: {
|
|
84808
|
+
state: { running: {
|
|
84809
|
+
whenTrue: t("When the dryer starts", "Quando l'asciugatrice inizia"),
|
|
84810
|
+
whenFalse: t("When the dryer has finished", "Quando l'asciugatrice ha finito")
|
|
84811
|
+
} },
|
|
84812
|
+
events: {
|
|
84813
|
+
onStarted: { phrase: t("When the dryer starts", "Quando l'asciugatrice inizia") },
|
|
84814
|
+
onFinished: { phrase: t("When the dryer has finished", "Quando l'asciugatrice ha finito") }
|
|
84815
|
+
}
|
|
84816
|
+
},
|
|
84817
|
+
[DeviceType.Dishwasher]: {
|
|
84818
|
+
state: { running: {
|
|
84819
|
+
whenTrue: t("When the dishwasher starts", "Quando la lavastoviglie inizia"),
|
|
84820
|
+
whenFalse: t("When the dishwasher has finished", "Quando la lavastoviglie ha finito")
|
|
84821
|
+
} },
|
|
84822
|
+
events: {
|
|
84823
|
+
onStarted: { phrase: t("When the dishwasher starts", "Quando la lavastoviglie inizia") },
|
|
84824
|
+
onFinished: { phrase: t("When the dishwasher has finished", "Quando la lavastoviglie ha finito") }
|
|
84825
|
+
}
|
|
84826
|
+
}
|
|
84827
|
+
} }
|
|
84256
84828
|
},
|
|
84257
84829
|
update: {
|
|
84258
84830
|
scope: "device",
|
|
@@ -85024,6 +85596,10 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
85024
85596
|
icon: "flame"
|
|
85025
85597
|
}]
|
|
85026
85598
|
},
|
|
85599
|
+
"group-active": {
|
|
85600
|
+
scope: "device",
|
|
85601
|
+
noun: t("Group state", "Stato del gruppo")
|
|
85602
|
+
},
|
|
85027
85603
|
"group-commands": {
|
|
85028
85604
|
scope: "device",
|
|
85029
85605
|
noun: t("Group command", "Comando di gruppo")
|
|
@@ -85080,6 +85656,17 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
85080
85656
|
}],
|
|
85081
85657
|
events: { onMotionChanged: { notOperatorFacing: "the `detected` state trigger phrases both edges, from the mirror that survives a dropped event (D49)" } }
|
|
85082
85658
|
},
|
|
85659
|
+
meter: {
|
|
85660
|
+
scope: "device",
|
|
85661
|
+
noun: t("Meter", "Contatore"),
|
|
85662
|
+
state: [{
|
|
85663
|
+
kind: "numeric",
|
|
85664
|
+
field: "value",
|
|
85665
|
+
quantity: t("the total", "il totale"),
|
|
85666
|
+
label: t("Total", "Totale"),
|
|
85667
|
+
icon: "gauge"
|
|
85668
|
+
}]
|
|
85669
|
+
},
|
|
85083
85670
|
"numeric-sensor": {
|
|
85084
85671
|
scope: "device",
|
|
85085
85672
|
noun: t("Sensor", "Sensore"),
|
|
@@ -85552,8 +86139,47 @@ function projectAction(cap, action) {
|
|
|
85552
86139
|
};
|
|
85553
86140
|
}
|
|
85554
86141
|
Object.entries(CAP_VOCABULARY_BY_NAME).flatMap(([cap, entry]) => entry.scope === "device" ? (entry.actions ?? []).map((a) => projectAction(cap, a)) : []);
|
|
85555
|
-
DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, 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.Dishwasher;
|
|
86142
|
+
DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, 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.Dishwasher, DeviceType.Washer, DeviceType.Dryer;
|
|
85556
86143
|
DeviceFeature.BatteryOperated;
|
|
86144
|
+
DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher;
|
|
86145
|
+
var HA_AS = "a power sensor (device_class power). Home Assistant has no laundry domain. running-state stays unexported until a null reading can be published as unavailable.";
|
|
86146
|
+
var HOMEKIT_REASON = "HomeKit has no laundry-appliance service. The export tab would pair an accessory with nothing on it: running-state is withheld until a null reading can be unavailable, and power is not a HomeKit service this export honours.";
|
|
86147
|
+
var ALEXA_REASON = "Alexa has no laundry category in this export, and neither power nor running has an Alexa interface.";
|
|
86148
|
+
var GOOGLE_REASON = "Google WASHER, DRYER and DISHWASHER require RunCycle. A power threshold is not that trait, and this export does not publish RunCycle.";
|
|
86149
|
+
var MATTER_REASON = "No Matter export is built. The closest device types are Laundry Washer (0x0073) and Laundry Dryer (0x0074); a power threshold is not the Laundry Washer Mode cluster.";
|
|
86150
|
+
function withheld(reason) {
|
|
86151
|
+
return {
|
|
86152
|
+
[DeviceType.Washer]: {
|
|
86153
|
+
exported: false,
|
|
86154
|
+
reason
|
|
86155
|
+
},
|
|
86156
|
+
[DeviceType.Dryer]: {
|
|
86157
|
+
exported: false,
|
|
86158
|
+
reason
|
|
86159
|
+
},
|
|
86160
|
+
[DeviceType.Dishwasher]: {
|
|
86161
|
+
exported: false,
|
|
86162
|
+
reason
|
|
86163
|
+
}
|
|
86164
|
+
};
|
|
86165
|
+
}
|
|
86166
|
+
function offered(received) {
|
|
86167
|
+
return {
|
|
86168
|
+
[DeviceType.Washer]: {
|
|
86169
|
+
exported: true,
|
|
86170
|
+
as: received
|
|
86171
|
+
},
|
|
86172
|
+
[DeviceType.Dryer]: {
|
|
86173
|
+
exported: true,
|
|
86174
|
+
as: received
|
|
86175
|
+
},
|
|
86176
|
+
[DeviceType.Dishwasher]: {
|
|
86177
|
+
exported: true,
|
|
86178
|
+
as: received
|
|
86179
|
+
}
|
|
86180
|
+
};
|
|
86181
|
+
}
|
|
86182
|
+
offered(HA_AS), withheld(HOMEKIT_REASON), withheld(ALEXA_REASON), withheld(GOOGLE_REASON), withheld(MATTER_REASON);
|
|
85557
86183
|
Object.freeze({
|
|
85558
86184
|
"accessories.getStatus": [{
|
|
85559
86185
|
name: "deviceId",
|
|
@@ -86520,6 +87146,11 @@ Object.freeze({
|
|
|
86520
87146
|
form: "single",
|
|
86521
87147
|
optional: false
|
|
86522
87148
|
}],
|
|
87149
|
+
"groupActive.getStatus": [{
|
|
87150
|
+
name: "deviceId",
|
|
87151
|
+
form: "single",
|
|
87152
|
+
optional: false
|
|
87153
|
+
}],
|
|
86523
87154
|
"groupCommands.getStatus": [{
|
|
86524
87155
|
name: "deviceId",
|
|
86525
87156
|
form: "single",
|
|
@@ -86730,6 +87361,11 @@ Object.freeze({
|
|
|
86730
87361
|
form: "single",
|
|
86731
87362
|
optional: false
|
|
86732
87363
|
}],
|
|
87364
|
+
"meter.getStatus": [{
|
|
87365
|
+
name: "deviceId",
|
|
87366
|
+
form: "single",
|
|
87367
|
+
optional: false
|
|
87368
|
+
}],
|
|
86733
87369
|
"motion.getStatus": [{
|
|
86734
87370
|
name: "deviceId",
|
|
86735
87371
|
form: "single",
|
|
@@ -88337,7 +88973,6 @@ Object.freeze({
|
|
|
88337
88973
|
"network-access": "ingress",
|
|
88338
88974
|
"smtp-provider": "email"
|
|
88339
88975
|
});
|
|
88340
|
-
DeviceType.Camera;
|
|
88341
88976
|
/**
|
|
88342
88977
|
* A saved Customize assignment (D936). The schema is the type: callers use
|
|
88343
88978
|
* `z.infer`, they do not restate the shape.
|