@camstack/addon-provider-homeassistant 1.2.630 → 1.2.632

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.
@@ -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",
@@ -17552,7 +17614,22 @@ var BrokerProviderInfoSchema = object({
17552
17614
  */
17553
17615
  interactiveConnectPath: string().min(1).optional(),
17554
17616
  /** Relative hub path to disconnect the linked account (same popup pattern). */
17555
- interactiveDisconnectPath: string().min(1).optional()
17617
+ interactiveDisconnectPath: string().min(1).optional(),
17618
+ /**
17619
+ * The kind signs in through a server-held interactive session instead of
17620
+ * (or before) typed credentials. `basePath` is a hub-relative route set
17621
+ * served by the owning addon (`/addon/<id>/...`) speaking the sign-in
17622
+ * contract: `POST {basePath}/start` (body: the form's settings) answers
17623
+ * `{ sessionId, loginUrl }`; `GET {basePath}/status?sessionId=` answers
17624
+ * `{ phase: 'starting' | 'awaiting-login' | 'captured' | 'error' |
17625
+ * 'cancelled', loginUrl, error }`; `POST {basePath}/commit`
17626
+ * (`{ sessionId, name, brokerId? }`) stores the credentials on a new or
17627
+ * existing broker and answers `{ brokerId }`; `POST {basePath}/cancel`
17628
+ * (`{ sessionId }`) drops the session. The dialog that edits a broker
17629
+ * offers it as the default path; the fields the session fills are
17630
+ * marked `filledBySignIn` in the kind's settings schema.
17631
+ */
17632
+ signIn: object({ basePath: string().min(1) }).optional()
17556
17633
  }))
17557
17634
  });
