@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
|
@@ -5582,7 +5582,7 @@ var ZodIssueCode = {
|
|
|
5582
5582
|
var ZodFirstPartyTypeKind;
|
|
5583
5583
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5584
5584
|
//#endregion
|
|
5585
|
-
//#region ../types/dist/sleep
|
|
5585
|
+
//#region ../types/dist/sleep--jXS9hWo.mjs
|
|
5586
5586
|
/**
|
|
5587
5587
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5588
5588
|
* window to float samples (D455).
|
|
@@ -8991,6 +8991,7 @@ var CAP_NAMES = Object.freeze([
|
|
|
8991
8991
|
"filesystem-browse",
|
|
8992
8992
|
"flood",
|
|
8993
8993
|
"gas",
|
|
8994
|
+
"group-active",
|
|
8994
8995
|
"group-commands",
|
|
8995
8996
|
"group-status",
|
|
8996
8997
|
"heating-valve",
|
|
@@ -9013,6 +9014,7 @@ var CAP_NAMES = Object.freeze([
|
|
|
9013
9014
|
"login-method",
|
|
9014
9015
|
"media-player",
|
|
9015
9016
|
"mesh-network",
|
|
9017
|
+
"meter",
|
|
9016
9018
|
"metrics-provider",
|
|
9017
9019
|
"model-convert",
|
|
9018
9020
|
"model-distributor",
|
|
@@ -9811,6 +9813,10 @@ Object.freeze({
|
|
|
9811
9813
|
"path": "detected",
|
|
9812
9814
|
"valueType": "boolean"
|
|
9813
9815
|
}],
|
|
9816
|
+
"group-active": [{
|
|
9817
|
+
"path": "active",
|
|
9818
|
+
"valueType": "boolean"
|
|
9819
|
+
}],
|
|
9814
9820
|
"group-status": [
|
|
9815
9821
|
{
|
|
9816
9822
|
"path": "included",
|
|
@@ -10070,6 +10076,10 @@ Object.freeze({
|
|
|
10070
10076
|
]
|
|
10071
10077
|
}
|
|
10072
10078
|
],
|
|
10079
|
+
"meter": [{
|
|
10080
|
+
"path": "value",
|
|
10081
|
+
"valueType": "number"
|
|
10082
|
+
}],
|
|
10073
10083
|
"motion": [
|
|
10074
10084
|
{
|
|
10075
10085
|
"path": "detected",
|
|
@@ -10813,7 +10823,7 @@ object({
|
|
|
10813
10823
|
params: record(string(), union([string(), number()])).optional()
|
|
10814
10824
|
});
|
|
10815
10825
|
//#endregion
|
|
10816
|
-
//#region ../types/dist/err-msg-
|
|
10826
|
+
//#region ../types/dist/err-msg-DIorGYeC.mjs
|
|
10817
10827
|
var DeviceType = /* @__PURE__ */ function(DeviceType) {
|
|
10818
10828
|
DeviceType["Camera"] = "camera";
|
|
10819
10829
|
DeviceType["Hub"] = "hub";
|
|
@@ -10907,8 +10917,14 @@ var DeviceType = /* @__PURE__ */ function(DeviceType) {
|
|
|
10907
10917
|
DeviceType["PetFeeder"] = "pet-feeder";
|
|
10908
10918
|
/** Built-in dishwasher — program lifecycle, door / remote-start gates,
|
|
10909
10919
|
* salt and rinse-aid levels. Installed with the `dishwasher` cap.
|
|
10910
|
-
* Sources: native Bosch Home Connect, reusable by similar integrations.
|
|
10920
|
+
* Sources: native Bosch Home Connect, reusable by similar integrations.
|
|
10921
|
+
* A plug-built dishwasher carries running-state and power instead. */
|
|
10911
10922
|
DeviceType["Dishwasher"] = "dishwasher";
|
|
10923
|
+
/** Washing machine. A plug-built one is running while its power stays
|
|
10924
|
+
* above a threshold. No program cap — that surface is the dishwasher's. */
|
|
10925
|
+
DeviceType["Washer"] = "washer";
|
|
10926
|
+
/** Tumble dryer. Same plug-built running surface as {@link Washer}. */
|
|
10927
|
+
DeviceType["Dryer"] = "dryer";
|
|
10912
10928
|
return DeviceType;
|
|
10913
10929
|
}({});
|
|
10914
10930
|
var DeviceFeature = /* @__PURE__ */ function(DeviceFeature) {
|
|
@@ -11156,7 +11172,7 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
|
|
|
11156
11172
|
return DeviceRole;
|
|
11157
11173
|
}({});
|
|
11158
11174
|
//#endregion
|
|
11159
|
-
//#region ../types/dist/composition-
|
|
11175
|
+
//#region ../types/dist/composition-Bb8iwHEJ.mjs
|
|
11160
11176
|
/**
|
|
11161
11177
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
11162
11178
|
*
|
|
@@ -11471,6 +11487,13 @@ var table = {
|
|
|
11471
11487
|
apply: () => {
|
|
11472
11488
|
throw new ExpressionEvalError("latchedAt: stateful evaluation context is required");
|
|
11473
11489
|
}
|
|
11490
|
+
},
|
|
11491
|
+
schmitt: {
|
|
11492
|
+
minArgs: 3,
|
|
11493
|
+
maxArgs: 5,
|
|
11494
|
+
apply: () => {
|
|
11495
|
+
throw new ExpressionEvalError("schmitt: stateful evaluation context is required");
|
|
11496
|
+
}
|
|
11474
11497
|
}
|
|
11475
11498
|
};
|
|
11476
11499
|
Object.freeze(Object.assign(Object.create(null), table));
|
|
@@ -11912,6 +11935,99 @@ function validateExpressionSource(src) {
|
|
|
11912
11935
|
return null;
|
|
11913
11936
|
}
|
|
11914
11937
|
/**
|
|
11938
|
+
* One power reading becomes a washer, dryer or dishwasher (D944 helper).
|
|
11939
|
+
*
|
|
11940
|
+
* Standby of the control board is under 5 W; a motor or a heater is far
|
|
11941
|
+
* above that, so 5 W is the line. A door lock or a short pump spike is not
|
|
11942
|
+
* a cycle, so running starts only after 30 s above the line.
|
|
11943
|
+
*
|
|
11944
|
+
* A wash, dry or dishwasher pause (soak, heat-wait, heater off between
|
|
11945
|
+
* bursts) lasts several minutes. Ending the cycle on the first dip would
|
|
11946
|
+
* report "finished" in the middle of the program, so the stop dwell is
|
|
11947
|
+
* 10 minutes on every type. The number is stored per type so one machine
|
|
11948
|
+
* can move later without moving the others.
|
|
11949
|
+
*/
|
|
11950
|
+
var APPLIANCE_TEMPLATE_ID = "appliance";
|
|
11951
|
+
var APPLIANCE_KINDS = [
|
|
11952
|
+
"washer",
|
|
11953
|
+
"dryer",
|
|
11954
|
+
"dishwasher"
|
|
11955
|
+
];
|
|
11956
|
+
DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher;
|
|
11957
|
+
/**
|
|
11958
|
+
* Statistics and integrals over a history read (D944).
|
|
11959
|
+
*
|
|
11960
|
+
* Pure: the same points always give the same answer, so a restart recomputes
|
|
11961
|
+
* rather than trusting a buffer. A gauge mean is time-weighted (value × ms),
|
|
11962
|
+
* never the mean of the samples. A hole with no held value is not integrated
|
|
11963
|
+
* as zero. A truncated read is not published.
|
|
11964
|
+
*/
|
|
11965
|
+
var STATISTIC_STATS = [
|
|
11966
|
+
"min",
|
|
11967
|
+
"max",
|
|
11968
|
+
"mean",
|
|
11969
|
+
"sum",
|
|
11970
|
+
"count",
|
|
11971
|
+
"change"
|
|
11972
|
+
];
|
|
11973
|
+
/**
|
|
11974
|
+
* The range a statistics or integral helper asks history for (D944).
|
|
11975
|
+
*
|
|
11976
|
+
* Calendar edges are the hub's timezone, never UTC midnight: a day is 23, 24
|
|
11977
|
+
* or 25 hours across a DST change. A tier is eligible only when its retention
|
|
11978
|
+
* is strictly longer than the longest that range can be. Forever qualifies.
|
|
11979
|
+
* Equal to a tier's retention is a refusal, not a short answer.
|
|
11980
|
+
*/
|
|
11981
|
+
var MINUTE_MS = 6e4;
|
|
11982
|
+
var HOUR_MS = 60 * MINUTE_MS;
|
|
11983
|
+
var DAY_MS$1 = 24 * HOUR_MS;
|
|
11984
|
+
var ROLLING_SPANS = [
|
|
11985
|
+
"1h",
|
|
11986
|
+
"24h",
|
|
11987
|
+
"2d",
|
|
11988
|
+
"7d",
|
|
11989
|
+
"30d",
|
|
11990
|
+
"custom"
|
|
11991
|
+
];
|
|
11992
|
+
var CALENDAR_PERIODS = [
|
|
11993
|
+
"today",
|
|
11994
|
+
"yesterday",
|
|
11995
|
+
"this-week",
|
|
11996
|
+
"this-month"
|
|
11997
|
+
];
|
|
11998
|
+
var RESET_PERIODS = [
|
|
11999
|
+
"never",
|
|
12000
|
+
"daily",
|
|
12001
|
+
"weekly",
|
|
12002
|
+
"monthly"
|
|
12003
|
+
];
|
|
12004
|
+
5 * MINUTE_MS;
|
|
12005
|
+
24 * HOUR_MS, 2 * DAY_MS$1, 7 * DAY_MS$1, 30 * DAY_MS$1;
|
|
12006
|
+
7 * DAY_MS$1, 30 * DAY_MS$1, 365 * DAY_MS$1;
|
|
12007
|
+
var rollingWindowObject = object({
|
|
12008
|
+
kind: literal("rolling"),
|
|
12009
|
+
span: _enum(ROLLING_SPANS),
|
|
12010
|
+
customMinutes: number().int().min(5).optional()
|
|
12011
|
+
}).check((payload) => {
|
|
12012
|
+
if (payload.value.span === "custom" && payload.value.customMinutes === void 0) payload.issues.push({
|
|
12013
|
+
code: "custom",
|
|
12014
|
+
message: "a custom range needs a duration in minutes",
|
|
12015
|
+
path: ["customMinutes"],
|
|
12016
|
+
input: payload.value
|
|
12017
|
+
});
|
|
12018
|
+
if (payload.value.span !== "custom" && payload.value.customMinutes !== void 0) payload.issues.push({
|
|
12019
|
+
code: "custom",
|
|
12020
|
+
message: "only a custom range carries a duration",
|
|
12021
|
+
path: ["customMinutes"],
|
|
12022
|
+
input: payload.value
|
|
12023
|
+
});
|
|
12024
|
+
});
|
|
12025
|
+
var RollingWindowSchema = rollingWindowObject;
|
|
12026
|
+
var StatisticWindowSchema = discriminatedUnion("kind", [rollingWindowObject, object({
|
|
12027
|
+
kind: literal("calendar"),
|
|
12028
|
+
period: _enum(CALENDAR_PERIODS)
|
|
12029
|
+
})]);
|
|
12030
|
+
/**
|
|
11915
12031
|
* A composition source identity: `(addonId, stableId)`, never a numeric device
|
|
11916
12032
|
* id. Split out so helper schemas can name it without a cycle through
|
|
11917
12033
|
* `composition.ts` (D659).
|
|
@@ -11937,7 +12053,13 @@ var GROUP_TEMPLATE_IDS = [
|
|
|
11937
12053
|
"occupancy",
|
|
11938
12054
|
"binary",
|
|
11939
12055
|
"switch",
|
|
11940
|
-
"light"
|
|
12056
|
+
"light",
|
|
12057
|
+
"fan",
|
|
12058
|
+
"cover",
|
|
12059
|
+
"valve",
|
|
12060
|
+
"lock",
|
|
12061
|
+
"media-player",
|
|
12062
|
+
"climate"
|
|
11941
12063
|
];
|
|
11942
12064
|
var NUMERIC_AGGREGATES = [
|
|
11943
12065
|
"mean",
|
|
@@ -11967,14 +12089,73 @@ var HelperMemberSchema = object({
|
|
|
11967
12089
|
cap: string().min(1),
|
|
11968
12090
|
fieldPath: string().min(1)
|
|
11969
12091
|
});
|
|
11970
|
-
var HelperSpecSchema = discriminatedUnion("kind", [
|
|
11971
|
-
|
|
11972
|
-
|
|
11973
|
-
|
|
11974
|
-
|
|
11975
|
-
|
|
11976
|
-
|
|
11977
|
-
|
|
12092
|
+
var HelperSpecSchema = discriminatedUnion("kind", [
|
|
12093
|
+
object({
|
|
12094
|
+
kind: literal("group"),
|
|
12095
|
+
templateId: GroupTemplateIdSchema,
|
|
12096
|
+
aggregate: AggregateReducerSchema,
|
|
12097
|
+
members: array(HelperMemberSchema).min(1).max(64),
|
|
12098
|
+
/** Actuator groups only. Readings leave this unset. */
|
|
12099
|
+
active: ActiveCriterionSchema.optional()
|
|
12100
|
+
}),
|
|
12101
|
+
object({
|
|
12102
|
+
kind: literal("appliance"),
|
|
12103
|
+
templateId: literal(APPLIANCE_TEMPLATE_ID),
|
|
12104
|
+
appliance: _enum(APPLIANCE_KINDS),
|
|
12105
|
+
thresholdWatts: number().positive(),
|
|
12106
|
+
startDwellMs: number().int().nonnegative(),
|
|
12107
|
+
stopDwellMs: number().int().nonnegative(),
|
|
12108
|
+
member: HelperMemberSchema
|
|
12109
|
+
}),
|
|
12110
|
+
object({
|
|
12111
|
+
kind: literal("statistic"),
|
|
12112
|
+
stat: _enum(STATISTIC_STATS),
|
|
12113
|
+
window: StatisticWindowSchema,
|
|
12114
|
+
source: HelperMemberSchema
|
|
12115
|
+
}),
|
|
12116
|
+
object({
|
|
12117
|
+
kind: literal("integral"),
|
|
12118
|
+
reset: _enum(RESET_PERIODS),
|
|
12119
|
+
output: _enum(["energy", "meter"]),
|
|
12120
|
+
source: HelperMemberSchema
|
|
12121
|
+
}),
|
|
12122
|
+
object({
|
|
12123
|
+
kind: literal("threshold"),
|
|
12124
|
+
source: HelperMemberSchema,
|
|
12125
|
+
high: number(),
|
|
12126
|
+
low: number(),
|
|
12127
|
+
onForMs: number().int().nonnegative(),
|
|
12128
|
+
offForMs: number().int().nonnegative()
|
|
12129
|
+
}),
|
|
12130
|
+
object({
|
|
12131
|
+
kind: literal("arithmetic"),
|
|
12132
|
+
op: _enum([
|
|
12133
|
+
"sum",
|
|
12134
|
+
"difference",
|
|
12135
|
+
"ratio"
|
|
12136
|
+
]),
|
|
12137
|
+
inputs: array(HelperMemberSchema).min(2).max(64)
|
|
12138
|
+
}),
|
|
12139
|
+
object({
|
|
12140
|
+
kind: literal("expression"),
|
|
12141
|
+
expr: string().min(1),
|
|
12142
|
+
inputs: array(object({
|
|
12143
|
+
name: string().min(1),
|
|
12144
|
+
member: HelperMemberSchema
|
|
12145
|
+
})).min(1).max(64),
|
|
12146
|
+
output: _enum(["number", "boolean"])
|
|
12147
|
+
}),
|
|
12148
|
+
object({
|
|
12149
|
+
kind: literal("derivative"),
|
|
12150
|
+
window: RollingWindowSchema,
|
|
12151
|
+
per: _enum([
|
|
12152
|
+
"second",
|
|
12153
|
+
"minute",
|
|
12154
|
+
"hour"
|
|
12155
|
+
]),
|
|
12156
|
+
source: HelperMemberSchema
|
|
12157
|
+
})
|
|
12158
|
+
]);
|
|
11978
12159
|
/** A composed device's stableId is this prefix plus the block id. */
|
|
11979
12160
|
var COMPOSED_DEVICE_STABLE_ID_PREFIX = "composed-";
|
|
11980
12161
|
/** Longest snippet a `code` source may carry (slice 4). */
|
|
@@ -12035,6 +12216,12 @@ var CompositionFieldSourceSchema = discriminatedUnion("kind", [
|
|
|
12035
12216
|
"all"
|
|
12036
12217
|
]),
|
|
12037
12218
|
reads: array(CompositionFieldReadSchema).min(1).max(64),
|
|
12219
|
+
/**
|
|
12220
|
+
* Set when the reads are an enum state, not a yes/no: the listed states
|
|
12221
|
+
* count as active (a cover is `open`). A state outside the list is inactive;
|
|
12222
|
+
* a read that is not a state at all is left out. Only `any` / `all` use it.
|
|
12223
|
+
*/
|
|
12224
|
+
activeWhen: array(string().min(1)).min(1).optional(),
|
|
12038
12225
|
/** `value` is the reading; the others are the member counts. */
|
|
12039
12226
|
publish: _enum([
|
|
12040
12227
|
"value",
|
|
@@ -12048,6 +12235,26 @@ var CompositionFieldSourceSchema = discriminatedUnion("kind", [
|
|
|
12048
12235
|
"omit",
|
|
12049
12236
|
"offline"
|
|
12050
12237
|
])
|
|
12238
|
+
}),
|
|
12239
|
+
object({
|
|
12240
|
+
kind: literal("series"),
|
|
12241
|
+
read: CompositionFieldReadSchema,
|
|
12242
|
+
/** `value` is the statistic or the integral. The others are the gap counts. */
|
|
12243
|
+
publish: _enum([
|
|
12244
|
+
"value",
|
|
12245
|
+
"included",
|
|
12246
|
+
"excluded",
|
|
12247
|
+
"total"
|
|
12248
|
+
]),
|
|
12249
|
+
/**
|
|
12250
|
+
* What an unanswered `value` does. Counts ignore this. `offline` leaves the
|
|
12251
|
+
* device unseeded until history answers, so a restart cannot publish 0.
|
|
12252
|
+
*/
|
|
12253
|
+
empty: _enum([
|
|
12254
|
+
"null",
|
|
12255
|
+
"omit",
|
|
12256
|
+
"offline"
|
|
12257
|
+
])
|
|
12051
12258
|
})
|
|
12052
12259
|
]);
|
|
12053
12260
|
var CompositionCommandTargetSchema = discriminatedUnion("kind", [object({
|
|
@@ -17207,7 +17414,22 @@ var BrokerProviderInfoSchema = object({
|
|
|
17207
17414
|
*/
|
|
17208
17415
|
interactiveConnectPath: string().min(1).optional(),
|
|
17209
17416
|
/** Relative hub path to disconnect the linked account (same popup pattern). */
|
|
17210
|
-
interactiveDisconnectPath: string().min(1).optional()
|
|
17417
|
+
interactiveDisconnectPath: string().min(1).optional(),
|
|
17418
|
+
/**
|
|
17419
|
+
* The kind signs in through a server-held interactive session instead of
|
|
17420
|
+
* (or before) typed credentials. `basePath` is a hub-relative route set
|
|
17421
|
+
* served by the owning addon (`/addon/<id>/...`) speaking the sign-in
|
|
17422
|
+
* contract: `POST {basePath}/start` (body: the form's settings) answers
|
|
17423
|
+
* `{ sessionId, loginUrl }`; `GET {basePath}/status?sessionId=` answers
|
|
17424
|
+
* `{ phase: 'starting' | 'awaiting-login' | 'captured' | 'error' |
|
|
17425
|
+
* 'cancelled', loginUrl, error }`; `POST {basePath}/commit`
|
|
17426
|
+
* (`{ sessionId, name, brokerId? }`) stores the credentials on a new or
|
|
17427
|
+
* existing broker and answers `{ brokerId }`; `POST {basePath}/cancel`
|
|
17428
|
+
* (`{ sessionId }`) drops the session. The dialog that edits a broker
|
|
17429
|
+
* offers it as the default path; the fields the session fills are
|
|
17430
|
+
* marked `filledBySignIn` in the kind's settings schema.
|
|
17431
|
+
*/
|
|
17432
|
+
signIn: object({ basePath: string().min(1) }).optional()
|
|
17211
17433
|
}))
|
|
17212
17434
|
});
|
|
17213
17435
|
var ListInputSchema = object({
|
|
@@ -18206,7 +18428,8 @@ var CompositionProblemSchema = object({
|
|
|
18206
18428
|
"native-capability-replace",
|
|
18207
18429
|
"mixed-quantity",
|
|
18208
18430
|
"helper-mismatch",
|
|
18209
|
-
"member-constraint"
|
|
18431
|
+
"member-constraint",
|
|
18432
|
+
"retention"
|
|
18210
18433
|
]),
|
|
18211
18434
|
path: string(),
|
|
18212
18435
|
message: string()
|
|
@@ -18440,13 +18663,17 @@ Object.freeze({
|
|
|
18440
18663
|
latchedAt: {
|
|
18441
18664
|
kind: "fixed",
|
|
18442
18665
|
result: ["number", "null"]
|
|
18666
|
+
},
|
|
18667
|
+
schmitt: {
|
|
18668
|
+
kind: "fixed",
|
|
18669
|
+
result: ["boolean", "null"]
|
|
18443
18670
|
}
|
|
18444
18671
|
});
|
|
18445
18672
|
/**
|
|
18446
18673
|
* One catalog row per base reading a group helper can build (D944 §3).
|
|
18447
18674
|
* Data, not a form default written into the block.
|
|
18448
18675
|
*/
|
|
18449
|
-
var NOW = {
|
|
18676
|
+
var NOW$2 = {
|
|
18450
18677
|
fieldPath: "lastFetchedAt",
|
|
18451
18678
|
expr: "now"
|
|
18452
18679
|
};
|
|
@@ -18460,6 +18687,8 @@ function numeric(input) {
|
|
|
18460
18687
|
family: "numeric",
|
|
18461
18688
|
deviceType: DeviceType.Sensor,
|
|
18462
18689
|
memberDeviceType: DeviceType.Sensor,
|
|
18690
|
+
memberDeviceTypes: [DeviceType.Sensor],
|
|
18691
|
+
activeWhen: void 0,
|
|
18463
18692
|
commandCaps: [],
|
|
18464
18693
|
baseUnit: baseUnitOf(input.quantity),
|
|
18465
18694
|
aggregates: NUMERIC_AGGREGATES,
|
|
@@ -18475,6 +18704,8 @@ function binary(input) {
|
|
|
18475
18704
|
family: "binary",
|
|
18476
18705
|
deviceType: DeviceType.Sensor,
|
|
18477
18706
|
memberDeviceType: DeviceType.Sensor,
|
|
18707
|
+
memberDeviceTypes: [DeviceType.Sensor],
|
|
18708
|
+
activeWhen: void 0,
|
|
18478
18709
|
commandCaps: [],
|
|
18479
18710
|
quantity: "none",
|
|
18480
18711
|
baseUnit: void 0,
|
|
@@ -18492,7 +18723,7 @@ var GROUP_TEMPLATES = [
|
|
|
18492
18723
|
quantity: "temperature",
|
|
18493
18724
|
defaultAggregate: "mean",
|
|
18494
18725
|
empty: "null",
|
|
18495
|
-
companions: [NOW]
|
|
18726
|
+
companions: [NOW$2]
|
|
18496
18727
|
}),
|
|
18497
18728
|
numeric({
|
|
18498
18729
|
id: "humidity",
|
|
@@ -18503,7 +18734,7 @@ var GROUP_TEMPLATES = [
|
|
|
18503
18734
|
quantity: "humidity",
|
|
18504
18735
|
defaultAggregate: "mean",
|
|
18505
18736
|
empty: "null",
|
|
18506
|
-
companions: [NOW]
|
|
18737
|
+
companions: [NOW$2]
|
|
18507
18738
|
}),
|
|
18508
18739
|
numeric({
|
|
18509
18740
|
id: "pressure",
|
|
@@ -18514,7 +18745,7 @@ var GROUP_TEMPLATES = [
|
|
|
18514
18745
|
quantity: "pressure",
|
|
18515
18746
|
defaultAggregate: "mean",
|
|
18516
18747
|
empty: "null",
|
|
18517
|
-
companions: [NOW]
|
|
18748
|
+
companions: [NOW$2]
|
|
18518
18749
|
}),
|
|
18519
18750
|
numeric({
|
|
18520
18751
|
id: "illuminance",
|
|
@@ -18525,7 +18756,7 @@ var GROUP_TEMPLATES = [
|
|
|
18525
18756
|
quantity: "illuminance",
|
|
18526
18757
|
defaultAggregate: "mean",
|
|
18527
18758
|
empty: "null",
|
|
18528
|
-
companions: [NOW]
|
|
18759
|
+
companions: [NOW$2]
|
|
18529
18760
|
}),
|
|
18530
18761
|
numeric({
|
|
18531
18762
|
id: "power",
|
|
@@ -18536,7 +18767,7 @@ var GROUP_TEMPLATES = [
|
|
|
18536
18767
|
quantity: "power",
|
|
18537
18768
|
defaultAggregate: "sum",
|
|
18538
18769
|
empty: "omit",
|
|
18539
|
-
companions: [NOW]
|
|
18770
|
+
companions: [NOW$2]
|
|
18540
18771
|
}),
|
|
18541
18772
|
numeric({
|
|
18542
18773
|
id: "energy",
|
|
@@ -18547,7 +18778,7 @@ var GROUP_TEMPLATES = [
|
|
|
18547
18778
|
quantity: "energy",
|
|
18548
18779
|
defaultAggregate: "sum",
|
|
18549
18780
|
empty: "omit",
|
|
18550
|
-
companions: [NOW]
|
|
18781
|
+
companions: [NOW$2]
|
|
18551
18782
|
}),
|
|
18552
18783
|
numeric({
|
|
18553
18784
|
id: "battery",
|
|
@@ -18582,7 +18813,7 @@ var GROUP_TEMPLATES = [
|
|
|
18582
18813
|
quantity: "device",
|
|
18583
18814
|
defaultAggregate: "mean",
|
|
18584
18815
|
empty: "null",
|
|
18585
|
-
companions: [NOW]
|
|
18816
|
+
companions: [NOW$2]
|
|
18586
18817
|
}),
|
|
18587
18818
|
binary({
|
|
18588
18819
|
id: "motion",
|
|
@@ -18676,6 +18907,11 @@ var GROUP_TEMPLATES = [
|
|
|
18676
18907
|
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.",
|
|
18677
18908
|
deviceType: DeviceType.Switch,
|
|
18678
18909
|
outputCap: "switch",
|
|
18910
|
+
outputField: "on",
|
|
18911
|
+
member: {
|
|
18912
|
+
cap: "switch",
|
|
18913
|
+
fieldPath: "on"
|
|
18914
|
+
},
|
|
18679
18915
|
commandCaps: ["switch"]
|
|
18680
18916
|
}),
|
|
18681
18917
|
actuator({
|
|
@@ -18683,34 +18919,136 @@ var GROUP_TEMPLATES = [
|
|
|
18683
18919
|
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.",
|
|
18684
18920
|
deviceType: DeviceType.Light,
|
|
18685
18921
|
outputCap: "switch",
|
|
18922
|
+
outputField: "on",
|
|
18923
|
+
member: {
|
|
18924
|
+
cap: "switch",
|
|
18925
|
+
fieldPath: "on"
|
|
18926
|
+
},
|
|
18686
18927
|
commandCaps: [
|
|
18687
18928
|
"switch",
|
|
18688
18929
|
"brightness",
|
|
18689
18930
|
"color"
|
|
18690
18931
|
]
|
|
18932
|
+
}),
|
|
18933
|
+
actuator({
|
|
18934
|
+
id: "fan",
|
|
18935
|
+
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.",
|
|
18936
|
+
deviceType: DeviceType.Fan,
|
|
18937
|
+
outputCap: "switch",
|
|
18938
|
+
outputField: "on",
|
|
18939
|
+
member: {
|
|
18940
|
+
cap: "switch",
|
|
18941
|
+
fieldPath: "on"
|
|
18942
|
+
},
|
|
18943
|
+
commandCaps: ["switch", "fan-control"]
|
|
18944
|
+
}),
|
|
18945
|
+
actuator({
|
|
18946
|
+
id: "cover",
|
|
18947
|
+
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.",
|
|
18948
|
+
deviceType: DeviceType.Cover,
|
|
18949
|
+
outputCap: "group-active",
|
|
18950
|
+
outputField: "active",
|
|
18951
|
+
member: {
|
|
18952
|
+
cap: "cover",
|
|
18953
|
+
fieldPath: "state"
|
|
18954
|
+
},
|
|
18955
|
+
activeWhen: [
|
|
18956
|
+
"open",
|
|
18957
|
+
"opening",
|
|
18958
|
+
"stopped"
|
|
18959
|
+
],
|
|
18960
|
+
commandCaps: ["cover"]
|
|
18961
|
+
}),
|
|
18962
|
+
actuator({
|
|
18963
|
+
id: "valve",
|
|
18964
|
+
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.",
|
|
18965
|
+
deviceType: DeviceType.Valve,
|
|
18966
|
+
outputCap: "group-active",
|
|
18967
|
+
outputField: "active",
|
|
18968
|
+
member: {
|
|
18969
|
+
cap: "valve",
|
|
18970
|
+
fieldPath: "state"
|
|
18971
|
+
},
|
|
18972
|
+
activeWhen: [
|
|
18973
|
+
"open",
|
|
18974
|
+
"opening",
|
|
18975
|
+
"stopped"
|
|
18976
|
+
],
|
|
18977
|
+
commandCaps: ["valve"]
|
|
18978
|
+
}),
|
|
18979
|
+
actuator({
|
|
18980
|
+
id: "lock",
|
|
18981
|
+
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.",
|
|
18982
|
+
deviceType: DeviceType.Lock,
|
|
18983
|
+
outputCap: "group-active",
|
|
18984
|
+
outputField: "active",
|
|
18985
|
+
member: {
|
|
18986
|
+
cap: "lock-control",
|
|
18987
|
+
fieldPath: "state"
|
|
18988
|
+
},
|
|
18989
|
+
activeWhen: ["locked"],
|
|
18990
|
+
commandCaps: ["lock-control"]
|
|
18991
|
+
}),
|
|
18992
|
+
actuator({
|
|
18993
|
+
id: "media-player",
|
|
18994
|
+
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.",
|
|
18995
|
+
deviceType: DeviceType.MediaPlayer,
|
|
18996
|
+
outputCap: "group-active",
|
|
18997
|
+
outputField: "active",
|
|
18998
|
+
member: {
|
|
18999
|
+
cap: "media-player",
|
|
19000
|
+
fieldPath: "state"
|
|
19001
|
+
},
|
|
19002
|
+
activeWhen: ["playing", "buffering"],
|
|
19003
|
+
commandCaps: ["media-player"]
|
|
19004
|
+
}),
|
|
19005
|
+
actuator({
|
|
19006
|
+
id: "climate",
|
|
19007
|
+
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.",
|
|
19008
|
+
deviceType: DeviceType.Thermostat,
|
|
19009
|
+
memberDeviceTypes: [DeviceType.Thermostat, DeviceType.Climate],
|
|
19010
|
+
outputCap: "group-active",
|
|
19011
|
+
outputField: "active",
|
|
19012
|
+
member: {
|
|
19013
|
+
cap: "climate-control",
|
|
19014
|
+
fieldPath: "mode"
|
|
19015
|
+
},
|
|
19016
|
+
activeWhen: [
|
|
19017
|
+
"heat",
|
|
19018
|
+
"cool",
|
|
19019
|
+
"auto",
|
|
19020
|
+
"heat_cool",
|
|
19021
|
+
"fan_only",
|
|
19022
|
+
"dry"
|
|
19023
|
+
],
|
|
19024
|
+
commandCaps: ["climate-control"]
|
|
18691
19025
|
})
|
|
18692
19026
|
];
|
|
18693
19027
|
function actuator(input) {
|
|
18694
19028
|
return {
|
|
18695
|
-
|
|
19029
|
+
id: input.id,
|
|
19030
|
+
summary: input.summary,
|
|
19031
|
+
deviceType: input.deviceType,
|
|
19032
|
+
outputCap: input.outputCap,
|
|
19033
|
+
outputField: input.outputField,
|
|
19034
|
+
commandCaps: input.commandCaps,
|
|
18696
19035
|
family: "actuator",
|
|
18697
19036
|
role: void 0,
|
|
18698
19037
|
memberDeviceType: input.deviceType,
|
|
18699
|
-
|
|
19038
|
+
memberDeviceTypes: input.memberDeviceTypes ?? [input.deviceType],
|
|
19039
|
+
activeWhen: input.activeWhen,
|
|
18700
19040
|
quantity: "none",
|
|
18701
19041
|
baseUnit: void 0,
|
|
18702
19042
|
aggregates: BINARY_AGGREGATES,
|
|
18703
19043
|
defaultAggregate: "any",
|
|
18704
19044
|
empty: "offline",
|
|
18705
|
-
accept: [
|
|
18706
|
-
cap: "switch",
|
|
18707
|
-
fieldPath: "on"
|
|
18708
|
-
}],
|
|
19045
|
+
accept: [input.member],
|
|
18709
19046
|
companions: [CHANGED]
|
|
18710
19047
|
};
|
|
18711
19048
|
}
|
|
18712
19049
|
new Map(GROUP_TEMPLATES.map((template) => [template.id, template]));
|
|
18713
19050
|
DeviceFeature.LightColorRgb, DeviceFeature.LightColorHsv, DeviceFeature.LightColorMired;
|
|
19051
|
+
DeviceType.Camera;
|
|
18714
19052
|
`${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
|
|
18715
19053
|
/**
|
|
18716
19054
|
* What a composition may BUILD on a device type (G2, D676): the caps a new
|
|
@@ -43725,7 +44063,7 @@ var NetworkAccessStatusSchema = object({
|
|
|
43725
44063
|
});
|
|
43726
44064
|
/**
|
|
43727
44065
|
* Optional, richer endpoint shape returned by providers that expose
|
|
43728
|
-
* MORE than one ingress concurrently (Tailscale
|
|
44066
|
+
* MORE than one ingress concurrently (Tailscale Funnel with mixed
|
|
43729
44067
|
* serve+funnel rules, future ngrok multi-tunnel, …). Each entry carries
|
|
43730
44068
|
* the originating provider config (mode + sourcePort) so the
|
|
43731
44069
|
* orchestrator UI can label rows distinctly. Providers that expose only
|
|
@@ -46368,7 +46706,20 @@ var NcRuleInputSchema = object({
|
|
|
46368
46706
|
* save by the hub's grouping guard). `.optional()`, never `.default()`: the addon cap
|
|
46369
46707
|
* path does not run Zod defaults.
|
|
46370
46708
|
*/
|
|
46371
|
-
groupingSec: number().int().min(5).max(60).optional()
|
|
46709
|
+
groupingSec: number().int().min(5).max(60).optional(),
|
|
46710
|
+
/**
|
|
46711
|
+
* ASK ME TO CONFIRM DETECTIONS (#243): a DETECTION notification of this rule
|
|
46712
|
+
* carries "Correct" / "Wrong" buttons (and, where the channel has room, a
|
|
46713
|
+
* "Wrong, it is a <class>" choice). A tap marks the track for retraining, the
|
|
46714
|
+
* same mark the Library writes, and records whose notification it was and
|
|
46715
|
+
* when. A channel with no buttons gets the same two choices as links.
|
|
46716
|
+
*
|
|
46717
|
+
* `.optional()`, never `.default()` (a Zod default does not run on the addon
|
|
46718
|
+
* cap path): absent and `false` both mean off, which is what every rule
|
|
46719
|
+
* authored before this field meant. An editor turns it off by writing
|
|
46720
|
+
* `false`, so it needs no `clear` key.
|
|
46721
|
+
*/
|
|
46722
|
+
askVerdict: boolean().optional()
|
|
46372
46723
|
});
|
|
46373
46724
|
/**
|
|
46374
46725
|
* Partial patch for `updateRule` — any subset of the input fields, plus the
|
|
@@ -56825,7 +57176,7 @@ var BatteryStatusSchema = object({
|
|
|
56825
57176
|
*/
|
|
56826
57177
|
binary: boolean().optional().meta({ label: "Binary indicator" })
|
|
56827
57178
|
});
|
|
56828
|
-
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat;
|
|
57179
|
+
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.EventEmitter;
|
|
56829
57180
|
method(object({
|
|
56830
57181
|
deviceId: number(),
|
|
56831
57182
|
/** Bound on the wait. Sensible range 3000–10000ms. */
|
|
@@ -58579,7 +58930,13 @@ results: array(object({
|
|
|
58579
58930
|
/** Ms epoch of the attempt. */
|
|
58580
58931
|
at: number()
|
|
58581
58932
|
})) });
|
|
58582
|
-
DeviceType.Switch, DeviceType.Light;
|
|
58933
|
+
DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Cover, DeviceType.Valve, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.Thermostat, DeviceType.Climate;
|
|
58934
|
+
object({
|
|
58935
|
+
active: boolean().meta({ label: "Active" }),
|
|
58936
|
+
/** Ms epoch when the slice was last updated. */
|
|
58937
|
+
lastChangedAt: number()
|
|
58938
|
+
});
|
|
58939
|
+
DeviceType.Cover, DeviceType.Valve, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.Climate, DeviceType.Thermostat;
|
|
58583
58940
|
object({
|
|
58584
58941
|
/** Members whose current value entered the aggregate. */
|
|
58585
58942
|
included: number().int().nonnegative().meta(readingMeta("count", {
|
|
@@ -58597,7 +58954,7 @@ object({
|
|
|
58597
58954
|
label: "Members"
|
|
58598
58955
|
}))
|
|
58599
58956
|
});
|
|
58600
|
-
DeviceType.Sensor, DeviceType.Switch, DeviceType.Light;
|
|
58957
|
+
DeviceType.Sensor, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Cover, DeviceType.Valve, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.Thermostat, DeviceType.Climate;
|
|
58601
58958
|
object({
|
|
58602
58959
|
/** Radiator valve opening 0 (closed) .. 100 (open). Null = not yet known. */
|
|
58603
58960
|
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
@@ -59504,7 +59861,14 @@ DeviceType.Lock, method(object({
|
|
|
59504
59861
|
auth: "protected"
|
|
59505
59862
|
}), method(object({
|
|
59506
59863
|
deviceId: number().int().nonnegative(),
|
|
59507
|
-
code: string().min(1).optional()
|
|
59864
|
+
code: string().min(1).optional(),
|
|
59865
|
+
/**
|
|
59866
|
+
* Honoured by a helper lock GROUP only (D944): unlocking several doors
|
|
59867
|
+
* with one call is refused unless the caller says it was confirmed. A
|
|
59868
|
+
* single lock ignores it. The refusal lives in the callee, so no
|
|
59869
|
+
* automation or API caller reaches the doors by skipping a dialog.
|
|
59870
|
+
*/
|
|
59871
|
+
confirm: boolean().optional()
|
|
59508
59872
|
}), _void(), {
|
|
59509
59873
|
kind: "mutation",
|
|
59510
59874
|
auth: "protected"
|
|
@@ -59512,6 +59876,11 @@ DeviceType.Lock, method(object({
|
|
|
59512
59876
|
kind: "mutation",
|
|
59513
59877
|
auth: "protected"
|
|
59514
59878
|
});
|
|
59879
|
+
object({
|
|
59880
|
+
value: number().nullable().meta(readingMeta("device", { label: "Total" })),
|
|
59881
|
+
lastFetchedAt: number()
|
|
59882
|
+
});
|
|
59883
|
+
DeviceType.Sensor;
|
|
59515
59884
|
/**
|
|
59516
59885
|
* Media-player cap. Models HA `media_player.*` (Sonos, Chromecast,
|
|
59517
59886
|
* Apple TV, Spotify, Roku, generic OTT receivers, …) on
|
|
@@ -61419,9 +61788,9 @@ object({
|
|
|
61419
61788
|
/** Cumulative energy in kilowatt-hours since the meter was reset. */
|
|
61420
61789
|
kwhTotal: number().optional().meta(readingMeta("energy", { label: "Energy" })),
|
|
61421
61790
|
/** Voltage in volts. */
|
|
61422
|
-
volts: number().optional().meta(readingMeta("voltage")),
|
|
61791
|
+
volts: number().optional().meta(readingMeta("voltage", { label: "Voltage" })),
|
|
61423
61792
|
/** Current in amperes. */
|
|
61424
|
-
amps: number().optional().meta(readingMeta("current")),
|
|
61793
|
+
amps: number().optional().meta(readingMeta("current", { label: "Current" })),
|
|
61425
61794
|
/** Apparent power in volt-amperes. */
|
|
61426
61795
|
va: number().optional().meta(readingMeta("apparent-power")),
|
|
61427
61796
|
/** Power factor (0..1) if reported. */
|
|
@@ -61429,7 +61798,23 @@ object({
|
|
|
61429
61798
|
/** Ms epoch when the slice was last updated. */
|
|
61430
61799
|
lastFetchedAt: number()
|
|
61431
61800
|
});
|
|
61432
|
-
|
|
61801
|
+
[
|
|
61802
|
+
DeviceType.Sensor,
|
|
61803
|
+
DeviceType.Switch,
|
|
61804
|
+
DeviceType.Light,
|
|
61805
|
+
DeviceType.Fan,
|
|
61806
|
+
DeviceType.Climate,
|
|
61807
|
+
DeviceType.Thermostat,
|
|
61808
|
+
DeviceType.Humidifier,
|
|
61809
|
+
DeviceType.WaterHeater,
|
|
61810
|
+
DeviceType.MediaPlayer,
|
|
61811
|
+
DeviceType.Washer,
|
|
61812
|
+
DeviceType.Dryer,
|
|
61813
|
+
DeviceType.Dishwasher,
|
|
61814
|
+
DeviceType.Vacuum,
|
|
61815
|
+
DeviceType.LawnMower,
|
|
61816
|
+
DeviceType.PetFeeder
|
|
61817
|
+
].filter((type) => type !== DeviceType.Sensor);
|
|
61433
61818
|
/**
|
|
61434
61819
|
* Presence cap. Models HA `person.*` and `device_tracker.*` entities
|
|
61435
61820
|
* on `DeviceType.Presence`. Read-only — no setters: presence is
|
|
@@ -61876,7 +62261,7 @@ object({
|
|
|
61876
62261
|
phase: string().nullable()
|
|
61877
62262
|
});
|
|
61878
62263
|
Object.values(DeviceType);
|
|
61879
|
-
DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
|
|
62264
|
+
DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
|
|
61880
62265
|
DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch, method(object({ deviceId: number().int().nonnegative() }), object({ success: literal(true) }), {
|
|
61881
62266
|
kind: "mutation",
|
|
61882
62267
|
auth: "admin"
|
|
@@ -63915,7 +64300,7 @@ object({
|
|
|
63915
64300
|
/** Ms epoch of the last state change. Useful for UI "X minutes ago". */
|
|
63916
64301
|
lastChangedAt: number()
|
|
63917
64302
|
});
|
|
63918
|
-
DeviceType.Switch, DeviceType.Siren, DeviceType.Light, method(object({
|
|
64303
|
+
DeviceType.Switch, DeviceType.Siren, DeviceType.Light, DeviceType.Fan, method(object({
|
|
63919
64304
|
deviceId: number(),
|
|
63920
64305
|
on: boolean()
|
|
63921
64306
|
}), _void(), {
|
|
@@ -65607,8 +65992,9 @@ method(object({}), array(TrainingBaseModelSchema).readonly(), { auth: "admin" })
|
|
|
65607
65992
|
kind: "mutation",
|
|
65608
65993
|
auth: "admin"
|
|
65609
65994
|
});
|
|
65995
|
+
DeviceFeature.FanSpeed, DeviceFeature.FanPreset, DeviceFeature.FanDirection, DeviceFeature.FanOscillating, DeviceFeature.CoverPositionable, DeviceFeature.CoverTilt, DeviceFeature.ValvePositionable, DeviceFeature.MediaPlayerVolume, DeviceFeature.ClimateFanMode;
|
|
65610
65996
|
SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
|
|
65611
|
-
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;
|
|
65997
|
+
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;
|
|
65612
65998
|
String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
|
|
65613
65999
|
DeviceRole.BinarySensor, DeviceRole.MotionSensor;
|
|
65614
66000
|
new Set(CAP_NAMES);
|
|
@@ -65661,7 +66047,7 @@ var AccessoryKind = {
|
|
|
65661
66047
|
PrivacyMask: DeviceRole.PrivacyMask
|
|
65662
66048
|
};
|
|
65663
66049
|
AccessoryKind.Siren, AccessoryKind.Floodlight, AccessoryKind.Spotlight, AccessoryKind.PirSensor, AccessoryKind.Chime, AccessoryKind.Autotrack, AccessoryKind.Nightvision, AccessoryKind.PrivacyMask;
|
|
65664
|
-
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;
|
|
66050
|
+
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;
|
|
65665
66051
|
new Set(Object.values(DeviceType));
|
|
65666
66052
|
Object.freeze({
|
|
65667
66053
|
"accessories.getStatus": {
|
|
@@ -68884,6 +69270,13 @@ Object.freeze({
|
|
|
68884
69270
|
access: "view",
|
|
68885
69271
|
role: "viewer"
|
|
68886
69272
|
},
|
|
69273
|
+
"groupActive.getStatus": {
|
|
69274
|
+
capName: "group-active",
|
|
69275
|
+
capScope: "device",
|
|
69276
|
+
addonId: null,
|
|
69277
|
+
access: "view",
|
|
69278
|
+
role: "viewer"
|
|
69279
|
+
},
|
|
68887
69280
|
"groupCommands.getStatus": {
|
|
68888
69281
|
capName: "group-commands",
|
|
68889
69282
|
capScope: "device",
|
|
@@ -69850,6 +70243,13 @@ Object.freeze({
|
|
|
69850
70243
|
access: "create",
|
|
69851
70244
|
role: "admin"
|
|
69852
70245
|
},
|
|
70246
|
+
"meter.getStatus": {
|
|
70247
|
+
capName: "meter",
|
|
70248
|
+
capScope: "device",
|
|
70249
|
+
addonId: null,
|
|
70250
|
+
access: "view",
|
|
70251
|
+
role: "viewer"
|
|
70252
|
+
},
|
|
69853
70253
|
"metricsProvider.collectSnapshot": {
|
|
69854
70254
|
capName: "metrics-provider",
|
|
69855
70255
|
capScope: "system",
|
|
@@ -77948,7 +78348,39 @@ var APPLIANCE_CAP_VOCABULARY = {
|
|
|
77948
78348
|
phrase: t("When {device} finishes", "Quando {device} finisce"),
|
|
77949
78349
|
icon: "square"
|
|
77950
78350
|
}
|
|
77951
|
-
}
|
|
78351
|
+
},
|
|
78352
|
+
overrides: { byType: {
|
|
78353
|
+
[DeviceType.Washer]: {
|
|
78354
|
+
state: { running: {
|
|
78355
|
+
whenTrue: t("When the washing machine starts", "Quando la lavatrice inizia"),
|
|
78356
|
+
whenFalse: t("When the washing machine has finished", "Quando la lavatrice ha finito")
|
|
78357
|
+
} },
|
|
78358
|
+
events: {
|
|
78359
|
+
onStarted: { phrase: t("When the washing machine starts", "Quando la lavatrice inizia") },
|
|
78360
|
+
onFinished: { phrase: t("When the washing machine has finished", "Quando la lavatrice ha finito") }
|
|
78361
|
+
}
|
|
78362
|
+
},
|
|
78363
|
+
[DeviceType.Dryer]: {
|
|
78364
|
+
state: { running: {
|
|
78365
|
+
whenTrue: t("When the dryer starts", "Quando l'asciugatrice inizia"),
|
|
78366
|
+
whenFalse: t("When the dryer has finished", "Quando l'asciugatrice ha finito")
|
|
78367
|
+
} },
|
|
78368
|
+
events: {
|
|
78369
|
+
onStarted: { phrase: t("When the dryer starts", "Quando l'asciugatrice inizia") },
|
|
78370
|
+
onFinished: { phrase: t("When the dryer has finished", "Quando l'asciugatrice ha finito") }
|
|
78371
|
+
}
|
|
78372
|
+
},
|
|
78373
|
+
[DeviceType.Dishwasher]: {
|
|
78374
|
+
state: { running: {
|
|
78375
|
+
whenTrue: t("When the dishwasher starts", "Quando la lavastoviglie inizia"),
|
|
78376
|
+
whenFalse: t("When the dishwasher has finished", "Quando la lavastoviglie ha finito")
|
|
78377
|
+
} },
|
|
78378
|
+
events: {
|
|
78379
|
+
onStarted: { phrase: t("When the dishwasher starts", "Quando la lavastoviglie inizia") },
|
|
78380
|
+
onFinished: { phrase: t("When the dishwasher has finished", "Quando la lavastoviglie ha finito") }
|
|
78381
|
+
}
|
|
78382
|
+
}
|
|
78383
|
+
} }
|
|
77952
78384
|
},
|
|
77953
78385
|
update: {
|
|
77954
78386
|
scope: "device",
|
|
@@ -78720,6 +79152,10 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78720
79152
|
icon: "flame"
|
|
78721
79153
|
}]
|
|
78722
79154
|
},
|
|
79155
|
+
"group-active": {
|
|
79156
|
+
scope: "device",
|
|
79157
|
+
noun: t("Group state", "Stato del gruppo")
|
|
79158
|
+
},
|
|
78723
79159
|
"group-commands": {
|
|
78724
79160
|
scope: "device",
|
|
78725
79161
|
noun: t("Group command", "Comando di gruppo")
|
|
@@ -78776,6 +79212,17 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78776
79212
|
}],
|
|
78777
79213
|
events: { onMotionChanged: { notOperatorFacing: "the `detected` state trigger phrases both edges, from the mirror that survives a dropped event (D49)" } }
|
|
78778
79214
|
},
|
|
79215
|
+
meter: {
|
|
79216
|
+
scope: "device",
|
|
79217
|
+
noun: t("Meter", "Contatore"),
|
|
79218
|
+
state: [{
|
|
79219
|
+
kind: "numeric",
|
|
79220
|
+
field: "value",
|
|
79221
|
+
quantity: t("the total", "il totale"),
|
|
79222
|
+
label: t("Total", "Totale"),
|
|
79223
|
+
icon: "gauge"
|
|
79224
|
+
}]
|
|
79225
|
+
},
|
|
78779
79226
|
"numeric-sensor": {
|
|
78780
79227
|
scope: "device",
|
|
78781
79228
|
noun: t("Sensor", "Sensore"),
|
|
@@ -79248,8 +79695,47 @@ function projectAction(cap, action) {
|
|
|
79248
79695
|
};
|
|
79249
79696
|
}
|
|
79250
79697
|
Object.entries(CAP_VOCABULARY_BY_NAME).flatMap(([cap, entry]) => entry.scope === "device" ? (entry.actions ?? []).map((a) => projectAction(cap, a)) : []);
|
|
79251
|
-
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;
|
|
79698
|
+
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;
|
|
79252
79699
|
DeviceFeature.BatteryOperated;
|
|
79700
|
+
DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher;
|
|
79701
|
+
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.";
|
|
79702
|
+
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.";
|
|
79703
|
+
var ALEXA_REASON = "Alexa has no laundry category in this export, and neither power nor running has an Alexa interface.";
|
|
79704
|
+
var GOOGLE_REASON = "Google WASHER, DRYER and DISHWASHER require RunCycle. A power threshold is not that trait, and this export does not publish RunCycle.";
|
|
79705
|
+
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.";
|
|
79706
|
+
function withheld(reason) {
|
|
79707
|
+
return {
|
|
79708
|
+
[DeviceType.Washer]: {
|
|
79709
|
+
exported: false,
|
|
79710
|
+
reason
|
|
79711
|
+
},
|
|
79712
|
+
[DeviceType.Dryer]: {
|
|
79713
|
+
exported: false,
|
|
79714
|
+
reason
|
|
79715
|
+
},
|
|
79716
|
+
[DeviceType.Dishwasher]: {
|
|
79717
|
+
exported: false,
|
|
79718
|
+
reason
|
|
79719
|
+
}
|
|
79720
|
+
};
|
|
79721
|
+
}
|
|
79722
|
+
function offered(received) {
|
|
79723
|
+
return {
|
|
79724
|
+
[DeviceType.Washer]: {
|
|
79725
|
+
exported: true,
|
|
79726
|
+
as: received
|
|
79727
|
+
},
|
|
79728
|
+
[DeviceType.Dryer]: {
|
|
79729
|
+
exported: true,
|
|
79730
|
+
as: received
|
|
79731
|
+
},
|
|
79732
|
+
[DeviceType.Dishwasher]: {
|
|
79733
|
+
exported: true,
|
|
79734
|
+
as: received
|
|
79735
|
+
}
|
|
79736
|
+
};
|
|
79737
|
+
}
|
|
79738
|
+
offered(HA_AS), withheld(HOMEKIT_REASON), withheld(ALEXA_REASON), withheld(GOOGLE_REASON), withheld(MATTER_REASON);
|
|
79253
79739
|
Object.freeze({
|
|
79254
79740
|
"accessories.getStatus": [{
|
|
79255
79741
|
name: "deviceId",
|
|
@@ -80216,6 +80702,11 @@ Object.freeze({
|
|
|
80216
80702
|
form: "single",
|
|
80217
80703
|
optional: false
|
|
80218
80704
|
}],
|
|
80705
|
+
"groupActive.getStatus": [{
|
|
80706
|
+
name: "deviceId",
|
|
80707
|
+
form: "single",
|
|
80708
|
+
optional: false
|
|
80709
|
+
}],
|
|
80219
80710
|
"groupCommands.getStatus": [{
|
|
80220
80711
|
name: "deviceId",
|
|
80221
80712
|
form: "single",
|
|
@@ -80426,6 +80917,11 @@ Object.freeze({
|
|
|
80426
80917
|
form: "single",
|
|
80427
80918
|
optional: false
|
|
80428
80919
|
}],
|
|
80920
|
+
"meter.getStatus": [{
|
|
80921
|
+
name: "deviceId",
|
|
80922
|
+
form: "single",
|
|
80923
|
+
optional: false
|
|
80924
|
+
}],
|
|
80429
80925
|
"motion.getStatus": [{
|
|
80430
80926
|
name: "deviceId",
|
|
80431
80927
|
form: "single",
|
|
@@ -82033,7 +82529,6 @@ Object.freeze({
|
|
|
82033
82529
|
"network-access": "ingress",
|
|
82034
82530
|
"smtp-provider": "email"
|
|
82035
82531
|
});
|
|
82036
|
-
DeviceType.Camera;
|
|
82037
82532
|
/**
|
|
82038
82533
|
* A saved Customize assignment (D936). The schema is the type: callers use
|
|
82039
82534
|
* `z.infer`, they do not restate the shape.
|