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