17558
17635
  var ListInputSchema = object({
@@ -18941,13 +19018,17 @@ Object.freeze({
18941
19018
  latchedAt: {
18942
19019
  kind: "fixed",
18943
19020
  result: ["number", "null"]
19021
+ },
19022
+ schmitt: {
19023
+ kind: "fixed",
19024
+ result: ["boolean", "null"]
18944
19025
  }
18945
19026
  });
18946
19027
  /**
18947
19028
  * One catalog row per base reading a group helper can build (D944 §3).
18948
19029
  * Data, not a form default written into the block.
18949
19030
  */
18950
- var NOW$1 = {
19031
+ var NOW$2 = {
18951
19032
  fieldPath: "lastFetchedAt",
18952
19033
  expr: "now"
18953
19034
  };
@@ -18961,6 +19042,8 @@ function numeric(input) {
18961
19042
  family: "numeric",
18962
19043
  deviceType: DeviceType.Sensor,
18963
19044
  memberDeviceType: DeviceType.Sensor,
19045
+ memberDeviceTypes: [DeviceType.Sensor],
19046
+ activeWhen: void 0,
18964
19047
  commandCaps: [],
18965
19048
  baseUnit: baseUnitOf(input.quantity),
18966
19049
  aggregates: NUMERIC_AGGREGATES,
@@ -18976,6 +19059,8 @@ function binary(input) {
18976
19059
  family: "binary",
18977
19060
  deviceType: DeviceType.Sensor,
18978
19061
  memberDeviceType: DeviceType.Sensor,
19062
+ memberDeviceTypes: [DeviceType.Sensor],
19063
+ activeWhen: void 0,
18979
19064
  commandCaps: [],
18980
19065
  quantity: "none",
18981
19066
  baseUnit: void 0,
@@ -18993,7 +19078,7 @@ var GROUP_TEMPLATES = [
18993
19078
  quantity: "temperature",
18994
19079
  defaultAggregate: "mean",
18995
19080
  empty: "null",
18996
- companions: [NOW$1]
19081
+ companions: [NOW$2]
18997
19082
  }),
18998
19083
  numeric({
18999
19084
  id: "humidity",
@@ -19004,7 +19089,7 @@ var GROUP_TEMPLATES = [
19004
19089
  quantity: "humidity",
19005
19090
  defaultAggregate: "mean",
19006
19091
  empty: "null",
19007
- companions: [NOW$1]
19092
+ companions: [NOW$2]
19008
19093
  }),
19009
19094
  numeric({
19010
19095
  id: "pressure",
@@ -19015,7 +19100,7 @@ var GROUP_TEMPLATES = [
19015
19100
  quantity: "pressure",
19016
19101
  defaultAggregate: "mean",
19017
19102
  empty: "null",
19018
- companions: [NOW$1]
19103
+ companions: [NOW$2]
19019
19104
  }),
19020
19105
  numeric({
19021
19106
  id: "illuminance",
@@ -19026,7 +19111,7 @@ var GROUP_TEMPLATES = [
19026
19111
  quantity: "illuminance",
19027
19112
  defaultAggregate: "mean",
19028
19113
  empty: "null",
19029
- companions: [NOW$1]
19114
+ companions: [NOW$2]
19030
19115
  }),
19031
19116
  numeric({
19032
19117
  id: "power",
@@ -19037,7 +19122,7 @@ var GROUP_TEMPLATES = [
19037
19122
  quantity: "power",
19038
19123
  defaultAggregate: "sum",
19039
19124
  empty: "omit",
19040
- companions: [NOW$1]
19125
+ companions: [NOW$2]
19041
19126
  }),
19042
19127
  numeric({
19043
19128
  id: "energy",
@@ -19048,7 +19133,7 @@ var GROUP_TEMPLATES = [
19048
19133
  quantity: "energy",
19049
19134
  defaultAggregate: "sum",
19050
19135
  empty: "omit",
19051
- companions: [NOW$1]
19136
+ companions: [NOW$2]
19052
19137
  }),
19053
19138
  numeric({
19054
19139
  id: "battery",
@@ -19083,7 +19168,7 @@ var GROUP_TEMPLATES = [
19083
19168
  quantity: "device",
19084
19169
  defaultAggregate: "mean",
19085
19170
  empty: "null",
19086
- companions: [NOW$1]
19171
+ companions: [NOW$2]
19087
19172
  }),
19088
19173
  binary({
19089
19174
  id: "motion",
@@ -19177,6 +19262,11 @@ var GROUP_TEMPLATES = [
19177
19262
  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
19263
  deviceType: DeviceType.Switch,
19179
19264
  outputCap: "switch",
19265
+ outputField: "on",
19266
+ member: {
19267
+ cap: "switch",
19268
+ fieldPath: "on"
19269
+ },
19180
19270
  commandCaps: ["switch"]
19181
19271
  }),
19182
19272
  actuator({
@@ -19184,29 +19274,130 @@ var GROUP_TEMPLATES = [
19184
19274
  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
19275
  deviceType: DeviceType.Light,
19186
19276
  outputCap: "switch",
19277
+ outputField: "on",
19278
+ member: {
19279
+ cap: "switch",
19280
+ fieldPath: "on"
19281
+ },
19187
19282
  commandCaps: [
19188
19283
  "switch",
19189
19284
  "brightness",
19190
19285
  "color"
19191
19286
  ]
19287
+ }),
19288
+ actuator({
19289
+ id: "fan",
19290
+ 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.",
19291
+ deviceType: DeviceType.Fan,
19292
+ outputCap: "switch",
19293
+ outputField: "on",
19294
+ member: {
19295
+ cap: "switch",
19296
+ fieldPath: "on"
19297
+ },
19298
+ commandCaps: ["switch", "fan-control"]
19299
+ }),
19300
+ actuator({
19301
+ id: "cover",
19302
+ 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.",
19303
+ deviceType: DeviceType.Cover,
19304
+ outputCap: "group-active",
19305
+ outputField: "active",
19306
+ member: {
19307
+ cap: "cover",
19308
+ fieldPath: "state"
19309
+ },
19310
+ activeWhen: [
19311
+ "open",
19312
+ "opening",
19313
+ "stopped"
19314
+ ],
19315
+ commandCaps: ["cover"]
19316
+ }),
19317
+ actuator({
19318
+ id: "valve",
19319
+ 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.",
19320
+ deviceType: DeviceType.Valve,
19321
+ outputCap: "group-active",
19322
+ outputField: "active",
19323
+ member: {
19324
+ cap: "valve",
19325
+ fieldPath: "state"
19326
+ },
19327
+ activeWhen: [
19328
+ "open",
19329
+ "opening",
19330
+ "stopped"
19331
+ ],
19332
+ commandCaps: ["valve"]
19333
+ }),
19334
+ actuator({
19335
+ id: "lock",
19336
+ 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.",
19337
+ deviceType: DeviceType.Lock,
19338
+ outputCap: "group-active",
19339
+ outputField: "active",
19340
+ member: {
19341
+ cap: "lock-control",
19342
+ fieldPath: "state"
19343
+ },
19344
+ activeWhen: ["locked"],
19345
+ commandCaps: ["lock-control"]
19346
+ }),
19347
+ actuator({
19348
+ id: "media-player",
19349
+ 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.",
19350
+ deviceType: DeviceType.MediaPlayer,
19351
+ outputCap: "group-active",
19352
+ outputField: "active",
19353
+ member: {
19354
+ cap: "media-player",
19355
+ fieldPath: "state"
19356
+ },
19357
+ activeWhen: ["playing", "buffering"],
19358
+ commandCaps: ["media-player"]
19359
+ }),
19360
+ actuator({
19361
+ id: "climate",
19362
+ 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.",
19363
+ deviceType: DeviceType.Thermostat,
19364
+ memberDeviceTypes: [DeviceType.Thermostat, DeviceType.Climate],
19365
+ outputCap: "group-active",
19366
+ outputField: "active",
19367
+ member: {
19368
+ cap: "climate-control",
19369
+ fieldPath: "mode"
19370
+ },
19371
+ activeWhen: [
19372
+ "heat",
19373
+ "cool",
19374
+ "auto",
19375
+ "heat_cool",
19376
+ "fan_only",
19377
+ "dry"
19378
+ ],
19379
+ commandCaps: ["climate-control"]
19192
19380
  })
19193
19381
  ];
19194
19382
  function actuator(input) {
19195
19383
  return {
19196
- ...input,
19384
+ id: input.id,
19385
+ summary: input.summary,
19386
+ deviceType: input.deviceType,
19387
+ outputCap: input.outputCap,
19388
+ outputField: input.outputField,
19389
+ commandCaps: input.commandCaps,
19197
19390
  family: "actuator",
19198
19391
  role: void 0,
19199
19392
  memberDeviceType: input.deviceType,
19200
- outputField: "on",
19393
+ memberDeviceTypes: input.memberDeviceTypes ?? [input.deviceType],
19394
+ activeWhen: input.activeWhen,
19201
19395
  quantity: "none",
19202
19396
  baseUnit: void 0,
19203
19397
  aggregates: BINARY_AGGREGATES,
19204
19398
  defaultAggregate: "any",
19205
19399
  empty: "offline",
19206
- accept: [{
19207
- cap: "switch",
19208
- fieldPath: "on"
19209
- }],
19400
+ accept: [input.member],
19210
19401
  companions: [CHANGED]
19211
19402
  };
19212
19403
  }
@@ -47391,7 +47582,20 @@ var NcRuleInputSchema = object({
47391
47582
  * save by the hub's grouping guard). `.optional()`, never `.default()`: the addon cap
47392
47583
  * path does not run Zod defaults.
47393
47584
  */
47394
- groupingSec: number().int().min(5).max(60).optional()
47585
+ groupingSec: number().int().min(5).max(60).optional(),
47586
+ /**
47587
+ * ASK ME TO CONFIRM DETECTIONS (#243): a DETECTION notification of this rule
47588
+ * carries "Correct" / "Wrong" buttons (and, where the channel has room, a
47589
+ * "Wrong, it is a <class>" choice). A tap marks the track for retraining, the
47590
+ * same mark the Library writes, and records whose notification it was and
47591
+ * when. A channel with no buttons gets the same two choices as links.
47592
+ *
47593
+ * `.optional()`, never `.default()` (a Zod default does not run on the addon
47594
+ * cap path): absent and `false` both mean off, which is what every rule
47595
+ * authored before this field meant. An editor turns it off by writing
47596
+ * `false`, so it needs no `clear` key.
47597
+ */
47598
+ askVerdict: boolean().optional()
47395
47599
  });
47396
47600
  /**
47397
47601
  * Partial patch for `updateRule` — any subset of the input fields, plus the
@@ -61110,7 +61314,17 @@ var groupCommandsCapability = {
61110
61314
  scope: "device",
61111
61315
  deviceNative: true,
61112
61316
  mode: "singleton",
61113
- deviceTypes: [DeviceType.Switch, DeviceType.Light],
61317
+ deviceTypes: [
61318
+ DeviceType.Switch,
61319
+ DeviceType.Light,
61320
+ DeviceType.Fan,
61321
+ DeviceType.Cover,
61322
+ DeviceType.Valve,
61323
+ DeviceType.Lock,
61324
+ DeviceType.MediaPlayer,
61325
+ DeviceType.Thermostat,
61326
+ DeviceType.Climate
61327
+ ],
61114
61328
  methods: {},
61115
61329
  status: {
61116
61330
  schema: GroupCommandsSchema,
@@ -61128,6 +61342,49 @@ var groupCommandsCapability = {
61128
61342
  history: "none"
61129
61343
  };
61130
61344
  /**
61345
+ * Whether a helper actuator group counts as active (D944): at least one
61346
+ * included member is, or every included member is. What "active" means is the
61347
+ * type's: a cover is open, a lock is locked, a media player is playing, a
61348
+ * climate device is not off. A group of lights, switches and fans reports
61349
+ * `switch.on` instead; this cap is for the types whose own state is not a
61350
+ * yes/no. Unknown members are left out (`group-status` counts them) and an
61351
+ * empty included set takes the device offline, never `active: false`.
61352
+ */
61353
+ var GroupActiveSchema = object({
61354
+ active: boolean().meta({ label: "Active" }),
61355
+ /** Ms epoch when the slice was last updated. */
61356
+ lastChangedAt: number()
61357
+ });
61358
+ var groupActiveCapability = {
61359
+ name: "group-active",
61360
+ scope: "device",
61361
+ deviceNative: true,
61362
+ mode: "singleton",
61363
+ deviceTypes: [
61364
+ DeviceType.Cover,
61365
+ DeviceType.Valve,
61366
+ DeviceType.Lock,
61367
+ DeviceType.MediaPlayer,
61368
+ DeviceType.Climate,
61369
+ DeviceType.Thermostat
61370
+ ],
61371
+ methods: {},
61372
+ status: {
61373
+ schema: GroupActiveSchema,
61374
+ kind: "push"
61375
+ },
61376
+ runtimeState: GroupActiveSchema,
61377
+ /**
61378
+ * Runtime-state durability: **session** — recomputed from the members on the
61379
+ * next source event; a restored value would outlive the members it named.
61380
+ *
61381
+ * See `RuntimeStateDurability`. Enforced by
61382
+ * `scripts/check-runtime-state-durability.ts`.
61383
+ */
61384
+ durability: "session",
61385
+ history: "none"
61386
+ };
61387
+ /**
61131
61388
  * How many members of a helper group answered (D944). Counts are integers,
61132
61389
  * not measurements: zero included is a real count, never a stand-in reading.
61133
61390
  * The reading itself stays on the output capability. History is none — the
@@ -61158,7 +61415,14 @@ var groupStatusCapability = {
61158
61415
  deviceTypes: [
61159
61416
  DeviceType.Sensor,
61160
61417
  DeviceType.Switch,
61161
- DeviceType.Light
61418
+ DeviceType.Light,
61419
+ DeviceType.Fan,
61420
+ DeviceType.Cover,
61421
+ DeviceType.Valve,
61422
+ DeviceType.Lock,
61423
+ DeviceType.MediaPlayer,
61424
+ DeviceType.Thermostat,
61425
+ DeviceType.Climate
61162
61426
  ],
61163
61427
  methods: {},
61164
61428
  status: {
@@ -62431,7 +62695,14 @@ var lockControlCapability = {
62431
62695
  }),
62432
62696
  unlock: method(object({
62433
62697
  deviceId: number().int().nonnegative(),
62434
- code: string().min(1).optional()
62698
+ code: string().min(1).optional(),
62699
+ /**
62700
+ * Honoured by a helper lock GROUP only (D944): unlocking several doors
62701
+ * with one call is refused unless the caller says it was confirmed. A
62702
+ * single lock ignores it. The refusal lives in the callee, so no
62703
+ * automation or API caller reaches the doors by skipping a dialog.
62704
+ */
62705
+ confirm: boolean().optional()
62435
62706
  }), _void(), {
62436
62707
  kind: "mutation",
62437
62708
  auth: "protected"
@@ -65017,9 +65288,9 @@ var PowerMeterStatusSchema = object({
65017
65288
  /** Cumulative energy in kilowatt-hours since the meter was reset. */
65018
65289
  kwhTotal: number().optional().meta(readingMeta("energy", { label: "Energy" })),
65019
65290
  /** Voltage in volts. */
65020
- volts: number().optional().meta(readingMeta("voltage")),
65291
+ volts: number().optional().meta(readingMeta("voltage", { label: "Voltage" })),
65021
65292
  /** Current in amperes. */
65022
- amps: number().optional().meta(readingMeta("current")),
65293
+ amps: number().optional().meta(readingMeta("current", { label: "Current" })),
65023
65294
  /** Apparent power in volt-amperes. */
65024
65295
  va: number().optional().meta(readingMeta("apparent-power")),
65025
65296
  /** Power factor (0..1) if reported. */
@@ -65027,17 +65298,74 @@ var PowerMeterStatusSchema = object({
65027
65298
  /** Ms epoch when the slice was last updated. */
65028
65299
  lastFetchedAt: number()
65029
65300
  });
65301
+ /**
65302
+ * Loads that draw metered mains power (D951). The reading is a feature of the
65303
+ * device itself — a plug, a lamp, a fan, an air conditioner, a boiler, a
65304
+ * vacuum dock — not a separate sensor beside it. A `Sensor` stays: a clamp
65305
+ * meter or a standalone energy monitor IS the device. Cover, lock, valve,
65306
+ * camera and the like are left out: their draw is not what anyone meters.
65307
+ */
65308
+ var POWER_METER_DEVICE_TYPES = [
65309
+ DeviceType.Sensor,
65310
+ DeviceType.Switch,
65311
+ DeviceType.Light,
65312
+ DeviceType.Fan,
65313
+ DeviceType.Climate,
65314
+ DeviceType.Thermostat,
65315
+ DeviceType.Humidifier,
65316
+ DeviceType.WaterHeater,
65317
+ DeviceType.MediaPlayer,
65318
+ DeviceType.Washer,
65319
+ DeviceType.Dryer,
65320
+ DeviceType.Dishwasher,
65321
+ DeviceType.Vacuum,
65322
+ DeviceType.LawnMower,
65323
+ DeviceType.PetFeeder
65324
+ ];
65325
+ /** Everything but a bare `Sensor`: a sensor that takes its reading from another sensor adds nothing. */
65326
+ var POWER_METER_CUSTOMIZE_DEVICE_TYPES = POWER_METER_DEVICE_TYPES.filter((type) => type !== DeviceType.Sensor);
65327
+ /** One scalar target per reading; each is sourced from a device of its own (D951). */
65328
+ function powerTarget(id, unit) {
65329
+ return {
65330
+ id,
65331
+ cardinality: "scalar",
65332
+ vocabulary: {
65333
+ cap: "power-meter",
65334
+ stateField: id
65335
+ },
65336
+ deviceTypes: POWER_METER_CUSTOMIZE_DEVICE_TYPES,
65337
+ apply: "add",
65338
+ path: id,
65339
+ sources: [{
65340
+ kind: "numeric",
65341
+ requiredUnit: unit,
65342
+ transforms: [{ kind: "identity" }]
65343
+ }],
65344
+ companions: [{
65345
+ kind: "clock",
65346
+ path: "lastFetchedAt",
65347
+ when: "always"
65348
+ }],
65349
+ sourceReport: { status: "assignment-status" },
65350
+ advancedExpression: true
65351
+ };
65352
+ }
65353
+ /** "Power and energy" extension: watts, energy, voltage and current from other devices (D951). */
65354
+ var powerMeterCustomize = {
65355
+ version: 1,
65356
+ targets: [
65357
+ powerTarget("watts", "W"),
65358
+ powerTarget("kwhTotal", "kWh"),
65359
+ powerTarget("volts", "V"),
65360
+ powerTarget("amps", "A")
65361
+ ]
65362
+ };
65030
65363
  var powerMeterCapability = {
65031
65364
  name: "power-meter",
65032
65365
  scope: "device",
65033
65366
  deviceNative: true,
65034
65367
  mode: "singleton",
65035
- deviceTypes: [
65036
- DeviceType.Sensor,
65037
- DeviceType.Washer,
65038
- DeviceType.Dryer,
65039
- DeviceType.Dishwasher
65040
- ],
65368
+ deviceTypes: POWER_METER_DEVICE_TYPES,
65041
65369
  methods: {},
65042
65370
  status: {
65043
65371
  schema: PowerMeterStatusSchema,
@@ -65094,7 +65422,8 @@ var powerMeterCapability = {
65094
65422
  } },
65095
65423
  /** Clock fields: written, but excluded from the compare that decides
65096
65424
  * whether persisting is worth a SQLite commit. */
65097
- volatileStateFields: ["lastFetchedAt"]
65425
+ volatileStateFields: ["lastFetchedAt"],
65426
+ customize: powerMeterCustomize
65098
65427
  };
65099
65428
  /**
65100
65429
  * Presence cap. Models HA `person.*` and `device_tracker.*` entities
@@ -68274,7 +68603,8 @@ var switchCapability = {
68274
68603
  deviceTypes: [
68275
68604
  DeviceType.Switch,
68276
68605
  DeviceType.Siren,
68277
- DeviceType.Light
68606
+ DeviceType.Light,
68607
+ DeviceType.Fan
68278
68608
  ],
68279
68609
  methods: { setState: method(object({
68280
68610
  deviceId: number(),
@@ -70524,6 +70854,7 @@ function runningFromMediaPlayer(state, previous, fetchedAt, transitionAt) {
70524
70854
  if (state === "paused") return nativeSlice(false, "paused", previous, transitionAtMs, fetchedAt, null);
70525
70855
  return nativeSlice(false, state, previous, transitionAtMs, fetchedAt, null);
70526
70856
  }
70857
+ DeviceFeature.FanSpeed, DeviceFeature.FanPreset, DeviceFeature.FanDirection, DeviceFeature.FanOscillating, DeviceFeature.CoverPositionable, DeviceFeature.CoverTilt, DeviceFeature.ValvePositionable, DeviceFeature.MediaPlayerVolume, DeviceFeature.ClimateFanMode;
70527
70858
  /**
70528
70859
  * Frozen unit → spec table. `•` in the doc marks each dimension's canonical
70529
70860
  * unit (`factor: 1, offset: 0`). °F derives from `°C = (°F − 32) × 5/9` ⇒
@@ -70923,7 +71254,7 @@ function tryConvertDelta(value, from, to) {
70923
71254
  return shifted - origin;
70924
71255
  }
70925
71256
  SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
70926
- 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.Washer, DeviceType.Dryer, DeviceType.Camera, DeviceType.Camera, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
71257
+ 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.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;
70927
71258
  String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
70928
71259
  DeviceRole.BinarySensor, DeviceRole.MotionSensor;
70929
71260
  new Set(CAP_NAMES);
@@ -71252,6 +71583,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
71252
71583
  featureProbe: featureProbeCapability,
71253
71584
  flood: floodCapability,
71254
71585
  gas: gasCapability,
71586
+ groupActive: groupActiveCapability,
71255
71587
  groupCommands: groupCommandsCapability,
71256
71588
  groupStatus: groupStatusCapability,
71257
71589
  heatingValve: heatingValveCapability,
@@ -75746,6 +76078,13 @@ Object.freeze({
75746
76078
  access: "view",
75747
76079
  role: "viewer"
75748
76080
  },
76081
+ "groupActive.getStatus": {
76082
+ capName: "group-active",
76083
+ capScope: "device",
76084
+ addonId: null,
76085
+ access: "view",
76086
+ role: "viewer"
76087
+ },
75749
76088
  "groupCommands.getStatus": {
75750
76089
  capName: "group-commands",
75751
76090
  capScope: "device",
@@ -85621,6 +85960,10 @@ var SENSOR_CAP_VOCABULARY = {
85621
85960
  icon: "flame"
85622
85961
  }]
85623
85962
  },
85963
+ "group-active": {
85964
+ scope: "device",
85965
+ noun: t("Group state", "Stato del gruppo")
85966
+ },
85624
85967
  "group-commands": {
85625
85968
  scope: "device",
85626
85969
  noun: t("Group command", "Comando di gruppo")
@@ -87178,6 +87521,11 @@ Object.freeze({
87178
87521
  form: "single",
87179
87522
  optional: false
87180
87523
  }],
87524
+ "groupActive.getStatus": [{
87525
+ name: "deviceId",
87526
+ form: "single",
87527
+ optional: false
87528
+ }],
87181
87529
  "groupCommands.getStatus": [{
87182
87530
  name: "deviceId",
87183
87531
  form: "single",