@camstack/addon-waste-collections 0.1.30 → 0.1.31
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 +18 -9
- package/dist/waste-collections.addon.js +540 -45
- package/dist/waste-collections.addon.mjs +540 -45
- package/package.json +3 -3
|
@@ -5578,7 +5578,7 @@ var ZodIssueCode = {
|
|
|
5578
5578
|
var ZodFirstPartyTypeKind;
|
|
5579
5579
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5580
5580
|
//#endregion
|
|
5581
|
-
//#region ../types/dist/sleep
|
|
5581
|
+
//#region ../types/dist/sleep--jXS9hWo.mjs
|
|
5582
5582
|
/**
|
|
5583
5583
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5584
5584
|
* window to float samples (D455).
|
|
@@ -8987,6 +8987,7 @@ var CAP_NAMES = Object.freeze([
|
|
|
8987
8987
|
"filesystem-browse",
|
|
8988
8988
|
"flood",
|
|
8989
8989
|
"gas",
|
|
8990
|
+
"group-active",
|
|
8990
8991
|
"group-commands",
|
|
8991
8992
|
"group-status",
|
|
8992
8993
|
"heating-valve",
|
|
@@ -9009,6 +9010,7 @@ var CAP_NAMES = Object.freeze([
|
|
|
9009
9010
|
"login-method",
|
|
9010
9011
|
"media-player",
|
|
9011
9012
|
"mesh-network",
|
|
9013
|
+
"meter",
|
|
9012
9014
|
"metrics-provider",
|
|
9013
9015
|
"model-convert",
|
|
9014
9016
|
"model-distributor",
|
|
@@ -9807,6 +9809,10 @@ Object.freeze({
|
|
|
9807
9809
|
"path": "detected",
|
|
9808
9810
|
"valueType": "boolean"
|
|
9809
9811
|
}],
|
|
9812
|
+
"group-active": [{
|
|
9813
|
+
"path": "active",
|
|
9814
|
+
"valueType": "boolean"
|
|
9815
|
+
}],
|
|
9810
9816
|
"group-status": [
|
|
9811
9817
|
{
|
|
9812
9818
|
"path": "included",
|
|
@@ -10066,6 +10072,10 @@ Object.freeze({
|
|
|
10066
10072
|
]
|
|
10067
10073
|
}
|
|
10068
10074
|
],
|
|
10075
|
+
"meter": [{
|
|
10076
|
+
"path": "value",
|
|
10077
|
+
"valueType": "number"
|
|
10078
|
+
}],
|
|
10069
10079
|
"motion": [
|
|
10070
10080
|
{
|
|
10071
10081
|
"path": "detected",
|
|
@@ -10809,7 +10819,7 @@ object({
|
|
|
10809
10819
|
params: record(string(), union([string(), number()])).optional()
|
|
10810
10820
|
});
|
|
10811
10821
|
//#endregion
|
|
10812
|
-
//#region ../types/dist/err-msg-
|
|
10822
|
+
//#region ../types/dist/err-msg-DIorGYeC.mjs
|
|
10813
10823
|
var DeviceType = /* @__PURE__ */ function(DeviceType) {
|
|
10814
10824
|
DeviceType["Camera"] = "camera";
|
|
10815
10825
|
DeviceType["Hub"] = "hub";
|
|
@@ -10903,8 +10913,14 @@ var DeviceType = /* @__PURE__ */ function(DeviceType) {
|
|
|
10903
10913
|
DeviceType["PetFeeder"] = "pet-feeder";
|
|
10904
10914
|
/** Built-in dishwasher — program lifecycle, door / remote-start gates,
|
|
10905
10915
|
* salt and rinse-aid levels. Installed with the `dishwasher` cap.
|
|
10906
|
-
* Sources: native Bosch Home Connect, reusable by similar integrations.
|
|
10916
|
+
* Sources: native Bosch Home Connect, reusable by similar integrations.
|
|
10917
|
+
* A plug-built dishwasher carries running-state and power instead. */
|
|
10907
10918
|
DeviceType["Dishwasher"] = "dishwasher";
|
|
10919
|
+
/** Washing machine. A plug-built one is running while its power stays
|
|
10920
|
+
* above a threshold. No program cap — that surface is the dishwasher's. */
|
|
10921
|
+
DeviceType["Washer"] = "washer";
|
|
10922
|
+
/** Tumble dryer. Same plug-built running surface as {@link Washer}. */
|
|
10923
|
+
DeviceType["Dryer"] = "dryer";
|
|
10908
10924
|
return DeviceType;
|
|
10909
10925
|
}({});
|
|
10910
10926
|
var DeviceFeature = /* @__PURE__ */ function(DeviceFeature) {
|
|
@@ -11152,7 +11168,7 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
|
|
|
11152
11168
|
return DeviceRole;
|
|
11153
11169
|
}({});
|
|
11154
11170
|
//#endregion
|
|
11155
|
-
//#region ../types/dist/composition-
|
|
11171
|
+
//#region ../types/dist/composition-Bb8iwHEJ.mjs
|
|
11156
11172
|
/**
|
|
11157
11173
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
11158
11174
|
*
|
|
@@ -11467,6 +11483,13 @@ var table = {
|
|
|
11467
11483
|
apply: () => {
|
|
11468
11484
|
throw new ExpressionEvalError("latchedAt: stateful evaluation context is required");
|
|
11469
11485
|
}
|
|
11486
|
+
},
|
|
11487
|
+
schmitt: {
|
|
11488
|
+
minArgs: 3,
|
|
11489
|
+
maxArgs: 5,
|
|
11490
|
+
apply: () => {
|
|
11491
|
+
throw new ExpressionEvalError("schmitt: stateful evaluation context is required");
|
|
11492
|
+
}
|
|
11470
11493
|
}
|
|
11471
11494
|
};
|
|
11472
11495
|
Object.freeze(Object.assign(Object.create(null), table));
|
|
@@ -11908,6 +11931,99 @@ function validateExpressionSource(src) {
|
|
|
11908
11931
|
return null;
|
|
11909
11932
|
}
|
|
11910
11933
|
/**
|
|
11934
|
+
* One power reading becomes a washer, dryer or dishwasher (D944 helper).
|
|
11935
|
+
*
|
|
11936
|
+
* Standby of the control board is under 5 W; a motor or a heater is far
|
|
11937
|
+
* above that, so 5 W is the line. A door lock or a short pump spike is not
|
|
11938
|
+
* a cycle, so running starts only after 30 s above the line.
|
|
11939
|
+
*
|
|
11940
|
+
* A wash, dry or dishwasher pause (soak, heat-wait, heater off between
|
|
11941
|
+
* bursts) lasts several minutes. Ending the cycle on the first dip would
|
|
11942
|
+
* report "finished" in the middle of the program, so the stop dwell is
|
|
11943
|
+
* 10 minutes on every type. The number is stored per type so one machine
|
|
11944
|
+
* can move later without moving the others.
|
|
11945
|
+
*/
|
|
11946
|
+
var APPLIANCE_TEMPLATE_ID = "appliance";
|
|
11947
|
+
var APPLIANCE_KINDS = [
|
|
11948
|
+
"washer",
|
|
11949
|
+
"dryer",
|
|
11950
|
+
"dishwasher"
|
|
11951
|
+
];
|
|
11952
|
+
DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher;
|
|
11953
|
+
/**
|
|
11954
|
+
* Statistics and integrals over a history read (D944).
|
|
11955
|
+
*
|
|
11956
|
+
* Pure: the same points always give the same answer, so a restart recomputes
|
|
11957
|
+
* rather than trusting a buffer. A gauge mean is time-weighted (value × ms),
|
|
11958
|
+
* never the mean of the samples. A hole with no held value is not integrated
|
|
11959
|
+
* as zero. A truncated read is not published.
|
|
11960
|
+
*/
|
|
11961
|
+
var STATISTIC_STATS = [
|
|
11962
|
+
"min",
|
|
11963
|
+
"max",
|
|
11964
|
+
"mean",
|
|
11965
|
+
"sum",
|
|
11966
|
+
"count",
|
|
11967
|
+
"change"
|
|
11968
|
+
];
|
|
11969
|
+
/**
|
|
11970
|
+
* The range a statistics or integral helper asks history for (D944).
|
|
11971
|
+
*
|
|
11972
|
+
* Calendar edges are the hub's timezone, never UTC midnight: a day is 23, 24
|
|
11973
|
+
* or 25 hours across a DST change. A tier is eligible only when its retention
|
|
11974
|
+
* is strictly longer than the longest that range can be. Forever qualifies.
|
|
11975
|
+
* Equal to a tier's retention is a refusal, not a short answer.
|
|
11976
|
+
*/
|
|
11977
|
+
var MINUTE_MS = 6e4;
|
|
11978
|
+
var HOUR_MS = 60 * MINUTE_MS;
|
|
11979
|
+
var DAY_MS$1 = 24 * HOUR_MS;
|
|
11980
|
+
var ROLLING_SPANS = [
|
|
11981
|
+
"1h",
|
|
11982
|
+
"24h",
|
|
11983
|
+
"2d",
|
|
11984
|
+
"7d",
|
|
11985
|
+
"30d",
|
|
11986
|
+
"custom"
|
|
11987
|
+
];
|
|
11988
|
+
var CALENDAR_PERIODS = [
|
|
11989
|
+
"today",
|
|
11990
|
+
"yesterday",
|
|
11991
|
+
"this-week",
|
|
11992
|
+
"this-month"
|
|
11993
|
+
];
|
|
11994
|
+
var RESET_PERIODS = [
|
|
11995
|
+
"never",
|
|
11996
|
+
"daily",
|
|
11997
|
+
"weekly",
|
|
11998
|
+
"monthly"
|
|
11999
|
+
];
|
|
12000
|
+
5 * MINUTE_MS;
|
|
12001
|
+
24 * HOUR_MS, 2 * DAY_MS$1, 7 * DAY_MS$1, 30 * DAY_MS$1;
|
|
12002
|
+
7 * DAY_MS$1, 30 * DAY_MS$1, 365 * DAY_MS$1;
|
|
12003
|
+
var rollingWindowObject = object({
|
|
12004
|
+
kind: literal("rolling"),
|
|
12005
|
+
span: _enum(ROLLING_SPANS),
|
|
12006
|
+
customMinutes: number().int().min(5).optional()
|
|
12007
|
+
}).check((payload) => {
|
|
12008
|
+
if (payload.value.span === "custom" && payload.value.customMinutes === void 0) payload.issues.push({
|
|
12009
|
+
code: "custom",
|
|
12010
|
+
message: "a custom range needs a duration in minutes",
|
|
12011
|
+
path: ["customMinutes"],
|
|
12012
|
+
input: payload.value
|
|
12013
|
+
});
|
|
12014
|
+
if (payload.value.span !== "custom" && payload.value.customMinutes !== void 0) payload.issues.push({
|
|
12015
|
+
code: "custom",
|
|
12016
|
+
message: "only a custom range carries a duration",
|
|
12017
|
+
path: ["customMinutes"],
|
|
12018
|
+
input: payload.value
|
|
12019
|
+
});
|
|
12020
|
+
});
|
|
12021
|
+
var RollingWindowSchema = rollingWindowObject;
|
|
12022
|
+
var StatisticWindowSchema = discriminatedUnion("kind", [rollingWindowObject, object({
|
|
12023
|
+
kind: literal("calendar"),
|
|
12024
|
+
period: _enum(CALENDAR_PERIODS)
|
|
12025
|
+
})]);
|
|
12026
|
+
/**
|
|
11911
12027
|
* A composition source identity: `(addonId, stableId)`, never a numeric device
|
|
11912
12028
|
* id. Split out so helper schemas can name it without a cycle through
|
|
11913
12029
|
* `composition.ts` (D659).
|
|
@@ -11933,7 +12049,13 @@ var GROUP_TEMPLATE_IDS = [
|
|
|
11933
12049
|
"occupancy",
|
|
11934
12050
|
"binary",
|
|
11935
12051
|
"switch",
|
|
11936
|
-
"light"
|
|
12052
|
+
"light",
|
|
12053
|
+
"fan",
|
|
12054
|
+
"cover",
|
|
12055
|
+
"valve",
|
|
12056
|
+
"lock",
|
|
12057
|
+
"media-player",
|
|
12058
|
+
"climate"
|
|
11937
12059
|
];
|
|
11938
12060
|
var NUMERIC_AGGREGATES = [
|
|
11939
12061
|
"mean",
|
|
@@ -11963,14 +12085,73 @@ var HelperMemberSchema = object({
|
|
|
11963
12085
|
cap: string().min(1),
|
|
11964
12086
|
fieldPath: string().min(1)
|
|
11965
12087
|
});
|
|
11966
|
-
var HelperSpecSchema = discriminatedUnion("kind", [
|
|
11967
|
-
|
|
11968
|
-
|
|
11969
|
-
|
|
11970
|
-
|
|
11971
|
-
|
|
11972
|
-
|
|
11973
|
-
|
|
12088
|
+
var HelperSpecSchema = discriminatedUnion("kind", [
|
|
12089
|
+
object({
|
|
12090
|
+
kind: literal("group"),
|
|
12091
|
+
templateId: GroupTemplateIdSchema,
|
|
12092
|
+
aggregate: AggregateReducerSchema,
|
|
12093
|
+
members: array(HelperMemberSchema).min(1).max(64),
|
|
12094
|
+
/** Actuator groups only. Readings leave this unset. */
|
|
12095
|
+
active: ActiveCriterionSchema.optional()
|
|
12096
|
+
}),
|
|
12097
|
+
object({
|
|
12098
|
+
kind: literal("appliance"),
|
|
12099
|
+
templateId: literal(APPLIANCE_TEMPLATE_ID),
|
|
12100
|
+
appliance: _enum(APPLIANCE_KINDS),
|
|
12101
|
+
thresholdWatts: number().positive(),
|
|
12102
|
+
startDwellMs: number().int().nonnegative(),
|
|
12103
|
+
stopDwellMs: number().int().nonnegative(),
|
|
12104
|
+
member: HelperMemberSchema
|
|
12105
|
+
}),
|
|
12106
|
+
object({
|
|
12107
|
+
kind: literal("statistic"),
|
|
12108
|
+
stat: _enum(STATISTIC_STATS),
|
|
12109
|
+
window: StatisticWindowSchema,
|
|
12110
|
+
source: HelperMemberSchema
|
|
12111
|
+
}),
|
|
12112
|
+
object({
|
|
12113
|
+
kind: literal("integral"),
|
|
12114
|
+
reset: _enum(RESET_PERIODS),
|
|
12115
|
+
output: _enum(["energy", "meter"]),
|
|
12116
|
+
source: HelperMemberSchema
|
|
12117
|
+
}),
|
|
12118
|
+
object({
|
|
12119
|
+
kind: literal("threshold"),
|
|
12120
|
+
source: HelperMemberSchema,
|
|
12121
|
+
high: number(),
|
|
12122
|
+
low: number(),
|
|
12123
|
+
onForMs: number().int().nonnegative(),
|
|
12124
|
+
offForMs: number().int().nonnegative()
|
|
12125
|
+
}),
|
|
12126
|
+
object({
|
|
12127
|
+
kind: literal("arithmetic"),
|
|
12128
|
+
op: _enum([
|
|
12129
|
+
"sum",
|
|
12130
|
+
"difference",
|
|
12131
|
+
"ratio"
|
|
12132
|
+
]),
|
|
12133
|
+
inputs: array(HelperMemberSchema).min(2).max(64)
|
|
12134
|
+
}),
|
|
12135
|
+
object({
|
|
12136
|
+
kind: literal("expression"),
|
|
12137
|
+
expr: string().min(1),
|
|
12138
|
+
inputs: array(object({
|
|
12139
|
+
name: string().min(1),
|
|
12140
|
+
member: HelperMemberSchema
|
|
12141
|
+
})).min(1).max(64),
|
|
12142
|
+
output: _enum(["number", "boolean"])
|
|
12143
|
+
}),
|
|
12144
|
+
object({
|
|
12145
|
+
kind: literal("derivative"),
|
|
12146
|
+
window: RollingWindowSchema,
|
|
12147
|
+
per: _enum([
|
|
12148
|
+
"second",
|
|
12149
|
+
"minute",
|
|
12150
|
+
"hour"
|
|
12151
|
+
]),
|
|
12152
|
+
source: HelperMemberSchema
|
|
12153
|
+
})
|
|
12154
|
+
]);
|
|
11974
12155
|
/** A composed device's stableId is this prefix plus the block id. */
|
|
11975
12156
|
var COMPOSED_DEVICE_STABLE_ID_PREFIX = "composed-";
|
|
11976
12157
|
/** Longest snippet a `code` source may carry (slice 4). */
|
|
@@ -12031,6 +12212,12 @@ var CompositionFieldSourceSchema = discriminatedUnion("kind", [
|
|
|
12031
12212
|
"all"
|
|
12032
12213
|
]),
|
|
12033
12214
|
reads: array(CompositionFieldReadSchema).min(1).max(64),
|
|
12215
|
+
/**
|
|
12216
|
+
* Set when the reads are an enum state, not a yes/no: the listed states
|
|
12217
|
+
* count as active (a cover is `open`). A state outside the list is inactive;
|
|
12218
|
+
* a read that is not a state at all is left out. Only `any` / `all` use it.
|
|
12219
|
+
*/
|
|
12220
|
+
activeWhen: array(string().min(1)).min(1).optional(),
|
|
12034
12221
|
/** `value` is the reading; the others are the member counts. */
|
|
12035
12222
|
publish: _enum([
|
|
12036
12223
|
"value",
|
|
@@ -12044,6 +12231,26 @@ var CompositionFieldSourceSchema = discriminatedUnion("kind", [
|
|
|
12044
12231
|
"omit",
|
|
12045
12232
|
"offline"
|
|
12046
12233
|
])
|
|
12234
|
+
}),
|
|
12235
|
+
object({
|
|
12236
|
+
kind: literal("series"),
|
|
12237
|
+
read: CompositionFieldReadSchema,
|
|
12238
|
+
/** `value` is the statistic or the integral. The others are the gap counts. */
|
|
12239
|
+
publish: _enum([
|
|
12240
|
+
"value",
|
|
12241
|
+
"included",
|
|
12242
|
+
"excluded",
|
|
12243
|
+
"total"
|
|
12244
|
+
]),
|
|
12245
|
+
/**
|
|
12246
|
+
* What an unanswered `value` does. Counts ignore this. `offline` leaves the
|
|
12247
|
+
* device unseeded until history answers, so a restart cannot publish 0.
|
|
12248
|
+
*/
|
|
12249
|
+
empty: _enum([
|
|
12250
|
+
"null",
|
|
12251
|
+
"omit",
|
|
12252
|
+
"offline"
|
|
12253
|
+
])
|
|
12047
12254
|
})
|
|
12048
12255
|
]);
|
|
12049
12256
|
var CompositionCommandTargetSchema = discriminatedUnion("kind", [object({
|
|
@@ -17203,7 +17410,22 @@ var BrokerProviderInfoSchema = object({
|
|
|
17203
17410
|
*/
|
|
17204
17411
|
interactiveConnectPath: string().min(1).optional(),
|
|
17205
17412
|
/** Relative hub path to disconnect the linked account (same popup pattern). */
|
|
17206
|
-
interactiveDisconnectPath: string().min(1).optional()
|
|
17413
|
+
interactiveDisconnectPath: string().min(1).optional(),
|
|
17414
|
+
/**
|
|
17415
|
+
* The kind signs in through a server-held interactive session instead of
|
|
17416
|
+
* (or before) typed credentials. `basePath` is a hub-relative route set
|
|
17417
|
+
* served by the owning addon (`/addon/<id>/...`) speaking the sign-in
|
|
17418
|
+
* contract: `POST {basePath}/start` (body: the form's settings) answers
|
|
17419
|
+
* `{ sessionId, loginUrl }`; `GET {basePath}/status?sessionId=` answers
|
|
17420
|
+
* `{ phase: 'starting' | 'awaiting-login' | 'captured' | 'error' |
|
|
17421
|
+
* 'cancelled', loginUrl, error }`; `POST {basePath}/commit`
|
|
17422
|
+
* (`{ sessionId, name, brokerId? }`) stores the credentials on a new or
|
|
17423
|
+
* existing broker and answers `{ brokerId }`; `POST {basePath}/cancel`
|
|
17424
|
+
* (`{ sessionId }`) drops the session. The dialog that edits a broker
|
|
17425
|
+
* offers it as the default path; the fields the session fills are
|
|
17426
|
+
* marked `filledBySignIn` in the kind's settings schema.
|
|
17427
|
+
*/
|
|
17428
|
+
signIn: object({ basePath: string().min(1) }).optional()
|
|
17207
17429
|
}))
|
|
17208
17430
|
});
|
|
17209
17431
|
var ListInputSchema = object({
|
|
@@ -18202,7 +18424,8 @@ var CompositionProblemSchema = object({
|
|
|
18202
18424
|
"native-capability-replace",
|
|
18203
18425
|
"mixed-quantity",
|
|
18204
18426
|
"helper-mismatch",
|
|
18205
|
-
"member-constraint"
|
|
18427
|
+
"member-constraint",
|
|
18428
|
+
"retention"
|
|
18206
18429
|
]),
|
|
18207
18430
|
path: string(),
|
|
18208
18431
|
message: string()
|
|
@@ -18436,13 +18659,17 @@ Object.freeze({
|
|
|
18436
18659
|
latchedAt: {
|
|
18437
18660
|
kind: "fixed",
|
|
18438
18661
|
result: ["number", "null"]
|
|
18662
|
+
},
|
|
18663
|
+
schmitt: {
|
|
18664
|
+
kind: "fixed",
|
|
18665
|
+
result: ["boolean", "null"]
|
|
18439
18666
|
}
|
|
18440
18667
|
});
|
|
18441
18668
|
/**
|
|
18442
18669
|
* One catalog row per base reading a group helper can build (D944 §3).
|
|
18443
18670
|
* Data, not a form default written into the block.
|
|
18444
18671
|
*/
|
|
18445
|
-
var NOW = {
|
|
18672
|
+
var NOW$2 = {
|
|
18446
18673
|
fieldPath: "lastFetchedAt",
|
|
18447
18674
|
expr: "now"
|
|
18448
18675
|
};
|
|
@@ -18456,6 +18683,8 @@ function numeric(input) {
|
|
|
18456
18683
|
family: "numeric",
|
|
18457
18684
|
deviceType: DeviceType.Sensor,
|
|
18458
18685
|
memberDeviceType: DeviceType.Sensor,
|
|
18686
|
+
memberDeviceTypes: [DeviceType.Sensor],
|
|
18687
|
+
activeWhen: void 0,
|
|
18459
18688
|
commandCaps: [],
|
|
18460
18689
|
baseUnit: baseUnitOf(input.quantity),
|
|
18461
18690
|
aggregates: NUMERIC_AGGREGATES,
|
|
@@ -18471,6 +18700,8 @@ function binary(input) {
|
|
|
18471
18700
|
family: "binary",
|
|
18472
18701
|
deviceType: DeviceType.Sensor,
|
|
18473
18702
|
memberDeviceType: DeviceType.Sensor,
|
|
18703
|
+
memberDeviceTypes: [DeviceType.Sensor],
|
|
18704
|
+
activeWhen: void 0,
|
|
18474
18705
|
commandCaps: [],
|
|
18475
18706
|
quantity: "none",
|
|
18476
18707
|
baseUnit: void 0,
|
|
@@ -18488,7 +18719,7 @@ var GROUP_TEMPLATES = [
|
|
|
18488
18719
|
quantity: "temperature",
|
|
18489
18720
|
defaultAggregate: "mean",
|
|
18490
18721
|
empty: "null",
|
|
18491
|
-
companions: [NOW]
|
|
18722
|
+
companions: [NOW$2]
|
|
18492
18723
|
}),
|
|
18493
18724
|
numeric({
|
|
18494
18725
|
id: "humidity",
|
|
@@ -18499,7 +18730,7 @@ var GROUP_TEMPLATES = [
|
|
|
18499
18730
|
quantity: "humidity",
|
|
18500
18731
|
defaultAggregate: "mean",
|
|
18501
18732
|
empty: "null",
|
|
18502
|
-
companions: [NOW]
|
|
18733
|
+
companions: [NOW$2]
|
|
18503
18734
|
}),
|
|
18504
18735
|
numeric({
|
|
18505
18736
|
id: "pressure",
|
|
@@ -18510,7 +18741,7 @@ var GROUP_TEMPLATES = [
|
|
|
18510
18741
|
quantity: "pressure",
|
|
18511
18742
|
defaultAggregate: "mean",
|
|
18512
18743
|
empty: "null",
|
|
18513
|
-
companions: [NOW]
|
|
18744
|
+
companions: [NOW$2]
|
|
18514
18745
|
}),
|
|
18515
18746
|
numeric({
|
|
18516
18747
|
id: "illuminance",
|
|
@@ -18521,7 +18752,7 @@ var GROUP_TEMPLATES = [
|
|
|
18521
18752
|
quantity: "illuminance",
|
|
18522
18753
|
defaultAggregate: "mean",
|
|
18523
18754
|
empty: "null",
|
|
18524
|
-
companions: [NOW]
|
|
18755
|
+
companions: [NOW$2]
|
|
18525
18756
|
}),
|
|
18526
18757
|
numeric({
|
|
18527
18758
|
id: "power",
|
|
@@ -18532,7 +18763,7 @@ var GROUP_TEMPLATES = [
|
|
|
18532
18763
|
quantity: "power",
|
|
18533
18764
|
defaultAggregate: "sum",
|
|
18534
18765
|
empty: "omit",
|
|
18535
|
-
companions: [NOW]
|
|
18766
|
+
companions: [NOW$2]
|
|
18536
18767
|
}),
|
|
18537
18768
|
numeric({
|
|
18538
18769
|
id: "energy",
|
|
@@ -18543,7 +18774,7 @@ var GROUP_TEMPLATES = [
|
|
|
18543
18774
|
quantity: "energy",
|
|
18544
18775
|
defaultAggregate: "sum",
|
|
18545
18776
|
empty: "omit",
|
|
18546
|
-
companions: [NOW]
|
|
18777
|
+
companions: [NOW$2]
|
|
18547
18778
|
}),
|
|
18548
18779
|
numeric({
|
|
18549
18780
|
id: "battery",
|
|
@@ -18578,7 +18809,7 @@ var GROUP_TEMPLATES = [
|
|
|
18578
18809
|
quantity: "device",
|
|
18579
18810
|
defaultAggregate: "mean",
|
|
18580
18811
|
empty: "null",
|
|
18581
|
-
companions: [NOW]
|
|
18812
|
+
companions: [NOW$2]
|
|
18582
18813
|
}),
|
|
18583
18814
|
binary({
|
|
18584
18815
|
id: "motion",
|
|
@@ -18672,6 +18903,11 @@ var GROUP_TEMPLATES = [
|
|
|
18672
18903
|
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.",
|
|
18673
18904
|
deviceType: DeviceType.Switch,
|
|
18674
18905
|
outputCap: "switch",
|
|
18906
|
+
outputField: "on",
|
|
18907
|
+
member: {
|
|
18908
|
+
cap: "switch",
|
|
18909
|
+
fieldPath: "on"
|
|
18910
|
+
},
|
|
18675
18911
|
commandCaps: ["switch"]
|
|
18676
18912
|
}),
|
|
18677
18913
|
actuator({
|
|
@@ -18679,34 +18915,136 @@ var GROUP_TEMPLATES = [
|
|
|
18679
18915
|
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.",
|
|
18680
18916
|
deviceType: DeviceType.Light,
|
|
18681
18917
|
outputCap: "switch",
|
|
18918
|
+
outputField: "on",
|
|
18919
|
+
member: {
|
|
18920
|
+
cap: "switch",
|
|
18921
|
+
fieldPath: "on"
|
|
18922
|
+
},
|
|
18682
18923
|
commandCaps: [
|
|
18683
18924
|
"switch",
|
|
18684
18925
|
"brightness",
|
|
18685
18926
|
"color"
|
|
18686
18927
|
]
|
|
18928
|
+
}),
|
|
18929
|
+
actuator({
|
|
18930
|
+
id: "fan",
|
|
18931
|
+
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.",
|
|
18932
|
+
deviceType: DeviceType.Fan,
|
|
18933
|
+
outputCap: "switch",
|
|
18934
|
+
outputField: "on",
|
|
18935
|
+
member: {
|
|
18936
|
+
cap: "switch",
|
|
18937
|
+
fieldPath: "on"
|
|
18938
|
+
},
|
|
18939
|
+
commandCaps: ["switch", "fan-control"]
|
|
18940
|
+
}),
|
|
18941
|
+
actuator({
|
|
18942
|
+
id: "cover",
|
|
18943
|
+
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.",
|
|
18944
|
+
deviceType: DeviceType.Cover,
|
|
18945
|
+
outputCap: "group-active",
|
|
18946
|
+
outputField: "active",
|
|
18947
|
+
member: {
|
|
18948
|
+
cap: "cover",
|
|
18949
|
+
fieldPath: "state"
|
|
18950
|
+
},
|
|
18951
|
+
activeWhen: [
|
|
18952
|
+
"open",
|
|
18953
|
+
"opening",
|
|
18954
|
+
"stopped"
|
|
18955
|
+
],
|
|
18956
|
+
commandCaps: ["cover"]
|
|
18957
|
+
}),
|
|
18958
|
+
actuator({
|
|
18959
|
+
id: "valve",
|
|
18960
|
+
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.",
|
|
18961
|
+
deviceType: DeviceType.Valve,
|
|
18962
|
+
outputCap: "group-active",
|
|
18963
|
+
outputField: "active",
|
|
18964
|
+
member: {
|
|
18965
|
+
cap: "valve",
|
|
18966
|
+
fieldPath: "state"
|
|
18967
|
+
},
|
|
18968
|
+
activeWhen: [
|
|
18969
|
+
"open",
|
|
18970
|
+
"opening",
|
|
18971
|
+
"stopped"
|
|
18972
|
+
],
|
|
18973
|
+
commandCaps: ["valve"]
|
|
18974
|
+
}),
|
|
18975
|
+
actuator({
|
|
18976
|
+
id: "lock",
|
|
18977
|
+
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.",
|
|
18978
|
+
deviceType: DeviceType.Lock,
|
|
18979
|
+
outputCap: "group-active",
|
|
18980
|
+
outputField: "active",
|
|
18981
|
+
member: {
|
|
18982
|
+
cap: "lock-control",
|
|
18983
|
+
fieldPath: "state"
|
|
18984
|
+
},
|
|
18985
|
+
activeWhen: ["locked"],
|
|
18986
|
+
commandCaps: ["lock-control"]
|
|
18987
|
+
}),
|
|
18988
|
+
actuator({
|
|
18989
|
+
id: "media-player",
|
|
18990
|
+
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.",
|
|
18991
|
+
deviceType: DeviceType.MediaPlayer,
|
|
18992
|
+
outputCap: "group-active",
|
|
18993
|
+
outputField: "active",
|
|
18994
|
+
member: {
|
|
18995
|
+
cap: "media-player",
|
|
18996
|
+
fieldPath: "state"
|
|
18997
|
+
},
|
|
18998
|
+
activeWhen: ["playing", "buffering"],
|
|
18999
|
+
commandCaps: ["media-player"]
|
|
19000
|
+
}),
|
|
19001
|
+
actuator({
|
|
19002
|
+
id: "climate",
|
|
19003
|
+
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.",
|
|
19004
|
+
deviceType: DeviceType.Thermostat,
|
|
19005
|
+
memberDeviceTypes: [DeviceType.Thermostat, DeviceType.Climate],
|
|
19006
|
+
outputCap: "group-active",
|
|
19007
|
+
outputField: "active",
|
|
19008
|
+
member: {
|
|
19009
|
+
cap: "climate-control",
|
|
19010
|
+
fieldPath: "mode"
|
|
19011
|
+
},
|
|
19012
|
+
activeWhen: [
|
|
19013
|
+
"heat",
|
|
19014
|
+
"cool",
|
|
19015
|
+
"auto",
|
|
19016
|
+
"heat_cool",
|
|
19017
|
+
"fan_only",
|
|
19018
|
+
"dry"
|
|
19019
|
+
],
|
|
19020
|
+
commandCaps: ["climate-control"]
|
|
18687
19021
|
})
|
|
18688
19022
|
];
|
|
18689
19023
|
function actuator(input) {
|
|
18690
19024
|
return {
|
|
18691
|
-
|
|
19025
|
+
id: input.id,
|
|
19026
|
+
summary: input.summary,
|
|
19027
|
+
deviceType: input.deviceType,
|
|
19028
|
+
outputCap: input.outputCap,
|
|
19029
|
+
outputField: input.outputField,
|
|
19030
|
+
commandCaps: input.commandCaps,
|
|
18692
19031
|
family: "actuator",
|
|
18693
19032
|
role: void 0,
|
|
18694
19033
|
memberDeviceType: input.deviceType,
|
|
18695
|
-
|
|
19034
|
+
memberDeviceTypes: input.memberDeviceTypes ?? [input.deviceType],
|
|
19035
|
+
activeWhen: input.activeWhen,
|
|
18696
19036
|
quantity: "none",
|
|
18697
19037
|
baseUnit: void 0,
|
|
18698
19038
|
aggregates: BINARY_AGGREGATES,
|
|
18699
19039
|
defaultAggregate: "any",
|
|
18700
19040
|
empty: "offline",
|
|
18701
|
-
accept: [
|
|
18702
|
-
cap: "switch",
|
|
18703
|
-
fieldPath: "on"
|
|
18704
|
-
}],
|
|
19041
|
+
accept: [input.member],
|
|
18705
19042
|
companions: [CHANGED]
|
|
18706
19043
|
};
|
|
18707
19044
|
}
|
|
18708
19045
|
new Map(GROUP_TEMPLATES.map((template) => [template.id, template]));
|
|
18709
19046
|
DeviceFeature.LightColorRgb, DeviceFeature.LightColorHsv, DeviceFeature.LightColorMired;
|
|
19047
|
+
DeviceType.Camera;
|
|
18710
19048
|
`${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
|
|
18711
19049
|
/**
|
|
18712
19050
|
* What a composition may BUILD on a device type (G2, D676): the caps a new
|
|
@@ -43721,7 +44059,7 @@ var NetworkAccessStatusSchema = object({
|
|
|
43721
44059
|
});
|
|
43722
44060
|
/**
|
|
43723
44061
|
* Optional, richer endpoint shape returned by providers that expose
|
|
43724
|
-
* MORE than one ingress concurrently (Tailscale
|
|
44062
|
+
* MORE than one ingress concurrently (Tailscale Funnel with mixed
|
|
43725
44063
|
* serve+funnel rules, future ngrok multi-tunnel, …). Each entry carries
|
|
43726
44064
|
* the originating provider config (mode + sourcePort) so the
|
|
43727
44065
|
* orchestrator UI can label rows distinctly. Providers that expose only
|
|
@@ -46364,7 +46702,20 @@ var NcRuleInputSchema = object({
|
|
|
46364
46702
|
* save by the hub's grouping guard). `.optional()`, never `.default()`: the addon cap
|
|
46365
46703
|
* path does not run Zod defaults.
|
|
46366
46704
|
*/
|
|
46367
|
-
groupingSec: number().int().min(5).max(60).optional()
|
|
46705
|
+
groupingSec: number().int().min(5).max(60).optional(),
|
|
46706
|
+
/**
|
|
46707
|
+
* ASK ME TO CONFIRM DETECTIONS (#243): a DETECTION notification of this rule
|
|
46708
|
+
* carries "Correct" / "Wrong" buttons (and, where the channel has room, a
|
|
46709
|
+
* "Wrong, it is a <class>" choice). A tap marks the track for retraining, the
|
|
46710
|
+
* same mark the Library writes, and records whose notification it was and
|
|
46711
|
+
* when. A channel with no buttons gets the same two choices as links.
|
|
46712
|
+
*
|
|
46713
|
+
* `.optional()`, never `.default()` (a Zod default does not run on the addon
|
|
46714
|
+
* cap path): absent and `false` both mean off, which is what every rule
|
|
46715
|
+
* authored before this field meant. An editor turns it off by writing
|
|
46716
|
+
* `false`, so it needs no `clear` key.
|
|
46717
|
+
*/
|
|
46718
|
+
askVerdict: boolean().optional()
|
|
46368
46719
|
});
|
|
46369
46720
|
/**
|
|
46370
46721
|
* Partial patch for `updateRule` — any subset of the input fields, plus the
|
|
@@ -56821,7 +57172,7 @@ var BatteryStatusSchema = object({
|
|
|
56821
57172
|
*/
|
|
56822
57173
|
binary: boolean().optional().meta({ label: "Binary indicator" })
|
|
56823
57174
|
});
|
|
56824
|
-
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat;
|
|
57175
|
+
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.EventEmitter;
|
|
56825
57176
|
method(object({
|
|
56826
57177
|
deviceId: number(),
|
|
56827
57178
|
/** Bound on the wait. Sensible range 3000–10000ms. */
|
|
@@ -58575,7 +58926,13 @@ results: array(object({
|
|
|
58575
58926
|
/** Ms epoch of the attempt. */
|
|
58576
58927
|
at: number()
|
|
58577
58928
|
})) });
|
|
58578
|
-
DeviceType.Switch, DeviceType.Light;
|
|
58929
|
+
DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Cover, DeviceType.Valve, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.Thermostat, DeviceType.Climate;
|
|
58930
|
+
object({
|
|
58931
|
+
active: boolean().meta({ label: "Active" }),
|
|
58932
|
+
/** Ms epoch when the slice was last updated. */
|
|
58933
|
+
lastChangedAt: number()
|
|
58934
|
+
});
|
|
58935
|
+
DeviceType.Cover, DeviceType.Valve, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.Climate, DeviceType.Thermostat;
|
|
58579
58936
|
object({
|
|
58580
58937
|
/** Members whose current value entered the aggregate. */
|
|
58581
58938
|
included: number().int().nonnegative().meta(readingMeta("count", {
|
|
@@ -58593,7 +58950,7 @@ object({
|
|
|
58593
58950
|
label: "Members"
|
|
58594
58951
|
}))
|
|
58595
58952
|
});
|
|
58596
|
-
DeviceType.Sensor, DeviceType.Switch, DeviceType.Light;
|
|
58953
|
+
DeviceType.Sensor, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Cover, DeviceType.Valve, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.Thermostat, DeviceType.Climate;
|
|
58597
58954
|
object({
|
|
58598
58955
|
/** Radiator valve opening 0 (closed) .. 100 (open). Null = not yet known. */
|
|
58599
58956
|
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
@@ -59500,7 +59857,14 @@ DeviceType.Lock, method(object({
|
|
|
59500
59857
|
auth: "protected"
|
|
59501
59858
|
}), method(object({
|
|
59502
59859
|
deviceId: number().int().nonnegative(),
|
|
59503
|
-
code: string().min(1).optional()
|
|
59860
|
+
code: string().min(1).optional(),
|
|
59861
|
+
/**
|
|
59862
|
+
* Honoured by a helper lock GROUP only (D944): unlocking several doors
|
|
59863
|
+
* with one call is refused unless the caller says it was confirmed. A
|
|
59864
|
+
* single lock ignores it. The refusal lives in the callee, so no
|
|
59865
|
+
* automation or API caller reaches the doors by skipping a dialog.
|
|
59866
|
+
*/
|
|
59867
|
+
confirm: boolean().optional()
|
|
59504
59868
|
}), _void(), {
|
|
59505
59869
|
kind: "mutation",
|
|
59506
59870
|
auth: "protected"
|
|
@@ -59508,6 +59872,11 @@ DeviceType.Lock, method(object({
|
|
|
59508
59872
|
kind: "mutation",
|
|
59509
59873
|
auth: "protected"
|
|
59510
59874
|
});
|
|
59875
|
+
object({
|
|
59876
|
+
value: number().nullable().meta(readingMeta("device", { label: "Total" })),
|
|
59877
|
+
lastFetchedAt: number()
|
|
59878
|
+
});
|
|
59879
|
+
DeviceType.Sensor;
|
|
59511
59880
|
/**
|
|
59512
59881
|
* Media-player cap. Models HA `media_player.*` (Sonos, Chromecast,
|
|
59513
59882
|
* Apple TV, Spotify, Roku, generic OTT receivers, …) on
|
|
@@ -61415,9 +61784,9 @@ object({
|
|
|
61415
61784
|
/** Cumulative energy in kilowatt-hours since the meter was reset. */
|
|
61416
61785
|
kwhTotal: number().optional().meta(readingMeta("energy", { label: "Energy" })),
|
|
61417
61786
|
/** Voltage in volts. */
|
|
61418
|
-
volts: number().optional().meta(readingMeta("voltage")),
|
|
61787
|
+
volts: number().optional().meta(readingMeta("voltage", { label: "Voltage" })),
|
|
61419
61788
|
/** Current in amperes. */
|
|
61420
|
-
amps: number().optional().meta(readingMeta("current")),
|
|
61789
|
+
amps: number().optional().meta(readingMeta("current", { label: "Current" })),
|
|
61421
61790
|
/** Apparent power in volt-amperes. */
|
|
61422
61791
|
va: number().optional().meta(readingMeta("apparent-power")),
|
|
61423
61792
|
/** Power factor (0..1) if reported. */
|
|
@@ -61425,7 +61794,23 @@ object({
|
|
|
61425
61794
|
/** Ms epoch when the slice was last updated. */
|
|
61426
61795
|
lastFetchedAt: number()
|
|
61427
61796
|
});
|
|
61428
|
-
|
|
61797
|
+
[
|
|
61798
|
+
DeviceType.Sensor,
|
|
61799
|
+
DeviceType.Switch,
|
|
61800
|
+
DeviceType.Light,
|
|
61801
|
+
DeviceType.Fan,
|
|
61802
|
+
DeviceType.Climate,
|
|
61803
|
+
DeviceType.Thermostat,
|
|
61804
|
+
DeviceType.Humidifier,
|
|
61805
|
+
DeviceType.WaterHeater,
|
|
61806
|
+
DeviceType.MediaPlayer,
|
|
61807
|
+
DeviceType.Washer,
|
|
61808
|
+
DeviceType.Dryer,
|
|
61809
|
+
DeviceType.Dishwasher,
|
|
61810
|
+
DeviceType.Vacuum,
|
|
61811
|
+
DeviceType.LawnMower,
|
|
61812
|
+
DeviceType.PetFeeder
|
|
61813
|
+
].filter((type) => type !== DeviceType.Sensor);
|
|
61429
61814
|
/**
|
|
61430
61815
|
* Presence cap. Models HA `person.*` and `device_tracker.*` entities
|
|
61431
61816
|
* on `DeviceType.Presence`. Read-only — no setters: presence is
|
|
@@ -61872,7 +62257,7 @@ object({
|
|
|
61872
62257
|
phase: string().nullable()
|
|
61873
62258
|
});
|
|
61874
62259
|
Object.values(DeviceType);
|
|
61875
|
-
DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
|
|
62260
|
+
DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
|
|
61876
62261
|
DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch, method(object({ deviceId: number().int().nonnegative() }), object({ success: literal(true) }), {
|
|
61877
62262
|
kind: "mutation",
|
|
61878
62263
|
auth: "admin"
|
|
@@ -63911,7 +64296,7 @@ object({
|
|
|
63911
64296
|
/** Ms epoch of the last state change. Useful for UI "X minutes ago". */
|
|
63912
64297
|
lastChangedAt: number()
|
|
63913
64298
|
});
|
|
63914
|
-
DeviceType.Switch, DeviceType.Siren, DeviceType.Light, method(object({
|
|
64299
|
+
DeviceType.Switch, DeviceType.Siren, DeviceType.Light, DeviceType.Fan, method(object({
|
|
63915
64300
|
deviceId: number(),
|
|
63916
64301
|
on: boolean()
|
|
63917
64302
|
}), _void(), {
|
|
@@ -65603,8 +65988,9 @@ method(object({}), array(TrainingBaseModelSchema).readonly(), { auth: "admin" })
|
|
|
65603
65988
|
kind: "mutation",
|
|
65604
65989
|
auth: "admin"
|
|
65605
65990
|
});
|
|
65991
|
+
DeviceFeature.FanSpeed, DeviceFeature.FanPreset, DeviceFeature.FanDirection, DeviceFeature.FanOscillating, DeviceFeature.CoverPositionable, DeviceFeature.CoverTilt, DeviceFeature.ValvePositionable, DeviceFeature.MediaPlayerVolume, DeviceFeature.ClimateFanMode;
|
|
65606
65992
|
SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
|
|
65607
|
-
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;
|
|
65993
|
+
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;
|
|
65608
65994
|
String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
|
|
65609
65995
|
DeviceRole.BinarySensor, DeviceRole.MotionSensor;
|
|
65610
65996
|
new Set(CAP_NAMES);
|
|
@@ -65657,7 +66043,7 @@ var AccessoryKind = {
|
|
|
65657
66043
|
PrivacyMask: DeviceRole.PrivacyMask
|
|
65658
66044
|
};
|
|
65659
66045
|
AccessoryKind.Siren, AccessoryKind.Floodlight, AccessoryKind.Spotlight, AccessoryKind.PirSensor, AccessoryKind.Chime, AccessoryKind.Autotrack, AccessoryKind.Nightvision, AccessoryKind.PrivacyMask;
|
|
65660
|
-
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;
|
|
66046
|
+
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;
|
|
65661
66047
|
new Set(Object.values(DeviceType));
|
|
65662
66048
|
Object.freeze({
|
|
65663
66049
|
"accessories.getStatus": {
|
|
@@ -68880,6 +69266,13 @@ Object.freeze({
|
|
|
68880
69266
|
access: "view",
|
|
68881
69267
|
role: "viewer"
|
|
68882
69268
|
},
|
|
69269
|
+
"groupActive.getStatus": {
|
|
69270
|
+
capName: "group-active",
|
|
69271
|
+
capScope: "device",
|
|
69272
|
+
addonId: null,
|
|
69273
|
+
access: "view",
|
|
69274
|
+
role: "viewer"
|
|
69275
|
+
},
|
|
68883
69276
|
"groupCommands.getStatus": {
|
|
68884
69277
|
capName: "group-commands",
|
|
68885
69278
|
capScope: "device",
|
|
@@ -69846,6 +70239,13 @@ Object.freeze({
|
|
|
69846
70239
|
access: "create",
|
|
69847
70240
|
role: "admin"
|
|
69848
70241
|
},
|
|
70242
|
+
"meter.getStatus": {
|
|
70243
|
+
capName: "meter",
|
|
70244
|
+
capScope: "device",
|
|
70245
|
+
addonId: null,
|
|
70246
|
+
access: "view",
|
|
70247
|
+
role: "viewer"
|
|
70248
|
+
},
|
|
69849
70249
|
"metricsProvider.collectSnapshot": {
|
|
69850
70250
|
capName: "metrics-provider",
|
|
69851
70251
|
capScope: "system",
|
|
@@ -77944,7 +78344,39 @@ var APPLIANCE_CAP_VOCABULARY = {
|
|
|
77944
78344
|
phrase: t("When {device} finishes", "Quando {device} finisce"),
|
|
77945
78345
|
icon: "square"
|
|
77946
78346
|
}
|
|
77947
|
-
}
|
|
78347
|
+
},
|
|
78348
|
+
overrides: { byType: {
|
|
78349
|
+
[DeviceType.Washer]: {
|
|
78350
|
+
state: { running: {
|
|
78351
|
+
whenTrue: t("When the washing machine starts", "Quando la lavatrice inizia"),
|
|
78352
|
+
whenFalse: t("When the washing machine has finished", "Quando la lavatrice ha finito")
|
|
78353
|
+
} },
|
|
78354
|
+
events: {
|
|
78355
|
+
onStarted: { phrase: t("When the washing machine starts", "Quando la lavatrice inizia") },
|
|
78356
|
+
onFinished: { phrase: t("When the washing machine has finished", "Quando la lavatrice ha finito") }
|
|
78357
|
+
}
|
|
78358
|
+
},
|
|
78359
|
+
[DeviceType.Dryer]: {
|
|
78360
|
+
state: { running: {
|
|
78361
|
+
whenTrue: t("When the dryer starts", "Quando l'asciugatrice inizia"),
|
|
78362
|
+
whenFalse: t("When the dryer has finished", "Quando l'asciugatrice ha finito")
|
|
78363
|
+
} },
|
|
78364
|
+
events: {
|
|
78365
|
+
onStarted: { phrase: t("When the dryer starts", "Quando l'asciugatrice inizia") },
|
|
78366
|
+
onFinished: { phrase: t("When the dryer has finished", "Quando l'asciugatrice ha finito") }
|
|
78367
|
+
}
|
|
78368
|
+
},
|
|
78369
|
+
[DeviceType.Dishwasher]: {
|
|
78370
|
+
state: { running: {
|
|
78371
|
+
whenTrue: t("When the dishwasher starts", "Quando la lavastoviglie inizia"),
|
|
78372
|
+
whenFalse: t("When the dishwasher has finished", "Quando la lavastoviglie ha finito")
|
|
78373
|
+
} },
|
|
78374
|
+
events: {
|
|
78375
|
+
onStarted: { phrase: t("When the dishwasher starts", "Quando la lavastoviglie inizia") },
|
|
78376
|
+
onFinished: { phrase: t("When the dishwasher has finished", "Quando la lavastoviglie ha finito") }
|
|
78377
|
+
}
|
|
78378
|
+
}
|
|
78379
|
+
} }
|
|
77948
78380
|
},
|
|
77949
78381
|
update: {
|
|
77950
78382
|
scope: "device",
|
|
@@ -78716,6 +79148,10 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78716
79148
|
icon: "flame"
|
|
78717
79149
|
}]
|
|
78718
79150
|
},
|
|
79151
|
+
"group-active": {
|
|
79152
|
+
scope: "device",
|
|
79153
|
+
noun: t("Group state", "Stato del gruppo")
|
|
79154
|
+
},
|
|
78719
79155
|
"group-commands": {
|
|
78720
79156
|
scope: "device",
|
|
78721
79157
|
noun: t("Group command", "Comando di gruppo")
|
|
@@ -78772,6 +79208,17 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78772
79208
|
}],
|
|
78773
79209
|
events: { onMotionChanged: { notOperatorFacing: "the `detected` state trigger phrases both edges, from the mirror that survives a dropped event (D49)" } }
|
|
78774
79210
|
},
|
|
79211
|
+
meter: {
|
|
79212
|
+
scope: "device",
|
|
79213
|
+
noun: t("Meter", "Contatore"),
|
|
79214
|
+
state: [{
|
|
79215
|
+
kind: "numeric",
|
|
79216
|
+
field: "value",
|
|
79217
|
+
quantity: t("the total", "il totale"),
|
|
79218
|
+
label: t("Total", "Totale"),
|
|
79219
|
+
icon: "gauge"
|
|
79220
|
+
}]
|
|
79221
|
+
},
|
|
78775
79222
|
"numeric-sensor": {
|
|
78776
79223
|
scope: "device",
|
|
78777
79224
|
noun: t("Sensor", "Sensore"),
|
|
@@ -79244,8 +79691,47 @@ function projectAction(cap, action) {
|
|
|
79244
79691
|
};
|
|
79245
79692
|
}
|
|
79246
79693
|
Object.entries(CAP_VOCABULARY_BY_NAME).flatMap(([cap, entry]) => entry.scope === "device" ? (entry.actions ?? []).map((a) => projectAction(cap, a)) : []);
|
|
79247
|
-
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;
|
|
79694
|
+
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;
|
|
79248
79695
|
DeviceFeature.BatteryOperated;
|
|
79696
|
+
DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher;
|
|
79697
|
+
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.";
|
|
79698
|
+
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.";
|
|
79699
|
+
var ALEXA_REASON = "Alexa has no laundry category in this export, and neither power nor running has an Alexa interface.";
|
|
79700
|
+
var GOOGLE_REASON = "Google WASHER, DRYER and DISHWASHER require RunCycle. A power threshold is not that trait, and this export does not publish RunCycle.";
|
|
79701
|
+
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.";
|
|
79702
|
+
function withheld(reason) {
|
|
79703
|
+
return {
|
|
79704
|
+
[DeviceType.Washer]: {
|
|
79705
|
+
exported: false,
|
|
79706
|
+
reason
|
|
79707
|
+
},
|
|
79708
|
+
[DeviceType.Dryer]: {
|
|
79709
|
+
exported: false,
|
|
79710
|
+
reason
|
|
79711
|
+
},
|
|
79712
|
+
[DeviceType.Dishwasher]: {
|
|
79713
|
+
exported: false,
|
|
79714
|
+
reason
|
|
79715
|
+
}
|
|
79716
|
+
};
|
|
79717
|
+
}
|
|
79718
|
+
function offered(received) {
|
|
79719
|
+
return {
|
|
79720
|
+
[DeviceType.Washer]: {
|
|
79721
|
+
exported: true,
|
|
79722
|
+
as: received
|
|
79723
|
+
},
|
|
79724
|
+
[DeviceType.Dryer]: {
|
|
79725
|
+
exported: true,
|
|
79726
|
+
as: received
|
|
79727
|
+
},
|
|
79728
|
+
[DeviceType.Dishwasher]: {
|
|
79729
|
+
exported: true,
|
|
79730
|
+
as: received
|
|
79731
|
+
}
|
|
79732
|
+
};
|
|
79733
|
+
}
|
|
79734
|
+
offered(HA_AS), withheld(HOMEKIT_REASON), withheld(ALEXA_REASON), withheld(GOOGLE_REASON), withheld(MATTER_REASON);
|
|
79249
79735
|
Object.freeze({
|
|
79250
79736
|
"accessories.getStatus": [{
|
|
79251
79737
|
name: "deviceId",
|
|
@@ -80212,6 +80698,11 @@ Object.freeze({
|
|
|
80212
80698
|
form: "single",
|
|
80213
80699
|
optional: false
|
|
80214
80700
|
}],
|
|
80701
|
+
"groupActive.getStatus": [{
|
|
80702
|
+
name: "deviceId",
|
|
80703
|
+
form: "single",
|
|
80704
|
+
optional: false
|
|
80705
|
+
}],
|
|
80215
80706
|
"groupCommands.getStatus": [{
|
|
80216
80707
|
name: "deviceId",
|
|
80217
80708
|
form: "single",
|
|
@@ -80422,6 +80913,11 @@ Object.freeze({
|
|
|
80422
80913
|
form: "single",
|
|
80423
80914
|
optional: false
|
|
80424
80915
|
}],
|
|
80916
|
+
"meter.getStatus": [{
|
|
80917
|
+
name: "deviceId",
|
|
80918
|
+
form: "single",
|
|
80919
|
+
optional: false
|
|
80920
|
+
}],
|
|
80425
80921
|
"motion.getStatus": [{
|
|
80426
80922
|
name: "deviceId",
|
|
80427
80923
|
form: "single",
|
|
@@ -82029,7 +82525,6 @@ Object.freeze({
|
|
|
82029
82525
|
"network-access": "ingress",
|
|
82030
82526
|
"smtp-provider": "email"
|
|
82031
82527
|
});
|
|
82032
|
-
DeviceType.Camera;
|
|
82033
82528
|
/**
|
|
82034
82529
|
* A saved Customize assignment (D936). The schema is the type: callers use
|
|
82035
82530
|
* `z.infer`, they do not restate the shape.
|