@camstack/addon-provider-homeassistant 1.2.630 → 1.2.631

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/dist/addon.js CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_dist = require("./dist-Dcmr-Isu.js");
2
+ const require_dist = require("./dist-DV8KQcWd.js");
3
3
  let node_crypto = require("node:crypto");
4
4
  let node_zlib = require("node:zlib");
5
5
  //#region src/ha-admin-link.ts
package/dist/addon.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as lawnMowerControlCapability, $t as union, A as buttonCapability, At as weatherCapability, B as coverCapability, Bt as defineRecordKinds, C as batteryCapability, Ct as tryConvertDelta, D as brokerCapability, Dt as valveCapability, E as brightnessCapability, Et as vacuumControlCapability, F as connectivityCapability, G as eventEmitterCapability, Gt as array, H as deviceAdoptionCapability, It as RecordSecretUnavailableError, J as gasCapability, Jt as literal, K as fanControlCapability, Kt as boolean, Lt as baseUnitOf, M as carbonMonoxideCapability, Mt as DeviceRole, N as climateControlCapability, Nt as DeviceType, O as buildAddonRouteProvider, Ot as vibrationCapability, P as colorCapability, Pt as errMsg, Q as ingestReading, Qt as string, R as contactCapability, Rt as createEvent, S as automationControlCapability, St as temperatureSensorCapability, T as binaryCapability, Tt as updateCapability, V as deviceAdminLinkCapability, Vt as entryBody, W as enumSensorCapability, Wt as _enum, X as humiditySensorCapability, Xt as object, Y as humidifierCapability, Yt as number, Z as imageCapability, Zt as record, _ as accessoriesCapability, _t as runningStateCapability, at as notifierCapability, b as alarmPanelCapability, bt as switchCapability, ct as parseAdminBase, dt as presenceCapability, en as unknown, et as lockControlCapability, ft as pressureSensorCapability, g as TargetSchema, gt as runningFromVacuumState, h as RUNNING_STATE_COLD, ht as runningFromMediaPlayer, it as notificationOutputCapability, j as calendarSourceCapability, jt as DeviceFeature, k as buildDeviceAdminUrl, kt as waterHeaterCapability, lt as powerMeterCapability, mt as runningFromLawnMower, n as BaseDevice, nn as EventCategory, nt as motionCapability, ot as numericSensorCapability, pt as quantityFromUnit, q as floodCapability, qt as discriminatedUnion, r as BaseDeviceProvider, rt as normalizeUnit, tn as url, tt as mediaPlayerCapability, u as EnumSensorDateTimeFormatSchema, ut as prepareNotification, v as addonRoutesCapability, vt as scriptRunnerCapability, w as bestLocationMatch, wt as tryConvertUnit, x as ambientLightSensorCapability, xt as tamperCapability, y as airQualitySensorCapability, yt as smokeCapability, z as controlCapability, zt as defineEntryKind } from "./dist-CT3sP-p0.mjs";
1
+ import { $ as lawnMowerControlCapability, $t as union, A as buttonCapability, At as weatherCapability, B as coverCapability, Bt as defineRecordKinds, C as batteryCapability, Ct as tryConvertDelta, D as brokerCapability, Dt as valveCapability, E as brightnessCapability, Et as vacuumControlCapability, F as connectivityCapability, G as eventEmitterCapability, Gt as array, H as deviceAdoptionCapability, It as RecordSecretUnavailableError, J as gasCapability, Jt as literal, K as fanControlCapability, Kt as boolean, Lt as baseUnitOf, M as carbonMonoxideCapability, Mt as DeviceRole, N as climateControlCapability, Nt as DeviceType, O as buildAddonRouteProvider, Ot as vibrationCapability, P as colorCapability, Pt as errMsg, Q as ingestReading, Qt as string, R as contactCapability, Rt as createEvent, S as automationControlCapability, St as temperatureSensorCapability, T as binaryCapability, Tt as updateCapability, V as deviceAdminLinkCapability, Vt as entryBody, W as enumSensorCapability, Wt as _enum, X as humiditySensorCapability, Xt as object, Y as humidifierCapability, Yt as number, Z as imageCapability, Zt as record, _ as accessoriesCapability, _t as runningStateCapability, at as notifierCapability, b as alarmPanelCapability, bt as switchCapability, ct as parseAdminBase, dt as presenceCapability, en as unknown, et as lockControlCapability, ft as pressureSensorCapability, g as TargetSchema, gt as runningFromVacuumState, h as RUNNING_STATE_COLD, ht as runningFromMediaPlayer, it as notificationOutputCapability, j as calendarSourceCapability, jt as DeviceFeature, k as buildDeviceAdminUrl, kt as waterHeaterCapability, lt as powerMeterCapability, mt as runningFromLawnMower, n as BaseDevice, nn as EventCategory, nt as motionCapability, ot as numericSensorCapability, pt as quantityFromUnit, q as floodCapability, qt as discriminatedUnion, r as BaseDeviceProvider, rt as normalizeUnit, tn as url, tt as mediaPlayerCapability, u as EnumSensorDateTimeFormatSchema, ut as prepareNotification, v as addonRoutesCapability, vt as scriptRunnerCapability, w as bestLocationMatch, wt as tryConvertUnit, x as ambientLightSensorCapability, xt as tamperCapability, y as airQualitySensorCapability, yt as smokeCapability, z as controlCapability, zt as defineEntryKind } from "./dist-CdqN_VJZ.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import { brotliCompressSync, deflateSync, gzipSync } from "node:zlib";
4
4
  //#region src/ha-admin-link.ts
