@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
|
@@ -5622,7 +5622,7 @@ var ZodIssueCode = {
|
|
|
5622
5622
|
var ZodFirstPartyTypeKind;
|
|
5623
5623
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5624
5624
|
//#endregion
|
|
5625
|
-
//#region ../types/dist/sleep
|
|
5625
|
+
//#region ../types/dist/sleep--jXS9hWo.mjs
|
|
5626
5626
|
/**
|
|
5627
5627
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5628
5628
|
* window to float samples (D455).
|
|
@@ -8999,6 +8999,7 @@ var CAP_NAMES = Object.freeze([
|
|
|
8999
8999
|
"filesystem-browse",
|
|
9000
9000
|
"flood",
|
|
9001
9001
|
"gas",
|
|
9002
|
+
"group-active",
|
|
9002
9003
|
"group-commands",
|
|
9003
9004
|
"group-status",
|
|
9004
9005
|
"heating-valve",
|
|
@@ -9021,6 +9022,7 @@ var CAP_NAMES = Object.freeze([
|
|
|
9021
9022
|
"login-method",
|
|
9022
9023
|
"media-player",
|
|
9023
9024
|
"mesh-network",
|
|
9025
|
+
"meter",
|
|
9024
9026
|
"metrics-provider",
|
|
9025
9027
|
"model-convert",
|
|
9026
9028
|
"model-distributor",
|
|
@@ -9819,6 +9821,10 @@ Object.freeze({
|
|
|
9819
9821
|
"path": "detected",
|
|
9820
9822
|
"valueType": "boolean"
|
|
9821
9823
|
}],
|
|
9824
|
+
"group-active": [{
|
|
9825
|
+
"path": "active",
|
|
9826
|
+
"valueType": "boolean"
|
|
9827
|
+
}],
|
|
9822
9828
|
"group-status": [
|
|
9823
9829
|
{
|
|
9824
9830
|
"path": "included",
|
|
@@ -10078,6 +10084,10 @@ Object.freeze({
|
|
|
10078
10084
|
]
|
|
10079
10085
|
}
|
|
10080
10086
|
],
|
|
10087
|
+
"meter": [{
|
|
10088
|
+
"path": "value",
|
|
10089
|
+
"valueType": "number"
|
|
10090
|
+
}],
|
|
10081
10091
|
"motion": [
|
|
10082
10092
|
{
|
|
10083
10093
|
"path": "detected",
|
|
@@ -10821,7 +10831,7 @@ object({
|
|
|
10821
10831
|
params: record(string(), union([string(), number()])).optional()
|
|
10822
10832
|
});
|
|
10823
10833
|
//#endregion
|
|
10824
|
-
//#region ../types/dist/err-msg-
|
|
10834
|
+
//#region ../types/dist/err-msg-DIorGYeC.mjs
|
|
10825
10835
|
var DeviceType = /* @__PURE__ */ function(DeviceType) {
|
|
10826
10836
|
DeviceType["Camera"] = "camera";
|
|
10827
10837
|
DeviceType["Hub"] = "hub";
|
|
@@ -10915,8 +10925,14 @@ var DeviceType = /* @__PURE__ */ function(DeviceType) {
|
|
|
10915
10925
|
DeviceType["PetFeeder"] = "pet-feeder";
|
|
10916
10926
|
/** Built-in dishwasher — program lifecycle, door / remote-start gates,
|
|
10917
10927
|
* salt and rinse-aid levels. Installed with the `dishwasher` cap.
|
|
10918
|
-
* Sources: native Bosch Home Connect, reusable by similar integrations.
|
|
10928
|
+
* Sources: native Bosch Home Connect, reusable by similar integrations.
|
|
10929
|
+
* A plug-built dishwasher carries running-state and power instead. */
|
|
10919
10930
|
DeviceType["Dishwasher"] = "dishwasher";
|
|
10931
|
+
/** Washing machine. A plug-built one is running while its power stays
|
|
10932
|
+
* above a threshold. No program cap — that surface is the dishwasher's. */
|
|
10933
|
+
DeviceType["Washer"] = "washer";
|
|
10934
|
+
/** Tumble dryer. Same plug-built running surface as {@link Washer}. */
|
|
10935
|
+
DeviceType["Dryer"] = "dryer";
|
|
10920
10936
|
return DeviceType;
|
|
10921
10937
|
}({});
|
|
10922
10938
|
var DeviceFeature = /* @__PURE__ */ function(DeviceFeature) {
|
|
@@ -11164,7 +11180,7 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
|
|
|
11164
11180
|
return DeviceRole;
|
|
11165
11181
|
}({});
|
|
11166
11182
|
//#endregion
|
|
11167
|
-
//#region ../types/dist/composition-
|
|
11183
|
+
//#region ../types/dist/composition-Bb8iwHEJ.mjs
|
|
11168
11184
|
/**
|
|
11169
11185
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
11170
11186
|
*
|
|
@@ -11479,6 +11495,13 @@ var table = {
|
|
|
11479
11495
|
apply: () => {
|
|
11480
11496
|
throw new ExpressionEvalError("latchedAt: stateful evaluation context is required");
|
|
11481
11497
|
}
|
|
11498
|
+
},
|
|
11499
|
+
schmitt: {
|
|
11500
|
+
minArgs: 3,
|
|
11501
|
+
maxArgs: 5,
|
|
11502
|
+
apply: () => {
|
|
11503
|
+
throw new ExpressionEvalError("schmitt: stateful evaluation context is required");
|
|
11504
|
+
}
|
|
11482
11505
|
}
|
|
11483
11506
|
};
|
|
11484
11507
|
Object.freeze(Object.assign(Object.create(null), table));
|
|
@@ -11920,6 +11943,99 @@ function validateExpressionSource(src) {
|
|
|
11920
11943
|
return null;
|
|
11921
11944
|
}
|
|
11922
11945
|
/**
|
|
11946
|
+
* One power reading becomes a washer, dryer or dishwasher (D944 helper).
|
|
11947
|
+
*
|
|
11948
|
+
* Standby of the control board is under 5 W; a motor or a heater is far
|
|
11949
|
+
* above that, so 5 W is the line. A door lock or a short pump spike is not
|
|
11950
|
+
* a cycle, so running starts only after 30 s above the line.
|
|
11951
|
+
*
|
|
11952
|
+
* A wash, dry or dishwasher pause (soak, heat-wait, heater off between
|
|
11953
|
+
* bursts) lasts several minutes. Ending the cycle on the first dip would
|
|
11954
|
+
* report "finished" in the middle of the program, so the stop dwell is
|
|
11955
|
+
* 10 minutes on every type. The number is stored per type so one machine
|
|
11956
|
+
* can move later without moving the others.
|
|
11957
|
+
*/
|
|
11958
|
+
var APPLIANCE_TEMPLATE_ID = "appliance";
|
|
11959
|
+
var APPLIANCE_KINDS = [
|
|
11960
|
+
"washer",
|
|
11961
|
+
"dryer",
|
|
11962
|
+
"dishwasher"
|
|
11963
|
+
];
|
|
11964
|
+
DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher;
|
|
11965
|
+
/**
|
|
11966
|
+
* Statistics and integrals over a history read (D944).
|
|
11967
|
+
*
|
|
11968
|
+
* Pure: the same points always give the same answer, so a restart recomputes
|
|
11969
|
+
* rather than trusting a buffer. A gauge mean is time-weighted (value × ms),
|
|
11970
|
+
* never the mean of the samples. A hole with no held value is not integrated
|
|
11971
|
+
* as zero. A truncated read is not published.
|
|
11972
|
+
*/
|
|
11973
|
+
var STATISTIC_STATS = [
|
|
11974
|
+
"min",
|
|
11975
|
+
"max",
|
|
11976
|
+
"mean",
|
|
11977
|
+
"sum",
|
|
11978
|
+
"count",
|
|
11979
|
+
"change"
|
|
11980
|
+
];
|
|
11981
|
+
/**
|
|
11982
|
+
* The range a statistics or integral helper asks history for (D944).
|
|
11983
|
+
*
|
|
11984
|
+
* Calendar edges are the hub's timezone, never UTC midnight: a day is 23, 24
|
|
11985
|
+
* or 25 hours across a DST change. A tier is eligible only when its retention
|
|
11986
|
+
* is strictly longer than the longest that range can be. Forever qualifies.
|
|
11987
|
+
* Equal to a tier's retention is a refusal, not a short answer.
|
|
11988
|
+
*/
|
|
11989
|
+
var MINUTE_MS = 6e4;
|
|
11990
|
+
var HOUR_MS = 60 * MINUTE_MS;
|
|
11991
|
+
var DAY_MS = 24 * HOUR_MS;
|
|
11992
|
+
var ROLLING_SPANS = [
|
|
11993
|
+
"1h",
|
|
11994
|
+
"24h",
|
|
11995
|
+
"2d",
|
|
11996
|
+
"7d",
|
|
11997
|
+
"30d",
|
|
11998
|
+
"custom"
|
|
11999
|
+
];
|
|
12000
|
+
var CALENDAR_PERIODS = [
|
|
12001
|
+
"today",
|
|
12002
|
+
"yesterday",
|
|
12003
|
+
"this-week",
|
|
12004
|
+
"this-month"
|
|
12005
|
+
];
|
|
12006
|
+
var RESET_PERIODS = [
|
|
12007
|
+
"never",
|
|
12008
|
+
"daily",
|
|
12009
|
+
"weekly",
|
|
12010
|
+
"monthly"
|
|
12011
|
+
];
|
|
12012
|
+
5 * MINUTE_MS;
|
|
12013
|
+
24 * HOUR_MS, 2 * DAY_MS, 7 * DAY_MS, 30 * DAY_MS;
|
|
12014
|
+
7 * DAY_MS, 30 * DAY_MS, 365 * DAY_MS;
|
|
12015
|
+
var rollingWindowObject = object({
|
|
12016
|
+
kind: literal("rolling"),
|
|
12017
|
+
span: _enum(ROLLING_SPANS),
|
|
12018
|
+
customMinutes: number().int().min(5).optional()
|
|
12019
|
+
}).check((payload) => {
|
|
12020
|
+
if (payload.value.span === "custom" && payload.value.customMinutes === void 0) payload.issues.push({
|
|
12021
|
+
code: "custom",
|
|
12022
|
+
message: "a custom range needs a duration in minutes",
|
|
12023
|
+
path: ["customMinutes"],
|
|
12024
|
+
input: payload.value
|
|
12025
|
+
});
|
|
12026
|
+
if (payload.value.span !== "custom" && payload.value.customMinutes !== void 0) payload.issues.push({
|
|
12027
|
+
code: "custom",
|
|
12028
|
+
message: "only a custom range carries a duration",
|
|
12029
|
+
path: ["customMinutes"],
|
|
12030
|
+
input: payload.value
|
|
12031
|
+
});
|
|
12032
|
+
});
|
|
12033
|
+
var RollingWindowSchema = rollingWindowObject;
|
|
12034
|
+
var StatisticWindowSchema = discriminatedUnion("kind", [rollingWindowObject, object({
|
|
12035
|
+
kind: literal("calendar"),
|
|
12036
|
+
period: _enum(CALENDAR_PERIODS)
|
|
12037
|
+
})]);
|
|
12038
|
+
/**
|
|
11923
12039
|
* A composition source identity: `(addonId, stableId)`, never a numeric device
|
|
11924
12040
|
* id. Split out so helper schemas can name it without a cycle through
|
|
11925
12041
|
* `composition.ts` (D659).
|
|
@@ -11945,7 +12061,13 @@ var GROUP_TEMPLATE_IDS = [
|
|
|
11945
12061
|
"occupancy",
|
|
11946
12062
|
"binary",
|
|
11947
12063
|
"switch",
|
|
11948
|
-
"light"
|
|
12064
|
+
"light",
|
|
12065
|
+
"fan",
|
|
12066
|
+
"cover",
|
|
12067
|
+
"valve",
|
|
12068
|
+
"lock",
|
|
12069
|
+
"media-player",
|
|
12070
|
+
"climate"
|
|
11949
12071
|
];
|
|
11950
12072
|
var NUMERIC_AGGREGATES = [
|
|
11951
12073
|
"mean",
|
|
@@ -11975,14 +12097,73 @@ var HelperMemberSchema = object({
|
|
|
11975
12097
|
cap: string().min(1),
|
|
11976
12098
|
fieldPath: string().min(1)
|
|
11977
12099
|
});
|
|
11978
|
-
var HelperSpecSchema = discriminatedUnion("kind", [
|
|
11979
|
-
|
|
11980
|
-
|
|
11981
|
-
|
|
11982
|
-
|
|
11983
|
-
|
|
11984
|
-
|
|
11985
|
-
|
|
12100
|
+
var HelperSpecSchema = discriminatedUnion("kind", [
|
|
12101
|
+
object({
|
|
12102
|
+
kind: literal("group"),
|
|
12103
|
+
templateId: GroupTemplateIdSchema,
|
|
12104
|
+
aggregate: AggregateReducerSchema,
|
|
12105
|
+
members: array(HelperMemberSchema).min(1).max(64),
|
|
12106
|
+
/** Actuator groups only. Readings leave this unset. */
|
|
12107
|
+
active: ActiveCriterionSchema.optional()
|
|
12108
|
+
}),
|
|
12109
|
+
object({
|
|
12110
|
+
kind: literal("appliance"),
|
|
12111
|
+
templateId: literal(APPLIANCE_TEMPLATE_ID),
|
|
12112
|
+
appliance: _enum(APPLIANCE_KINDS),
|
|
12113
|
+
thresholdWatts: number().positive(),
|
|
12114
|
+
startDwellMs: number().int().nonnegative(),
|
|
12115
|
+
stopDwellMs: number().int().nonnegative(),
|
|
12116
|
+
member: HelperMemberSchema
|
|
12117
|
+
}),
|
|
12118
|
+
object({
|
|
12119
|
+
kind: literal("statistic"),
|
|
12120
|
+
stat: _enum(STATISTIC_STATS),
|
|
12121
|
+
window: StatisticWindowSchema,
|
|
12122
|
+
source: HelperMemberSchema
|
|
12123
|
+
}),
|
|
12124
|
+
object({
|
|
12125
|
+
kind: literal("integral"),
|
|
12126
|
+
reset: _enum(RESET_PERIODS),
|
|
12127
|
+
output: _enum(["energy", "meter"]),
|
|
12128
|
+
source: HelperMemberSchema
|
|
12129
|
+
}),
|
|
12130
|
+
object({
|
|
12131
|
+
kind: literal("threshold"),
|
|
12132
|
+
source: HelperMemberSchema,
|
|
12133
|
+
high: number(),
|
|
12134
|
+
low: number(),
|
|
12135
|
+
onForMs: number().int().nonnegative(),
|
|
12136
|
+
offForMs: number().int().nonnegative()
|
|
12137
|
+
}),
|
|
12138
|
+
object({
|
|
12139
|
+
kind: literal("arithmetic"),
|
|
12140
|
+
op: _enum([
|
|
12141
|
+
"sum",
|
|
12142
|
+
"difference",
|
|
12143
|
+
"ratio"
|
|
12144
|
+
]),
|
|
12145
|
+
inputs: array(HelperMemberSchema).min(2).max(64)
|
|
12146
|
+
}),
|
|
12147
|
+
object({
|
|
12148
|
+
kind: literal("expression"),
|
|
12149
|
+
expr: string().min(1),
|
|
12150
|
+
inputs: array(object({
|
|
12151
|
+
name: string().min(1),
|
|
12152
|
+
member: HelperMemberSchema
|
|
12153
|
+
})).min(1).max(64),
|
|
12154
|
+
output: _enum(["number", "boolean"])
|
|
12155
|
+
}),
|
|
12156
|
+
object({
|
|
12157
|
+
kind: literal("derivative"),
|
|
12158
|
+
window: RollingWindowSchema,
|
|
12159
|
+
per: _enum([
|
|
12160
|
+
"second",
|
|
12161
|
+
"minute",
|
|
12162
|
+
"hour"
|
|
12163
|
+
]),
|
|
12164
|
+
source: HelperMemberSchema
|
|
12165
|
+
})
|
|
12166
|
+
]);
|
|
11986
12167
|
/** A composed device's stableId is this prefix plus the block id. */
|
|
11987
12168
|
var COMPOSED_DEVICE_STABLE_ID_PREFIX = "composed-";
|
|
11988
12169
|
/** Longest snippet a `code` source may carry (slice 4). */
|
|
@@ -12043,6 +12224,12 @@ var CompositionFieldSourceSchema = discriminatedUnion("kind", [
|
|
|
12043
12224
|
"all"
|
|
12044
12225
|
]),
|
|
12045
12226
|
reads: array(CompositionFieldReadSchema).min(1).max(64),
|
|
12227
|
+
/**
|
|
12228
|
+
* Set when the reads are an enum state, not a yes/no: the listed states
|
|
12229
|
+
* count as active (a cover is `open`). A state outside the list is inactive;
|
|
12230
|
+
* a read that is not a state at all is left out. Only `any` / `all` use it.
|
|
12231
|
+
*/
|
|
12232
|
+
activeWhen: array(string().min(1)).min(1).optional(),
|
|
12046
12233
|
/** `value` is the reading; the others are the member counts. */
|
|
12047
12234
|
publish: _enum([
|
|
12048
12235
|
"value",
|
|
@@ -12056,6 +12243,26 @@ var CompositionFieldSourceSchema = discriminatedUnion("kind", [
|
|
|
12056
12243
|
"omit",
|
|
12057
12244
|
"offline"
|
|
12058
12245
|
])
|
|
12246
|
+
}),
|
|
12247
|
+
object({
|
|
12248
|
+
kind: literal("series"),
|
|
12249
|
+
read: CompositionFieldReadSchema,
|
|
12250
|
+
/** `value` is the statistic or the integral. The others are the gap counts. */
|
|
12251
|
+
publish: _enum([
|
|
12252
|
+
"value",
|
|
12253
|
+
"included",
|
|
12254
|
+
"excluded",
|
|
12255
|
+
"total"
|
|
12256
|
+
]),
|
|
12257
|
+
/**
|
|
12258
|
+
* What an unanswered `value` does. Counts ignore this. `offline` leaves the
|
|
12259
|
+
* device unseeded until history answers, so a restart cannot publish 0.
|
|
12260
|
+
*/
|
|
12261
|
+
empty: _enum([
|
|
12262
|
+
"null",
|
|
12263
|
+
"omit",
|
|
12264
|
+
"offline"
|
|
12265
|
+
])
|
|
12059
12266
|
})
|
|
12060
12267
|
]);
|
|
12061
12268
|
var CompositionCommandTargetSchema = discriminatedUnion("kind", [object({
|
|
@@ -17215,7 +17422,22 @@ var BrokerProviderInfoSchema = object({
|
|
|
17215
17422
|
*/
|
|
17216
17423
|
interactiveConnectPath: string().min(1).optional(),
|
|
17217
17424
|
/** Relative hub path to disconnect the linked account (same popup pattern). */
|
|
17218
|
-
interactiveDisconnectPath: string().min(1).optional()
|
|
17425
|
+
interactiveDisconnectPath: string().min(1).optional(),
|
|
17426
|
+
/**
|
|
17427
|
+
* The kind signs in through a server-held interactive session instead of
|
|
17428
|
+
* (or before) typed credentials. `basePath` is a hub-relative route set
|
|
17429
|
+
* served by the owning addon (`/addon/<id>/...`) speaking the sign-in
|
|
17430
|
+
* contract: `POST {basePath}/start` (body: the form's settings) answers
|
|
17431
|
+
* `{ sessionId, loginUrl }`; `GET {basePath}/status?sessionId=` answers
|
|
17432
|
+
* `{ phase: 'starting' | 'awaiting-login' | 'captured' | 'error' |
|
|
17433
|
+
* 'cancelled', loginUrl, error }`; `POST {basePath}/commit`
|
|
17434
|
+
* (`{ sessionId, name, brokerId? }`) stores the credentials on a new or
|
|
17435
|
+
* existing broker and answers `{ brokerId }`; `POST {basePath}/cancel`
|
|
17436
|
+
* (`{ sessionId }`) drops the session. The dialog that edits a broker
|
|
17437
|
+
* offers it as the default path; the fields the session fills are
|
|
17438
|
+
* marked `filledBySignIn` in the kind's settings schema.
|
|
17439
|
+
*/
|
|
17440
|
+
signIn: object({ basePath: string().min(1) }).optional()
|
|
17219
17441
|
}))
|
|
17220
17442
|
});
|
|
17221
17443
|
var ListInputSchema = object({
|
|
@@ -18263,7 +18485,8 @@ var CompositionProblemSchema = object({
|
|
|
18263
18485
|
"native-capability-replace",
|
|
18264
18486
|
"mixed-quantity",
|
|
18265
18487
|
"helper-mismatch",
|
|
18266
|
-
"member-constraint"
|
|
18488
|
+
"member-constraint",
|
|
18489
|
+
"retention"
|
|
18267
18490
|
]),
|
|
18268
18491
|
path: string(),
|
|
18269
18492
|
message: string()
|
|
@@ -18497,13 +18720,17 @@ Object.freeze({
|
|
|
18497
18720
|
latchedAt: {
|
|
18498
18721
|
kind: "fixed",
|
|
18499
18722
|
result: ["number", "null"]
|
|
18723
|
+
},
|
|
18724
|
+
schmitt: {
|
|
18725
|
+
kind: "fixed",
|
|
18726
|
+
result: ["boolean", "null"]
|
|
18500
18727
|
}
|
|
18501
18728
|
});
|
|
18502
18729
|
/**
|
|
18503
18730
|
* One catalog row per base reading a group helper can build (D944 §3).
|
|
18504
18731
|
* Data, not a form default written into the block.
|
|
18505
18732
|
*/
|
|
18506
|
-
var NOW = {
|
|
18733
|
+
var NOW$2 = {
|
|
18507
18734
|
fieldPath: "lastFetchedAt",
|
|
18508
18735
|
expr: "now"
|
|
18509
18736
|
};
|
|
@@ -18517,6 +18744,8 @@ function numeric(input) {
|
|
|
18517
18744
|
family: "numeric",
|
|
18518
18745
|
deviceType: DeviceType.Sensor,
|
|
18519
18746
|
memberDeviceType: DeviceType.Sensor,
|
|
18747
|
+
memberDeviceTypes: [DeviceType.Sensor],
|
|
18748
|
+
activeWhen: void 0,
|
|
18520
18749
|
commandCaps: [],
|
|
18521
18750
|
baseUnit: baseUnitOf(input.quantity),
|
|
18522
18751
|
aggregates: NUMERIC_AGGREGATES,
|
|
@@ -18532,6 +18761,8 @@ function binary(input) {
|
|
|
18532
18761
|
family: "binary",
|
|
18533
18762
|
deviceType: DeviceType.Sensor,
|
|
18534
18763
|
memberDeviceType: DeviceType.Sensor,
|
|
18764
|
+
memberDeviceTypes: [DeviceType.Sensor],
|
|
18765
|
+
activeWhen: void 0,
|
|
18535
18766
|
commandCaps: [],
|
|
18536
18767
|
quantity: "none",
|
|
18537
18768
|
baseUnit: void 0,
|
|
@@ -18549,7 +18780,7 @@ var GROUP_TEMPLATES = [
|
|
|
18549
18780
|
quantity: "temperature",
|
|
18550
18781
|
defaultAggregate: "mean",
|
|
18551
18782
|
empty: "null",
|
|
18552
|
-
companions: [NOW]
|
|
18783
|
+
companions: [NOW$2]
|
|
18553
18784
|
}),
|
|
18554
18785
|
numeric({
|
|
18555
18786
|
id: "humidity",
|
|
@@ -18560,7 +18791,7 @@ var GROUP_TEMPLATES = [
|
|
|
18560
18791
|
quantity: "humidity",
|
|
18561
18792
|
defaultAggregate: "mean",
|
|
18562
18793
|
empty: "null",
|
|
18563
|
-
companions: [NOW]
|
|
18794
|
+
companions: [NOW$2]
|
|
18564
18795
|
}),
|
|
18565
18796
|
numeric({
|
|
18566
18797
|
id: "pressure",
|
|
@@ -18571,7 +18802,7 @@ var GROUP_TEMPLATES = [
|
|
|
18571
18802
|
quantity: "pressure",
|
|
18572
18803
|
defaultAggregate: "mean",
|
|
18573
18804
|
empty: "null",
|
|
18574
|
-
companions: [NOW]
|
|
18805
|
+
companions: [NOW$2]
|
|
18575
18806
|
}),
|
|
18576
18807
|
numeric({
|
|
18577
18808
|
id: "illuminance",
|
|
@@ -18582,7 +18813,7 @@ var GROUP_TEMPLATES = [
|
|
|
18582
18813
|
quantity: "illuminance",
|
|
18583
18814
|
defaultAggregate: "mean",
|
|
18584
18815
|
empty: "null",
|
|
18585
|
-
companions: [NOW]
|
|
18816
|
+
companions: [NOW$2]
|
|
18586
18817
|
}),
|
|
18587
18818
|
numeric({
|
|
18588
18819
|
id: "power",
|
|
@@ -18593,7 +18824,7 @@ var GROUP_TEMPLATES = [
|
|
|
18593
18824
|
quantity: "power",
|
|
18594
18825
|
defaultAggregate: "sum",
|
|
18595
18826
|
empty: "omit",
|
|
18596
|
-
companions: [NOW]
|
|
18827
|
+
companions: [NOW$2]
|
|
18597
18828
|
}),
|
|
18598
18829
|
numeric({
|
|
18599
18830
|
id: "energy",
|
|
@@ -18604,7 +18835,7 @@ var GROUP_TEMPLATES = [
|
|
|
18604
18835
|
quantity: "energy",
|
|
18605
18836
|
defaultAggregate: "sum",
|
|
18606
18837
|
empty: "omit",
|
|
18607
|
-
companions: [NOW]
|
|
18838
|
+
companions: [NOW$2]
|
|
18608
18839
|
}),
|
|
18609
18840
|
numeric({
|
|
18610
18841
|
id: "battery",
|
|
@@ -18639,7 +18870,7 @@ var GROUP_TEMPLATES = [
|
|
|
18639
18870
|
quantity: "device",
|
|
18640
18871
|
defaultAggregate: "mean",
|
|
18641
18872
|
empty: "null",
|
|
18642
|
-
companions: [NOW]
|
|
18873
|
+
companions: [NOW$2]
|
|
18643
18874
|
}),
|
|
18644
18875
|
binary({
|
|
18645
18876
|
id: "motion",
|
|
@@ -18733,6 +18964,11 @@ var GROUP_TEMPLATES = [
|
|
|
18733
18964
|
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.",
|
|
18734
18965
|
deviceType: DeviceType.Switch,
|
|
18735
18966
|
outputCap: "switch",
|
|
18967
|
+
outputField: "on",
|
|
18968
|
+
member: {
|
|
18969
|
+
cap: "switch",
|
|
18970
|
+
fieldPath: "on"
|
|
18971
|
+
},
|
|
18736
18972
|
commandCaps: ["switch"]
|
|
18737
18973
|
}),
|
|
18738
18974
|
actuator({
|
|
@@ -18740,34 +18976,136 @@ var GROUP_TEMPLATES = [
|
|
|
18740
18976
|
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.",
|
|
18741
18977
|
deviceType: DeviceType.Light,
|
|
18742
18978
|
outputCap: "switch",
|
|
18979
|
+
outputField: "on",
|
|
18980
|
+
member: {
|
|
18981
|
+
cap: "switch",
|
|
18982
|
+
fieldPath: "on"
|
|
18983
|
+
},
|
|
18743
18984
|
commandCaps: [
|
|
18744
18985
|
"switch",
|
|
18745
18986
|
"brightness",
|
|
18746
18987
|
"color"
|
|
18747
18988
|
]
|
|
18989
|
+
}),
|
|
18990
|
+
actuator({
|
|
18991
|
+
id: "fan",
|
|
18992
|
+
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.",
|
|
18993
|
+
deviceType: DeviceType.Fan,
|
|
18994
|
+
outputCap: "switch",
|
|
18995
|
+
outputField: "on",
|
|
18996
|
+
member: {
|
|
18997
|
+
cap: "switch",
|
|
18998
|
+
fieldPath: "on"
|
|
18999
|
+
},
|
|
19000
|
+
commandCaps: ["switch", "fan-control"]
|
|
19001
|
+
}),
|
|
19002
|
+
actuator({
|
|
19003
|
+
id: "cover",
|
|
19004
|
+
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.",
|
|
19005
|
+
deviceType: DeviceType.Cover,
|
|
19006
|
+
outputCap: "group-active",
|
|
19007
|
+
outputField: "active",
|
|
19008
|
+
member: {
|
|
19009
|
+
cap: "cover",
|
|
19010
|
+
fieldPath: "state"
|
|
19011
|
+
},
|
|
19012
|
+
activeWhen: [
|
|
19013
|
+
"open",
|
|
19014
|
+
"opening",
|
|
19015
|
+
"stopped"
|
|
19016
|
+
],
|
|
19017
|
+
commandCaps: ["cover"]
|
|
19018
|
+
}),
|
|
19019
|
+
actuator({
|
|
19020
|
+
id: "valve",
|
|
19021
|
+
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.",
|
|
19022
|
+
deviceType: DeviceType.Valve,
|
|
19023
|
+
outputCap: "group-active",
|
|
19024
|
+
outputField: "active",
|
|
19025
|
+
member: {
|
|
19026
|
+
cap: "valve",
|
|
19027
|
+
fieldPath: "state"
|
|
19028
|
+
},
|
|
19029
|
+
activeWhen: [
|
|
19030
|
+
"open",
|
|
19031
|
+
"opening",
|
|
19032
|
+
"stopped"
|
|
19033
|
+
],
|
|
19034
|
+
commandCaps: ["valve"]
|
|
19035
|
+
}),
|
|
19036
|
+
actuator({
|
|
19037
|
+
id: "lock",
|
|
19038
|
+
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.",
|
|
19039
|
+
deviceType: DeviceType.Lock,
|
|
19040
|
+
outputCap: "group-active",
|
|
19041
|
+
outputField: "active",
|
|
19042
|
+
member: {
|
|
19043
|
+
cap: "lock-control",
|
|
19044
|
+
fieldPath: "state"
|
|
19045
|
+
},
|
|
19046
|
+
activeWhen: ["locked"],
|
|
19047
|
+
commandCaps: ["lock-control"]
|
|
19048
|
+
}),
|
|
19049
|
+
actuator({
|
|
19050
|
+
id: "media-player",
|
|
19051
|
+
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.",
|
|
19052
|
+
deviceType: DeviceType.MediaPlayer,
|
|
19053
|
+
outputCap: "group-active",
|
|
19054
|
+
outputField: "active",
|
|
19055
|
+
member: {
|
|
19056
|
+
cap: "media-player",
|
|
19057
|
+
fieldPath: "state"
|
|
19058
|
+
},
|
|
19059
|
+
activeWhen: ["playing", "buffering"],
|
|
19060
|
+
commandCaps: ["media-player"]
|
|
19061
|
+
}),
|
|
19062
|
+
actuator({
|
|
19063
|
+
id: "climate",
|
|
19064
|
+
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.",
|
|
19065
|
+
deviceType: DeviceType.Thermostat,
|
|
19066
|
+
memberDeviceTypes: [DeviceType.Thermostat, DeviceType.Climate],
|
|
19067
|
+
outputCap: "group-active",
|
|
19068
|
+
outputField: "active",
|
|
19069
|
+
member: {
|
|
19070
|
+
cap: "climate-control",
|
|
19071
|
+
fieldPath: "mode"
|
|
19072
|
+
},
|
|
19073
|
+
activeWhen: [
|
|
19074
|
+
"heat",
|
|
19075
|
+
"cool",
|
|
19076
|
+
"auto",
|
|
19077
|
+
"heat_cool",
|
|
19078
|
+
"fan_only",
|
|
19079
|
+
"dry"
|
|
19080
|
+
],
|
|
19081
|
+
commandCaps: ["climate-control"]
|
|
18748
19082
|
})
|
|
18749
19083
|
];
|
|
18750
19084
|
function actuator(input) {
|
|
18751
19085
|
return {
|
|
18752
|
-
|
|
19086
|
+
id: input.id,
|
|
19087
|
+
summary: input.summary,
|
|
19088
|
+
deviceType: input.deviceType,
|
|
19089
|
+
outputCap: input.outputCap,
|
|
19090
|
+
outputField: input.outputField,
|
|
19091
|
+
commandCaps: input.commandCaps,
|
|
18753
19092
|
family: "actuator",
|
|
18754
19093
|
role: void 0,
|
|
18755
19094
|
memberDeviceType: input.deviceType,
|
|
18756
|
-
|
|
19095
|
+
memberDeviceTypes: input.memberDeviceTypes ?? [input.deviceType],
|
|
19096
|
+
activeWhen: input.activeWhen,
|
|
18757
19097
|
quantity: "none",
|
|
18758
19098
|
baseUnit: void 0,
|
|
18759
19099
|
aggregates: BINARY_AGGREGATES,
|
|
18760
19100
|
defaultAggregate: "any",
|
|
18761
19101
|
empty: "offline",
|
|
18762
|
-
accept: [
|
|
18763
|
-
cap: "switch",
|
|
18764
|
-
fieldPath: "on"
|
|
18765
|
-
}],
|
|
19102
|
+
accept: [input.member],
|
|
18766
19103
|
companions: [CHANGED]
|
|
18767
19104
|
};
|
|
18768
19105
|
}
|
|
18769
19106
|
new Map(GROUP_TEMPLATES.map((template) => [template.id, template]));
|
|
18770
19107
|
DeviceFeature.LightColorRgb, DeviceFeature.LightColorHsv, DeviceFeature.LightColorMired;
|
|
19108
|
+
DeviceType.Camera;
|
|
18771
19109
|
`${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
|
|
18772
19110
|
/**
|
|
18773
19111
|
* What a composition may BUILD on a device type (G2, D676): the caps a new
|
|
@@ -43801,7 +44139,7 @@ var NetworkAccessStatusSchema = object({
|
|
|
43801
44139
|
});
|
|
43802
44140
|
/**
|
|
43803
44141
|
* Optional, richer endpoint shape returned by providers that expose
|
|
43804
|
-
* MORE than one ingress concurrently (Tailscale
|
|
44142
|
+
* MORE than one ingress concurrently (Tailscale Funnel with mixed
|
|
43805
44143
|
* serve+funnel rules, future ngrok multi-tunnel, …). Each entry carries
|
|
43806
44144
|
* the originating provider config (mode + sourcePort) so the
|
|
43807
44145
|
* orchestrator UI can label rows distinctly. Providers that expose only
|
|
@@ -46444,7 +46782,20 @@ var NcRuleInputSchema = object({
|
|
|
46444
46782
|
* save by the hub's grouping guard). `.optional()`, never `.default()`: the addon cap
|
|
46445
46783
|
* path does not run Zod defaults.
|
|
46446
46784
|
*/
|
|
46447
|
-
groupingSec: number().int().min(5).max(60).optional()
|
|
46785
|
+
groupingSec: number().int().min(5).max(60).optional(),
|
|
46786
|
+
/**
|
|
46787
|
+
* ASK ME TO CONFIRM DETECTIONS (#243): a DETECTION notification of this rule
|
|
46788
|
+
* carries "Correct" / "Wrong" buttons (and, where the channel has room, a
|
|
46789
|
+
* "Wrong, it is a <class>" choice). A tap marks the track for retraining, the
|
|
46790
|
+
* same mark the Library writes, and records whose notification it was and
|
|
46791
|
+
* when. A channel with no buttons gets the same two choices as links.
|
|
46792
|
+
*
|
|
46793
|
+
* `.optional()`, never `.default()` (a Zod default does not run on the addon
|
|
46794
|
+
* cap path): absent and `false` both mean off, which is what every rule
|
|
46795
|
+
* authored before this field meant. An editor turns it off by writing
|
|
46796
|
+
* `false`, so it needs no `clear` key.
|
|
46797
|
+
*/
|
|
46798
|
+
askVerdict: boolean().optional()
|
|
46448
46799
|
});
|
|
46449
46800
|
/**
|
|
46450
46801
|
* Partial patch for `updateRule` — any subset of the input fields, plus the
|
|
@@ -56901,7 +57252,7 @@ var BatteryStatusSchema = object({
|
|
|
56901
57252
|
*/
|
|
56902
57253
|
binary: boolean().optional().meta({ label: "Binary indicator" })
|
|
56903
57254
|
});
|
|
56904
|
-
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat;
|
|
57255
|
+
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.EventEmitter;
|
|
56905
57256
|
method(object({
|
|
56906
57257
|
deviceId: number(),
|
|
56907
57258
|
/** Bound on the wait. Sensible range 3000–10000ms. */
|
|
@@ -58645,7 +58996,13 @@ results: array(object({
|
|
|
58645
58996
|
/** Ms epoch of the attempt. */
|
|
58646
58997
|
at: number()
|
|
58647
58998
|
})) });
|
|
58648
|
-
DeviceType.Switch, DeviceType.Light;
|
|
58999
|
+
DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Cover, DeviceType.Valve, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.Thermostat, DeviceType.Climate;
|
|
59000
|
+
object({
|
|
59001
|
+
active: boolean().meta({ label: "Active" }),
|
|
59002
|
+
/** Ms epoch when the slice was last updated. */
|
|
59003
|
+
lastChangedAt: number()
|
|
59004
|
+
});
|
|
59005
|
+
DeviceType.Cover, DeviceType.Valve, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.Climate, DeviceType.Thermostat;
|
|
58649
59006
|
object({
|
|
58650
59007
|
/** Members whose current value entered the aggregate. */
|
|
58651
59008
|
included: number().int().nonnegative().meta(readingMeta("count", {
|
|
@@ -58663,7 +59020,7 @@ object({
|
|
|
58663
59020
|
label: "Members"
|
|
58664
59021
|
}))
|
|
58665
59022
|
});
|
|
58666
|
-
DeviceType.Sensor, DeviceType.Switch, DeviceType.Light;
|
|
59023
|
+
DeviceType.Sensor, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Cover, DeviceType.Valve, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.Thermostat, DeviceType.Climate;
|
|
58667
59024
|
object({
|
|
58668
59025
|
/** Radiator valve opening 0 (closed) .. 100 (open). Null = not yet known. */
|
|
58669
59026
|
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
@@ -59570,7 +59927,14 @@ DeviceType.Lock, method(object({
|
|
|
59570
59927
|
auth: "protected"
|
|
59571
59928
|
}), method(object({
|
|
59572
59929
|
deviceId: number().int().nonnegative(),
|
|
59573
|
-
code: string().min(1).optional()
|
|
59930
|
+
code: string().min(1).optional(),
|
|
59931
|
+
/**
|
|
59932
|
+
* Honoured by a helper lock GROUP only (D944): unlocking several doors
|
|
59933
|
+
* with one call is refused unless the caller says it was confirmed. A
|
|
59934
|
+
* single lock ignores it. The refusal lives in the callee, so no
|
|
59935
|
+
* automation or API caller reaches the doors by skipping a dialog.
|
|
59936
|
+
*/
|
|
59937
|
+
confirm: boolean().optional()
|
|
59574
59938
|
}), _void(), {
|
|
59575
59939
|
kind: "mutation",
|
|
59576
59940
|
auth: "protected"
|
|
@@ -59578,6 +59942,11 @@ DeviceType.Lock, method(object({
|
|
|
59578
59942
|
kind: "mutation",
|
|
59579
59943
|
auth: "protected"
|
|
59580
59944
|
});
|
|
59945
|
+
object({
|
|
59946
|
+
value: number().nullable().meta(readingMeta("device", { label: "Total" })),
|
|
59947
|
+
lastFetchedAt: number()
|
|
59948
|
+
});
|
|
59949
|
+
DeviceType.Sensor;
|
|
59581
59950
|
/**
|
|
59582
59951
|
* Media-player cap. Models HA `media_player.*` (Sonos, Chromecast,
|
|
59583
59952
|
* Apple TV, Spotify, Roku, generic OTT receivers, …) on
|
|
@@ -61485,9 +61854,9 @@ object({
|
|
|
61485
61854
|
/** Cumulative energy in kilowatt-hours since the meter was reset. */
|
|
61486
61855
|
kwhTotal: number().optional().meta(readingMeta("energy", { label: "Energy" })),
|
|
61487
61856
|
/** Voltage in volts. */
|
|
61488
|
-
volts: number().optional().meta(readingMeta("voltage")),
|
|
61857
|
+
volts: number().optional().meta(readingMeta("voltage", { label: "Voltage" })),
|
|
61489
61858
|
/** Current in amperes. */
|
|
61490
|
-
amps: number().optional().meta(readingMeta("current")),
|
|
61859
|
+
amps: number().optional().meta(readingMeta("current", { label: "Current" })),
|
|
61491
61860
|
/** Apparent power in volt-amperes. */
|
|
61492
61861
|
va: number().optional().meta(readingMeta("apparent-power")),
|
|
61493
61862
|
/** Power factor (0..1) if reported. */
|
|
@@ -61495,7 +61864,23 @@ object({
|
|
|
61495
61864
|
/** Ms epoch when the slice was last updated. */
|
|
61496
61865
|
lastFetchedAt: number()
|
|
61497
61866
|
});
|
|
61498
|
-
|
|
61867
|
+
[
|
|
61868
|
+
DeviceType.Sensor,
|
|
61869
|
+
DeviceType.Switch,
|
|
61870
|
+
DeviceType.Light,
|
|
61871
|
+
DeviceType.Fan,
|
|
61872
|
+
DeviceType.Climate,
|
|
61873
|
+
DeviceType.Thermostat,
|
|
61874
|
+
DeviceType.Humidifier,
|
|
61875
|
+
DeviceType.WaterHeater,
|
|
61876
|
+
DeviceType.MediaPlayer,
|
|
61877
|
+
DeviceType.Washer,
|
|
61878
|
+
DeviceType.Dryer,
|
|
61879
|
+
DeviceType.Dishwasher,
|
|
61880
|
+
DeviceType.Vacuum,
|
|
61881
|
+
DeviceType.LawnMower,
|
|
61882
|
+
DeviceType.PetFeeder
|
|
61883
|
+
].filter((type) => type !== DeviceType.Sensor);
|
|
61499
61884
|
/**
|
|
61500
61885
|
* Presence cap. Models HA `person.*` and `device_tracker.*` entities
|
|
61501
61886
|
* on `DeviceType.Presence`. Read-only — no setters: presence is
|
|
@@ -61942,7 +62327,7 @@ object({
|
|
|
61942
62327
|
phase: string().nullable()
|
|
61943
62328
|
});
|
|
61944
62329
|
Object.values(DeviceType);
|
|
61945
|
-
DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
|
|
62330
|
+
DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
|
|
61946
62331
|
DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch, method(object({ deviceId: number().int().nonnegative() }), object({ success: literal(true) }), {
|
|
61947
62332
|
kind: "mutation",
|
|
61948
62333
|
auth: "admin"
|
|
@@ -63981,7 +64366,7 @@ object({
|
|
|
63981
64366
|
/** Ms epoch of the last state change. Useful for UI "X minutes ago". */
|
|
63982
64367
|
lastChangedAt: number()
|
|
63983
64368
|
});
|
|
63984
|
-
DeviceType.Switch, DeviceType.Siren, DeviceType.Light, method(object({
|
|
64369
|
+
DeviceType.Switch, DeviceType.Siren, DeviceType.Light, DeviceType.Fan, method(object({
|
|
63985
64370
|
deviceId: number(),
|
|
63986
64371
|
on: boolean()
|
|
63987
64372
|
}), _void(), {
|
|
@@ -65673,8 +66058,9 @@ method(object({}), array(TrainingBaseModelSchema).readonly(), { auth: "admin" })
|
|
|
65673
66058
|
kind: "mutation",
|
|
65674
66059
|
auth: "admin"
|
|
65675
66060
|
});
|
|
66061
|
+
DeviceFeature.FanSpeed, DeviceFeature.FanPreset, DeviceFeature.FanDirection, DeviceFeature.FanOscillating, DeviceFeature.CoverPositionable, DeviceFeature.CoverTilt, DeviceFeature.ValvePositionable, DeviceFeature.MediaPlayerVolume, DeviceFeature.ClimateFanMode;
|
|
65676
66062
|
SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
|
|
65677
|
-
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;
|
|
66063
|
+
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;
|
|
65678
66064
|
String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
|
|
65679
66065
|
DeviceRole.BinarySensor, DeviceRole.MotionSensor;
|
|
65680
66066
|
new Set(CAP_NAMES);
|
|
@@ -65727,7 +66113,7 @@ var AccessoryKind = {
|
|
|
65727
66113
|
PrivacyMask: DeviceRole.PrivacyMask
|
|
65728
66114
|
};
|
|
65729
66115
|
AccessoryKind.Siren, AccessoryKind.Floodlight, AccessoryKind.Spotlight, AccessoryKind.PirSensor, AccessoryKind.Chime, AccessoryKind.Autotrack, AccessoryKind.Nightvision, AccessoryKind.PrivacyMask;
|
|
65730
|
-
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;
|
|
66116
|
+
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;
|
|
65731
66117
|
new Set(Object.values(DeviceType));
|
|
65732
66118
|
Object.freeze({
|
|
65733
66119
|
"accessories.getStatus": {
|
|
@@ -68950,6 +69336,13 @@ Object.freeze({
|
|
|
68950
69336
|
access: "view",
|
|
68951
69337
|
role: "viewer"
|
|
68952
69338
|
},
|
|
69339
|
+
"groupActive.getStatus": {
|
|
69340
|
+
capName: "group-active",
|
|
69341
|
+
capScope: "device",
|
|
69342
|
+
addonId: null,
|
|
69343
|
+
access: "view",
|
|
69344
|
+
role: "viewer"
|
|
69345
|
+
},
|
|
68953
69346
|
"groupCommands.getStatus": {
|
|
68954
69347
|
capName: "group-commands",
|
|
68955
69348
|
capScope: "device",
|
|
@@ -69916,6 +70309,13 @@ Object.freeze({
|
|
|
69916
70309
|
access: "create",
|
|
69917
70310
|
role: "admin"
|
|
69918
70311
|
},
|
|
70312
|
+
"meter.getStatus": {
|
|
70313
|
+
capName: "meter",
|
|
70314
|
+
capScope: "device",
|
|
70315
|
+
addonId: null,
|
|
70316
|
+
access: "view",
|
|
70317
|
+
role: "viewer"
|
|
70318
|
+
},
|
|
69919
70319
|
"metricsProvider.collectSnapshot": {
|
|
69920
70320
|
capName: "metrics-provider",
|
|
69921
70321
|
capScope: "system",
|
|
@@ -78014,7 +78414,39 @@ var APPLIANCE_CAP_VOCABULARY = {
|
|
|
78014
78414
|
phrase: t("When {device} finishes", "Quando {device} finisce"),
|
|
78015
78415
|
icon: "square"
|
|
78016
78416
|
}
|
|
78017
|
-
}
|
|
78417
|
+
},
|
|
78418
|
+
overrides: { byType: {
|
|
78419
|
+
[DeviceType.Washer]: {
|
|
78420
|
+
state: { running: {
|
|
78421
|
+
whenTrue: t("When the washing machine starts", "Quando la lavatrice inizia"),
|
|
78422
|
+
whenFalse: t("When the washing machine has finished", "Quando la lavatrice ha finito")
|
|
78423
|
+
} },
|
|
78424
|
+
events: {
|
|
78425
|
+
onStarted: { phrase: t("When the washing machine starts", "Quando la lavatrice inizia") },
|
|
78426
|
+
onFinished: { phrase: t("When the washing machine has finished", "Quando la lavatrice ha finito") }
|
|
78427
|
+
}
|
|
78428
|
+
},
|
|
78429
|
+
[DeviceType.Dryer]: {
|
|
78430
|
+
state: { running: {
|
|
78431
|
+
whenTrue: t("When the dryer starts", "Quando l'asciugatrice inizia"),
|
|
78432
|
+
whenFalse: t("When the dryer has finished", "Quando l'asciugatrice ha finito")
|
|
78433
|
+
} },
|
|
78434
|
+
events: {
|
|
78435
|
+
onStarted: { phrase: t("When the dryer starts", "Quando l'asciugatrice inizia") },
|
|
78436
|
+
onFinished: { phrase: t("When the dryer has finished", "Quando l'asciugatrice ha finito") }
|
|
78437
|
+
}
|
|
78438
|
+
},
|
|
78439
|
+
[DeviceType.Dishwasher]: {
|
|
78440
|
+
state: { running: {
|
|
78441
|
+
whenTrue: t("When the dishwasher starts", "Quando la lavastoviglie inizia"),
|
|
78442
|
+
whenFalse: t("When the dishwasher has finished", "Quando la lavastoviglie ha finito")
|
|
78443
|
+
} },
|
|
78444
|
+
events: {
|
|
78445
|
+
onStarted: { phrase: t("When the dishwasher starts", "Quando la lavastoviglie inizia") },
|
|
78446
|
+
onFinished: { phrase: t("When the dishwasher has finished", "Quando la lavastoviglie ha finito") }
|
|
78447
|
+
}
|
|
78448
|
+
}
|
|
78449
|
+
} }
|
|
78018
78450
|
},
|
|
78019
78451
|
update: {
|
|
78020
78452
|
scope: "device",
|
|
@@ -78786,6 +79218,10 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78786
79218
|
icon: "flame"
|
|
78787
79219
|
}]
|
|
78788
79220
|
},
|
|
79221
|
+
"group-active": {
|
|
79222
|
+
scope: "device",
|
|
79223
|
+
noun: t("Group state", "Stato del gruppo")
|
|
79224
|
+
},
|
|
78789
79225
|
"group-commands": {
|
|
78790
79226
|
scope: "device",
|
|
78791
79227
|
noun: t("Group command", "Comando di gruppo")
|
|
@@ -78842,6 +79278,17 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78842
79278
|
}],
|
|
78843
79279
|
events: { onMotionChanged: { notOperatorFacing: "the `detected` state trigger phrases both edges, from the mirror that survives a dropped event (D49)" } }
|
|
78844
79280
|
},
|
|
79281
|
+
meter: {
|
|
79282
|
+
scope: "device",
|
|
79283
|
+
noun: t("Meter", "Contatore"),
|
|
79284
|
+
state: [{
|
|
79285
|
+
kind: "numeric",
|
|
79286
|
+
field: "value",
|
|
79287
|
+
quantity: t("the total", "il totale"),
|
|
79288
|
+
label: t("Total", "Totale"),
|
|
79289
|
+
icon: "gauge"
|
|
79290
|
+
}]
|
|
79291
|
+
},
|
|
78845
79292
|
"numeric-sensor": {
|
|
78846
79293
|
scope: "device",
|
|
78847
79294
|
noun: t("Sensor", "Sensore"),
|
|
@@ -79314,8 +79761,47 @@ function projectAction(cap, action) {
|
|
|
79314
79761
|
};
|
|
79315
79762
|
}
|
|
79316
79763
|
Object.entries(CAP_VOCABULARY_BY_NAME).flatMap(([cap, entry]) => entry.scope === "device" ? (entry.actions ?? []).map((a) => projectAction(cap, a)) : []);
|
|
79317
|
-
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;
|
|
79764
|
+
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;
|
|
79318
79765
|
DeviceFeature.BatteryOperated;
|
|
79766
|
+
DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher;
|
|
79767
|
+
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.";
|
|
79768
|
+
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.";
|
|
79769
|
+
var ALEXA_REASON = "Alexa has no laundry category in this export, and neither power nor running has an Alexa interface.";
|
|
79770
|
+
var GOOGLE_REASON = "Google WASHER, DRYER and DISHWASHER require RunCycle. A power threshold is not that trait, and this export does not publish RunCycle.";
|
|
79771
|
+
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.";
|
|
79772
|
+
function withheld(reason) {
|
|
79773
|
+
return {
|
|
79774
|
+
[DeviceType.Washer]: {
|
|
79775
|
+
exported: false,
|
|
79776
|
+
reason
|
|
79777
|
+
},
|
|
79778
|
+
[DeviceType.Dryer]: {
|
|
79779
|
+
exported: false,
|
|
79780
|
+
reason
|
|
79781
|
+
},
|
|
79782
|
+
[DeviceType.Dishwasher]: {
|
|
79783
|
+
exported: false,
|
|
79784
|
+
reason
|
|
79785
|
+
}
|
|
79786
|
+
};
|
|
79787
|
+
}
|
|
79788
|
+
function offered(received) {
|
|
79789
|
+
return {
|
|
79790
|
+
[DeviceType.Washer]: {
|
|
79791
|
+
exported: true,
|
|
79792
|
+
as: received
|
|
79793
|
+
},
|
|
79794
|
+
[DeviceType.Dryer]: {
|
|
79795
|
+
exported: true,
|
|
79796
|
+
as: received
|
|
79797
|
+
},
|
|
79798
|
+
[DeviceType.Dishwasher]: {
|
|
79799
|
+
exported: true,
|
|
79800
|
+
as: received
|
|
79801
|
+
}
|
|
79802
|
+
};
|
|
79803
|
+
}
|
|
79804
|
+
offered(HA_AS), withheld(HOMEKIT_REASON), withheld(ALEXA_REASON), withheld(GOOGLE_REASON), withheld(MATTER_REASON);
|
|
79319
79805
|
Object.freeze({
|
|
79320
79806
|
"accessories.getStatus": [{
|
|
79321
79807
|
name: "deviceId",
|
|
@@ -80282,6 +80768,11 @@ Object.freeze({
|
|
|
80282
80768
|
form: "single",
|
|
80283
80769
|
optional: false
|
|
80284
80770
|
}],
|
|
80771
|
+
"groupActive.getStatus": [{
|
|
80772
|
+
name: "deviceId",
|
|
80773
|
+
form: "single",
|
|
80774
|
+
optional: false
|
|
80775
|
+
}],
|
|
80285
80776
|
"groupCommands.getStatus": [{
|
|
80286
80777
|
name: "deviceId",
|
|
80287
80778
|
form: "single",
|
|
@@ -80492,6 +80983,11 @@ Object.freeze({
|
|
|
80492
80983
|
form: "single",
|
|
80493
80984
|
optional: false
|
|
80494
80985
|
}],
|
|
80986
|
+
"meter.getStatus": [{
|
|
80987
|
+
name: "deviceId",
|
|
80988
|
+
form: "single",
|
|
80989
|
+
optional: false
|
|
80990
|
+
}],
|
|
80495
80991
|
"motion.getStatus": [{
|
|
80496
80992
|
name: "deviceId",
|
|
80497
80993
|
form: "single",
|
|
@@ -82099,7 +82595,6 @@ Object.freeze({
|
|
|
82099
82595
|
"network-access": "ingress",
|
|
82100
82596
|
"smtp-provider": "email"
|
|
82101
82597
|
});
|
|
82102
|
-
DeviceType.Camera;
|
|
82103
82598
|
/**
|
|
82104
82599
|
* A saved Customize assignment (D936). The schema is the type: callers use
|
|
82105
82600
|
* `z.infer`, they do not restate the shape.
|