@camstack/addon-mqtt-broker 1.2.146 → 1.2.147
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 +22 -9
- package/dist/mqtt-broker.addon.js +540 -45
- package/dist/mqtt-broker.addon.mjs +540 -45
- package/package.json +1 -1
|
@@ -5615,7 +5615,7 @@ var ZodIssueCode = {
|
|
|
5615
5615
|
var ZodFirstPartyTypeKind;
|
|
5616
5616
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5617
5617
|
//#endregion
|
|
5618
|
-
//#region ../types/dist/sleep
|
|
5618
|
+
//#region ../types/dist/sleep--jXS9hWo.mjs
|
|
5619
5619
|
/**
|
|
5620
5620
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5621
5621
|
* window to float samples (D455).
|
|
@@ -8992,6 +8992,7 @@ var CAP_NAMES = Object.freeze([
|
|
|
8992
8992
|
"filesystem-browse",
|
|
8993
8993
|
"flood",
|
|
8994
8994
|
"gas",
|
|
8995
|
+
"group-active",
|
|
8995
8996
|
"group-commands",
|
|
8996
8997
|
"group-status",
|
|
8997
8998
|
"heating-valve",
|
|
@@ -9014,6 +9015,7 @@ var CAP_NAMES = Object.freeze([
|
|
|
9014
9015
|
"login-method",
|
|
9015
9016
|
"media-player",
|
|
9016
9017
|
"mesh-network",
|
|
9018
|
+
"meter",
|
|
9017
9019
|
"metrics-provider",
|
|
9018
9020
|
"model-convert",
|
|
9019
9021
|
"model-distributor",
|
|
@@ -9812,6 +9814,10 @@ Object.freeze({
|
|
|
9812
9814
|
"path": "detected",
|
|
9813
9815
|
"valueType": "boolean"
|
|
9814
9816
|
}],
|
|
9817
|
+
"group-active": [{
|
|
9818
|
+
"path": "active",
|
|
9819
|
+
"valueType": "boolean"
|
|
9820
|
+
}],
|
|
9815
9821
|
"group-status": [
|
|
9816
9822
|
{
|
|
9817
9823
|
"path": "included",
|
|
@@ -10071,6 +10077,10 @@ Object.freeze({
|
|
|
10071
10077
|
]
|
|
10072
10078
|
}
|
|
10073
10079
|
],
|
|
10080
|
+
"meter": [{
|
|
10081
|
+
"path": "value",
|
|
10082
|
+
"valueType": "number"
|
|
10083
|
+
}],
|
|
10074
10084
|
"motion": [
|
|
10075
10085
|
{
|
|
10076
10086
|
"path": "detected",
|
|
@@ -10814,7 +10824,7 @@ object({
|
|
|
10814
10824
|
params: record(string(), union([string(), number()])).optional()
|
|
10815
10825
|
});
|
|
10816
10826
|
//#endregion
|
|
10817
|
-
//#region ../types/dist/err-msg-
|
|
10827
|
+
//#region ../types/dist/err-msg-DIorGYeC.mjs
|
|
10818
10828
|
var DeviceType = /* @__PURE__ */ function(DeviceType) {
|
|
10819
10829
|
DeviceType["Camera"] = "camera";
|
|
10820
10830
|
DeviceType["Hub"] = "hub";
|
|
@@ -10908,8 +10918,14 @@ var DeviceType = /* @__PURE__ */ function(DeviceType) {
|
|
|
10908
10918
|
DeviceType["PetFeeder"] = "pet-feeder";
|
|
10909
10919
|
/** Built-in dishwasher — program lifecycle, door / remote-start gates,
|
|
10910
10920
|
* salt and rinse-aid levels. Installed with the `dishwasher` cap.
|
|
10911
|
-
* Sources: native Bosch Home Connect, reusable by similar integrations.
|
|
10921
|
+
* Sources: native Bosch Home Connect, reusable by similar integrations.
|
|
10922
|
+
* A plug-built dishwasher carries running-state and power instead. */
|
|
10912
10923
|
DeviceType["Dishwasher"] = "dishwasher";
|
|
10924
|
+
/** Washing machine. A plug-built one is running while its power stays
|
|
10925
|
+
* above a threshold. No program cap — that surface is the dishwasher's. */
|
|
10926
|
+
DeviceType["Washer"] = "washer";
|
|
10927
|
+
/** Tumble dryer. Same plug-built running surface as {@link Washer}. */
|
|
10928
|
+
DeviceType["Dryer"] = "dryer";
|
|
10913
10929
|
return DeviceType;
|
|
10914
10930
|
}({});
|
|
10915
10931
|
var DeviceFeature = /* @__PURE__ */ function(DeviceFeature) {
|
|
@@ -11157,7 +11173,7 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
|
|
|
11157
11173
|
return DeviceRole;
|
|
11158
11174
|
}({});
|
|
11159
11175
|
//#endregion
|
|
11160
|
-
//#region ../types/dist/composition-
|
|
11176
|
+
//#region ../types/dist/composition-Bb8iwHEJ.mjs
|
|
11161
11177
|
/**
|
|
11162
11178
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
11163
11179
|
*
|
|
@@ -11472,6 +11488,13 @@ var table = {
|
|
|
11472
11488
|
apply: () => {
|
|
11473
11489
|
throw new ExpressionEvalError("latchedAt: stateful evaluation context is required");
|
|
11474
11490
|
}
|
|
11491
|
+
},
|
|
11492
|
+
schmitt: {
|
|
11493
|
+
minArgs: 3,
|
|
11494
|
+
maxArgs: 5,
|
|
11495
|
+
apply: () => {
|
|
11496
|
+
throw new ExpressionEvalError("schmitt: stateful evaluation context is required");
|
|
11497
|
+
}
|
|
11475
11498
|
}
|
|
11476
11499
|
};
|
|
11477
11500
|
Object.freeze(Object.assign(Object.create(null), table));
|
|
@@ -11913,6 +11936,99 @@ function validateExpressionSource(src) {
|
|
|
11913
11936
|
return null;
|
|
11914
11937
|
}
|
|
11915
11938
|
/**
|
|
11939
|
+
* One power reading becomes a washer, dryer or dishwasher (D944 helper).
|
|
11940
|
+
*
|
|
11941
|
+
* Standby of the control board is under 5 W; a motor or a heater is far
|
|
11942
|
+
* above that, so 5 W is the line. A door lock or a short pump spike is not
|
|
11943
|
+
* a cycle, so running starts only after 30 s above the line.
|
|
11944
|
+
*
|
|
11945
|
+
* A wash, dry or dishwasher pause (soak, heat-wait, heater off between
|
|
11946
|
+
* bursts) lasts several minutes. Ending the cycle on the first dip would
|
|
11947
|
+
* report "finished" in the middle of the program, so the stop dwell is
|
|
11948
|
+
* 10 minutes on every type. The number is stored per type so one machine
|
|
11949
|
+
* can move later without moving the others.
|
|
11950
|
+
*/
|
|
11951
|
+
var APPLIANCE_TEMPLATE_ID = "appliance";
|
|
11952
|
+
var APPLIANCE_KINDS = [
|
|
11953
|
+
"washer",
|
|
11954
|
+
"dryer",
|
|
11955
|
+
"dishwasher"
|
|
11956
|
+
];
|
|
11957
|
+
DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher;
|
|
11958
|
+
/**
|
|
11959
|
+
* Statistics and integrals over a history read (D944).
|
|
11960
|
+
*
|
|
11961
|
+
* Pure: the same points always give the same answer, so a restart recomputes
|
|
11962
|
+
* rather than trusting a buffer. A gauge mean is time-weighted (value × ms),
|
|
11963
|
+
* never the mean of the samples. A hole with no held value is not integrated
|
|
11964
|
+
* as zero. A truncated read is not published.
|
|
11965
|
+
*/
|
|
11966
|
+
var STATISTIC_STATS = [
|
|
11967
|
+
"min",
|
|
11968
|
+
"max",
|
|
11969
|
+
"mean",
|
|
11970
|
+
"sum",
|
|
11971
|
+
"count",
|
|
11972
|
+
"change"
|
|
11973
|
+
];
|
|
11974
|
+
/**
|
|
11975
|
+
* The range a statistics or integral helper asks history for (D944).
|
|
11976
|
+
*
|
|
11977
|
+
* Calendar edges are the hub's timezone, never UTC midnight: a day is 23, 24
|
|
11978
|
+
* or 25 hours across a DST change. A tier is eligible only when its retention
|
|
11979
|
+
* is strictly longer than the longest that range can be. Forever qualifies.
|
|
11980
|
+
* Equal to a tier's retention is a refusal, not a short answer.
|
|
11981
|
+
*/
|
|
11982
|
+
var MINUTE_MS = 6e4;
|
|
11983
|
+
var HOUR_MS = 60 * MINUTE_MS;
|
|
11984
|
+
var DAY_MS = 24 * HOUR_MS;
|
|
11985
|
+
var ROLLING_SPANS = [
|
|
11986
|
+
"1h",
|
|
11987
|
+
"24h",
|
|
11988
|
+
"2d",
|
|
11989
|
+
"7d",
|
|
11990
|
+
"30d",
|
|
11991
|
+
"custom"
|
|
11992
|
+
];
|
|
11993
|
+
var CALENDAR_PERIODS = [
|
|
11994
|
+
"today",
|
|
11995
|
+
"yesterday",
|
|
11996
|
+
"this-week",
|
|
11997
|
+
"this-month"
|
|
11998
|
+
];
|
|
11999
|
+
var RESET_PERIODS = [
|
|
12000
|
+
"never",
|
|
12001
|
+
"daily",
|
|
12002
|
+
"weekly",
|
|
12003
|
+
"monthly"
|
|
12004
|
+
];
|
|
12005
|
+
5 * MINUTE_MS;
|
|
12006
|
+
24 * HOUR_MS, 2 * DAY_MS, 7 * DAY_MS, 30 * DAY_MS;
|
|
12007
|
+
7 * DAY_MS, 30 * DAY_MS, 365 * DAY_MS;
|
|
12008
|
+
var rollingWindowObject = object({
|
|
12009
|
+
kind: literal("rolling"),
|
|
12010
|
+
span: _enum(ROLLING_SPANS),
|
|
12011
|
+
customMinutes: number().int().min(5).optional()
|
|
12012
|
+
}).check((payload) => {
|
|
12013
|
+
if (payload.value.span === "custom" && payload.value.customMinutes === void 0) payload.issues.push({
|
|
12014
|
+
code: "custom",
|
|
12015
|
+
message: "a custom range needs a duration in minutes",
|
|
12016
|
+
path: ["customMinutes"],
|
|
12017
|
+
input: payload.value
|
|
12018
|
+
});
|
|
12019
|
+
if (payload.value.span !== "custom" && payload.value.customMinutes !== void 0) payload.issues.push({
|
|
12020
|
+
code: "custom",
|
|
12021
|
+
message: "only a custom range carries a duration",
|
|
12022
|
+
path: ["customMinutes"],
|
|
12023
|
+
input: payload.value
|
|
12024
|
+
});
|
|
12025
|
+
});
|
|
12026
|
+
var RollingWindowSchema = rollingWindowObject;
|
|
12027
|
+
var StatisticWindowSchema = discriminatedUnion("kind", [rollingWindowObject, object({
|
|
12028
|
+
kind: literal("calendar"),
|
|
12029
|
+
period: _enum(CALENDAR_PERIODS)
|
|
12030
|
+
})]);
|
|
12031
|
+
/**
|
|
11916
12032
|
* A composition source identity: `(addonId, stableId)`, never a numeric device
|
|
11917
12033
|
* id. Split out so helper schemas can name it without a cycle through
|
|
11918
12034
|
* `composition.ts` (D659).
|
|
@@ -11938,7 +12054,13 @@ var GROUP_TEMPLATE_IDS = [
|
|
|
11938
12054
|
"occupancy",
|
|
11939
12055
|
"binary",
|
|
11940
12056
|
"switch",
|
|
11941
|
-
"light"
|
|
12057
|
+
"light",
|
|
12058
|
+
"fan",
|
|
12059
|
+
"cover",
|
|
12060
|
+
"valve",
|
|
12061
|
+
"lock",
|
|
12062
|
+
"media-player",
|
|
12063
|
+
"climate"
|
|
11942
12064
|
];
|
|
11943
12065
|
var NUMERIC_AGGREGATES = [
|
|
11944
12066
|
"mean",
|
|
@@ -11968,14 +12090,73 @@ var HelperMemberSchema = object({
|
|
|
11968
12090
|
cap: string().min(1),
|
|
11969
12091
|
fieldPath: string().min(1)
|
|
11970
12092
|
});
|
|
11971
|
-
var HelperSpecSchema = discriminatedUnion("kind", [
|
|
11972
|
-
|
|
11973
|
-
|
|
11974
|
-
|
|
11975
|
-
|
|
11976
|
-
|
|
11977
|
-
|
|
11978
|
-
|
|
12093
|
+
var HelperSpecSchema = discriminatedUnion("kind", [
|
|
12094
|
+
object({
|
|
12095
|
+
kind: literal("group"),
|
|
12096
|
+
templateId: GroupTemplateIdSchema,
|
|
12097
|
+
aggregate: AggregateReducerSchema,
|
|
12098
|
+
members: array(HelperMemberSchema).min(1).max(64),
|
|
12099
|
+
/** Actuator groups only. Readings leave this unset. */
|
|
12100
|
+
active: ActiveCriterionSchema.optional()
|
|
12101
|
+
}),
|
|
12102
|
+
object({
|
|
12103
|
+
kind: literal("appliance"),
|
|
12104
|
+
templateId: literal(APPLIANCE_TEMPLATE_ID),
|
|
12105
|
+
appliance: _enum(APPLIANCE_KINDS),
|
|
12106
|
+
thresholdWatts: number().positive(),
|
|
12107
|
+
startDwellMs: number().int().nonnegative(),
|
|
12108
|
+
stopDwellMs: number().int().nonnegative(),
|
|
12109
|
+
member: HelperMemberSchema
|
|
12110
|
+
}),
|
|
12111
|
+
object({
|
|
12112
|
+
kind: literal("statistic"),
|
|
12113
|
+
stat: _enum(STATISTIC_STATS),
|
|
12114
|
+
window: StatisticWindowSchema,
|
|
12115
|
+
source: HelperMemberSchema
|
|
12116
|
+
}),
|
|
12117
|
+
object({
|
|
12118
|
+
kind: literal("integral"),
|
|
12119
|
+
reset: _enum(RESET_PERIODS),
|
|
12120
|
+
output: _enum(["energy", "meter"]),
|
|
12121
|
+
source: HelperMemberSchema
|
|
12122
|
+
}),
|
|
12123
|
+
object({
|
|
12124
|
+
kind: literal("threshold"),
|
|
12125
|
+
source: HelperMemberSchema,
|
|
12126
|
+
high: number(),
|
|
12127
|
+
low: number(),
|
|
12128
|
+
onForMs: number().int().nonnegative(),
|
|
12129
|
+
offForMs: number().int().nonnegative()
|
|
12130
|
+
}),
|
|
12131
|
+
object({
|
|
12132
|
+
kind: literal("arithmetic"),
|
|
12133
|
+
op: _enum([
|
|
12134
|
+
"sum",
|
|
12135
|
+
"difference",
|
|
12136
|
+
"ratio"
|
|
12137
|
+
]),
|
|
12138
|
+
inputs: array(HelperMemberSchema).min(2).max(64)
|
|
12139
|
+
}),
|
|
12140
|
+
object({
|
|
12141
|
+
kind: literal("expression"),
|
|
12142
|
+
expr: string().min(1),
|
|
12143
|
+
inputs: array(object({
|
|
12144
|
+
name: string().min(1),
|
|
12145
|
+
member: HelperMemberSchema
|
|
12146
|
+
})).min(1).max(64),
|
|
12147
|
+
output: _enum(["number", "boolean"])
|
|
12148
|
+
}),
|
|
12149
|
+
object({
|
|
12150
|
+
kind: literal("derivative"),
|
|
12151
|
+
window: RollingWindowSchema,
|
|
12152
|
+
per: _enum([
|
|
12153
|
+
"second",
|
|
12154
|
+
"minute",
|
|
12155
|
+
"hour"
|
|
12156
|
+
]),
|
|
12157
|
+
source: HelperMemberSchema
|
|
12158
|
+
})
|
|
12159
|
+
]);
|
|
11979
12160
|
/** A composed device's stableId is this prefix plus the block id. */
|
|
11980
12161
|
var COMPOSED_DEVICE_STABLE_ID_PREFIX = "composed-";
|
|
11981
12162
|
/** Longest snippet a `code` source may carry (slice 4). */
|
|
@@ -12036,6 +12217,12 @@ var CompositionFieldSourceSchema = discriminatedUnion("kind", [
|
|
|
12036
12217
|
"all"
|
|
12037
12218
|
]),
|
|
12038
12219
|
reads: array(CompositionFieldReadSchema).min(1).max(64),
|
|
12220
|
+
/**
|
|
12221
|
+
* Set when the reads are an enum state, not a yes/no: the listed states
|
|
12222
|
+
* count as active (a cover is `open`). A state outside the list is inactive;
|
|
12223
|
+
* a read that is not a state at all is left out. Only `any` / `all` use it.
|
|
12224
|
+
*/
|
|
12225
|
+
activeWhen: array(string().min(1)).min(1).optional(),
|
|
12039
12226
|
/** `value` is the reading; the others are the member counts. */
|
|
12040
12227
|
publish: _enum([
|
|
12041
12228
|
"value",
|
|
@@ -12049,6 +12236,26 @@ var CompositionFieldSourceSchema = discriminatedUnion("kind", [
|
|
|
12049
12236
|
"omit",
|
|
12050
12237
|
"offline"
|
|
12051
12238
|
])
|
|
12239
|
+
}),
|
|
12240
|
+
object({
|
|
12241
|
+
kind: literal("series"),
|
|
12242
|
+
read: CompositionFieldReadSchema,
|
|
12243
|
+
/** `value` is the statistic or the integral. The others are the gap counts. */
|
|
12244
|
+
publish: _enum([
|
|
12245
|
+
"value",
|
|
12246
|
+
"included",
|
|
12247
|
+
"excluded",
|
|
12248
|
+
"total"
|
|
12249
|
+
]),
|
|
12250
|
+
/**
|
|
12251
|
+
* What an unanswered `value` does. Counts ignore this. `offline` leaves the
|
|
12252
|
+
* device unseeded until history answers, so a restart cannot publish 0.
|
|
12253
|
+
*/
|
|
12254
|
+
empty: _enum([
|
|
12255
|
+
"null",
|
|
12256
|
+
"omit",
|
|
12257
|
+
"offline"
|
|
12258
|
+
])
|
|
12052
12259
|
})
|
|
12053
12260
|
]);
|
|
12054
12261
|
var CompositionCommandTargetSchema = discriminatedUnion("kind", [object({
|
|
@@ -17208,7 +17415,22 @@ var BrokerProviderInfoSchema = object({
|
|
|
17208
17415
|
*/
|
|
17209
17416
|
interactiveConnectPath: string().min(1).optional(),
|
|
17210
17417
|
/** Relative hub path to disconnect the linked account (same popup pattern). */
|
|
17211
|
-
interactiveDisconnectPath: string().min(1).optional()
|
|
17418
|
+
interactiveDisconnectPath: string().min(1).optional(),
|
|
17419
|
+
/**
|
|
17420
|
+
* The kind signs in through a server-held interactive session instead of
|
|
17421
|
+
* (or before) typed credentials. `basePath` is a hub-relative route set
|
|
17422
|
+
* served by the owning addon (`/addon/<id>/...`) speaking the sign-in
|
|
17423
|
+
* contract: `POST {basePath}/start` (body: the form's settings) answers
|
|
17424
|
+
* `{ sessionId, loginUrl }`; `GET {basePath}/status?sessionId=` answers
|
|
17425
|
+
* `{ phase: 'starting' | 'awaiting-login' | 'captured' | 'error' |
|
|
17426
|
+
* 'cancelled', loginUrl, error }`; `POST {basePath}/commit`
|
|
17427
|
+
* (`{ sessionId, name, brokerId? }`) stores the credentials on a new or
|
|
17428
|
+
* existing broker and answers `{ brokerId }`; `POST {basePath}/cancel`
|
|
17429
|
+
* (`{ sessionId }`) drops the session. The dialog that edits a broker
|
|
17430
|
+
* offers it as the default path; the fields the session fills are
|
|
17431
|
+
* marked `filledBySignIn` in the kind's settings schema.
|
|
17432
|
+
*/
|
|
17433
|
+
signIn: object({ basePath: string().min(1) }).optional()
|
|
17212
17434
|
}))
|
|
17213
17435
|
});
|
|
17214
17436
|
var ListInputSchema = object({
|
|
@@ -18256,7 +18478,8 @@ var CompositionProblemSchema = object({
|
|
|
18256
18478
|
"native-capability-replace",
|
|
18257
18479
|
"mixed-quantity",
|
|
18258
18480
|
"helper-mismatch",
|
|
18259
|
-
"member-constraint"
|
|
18481
|
+
"member-constraint",
|
|
18482
|
+
"retention"
|
|
18260
18483
|
]),
|
|
18261
18484
|
path: string(),
|
|
18262
18485
|
message: string()
|
|
@@ -18490,13 +18713,17 @@ Object.freeze({
|
|
|
18490
18713
|
latchedAt: {
|
|
18491
18714
|
kind: "fixed",
|
|
18492
18715
|
result: ["number", "null"]
|
|
18716
|
+
},
|
|
18717
|
+
schmitt: {
|
|
18718
|
+
kind: "fixed",
|
|
18719
|
+
result: ["boolean", "null"]
|
|
18493
18720
|
}
|
|
18494
18721
|
});
|
|
18495
18722
|
/**
|
|
18496
18723
|
* One catalog row per base reading a group helper can build (D944 §3).
|
|
18497
18724
|
* Data, not a form default written into the block.
|
|
18498
18725
|
*/
|
|
18499
|
-
var NOW = {
|
|
18726
|
+
var NOW$2 = {
|
|
18500
18727
|
fieldPath: "lastFetchedAt",
|
|
18501
18728
|
expr: "now"
|
|
18502
18729
|
};
|
|
@@ -18510,6 +18737,8 @@ function numeric(input) {
|
|
|
18510
18737
|
family: "numeric",
|
|
18511
18738
|
deviceType: DeviceType.Sensor,
|
|
18512
18739
|
memberDeviceType: DeviceType.Sensor,
|
|
18740
|
+
memberDeviceTypes: [DeviceType.Sensor],
|
|
18741
|
+
activeWhen: void 0,
|
|
18513
18742
|
commandCaps: [],
|
|
18514
18743
|
baseUnit: baseUnitOf(input.quantity),
|
|
18515
18744
|
aggregates: NUMERIC_AGGREGATES,
|
|
@@ -18525,6 +18754,8 @@ function binary(input) {
|
|
|
18525
18754
|
family: "binary",
|
|
18526
18755
|
deviceType: DeviceType.Sensor,
|
|
18527
18756
|
memberDeviceType: DeviceType.Sensor,
|
|
18757
|
+
memberDeviceTypes: [DeviceType.Sensor],
|
|
18758
|
+
activeWhen: void 0,
|
|
18528
18759
|
commandCaps: [],
|
|
18529
18760
|
quantity: "none",
|
|
18530
18761
|
baseUnit: void 0,
|
|
@@ -18542,7 +18773,7 @@ var GROUP_TEMPLATES = [
|
|
|
18542
18773
|
quantity: "temperature",
|
|
18543
18774
|
defaultAggregate: "mean",
|
|
18544
18775
|
empty: "null",
|
|
18545
|
-
companions: [NOW]
|
|
18776
|
+
companions: [NOW$2]
|
|
18546
18777
|
}),
|
|
18547
18778
|
numeric({
|
|
18548
18779
|
id: "humidity",
|
|
@@ -18553,7 +18784,7 @@ var GROUP_TEMPLATES = [
|
|
|
18553
18784
|
quantity: "humidity",
|
|
18554
18785
|
defaultAggregate: "mean",
|
|
18555
18786
|
empty: "null",
|
|
18556
|
-
companions: [NOW]
|
|
18787
|
+
companions: [NOW$2]
|
|
18557
18788
|
}),
|
|
18558
18789
|
numeric({
|
|
18559
18790
|
id: "pressure",
|
|
@@ -18564,7 +18795,7 @@ var GROUP_TEMPLATES = [
|
|
|
18564
18795
|
quantity: "pressure",
|
|
18565
18796
|
defaultAggregate: "mean",
|
|
18566
18797
|
empty: "null",
|
|
18567
|
-
companions: [NOW]
|
|
18798
|
+
companions: [NOW$2]
|
|
18568
18799
|
}),
|
|
18569
18800
|
numeric({
|
|
18570
18801
|
id: "illuminance",
|
|
@@ -18575,7 +18806,7 @@ var GROUP_TEMPLATES = [
|
|
|
18575
18806
|
quantity: "illuminance",
|
|
18576
18807
|
defaultAggregate: "mean",
|
|
18577
18808
|
empty: "null",
|
|
18578
|
-
companions: [NOW]
|
|
18809
|
+
companions: [NOW$2]
|
|
18579
18810
|
}),
|
|
18580
18811
|
numeric({
|
|
18581
18812
|
id: "power",
|
|
@@ -18586,7 +18817,7 @@ var GROUP_TEMPLATES = [
|
|
|
18586
18817
|
quantity: "power",
|
|
18587
18818
|
defaultAggregate: "sum",
|
|
18588
18819
|
empty: "omit",
|
|
18589
|
-
companions: [NOW]
|
|
18820
|
+
companions: [NOW$2]
|
|
18590
18821
|
}),
|
|
18591
18822
|
numeric({
|
|
18592
18823
|
id: "energy",
|
|
@@ -18597,7 +18828,7 @@ var GROUP_TEMPLATES = [
|
|
|
18597
18828
|
quantity: "energy",
|
|
18598
18829
|
defaultAggregate: "sum",
|
|
18599
18830
|
empty: "omit",
|
|
18600
|
-
companions: [NOW]
|
|
18831
|
+
companions: [NOW$2]
|
|
18601
18832
|
}),
|
|
18602
18833
|
numeric({
|
|
18603
18834
|
id: "battery",
|
|
@@ -18632,7 +18863,7 @@ var GROUP_TEMPLATES = [
|
|
|
18632
18863
|
quantity: "device",
|
|
18633
18864
|
defaultAggregate: "mean",
|
|
18634
18865
|
empty: "null",
|
|
18635
|
-
companions: [NOW]
|
|
18866
|
+
companions: [NOW$2]
|
|
18636
18867
|
}),
|
|
18637
18868
|
binary({
|
|
18638
18869
|
id: "motion",
|
|
@@ -18726,6 +18957,11 @@ var GROUP_TEMPLATES = [
|
|
|
18726
18957
|
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.",
|
|
18727
18958
|
deviceType: DeviceType.Switch,
|
|
18728
18959
|
outputCap: "switch",
|
|
18960
|
+
outputField: "on",
|
|
18961
|
+
member: {
|
|
18962
|
+
cap: "switch",
|
|
18963
|
+
fieldPath: "on"
|
|
18964
|
+
},
|
|
18729
18965
|
commandCaps: ["switch"]
|
|
18730
18966
|
}),
|
|
18731
18967
|
actuator({
|
|
@@ -18733,34 +18969,136 @@ var GROUP_TEMPLATES = [
|
|
|
18733
18969
|
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.",
|
|
18734
18970
|
deviceType: DeviceType.Light,
|
|
18735
18971
|
outputCap: "switch",
|
|
18972
|
+
outputField: "on",
|
|
18973
|
+
member: {
|
|
18974
|
+
cap: "switch",
|
|
18975
|
+
fieldPath: "on"
|
|
18976
|
+
},
|
|
18736
18977
|
commandCaps: [
|
|
18737
18978
|
"switch",
|
|
18738
18979
|
"brightness",
|
|
18739
18980
|
"color"
|
|
18740
18981
|
]
|
|
18982
|
+
}),
|
|
18983
|
+
actuator({
|
|
18984
|
+
id: "fan",
|
|
18985
|
+
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.",
|
|
18986
|
+
deviceType: DeviceType.Fan,
|
|
18987
|
+
outputCap: "switch",
|
|
18988
|
+
outputField: "on",
|
|
18989
|
+
member: {
|
|
18990
|
+
cap: "switch",
|
|
18991
|
+
fieldPath: "on"
|
|
18992
|
+
},
|
|
18993
|
+
commandCaps: ["switch", "fan-control"]
|
|
18994
|
+
}),
|
|
18995
|
+
actuator({
|
|
18996
|
+
id: "cover",
|
|
18997
|
+
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.",
|
|
18998
|
+
deviceType: DeviceType.Cover,
|
|
18999
|
+
outputCap: "group-active",
|
|
19000
|
+
outputField: "active",
|
|
19001
|
+
member: {
|
|
19002
|
+
cap: "cover",
|
|
19003
|
+
fieldPath: "state"
|
|
19004
|
+
},
|
|
19005
|
+
activeWhen: [
|
|
19006
|
+
"open",
|
|
19007
|
+
"opening",
|
|
19008
|
+
"stopped"
|
|
19009
|
+
],
|
|
19010
|
+
commandCaps: ["cover"]
|
|
19011
|
+
}),
|
|
19012
|
+
actuator({
|
|
19013
|
+
id: "valve",
|
|
19014
|
+
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.",
|
|
19015
|
+
deviceType: DeviceType.Valve,
|
|
19016
|
+
outputCap: "group-active",
|
|
19017
|
+
outputField: "active",
|
|
19018
|
+
member: {
|
|
19019
|
+
cap: "valve",
|
|
19020
|
+
fieldPath: "state"
|
|
19021
|
+
},
|
|
19022
|
+
activeWhen: [
|
|
19023
|
+
"open",
|
|
19024
|
+
"opening",
|
|
19025
|
+
"stopped"
|
|
19026
|
+
],
|
|
19027
|
+
commandCaps: ["valve"]
|
|
19028
|
+
}),
|
|
19029
|
+
actuator({
|
|
19030
|
+
id: "lock",
|
|
19031
|
+
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.",
|
|
19032
|
+
deviceType: DeviceType.Lock,
|
|
19033
|
+
outputCap: "group-active",
|
|
19034
|
+
outputField: "active",
|
|
19035
|
+
member: {
|
|
19036
|
+
cap: "lock-control",
|
|
19037
|
+
fieldPath: "state"
|
|
19038
|
+
},
|
|
19039
|
+
activeWhen: ["locked"],
|
|
19040
|
+
commandCaps: ["lock-control"]
|
|
19041
|
+
}),
|
|
19042
|
+
actuator({
|
|
19043
|
+
id: "media-player",
|
|
19044
|
+
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.",
|
|
19045
|
+
deviceType: DeviceType.MediaPlayer,
|
|
19046
|
+
outputCap: "group-active",
|
|
19047
|
+
outputField: "active",
|
|
19048
|
+
member: {
|
|
19049
|
+
cap: "media-player",
|
|
19050
|
+
fieldPath: "state"
|
|
19051
|
+
},
|
|
19052
|
+
activeWhen: ["playing", "buffering"],
|
|
19053
|
+
commandCaps: ["media-player"]
|
|
19054
|
+
}),
|
|
19055
|
+
actuator({
|
|
19056
|
+
id: "climate",
|
|
19057
|
+
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.",
|
|
19058
|
+
deviceType: DeviceType.Thermostat,
|
|
19059
|
+
memberDeviceTypes: [DeviceType.Thermostat, DeviceType.Climate],
|
|
19060
|
+
outputCap: "group-active",
|
|
19061
|
+
outputField: "active",
|
|
19062
|
+
member: {
|
|
19063
|
+
cap: "climate-control",
|
|
19064
|
+
fieldPath: "mode"
|
|
19065
|
+
},
|
|
19066
|
+
activeWhen: [
|
|
19067
|
+
"heat",
|
|
19068
|
+
"cool",
|
|
19069
|
+
"auto",
|
|
19070
|
+
"heat_cool",
|
|
19071
|
+
"fan_only",
|
|
19072
|
+
"dry"
|
|
19073
|
+
],
|
|
19074
|
+
commandCaps: ["climate-control"]
|
|
18741
19075
|
})
|
|
18742
19076
|
];
|
|
18743
19077
|
function actuator(input) {
|
|
18744
19078
|
return {
|
|
18745
|
-
|
|
19079
|
+
id: input.id,
|
|
19080
|
+
summary: input.summary,
|
|
19081
|
+
deviceType: input.deviceType,
|
|
19082
|
+
outputCap: input.outputCap,
|
|
19083
|
+
outputField: input.outputField,
|
|
19084
|
+
commandCaps: input.commandCaps,
|
|
18746
19085
|
family: "actuator",
|
|
18747
19086
|
role: void 0,
|
|
18748
19087
|
memberDeviceType: input.deviceType,
|
|
18749
|
-
|
|
19088
|
+
memberDeviceTypes: input.memberDeviceTypes ?? [input.deviceType],
|
|
19089
|
+
activeWhen: input.activeWhen,
|
|
18750
19090
|
quantity: "none",
|
|
18751
19091
|
baseUnit: void 0,
|
|
18752
19092
|
aggregates: BINARY_AGGREGATES,
|
|
18753
19093
|
defaultAggregate: "any",
|
|
18754
19094
|
empty: "offline",
|
|
18755
|
-
accept: [
|
|
18756
|
-
cap: "switch",
|
|
18757
|
-
fieldPath: "on"
|
|
18758
|
-
}],
|
|
19095
|
+
accept: [input.member],
|
|
18759
19096
|
companions: [CHANGED]
|
|
18760
19097
|
};
|
|
18761
19098
|
}
|
|
18762
19099
|
new Map(GROUP_TEMPLATES.map((template) => [template.id, template]));
|
|
18763
19100
|
DeviceFeature.LightColorRgb, DeviceFeature.LightColorHsv, DeviceFeature.LightColorMired;
|
|
19101
|
+
DeviceType.Camera;
|
|
18764
19102
|
`${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
|
|
18765
19103
|
/**
|
|
18766
19104
|
* What a composition may BUILD on a device type (G2, D676): the caps a new
|
|
@@ -43794,7 +44132,7 @@ var NetworkAccessStatusSchema = object({
|
|
|
43794
44132
|
});
|
|
43795
44133
|
/**
|
|
43796
44134
|
* Optional, richer endpoint shape returned by providers that expose
|
|
43797
|
-
* MORE than one ingress concurrently (Tailscale
|
|
44135
|
+
* MORE than one ingress concurrently (Tailscale Funnel with mixed
|
|
43798
44136
|
* serve+funnel rules, future ngrok multi-tunnel, …). Each entry carries
|
|
43799
44137
|
* the originating provider config (mode + sourcePort) so the
|
|
43800
44138
|
* orchestrator UI can label rows distinctly. Providers that expose only
|
|
@@ -46437,7 +46775,20 @@ var NcRuleInputSchema = object({
|
|
|
46437
46775
|
* save by the hub's grouping guard). `.optional()`, never `.default()`: the addon cap
|
|
46438
46776
|
* path does not run Zod defaults.
|
|
46439
46777
|
*/
|
|
46440
|
-
groupingSec: number().int().min(5).max(60).optional()
|
|
46778
|
+
groupingSec: number().int().min(5).max(60).optional(),
|
|
46779
|
+
/**
|
|
46780
|
+
* ASK ME TO CONFIRM DETECTIONS (#243): a DETECTION notification of this rule
|
|
46781
|
+
* carries "Correct" / "Wrong" buttons (and, where the channel has room, a
|
|
46782
|
+
* "Wrong, it is a <class>" choice). A tap marks the track for retraining, the
|
|
46783
|
+
* same mark the Library writes, and records whose notification it was and
|
|
46784
|
+
* when. A channel with no buttons gets the same two choices as links.
|
|
46785
|
+
*
|
|
46786
|
+
* `.optional()`, never `.default()` (a Zod default does not run on the addon
|
|
46787
|
+
* cap path): absent and `false` both mean off, which is what every rule
|
|
46788
|
+
* authored before this field meant. An editor turns it off by writing
|
|
46789
|
+
* `false`, so it needs no `clear` key.
|
|
46790
|
+
*/
|
|
46791
|
+
askVerdict: boolean().optional()
|
|
46441
46792
|
});
|
|
46442
46793
|
/**
|
|
46443
46794
|
* Partial patch for `updateRule` — any subset of the input fields, plus the
|
|
@@ -56894,7 +57245,7 @@ var BatteryStatusSchema = object({
|
|
|
56894
57245
|
*/
|
|
56895
57246
|
binary: boolean().optional().meta({ label: "Binary indicator" })
|
|
56896
57247
|
});
|
|
56897
|
-
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat;
|
|
57248
|
+
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.EventEmitter;
|
|
56898
57249
|
method(object({
|
|
56899
57250
|
deviceId: number(),
|
|
56900
57251
|
/** Bound on the wait. Sensible range 3000–10000ms. */
|
|
@@ -58638,7 +58989,13 @@ results: array(object({
|
|
|
58638
58989
|
/** Ms epoch of the attempt. */
|
|
58639
58990
|
at: number()
|
|
58640
58991
|
})) });
|
|
58641
|
-
DeviceType.Switch, DeviceType.Light;
|
|
58992
|
+
DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Cover, DeviceType.Valve, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.Thermostat, DeviceType.Climate;
|
|
58993
|
+
object({
|
|
58994
|
+
active: boolean().meta({ label: "Active" }),
|
|
58995
|
+
/** Ms epoch when the slice was last updated. */
|
|
58996
|
+
lastChangedAt: number()
|
|
58997
|
+
});
|
|
58998
|
+
DeviceType.Cover, DeviceType.Valve, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.Climate, DeviceType.Thermostat;
|
|
58642
58999
|
object({
|
|
58643
59000
|
/** Members whose current value entered the aggregate. */
|
|
58644
59001
|
included: number().int().nonnegative().meta(readingMeta("count", {
|
|
@@ -58656,7 +59013,7 @@ object({
|
|
|
58656
59013
|
label: "Members"
|
|
58657
59014
|
}))
|
|
58658
59015
|
});
|
|
58659
|
-
DeviceType.Sensor, DeviceType.Switch, DeviceType.Light;
|
|
59016
|
+
DeviceType.Sensor, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Cover, DeviceType.Valve, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.Thermostat, DeviceType.Climate;
|
|
58660
59017
|
object({
|
|
58661
59018
|
/** Radiator valve opening 0 (closed) .. 100 (open). Null = not yet known. */
|
|
58662
59019
|
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
@@ -59563,7 +59920,14 @@ DeviceType.Lock, method(object({
|
|
|
59563
59920
|
auth: "protected"
|
|
59564
59921
|
}), method(object({
|
|
59565
59922
|
deviceId: number().int().nonnegative(),
|
|
59566
|
-
code: string().min(1).optional()
|
|
59923
|
+
code: string().min(1).optional(),
|
|
59924
|
+
/**
|
|
59925
|
+
* Honoured by a helper lock GROUP only (D944): unlocking several doors
|
|
59926
|
+
* with one call is refused unless the caller says it was confirmed. A
|
|
59927
|
+
* single lock ignores it. The refusal lives in the callee, so no
|
|
59928
|
+
* automation or API caller reaches the doors by skipping a dialog.
|
|
59929
|
+
*/
|
|
59930
|
+
confirm: boolean().optional()
|
|
59567
59931
|
}), _void(), {
|
|
59568
59932
|
kind: "mutation",
|
|
59569
59933
|
auth: "protected"
|
|
@@ -59571,6 +59935,11 @@ DeviceType.Lock, method(object({
|
|
|
59571
59935
|
kind: "mutation",
|
|
59572
59936
|
auth: "protected"
|
|
59573
59937
|
});
|
|
59938
|
+
object({
|
|
59939
|
+
value: number().nullable().meta(readingMeta("device", { label: "Total" })),
|
|
59940
|
+
lastFetchedAt: number()
|
|
59941
|
+
});
|
|
59942
|
+
DeviceType.Sensor;
|
|
59574
59943
|
/**
|
|
59575
59944
|
* Media-player cap. Models HA `media_player.*` (Sonos, Chromecast,
|
|
59576
59945
|
* Apple TV, Spotify, Roku, generic OTT receivers, …) on
|
|
@@ -61478,9 +61847,9 @@ object({
|
|
|
61478
61847
|
/** Cumulative energy in kilowatt-hours since the meter was reset. */
|
|
61479
61848
|
kwhTotal: number().optional().meta(readingMeta("energy", { label: "Energy" })),
|
|
61480
61849
|
/** Voltage in volts. */
|
|
61481
|
-
volts: number().optional().meta(readingMeta("voltage")),
|
|
61850
|
+
volts: number().optional().meta(readingMeta("voltage", { label: "Voltage" })),
|
|
61482
61851
|
/** Current in amperes. */
|
|
61483
|
-
amps: number().optional().meta(readingMeta("current")),
|
|
61852
|
+
amps: number().optional().meta(readingMeta("current", { label: "Current" })),
|
|
61484
61853
|
/** Apparent power in volt-amperes. */
|
|
61485
61854
|
va: number().optional().meta(readingMeta("apparent-power")),
|
|
61486
61855
|
/** Power factor (0..1) if reported. */
|
|
@@ -61488,7 +61857,23 @@ object({
|
|
|
61488
61857
|
/** Ms epoch when the slice was last updated. */
|
|
61489
61858
|
lastFetchedAt: number()
|
|
61490
61859
|
});
|
|
61491
|
-
|
|
61860
|
+
[
|
|
61861
|
+
DeviceType.Sensor,
|
|
61862
|
+
DeviceType.Switch,
|
|
61863
|
+
DeviceType.Light,
|
|
61864
|
+
DeviceType.Fan,
|
|
61865
|
+
DeviceType.Climate,
|
|
61866
|
+
DeviceType.Thermostat,
|
|
61867
|
+
DeviceType.Humidifier,
|
|
61868
|
+
DeviceType.WaterHeater,
|
|
61869
|
+
DeviceType.MediaPlayer,
|
|
61870
|
+
DeviceType.Washer,
|
|
61871
|
+
DeviceType.Dryer,
|
|
61872
|
+
DeviceType.Dishwasher,
|
|
61873
|
+
DeviceType.Vacuum,
|
|
61874
|
+
DeviceType.LawnMower,
|
|
61875
|
+
DeviceType.PetFeeder
|
|
61876
|
+
].filter((type) => type !== DeviceType.Sensor);
|
|
61492
61877
|
/**
|
|
61493
61878
|
* Presence cap. Models HA `person.*` and `device_tracker.*` entities
|
|
61494
61879
|
* on `DeviceType.Presence`. Read-only — no setters: presence is
|
|
@@ -61935,7 +62320,7 @@ object({
|
|
|
61935
62320
|
phase: string().nullable()
|
|
61936
62321
|
});
|
|
61937
62322
|
Object.values(DeviceType);
|
|
61938
|
-
DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
|
|
62323
|
+
DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
|
|
61939
62324
|
DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch, method(object({ deviceId: number().int().nonnegative() }), object({ success: literal(true) }), {
|
|
61940
62325
|
kind: "mutation",
|
|
61941
62326
|
auth: "admin"
|
|
@@ -63974,7 +64359,7 @@ object({
|
|
|
63974
64359
|
/** Ms epoch of the last state change. Useful for UI "X minutes ago". */
|
|
63975
64360
|
lastChangedAt: number()
|
|
63976
64361
|
});
|
|
63977
|
-
DeviceType.Switch, DeviceType.Siren, DeviceType.Light, method(object({
|
|
64362
|
+
DeviceType.Switch, DeviceType.Siren, DeviceType.Light, DeviceType.Fan, method(object({
|
|
63978
64363
|
deviceId: number(),
|
|
63979
64364
|
on: boolean()
|
|
63980
64365
|
}), _void(), {
|
|
@@ -65666,8 +66051,9 @@ method(object({}), array(TrainingBaseModelSchema).readonly(), { auth: "admin" })
|
|
|
65666
66051
|
kind: "mutation",
|
|
65667
66052
|
auth: "admin"
|
|
65668
66053
|
});
|
|
66054
|
+
DeviceFeature.FanSpeed, DeviceFeature.FanPreset, DeviceFeature.FanDirection, DeviceFeature.FanOscillating, DeviceFeature.CoverPositionable, DeviceFeature.CoverTilt, DeviceFeature.ValvePositionable, DeviceFeature.MediaPlayerVolume, DeviceFeature.ClimateFanMode;
|
|
65669
66055
|
SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
|
|
65670
|
-
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;
|
|
66056
|
+
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;
|
|
65671
66057
|
String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
|
|
65672
66058
|
DeviceRole.BinarySensor, DeviceRole.MotionSensor;
|
|
65673
66059
|
new Set(CAP_NAMES);
|
|
@@ -65720,7 +66106,7 @@ var AccessoryKind = {
|
|
|
65720
66106
|
PrivacyMask: DeviceRole.PrivacyMask
|
|
65721
66107
|
};
|
|
65722
66108
|
AccessoryKind.Siren, AccessoryKind.Floodlight, AccessoryKind.Spotlight, AccessoryKind.PirSensor, AccessoryKind.Chime, AccessoryKind.Autotrack, AccessoryKind.Nightvision, AccessoryKind.PrivacyMask;
|
|
65723
|
-
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;
|
|
66109
|
+
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;
|
|
65724
66110
|
new Set(Object.values(DeviceType));
|
|
65725
66111
|
Object.freeze({
|
|
65726
66112
|
"accessories.getStatus": {
|
|
@@ -68943,6 +69329,13 @@ Object.freeze({
|
|
|
68943
69329
|
access: "view",
|
|
68944
69330
|
role: "viewer"
|
|
68945
69331
|
},
|
|
69332
|
+
"groupActive.getStatus": {
|
|
69333
|
+
capName: "group-active",
|
|
69334
|
+
capScope: "device",
|
|
69335
|
+
addonId: null,
|
|
69336
|
+
access: "view",
|
|
69337
|
+
role: "viewer"
|
|
69338
|
+
},
|
|
68946
69339
|
"groupCommands.getStatus": {
|
|
68947
69340
|
capName: "group-commands",
|
|
68948
69341
|
capScope: "device",
|
|
@@ -69909,6 +70302,13 @@ Object.freeze({
|
|
|
69909
70302
|
access: "create",
|
|
69910
70303
|
role: "admin"
|
|
69911
70304
|
},
|
|
70305
|
+
"meter.getStatus": {
|
|
70306
|
+
capName: "meter",
|
|
70307
|
+
capScope: "device",
|
|
70308
|
+
addonId: null,
|
|
70309
|
+
access: "view",
|
|
70310
|
+
role: "viewer"
|
|
70311
|
+
},
|
|
69912
70312
|
"metricsProvider.collectSnapshot": {
|
|
69913
70313
|
capName: "metrics-provider",
|
|
69914
70314
|
capScope: "system",
|
|
@@ -78007,7 +78407,39 @@ var APPLIANCE_CAP_VOCABULARY = {
|
|
|
78007
78407
|
phrase: t("When {device} finishes", "Quando {device} finisce"),
|
|
78008
78408
|
icon: "square"
|
|
78009
78409
|
}
|
|
78010
|
-
}
|
|
78410
|
+
},
|
|
78411
|
+
overrides: { byType: {
|
|
78412
|
+
[DeviceType.Washer]: {
|
|
78413
|
+
state: { running: {
|
|
78414
|
+
whenTrue: t("When the washing machine starts", "Quando la lavatrice inizia"),
|
|
78415
|
+
whenFalse: t("When the washing machine has finished", "Quando la lavatrice ha finito")
|
|
78416
|
+
} },
|
|
78417
|
+
events: {
|
|
78418
|
+
onStarted: { phrase: t("When the washing machine starts", "Quando la lavatrice inizia") },
|
|
78419
|
+
onFinished: { phrase: t("When the washing machine has finished", "Quando la lavatrice ha finito") }
|
|
78420
|
+
}
|
|
78421
|
+
},
|
|
78422
|
+
[DeviceType.Dryer]: {
|
|
78423
|
+
state: { running: {
|
|
78424
|
+
whenTrue: t("When the dryer starts", "Quando l'asciugatrice inizia"),
|
|
78425
|
+
whenFalse: t("When the dryer has finished", "Quando l'asciugatrice ha finito")
|
|
78426
|
+
} },
|
|
78427
|
+
events: {
|
|
78428
|
+
onStarted: { phrase: t("When the dryer starts", "Quando l'asciugatrice inizia") },
|
|
78429
|
+
onFinished: { phrase: t("When the dryer has finished", "Quando l'asciugatrice ha finito") }
|
|
78430
|
+
}
|
|
78431
|
+
},
|
|
78432
|
+
[DeviceType.Dishwasher]: {
|
|
78433
|
+
state: { running: {
|
|
78434
|
+
whenTrue: t("When the dishwasher starts", "Quando la lavastoviglie inizia"),
|
|
78435
|
+
whenFalse: t("When the dishwasher has finished", "Quando la lavastoviglie ha finito")
|
|
78436
|
+
} },
|
|
78437
|
+
events: {
|
|
78438
|
+
onStarted: { phrase: t("When the dishwasher starts", "Quando la lavastoviglie inizia") },
|
|
78439
|
+
onFinished: { phrase: t("When the dishwasher has finished", "Quando la lavastoviglie ha finito") }
|
|
78440
|
+
}
|
|
78441
|
+
}
|
|
78442
|
+
} }
|
|
78011
78443
|
},
|
|
78012
78444
|
update: {
|
|
78013
78445
|
scope: "device",
|
|
@@ -78779,6 +79211,10 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78779
79211
|
icon: "flame"
|
|
78780
79212
|
}]
|
|
78781
79213
|
},
|
|
79214
|
+
"group-active": {
|
|
79215
|
+
scope: "device",
|
|
79216
|
+
noun: t("Group state", "Stato del gruppo")
|
|
79217
|
+
},
|
|
78782
79218
|
"group-commands": {
|
|
78783
79219
|
scope: "device",
|
|
78784
79220
|
noun: t("Group command", "Comando di gruppo")
|
|
@@ -78835,6 +79271,17 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78835
79271
|
}],
|
|
78836
79272
|
events: { onMotionChanged: { notOperatorFacing: "the `detected` state trigger phrases both edges, from the mirror that survives a dropped event (D49)" } }
|
|
78837
79273
|
},
|
|
79274
|
+
meter: {
|
|
79275
|
+
scope: "device",
|
|
79276
|
+
noun: t("Meter", "Contatore"),
|
|
79277
|
+
state: [{
|
|
79278
|
+
kind: "numeric",
|
|
79279
|
+
field: "value",
|
|
79280
|
+
quantity: t("the total", "il totale"),
|
|
79281
|
+
label: t("Total", "Totale"),
|
|
79282
|
+
icon: "gauge"
|
|
79283
|
+
}]
|
|
79284
|
+
},
|
|
78838
79285
|
"numeric-sensor": {
|
|
78839
79286
|
scope: "device",
|
|
78840
79287
|
noun: t("Sensor", "Sensore"),
|
|
@@ -79307,8 +79754,47 @@ function projectAction(cap, action) {
|
|
|
79307
79754
|
};
|
|
79308
79755
|
}
|
|
79309
79756
|
Object.entries(CAP_VOCABULARY_BY_NAME).flatMap(([cap, entry]) => entry.scope === "device" ? (entry.actions ?? []).map((a) => projectAction(cap, a)) : []);
|
|
79310
|
-
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;
|
|
79757
|
+
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;
|
|
79311
79758
|
DeviceFeature.BatteryOperated;
|
|
79759
|
+
DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher;
|
|
79760
|
+
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.";
|
|
79761
|
+
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.";
|
|
79762
|
+
var ALEXA_REASON = "Alexa has no laundry category in this export, and neither power nor running has an Alexa interface.";
|
|
79763
|
+
var GOOGLE_REASON = "Google WASHER, DRYER and DISHWASHER require RunCycle. A power threshold is not that trait, and this export does not publish RunCycle.";
|
|
79764
|
+
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.";
|
|
79765
|
+
function withheld(reason) {
|
|
79766
|
+
return {
|
|
79767
|
+
[DeviceType.Washer]: {
|
|
79768
|
+
exported: false,
|
|
79769
|
+
reason
|
|
79770
|
+
},
|
|
79771
|
+
[DeviceType.Dryer]: {
|
|
79772
|
+
exported: false,
|
|
79773
|
+
reason
|
|
79774
|
+
},
|
|
79775
|
+
[DeviceType.Dishwasher]: {
|
|
79776
|
+
exported: false,
|
|
79777
|
+
reason
|
|
79778
|
+
}
|
|
79779
|
+
};
|
|
79780
|
+
}
|
|
79781
|
+
function offered(received) {
|
|
79782
|
+
return {
|
|
79783
|
+
[DeviceType.Washer]: {
|
|
79784
|
+
exported: true,
|
|
79785
|
+
as: received
|
|
79786
|
+
},
|
|
79787
|
+
[DeviceType.Dryer]: {
|
|
79788
|
+
exported: true,
|
|
79789
|
+
as: received
|
|
79790
|
+
},
|
|
79791
|
+
[DeviceType.Dishwasher]: {
|
|
79792
|
+
exported: true,
|
|
79793
|
+
as: received
|
|
79794
|
+
}
|
|
79795
|
+
};
|
|
79796
|
+
}
|
|
79797
|
+
offered(HA_AS), withheld(HOMEKIT_REASON), withheld(ALEXA_REASON), withheld(GOOGLE_REASON), withheld(MATTER_REASON);
|
|
79312
79798
|
Object.freeze({
|
|
79313
79799
|
"accessories.getStatus": [{
|
|
79314
79800
|
name: "deviceId",
|
|
@@ -80275,6 +80761,11 @@ Object.freeze({
|
|
|
80275
80761
|
form: "single",
|
|
80276
80762
|
optional: false
|
|
80277
80763
|
}],
|
|
80764
|
+
"groupActive.getStatus": [{
|
|
80765
|
+
name: "deviceId",
|
|
80766
|
+
form: "single",
|
|
80767
|
+
optional: false
|
|
80768
|
+
}],
|
|
80278
80769
|
"groupCommands.getStatus": [{
|
|
80279
80770
|
name: "deviceId",
|
|
80280
80771
|
form: "single",
|
|
@@ -80485,6 +80976,11 @@ Object.freeze({
|
|
|
80485
80976
|
form: "single",
|
|
80486
80977
|
optional: false
|
|
80487
80978
|
}],
|
|
80979
|
+
"meter.getStatus": [{
|
|
80980
|
+
name: "deviceId",
|
|
80981
|
+
form: "single",
|
|
80982
|
+
optional: false
|
|
80983
|
+
}],
|
|
80488
80984
|
"motion.getStatus": [{
|
|
80489
80985
|
name: "deviceId",
|
|
80490
80986
|
form: "single",
|
|
@@ -82092,7 +82588,6 @@ Object.freeze({
|
|
|
82092
82588
|
"network-access": "ingress",
|
|
82093
82589
|
"smtp-provider": "email"
|
|
82094
82590
|
});
|
|
82095
|
-
DeviceType.Camera;
|
|
82096
82591
|
/**
|
|
82097
82592
|
* A saved Customize assignment (D936). The schema is the type: callers use
|
|
82098
82593
|
* `z.infer`, they do not restate the shape.
|