@@ -5574,7 +5574,7 @@ var ZodIssueCode = {
5574
5574
  var ZodFirstPartyTypeKind;
5575
5575
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5576
5576
  //#endregion
5577
- //#region ../types/dist/sleep-0sD_LHLI.mjs
5577
+ //#region ../types/dist/sleep--jXS9hWo.mjs
5578
5578
  /**
5579
5579
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5580
5580
  * window to float samples (D455).
@@ -9017,6 +9017,7 @@ var CAP_NAMES = Object.freeze([
9017
9017
  "filesystem-browse",
9018
9018
  "flood",
9019
9019
  "gas",
9020
+ "group-active",
9020
9021
  "group-commands",
9021
9022
  "group-status",
9022
9023
  "heating-valve",
@@ -9838,6 +9839,10 @@ Object.freeze({
9838
9839
  "path": "detected",
9839
9840
  "valueType": "boolean"
9840
9841
  }],
9842
+ "group-active": [{
9843
+ "path": "active",
9844
+ "valueType": "boolean"
9845
+ }],
9841
9846
  "group-status": [
9842
9847
  {
9843
9848
  "path": "included",
@@ -11203,7 +11208,7 @@ function errMsg(err) {
11203
11208
  return String(err);
11204
11209
  }
11205
11210
  //#endregion
11206
- //#region ../types/dist/composition-CpETZ4HL.mjs
11211
+ //#region ../types/dist/composition-Bb8iwHEJ.mjs
11207
11212
  /**
11208
11213
  * The ffmpeg build every CamStack node downloads, per platform and arch.
11209
11214
  *
@@ -11518,6 +11523,13 @@ var table = {
11518
11523
  apply: () => {
11519
11524
  throw new ExpressionEvalError("latchedAt: stateful evaluation context is required");
11520
11525
  }
11526
+ },
11527
+ schmitt: {
11528
+ minArgs: 3,
11529
+ maxArgs: 5,
11530
+ apply: () => {
11531
+ throw new ExpressionEvalError("schmitt: stateful evaluation context is required");
11532
+ }
11521
11533
  }
11522
11534
  };
11523
11535
  Object.freeze(Object.assign(Object.create(null), table));
@@ -12028,7 +12040,7 @@ var RESET_PERIODS = [
12028
12040
  5 * MINUTE_MS;
12029
12041
  24 * HOUR_MS, 2 * DAY_MS, 7 * DAY_MS, 30 * DAY_MS;
12030
12042
  7 * DAY_MS, 30 * DAY_MS, 365 * DAY_MS;
12031
- var StatisticWindowSchema = discriminatedUnion("kind", [object({
12043
+ var rollingWindowObject = object({
12032
12044
  kind: literal("rolling"),
12033
12045
  span: _enum(ROLLING_SPANS),
12034
12046
  customMinutes: number().int().min(5).optional()
@@ -12045,7 +12057,9 @@ var StatisticWindowSchema = discriminatedUnion("kind", [object({
12045
12057
  path: ["customMinutes"],
12046
12058
  input: payload.value
12047
12059
  });
12048
- }), object({
12060
+ });
12061
+ var RollingWindowSchema = rollingWindowObject;
12062
+ var StatisticWindowSchema = discriminatedUnion("kind", [rollingWindowObject, object({
12049
12063
  kind: literal("calendar"),
12050
12064
  period: _enum(CALENDAR_PERIODS)
12051
12065
  })]);
@@ -12075,7 +12089,13 @@ var GROUP_TEMPLATE_IDS = [
12075
12089
  "occupancy",
12076
12090
  "binary",
12077
12091
  "switch",
12078
- "light"
12092
+ "light",
12093
+ "fan",
12094
+ "cover",
12095
+ "valve",
12096
+ "lock",
12097
+ "media-player",
12098
+ "climate"
12079
12099
  ];
12080
12100
  var NUMERIC_AGGREGATES = [
12081
12101
  "mean",
@@ -12134,6 +12154,42 @@ var HelperSpecSchema = discriminatedUnion("kind", [
12134
12154
  reset: _enum(RESET_PERIODS),
12135
12155
  output: _enum(["energy", "meter"]),
12136
12156
  source: HelperMemberSchema
12157
+ }),
12158
+ object({
12159
+ kind: literal("threshold"),
12160
+ source: HelperMemberSchema,
12161
+ high: number(),
12162
+ low: number(),
12163
+ onForMs: number().int().nonnegative(),
12164
+ offForMs: number().int().nonnegative()
12165
+ }),
12166
+ object({
12167
+ kind: literal("arithmetic"),
12168
+ op: _enum([
12169
+ "sum",
12170
+ "difference",
12171
+ "ratio"
12172
+ ]),
12173
+ inputs: array(HelperMemberSchema).min(2).max(64)
12174
+ }),
12175
+ object({
12176
+ kind: literal("expression"),
12177
+ expr: string().min(1),
12178
+ inputs: array(object({
12179
+ name: string().min(1),
12180
+ member: HelperMemberSchema
12181
+ })).min(1).max(64),
12182
+ output: _enum(["number", "boolean"])
12183
+ }),
12184
+ object({
12185
+ kind: literal("derivative"),
12186
+ window: RollingWindowSchema,
12187
+ per: _enum([
12188
+ "second",
12189
+ "minute",
12190
+ "hour"
12191
+ ]),
12192
+ source: HelperMemberSchema
12137
12193
  })
12138
12194
  ]);
12139
12195
  /** A composed device's stableId is this prefix plus the block id. */
@@ -12196,6 +12252,12 @@ var CompositionFieldSourceSchema = discriminatedUnion("kind", [
12196
12252
  "all"
12197
12253
  ]),
12198
12254
  reads: array(CompositionFieldReadSchema).min(1).max(64),
12255
+ /**
12256
+ * Set when the reads are an enum state, not a yes/no: the listed states
12257
+ * count as active (a cover is `open`). A state outside the list is inactive;
12258
+ * a read that is not a state at all is left out. Only `any` / `all` use it.
12259
+ */
12260
+ activeWhen: array(string().min(1)).min(1).optional(),
12199
12261
  /** `value` is the reading; the others are the member counts. */
12200
12262
  publish: _enum([
12201
12263
  "value",
@@ -18940,13 +19002,17 @@ Object.freeze({
18940
19002
  latchedAt: {
18941
19003
  kind: "fixed",
18942
19004
  result: ["number", "null"]
19005
+ },
19006
+ schmitt: {
19007
+ kind: "fixed",
19008
+ result: ["boolean", "null"]
18943
19009
  }
18944
19010
  });
18945
19011
  /**
18946
19012
  * One catalog row per base reading a group helper can build (D944 §3).
18947
19013
  * Data, not a form default written into the block.
18948
19014
  */
18949
- var NOW$1 = {
19015
+ var NOW$2 = {
18950
19016
  fieldPath: "lastFetchedAt",
18951
19017
  expr: "now"
18952
19018
  };
@@ -18960,6 +19026,8 @@ function numeric(input) {
18960
19026
  family: "numeric",
18961
19027
  deviceType: DeviceType.Sensor,
18962
19028
  memberDeviceType: DeviceType.Sensor,
19029
+ memberDeviceTypes: [DeviceType.Sensor],
19030
+ activeWhen: void 0,
18963
19031
  commandCaps: [],
18964
19032
  baseUnit: baseUnitOf(input.quantity),
18965
19033
  aggregates: NUMERIC_AGGREGATES,
@@ -18975,6 +19043,8 @@ function binary(input) {
18975
19043
  family: "binary",
18976
19044
  deviceType: DeviceType.Sensor,
18977
19045
  memberDeviceType: DeviceType.Sensor,
19046
+ memberDeviceTypes: [DeviceType.Sensor],
19047
+ activeWhen: void 0,
18978
19048
  commandCaps: [],
18979
19049
  quantity: "none",
18980
19050
  baseUnit: void 0,
@@ -18992,7 +19062,7 @@ var GROUP_TEMPLATES = [
18992
19062
  quantity: "temperature",
18993
19063
  defaultAggregate: "mean",
18994
19064
  empty: "null",
18995
- companions: [NOW$1]
19065
+ companions: [NOW$2]
18996
19066
  }),
18997
19067
  numeric({
18998
19068
  id: "humidity",
@@ -19003,7 +19073,7 @@ var GROUP_TEMPLATES = [
19003
19073
  quantity: "humidity",
19004
19074
  defaultAggregate: "mean",
19005
19075
  empty: "null",
19006
- companions: [NOW$1]
19076
+ companions: [NOW$2]
19007
19077
  }),
19008
19078
  numeric({
19009
19079
  id: "pressure",
@@ -19014,7 +19084,7 @@ var GROUP_TEMPLATES = [
19014
19084
  quantity: "pressure",
19015
19085
  defaultAggregate: "mean",
19016
19086
  empty: "null",
19017
- companions: [NOW$1]
19087
+ companions: [NOW$2]
19018
19088
  }),
19019
19089
  numeric({
19020
19090
  id: "illuminance",
@@ -19025,7 +19095,7 @@ var GROUP_TEMPLATES = [
19025
19095
  quantity: "illuminance",
19026
19096
  defaultAggregate: "mean",
19027
19097
  empty: "null",
19028
- companions: [NOW$1]
19098
+ companions: [NOW$2]
19029
19099
  }),
19030
19100
  numeric({
19031
19101
  id: "power",
@@ -19036,7 +19106,7 @@ var GROUP_TEMPLATES = [
19036
19106
  quantity: "power",
19037
19107
  defaultAggregate: "sum",
19038
19108
  empty: "omit",
19039
- companions: [NOW$1]
19109
+ companions: [NOW$2]
19040
19110
  }),
19041
19111
  numeric({
19042
19112
  id: "energy",
@@ -19047,7 +19117,7 @@ var GROUP_TEMPLATES = [
19047
19117
  quantity: "energy",
19048
19118
  defaultAggregate: "sum",
19049
19119
  empty: "omit",
19050
- companions: [NOW$1]
19120
+ companions: [NOW$2]
19051
19121
  }),
19052
19122
  numeric({
19053
19123
  id: "battery",
@@ -19082,7 +19152,7 @@ var GROUP_TEMPLATES = [
19082
19152
  quantity: "device",
19083
19153
  defaultAggregate: "mean",
19084
19154
  empty: "null",
19085
- companions: [NOW$1]
19155
+ companions: [NOW$2]
19086
19156
  }),
19087
19157
  binary({
19088
19158
  id: "motion",
@@ -19176,6 +19246,11 @@ var GROUP_TEMPLATES = [
19176
19246
  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.",
19177
19247
  deviceType: DeviceType.Switch,
19178
19248
  outputCap: "switch",
19249
+ outputField: "on",
19250
+ member: {
19251
+ cap: "switch",
19252
+ fieldPath: "on"
19253
+ },
19179
19254
  commandCaps: ["switch"]
19180
19255
  }),
19181
19256
  actuator({
@@ -19183,29 +19258,130 @@ var GROUP_TEMPLATES = [
19183
19258
  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.",
19184
19259
  deviceType: DeviceType.Light,
19185
19260
  outputCap: "switch",
19261
+ outputField: "on",
19262
+ member: {
19263
+ cap: "switch",
19264
+ fieldPath: "on"
19265
+ },
19186
19266
  commandCaps: [
19187
19267
  "switch",
19188
19268
  "brightness",
19189
19269
  "color"
19190
19270
  ]
19271
+ }),
19272
+ actuator({
19273
+ id: "fan",
19274
+ 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.",
19275
+ deviceType: DeviceType.Fan,
19276
+ outputCap: "switch",
19277
+ outputField: "on",
19278
+ member: {
19279
+ cap: "switch",
19280
+ fieldPath: "on"
19281
+ },
19282
+ commandCaps: ["switch", "fan-control"]
19283
+ }),
19284
+ actuator({
19285
+ id: "cover",
19286
+ 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.",
19287
+ deviceType: DeviceType.Cover,
19288
+ outputCap: "group-active",
19289
+ outputField: "active",
19290
+ member: {
19291
+ cap: "cover",
19292
+ fieldPath: "state"
19293
+ },
19294
+ activeWhen: [
19295
+ "open",
19296
+ "opening",
19297
+ "stopped"
19298
+ ],
19299
+ commandCaps: ["cover"]
19300
+ }),
19301
+ actuator({
19302
+ id: "valve",
19303
+ 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.",
19304
+ deviceType: DeviceType.Valve,
19305
+ outputCap: "group-active",
19306
+ outputField: "active",
19307
+ member: {
19308
+ cap: "valve",
19309
+ fieldPath: "state"
19310
+ },
19311
+ activeWhen: [
19312
+ "open",
19313
+ "opening",
19314
+ "stopped"
19315
+ ],
19316
+ commandCaps: ["valve"]
19317
+ }),
19318
+ actuator({
19319
+ id: "lock",
19320
+ 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.",
19321
+ deviceType: DeviceType.Lock,
19322
+ outputCap: "group-active",
19323
+ outputField: "active",
19324
+ member: {
19325
+ cap: "lock-control",
19326
+ fieldPath: "state"
19327
+ },
19328
+ activeWhen: ["locked"],
19329
+ commandCaps: ["lock-control"]
19330
+ }),
19331
+ actuator({
19332
+ id: "media-player",
19333
+ 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.",
19334
+ deviceType: DeviceType.MediaPlayer,
19335
+ outputCap: "group-active",
19336
+ outputField: "active",
19337
+ member: {
19338
+ cap: "media-player",
19339
+ fieldPath: "state"
19340
+ },
19341
+ activeWhen: ["playing", "buffering"],
19342
+ commandCaps: ["media-player"]
19343
+ }),
19344
+ actuator({
19345
+ id: "climate",
19346
+ 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.",
19347
+ deviceType: DeviceType.Thermostat,
19348
+ memberDeviceTypes: [DeviceType.Thermostat, DeviceType.Climate],
19349
+ outputCap: "group-active",
19350
+ outputField: "active",
19351
+ member: {
19352
+ cap: "climate-control",
19353
+ fieldPath: "mode"
19354
+ },
19355
+ activeWhen: [
19356
+ "heat",
19357
+ "cool",
19358
+ "auto",
19359
+ "heat_cool",
19360
+ "fan_only",
19361
+ "dry"
19362
+ ],
19363
+ commandCaps: ["climate-control"]
19191
19364
  })
19192
19365
  ];
19193
19366
  function actuator(input) {
19194
19367
  return {
19195
- ...input,
19368
+ id: input.id,
19369
+ summary: input.summary,
19370
+ deviceType: input.deviceType,
19371
+ outputCap: input.outputCap,
19372
+ outputField: input.outputField,
19373
+ commandCaps: input.commandCaps,
19196
19374
  family: "actuator",
19197
19375
  role: void 0,
19198
19376
  memberDeviceType: input.deviceType,
19199
- outputField: "on",
19377
+ memberDeviceTypes: input.memberDeviceTypes ?? [input.deviceType],
19378
+ activeWhen: input.activeWhen,
19200
19379
  quantity: "none",
19201
19380
  baseUnit: void 0,
19202
19381
  aggregates: BINARY_AGGREGATES,
19203
19382
  defaultAggregate: "any",
19204
19383
  empty: "offline",
19205
- accept: [{
19206
- cap: "switch",
19207
- fieldPath: "on"
19208
- }],
19384
+ accept: [input.member],
19209
19385
  companions: [CHANGED]
19210
19386
  };
19211
19387
  }
@@ -47390,7 +47566,20 @@ var NcRuleInputSchema = object({
47390
47566
  * save by the hub's grouping guard). `.optional()`, never `.default()`: the addon cap
47391
47567
  * path does not run Zod defaults.
47392
47568
  */
47393
- groupingSec: number().int().min(5).max(60).optional()
47569
+ groupingSec: number().int().min(5).max(60).optional(),
47570
+ /**
47571
+ * ASK ME TO CONFIRM DETECTIONS (#243): a DETECTION notification of this rule
47572
+ * carries "Correct" / "Wrong" buttons (and, where the channel has room, a
47573
+ * "Wrong, it is a <class>" choice). A tap marks the track for retraining, the
47574
+ * same mark the Library writes, and records whose notification it was and
47575
+ * when. A channel with no buttons gets the same two choices as links.
47576
+ *
47577
+ * `.optional()`, never `.default()` (a Zod default does not run on the addon
47578
+ * cap path): absent and `false` both mean off, which is what every rule
47579
+ * authored before this field meant. An editor turns it off by writing
47580
+ * `false`, so it needs no `clear` key.
47581
+ */
47582
+ askVerdict: boolean().optional()
47394
47583
  });
47395
47584
  /**
47396
47585
  * Partial patch for `updateRule` — any subset of the input fields, plus the
@@ -61109,7 +61298,17 @@ var groupCommandsCapability = {
61109
61298
  scope: "device",
61110
61299
  deviceNative: true,
61111
61300
  mode: "singleton",
61112
- deviceTypes: [DeviceType.Switch, DeviceType.Light],
61301
+ deviceTypes: [
61302
+ DeviceType.Switch,
61303
+ DeviceType.Light,
61304
+ DeviceType.Fan,
61305
+ DeviceType.Cover,
61306
+ DeviceType.Valve,
61307
+ DeviceType.Lock,
61308
+ DeviceType.MediaPlayer,
61309
+ DeviceType.Thermostat,
61310
+ DeviceType.Climate
61311
+ ],
61113
61312
  methods: {},
61114
61313
  status: {
61115
61314
  schema: GroupCommandsSchema,
@@ -61127,6 +61326,49 @@ var groupCommandsCapability = {
61127
61326
  history: "none"
61128
61327
  };
61129
61328
  /**
61329
+ * Whether a helper actuator group counts as active (D944): at least one
61330
+ * included member is, or every included member is. What "active" means is the
61331
+ * type's: a cover is open, a lock is locked, a media player is playing, a
61332
+ * climate device is not off. A group of lights, switches and fans reports
61333
+ * `switch.on` instead; this cap is for the types whose own state is not a
61334
+ * yes/no. Unknown members are left out (`group-status` counts them) and an
61335
+ * empty included set takes the device offline, never `active: false`.
61336
+ */
61337
+ var GroupActiveSchema = object({
61338
+ active: boolean().meta({ label: "Active" }),
61339
+ /** Ms epoch when the slice was last updated. */
61340
+ lastChangedAt: number()
61341
+ });
61342
+ var groupActiveCapability = {
61343
+ name: "group-active",
61344
+ scope: "device",
61345
+ deviceNative: true,
61346
+ mode: "singleton",
61347
+ deviceTypes: [
61348
+ DeviceType.Cover,
61349
+ DeviceType.Valve,
61350
+ DeviceType.Lock,
61351
+ DeviceType.MediaPlayer,
61352
+ DeviceType.Climate,
61353
+ DeviceType.Thermostat
61354
+ ],
61355
+ methods: {},
61356
+ status: {
61357
+ schema: GroupActiveSchema,
61358
+ kind: "push"
61359
+ },
61360
+ runtimeState: GroupActiveSchema,
61361
+ /**
61362
+ * Runtime-state durability: **session** — recomputed from the members on the
61363
+ * next source event; a restored value would outlive the members it named.
61364
+ *
61365
+ * See `RuntimeStateDurability`. Enforced by
61366
+ * `scripts/check-runtime-state-durability.ts`.
61367
+ */
61368
+ durability: "session",
61369
+ history: "none"
61370
+ };
61371
+ /**
61130
61372
  * How many members of a helper group answered (D944). Counts are integers,
61131
61373
  * not measurements: zero included is a real count, never a stand-in reading.
61132
61374
  * The reading itself stays on the output capability. History is none — the
@@ -61157,7 +61399,14 @@ var groupStatusCapability = {
61157
61399
  deviceTypes: [
61158
61400
  DeviceType.Sensor,
61159
61401
  DeviceType.Switch,
61160
- DeviceType.Light
61402
+ DeviceType.Light,
61403
+ DeviceType.Fan,
61404
+ DeviceType.Cover,
61405
+ DeviceType.Valve,
61406
+ DeviceType.Lock,
61407
+ DeviceType.MediaPlayer,
61408
+ DeviceType.Thermostat,
61409
+ DeviceType.Climate
61161
61410
  ],
61162
61411
  methods: {},
61163
61412
  status: {
@@ -62430,7 +62679,14 @@ var lockControlCapability = {
62430
62679
  }),
62431
62680
  unlock: method(object({
62432
62681
  deviceId: number().int().nonnegative(),
62433
- code: string().min(1).optional()
62682
+ code: string().min(1).optional(),
62683
+ /**
62684
+ * Honoured by a helper lock GROUP only (D944): unlocking several doors
62685
+ * with one call is refused unless the caller says it was confirmed. A
62686
+ * single lock ignores it. The refusal lives in the callee, so no
62687
+ * automation or API caller reaches the doors by skipping a dialog.
62688
+ */
62689
+ confirm: boolean().optional()
62434
62690
  }), _void(), {
62435
62691
  kind: "mutation",
62436
62692
  auth: "protected"
@@ -68273,7 +68529,8 @@ var switchCapability = {
68273
68529
  deviceTypes: [
68274
68530
  DeviceType.Switch,
68275
68531
  DeviceType.Siren,
68276
- DeviceType.Light
68532
+ DeviceType.Light,
68533
+ DeviceType.Fan
68277
68534
  ],
68278
68535
  methods: { setState: method(object({
68279
68536
  deviceId: number(),
@@ -70523,6 +70780,7 @@ function runningFromMediaPlayer(state, previous, fetchedAt, transitionAt) {
70523
70780
  if (state === "paused") return nativeSlice(false, "paused", previous, transitionAtMs, fetchedAt, null);
70524
70781
  return nativeSlice(false, state, previous, transitionAtMs, fetchedAt, null);
70525
70782
  }
70783
+ DeviceFeature.FanSpeed, DeviceFeature.FanPreset, DeviceFeature.FanDirection, DeviceFeature.FanOscillating, DeviceFeature.CoverPositionable, DeviceFeature.CoverTilt, DeviceFeature.ValvePositionable, DeviceFeature.MediaPlayerVolume, DeviceFeature.ClimateFanMode;
70526
70784
  /**
70527
70785
  * Frozen unit → spec table. `•` in the doc marks each dimension's canonical
70528
70786
  * unit (`factor: 1, offset: 0`). °F derives from `°C = (°F − 32) × 5/9` ⇒
@@ -71251,6 +71509,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
71251
71509
  featureProbe: featureProbeCapability,
71252
71510
  flood: floodCapability,
71253
71511
  gas: gasCapability,
71512
+ groupActive: groupActiveCapability,
71254
71513
  groupCommands: groupCommandsCapability,
71255
71514
  groupStatus: groupStatusCapability,
71256
71515
  heatingValve: heatingValveCapability,
@@ -75745,6 +76004,13 @@ Object.freeze({
75745
76004
  access: "view",
75746
76005
  role: "viewer"
75747
76006
  },
76007
+ "groupActive.getStatus": {
76008
+ capName: "group-active",
76009
+ capScope: "device",
76010
+ addonId: null,
76011
+ access: "view",
76012
+ role: "viewer"
76013
+ },
75748
76014
  "groupCommands.getStatus": {
75749
76015
  capName: "group-commands",
75750
76016
  capScope: "device",
@@ -85620,6 +85886,10 @@ var SENSOR_CAP_VOCABULARY = {
85620
85886
  icon: "flame"
85621
85887
  }]
85622
85888
  },
85889
+ "group-active": {
85890
+ scope: "device",
85891
+ noun: t("Group state", "Stato del gruppo")
85892
+ },
85623
85893
  "group-commands": {
85624
85894
  scope: "device",
85625
85895
  noun: t("Group command", "Comando di gruppo")
@@ -87177,6 +87447,11 @@ Object.freeze({
87177
87447
  form: "single",
87178
87448
  optional: false
87179
87449
  }],
87450
+ "groupActive.getStatus": [{
87451
+ name: "deviceId",
87452
+ form: "single",
87453
+ optional: false
87454
+ }],
87180
87455
  "groupCommands.getStatus": [{
87181
87456
  name: "deviceId",
87182
87457
  form: "single",
@@ -5575,7 +5575,7 @@ var ZodIssueCode = {
5575
5575
  var ZodFirstPartyTypeKind;
5576
5576
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5577
5577
  //#endregion
5578
- //#region ../types/dist/sleep-0sD_LHLI.mjs
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).
@@ -9018,6 +9018,7 @@ var CAP_NAMES = Object.freeze([
9018
9018
  "filesystem-browse",
9019
9019
  "flood",
9020
9020
  "gas",
9021
+ "group-active",
9021
9022
  "group-commands",
9022
9023
  "group-status",
9023
9024
  "heating-valve",
@@ -9839,6 +9840,10 @@ Object.freeze({
9839
9840
  "path": "detected",
9840
9841
  "valueType": "boolean"
9841
9842
  }],
9843
+ "group-active": [{
9844
+ "path": "active",
9845
+ "valueType": "boolean"
9846
+ }],
9842
9847
  "group-status": [
9843
9848
  {
9844
9849
  "path": "included",
@@ -11204,7 +11209,7 @@ function errMsg(err) {
11204
11209
  return String(err);
11205
11210
  }
11206
11211
  //#endregion
11207
- //#region ../types/dist/composition-CpETZ4HL.mjs
11212
+ //#region ../types/dist/composition-Bb8iwHEJ.mjs
11208
11213
  /**
11209
11214
  * The ffmpeg build every CamStack node downloads, per platform and arch.
11210
11215
  *
@@ -11519,6 +11524,13 @@ var table = {
11519
11524
  apply: () => {
11520
11525
  throw new ExpressionEvalError("latchedAt: stateful evaluation context is required");
11521
11526
  }
11527
+ },
11528
+ schmitt: {
11529
+ minArgs: 3,
11530
+ maxArgs: 5,
11531
+ apply: () => {
11532
+ throw new ExpressionEvalError("schmitt: stateful evaluation context is required");
11533
+ }
11522
11534
  }
11523
11535
  };
11524
11536
  Object.freeze(Object.assign(Object.create(null), table));
@@ -12029,7 +12041,7 @@ var RESET_PERIODS = [
12029
12041
  5 * MINUTE_MS;
12030
12042
  24 * HOUR_MS, 2 * DAY_MS, 7 * DAY_MS, 30 * DAY_MS;
12031
12043
  7 * DAY_MS, 30 * DAY_MS, 365 * DAY_MS;
12032
- var StatisticWindowSchema = discriminatedUnion("kind", [object({
12044
+ var rollingWindowObject = object({
12033
12045
  kind: literal("rolling"),
12034
12046
  span: _enum(ROLLING_SPANS),
12035
12047
  customMinutes: number().int().min(5).optional()
@@ -12046,7 +12058,9 @@ var StatisticWindowSchema = discriminatedUnion("kind", [object({
12046
12058
  path: ["customMinutes"],
12047
12059
  input: payload.value
12048
12060
  });
12049
- }), object({
12061
+ });
12062
+ var RollingWindowSchema = rollingWindowObject;
12063
+ var StatisticWindowSchema = discriminatedUnion("kind", [rollingWindowObject, object({
12050
12064
  kind: literal("calendar"),
12051
12065
  period: _enum(CALENDAR_PERIODS)
12052
12066
  })]);
@@ -12076,7 +12090,13 @@ var GROUP_TEMPLATE_IDS = [
12076
12090
  "occupancy",
12077
12091
  "binary",
12078
12092
  "switch",
12079
- "light"
12093
+ "light",
12094
+ "fan",
12095
+ "cover",
12096
+ "valve",
12097
+ "lock",
12098
+ "media-player",
12099
+ "climate"
12080
12100
  ];
12081
12101
  var NUMERIC_AGGREGATES = [
12082
12102
  "mean",
@@ -12135,6 +12155,42 @@ var HelperSpecSchema = discriminatedUnion("kind", [
12135
12155
  reset: _enum(RESET_PERIODS),
12136
12156
  output: _enum(["energy", "meter"]),
12137
12157
  source: HelperMemberSchema
12158
+ }),
12159
+ object({
12160
+ kind: literal("threshold"),
12161
+ source: HelperMemberSchema,
12162
+ high: number(),
12163
+ low: number(),
12164
+ onForMs: number().int().nonnegative(),
12165
+ offForMs: number().int().nonnegative()
12166
+ }),
12167
+ object({
12168
+ kind: literal("arithmetic"),
12169
+ op: _enum([
12170
+ "sum",
12171
+ "difference",
12172
+ "ratio"
12173
+ ]),
12174
+ inputs: array(HelperMemberSchema).min(2).max(64)
12175
+ }),
12176
+ object({
12177
+ kind: literal("expression"),
12178
+ expr: string().min(1),
12179
+ inputs: array(object({
12180
+ name: string().min(1),
12181
+ member: HelperMemberSchema
12182
+ })).min(1).max(64),
12183
+ output: _enum(["number", "boolean"])
12184
+ }),
12185
+ object({
12186
+ kind: literal("derivative"),
12187
+ window: RollingWindowSchema,
12188
+ per: _enum([
12189
+ "second",
12190
+ "minute",
12191
+ "hour"
12192
+ ]),
12193
+ source: HelperMemberSchema
12138
12194
  })
12139
12195
  ]);
12140
12196
  /** A composed device's stableId is this prefix plus the block id. */
@@ -12197,6 +12253,12 @@ var CompositionFieldSourceSchema = discriminatedUnion("kind", [
12197
12253
  "all"
12198
12254
  ]),
12199
12255
  reads: array(CompositionFieldReadSchema).min(1).max(64),
12256
+ /**
12257
+ * Set when the reads are an enum state, not a yes/no: the listed states
12258
+ * count as active (a cover is `open`). A state outside the list is inactive;
12259
+ * a read that is not a state at all is left out. Only `any` / `all` use it.
12260
+ */
12261
+ activeWhen: array(string().min(1)).min(1).optional(),
12200
12262
  /** `value` is the reading; the others are the member counts. */
12201
12263
  publish: _enum([
12202
12264
  "value",
@@ -18941,13 +19003,17 @@ Object.freeze({
18941
19003
  latchedAt: {
18942
19004
  kind: "fixed",
18943
19005
  result: ["number", "null"]
19006
+ },
19007
+ schmitt: {
19008
+ kind: "fixed",
19009
+ result: ["boolean", "null"]
18944
19010
  }
18945
19011
  });
18946
19012
  /**
18947
19013
  * One catalog row per base reading a group helper can build (D944 §3).
18948
19014
  * Data, not a form default written into the block.
18949
19015
  */
18950
- var NOW$1 = {
19016
+ var NOW$2 = {
18951
19017
  fieldPath: "lastFetchedAt",
18952
19018
  expr: "now"
18953
19019
  };
@@ -18961,6 +19027,8 @@ function numeric(input) {
18961
19027
  family: "numeric",
18962
19028
  deviceType: DeviceType.Sensor,
18963
19029
  memberDeviceType: DeviceType.Sensor,
19030
+ memberDeviceTypes: [DeviceType.Sensor],
19031
+ activeWhen: void 0,
18964
19032
  commandCaps: [],
18965
19033
  baseUnit: baseUnitOf(input.quantity),
18966
19034
  aggregates: NUMERIC_AGGREGATES,
@@ -18976,6 +19044,8 @@ function binary(input) {
18976
19044
  family: "binary",
18977
19045
  deviceType: DeviceType.Sensor,
18978
19046
  memberDeviceType: DeviceType.Sensor,
19047
+ memberDeviceTypes: [DeviceType.Sensor],
19048
+ activeWhen: void 0,
18979
19049
  commandCaps: [],
18980
19050
  quantity: "none",
18981
19051
  baseUnit: void 0,
@@ -18993,7 +19063,7 @@ var GROUP_TEMPLATES = [
18993
19063
  quantity: "temperature",
18994
19064
  defaultAggregate: "mean",
18995
19065
  empty: "null",
18996
- companions: [NOW$1]
19066
+ companions: [NOW$2]
18997
19067
  }),
18998
19068
  numeric({
18999
19069
  id: "humidity",
@@ -19004,7 +19074,7 @@ var GROUP_TEMPLATES = [
19004
19074
  quantity: "humidity",
19005
19075
  defaultAggregate: "mean",
19006
19076
  empty: "null",
19007
- companions: [NOW$1]
19077
+ companions: [NOW$2]
19008
19078
  }),
19009
19079
  numeric({
19010
19080
  id: "pressure",
@@ -19015,7 +19085,7 @@ var GROUP_TEMPLATES = [
19015
19085
  quantity: "pressure",
19016
19086
  defaultAggregate: "mean",
19017
19087
  empty: "null",
19018
- companions: [NOW$1]
19088
+ companions: [NOW$2]
19019
19089
  }),
19020
19090
  numeric({
19021
19091
  id: "illuminance",
@@ -19026,7 +19096,7 @@ var GROUP_TEMPLATES = [
19026
19096
  quantity: "illuminance",
19027
19097
  defaultAggregate: "mean",
19028
19098
  empty: "null",
19029
- companions: [NOW$1]
19099
+ companions: [NOW$2]
19030
19100
  }),
19031
19101
  numeric({
19032
19102
  id: "power",
@@ -19037,7 +19107,7 @@ var GROUP_TEMPLATES = [
19037
19107
  quantity: "power",
19038
19108
  defaultAggregate: "sum",
19039
19109
  empty: "omit",
19040
- companions: [NOW$1]
19110
+ companions: [NOW$2]
19041
19111
  }),
19042
19112
  numeric({
19043
19113
  id: "energy",
@@ -19048,7 +19118,7 @@ var GROUP_TEMPLATES = [
19048
19118
  quantity: "energy",
19049
19119
  defaultAggregate: "sum",
19050
19120
  empty: "omit",
19051
- companions: [NOW$1]
19121
+ companions: [NOW$2]
19052
19122
  }),
19053
19123
  numeric({
19054
19124
  id: "battery",
@@ -19083,7 +19153,7 @@ var GROUP_TEMPLATES = [
19083
19153
  quantity: "device",
19084
19154
  defaultAggregate: "mean",
19085
19155
  empty: "null",
19086
- companions: [NOW$1]
19156
+ companions: [NOW$2]
19087
19157
  }),
19088
19158
  binary({
19089
19159
  id: "motion",
@@ -19177,6 +19247,11 @@ var GROUP_TEMPLATES = [
19177
19247
  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.",
19178
19248
  deviceType: DeviceType.Switch,
19179
19249
  outputCap: "switch",
19250
+ outputField: "on",
19251
+ member: {
19252
+ cap: "switch",
19253
+ fieldPath: "on"
19254
+ },
19180
19255
  commandCaps: ["switch"]
19181
19256
  }),
19182
19257
  actuator({
@@ -19184,29 +19259,130 @@ var GROUP_TEMPLATES = [
19184
19259
  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.",
19185
19260
  deviceType: DeviceType.Light,
19186
19261
  outputCap: "switch",
19262
+ outputField: "on",
19263
+ member: {
19264
+ cap: "switch",
19265
+ fieldPath: "on"
19266
+ },
19187
19267
  commandCaps: [
19188
19268
  "switch",
19189
19269
  "brightness",
19190
19270
  "color"
19191
19271
  ]
19272
+ }),
19273
+ actuator({
19274
+ id: "fan",
19275
+ 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.",
19276
+ deviceType: DeviceType.Fan,
19277
+ outputCap: "switch",
19278
+ outputField: "on",
19279
+ member: {
19280
+ cap: "switch",
19281
+ fieldPath: "on"
19282
+ },
19283
+ commandCaps: ["switch", "fan-control"]
19284
+ }),
19285
+ actuator({
19286
+ id: "cover",
19287
+ 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.",
19288
+ deviceType: DeviceType.Cover,
19289
+ outputCap: "group-active",
19290
+ outputField: "active",
19291
+ member: {
19292
+ cap: "cover",
19293
+ fieldPath: "state"
19294
+ },
19295
+ activeWhen: [
19296
+ "open",
19297
+ "opening",
19298
+ "stopped"
19299
+ ],
19300
+ commandCaps: ["cover"]
19301
+ }),
19302
+ actuator({
19303
+ id: "valve",
19304
+ 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.",
19305
+ deviceType: DeviceType.Valve,
19306
+ outputCap: "group-active",
19307
+ outputField: "active",
19308
+ member: {
19309
+ cap: "valve",
19310
+ fieldPath: "state"
19311
+ },
19312
+ activeWhen: [
19313
+ "open",
19314
+ "opening",
19315
+ "stopped"
19316
+ ],
19317
+ commandCaps: ["valve"]
19318
+ }),
19319
+ actuator({
19320
+ id: "lock",
19321
+ 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.",
19322
+ deviceType: DeviceType.Lock,
19323
+ outputCap: "group-active",
19324
+ outputField: "active",
19325
+ member: {
19326
+ cap: "lock-control",
19327
+ fieldPath: "state"
19328
+ },
19329
+ activeWhen: ["locked"],
19330
+ commandCaps: ["lock-control"]
19331
+ }),
19332
+ actuator({
19333
+ id: "media-player",
19334
+ 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.",
19335
+ deviceType: DeviceType.MediaPlayer,
19336
+ outputCap: "group-active",
19337
+ outputField: "active",
19338
+ member: {
19339
+ cap: "media-player",
19340
+ fieldPath: "state"
19341
+ },
19342
+ activeWhen: ["playing", "buffering"],
19343
+ commandCaps: ["media-player"]
19344
+ }),
19345
+ actuator({
19346
+ id: "climate",
19347
+ 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.",
19348
+ deviceType: DeviceType.Thermostat,
19349
+ memberDeviceTypes: [DeviceType.Thermostat, DeviceType.Climate],
19350
+ outputCap: "group-active",
19351
+ outputField: "active",
19352
+ member: {
19353
+ cap: "climate-control",
19354
+ fieldPath: "mode"
19355
+ },
19356
+ activeWhen: [
19357
+ "heat",
19358
+ "cool",
19359
+ "auto",
19360
+ "heat_cool",
19361
+ "fan_only",
19362
+ "dry"
19363
+ ],
19364
+ commandCaps: ["climate-control"]
19192
19365
  })
19193
19366
  ];
19194
19367
  function actuator(input) {
19195
19368
  return {
19196
- ...input,
19369
+ id: input.id,
19370
+ summary: input.summary,
19371
+ deviceType: input.deviceType,
19372
+ outputCap: input.outputCap,
19373
+ outputField: input.outputField,
19374
+ commandCaps: input.commandCaps,
19197
19375
  family: "actuator",
19198
19376
  role: void 0,
19199
19377
  memberDeviceType: input.deviceType,
19200
- outputField: "on",
19378
+ memberDeviceTypes: input.memberDeviceTypes ?? [input.deviceType],
19379
+ activeWhen: input.activeWhen,
19201
19380
  quantity: "none",
19202
19381
  baseUnit: void 0,
19203
19382
  aggregates: BINARY_AGGREGATES,
19204
19383
  defaultAggregate: "any",
19205
19384
  empty: "offline",
19206
- accept: [{
19207
- cap: "switch",
19208
- fieldPath: "on"
19209
- }],
19385
+ accept: [input.member],
19210
19386
  companions: [CHANGED]
19211
19387
  };
19212
19388
  }
@@ -47391,7 +47567,20 @@ var NcRuleInputSchema = object({
47391
47567
  * save by the hub's grouping guard). `.optional()`, never `.default()`: the addon cap
47392
47568
  * path does not run Zod defaults.
47393
47569
  */
47394
- groupingSec: number().int().min(5).max(60).optional()
47570
+ groupingSec: number().int().min(5).max(60).optional(),
47571
+ /**
47572
+ * ASK ME TO CONFIRM DETECTIONS (#243): a DETECTION notification of this rule
47573
+ * carries "Correct" / "Wrong" buttons (and, where the channel has room, a
47574
+ * "Wrong, it is a <class>" choice). A tap marks the track for retraining, the
47575
+ * same mark the Library writes, and records whose notification it was and
47576
+ * when. A channel with no buttons gets the same two choices as links.
47577
+ *
47578
+ * `.optional()`, never `.default()` (a Zod default does not run on the addon
47579
+ * cap path): absent and `false` both mean off, which is what every rule
47580
+ * authored before this field meant. An editor turns it off by writing
47581
+ * `false`, so it needs no `clear` key.
47582
+ */
47583
+ askVerdict: boolean().optional()
47395
47584
  });
47396
47585
  /**
47397
47586
  * Partial patch for `updateRule` — any subset of the input fields, plus the
@@ -61110,7 +61299,17 @@ var groupCommandsCapability = {
61110
61299
  scope: "device",
61111
61300
  deviceNative: true,
61112
61301
  mode: "singleton",
61113
- deviceTypes: [DeviceType.Switch, DeviceType.Light],
61302
+ deviceTypes: [
61303
+ DeviceType.Switch,
61304
+ DeviceType.Light,
61305
+ DeviceType.Fan,
61306
+ DeviceType.Cover,
61307
+ DeviceType.Valve,
61308
+ DeviceType.Lock,
61309
+ DeviceType.MediaPlayer,
61310
+ DeviceType.Thermostat,
61311
+ DeviceType.Climate
61312
+ ],
61114
61313
  methods: {},
61115
61314
  status: {
61116
61315
  schema: GroupCommandsSchema,
@@ -61128,6 +61327,49 @@ var groupCommandsCapability = {
61128
61327
  history: "none"
61129
61328
  };
61130
61329
  /**
61330
+ * Whether a helper actuator group counts as active (D944): at least one
61331
+ * included member is, or every included member is. What "active" means is the
61332
+ * type's: a cover is open, a lock is locked, a media player is playing, a
61333
+ * climate device is not off. A group of lights, switches and fans reports
61334
+ * `switch.on` instead; this cap is for the types whose own state is not a
61335
+ * yes/no. Unknown members are left out (`group-status` counts them) and an
61336
+ * empty included set takes the device offline, never `active: false`.
61337
+ */
61338
+ var GroupActiveSchema = object({
61339
+ active: boolean().meta({ label: "Active" }),
61340
+ /** Ms epoch when the slice was last updated. */
61341
+ lastChangedAt: number()
61342
+ });
61343
+ var groupActiveCapability = {
61344
+ name: "group-active",
61345
+ scope: "device",
61346
+ deviceNative: true,
61347
+ mode: "singleton",
61348
+ deviceTypes: [
61349
+ DeviceType.Cover,
61350
+ DeviceType.Valve,
61351
+ DeviceType.Lock,
61352
+ DeviceType.MediaPlayer,
61353
+ DeviceType.Climate,
61354
+ DeviceType.Thermostat
61355
+ ],
61356
+ methods: {},
61357
+ status: {
61358
+ schema: GroupActiveSchema,
61359
+ kind: "push"
61360
+ },
61361
+ runtimeState: GroupActiveSchema,
61362
+ /**
61363
+ * Runtime-state durability: **session** — recomputed from the members on the
61364
+ * next source event; a restored value would outlive the members it named.
61365
+ *
61366
+ * See `RuntimeStateDurability`. Enforced by
61367
+ * `scripts/check-runtime-state-durability.ts`.
61368
+ */
61369
+ durability: "session",
61370
+ history: "none"
61371
+ };
61372
+ /**
61131
61373
  * How many members of a helper group answered (D944). Counts are integers,
61132
61374
  * not measurements: zero included is a real count, never a stand-in reading.
61133
61375
  * The reading itself stays on the output capability. History is none — the
@@ -61158,7 +61400,14 @@ var groupStatusCapability = {
61158
61400
  deviceTypes: [
61159
61401
  DeviceType.Sensor,
61160
61402
  DeviceType.Switch,
61161
- DeviceType.Light
61403
+ DeviceType.Light,
61404
+ DeviceType.Fan,
61405
+ DeviceType.Cover,
61406
+ DeviceType.Valve,
61407
+ DeviceType.Lock,
61408
+ DeviceType.MediaPlayer,
61409
+ DeviceType.Thermostat,
61410
+ DeviceType.Climate
61162
61411
  ],
61163
61412
  methods: {},
61164
61413
  status: {
@@ -62431,7 +62680,14 @@ var lockControlCapability = {
62431
62680
  }),
62432
62681
  unlock: method(object({
62433
62682
  deviceId: number().int().nonnegative(),
62434
- code: string().min(1).optional()
62683
+ code: string().min(1).optional(),
62684
+ /**
62685
+ * Honoured by a helper lock GROUP only (D944): unlocking several doors
62686
+ * with one call is refused unless the caller says it was confirmed. A
62687
+ * single lock ignores it. The refusal lives in the callee, so no
62688
+ * automation or API caller reaches the doors by skipping a dialog.
62689
+ */
62690
+ confirm: boolean().optional()
62435
62691
  }), _void(), {
62436
62692
  kind: "mutation",
62437
62693
  auth: "protected"
@@ -68274,7 +68530,8 @@ var switchCapability = {
68274
68530
  deviceTypes: [
68275
68531
  DeviceType.Switch,
68276
68532
  DeviceType.Siren,
68277
- DeviceType.Light
68533
+ DeviceType.Light,
68534
+ DeviceType.Fan
68278
68535
  ],
68279
68536
  methods: { setState: method(object({
68280
68537
  deviceId: number(),
@@ -70524,6 +70781,7 @@ function runningFromMediaPlayer(state, previous, fetchedAt, transitionAt) {
70524
70781
  if (state === "paused") return nativeSlice(false, "paused", previous, transitionAtMs, fetchedAt, null);
70525
70782
  return nativeSlice(false, state, previous, transitionAtMs, fetchedAt, null);
70526
70783
  }
70784
+ DeviceFeature.FanSpeed, DeviceFeature.FanPreset, DeviceFeature.FanDirection, DeviceFeature.FanOscillating, DeviceFeature.CoverPositionable, DeviceFeature.CoverTilt, DeviceFeature.ValvePositionable, DeviceFeature.MediaPlayerVolume, DeviceFeature.ClimateFanMode;
70527
70785
  /**
70528
70786
  * Frozen unit → spec table. `•` in the doc marks each dimension's canonical
70529
70787
  * unit (`factor: 1, offset: 0`). °F derives from `°C = (°F − 32) × 5/9` ⇒
@@ -71252,6 +71510,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
71252
71510
  featureProbe: featureProbeCapability,
71253
71511
  flood: floodCapability,
71254
71512
  gas: gasCapability,
71513
+ groupActive: groupActiveCapability,
71255
71514
  groupCommands: groupCommandsCapability,
71256
71515
  groupStatus: groupStatusCapability,
71257
71516
  heatingValve: heatingValveCapability,
@@ -75746,6 +76005,13 @@ Object.freeze({
75746
76005
  access: "view",
75747
76006
  role: "viewer"
75748
76007
  },
76008
+ "groupActive.getStatus": {
76009
+ capName: "group-active",
76010
+ capScope: "device",
76011
+ addonId: null,
76012
+ access: "view",
76013
+ role: "viewer"
76014
+ },
75749
76015
  "groupCommands.getStatus": {
75750
76016
  capName: "group-commands",
75751
76017
  capScope: "device",
@@ -85621,6 +85887,10 @@ var SENSOR_CAP_VOCABULARY = {
85621
85887
  icon: "flame"
85622
85888
  }]
85623
85889
  },
85890
+ "group-active": {
85891
+ scope: "device",
85892
+ noun: t("Group state", "Stato del gruppo")
85893
+ },
85624
85894
  "group-commands": {
85625
85895
  scope: "device",
85626
85896
  noun: t("Group command", "Comando di gruppo")
@@ -87178,6 +87448,11 @@ Object.freeze({
87178
87448
  form: "single",
87179
87449
  optional: false
87180
87450
  }],
87451
+ "groupActive.getStatus": [{
87452
+ name: "deviceId",
87453
+ form: "single",
87454
+ optional: false
87455
+ }],
87181
87456
  "groupCommands.getStatus": [{
87182
87457
  name: "deviceId",
87183
87458
  form: "single",
@@ -24,7 +24,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
24
24
  enumerable: true
25
25
  }) : target, mod));
26
26
  //#endregion
27
- const require_dist = require("../dist-Dcmr-Isu.js");
27
+ const require_dist = require("../dist-DV8KQcWd.js");
28
28
  let node_crypto = require("node:crypto");
29
29
  require("node:zlib");
30
30
  let node_fs = require("node:fs");
@@ -3496,6 +3496,10 @@ var CAPS_NOT_EXPORTED = [
3496
3496
  cap: "meter",
3497
3497
  reason: "The integral of a gauge that is not watts (D944). The total is base-unit seconds between resets; energy from watts is power-meter.kwhTotal. The source quantity is not on this device yet, so publishing the total as a sensor would give it no unit."
3498
3498
  },
3499
+ {
3500
+ cap: "group-active",
3501
+ reason: "Whether a helper actuator group counts as active (D944): a cover is open, a lock is locked, a player is playing. Session-only, no history, and the group is not exported as the type it commands; the members are."
3502
+ },
3499
3503
  {
3500
3504
  cap: "group-commands",
3501
3505
  reason: "The last fan-out a helper group attempted (D944), one row per member. It is session-only and has no history. The command an automation sends is the member capability (switch, brightness, colour), not this record."
@@ -1,4 +1,4 @@
1
- import { Ft as BaseAddon, Gt as array, Ht as isReadingQuantity, I as consumableFormOf, L as consumableKindOf, Lt as baseUnitOf, O as buildAddonRouteProvider, Qt as string, U as deviceExportCapability, Ut as nodePin, Xt as object, a as COCO_TO_MACRO, c as ConsumableItemSchema, d as FanDirectionSchema, en as unknown, f as HvacModeSchema, i as CAMERA_SWITCH_ORDER, l as ConsumableStatusSchema, m as PLUG_APPLIANCE_TYPES, nn as EventCategory, o as CameraSwitchIdSchema, p as MediaPlayerRepeatSchema, s as ConsumableFormSchema, st as oauthIntegrationCapability, t as AlarmArmModeSchema, v as addonRoutesCapability } from "../dist-CT3sP-p0.mjs";
1
+ import { Ft as BaseAddon, Gt as array, Ht as isReadingQuantity, I as consumableFormOf, L as consumableKindOf, Lt as baseUnitOf, O as buildAddonRouteProvider, Qt as string, U as deviceExportCapability, Ut as nodePin, Xt as object, a as COCO_TO_MACRO, c as ConsumableItemSchema, d as FanDirectionSchema, en as unknown, f as HvacModeSchema, i as CAMERA_SWITCH_ORDER, l as ConsumableStatusSchema, m as PLUG_APPLIANCE_TYPES, nn as EventCategory, o as CameraSwitchIdSchema, p as MediaPlayerRepeatSchema, s as ConsumableFormSchema, st as oauthIntegrationCapability, t as AlarmArmModeSchema, v as addonRoutesCapability } from "../dist-CdqN_VJZ.mjs";
2
2
  import { createHmac, timingSafeEqual } from "node:crypto";
3
3
  import "node:zlib";
4
4
  import "node:fs";
@@ -3461,6 +3461,10 @@ var CAPS_NOT_EXPORTED = [
3461
3461
  cap: "meter",
3462
3462
  reason: "The integral of a gauge that is not watts (D944). The total is base-unit seconds between resets; energy from watts is power-meter.kwhTotal. The source quantity is not on this device yet, so publishing the total as a sensor would give it no unit."
3463
3463
  },
3464
+ {
3465
+ cap: "group-active",
3466
+ reason: "Whether a helper actuator group counts as active (D944): a cover is open, a lock is locked, a player is playing. Session-only, no history, and the group is not exported as the type it commands; the members are."
3467
+ },
3464
3468
  {
3465
3469
  cap: "group-commands",
3466
3470
  reason: "The last fan-out a helper group attempted (D944), one row per member. It is session-only and has no history. The command an automation sends is the member capability (switch, brightness, colour), not this record."
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-homeassistant",
3
- "version": "1.2.630",
3
+ "version": "1.2.631",
4
4
  "description": "Home Assistant device provider addon for CamStack",
5
5
  "keywords": [
6
6
  "camstack",