@camstack/addon-smtp-nodemailer 1.2.142 → 1.2.143
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 +11 -9
- package/dist/smtp.addon.js +540 -45
- package/dist/smtp.addon.mjs +540 -45
- package/package.json +3 -3
package/dist/smtp.addon.mjs
CHANGED
|
@@ -5477,7 +5477,7 @@ var ZodIssueCode = {
|
|
|
5477
5477
|
var ZodFirstPartyTypeKind;
|
|
5478
5478
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5479
5479
|
//#endregion
|
|
5480
|
-
//#region ../types/dist/sleep
|
|
5480
|
+
//#region ../types/dist/sleep--jXS9hWo.mjs
|
|
5481
5481
|
/**
|
|
5482
5482
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5483
5483
|
* window to float samples (D455).
|
|
@@ -8599,6 +8599,7 @@ var CAP_NAMES = Object.freeze([
|
|
|
8599
8599
|
"filesystem-browse",
|
|
8600
8600
|
"flood",
|
|
8601
8601
|
"gas",
|
|
8602
|
+
"group-active",
|
|
8602
8603
|
"group-commands",
|
|
8603
8604
|
"group-status",
|
|
8604
8605
|
"heating-valve",
|
|
@@ -8621,6 +8622,7 @@ var CAP_NAMES = Object.freeze([
|
|
|
8621
8622
|
"login-method",
|
|
8622
8623
|
"media-player",
|
|
8623
8624
|
"mesh-network",
|
|
8625
|
+
"meter",
|
|
8624
8626
|
"metrics-provider",
|
|
8625
8627
|
"model-convert",
|
|
8626
8628
|
"model-distributor",
|
|
@@ -9419,6 +9421,10 @@ Object.freeze({
|
|
|
9419
9421
|
"path": "detected",
|
|
9420
9422
|
"valueType": "boolean"
|
|
9421
9423
|
}],
|
|
9424
|
+
"group-active": [{
|
|
9425
|
+
"path": "active",
|
|
9426
|
+
"valueType": "boolean"
|
|
9427
|
+
}],
|
|
9422
9428
|
"group-status": [
|
|
9423
9429
|
{
|
|
9424
9430
|
"path": "included",
|
|
@@ -9678,6 +9684,10 @@ Object.freeze({
|
|
|
9678
9684
|
]
|
|
9679
9685
|
}
|
|
9680
9686
|
],
|
|
9687
|
+
"meter": [{
|
|
9688
|
+
"path": "value",
|
|
9689
|
+
"valueType": "number"
|
|
9690
|
+
}],
|
|
9681
9691
|
"motion": [
|
|
9682
9692
|
{
|
|
9683
9693
|
"path": "detected",
|
|
@@ -10421,7 +10431,7 @@ object({
|
|
|
10421
10431
|
params: record(string(), union([string(), number()])).optional()
|
|
10422
10432
|
});
|
|
10423
10433
|
//#endregion
|
|
10424
|
-
//#region ../types/dist/err-msg-
|
|
10434
|
+
//#region ../types/dist/err-msg-DIorGYeC.mjs
|
|
10425
10435
|
var DeviceType = /* @__PURE__ */ function(DeviceType) {
|
|
10426
10436
|
DeviceType["Camera"] = "camera";
|
|
10427
10437
|
DeviceType["Hub"] = "hub";
|
|
@@ -10515,8 +10525,14 @@ var DeviceType = /* @__PURE__ */ function(DeviceType) {
|
|
|
10515
10525
|
DeviceType["PetFeeder"] = "pet-feeder";
|
|
10516
10526
|
/** Built-in dishwasher — program lifecycle, door / remote-start gates,
|
|
10517
10527
|
* salt and rinse-aid levels. Installed with the `dishwasher` cap.
|
|
10518
|
-
* Sources: native Bosch Home Connect, reusable by similar integrations.
|
|
10528
|
+
* Sources: native Bosch Home Connect, reusable by similar integrations.
|
|
10529
|
+
* A plug-built dishwasher carries running-state and power instead. */
|
|
10519
10530
|
DeviceType["Dishwasher"] = "dishwasher";
|
|
10531
|
+
/** Washing machine. A plug-built one is running while its power stays
|
|
10532
|
+
* above a threshold. No program cap — that surface is the dishwasher's. */
|
|
10533
|
+
DeviceType["Washer"] = "washer";
|
|
10534
|
+
/** Tumble dryer. Same plug-built running surface as {@link Washer}. */
|
|
10535
|
+
DeviceType["Dryer"] = "dryer";
|
|
10520
10536
|
return DeviceType;
|
|
10521
10537
|
}({});
|
|
10522
10538
|
var DeviceFeature = /* @__PURE__ */ function(DeviceFeature) {
|
|
@@ -10764,7 +10780,7 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
|
|
|
10764
10780
|
return DeviceRole;
|
|
10765
10781
|
}({});
|
|
10766
10782
|
//#endregion
|
|
10767
|
-
//#region ../types/dist/composition-
|
|
10783
|
+
//#region ../types/dist/composition-Bb8iwHEJ.mjs
|
|
10768
10784
|
/**
|
|
10769
10785
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
10770
10786
|
*
|
|
@@ -11079,6 +11095,13 @@ var table = {
|
|
|
11079
11095
|
apply: () => {
|
|
11080
11096
|
throw new ExpressionEvalError("latchedAt: stateful evaluation context is required");
|
|
11081
11097
|
}
|
|
11098
|
+
},
|
|
11099
|
+
schmitt: {
|
|
11100
|
+
minArgs: 3,
|
|
11101
|
+
maxArgs: 5,
|
|
11102
|
+
apply: () => {
|
|
11103
|
+
throw new ExpressionEvalError("schmitt: stateful evaluation context is required");
|
|
11104
|
+
}
|
|
11082
11105
|
}
|
|
11083
11106
|
};
|
|
11084
11107
|
Object.freeze(Object.assign(Object.create(null), table));
|
|
@@ -11520,6 +11543,99 @@ function validateExpressionSource(src) {
|
|
|
11520
11543
|
return null;
|
|
11521
11544
|
}
|
|
11522
11545
|
/**
|
|
11546
|
+
* One power reading becomes a washer, dryer or dishwasher (D944 helper).
|
|
11547
|
+
*
|
|
11548
|
+
* Standby of the control board is under 5 W; a motor or a heater is far
|
|
11549
|
+
* above that, so 5 W is the line. A door lock or a short pump spike is not
|
|
11550
|
+
* a cycle, so running starts only after 30 s above the line.
|
|
11551
|
+
*
|
|
11552
|
+
* A wash, dry or dishwasher pause (soak, heat-wait, heater off between
|
|
11553
|
+
* bursts) lasts several minutes. Ending the cycle on the first dip would
|
|
11554
|
+
* report "finished" in the middle of the program, so the stop dwell is
|
|
11555
|
+
* 10 minutes on every type. The number is stored per type so one machine
|
|
11556
|
+
* can move later without moving the others.
|
|
11557
|
+
*/
|
|
11558
|
+
var APPLIANCE_TEMPLATE_ID = "appliance";
|
|
11559
|
+
var APPLIANCE_KINDS = [
|
|
11560
|
+
"washer",
|
|
11561
|
+
"dryer",
|
|
11562
|
+
"dishwasher"
|
|
11563
|
+
];
|
|
11564
|
+
DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher;
|
|
11565
|
+
/**
|
|
11566
|
+
* Statistics and integrals over a history read (D944).
|
|
11567
|
+
*
|
|
11568
|
+
* Pure: the same points always give the same answer, so a restart recomputes
|
|
11569
|
+
* rather than trusting a buffer. A gauge mean is time-weighted (value × ms),
|
|
11570
|
+
* never the mean of the samples. A hole with no held value is not integrated
|
|
11571
|
+
* as zero. A truncated read is not published.
|
|
11572
|
+
*/
|
|
11573
|
+
var STATISTIC_STATS = [
|
|
11574
|
+
"min",
|
|
11575
|
+
"max",
|
|
11576
|
+
"mean",
|
|
11577
|
+
"sum",
|
|
11578
|
+
"count",
|
|
11579
|
+
"change"
|
|
11580
|
+
];
|
|
11581
|
+
/**
|
|
11582
|
+
* The range a statistics or integral helper asks history for (D944).
|
|
11583
|
+
*
|
|
11584
|
+
* Calendar edges are the hub's timezone, never UTC midnight: a day is 23, 24
|
|
11585
|
+
* or 25 hours across a DST change. A tier is eligible only when its retention
|
|
11586
|
+
* is strictly longer than the longest that range can be. Forever qualifies.
|
|
11587
|
+
* Equal to a tier's retention is a refusal, not a short answer.
|
|
11588
|
+
*/
|
|
11589
|
+
var MINUTE_MS = 6e4;
|
|
11590
|
+
var HOUR_MS = 60 * MINUTE_MS;
|
|
11591
|
+
var DAY_MS = 24 * HOUR_MS;
|
|
11592
|
+
var ROLLING_SPANS = [
|
|
11593
|
+
"1h",
|
|
11594
|
+
"24h",
|
|
11595
|
+
"2d",
|
|
11596
|
+
"7d",
|
|
11597
|
+
"30d",
|
|
11598
|
+
"custom"
|
|
11599
|
+
];
|
|
11600
|
+
var CALENDAR_PERIODS = [
|
|
11601
|
+
"today",
|
|
11602
|
+
"yesterday",
|
|
11603
|
+
"this-week",
|
|
11604
|
+
"this-month"
|
|
11605
|
+
];
|
|
11606
|
+
var RESET_PERIODS = [
|
|
11607
|
+
"never",
|
|
11608
|
+
"daily",
|
|
11609
|
+
"weekly",
|
|
11610
|
+
"monthly"
|
|
11611
|
+
];
|
|
11612
|
+
5 * MINUTE_MS;
|
|
11613
|
+
24 * HOUR_MS, 2 * DAY_MS, 7 * DAY_MS, 30 * DAY_MS;
|
|
11614
|
+
7 * DAY_MS, 30 * DAY_MS, 365 * DAY_MS;
|
|
11615
|
+
var rollingWindowObject = object({
|
|
11616
|
+
kind: literal("rolling"),
|
|
11617
|
+
span: _enum(ROLLING_SPANS),
|
|
11618
|
+
customMinutes: number().int().min(5).optional()
|
|
11619
|
+
}).check((payload) => {
|
|
11620
|
+
if (payload.value.span === "custom" && payload.value.customMinutes === void 0) payload.issues.push({
|
|
11621
|
+
code: "custom",
|
|
11622
|
+
message: "a custom range needs a duration in minutes",
|
|
11623
|
+
path: ["customMinutes"],
|
|
11624
|
+
input: payload.value
|
|
11625
|
+
});
|
|
11626
|
+
if (payload.value.span !== "custom" && payload.value.customMinutes !== void 0) payload.issues.push({
|
|
11627
|
+
code: "custom",
|
|
11628
|
+
message: "only a custom range carries a duration",
|
|
11629
|
+
path: ["customMinutes"],
|
|
11630
|
+
input: payload.value
|
|
11631
|
+
});
|
|
11632
|
+
});
|
|
11633
|
+
var RollingWindowSchema = rollingWindowObject;
|
|
11634
|
+
var StatisticWindowSchema = discriminatedUnion("kind", [rollingWindowObject, object({
|
|
11635
|
+
kind: literal("calendar"),
|
|
11636
|
+
period: _enum(CALENDAR_PERIODS)
|
|
11637
|
+
})]);
|
|
11638
|
+
/**
|
|
11523
11639
|
* A composition source identity: `(addonId, stableId)`, never a numeric device
|
|
11524
11640
|
* id. Split out so helper schemas can name it without a cycle through
|
|
11525
11641
|
* `composition.ts` (D659).
|
|
@@ -11545,7 +11661,13 @@ var GROUP_TEMPLATE_IDS = [
|
|
|
11545
11661
|
"occupancy",
|
|
11546
11662
|
"binary",
|
|
11547
11663
|
"switch",
|
|
11548
|
-
"light"
|
|
11664
|
+
"light",
|
|
11665
|
+
"fan",
|
|
11666
|
+
"cover",
|
|
11667
|
+
"valve",
|
|
11668
|
+
"lock",
|
|
11669
|
+
"media-player",
|
|
11670
|
+
"climate"
|
|
11549
11671
|
];
|
|
11550
11672
|
var NUMERIC_AGGREGATES = [
|
|
11551
11673
|
"mean",
|
|
@@ -11575,14 +11697,73 @@ var HelperMemberSchema = object({
|
|
|
11575
11697
|
cap: string().min(1),
|
|
11576
11698
|
fieldPath: string().min(1)
|
|
11577
11699
|
});
|
|
11578
|
-
var HelperSpecSchema = discriminatedUnion("kind", [
|
|
11579
|
-
|
|
11580
|
-
|
|
11581
|
-
|
|
11582
|
-
|
|
11583
|
-
|
|
11584
|
-
|
|
11585
|
-
|
|
11700
|
+
var HelperSpecSchema = discriminatedUnion("kind", [
|
|
11701
|
+
object({
|
|
11702
|
+
kind: literal("group"),
|
|
11703
|
+
templateId: GroupTemplateIdSchema,
|
|
11704
|
+
aggregate: AggregateReducerSchema,
|
|
11705
|
+
members: array(HelperMemberSchema).min(1).max(64),
|
|
11706
|
+
/** Actuator groups only. Readings leave this unset. */
|
|
11707
|
+
active: ActiveCriterionSchema.optional()
|
|
11708
|
+
}),
|
|
11709
|
+
object({
|
|
11710
|
+
kind: literal("appliance"),
|
|
11711
|
+
templateId: literal(APPLIANCE_TEMPLATE_ID),
|
|
11712
|
+
appliance: _enum(APPLIANCE_KINDS),
|
|
11713
|
+
thresholdWatts: number().positive(),
|
|
11714
|
+
startDwellMs: number().int().nonnegative(),
|
|
11715
|
+
stopDwellMs: number().int().nonnegative(),
|
|
11716
|
+
member: HelperMemberSchema
|
|
11717
|
+
}),
|
|
11718
|
+
object({
|
|
11719
|
+
kind: literal("statistic"),
|
|
11720
|
+
stat: _enum(STATISTIC_STATS),
|
|
11721
|
+
window: StatisticWindowSchema,
|
|
11722
|
+
source: HelperMemberSchema
|
|
11723
|
+
}),
|
|
11724
|
+
object({
|
|
11725
|
+
kind: literal("integral"),
|
|
11726
|
+
reset: _enum(RESET_PERIODS),
|
|
11727
|
+
output: _enum(["energy", "meter"]),
|
|
11728
|
+
source: HelperMemberSchema
|
|
11729
|
+
}),
|
|
11730
|
+
object({
|
|
11731
|
+
kind: literal("threshold"),
|
|
11732
|
+
source: HelperMemberSchema,
|
|
11733
|
+
high: number(),
|
|
11734
|
+
low: number(),
|
|
11735
|
+
onForMs: number().int().nonnegative(),
|
|
11736
|
+
offForMs: number().int().nonnegative()
|
|
11737
|
+
}),
|
|
11738
|
+
object({
|
|
11739
|
+
kind: literal("arithmetic"),
|
|
11740
|
+
op: _enum([
|
|
11741
|
+
"sum",
|
|
11742
|
+
"difference",
|
|
11743
|
+
"ratio"
|
|
11744
|
+
]),
|
|
11745
|
+
inputs: array(HelperMemberSchema).min(2).max(64)
|
|
11746
|
+
}),
|
|
11747
|
+
object({
|
|
11748
|
+
kind: literal("expression"),
|
|
11749
|
+
expr: string().min(1),
|
|
11750
|
+
inputs: array(object({
|
|
11751
|
+
name: string().min(1),
|
|
11752
|
+
member: HelperMemberSchema
|
|
11753
|
+
})).min(1).max(64),
|
|
11754
|
+
output: _enum(["number", "boolean"])
|
|
11755
|
+
}),
|
|
11756
|
+
object({
|
|
11757
|
+
kind: literal("derivative"),
|
|
11758
|
+
window: RollingWindowSchema,
|
|
11759
|
+
per: _enum([
|
|
11760
|
+
"second",
|
|
11761
|
+
"minute",
|
|
11762
|
+
"hour"
|
|
11763
|
+
]),
|
|
11764
|
+
source: HelperMemberSchema
|
|
11765
|
+
})
|
|
11766
|
+
]);
|
|
11586
11767
|
/** A composed device's stableId is this prefix plus the block id. */
|
|
11587
11768
|
var COMPOSED_DEVICE_STABLE_ID_PREFIX = "composed-";
|
|
11588
11769
|
/** Longest snippet a `code` source may carry (slice 4). */
|
|
@@ -11643,6 +11824,12 @@ var CompositionFieldSourceSchema = discriminatedUnion("kind", [
|
|
|
11643
11824
|
"all"
|
|
11644
11825
|
]),
|
|
11645
11826
|
reads: array(CompositionFieldReadSchema).min(1).max(64),
|
|
11827
|
+
/**
|
|
11828
|
+
* Set when the reads are an enum state, not a yes/no: the listed states
|
|
11829
|
+
* count as active (a cover is `open`). A state outside the list is inactive;
|
|
11830
|
+
* a read that is not a state at all is left out. Only `any` / `all` use it.
|
|
11831
|
+
*/
|
|
11832
|
+
activeWhen: array(string().min(1)).min(1).optional(),
|
|
11646
11833
|
/** `value` is the reading; the others are the member counts. */
|
|
11647
11834
|
publish: _enum([
|
|
11648
11835
|
"value",
|
|
@@ -11656,6 +11843,26 @@ var CompositionFieldSourceSchema = discriminatedUnion("kind", [
|
|
|
11656
11843
|
"omit",
|
|
11657
11844
|
"offline"
|
|
11658
11845
|
])
|
|
11846
|
+
}),
|
|
11847
|
+
object({
|
|
11848
|
+
kind: literal("series"),
|
|
11849
|
+
read: CompositionFieldReadSchema,
|
|
11850
|
+
/** `value` is the statistic or the integral. The others are the gap counts. */
|
|
11851
|
+
publish: _enum([
|
|
11852
|
+
"value",
|
|
11853
|
+
"included",
|
|
11854
|
+
"excluded",
|
|
11855
|
+
"total"
|
|
11856
|
+
]),
|
|
11857
|
+
/**
|
|
11858
|
+
* What an unanswered `value` does. Counts ignore this. `offline` leaves the
|
|
11859
|
+
* device unseeded until history answers, so a restart cannot publish 0.
|
|
11860
|
+
*/
|
|
11861
|
+
empty: _enum([
|
|
11862
|
+
"null",
|
|
11863
|
+
"omit",
|
|
11864
|
+
"offline"
|
|
11865
|
+
])
|
|
11659
11866
|
})
|
|
11660
11867
|
]);
|
|
11661
11868
|
var CompositionCommandTargetSchema = discriminatedUnion("kind", [object({
|
|
@@ -16815,7 +17022,22 @@ var BrokerProviderInfoSchema = object({
|
|
|
16815
17022
|
*/
|
|
16816
17023
|
interactiveConnectPath: string().min(1).optional(),
|
|
16817
17024
|
/** Relative hub path to disconnect the linked account (same popup pattern). */
|
|
16818
|
-
interactiveDisconnectPath: string().min(1).optional()
|
|
17025
|
+
interactiveDisconnectPath: string().min(1).optional(),
|
|
17026
|
+
/**
|
|
17027
|
+
* The kind signs in through a server-held interactive session instead of
|
|
17028
|
+
* (or before) typed credentials. `basePath` is a hub-relative route set
|
|
17029
|
+
* served by the owning addon (`/addon/<id>/...`) speaking the sign-in
|
|
17030
|
+
* contract: `POST {basePath}/start` (body: the form's settings) answers
|
|
17031
|
+
* `{ sessionId, loginUrl }`; `GET {basePath}/status?sessionId=` answers
|
|
17032
|
+
* `{ phase: 'starting' | 'awaiting-login' | 'captured' | 'error' |
|
|
17033
|
+
* 'cancelled', loginUrl, error }`; `POST {basePath}/commit`
|
|
17034
|
+
* (`{ sessionId, name, brokerId? }`) stores the credentials on a new or
|
|
17035
|
+
* existing broker and answers `{ brokerId }`; `POST {basePath}/cancel`
|
|
17036
|
+
* (`{ sessionId }`) drops the session. The dialog that edits a broker
|
|
17037
|
+
* offers it as the default path; the fields the session fills are
|
|
17038
|
+
* marked `filledBySignIn` in the kind's settings schema.
|
|
17039
|
+
*/
|
|
17040
|
+
signIn: object({ basePath: string().min(1) }).optional()
|
|
16819
17041
|
}))
|
|
16820
17042
|
});
|
|
16821
17043
|
var ListInputSchema = object({
|
|
@@ -17814,7 +18036,8 @@ var CompositionProblemSchema = object({
|
|
|
17814
18036
|
"native-capability-replace",
|
|
17815
18037
|
"mixed-quantity",
|
|
17816
18038
|
"helper-mismatch",
|
|
17817
|
-
"member-constraint"
|
|
18039
|
+
"member-constraint",
|
|
18040
|
+
"retention"
|
|
17818
18041
|
]),
|
|
17819
18042
|
path: string(),
|
|
17820
18043
|
message: string()
|
|
@@ -18048,13 +18271,17 @@ Object.freeze({
|
|
|
18048
18271
|
latchedAt: {
|
|
18049
18272
|
kind: "fixed",
|
|
18050
18273
|
result: ["number", "null"]
|
|
18274
|
+
},
|
|
18275
|
+
schmitt: {
|
|
18276
|
+
kind: "fixed",
|
|
18277
|
+
result: ["boolean", "null"]
|
|
18051
18278
|
}
|
|
18052
18279
|
});
|
|
18053
18280
|
/**
|
|
18054
18281
|
* One catalog row per base reading a group helper can build (D944 §3).
|
|
18055
18282
|
* Data, not a form default written into the block.
|
|
18056
18283
|
*/
|
|
18057
|
-
var NOW = {
|
|
18284
|
+
var NOW$2 = {
|
|
18058
18285
|
fieldPath: "lastFetchedAt",
|
|
18059
18286
|
expr: "now"
|
|
18060
18287
|
};
|
|
@@ -18068,6 +18295,8 @@ function numeric(input) {
|
|
|
18068
18295
|
family: "numeric",
|
|
18069
18296
|
deviceType: DeviceType.Sensor,
|
|
18070
18297
|
memberDeviceType: DeviceType.Sensor,
|
|
18298
|
+
memberDeviceTypes: [DeviceType.Sensor],
|
|
18299
|
+
activeWhen: void 0,
|
|
18071
18300
|
commandCaps: [],
|
|
18072
18301
|
baseUnit: baseUnitOf(input.quantity),
|
|
18073
18302
|
aggregates: NUMERIC_AGGREGATES,
|
|
@@ -18083,6 +18312,8 @@ function binary(input) {
|
|
|
18083
18312
|
family: "binary",
|
|
18084
18313
|
deviceType: DeviceType.Sensor,
|
|
18085
18314
|
memberDeviceType: DeviceType.Sensor,
|
|
18315
|
+
memberDeviceTypes: [DeviceType.Sensor],
|
|
18316
|
+
activeWhen: void 0,
|
|
18086
18317
|
commandCaps: [],
|
|
18087
18318
|
quantity: "none",
|
|
18088
18319
|
baseUnit: void 0,
|
|
@@ -18100,7 +18331,7 @@ var GROUP_TEMPLATES = [
|
|
|
18100
18331
|
quantity: "temperature",
|
|
18101
18332
|
defaultAggregate: "mean",
|
|
18102
18333
|
empty: "null",
|
|
18103
|
-
companions: [NOW]
|
|
18334
|
+
companions: [NOW$2]
|
|
18104
18335
|
}),
|
|
18105
18336
|
numeric({
|
|
18106
18337
|
id: "humidity",
|
|
@@ -18111,7 +18342,7 @@ var GROUP_TEMPLATES = [
|
|
|
18111
18342
|
quantity: "humidity",
|
|
18112
18343
|
defaultAggregate: "mean",
|
|
18113
18344
|
empty: "null",
|
|
18114
|
-
companions: [NOW]
|
|
18345
|
+
companions: [NOW$2]
|
|
18115
18346
|
}),
|
|
18116
18347
|
numeric({
|
|
18117
18348
|
id: "pressure",
|
|
@@ -18122,7 +18353,7 @@ var GROUP_TEMPLATES = [
|
|
|
18122
18353
|
quantity: "pressure",
|
|
18123
18354
|
defaultAggregate: "mean",
|
|
18124
18355
|
empty: "null",
|
|
18125
|
-
companions: [NOW]
|
|
18356
|
+
companions: [NOW$2]
|
|
18126
18357
|
}),
|
|
18127
18358
|
numeric({
|
|
18128
18359
|
id: "illuminance",
|
|
@@ -18133,7 +18364,7 @@ var GROUP_TEMPLATES = [
|
|
|
18133
18364
|
quantity: "illuminance",
|
|
18134
18365
|
defaultAggregate: "mean",
|
|
18135
18366
|
empty: "null",
|
|
18136
|
-
companions: [NOW]
|
|
18367
|
+
companions: [NOW$2]
|
|
18137
18368
|
}),
|
|
18138
18369
|
numeric({
|
|
18139
18370
|
id: "power",
|
|
@@ -18144,7 +18375,7 @@ var GROUP_TEMPLATES = [
|
|
|
18144
18375
|
quantity: "power",
|
|
18145
18376
|
defaultAggregate: "sum",
|
|
18146
18377
|
empty: "omit",
|
|
18147
|
-
companions: [NOW]
|
|
18378
|
+
companions: [NOW$2]
|
|
18148
18379
|
}),
|
|
18149
18380
|
numeric({
|
|
18150
18381
|
id: "energy",
|
|
@@ -18155,7 +18386,7 @@ var GROUP_TEMPLATES = [
|
|
|
18155
18386
|
quantity: "energy",
|
|
18156
18387
|
defaultAggregate: "sum",
|
|
18157
18388
|
empty: "omit",
|
|
18158
|
-
companions: [NOW]
|
|
18389
|
+
companions: [NOW$2]
|
|
18159
18390
|
}),
|
|
18160
18391
|
numeric({
|
|
18161
18392
|
id: "battery",
|
|
@@ -18190,7 +18421,7 @@ var GROUP_TEMPLATES = [
|
|
|
18190
18421
|
quantity: "device",
|
|
18191
18422
|
defaultAggregate: "mean",
|
|
18192
18423
|
empty: "null",
|
|
18193
|
-
companions: [NOW]
|
|
18424
|
+
companions: [NOW$2]
|
|
18194
18425
|
}),
|
|
18195
18426
|
binary({
|
|
18196
18427
|
id: "motion",
|
|
@@ -18284,6 +18515,11 @@ var GROUP_TEMPLATES = [
|
|
|
18284
18515
|
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.",
|
|
18285
18516
|
deviceType: DeviceType.Switch,
|
|
18286
18517
|
outputCap: "switch",
|
|
18518
|
+
outputField: "on",
|
|
18519
|
+
member: {
|
|
18520
|
+
cap: "switch",
|
|
18521
|
+
fieldPath: "on"
|
|
18522
|
+
},
|
|
18287
18523
|
commandCaps: ["switch"]
|
|
18288
18524
|
}),
|
|
18289
18525
|
actuator({
|
|
@@ -18291,34 +18527,136 @@ var GROUP_TEMPLATES = [
|
|
|
18291
18527
|
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.",
|
|
18292
18528
|
deviceType: DeviceType.Light,
|
|
18293
18529
|
outputCap: "switch",
|
|
18530
|
+
outputField: "on",
|
|
18531
|
+
member: {
|
|
18532
|
+
cap: "switch",
|
|
18533
|
+
fieldPath: "on"
|
|
18534
|
+
},
|
|
18294
18535
|
commandCaps: [
|
|
18295
18536
|
"switch",
|
|
18296
18537
|
"brightness",
|
|
18297
18538
|
"color"
|
|
18298
18539
|
]
|
|
18540
|
+
}),
|
|
18541
|
+
actuator({
|
|
18542
|
+
id: "fan",
|
|
18543
|
+
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.",
|
|
18544
|
+
deviceType: DeviceType.Fan,
|
|
18545
|
+
outputCap: "switch",
|
|
18546
|
+
outputField: "on",
|
|
18547
|
+
member: {
|
|
18548
|
+
cap: "switch",
|
|
18549
|
+
fieldPath: "on"
|
|
18550
|
+
},
|
|
18551
|
+
commandCaps: ["switch", "fan-control"]
|
|
18552
|
+
}),
|
|
18553
|
+
actuator({
|
|
18554
|
+
id: "cover",
|
|
18555
|
+
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.",
|
|
18556
|
+
deviceType: DeviceType.Cover,
|
|
18557
|
+
outputCap: "group-active",
|
|
18558
|
+
outputField: "active",
|
|
18559
|
+
member: {
|
|
18560
|
+
cap: "cover",
|
|
18561
|
+
fieldPath: "state"
|
|
18562
|
+
},
|
|
18563
|
+
activeWhen: [
|
|
18564
|
+
"open",
|
|
18565
|
+
"opening",
|
|
18566
|
+
"stopped"
|
|
18567
|
+
],
|
|
18568
|
+
commandCaps: ["cover"]
|
|
18569
|
+
}),
|
|
18570
|
+
actuator({
|
|
18571
|
+
id: "valve",
|
|
18572
|
+
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.",
|
|
18573
|
+
deviceType: DeviceType.Valve,
|
|
18574
|
+
outputCap: "group-active",
|
|
18575
|
+
outputField: "active",
|
|
18576
|
+
member: {
|
|
18577
|
+
cap: "valve",
|
|
18578
|
+
fieldPath: "state"
|
|
18579
|
+
},
|
|
18580
|
+
activeWhen: [
|
|
18581
|
+
"open",
|
|
18582
|
+
"opening",
|
|
18583
|
+
"stopped"
|
|
18584
|
+
],
|
|
18585
|
+
commandCaps: ["valve"]
|
|
18586
|
+
}),
|
|
18587
|
+
actuator({
|
|
18588
|
+
id: "lock",
|
|
18589
|
+
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.",
|
|
18590
|
+
deviceType: DeviceType.Lock,
|
|
18591
|
+
outputCap: "group-active",
|
|
18592
|
+
outputField: "active",
|
|
18593
|
+
member: {
|
|
18594
|
+
cap: "lock-control",
|
|
18595
|
+
fieldPath: "state"
|
|
18596
|
+
},
|
|
18597
|
+
activeWhen: ["locked"],
|
|
18598
|
+
commandCaps: ["lock-control"]
|
|
18599
|
+
}),
|
|
18600
|
+
actuator({
|
|
18601
|
+
id: "media-player",
|
|
18602
|
+
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.",
|
|
18603
|
+
deviceType: DeviceType.MediaPlayer,
|
|
18604
|
+
outputCap: "group-active",
|
|
18605
|
+
outputField: "active",
|
|
18606
|
+
member: {
|
|
18607
|
+
cap: "media-player",
|
|
18608
|
+
fieldPath: "state"
|
|
18609
|
+
},
|
|
18610
|
+
activeWhen: ["playing", "buffering"],
|
|
18611
|
+
commandCaps: ["media-player"]
|
|
18612
|
+
}),
|
|
18613
|
+
actuator({
|
|
18614
|
+
id: "climate",
|
|
18615
|
+
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.",
|
|
18616
|
+
deviceType: DeviceType.Thermostat,
|
|
18617
|
+
memberDeviceTypes: [DeviceType.Thermostat, DeviceType.Climate],
|
|
18618
|
+
outputCap: "group-active",
|
|
18619
|
+
outputField: "active",
|
|
18620
|
+
member: {
|
|
18621
|
+
cap: "climate-control",
|
|
18622
|
+
fieldPath: "mode"
|
|
18623
|
+
},
|
|
18624
|
+
activeWhen: [
|
|
18625
|
+
"heat",
|
|
18626
|
+
"cool",
|
|
18627
|
+
"auto",
|
|
18628
|
+
"heat_cool",
|
|
18629
|
+
"fan_only",
|
|
18630
|
+
"dry"
|
|
18631
|
+
],
|
|
18632
|
+
commandCaps: ["climate-control"]
|
|
18299
18633
|
})
|
|
18300
18634
|
];
|
|
18301
18635
|
function actuator(input) {
|
|
18302
18636
|
return {
|
|
18303
|
-
|
|
18637
|
+
id: input.id,
|
|
18638
|
+
summary: input.summary,
|
|
18639
|
+
deviceType: input.deviceType,
|
|
18640
|
+
outputCap: input.outputCap,
|
|
18641
|
+
outputField: input.outputField,
|
|
18642
|
+
commandCaps: input.commandCaps,
|
|
18304
18643
|
family: "actuator",
|
|
18305
18644
|
role: void 0,
|
|
18306
18645
|
memberDeviceType: input.deviceType,
|
|
18307
|
-
|
|
18646
|
+
memberDeviceTypes: input.memberDeviceTypes ?? [input.deviceType],
|
|
18647
|
+
activeWhen: input.activeWhen,
|
|
18308
18648
|
quantity: "none",
|
|
18309
18649
|
baseUnit: void 0,
|
|
18310
18650
|
aggregates: BINARY_AGGREGATES,
|
|
18311
18651
|
defaultAggregate: "any",
|
|
18312
18652
|
empty: "offline",
|
|
18313
|
-
accept: [
|
|
18314
|
-
cap: "switch",
|
|
18315
|
-
fieldPath: "on"
|
|
18316
|
-
}],
|
|
18653
|
+
accept: [input.member],
|
|
18317
18654
|
companions: [CHANGED]
|
|
18318
18655
|
};
|
|
18319
18656
|
}
|
|
18320
18657
|
new Map(GROUP_TEMPLATES.map((template) => [template.id, template]));
|
|
18321
18658
|
DeviceFeature.LightColorRgb, DeviceFeature.LightColorHsv, DeviceFeature.LightColorMired;
|
|
18659
|
+
DeviceType.Camera;
|
|
18322
18660
|
`${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
|
|
18323
18661
|
/**
|
|
18324
18662
|
* What a composition may BUILD on a device type (G2, D676): the caps a new
|
|
@@ -43333,7 +43671,7 @@ var NetworkAccessStatusSchema = object({
|
|
|
43333
43671
|
});
|
|
43334
43672
|
/**
|
|
43335
43673
|
* Optional, richer endpoint shape returned by providers that expose
|
|
43336
|
-
* MORE than one ingress concurrently (Tailscale
|
|
43674
|
+
* MORE than one ingress concurrently (Tailscale Funnel with mixed
|
|
43337
43675
|
* serve+funnel rules, future ngrok multi-tunnel, …). Each entry carries
|
|
43338
43676
|
* the originating provider config (mode + sourcePort) so the
|
|
43339
43677
|
* orchestrator UI can label rows distinctly. Providers that expose only
|
|
@@ -45976,7 +46314,20 @@ var NcRuleInputSchema = object({
|
|
|
45976
46314
|
* save by the hub's grouping guard). `.optional()`, never `.default()`: the addon cap
|
|
45977
46315
|
* path does not run Zod defaults.
|
|
45978
46316
|
*/
|
|
45979
|
-
groupingSec: number().int().min(5).max(60).optional()
|
|
46317
|
+
groupingSec: number().int().min(5).max(60).optional(),
|
|
46318
|
+
/**
|
|
46319
|
+
* ASK ME TO CONFIRM DETECTIONS (#243): a DETECTION notification of this rule
|
|
46320
|
+
* carries "Correct" / "Wrong" buttons (and, where the channel has room, a
|
|
46321
|
+
* "Wrong, it is a <class>" choice). A tap marks the track for retraining, the
|
|
46322
|
+
* same mark the Library writes, and records whose notification it was and
|
|
46323
|
+
* when. A channel with no buttons gets the same two choices as links.
|
|
46324
|
+
*
|
|
46325
|
+
* `.optional()`, never `.default()` (a Zod default does not run on the addon
|
|
46326
|
+
* cap path): absent and `false` both mean off, which is what every rule
|
|
46327
|
+
* authored before this field meant. An editor turns it off by writing
|
|
46328
|
+
* `false`, so it needs no `clear` key.
|
|
46329
|
+
*/
|
|
46330
|
+
askVerdict: boolean().optional()
|
|
45980
46331
|
});
|
|
45981
46332
|
/**
|
|
45982
46333
|
* Partial patch for `updateRule` — any subset of the input fields, plus the
|
|
@@ -56446,7 +56797,7 @@ var BatteryStatusSchema = object({
|
|
|
56446
56797
|
*/
|
|
56447
56798
|
binary: boolean().optional().meta({ label: "Binary indicator" })
|
|
56448
56799
|
});
|
|
56449
|
-
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat;
|
|
56800
|
+
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.EventEmitter;
|
|
56450
56801
|
method(object({
|
|
56451
56802
|
deviceId: number(),
|
|
56452
56803
|
/** Bound on the wait. Sensible range 3000–10000ms. */
|
|
@@ -58190,7 +58541,13 @@ results: array(object({
|
|
|
58190
58541
|
/** Ms epoch of the attempt. */
|
|
58191
58542
|
at: number()
|
|
58192
58543
|
})) });
|
|
58193
|
-
DeviceType.Switch, DeviceType.Light;
|
|
58544
|
+
DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Cover, DeviceType.Valve, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.Thermostat, DeviceType.Climate;
|
|
58545
|
+
object({
|
|
58546
|
+
active: boolean().meta({ label: "Active" }),
|
|
58547
|
+
/** Ms epoch when the slice was last updated. */
|
|
58548
|
+
lastChangedAt: number()
|
|
58549
|
+
});
|
|
58550
|
+
DeviceType.Cover, DeviceType.Valve, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.Climate, DeviceType.Thermostat;
|
|
58194
58551
|
object({
|
|
58195
58552
|
/** Members whose current value entered the aggregate. */
|
|
58196
58553
|
included: number().int().nonnegative().meta(readingMeta("count", {
|
|
@@ -58208,7 +58565,7 @@ object({
|
|
|
58208
58565
|
label: "Members"
|
|
58209
58566
|
}))
|
|
58210
58567
|
});
|
|
58211
|
-
DeviceType.Sensor, DeviceType.Switch, DeviceType.Light;
|
|
58568
|
+
DeviceType.Sensor, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Cover, DeviceType.Valve, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.Thermostat, DeviceType.Climate;
|
|
58212
58569
|
object({
|
|
58213
58570
|
/** Radiator valve opening 0 (closed) .. 100 (open). Null = not yet known. */
|
|
58214
58571
|
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
@@ -59115,7 +59472,14 @@ DeviceType.Lock, method(object({
|
|
|
59115
59472
|
auth: "protected"
|
|
59116
59473
|
}), method(object({
|
|
59117
59474
|
deviceId: number().int().nonnegative(),
|
|
59118
|
-
code: string().min(1).optional()
|
|
59475
|
+
code: string().min(1).optional(),
|
|
59476
|
+
/**
|
|
59477
|
+
* Honoured by a helper lock GROUP only (D944): unlocking several doors
|
|
59478
|
+
* with one call is refused unless the caller says it was confirmed. A
|
|
59479
|
+
* single lock ignores it. The refusal lives in the callee, so no
|
|
59480
|
+
* automation or API caller reaches the doors by skipping a dialog.
|
|
59481
|
+
*/
|
|
59482
|
+
confirm: boolean().optional()
|
|
59119
59483
|
}), _void(), {
|
|
59120
59484
|
kind: "mutation",
|
|
59121
59485
|
auth: "protected"
|
|
@@ -59123,6 +59487,11 @@ DeviceType.Lock, method(object({
|
|
|
59123
59487
|
kind: "mutation",
|
|
59124
59488
|
auth: "protected"
|
|
59125
59489
|
});
|
|
59490
|
+
object({
|
|
59491
|
+
value: number().nullable().meta(readingMeta("device", { label: "Total" })),
|
|
59492
|
+
lastFetchedAt: number()
|
|
59493
|
+
});
|
|
59494
|
+
DeviceType.Sensor;
|
|
59126
59495
|
/**
|
|
59127
59496
|
* Media-player cap. Models HA `media_player.*` (Sonos, Chromecast,
|
|
59128
59497
|
* Apple TV, Spotify, Roku, generic OTT receivers, …) on
|
|
@@ -61030,9 +61399,9 @@ object({
|
|
|
61030
61399
|
/** Cumulative energy in kilowatt-hours since the meter was reset. */
|
|
61031
61400
|
kwhTotal: number().optional().meta(readingMeta("energy", { label: "Energy" })),
|
|
61032
61401
|
/** Voltage in volts. */
|
|
61033
|
-
volts: number().optional().meta(readingMeta("voltage")),
|
|
61402
|
+
volts: number().optional().meta(readingMeta("voltage", { label: "Voltage" })),
|
|
61034
61403
|
/** Current in amperes. */
|
|
61035
|
-
amps: number().optional().meta(readingMeta("current")),
|
|
61404
|
+
amps: number().optional().meta(readingMeta("current", { label: "Current" })),
|
|
61036
61405
|
/** Apparent power in volt-amperes. */
|
|
61037
61406
|
va: number().optional().meta(readingMeta("apparent-power")),
|
|
61038
61407
|
/** Power factor (0..1) if reported. */
|
|
@@ -61040,7 +61409,23 @@ object({
|
|
|
61040
61409
|
/** Ms epoch when the slice was last updated. */
|
|
61041
61410
|
lastFetchedAt: number()
|
|
61042
61411
|
});
|
|
61043
|
-
|
|
61412
|
+
[
|
|
61413
|
+
DeviceType.Sensor,
|
|
61414
|
+
DeviceType.Switch,
|
|
61415
|
+
DeviceType.Light,
|
|
61416
|
+
DeviceType.Fan,
|
|
61417
|
+
DeviceType.Climate,
|
|
61418
|
+
DeviceType.Thermostat,
|
|
61419
|
+
DeviceType.Humidifier,
|
|
61420
|
+
DeviceType.WaterHeater,
|
|
61421
|
+
DeviceType.MediaPlayer,
|
|
61422
|
+
DeviceType.Washer,
|
|
61423
|
+
DeviceType.Dryer,
|
|
61424
|
+
DeviceType.Dishwasher,
|
|
61425
|
+
DeviceType.Vacuum,
|
|
61426
|
+
DeviceType.LawnMower,
|
|
61427
|
+
DeviceType.PetFeeder
|
|
61428
|
+
].filter((type) => type !== DeviceType.Sensor);
|
|
61044
61429
|
/**
|
|
61045
61430
|
* Presence cap. Models HA `person.*` and `device_tracker.*` entities
|
|
61046
61431
|
* on `DeviceType.Presence`. Read-only — no setters: presence is
|
|
@@ -61487,7 +61872,7 @@ object({
|
|
|
61487
61872
|
phase: string().nullable()
|
|
61488
61873
|
});
|
|
61489
61874
|
Object.values(DeviceType);
|
|
61490
|
-
DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
|
|
61875
|
+
DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
|
|
61491
61876
|
DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch, method(object({ deviceId: number().int().nonnegative() }), object({ success: literal(true) }), {
|
|
61492
61877
|
kind: "mutation",
|
|
61493
61878
|
auth: "admin"
|
|
@@ -63526,7 +63911,7 @@ object({
|
|
|
63526
63911
|
/** Ms epoch of the last state change. Useful for UI "X minutes ago". */
|
|
63527
63912
|
lastChangedAt: number()
|
|
63528
63913
|
});
|
|
63529
|
-
DeviceType.Switch, DeviceType.Siren, DeviceType.Light, method(object({
|
|
63914
|
+
DeviceType.Switch, DeviceType.Siren, DeviceType.Light, DeviceType.Fan, method(object({
|
|
63530
63915
|
deviceId: number(),
|
|
63531
63916
|
on: boolean()
|
|
63532
63917
|
}), _void(), {
|
|
@@ -65218,8 +65603,9 @@ method(object({}), array(TrainingBaseModelSchema).readonly(), { auth: "admin" })
|
|
|
65218
65603
|
kind: "mutation",
|
|
65219
65604
|
auth: "admin"
|
|
65220
65605
|
});
|
|
65606
|
+
DeviceFeature.FanSpeed, DeviceFeature.FanPreset, DeviceFeature.FanDirection, DeviceFeature.FanOscillating, DeviceFeature.CoverPositionable, DeviceFeature.CoverTilt, DeviceFeature.ValvePositionable, DeviceFeature.MediaPlayerVolume, DeviceFeature.ClimateFanMode;
|
|
65221
65607
|
SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
|
|
65222
|
-
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;
|
|
65608
|
+
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;
|
|
65223
65609
|
String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
|
|
65224
65610
|
DeviceRole.BinarySensor, DeviceRole.MotionSensor;
|
|
65225
65611
|
new Set(CAP_NAMES);
|
|
@@ -65272,7 +65658,7 @@ var AccessoryKind = {
|
|
|
65272
65658
|
PrivacyMask: DeviceRole.PrivacyMask
|
|
65273
65659
|
};
|
|
65274
65660
|
AccessoryKind.Siren, AccessoryKind.Floodlight, AccessoryKind.Spotlight, AccessoryKind.PirSensor, AccessoryKind.Chime, AccessoryKind.Autotrack, AccessoryKind.Nightvision, AccessoryKind.PrivacyMask;
|
|
65275
|
-
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;
|
|
65661
|
+
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;
|
|
65276
65662
|
new Set(Object.values(DeviceType));
|
|
65277
65663
|
Object.freeze({
|
|
65278
65664
|
"accessories.getStatus": {
|
|
@@ -68495,6 +68881,13 @@ Object.freeze({
|
|
|
68495
68881
|
access: "view",
|
|
68496
68882
|
role: "viewer"
|
|
68497
68883
|
},
|
|
68884
|
+
"groupActive.getStatus": {
|
|
68885
|
+
capName: "group-active",
|
|
68886
|
+
capScope: "device",
|
|
68887
|
+
addonId: null,
|
|
68888
|
+
access: "view",
|
|
68889
|
+
role: "viewer"
|
|
68890
|
+
},
|
|
68498
68891
|
"groupCommands.getStatus": {
|
|
68499
68892
|
capName: "group-commands",
|
|
68500
68893
|
capScope: "device",
|
|
@@ -69461,6 +69854,13 @@ Object.freeze({
|
|
|
69461
69854
|
access: "create",
|
|
69462
69855
|
role: "admin"
|
|
69463
69856
|
},
|
|
69857
|
+
"meter.getStatus": {
|
|
69858
|
+
capName: "meter",
|
|
69859
|
+
capScope: "device",
|
|
69860
|
+
addonId: null,
|
|
69861
|
+
access: "view",
|
|
69862
|
+
role: "viewer"
|
|
69863
|
+
},
|
|
69464
69864
|
"metricsProvider.collectSnapshot": {
|
|
69465
69865
|
capName: "metrics-provider",
|
|
69466
69866
|
capScope: "system",
|
|
@@ -77559,7 +77959,39 @@ var APPLIANCE_CAP_VOCABULARY = {
|
|
|
77559
77959
|
phrase: t("When {device} finishes", "Quando {device} finisce"),
|
|
77560
77960
|
icon: "square"
|
|
77561
77961
|
}
|
|
77562
|
-
}
|
|
77962
|
+
},
|
|
77963
|
+
overrides: { byType: {
|
|
77964
|
+
[DeviceType.Washer]: {
|
|
77965
|
+
state: { running: {
|
|
77966
|
+
whenTrue: t("When the washing machine starts", "Quando la lavatrice inizia"),
|
|
77967
|
+
whenFalse: t("When the washing machine has finished", "Quando la lavatrice ha finito")
|
|
77968
|
+
} },
|
|
77969
|
+
events: {
|
|
77970
|
+
onStarted: { phrase: t("When the washing machine starts", "Quando la lavatrice inizia") },
|
|
77971
|
+
onFinished: { phrase: t("When the washing machine has finished", "Quando la lavatrice ha finito") }
|
|
77972
|
+
}
|
|
77973
|
+
},
|
|
77974
|
+
[DeviceType.Dryer]: {
|
|
77975
|
+
state: { running: {
|
|
77976
|
+
whenTrue: t("When the dryer starts", "Quando l'asciugatrice inizia"),
|
|
77977
|
+
whenFalse: t("When the dryer has finished", "Quando l'asciugatrice ha finito")
|
|
77978
|
+
} },
|
|
77979
|
+
events: {
|
|
77980
|
+
onStarted: { phrase: t("When the dryer starts", "Quando l'asciugatrice inizia") },
|
|
77981
|
+
onFinished: { phrase: t("When the dryer has finished", "Quando l'asciugatrice ha finito") }
|
|
77982
|
+
}
|
|
77983
|
+
},
|
|
77984
|
+
[DeviceType.Dishwasher]: {
|
|
77985
|
+
state: { running: {
|
|
77986
|
+
whenTrue: t("When the dishwasher starts", "Quando la lavastoviglie inizia"),
|
|
77987
|
+
whenFalse: t("When the dishwasher has finished", "Quando la lavastoviglie ha finito")
|
|
77988
|
+
} },
|
|
77989
|
+
events: {
|
|
77990
|
+
onStarted: { phrase: t("When the dishwasher starts", "Quando la lavastoviglie inizia") },
|
|
77991
|
+
onFinished: { phrase: t("When the dishwasher has finished", "Quando la lavastoviglie ha finito") }
|
|
77992
|
+
}
|
|
77993
|
+
}
|
|
77994
|
+
} }
|
|
77563
77995
|
},
|
|
77564
77996
|
update: {
|
|
77565
77997
|
scope: "device",
|
|
@@ -78331,6 +78763,10 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78331
78763
|
icon: "flame"
|
|
78332
78764
|
}]
|
|
78333
78765
|
},
|
|
78766
|
+
"group-active": {
|
|
78767
|
+
scope: "device",
|
|
78768
|
+
noun: t("Group state", "Stato del gruppo")
|
|
78769
|
+
},
|
|
78334
78770
|
"group-commands": {
|
|
78335
78771
|
scope: "device",
|
|
78336
78772
|
noun: t("Group command", "Comando di gruppo")
|
|
@@ -78387,6 +78823,17 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78387
78823
|
}],
|
|
78388
78824
|
events: { onMotionChanged: { notOperatorFacing: "the `detected` state trigger phrases both edges, from the mirror that survives a dropped event (D49)" } }
|
|
78389
78825
|
},
|
|
78826
|
+
meter: {
|
|
78827
|
+
scope: "device",
|
|
78828
|
+
noun: t("Meter", "Contatore"),
|
|
78829
|
+
state: [{
|
|
78830
|
+
kind: "numeric",
|
|
78831
|
+
field: "value",
|
|
78832
|
+
quantity: t("the total", "il totale"),
|
|
78833
|
+
label: t("Total", "Totale"),
|
|
78834
|
+
icon: "gauge"
|
|
78835
|
+
}]
|
|
78836
|
+
},
|
|
78390
78837
|
"numeric-sensor": {
|
|
78391
78838
|
scope: "device",
|
|
78392
78839
|
noun: t("Sensor", "Sensore"),
|
|
@@ -78859,8 +79306,47 @@ function projectAction(cap, action) {
|
|
|
78859
79306
|
};
|
|
78860
79307
|
}
|
|
78861
79308
|
Object.entries(CAP_VOCABULARY_BY_NAME).flatMap(([cap, entry]) => entry.scope === "device" ? (entry.actions ?? []).map((a) => projectAction(cap, a)) : []);
|
|
78862
|
-
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;
|
|
79309
|
+
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;
|
|
78863
79310
|
DeviceFeature.BatteryOperated;
|
|
79311
|
+
DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher;
|
|
79312
|
+
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.";
|
|
79313
|
+
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.";
|
|
79314
|
+
var ALEXA_REASON = "Alexa has no laundry category in this export, and neither power nor running has an Alexa interface.";
|
|
79315
|
+
var GOOGLE_REASON = "Google WASHER, DRYER and DISHWASHER require RunCycle. A power threshold is not that trait, and this export does not publish RunCycle.";
|
|
79316
|
+
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.";
|
|
79317
|
+
function withheld(reason) {
|
|
79318
|
+
return {
|
|
79319
|
+
[DeviceType.Washer]: {
|
|
79320
|
+
exported: false,
|
|
79321
|
+
reason
|
|
79322
|
+
},
|
|
79323
|
+
[DeviceType.Dryer]: {
|
|
79324
|
+
exported: false,
|
|
79325
|
+
reason
|
|
79326
|
+
},
|
|
79327
|
+
[DeviceType.Dishwasher]: {
|
|
79328
|
+
exported: false,
|
|
79329
|
+
reason
|
|
79330
|
+
}
|
|
79331
|
+
};
|
|
79332
|
+
}
|
|
79333
|
+
function offered(received) {
|
|
79334
|
+
return {
|
|
79335
|
+
[DeviceType.Washer]: {
|
|
79336
|
+
exported: true,
|
|
79337
|
+
as: received
|
|
79338
|
+
},
|
|
79339
|
+
[DeviceType.Dryer]: {
|
|
79340
|
+
exported: true,
|
|
79341
|
+
as: received
|
|
79342
|
+
},
|
|
79343
|
+
[DeviceType.Dishwasher]: {
|
|
79344
|
+
exported: true,
|
|
79345
|
+
as: received
|
|
79346
|
+
}
|
|
79347
|
+
};
|
|
79348
|
+
}
|
|
79349
|
+
offered(HA_AS), withheld(HOMEKIT_REASON), withheld(ALEXA_REASON), withheld(GOOGLE_REASON), withheld(MATTER_REASON);
|
|
78864
79350
|
Object.freeze({
|
|
78865
79351
|
"accessories.getStatus": [{
|
|
78866
79352
|
name: "deviceId",
|
|
@@ -79827,6 +80313,11 @@ Object.freeze({
|
|
|
79827
80313
|
form: "single",
|
|
79828
80314
|
optional: false
|
|
79829
80315
|
}],
|
|
80316
|
+
"groupActive.getStatus": [{
|
|
80317
|
+
name: "deviceId",
|
|
80318
|
+
form: "single",
|
|
80319
|
+
optional: false
|
|
80320
|
+
}],
|
|
79830
80321
|
"groupCommands.getStatus": [{
|
|
79831
80322
|
name: "deviceId",
|
|
79832
80323
|
form: "single",
|
|
@@ -80037,6 +80528,11 @@ Object.freeze({
|
|
|
80037
80528
|
form: "single",
|
|
80038
80529
|
optional: false
|
|
80039
80530
|
}],
|
|
80531
|
+
"meter.getStatus": [{
|
|
80532
|
+
name: "deviceId",
|
|
80533
|
+
form: "single",
|
|
80534
|
+
optional: false
|
|
80535
|
+
}],
|
|
80040
80536
|
"motion.getStatus": [{
|
|
80041
80537
|
name: "deviceId",
|
|
80042
80538
|
form: "single",
|
|
@@ -81644,7 +82140,6 @@ Object.freeze({
|
|
|
81644
82140
|
"network-access": "ingress",
|
|
81645
82141
|
"smtp-provider": "email"
|
|
81646
82142
|
});
|
|
81647
|
-
DeviceType.Camera;
|
|
81648
82143
|
/**
|
|
81649
82144
|
* A saved Customize assignment (D936). The schema is the type: callers use
|
|
81650
82145
|
* `z.infer`, they do not restate the shape.
|