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