@camstack/addon-google-services 0.2.32 → 0.2.33
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 +26 -8
- package/dist/google-services.addon.js +542 -47
- package/dist/google-services.addon.mjs +542 -47
- package/package.json +4 -4
|
@@ -5575,7 +5575,7 @@ var ZodIssueCode = {
|
|
|
5575
5575
|
var ZodFirstPartyTypeKind;
|
|
5576
5576
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5577
5577
|
//#endregion
|
|
5578
|
-
//#region ../types/dist/sleep
|
|
5578
|
+
//#region ../types/dist/sleep--jXS9hWo.mjs
|
|
5579
5579
|
/**
|
|
5580
5580
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5581
5581
|
* window to float samples (D455).
|
|
@@ -8952,6 +8952,7 @@ var CAP_NAMES = Object.freeze([
|
|
|
8952
8952
|
"filesystem-browse",
|
|
8953
8953
|
"flood",
|
|
8954
8954
|
"gas",
|
|
8955
|
+
"group-active",
|
|
8955
8956
|
"group-commands",
|
|
8956
8957
|
"group-status",
|
|
8957
8958
|
"heating-valve",
|
|
@@ -8974,6 +8975,7 @@ var CAP_NAMES = Object.freeze([
|
|
|
8974
8975
|
"login-method",
|
|
8975
8976
|
"media-player",
|
|
8976
8977
|
"mesh-network",
|
|
8978
|
+
"meter",
|
|
8977
8979
|
"metrics-provider",
|
|
8978
8980
|
"model-convert",
|
|
8979
8981
|
"model-distributor",
|
|
@@ -9772,6 +9774,10 @@ Object.freeze({
|
|
|
9772
9774
|
"path": "detected",
|
|
9773
9775
|
"valueType": "boolean"
|
|
9774
9776
|
}],
|
|
9777
|
+
"group-active": [{
|
|
9778
|
+
"path": "active",
|
|
9779
|
+
"valueType": "boolean"
|
|
9780
|
+
}],
|
|
9775
9781
|
"group-status": [
|
|
9776
9782
|
{
|
|
9777
9783
|
"path": "included",
|
|
@@ -10031,6 +10037,10 @@ Object.freeze({
|
|
|
10031
10037
|
]
|
|
10032
10038
|
}
|
|
10033
10039
|
],
|
|
10040
|
+
"meter": [{
|
|
10041
|
+
"path": "value",
|
|
10042
|
+
"valueType": "number"
|
|
10043
|
+
}],
|
|
10034
10044
|
"motion": [
|
|
10035
10045
|
{
|
|
10036
10046
|
"path": "detected",
|
|
@@ -10788,7 +10798,7 @@ function userError(code, params, englishFallback) {
|
|
|
10788
10798
|
return new CamstackError(code, params, englishFallback);
|
|
10789
10799
|
}
|
|
10790
10800
|
//#endregion
|
|
10791
|
-
//#region ../types/dist/err-msg-
|
|
10801
|
+
//#region ../types/dist/err-msg-DIorGYeC.mjs
|
|
10792
10802
|
var DeviceType = /* @__PURE__ */ function(DeviceType) {
|
|
10793
10803
|
DeviceType["Camera"] = "camera";
|
|
10794
10804
|
DeviceType["Hub"] = "hub";
|
|
@@ -10882,8 +10892,14 @@ var DeviceType = /* @__PURE__ */ function(DeviceType) {
|
|
|
10882
10892
|
DeviceType["PetFeeder"] = "pet-feeder";
|
|
10883
10893
|
/** Built-in dishwasher — program lifecycle, door / remote-start gates,
|
|
10884
10894
|
* salt and rinse-aid levels. Installed with the `dishwasher` cap.
|
|
10885
|
-
* Sources: native Bosch Home Connect, reusable by similar integrations.
|
|
10895
|
+
* Sources: native Bosch Home Connect, reusable by similar integrations.
|
|
10896
|
+
* A plug-built dishwasher carries running-state and power instead. */
|
|
10886
10897
|
DeviceType["Dishwasher"] = "dishwasher";
|
|
10898
|
+
/** Washing machine. A plug-built one is running while its power stays
|
|
10899
|
+
* above a threshold. No program cap — that surface is the dishwasher's. */
|
|
10900
|
+
DeviceType["Washer"] = "washer";
|
|
10901
|
+
/** Tumble dryer. Same plug-built running surface as {@link Washer}. */
|
|
10902
|
+
DeviceType["Dryer"] = "dryer";
|
|
10887
10903
|
return DeviceType;
|
|
10888
10904
|
}({});
|
|
10889
10905
|
var DeviceFeature = /* @__PURE__ */ function(DeviceFeature) {
|
|
@@ -11131,7 +11147,7 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
|
|
|
11131
11147
|
return DeviceRole;
|
|
11132
11148
|
}({});
|
|
11133
11149
|
//#endregion
|
|
11134
|
-
//#region ../types/dist/composition-
|
|
11150
|
+
//#region ../types/dist/composition-Bb8iwHEJ.mjs
|
|
11135
11151
|
/**
|
|
11136
11152
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
11137
11153
|
*
|
|
@@ -11446,6 +11462,13 @@ var table = {
|
|
|
11446
11462
|
apply: () => {
|
|
11447
11463
|
throw new ExpressionEvalError("latchedAt: stateful evaluation context is required");
|
|
11448
11464
|
}
|
|
11465
|
+
},
|
|
11466
|
+
schmitt: {
|
|
11467
|
+
minArgs: 3,
|
|
11468
|
+
maxArgs: 5,
|
|
11469
|
+
apply: () => {
|
|
11470
|
+
throw new ExpressionEvalError("schmitt: stateful evaluation context is required");
|
|
11471
|
+
}
|
|
11449
11472
|
}
|
|
11450
11473
|
};
|
|
11451
11474
|
Object.freeze(Object.assign(Object.create(null), table));
|
|
@@ -11887,6 +11910,99 @@ function validateExpressionSource(src) {
|
|
|
11887
11910
|
return null;
|
|
11888
11911
|
}
|
|
11889
11912
|
/**
|
|
11913
|
+
* One power reading becomes a washer, dryer or dishwasher (D944 helper).
|
|
11914
|
+
*
|
|
11915
|
+
* Standby of the control board is under 5 W; a motor or a heater is far
|
|
11916
|
+
* above that, so 5 W is the line. A door lock or a short pump spike is not
|
|
11917
|
+
* a cycle, so running starts only after 30 s above the line.
|
|
11918
|
+
*
|
|
11919
|
+
* A wash, dry or dishwasher pause (soak, heat-wait, heater off between
|
|
11920
|
+
* bursts) lasts several minutes. Ending the cycle on the first dip would
|
|
11921
|
+
* report "finished" in the middle of the program, so the stop dwell is
|
|
11922
|
+
* 10 minutes on every type. The number is stored per type so one machine
|
|
11923
|
+
* can move later without moving the others.
|
|
11924
|
+
*/
|
|
11925
|
+
var APPLIANCE_TEMPLATE_ID = "appliance";
|
|
11926
|
+
var APPLIANCE_KINDS = [
|
|
11927
|
+
"washer",
|
|
11928
|
+
"dryer",
|
|
11929
|
+
"dishwasher"
|
|
11930
|
+
];
|
|
11931
|
+
DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher;
|
|
11932
|
+
/**
|
|
11933
|
+
* Statistics and integrals over a history read (D944).
|
|
11934
|
+
*
|
|
11935
|
+
* Pure: the same points always give the same answer, so a restart recomputes
|
|
11936
|
+
* rather than trusting a buffer. A gauge mean is time-weighted (value × ms),
|
|
11937
|
+
* never the mean of the samples. A hole with no held value is not integrated
|
|
11938
|
+
* as zero. A truncated read is not published.
|
|
11939
|
+
*/
|
|
11940
|
+
var STATISTIC_STATS = [
|
|
11941
|
+
"min",
|
|
11942
|
+
"max",
|
|
11943
|
+
"mean",
|
|
11944
|
+
"sum",
|
|
11945
|
+
"count",
|
|
11946
|
+
"change"
|
|
11947
|
+
];
|
|
11948
|
+
/**
|
|
11949
|
+
* The range a statistics or integral helper asks history for (D944).
|
|
11950
|
+
*
|
|
11951
|
+
* Calendar edges are the hub's timezone, never UTC midnight: a day is 23, 24
|
|
11952
|
+
* or 25 hours across a DST change. A tier is eligible only when its retention
|
|
11953
|
+
* is strictly longer than the longest that range can be. Forever qualifies.
|
|
11954
|
+
* Equal to a tier's retention is a refusal, not a short answer.
|
|
11955
|
+
*/
|
|
11956
|
+
var MINUTE_MS = 6e4;
|
|
11957
|
+
var HOUR_MS = 60 * MINUTE_MS;
|
|
11958
|
+
var DAY_MS = 24 * HOUR_MS;
|
|
11959
|
+
var ROLLING_SPANS = [
|
|
11960
|
+
"1h",
|
|
11961
|
+
"24h",
|
|
11962
|
+
"2d",
|
|
11963
|
+
"7d",
|
|
11964
|
+
"30d",
|
|
11965
|
+
"custom"
|
|
11966
|
+
];
|
|
11967
|
+
var CALENDAR_PERIODS = [
|
|
11968
|
+
"today",
|
|
11969
|
+
"yesterday",
|
|
11970
|
+
"this-week",
|
|
11971
|
+
"this-month"
|
|
11972
|
+
];
|
|
11973
|
+
var RESET_PERIODS = [
|
|
11974
|
+
"never",
|
|
11975
|
+
"daily",
|
|
11976
|
+
"weekly",
|
|
11977
|
+
"monthly"
|
|
11978
|
+
];
|
|
11979
|
+
5 * MINUTE_MS;
|
|
11980
|
+
24 * HOUR_MS, 2 * DAY_MS, 7 * DAY_MS, 30 * DAY_MS;
|
|
11981
|
+
7 * DAY_MS, 30 * DAY_MS, 365 * DAY_MS;
|
|
11982
|
+
var rollingWindowObject = object({
|
|
11983
|
+
kind: literal("rolling"),
|
|
11984
|
+
span: _enum(ROLLING_SPANS),
|
|
11985
|
+
customMinutes: number().int().min(5).optional()
|
|
11986
|
+
}).check((payload) => {
|
|
11987
|
+
if (payload.value.span === "custom" && payload.value.customMinutes === void 0) payload.issues.push({
|
|
11988
|
+
code: "custom",
|
|
11989
|
+
message: "a custom range needs a duration in minutes",
|
|
11990
|
+
path: ["customMinutes"],
|
|
11991
|
+
input: payload.value
|
|
11992
|
+
});
|
|
11993
|
+
if (payload.value.span !== "custom" && payload.value.customMinutes !== void 0) payload.issues.push({
|
|
11994
|
+
code: "custom",
|
|
11995
|
+
message: "only a custom range carries a duration",
|
|
11996
|
+
path: ["customMinutes"],
|
|
11997
|
+
input: payload.value
|
|
11998
|
+
});
|
|
11999
|
+
});
|
|
12000
|
+
var RollingWindowSchema = rollingWindowObject;
|
|
12001
|
+
var StatisticWindowSchema = discriminatedUnion("kind", [rollingWindowObject, object({
|
|
12002
|
+
kind: literal("calendar"),
|
|
12003
|
+
period: _enum(CALENDAR_PERIODS)
|
|
12004
|
+
})]);
|
|
12005
|
+
/**
|
|
11890
12006
|
* A composition source identity: `(addonId, stableId)`, never a numeric device
|
|
11891
12007
|
* id. Split out so helper schemas can name it without a cycle through
|
|
11892
12008
|
* `composition.ts` (D659).
|
|
@@ -11912,7 +12028,13 @@ var GROUP_TEMPLATE_IDS = [
|
|
|
11912
12028
|
"occupancy",
|
|
11913
12029
|
"binary",
|
|
11914
12030
|
"switch",
|
|
11915
|
-
"light"
|
|
12031
|
+
"light",
|
|
12032
|
+
"fan",
|
|
12033
|
+
"cover",
|
|
12034
|
+
"valve",
|
|
12035
|
+
"lock",
|
|
12036
|
+
"media-player",
|
|
12037
|
+
"climate"
|
|
11916
12038
|
];
|
|
11917
12039
|
var NUMERIC_AGGREGATES = [
|
|
11918
12040
|
"mean",
|
|
@@ -11942,14 +12064,73 @@ var HelperMemberSchema = object({
|
|
|
11942
12064
|
cap: string().min(1),
|
|
11943
12065
|
fieldPath: string().min(1)
|
|
11944
12066
|
});
|
|
11945
|
-
var HelperSpecSchema = discriminatedUnion("kind", [
|
|
11946
|
-
|
|
11947
|
-
|
|
11948
|
-
|
|
11949
|
-
|
|
11950
|
-
|
|
11951
|
-
|
|
11952
|
-
|
|
12067
|
+
var HelperSpecSchema = discriminatedUnion("kind", [
|
|
12068
|
+
object({
|
|
12069
|
+
kind: literal("group"),
|
|
12070
|
+
templateId: GroupTemplateIdSchema,
|
|
12071
|
+
aggregate: AggregateReducerSchema,
|
|
12072
|
+
members: array(HelperMemberSchema).min(1).max(64),
|
|
12073
|
+
/** Actuator groups only. Readings leave this unset. */
|
|
12074
|
+
active: ActiveCriterionSchema.optional()
|
|
12075
|
+
}),
|
|
12076
|
+
object({
|
|
12077
|
+
kind: literal("appliance"),
|
|
12078
|
+
templateId: literal(APPLIANCE_TEMPLATE_ID),
|
|
12079
|
+
appliance: _enum(APPLIANCE_KINDS),
|
|
12080
|
+
thresholdWatts: number().positive(),
|
|
12081
|
+
startDwellMs: number().int().nonnegative(),
|
|
12082
|
+
stopDwellMs: number().int().nonnegative(),
|
|
12083
|
+
member: HelperMemberSchema
|
|
12084
|
+
}),
|
|
12085
|
+
object({
|
|
12086
|
+
kind: literal("statistic"),
|
|
12087
|
+
stat: _enum(STATISTIC_STATS),
|
|
12088
|
+
window: StatisticWindowSchema,
|
|
12089
|
+
source: HelperMemberSchema
|
|
12090
|
+
}),
|
|
12091
|
+
object({
|
|
12092
|
+
kind: literal("integral"),
|
|
12093
|
+
reset: _enum(RESET_PERIODS),
|
|
12094
|
+
output: _enum(["energy", "meter"]),
|
|
12095
|
+
source: HelperMemberSchema
|
|
12096
|
+
}),
|
|
12097
|
+
object({
|
|
12098
|
+
kind: literal("threshold"),
|
|
12099
|
+
source: HelperMemberSchema,
|
|
12100
|
+
high: number(),
|
|
12101
|
+
low: number(),
|
|
12102
|
+
onForMs: number().int().nonnegative(),
|
|
12103
|
+
offForMs: number().int().nonnegative()
|
|
12104
|
+
}),
|
|
12105
|
+
object({
|
|
12106
|
+
kind: literal("arithmetic"),
|
|
12107
|
+
op: _enum([
|
|
12108
|
+
"sum",
|
|
12109
|
+
"difference",
|
|
12110
|
+
"ratio"
|
|
12111
|
+
]),
|
|
12112
|
+
inputs: array(HelperMemberSchema).min(2).max(64)
|
|
12113
|
+
}),
|
|
12114
|
+
object({
|
|
12115
|
+
kind: literal("expression"),
|
|
12116
|
+
expr: string().min(1),
|
|
12117
|
+
inputs: array(object({
|
|
12118
|
+
name: string().min(1),
|
|
12119
|
+
member: HelperMemberSchema
|
|
12120
|
+
})).min(1).max(64),
|
|
12121
|
+
output: _enum(["number", "boolean"])
|
|
12122
|
+
}),
|
|
12123
|
+
object({
|
|
12124
|
+
kind: literal("derivative"),
|
|
12125
|
+
window: RollingWindowSchema,
|
|
12126
|
+
per: _enum([
|
|
12127
|
+
"second",
|
|
12128
|
+
"minute",
|
|
12129
|
+
"hour"
|
|
12130
|
+
]),
|
|
12131
|
+
source: HelperMemberSchema
|
|
12132
|
+
})
|
|
12133
|
+
]);
|
|
11953
12134
|
/** A composed device's stableId is this prefix plus the block id. */
|
|
11954
12135
|
var COMPOSED_DEVICE_STABLE_ID_PREFIX = "composed-";
|
|
11955
12136
|
/** Longest snippet a `code` source may carry (slice 4). */
|
|
@@ -12010,6 +12191,12 @@ var CompositionFieldSourceSchema = discriminatedUnion("kind", [
|
|
|
12010
12191
|
"all"
|
|
12011
12192
|
]),
|
|
12012
12193
|
reads: array(CompositionFieldReadSchema).min(1).max(64),
|
|
12194
|
+
/**
|
|
12195
|
+
* Set when the reads are an enum state, not a yes/no: the listed states
|
|
12196
|
+
* count as active (a cover is `open`). A state outside the list is inactive;
|
|
12197
|
+
* a read that is not a state at all is left out. Only `any` / `all` use it.
|
|
12198
|
+
*/
|
|
12199
|
+
activeWhen: array(string().min(1)).min(1).optional(),
|
|
12013
12200
|
/** `value` is the reading; the others are the member counts. */
|
|
12014
12201
|
publish: _enum([
|
|
12015
12202
|
"value",
|
|
@@ -12023,6 +12210,26 @@ var CompositionFieldSourceSchema = discriminatedUnion("kind", [
|
|
|
12023
12210
|
"omit",
|
|
12024
12211
|
"offline"
|
|
12025
12212
|
])
|
|
12213
|
+
}),
|
|
12214
|
+
object({
|
|
12215
|
+
kind: literal("series"),
|
|
12216
|
+
read: CompositionFieldReadSchema,
|
|
12217
|
+
/** `value` is the statistic or the integral. The others are the gap counts. */
|
|
12218
|
+
publish: _enum([
|
|
12219
|
+
"value",
|
|
12220
|
+
"included",
|
|
12221
|
+
"excluded",
|
|
12222
|
+
"total"
|
|
12223
|
+
]),
|
|
12224
|
+
/**
|
|
12225
|
+
* What an unanswered `value` does. Counts ignore this. `offline` leaves the
|
|
12226
|
+
* device unseeded until history answers, so a restart cannot publish 0.
|
|
12227
|
+
*/
|
|
12228
|
+
empty: _enum([
|
|
12229
|
+
"null",
|
|
12230
|
+
"omit",
|
|
12231
|
+
"offline"
|
|
12232
|
+
])
|
|
12026
12233
|
})
|
|
12027
12234
|
]);
|
|
12028
12235
|
var CompositionCommandTargetSchema = discriminatedUnion("kind", [object({
|
|
@@ -17318,7 +17525,22 @@ var BrokerProviderInfoSchema = object({
|
|
|
17318
17525
|
*/
|
|
17319
17526
|
interactiveConnectPath: string().min(1).optional(),
|
|
17320
17527
|
/** Relative hub path to disconnect the linked account (same popup pattern). */
|
|
17321
|
-
interactiveDisconnectPath: string().min(1).optional()
|
|
17528
|
+
interactiveDisconnectPath: string().min(1).optional(),
|
|
17529
|
+
/**
|
|
17530
|
+
* The kind signs in through a server-held interactive session instead of
|
|
17531
|
+
* (or before) typed credentials. `basePath` is a hub-relative route set
|
|
17532
|
+
* served by the owning addon (`/addon/<id>/...`) speaking the sign-in
|
|
17533
|
+
* contract: `POST {basePath}/start` (body: the form's settings) answers
|
|
17534
|
+
* `{ sessionId, loginUrl }`; `GET {basePath}/status?sessionId=` answers
|
|
17535
|
+
* `{ phase: 'starting' | 'awaiting-login' | 'captured' | 'error' |
|
|
17536
|
+
* 'cancelled', loginUrl, error }`; `POST {basePath}/commit`
|
|
17537
|
+
* (`{ sessionId, name, brokerId? }`) stores the credentials on a new or
|
|
17538
|
+
* existing broker and answers `{ brokerId }`; `POST {basePath}/cancel`
|
|
17539
|
+
* (`{ sessionId }`) drops the session. The dialog that edits a broker
|
|
17540
|
+
* offers it as the default path; the fields the session fills are
|
|
17541
|
+
* marked `filledBySignIn` in the kind's settings schema.
|
|
17542
|
+
*/
|
|
17543
|
+
signIn: object({ basePath: string().min(1) }).optional()
|
|
17322
17544
|
}))
|
|
17323
17545
|
});
|
|
17324
17546
|
var ListInputSchema = object({
|
|
@@ -18366,7 +18588,8 @@ var CompositionProblemSchema = object({
|
|
|
18366
18588
|
"native-capability-replace",
|
|
18367
18589
|
"mixed-quantity",
|
|
18368
18590
|
"helper-mismatch",
|
|
18369
|
-
"member-constraint"
|
|
18591
|
+
"member-constraint",
|
|
18592
|
+
"retention"
|
|
18370
18593
|
]),
|
|
18371
18594
|
path: string(),
|
|
18372
18595
|
message: string()
|
|
@@ -18600,13 +18823,17 @@ Object.freeze({
|
|
|
18600
18823
|
latchedAt: {
|
|
18601
18824
|
kind: "fixed",
|
|
18602
18825
|
result: ["number", "null"]
|
|
18826
|
+
},
|
|
18827
|
+
schmitt: {
|
|
18828
|
+
kind: "fixed",
|
|
18829
|
+
result: ["boolean", "null"]
|
|
18603
18830
|
}
|
|
18604
18831
|
});
|
|
18605
18832
|
/**
|
|
18606
18833
|
* One catalog row per base reading a group helper can build (D944 §3).
|
|
18607
18834
|
* Data, not a form default written into the block.
|
|
18608
18835
|
*/
|
|
18609
|
-
var NOW = {
|
|
18836
|
+
var NOW$2 = {
|
|
18610
18837
|
fieldPath: "lastFetchedAt",
|
|
18611
18838
|
expr: "now"
|
|
18612
18839
|
};
|
|
@@ -18620,6 +18847,8 @@ function numeric(input) {
|
|
|
18620
18847
|
family: "numeric",
|
|
18621
18848
|
deviceType: DeviceType.Sensor,
|
|
18622
18849
|
memberDeviceType: DeviceType.Sensor,
|
|
18850
|
+
memberDeviceTypes: [DeviceType.Sensor],
|
|
18851
|
+
activeWhen: void 0,
|
|
18623
18852
|
commandCaps: [],
|
|
18624
18853
|
baseUnit: baseUnitOf(input.quantity),
|
|
18625
18854
|
aggregates: NUMERIC_AGGREGATES,
|
|
@@ -18635,6 +18864,8 @@ function binary(input) {
|
|
|
18635
18864
|
family: "binary",
|
|
18636
18865
|
deviceType: DeviceType.Sensor,
|
|
18637
18866
|
memberDeviceType: DeviceType.Sensor,
|
|
18867
|
+
memberDeviceTypes: [DeviceType.Sensor],
|
|
18868
|
+
activeWhen: void 0,
|
|
18638
18869
|
commandCaps: [],
|
|
18639
18870
|
quantity: "none",
|
|
18640
18871
|
baseUnit: void 0,
|
|
@@ -18652,7 +18883,7 @@ var GROUP_TEMPLATES = [
|
|
|
18652
18883
|
quantity: "temperature",
|
|
18653
18884
|
defaultAggregate: "mean",
|
|
18654
18885
|
empty: "null",
|
|
18655
|
-
companions: [NOW]
|
|
18886
|
+
companions: [NOW$2]
|
|
18656
18887
|
}),
|
|
18657
18888
|
numeric({
|
|
18658
18889
|
id: "humidity",
|
|
@@ -18663,7 +18894,7 @@ var GROUP_TEMPLATES = [
|
|
|
18663
18894
|
quantity: "humidity",
|
|
18664
18895
|
defaultAggregate: "mean",
|
|
18665
18896
|
empty: "null",
|
|
18666
|
-
companions: [NOW]
|
|
18897
|
+
companions: [NOW$2]
|
|
18667
18898
|
}),
|
|
18668
18899
|
numeric({
|
|
18669
18900
|
id: "pressure",
|
|
@@ -18674,7 +18905,7 @@ var GROUP_TEMPLATES = [
|
|
|
18674
18905
|
quantity: "pressure",
|
|
18675
18906
|
defaultAggregate: "mean",
|
|
18676
18907
|
empty: "null",
|
|
18677
|
-
companions: [NOW]
|
|
18908
|
+
companions: [NOW$2]
|
|
18678
18909
|
}),
|
|
18679
18910
|
numeric({
|
|
18680
18911
|
id: "illuminance",
|
|
@@ -18685,7 +18916,7 @@ var GROUP_TEMPLATES = [
|
|
|
18685
18916
|
quantity: "illuminance",
|
|
18686
18917
|
defaultAggregate: "mean",
|
|
18687
18918
|
empty: "null",
|
|
18688
|
-
companions: [NOW]
|
|
18919
|
+
companions: [NOW$2]
|
|
18689
18920
|
}),
|
|
18690
18921
|
numeric({
|
|
18691
18922
|
id: "power",
|
|
@@ -18696,7 +18927,7 @@ var GROUP_TEMPLATES = [
|
|
|
18696
18927
|
quantity: "power",
|
|
18697
18928
|
defaultAggregate: "sum",
|
|
18698
18929
|
empty: "omit",
|
|
18699
|
-
companions: [NOW]
|
|
18930
|
+
companions: [NOW$2]
|
|
18700
18931
|
}),
|
|
18701
18932
|
numeric({
|
|
18702
18933
|
id: "energy",
|
|
@@ -18707,7 +18938,7 @@ var GROUP_TEMPLATES = [
|
|
|
18707
18938
|
quantity: "energy",
|
|
18708
18939
|
defaultAggregate: "sum",
|
|
18709
18940
|
empty: "omit",
|
|
18710
|
-
companions: [NOW]
|
|
18941
|
+
companions: [NOW$2]
|
|
18711
18942
|
}),
|
|
18712
18943
|
numeric({
|
|
18713
18944
|
id: "battery",
|
|
@@ -18742,7 +18973,7 @@ var GROUP_TEMPLATES = [
|
|
|
18742
18973
|
quantity: "device",
|
|
18743
18974
|
defaultAggregate: "mean",
|
|
18744
18975
|
empty: "null",
|
|
18745
|
-
companions: [NOW]
|
|
18976
|
+
companions: [NOW$2]
|
|
18746
18977
|
}),
|
|
18747
18978
|
binary({
|
|
18748
18979
|
id: "motion",
|
|
@@ -18836,6 +19067,11 @@ var GROUP_TEMPLATES = [
|
|
|
18836
19067
|
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.",
|
|
18837
19068
|
deviceType: DeviceType.Switch,
|
|
18838
19069
|
outputCap: "switch",
|
|
19070
|
+
outputField: "on",
|
|
19071
|
+
member: {
|
|
19072
|
+
cap: "switch",
|
|
19073
|
+
fieldPath: "on"
|
|
19074
|
+
},
|
|
18839
19075
|
commandCaps: ["switch"]
|
|
18840
19076
|
}),
|
|
18841
19077
|
actuator({
|
|
@@ -18843,34 +19079,136 @@ var GROUP_TEMPLATES = [
|
|
|
18843
19079
|
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.",
|
|
18844
19080
|
deviceType: DeviceType.Light,
|
|
18845
19081
|
outputCap: "switch",
|
|
19082
|
+
outputField: "on",
|
|
19083
|
+
member: {
|
|
19084
|
+
cap: "switch",
|
|
19085
|
+
fieldPath: "on"
|
|
19086
|
+
},
|
|
18846
19087
|
commandCaps: [
|
|
18847
19088
|
"switch",
|
|
18848
19089
|
"brightness",
|
|
18849
19090
|
"color"
|
|
18850
19091
|
]
|
|
19092
|
+
}),
|
|
19093
|
+
actuator({
|
|
19094
|
+
id: "fan",
|
|
19095
|
+
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.",
|
|
19096
|
+
deviceType: DeviceType.Fan,
|
|
19097
|
+
outputCap: "switch",
|
|
19098
|
+
outputField: "on",
|
|
19099
|
+
member: {
|
|
19100
|
+
cap: "switch",
|
|
19101
|
+
fieldPath: "on"
|
|
19102
|
+
},
|
|
19103
|
+
commandCaps: ["switch", "fan-control"]
|
|
19104
|
+
}),
|
|
19105
|
+
actuator({
|
|
19106
|
+
id: "cover",
|
|
19107
|
+
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.",
|
|
19108
|
+
deviceType: DeviceType.Cover,
|
|
19109
|
+
outputCap: "group-active",
|
|
19110
|
+
outputField: "active",
|
|
19111
|
+
member: {
|
|
19112
|
+
cap: "cover",
|
|
19113
|
+
fieldPath: "state"
|
|
19114
|
+
},
|
|
19115
|
+
activeWhen: [
|
|
19116
|
+
"open",
|
|
19117
|
+
"opening",
|
|
19118
|
+
"stopped"
|
|
19119
|
+
],
|
|
19120
|
+
commandCaps: ["cover"]
|
|
19121
|
+
}),
|
|
19122
|
+
actuator({
|
|
19123
|
+
id: "valve",
|
|
19124
|
+
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.",
|
|
19125
|
+
deviceType: DeviceType.Valve,
|
|
19126
|
+
outputCap: "group-active",
|
|
19127
|
+
outputField: "active",
|
|
19128
|
+
member: {
|
|
19129
|
+
cap: "valve",
|
|
19130
|
+
fieldPath: "state"
|
|
19131
|
+
},
|
|
19132
|
+
activeWhen: [
|
|
19133
|
+
"open",
|
|
19134
|
+
"opening",
|
|
19135
|
+
"stopped"
|
|
19136
|
+
],
|
|
19137
|
+
commandCaps: ["valve"]
|
|
19138
|
+
}),
|
|
19139
|
+
actuator({
|
|
19140
|
+
id: "lock",
|
|
19141
|
+
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.",
|
|
19142
|
+
deviceType: DeviceType.Lock,
|
|
19143
|
+
outputCap: "group-active",
|
|
19144
|
+
outputField: "active",
|
|
19145
|
+
member: {
|
|
19146
|
+
cap: "lock-control",
|
|
19147
|
+
fieldPath: "state"
|
|
19148
|
+
},
|
|
19149
|
+
activeWhen: ["locked"],
|
|
19150
|
+
commandCaps: ["lock-control"]
|
|
19151
|
+
}),
|
|
19152
|
+
actuator({
|
|
19153
|
+
id: "media-player",
|
|
19154
|
+
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.",
|
|
19155
|
+
deviceType: DeviceType.MediaPlayer,
|
|
19156
|
+
outputCap: "group-active",
|
|
19157
|
+
outputField: "active",
|
|
19158
|
+
member: {
|
|
19159
|
+
cap: "media-player",
|
|
19160
|
+
fieldPath: "state"
|
|
19161
|
+
},
|
|
19162
|
+
activeWhen: ["playing", "buffering"],
|
|
19163
|
+
commandCaps: ["media-player"]
|
|
19164
|
+
}),
|
|
19165
|
+
actuator({
|
|
19166
|
+
id: "climate",
|
|
19167
|
+
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.",
|
|
19168
|
+
deviceType: DeviceType.Thermostat,
|
|
19169
|
+
memberDeviceTypes: [DeviceType.Thermostat, DeviceType.Climate],
|
|
19170
|
+
outputCap: "group-active",
|
|
19171
|
+
outputField: "active",
|
|
19172
|
+
member: {
|
|
19173
|
+
cap: "climate-control",
|
|
19174
|
+
fieldPath: "mode"
|
|
19175
|
+
},
|
|
19176
|
+
activeWhen: [
|
|
19177
|
+
"heat",
|
|
19178
|
+
"cool",
|
|
19179
|
+
"auto",
|
|
19180
|
+
"heat_cool",
|
|
19181
|
+
"fan_only",
|
|
19182
|
+
"dry"
|
|
19183
|
+
],
|
|
19184
|
+
commandCaps: ["climate-control"]
|
|
18851
19185
|
})
|
|
18852
19186
|
];
|
|
18853
19187
|
function actuator(input) {
|
|
18854
19188
|
return {
|
|
18855
|
-
|
|
19189
|
+
id: input.id,
|
|
19190
|
+
summary: input.summary,
|
|
19191
|
+
deviceType: input.deviceType,
|
|
19192
|
+
outputCap: input.outputCap,
|
|
19193
|
+
outputField: input.outputField,
|
|
19194
|
+
commandCaps: input.commandCaps,
|
|
18856
19195
|
family: "actuator",
|
|
18857
19196
|
role: void 0,
|
|
18858
19197
|
memberDeviceType: input.deviceType,
|
|
18859
|
-
|
|
19198
|
+
memberDeviceTypes: input.memberDeviceTypes ?? [input.deviceType],
|
|
19199
|
+
activeWhen: input.activeWhen,
|
|
18860
19200
|
quantity: "none",
|
|
18861
19201
|
baseUnit: void 0,
|
|
18862
19202
|
aggregates: BINARY_AGGREGATES,
|
|
18863
19203
|
defaultAggregate: "any",
|
|
18864
19204
|
empty: "offline",
|
|
18865
|
-
accept: [
|
|
18866
|
-
cap: "switch",
|
|
18867
|
-
fieldPath: "on"
|
|
18868
|
-
}],
|
|
19205
|
+
accept: [input.member],
|
|
18869
19206
|
companions: [CHANGED]
|
|
18870
19207
|
};
|
|
18871
19208
|
}
|
|
18872
19209
|
new Map(GROUP_TEMPLATES.map((template) => [template.id, template]));
|
|
18873
19210
|
DeviceFeature.LightColorRgb, DeviceFeature.LightColorHsv, DeviceFeature.LightColorMired;
|
|
19211
|
+
DeviceType.Camera;
|
|
18874
19212
|
`${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
|
|
18875
19213
|
/**
|
|
18876
19214
|
* What a composition may BUILD on a device type (G2, D676): the caps a new
|
|
@@ -43885,7 +44223,7 @@ var NetworkAccessStatusSchema = object({
|
|
|
43885
44223
|
});
|
|
43886
44224
|
/**
|
|
43887
44225
|
* Optional, richer endpoint shape returned by providers that expose
|
|
43888
|
-
* MORE than one ingress concurrently (Tailscale
|
|
44226
|
+
* MORE than one ingress concurrently (Tailscale Funnel with mixed
|
|
43889
44227
|
* serve+funnel rules, future ngrok multi-tunnel, …). Each entry carries
|
|
43890
44228
|
* the originating provider config (mode + sourcePort) so the
|
|
43891
44229
|
* orchestrator UI can label rows distinctly. Providers that expose only
|
|
@@ -46528,7 +46866,20 @@ var NcRuleInputSchema = object({
|
|
|
46528
46866
|
* save by the hub's grouping guard). `.optional()`, never `.default()`: the addon cap
|
|
46529
46867
|
* path does not run Zod defaults.
|
|
46530
46868
|
*/
|
|
46531
|
-
groupingSec: number().int().min(5).max(60).optional()
|
|
46869
|
+
groupingSec: number().int().min(5).max(60).optional(),
|
|
46870
|
+
/**
|
|
46871
|
+
* ASK ME TO CONFIRM DETECTIONS (#243): a DETECTION notification of this rule
|
|
46872
|
+
* carries "Correct" / "Wrong" buttons (and, where the channel has room, a
|
|
46873
|
+
* "Wrong, it is a <class>" choice). A tap marks the track for retraining, the
|
|
46874
|
+
* same mark the Library writes, and records whose notification it was and
|
|
46875
|
+
* when. A channel with no buttons gets the same two choices as links.
|
|
46876
|
+
*
|
|
46877
|
+
* `.optional()`, never `.default()` (a Zod default does not run on the addon
|
|
46878
|
+
* cap path): absent and `false` both mean off, which is what every rule
|
|
46879
|
+
* authored before this field meant. An editor turns it off by writing
|
|
46880
|
+
* `false`, so it needs no `clear` key.
|
|
46881
|
+
*/
|
|
46882
|
+
askVerdict: boolean().optional()
|
|
46532
46883
|
});
|
|
46533
46884
|
/**
|
|
46534
46885
|
* Partial patch for `updateRule` — any subset of the input fields, plus the
|
|
@@ -56998,7 +57349,7 @@ var BatteryStatusSchema = object({
|
|
|
56998
57349
|
*/
|
|
56999
57350
|
binary: boolean().optional().meta({ label: "Binary indicator" })
|
|
57000
57351
|
});
|
|
57001
|
-
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat;
|
|
57352
|
+
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.EventEmitter;
|
|
57002
57353
|
method(object({
|
|
57003
57354
|
deviceId: number(),
|
|
57004
57355
|
/** Bound on the wait. Sensible range 3000–10000ms. */
|
|
@@ -58752,7 +59103,13 @@ results: array(object({
|
|
|
58752
59103
|
/** Ms epoch of the attempt. */
|
|
58753
59104
|
at: number()
|
|
58754
59105
|
})) });
|
|
58755
|
-
DeviceType.Switch, DeviceType.Light;
|
|
59106
|
+
DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Cover, DeviceType.Valve, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.Thermostat, DeviceType.Climate;
|
|
59107
|
+
object({
|
|
59108
|
+
active: boolean().meta({ label: "Active" }),
|
|
59109
|
+
/** Ms epoch when the slice was last updated. */
|
|
59110
|
+
lastChangedAt: number()
|
|
59111
|
+
});
|
|
59112
|
+
DeviceType.Cover, DeviceType.Valve, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.Climate, DeviceType.Thermostat;
|
|
58756
59113
|
object({
|
|
58757
59114
|
/** Members whose current value entered the aggregate. */
|
|
58758
59115
|
included: number().int().nonnegative().meta(readingMeta("count", {
|
|
@@ -58770,7 +59127,7 @@ object({
|
|
|
58770
59127
|
label: "Members"
|
|
58771
59128
|
}))
|
|
58772
59129
|
});
|
|
58773
|
-
DeviceType.Sensor, DeviceType.Switch, DeviceType.Light;
|
|
59130
|
+
DeviceType.Sensor, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Cover, DeviceType.Valve, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.Thermostat, DeviceType.Climate;
|
|
58774
59131
|
object({
|
|
58775
59132
|
/** Radiator valve opening 0 (closed) .. 100 (open). Null = not yet known. */
|
|
58776
59133
|
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
@@ -59677,7 +60034,14 @@ DeviceType.Lock, method(object({
|
|
|
59677
60034
|
auth: "protected"
|
|
59678
60035
|
}), method(object({
|
|
59679
60036
|
deviceId: number().int().nonnegative(),
|
|
59680
|
-
code: string().min(1).optional()
|
|
60037
|
+
code: string().min(1).optional(),
|
|
60038
|
+
/**
|
|
60039
|
+
* Honoured by a helper lock GROUP only (D944): unlocking several doors
|
|
60040
|
+
* with one call is refused unless the caller says it was confirmed. A
|
|
60041
|
+
* single lock ignores it. The refusal lives in the callee, so no
|
|
60042
|
+
* automation or API caller reaches the doors by skipping a dialog.
|
|
60043
|
+
*/
|
|
60044
|
+
confirm: boolean().optional()
|
|
59681
60045
|
}), _void(), {
|
|
59682
60046
|
kind: "mutation",
|
|
59683
60047
|
auth: "protected"
|
|
@@ -59685,6 +60049,11 @@ DeviceType.Lock, method(object({
|
|
|
59685
60049
|
kind: "mutation",
|
|
59686
60050
|
auth: "protected"
|
|
59687
60051
|
});
|
|
60052
|
+
object({
|
|
60053
|
+
value: number().nullable().meta(readingMeta("device", { label: "Total" })),
|
|
60054
|
+
lastFetchedAt: number()
|
|
60055
|
+
});
|
|
60056
|
+
DeviceType.Sensor;
|
|
59688
60057
|
/**
|
|
59689
60058
|
* Media-player cap. Models HA `media_player.*` (Sonos, Chromecast,
|
|
59690
60059
|
* Apple TV, Spotify, Roku, generic OTT receivers, …) on
|
|
@@ -61592,9 +61961,9 @@ object({
|
|
|
61592
61961
|
/** Cumulative energy in kilowatt-hours since the meter was reset. */
|
|
61593
61962
|
kwhTotal: number().optional().meta(readingMeta("energy", { label: "Energy" })),
|
|
61594
61963
|
/** Voltage in volts. */
|
|
61595
|
-
volts: number().optional().meta(readingMeta("voltage")),
|
|
61964
|
+
volts: number().optional().meta(readingMeta("voltage", { label: "Voltage" })),
|
|
61596
61965
|
/** Current in amperes. */
|
|
61597
|
-
amps: number().optional().meta(readingMeta("current")),
|
|
61966
|
+
amps: number().optional().meta(readingMeta("current", { label: "Current" })),
|
|
61598
61967
|
/** Apparent power in volt-amperes. */
|
|
61599
61968
|
va: number().optional().meta(readingMeta("apparent-power")),
|
|
61600
61969
|
/** Power factor (0..1) if reported. */
|
|
@@ -61602,7 +61971,23 @@ object({
|
|
|
61602
61971
|
/** Ms epoch when the slice was last updated. */
|
|
61603
61972
|
lastFetchedAt: number()
|
|
61604
61973
|
});
|
|
61605
|
-
|
|
61974
|
+
[
|
|
61975
|
+
DeviceType.Sensor,
|
|
61976
|
+
DeviceType.Switch,
|
|
61977
|
+
DeviceType.Light,
|
|
61978
|
+
DeviceType.Fan,
|
|
61979
|
+
DeviceType.Climate,
|
|
61980
|
+
DeviceType.Thermostat,
|
|
61981
|
+
DeviceType.Humidifier,
|
|
61982
|
+
DeviceType.WaterHeater,
|
|
61983
|
+
DeviceType.MediaPlayer,
|
|
61984
|
+
DeviceType.Washer,
|
|
61985
|
+
DeviceType.Dryer,
|
|
61986
|
+
DeviceType.Dishwasher,
|
|
61987
|
+
DeviceType.Vacuum,
|
|
61988
|
+
DeviceType.LawnMower,
|
|
61989
|
+
DeviceType.PetFeeder
|
|
61990
|
+
].filter((type) => type !== DeviceType.Sensor);
|
|
61606
61991
|
/**
|
|
61607
61992
|
* Presence cap. Models HA `person.*` and `device_tracker.*` entities
|
|
61608
61993
|
* on `DeviceType.Presence`. Read-only — no setters: presence is
|
|
@@ -62049,7 +62434,7 @@ object({
|
|
|
62049
62434
|
phase: string().nullable()
|
|
62050
62435
|
});
|
|
62051
62436
|
Object.values(DeviceType);
|
|
62052
|
-
DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
|
|
62437
|
+
DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
|
|
62053
62438
|
DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch, method(object({ deviceId: number().int().nonnegative() }), object({ success: literal(true) }), {
|
|
62054
62439
|
kind: "mutation",
|
|
62055
62440
|
auth: "admin"
|
|
@@ -64088,7 +64473,7 @@ object({
|
|
|
64088
64473
|
/** Ms epoch of the last state change. Useful for UI "X minutes ago". */
|
|
64089
64474
|
lastChangedAt: number()
|
|
64090
64475
|
});
|
|
64091
|
-
DeviceType.Switch, DeviceType.Siren, DeviceType.Light, method(object({
|
|
64476
|
+
DeviceType.Switch, DeviceType.Siren, DeviceType.Light, DeviceType.Fan, method(object({
|
|
64092
64477
|
deviceId: number(),
|
|
64093
64478
|
on: boolean()
|
|
64094
64479
|
}), _void(), {
|
|
@@ -65780,8 +66165,9 @@ method(object({}), array(TrainingBaseModelSchema).readonly(), { auth: "admin" })
|
|
|
65780
66165
|
kind: "mutation",
|
|
65781
66166
|
auth: "admin"
|
|
65782
66167
|
});
|
|
66168
|
+
DeviceFeature.FanSpeed, DeviceFeature.FanPreset, DeviceFeature.FanDirection, DeviceFeature.FanOscillating, DeviceFeature.CoverPositionable, DeviceFeature.CoverTilt, DeviceFeature.ValvePositionable, DeviceFeature.MediaPlayerVolume, DeviceFeature.ClimateFanMode;
|
|
65783
66169
|
SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
|
|
65784
|
-
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;
|
|
66170
|
+
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;
|
|
65785
66171
|
String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
|
|
65786
66172
|
DeviceRole.BinarySensor, DeviceRole.MotionSensor;
|
|
65787
66173
|
new Set(CAP_NAMES);
|
|
@@ -65834,7 +66220,7 @@ var AccessoryKind = {
|
|
|
65834
66220
|
PrivacyMask: DeviceRole.PrivacyMask
|
|
65835
66221
|
};
|
|
65836
66222
|
AccessoryKind.Siren, AccessoryKind.Floodlight, AccessoryKind.Spotlight, AccessoryKind.PirSensor, AccessoryKind.Chime, AccessoryKind.Autotrack, AccessoryKind.Nightvision, AccessoryKind.PrivacyMask;
|
|
65837
|
-
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;
|
|
66223
|
+
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;
|
|
65838
66224
|
new Set(Object.values(DeviceType));
|
|
65839
66225
|
Object.freeze({
|
|
65840
66226
|
"accessories.getStatus": {
|
|
@@ -69057,6 +69443,13 @@ Object.freeze({
|
|
|
69057
69443
|
access: "view",
|
|
69058
69444
|
role: "viewer"
|
|
69059
69445
|
},
|
|
69446
|
+
"groupActive.getStatus": {
|
|
69447
|
+
capName: "group-active",
|
|
69448
|
+
capScope: "device",
|
|
69449
|
+
addonId: null,
|
|
69450
|
+
access: "view",
|
|
69451
|
+
role: "viewer"
|
|
69452
|
+
},
|
|
69060
69453
|
"groupCommands.getStatus": {
|
|
69061
69454
|
capName: "group-commands",
|
|
69062
69455
|
capScope: "device",
|
|
@@ -70023,6 +70416,13 @@ Object.freeze({
|
|
|
70023
70416
|
access: "create",
|
|
70024
70417
|
role: "admin"
|
|
70025
70418
|
},
|
|
70419
|
+
"meter.getStatus": {
|
|
70420
|
+
capName: "meter",
|
|
70421
|
+
capScope: "device",
|
|
70422
|
+
addonId: null,
|
|
70423
|
+
access: "view",
|
|
70424
|
+
role: "viewer"
|
|
70425
|
+
},
|
|
70026
70426
|
"metricsProvider.collectSnapshot": {
|
|
70027
70427
|
capName: "metrics-provider",
|
|
70028
70428
|
capScope: "system",
|
|
@@ -78121,7 +78521,39 @@ var APPLIANCE_CAP_VOCABULARY = {
|
|
|
78121
78521
|
phrase: t("When {device} finishes", "Quando {device} finisce"),
|
|
78122
78522
|
icon: "square"
|
|
78123
78523
|
}
|
|
78124
|
-
}
|
|
78524
|
+
},
|
|
78525
|
+
overrides: { byType: {
|
|
78526
|
+
[DeviceType.Washer]: {
|
|
78527
|
+
state: { running: {
|
|
78528
|
+
whenTrue: t("When the washing machine starts", "Quando la lavatrice inizia"),
|
|
78529
|
+
whenFalse: t("When the washing machine has finished", "Quando la lavatrice ha finito")
|
|
78530
|
+
} },
|
|
78531
|
+
events: {
|
|
78532
|
+
onStarted: { phrase: t("When the washing machine starts", "Quando la lavatrice inizia") },
|
|
78533
|
+
onFinished: { phrase: t("When the washing machine has finished", "Quando la lavatrice ha finito") }
|
|
78534
|
+
}
|
|
78535
|
+
},
|
|
78536
|
+
[DeviceType.Dryer]: {
|
|
78537
|
+
state: { running: {
|
|
78538
|
+
whenTrue: t("When the dryer starts", "Quando l'asciugatrice inizia"),
|
|
78539
|
+
whenFalse: t("When the dryer has finished", "Quando l'asciugatrice ha finito")
|
|
78540
|
+
} },
|
|
78541
|
+
events: {
|
|
78542
|
+
onStarted: { phrase: t("When the dryer starts", "Quando l'asciugatrice inizia") },
|
|
78543
|
+
onFinished: { phrase: t("When the dryer has finished", "Quando l'asciugatrice ha finito") }
|
|
78544
|
+
}
|
|
78545
|
+
},
|
|
78546
|
+
[DeviceType.Dishwasher]: {
|
|
78547
|
+
state: { running: {
|
|
78548
|
+
whenTrue: t("When the dishwasher starts", "Quando la lavastoviglie inizia"),
|
|
78549
|
+
whenFalse: t("When the dishwasher has finished", "Quando la lavastoviglie ha finito")
|
|
78550
|
+
} },
|
|
78551
|
+
events: {
|
|
78552
|
+
onStarted: { phrase: t("When the dishwasher starts", "Quando la lavastoviglie inizia") },
|
|
78553
|
+
onFinished: { phrase: t("When the dishwasher has finished", "Quando la lavastoviglie ha finito") }
|
|
78554
|
+
}
|
|
78555
|
+
}
|
|
78556
|
+
} }
|
|
78125
78557
|
},
|
|
78126
78558
|
update: {
|
|
78127
78559
|
scope: "device",
|
|
@@ -78893,6 +79325,10 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78893
79325
|
icon: "flame"
|
|
78894
79326
|
}]
|
|
78895
79327
|
},
|
|
79328
|
+
"group-active": {
|
|
79329
|
+
scope: "device",
|
|
79330
|
+
noun: t("Group state", "Stato del gruppo")
|
|
79331
|
+
},
|
|
78896
79332
|
"group-commands": {
|
|
78897
79333
|
scope: "device",
|
|
78898
79334
|
noun: t("Group command", "Comando di gruppo")
|
|
@@ -78949,6 +79385,17 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
78949
79385
|
}],
|
|
78950
79386
|
events: { onMotionChanged: { notOperatorFacing: "the `detected` state trigger phrases both edges, from the mirror that survives a dropped event (D49)" } }
|
|
78951
79387
|
},
|
|
79388
|
+
meter: {
|
|
79389
|
+
scope: "device",
|
|
79390
|
+
noun: t("Meter", "Contatore"),
|
|
79391
|
+
state: [{
|
|
79392
|
+
kind: "numeric",
|
|
79393
|
+
field: "value",
|
|
79394
|
+
quantity: t("the total", "il totale"),
|
|
79395
|
+
label: t("Total", "Totale"),
|
|
79396
|
+
icon: "gauge"
|
|
79397
|
+
}]
|
|
79398
|
+
},
|
|
78952
79399
|
"numeric-sensor": {
|
|
78953
79400
|
scope: "device",
|
|
78954
79401
|
noun: t("Sensor", "Sensore"),
|
|
@@ -79421,8 +79868,47 @@ function projectAction(cap, action) {
|
|
|
79421
79868
|
};
|
|
79422
79869
|
}
|
|
79423
79870
|
Object.entries(CAP_VOCABULARY_BY_NAME).flatMap(([cap, entry]) => entry.scope === "device" ? (entry.actions ?? []).map((a) => projectAction(cap, a)) : []);
|
|
79424
|
-
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;
|
|
79871
|
+
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;
|
|
79425
79872
|
DeviceFeature.BatteryOperated;
|
|
79873
|
+
DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher;
|
|
79874
|
+
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.";
|
|
79875
|
+
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.";
|
|
79876
|
+
var ALEXA_REASON = "Alexa has no laundry category in this export, and neither power nor running has an Alexa interface.";
|
|
79877
|
+
var GOOGLE_REASON = "Google WASHER, DRYER and DISHWASHER require RunCycle. A power threshold is not that trait, and this export does not publish RunCycle.";
|
|
79878
|
+
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.";
|
|
79879
|
+
function withheld(reason) {
|
|
79880
|
+
return {
|
|
79881
|
+
[DeviceType.Washer]: {
|
|
79882
|
+
exported: false,
|
|
79883
|
+
reason
|
|
79884
|
+
},
|
|
79885
|
+
[DeviceType.Dryer]: {
|
|
79886
|
+
exported: false,
|
|
79887
|
+
reason
|
|
79888
|
+
},
|
|
79889
|
+
[DeviceType.Dishwasher]: {
|
|
79890
|
+
exported: false,
|
|
79891
|
+
reason
|
|
79892
|
+
}
|
|
79893
|
+
};
|
|
79894
|
+
}
|
|
79895
|
+
function offered(received) {
|
|
79896
|
+
return {
|
|
79897
|
+
[DeviceType.Washer]: {
|
|
79898
|
+
exported: true,
|
|
79899
|
+
as: received
|
|
79900
|
+
},
|
|
79901
|
+
[DeviceType.Dryer]: {
|
|
79902
|
+
exported: true,
|
|
79903
|
+
as: received
|
|
79904
|
+
},
|
|
79905
|
+
[DeviceType.Dishwasher]: {
|
|
79906
|
+
exported: true,
|
|
79907
|
+
as: received
|
|
79908
|
+
}
|
|
79909
|
+
};
|
|
79910
|
+
}
|
|
79911
|
+
offered(HA_AS), withheld(HOMEKIT_REASON), withheld(ALEXA_REASON), withheld(GOOGLE_REASON), withheld(MATTER_REASON);
|
|
79426
79912
|
Object.freeze({
|
|
79427
79913
|
"accessories.getStatus": [{
|
|
79428
79914
|
name: "deviceId",
|
|
@@ -80389,6 +80875,11 @@ Object.freeze({
|
|
|
80389
80875
|
form: "single",
|
|
80390
80876
|
optional: false
|
|
80391
80877
|
}],
|
|
80878
|
+
"groupActive.getStatus": [{
|
|
80879
|
+
name: "deviceId",
|
|
80880
|
+
form: "single",
|
|
80881
|
+
optional: false
|
|
80882
|
+
}],
|
|
80392
80883
|
"groupCommands.getStatus": [{
|
|
80393
80884
|
name: "deviceId",
|
|
80394
80885
|
form: "single",
|
|
@@ -80599,6 +81090,11 @@ Object.freeze({
|
|
|
80599
81090
|
form: "single",
|
|
80600
81091
|
optional: false
|
|
80601
81092
|
}],
|
|
81093
|
+
"meter.getStatus": [{
|
|
81094
|
+
name: "deviceId",
|
|
81095
|
+
form: "single",
|
|
81096
|
+
optional: false
|
|
81097
|
+
}],
|
|
80602
81098
|
"motion.getStatus": [{
|
|
80603
81099
|
name: "deviceId",
|
|
80604
81100
|
form: "single",
|
|
@@ -82206,7 +82702,6 @@ Object.freeze({
|
|
|
82206
82702
|
"network-access": "ingress",
|
|
82207
82703
|
"smtp-provider": "email"
|
|
82208
82704
|
});
|
|
82209
|
-
DeviceType.Camera;
|
|
82210
82705
|
/**
|
|
82211
82706
|
* A saved Customize assignment (D936). The schema is the type: callers use
|
|
82212
82707
|
* `z.infer`, they do not restate the shape.
|
|
@@ -84537,7 +85032,7 @@ function pickOauthRedirectOrigin(book) {
|
|
|
84537
85032
|
return book.roles.publicEndpoint.resolved ?? book.roles.internal.resolved ?? null;
|
|
84538
85033
|
}
|
|
84539
85034
|
var googleBrokersEntryKind = defineEntryKind("brokers", {
|
|
84540
|
-
title: "Google
|
|
85035
|
+
title: "Google brokers",
|
|
84541
85036
|
schema: entryBody({
|
|
84542
85037
|
clientId: GoogleBrokerEntrySchema.shape.clientId,
|
|
84543
85038
|
clientSecret: GoogleBrokerEntrySchema.shape.clientSecret,
|
|
@@ -84606,7 +85101,7 @@ var GoogleBrokerStore = class GoogleBrokerStore {
|
|
|
84606
85101
|
//#endregion
|
|
84607
85102
|
//#region src/google-services.addon.ts
|
|
84608
85103
|
/**
|
|
84609
|
-
* Google
|
|
85104
|
+
* Google — hub-only broker kind `google` + calendar-source + Gmail smtp.
|
|
84610
85105
|
* One OAuth account = one broker entry; feature caps aggregate connected brokers.
|
|
84611
85106
|
*/
|
|
84612
85107
|
var ADDON_ID = "google-services";
|