@camstack/addon-smtp-nodemailer 1.2.142 → 1.2.143

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.
@@ -5477,7 +5477,7 @@ var ZodIssueCode = {
5477
5477
  var ZodFirstPartyTypeKind;
5478
5478
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5479
5479
  //#endregion
5480
- //#region ../types/dist/sleep-bykKrTgu.mjs
5480
+ //#region ../types/dist/sleep--jXS9hWo.mjs
5481
5481
  /**
5482
5482
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5483
5483
  * window to float samples (D455).
@@ -8599,6 +8599,7 @@ var CAP_NAMES = Object.freeze([
8599
8599
  "filesystem-browse",
8600
8600
  "flood",
8601
8601
  "gas",
8602
+ "group-active",
8602
8603
  "group-commands",
8603
8604
  "group-status",
8604
8605
  "heating-valve",
@@ -8621,6 +8622,7 @@ var CAP_NAMES = Object.freeze([
8621
8622
  "login-method",
8622
8623
  "media-player",
8623
8624
  "mesh-network",
8625
+ "meter",
8624
8626
  "metrics-provider",
8625
8627
  "model-convert",
8626
8628
  "model-distributor",
@@ -9419,6 +9421,10 @@ Object.freeze({
9419
9421
  "path": "detected",
9420
9422
  "valueType": "boolean"
9421
9423
  }],
9424
+ "group-active": [{
9425
+ "path": "active",
9426
+ "valueType": "boolean"
9427
+ }],
9422
9428
  "group-status": [
9423
9429
  {
9424
9430
  "path": "included",
@@ -9678,6 +9684,10 @@ Object.freeze({
9678
9684
  ]
9679
9685
  }
9680
9686
  ],
9687
+ "meter": [{
9688
+ "path": "value",
9689
+ "valueType": "number"
9690
+ }],
9681
9691
  "motion": [
9682
9692
  {
9683
9693
  "path": "detected",
@@ -10421,7 +10431,7 @@ object({
10421
10431
  params: record(string(), union([string(), number()])).optional()
10422
10432
  });
10423
10433
  //#endregion
10424
- //#region ../types/dist/err-msg-BXKzRBwg.mjs
10434
+ //#region ../types/dist/err-msg-DIorGYeC.mjs
10425
10435
  var DeviceType = /* @__PURE__ */ function(DeviceType) {
10426
10436
  DeviceType["Camera"] = "camera";
10427
10437
  DeviceType["Hub"] = "hub";
@@ -10515,8 +10525,14 @@ var DeviceType = /* @__PURE__ */ function(DeviceType) {
10515
10525
  DeviceType["PetFeeder"] = "pet-feeder";
10516
10526
  /** Built-in dishwasher — program lifecycle, door / remote-start gates,
10517
10527
  * salt and rinse-aid levels. Installed with the `dishwasher` cap.
10518
- * Sources: native Bosch Home Connect, reusable by similar integrations. */
10528
+ * Sources: native Bosch Home Connect, reusable by similar integrations.
10529
+ * A plug-built dishwasher carries running-state and power instead. */
10519
10530
  DeviceType["Dishwasher"] = "dishwasher";
10531
+ /** Washing machine. A plug-built one is running while its power stays
10532
+ * above a threshold. No program cap — that surface is the dishwasher's. */
10533
+ DeviceType["Washer"] = "washer";
10534
+ /** Tumble dryer. Same plug-built running surface as {@link Washer}. */
10535
+ DeviceType["Dryer"] = "dryer";
10520
10536
  return DeviceType;
10521
10537
  }({});
10522
10538
  var DeviceFeature = /* @__PURE__ */ function(DeviceFeature) {
@@ -10764,7 +10780,7 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
10764
10780
  return DeviceRole;
10765
10781
  }({});
10766
10782
  //#endregion
10767
- //#region ../types/dist/composition-OhpuespA.mjs
10783
+ //#region ../types/dist/composition-Bb8iwHEJ.mjs
10768
10784
  /**
10769
10785
  * The ffmpeg build every CamStack node downloads, per platform and arch.
10770
10786
  *
@@ -11079,6 +11095,13 @@ var table = {
11079
11095
  apply: () => {
11080
11096
  throw new ExpressionEvalError("latchedAt: stateful evaluation context is required");
11081
11097
  }
11098
+ },
11099
+ schmitt: {
11100
+ minArgs: 3,
11101
+ maxArgs: 5,
11102
+ apply: () => {
11103
+ throw new ExpressionEvalError("schmitt: stateful evaluation context is required");
11104
+ }
11082
11105
  }
11083
11106
  };
11084
11107
  Object.freeze(Object.assign(Object.create(null), table));
@@ -11520,6 +11543,99 @@ function validateExpressionSource(src) {
11520
11543
  return null;
11521
11544
  }
11522
11545
  /**
11546
+ * One power reading becomes a washer, dryer or dishwasher (D944 helper).
11547
+ *
11548
+ * Standby of the control board is under 5 W; a motor or a heater is far
11549
+ * above that, so 5 W is the line. A door lock or a short pump spike is not
11550
+ * a cycle, so running starts only after 30 s above the line.
11551
+ *
11552
+ * A wash, dry or dishwasher pause (soak, heat-wait, heater off between
11553
+ * bursts) lasts several minutes. Ending the cycle on the first dip would
11554
+ * report "finished" in the middle of the program, so the stop dwell is
11555
+ * 10 minutes on every type. The number is stored per type so one machine
11556
+ * can move later without moving the others.
11557
+ */
11558
+ var APPLIANCE_TEMPLATE_ID = "appliance";
11559
+ var APPLIANCE_KINDS = [
11560
+ "washer",
11561
+ "dryer",
11562
+ "dishwasher"
11563
+ ];
11564
+ DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher;
11565
+ /**
11566
+ * Statistics and integrals over a history read (D944).
11567
+ *
11568
+ * Pure: the same points always give the same answer, so a restart recomputes
11569
+ * rather than trusting a buffer. A gauge mean is time-weighted (value × ms),
11570
+ * never the mean of the samples. A hole with no held value is not integrated
11571
+ * as zero. A truncated read is not published.
11572
+ */
11573
+ var STATISTIC_STATS = [
11574
+ "min",
11575
+ "max",
11576
+ "mean",
11577
+ "sum",
11578
+ "count",
11579
+ "change"
11580
+ ];
11581
+ /**
11582
+ * The range a statistics or integral helper asks history for (D944).
11583
+ *
11584
+ * Calendar edges are the hub's timezone, never UTC midnight: a day is 23, 24
11585
+ * or 25 hours across a DST change. A tier is eligible only when its retention
11586
+ * is strictly longer than the longest that range can be. Forever qualifies.
11587
+ * Equal to a tier's retention is a refusal, not a short answer.
11588
+ */
11589
+ var MINUTE_MS = 6e4;
11590
+ var HOUR_MS = 60 * MINUTE_MS;
11591
+ var DAY_MS = 24 * HOUR_MS;
11592
+ var ROLLING_SPANS = [
11593
+ "1h",
11594
+ "24h",
11595
+ "2d",
11596
+ "7d",
11597
+ "30d",
11598
+ "custom"
11599
+ ];
11600
+ var CALENDAR_PERIODS = [
11601
+ "today",
11602
+ "yesterday",
11603
+ "this-week",
11604
+ "this-month"
11605
+ ];
11606
+ var RESET_PERIODS = [
11607
+ "never",
11608
+ "daily",
11609
+ "weekly",
11610
+ "monthly"
11611
+ ];
11612
+ 5 * MINUTE_MS;
11613
+ 24 * HOUR_MS, 2 * DAY_MS, 7 * DAY_MS, 30 * DAY_MS;
11614
+ 7 * DAY_MS, 30 * DAY_MS, 365 * DAY_MS;
11615
+ var rollingWindowObject = object({
11616
+ kind: literal("rolling"),
11617
+ span: _enum(ROLLING_SPANS),
11618
+ customMinutes: number().int().min(5).optional()
11619
+ }).check((payload) => {
11620
+ if (payload.value.span === "custom" && payload.value.customMinutes === void 0) payload.issues.push({
11621
+ code: "custom",
11622
+ message: "a custom range needs a duration in minutes",
11623
+ path: ["customMinutes"],
11624
+ input: payload.value
11625
+ });
11626
+ if (payload.value.span !== "custom" && payload.value.customMinutes !== void 0) payload.issues.push({
11627
+ code: "custom",
11628
+ message: "only a custom range carries a duration",
11629
+ path: ["customMinutes"],
11630
+ input: payload.value
11631
+ });
11632
+ });
11633
+ var RollingWindowSchema = rollingWindowObject;
11634
+ var StatisticWindowSchema = discriminatedUnion("kind", [rollingWindowObject, object({
11635
+ kind: literal("calendar"),
11636
+ period: _enum(CALENDAR_PERIODS)
11637
+ })]);
11638
+ /**
11523
11639
  * A composition source identity: `(addonId, stableId)`, never a numeric device
11524
11640
  * id. Split out so helper schemas can name it without a cycle through
11525
11641
  * `composition.ts` (D659).
@@ -11545,7 +11661,13 @@ var GROUP_TEMPLATE_IDS = [
11545
11661
  "occupancy",
11546
11662
  "binary",
11547
11663
  "switch",
11548
- "light"
11664
+ "light",
11665
+ "fan",
11666
+ "cover",
11667
+ "valve",
11668
+ "lock",
11669
+ "media-player",
11670
+ "climate"
11549
11671
  ];
11550
11672
  var NUMERIC_AGGREGATES = [
11551
11673
  "mean",
@@ -11575,14 +11697,73 @@ var HelperMemberSchema = object({
11575
11697
  cap: string().min(1),
11576
11698
  fieldPath: string().min(1)
11577
11699
  });
11578
- var HelperSpecSchema = discriminatedUnion("kind", [object({
11579
- kind: literal("group"),
11580
- templateId: GroupTemplateIdSchema,
11581
- aggregate: AggregateReducerSchema,
11582
- members: array(HelperMemberSchema).min(1).max(64),
11583
- /** Actuator groups only. Readings leave this unset. */
11584
- active: ActiveCriterionSchema.optional()
11585
- })]);
11700
+ var HelperSpecSchema = discriminatedUnion("kind", [
11701
+ object({
11702
+ kind: literal("group"),
11703
+ templateId: GroupTemplateIdSchema,
11704
+ aggregate: AggregateReducerSchema,
11705
+ members: array(HelperMemberSchema).min(1).max(64),
11706
+ /** Actuator groups only. Readings leave this unset. */
11707
+ active: ActiveCriterionSchema.optional()
11708
+ }),
11709
+ object({
11710
+ kind: literal("appliance"),
11711
+ templateId: literal(APPLIANCE_TEMPLATE_ID),
11712
+ appliance: _enum(APPLIANCE_KINDS),
11713
+ thresholdWatts: number().positive(),
11714
+ startDwellMs: number().int().nonnegative(),
11715
+ stopDwellMs: number().int().nonnegative(),
11716
+ member: HelperMemberSchema
11717
+ }),
11718
+ object({
11719
+ kind: literal("statistic"),
11720
+ stat: _enum(STATISTIC_STATS),
11721
+ window: StatisticWindowSchema,
11722
+ source: HelperMemberSchema
11723
+ }),
11724
+ object({
11725
+ kind: literal("integral"),
11726
+ reset: _enum(RESET_PERIODS),
11727
+ output: _enum(["energy", "meter"]),
11728
+ source: HelperMemberSchema
11729
+ }),
11730
+ object({
11731
+ kind: literal("threshold"),
11732
+ source: HelperMemberSchema,
11733
+ high: number(),
11734
+ low: number(),
11735
+ onForMs: number().int().nonnegative(),
11736
+ offForMs: number().int().nonnegative()
11737
+ }),
11738
+ object({
11739
+ kind: literal("arithmetic"),
11740
+ op: _enum([
11741
+ "sum",
11742
+ "difference",
11743
+ "ratio"
11744
+ ]),
11745
+ inputs: array(HelperMemberSchema).min(2).max(64)
11746
+ }),
11747
+ object({
11748
+ kind: literal("expression"),
11749
+ expr: string().min(1),
11750
+ inputs: array(object({
11751
+ name: string().min(1),
11752
+ member: HelperMemberSchema
11753
+ })).min(1).max(64),
11754
+ output: _enum(["number", "boolean"])
11755
+ }),
11756
+ object({
11757
+ kind: literal("derivative"),
11758
+ window: RollingWindowSchema,
11759
+ per: _enum([
11760
+ "second",
11761
+ "minute",
11762
+ "hour"
11763
+ ]),
11764
+ source: HelperMemberSchema
11765
+ })
11766
+ ]);
11586
11767
  /** A composed device's stableId is this prefix plus the block id. */
11587
11768
  var COMPOSED_DEVICE_STABLE_ID_PREFIX = "composed-";
11588
11769
  /** Longest snippet a `code` source may carry (slice 4). */
@@ -11643,6 +11824,12 @@ var CompositionFieldSourceSchema = discriminatedUnion("kind", [
11643
11824
  "all"
11644
11825
  ]),
11645
11826
  reads: array(CompositionFieldReadSchema).min(1).max(64),
11827
+ /**
11828
+ * Set when the reads are an enum state, not a yes/no: the listed states
11829
+ * count as active (a cover is `open`). A state outside the list is inactive;
11830
+ * a read that is not a state at all is left out. Only `any` / `all` use it.
11831
+ */
11832
+ activeWhen: array(string().min(1)).min(1).optional(),
11646
11833
  /** `value` is the reading; the others are the member counts. */
11647
11834
  publish: _enum([
11648
11835
  "value",
@@ -11656,6 +11843,26 @@ var CompositionFieldSourceSchema = discriminatedUnion("kind", [
11656
11843
  "omit",
11657
11844
  "offline"
11658
11845
  ])
11846
+ }),
11847
+ object({
11848
+ kind: literal("series"),
11849
+ read: CompositionFieldReadSchema,
11850
+ /** `value` is the statistic or the integral. The others are the gap counts. */
11851
+ publish: _enum([
11852
+ "value",
11853
+ "included",
11854
+ "excluded",
11855
+ "total"
11856
+ ]),
11857
+ /**
11858
+ * What an unanswered `value` does. Counts ignore this. `offline` leaves the
11859
+ * device unseeded until history answers, so a restart cannot publish 0.
11860
+ */
11861
+ empty: _enum([
11862
+ "null",
11863
+ "omit",
11864
+ "offline"
11865
+ ])
11659
11866
  })
11660
11867
  ]);
11661
11868
  var CompositionCommandTargetSchema = discriminatedUnion("kind", [object({
@@ -16815,7 +17022,22 @@ var BrokerProviderInfoSchema = object({
16815
17022
  */
16816
17023
  interactiveConnectPath: string().min(1).optional(),
16817
17024
  /** Relative hub path to disconnect the linked account (same popup pattern). */
16818
- interactiveDisconnectPath: string().min(1).optional()
17025
+ interactiveDisconnectPath: string().min(1).optional(),
17026
+ /**
17027
+ * The kind signs in through a server-held interactive session instead of
17028
+ * (or before) typed credentials. `basePath` is a hub-relative route set
17029
+ * served by the owning addon (`/addon/<id>/...`) speaking the sign-in
17030
+ * contract: `POST {basePath}/start` (body: the form's settings) answers
17031
+ * `{ sessionId, loginUrl }`; `GET {basePath}/status?sessionId=` answers
17032
+ * `{ phase: 'starting' | 'awaiting-login' | 'captured' | 'error' |
17033
+ * 'cancelled', loginUrl, error }`; `POST {basePath}/commit`
17034
+ * (`{ sessionId, name, brokerId? }`) stores the credentials on a new or
17035
+ * existing broker and answers `{ brokerId }`; `POST {basePath}/cancel`
17036
+ * (`{ sessionId }`) drops the session. The dialog that edits a broker
17037
+ * offers it as the default path; the fields the session fills are
17038
+ * marked `filledBySignIn` in the kind's settings schema.
17039
+ */
17040
+ signIn: object({ basePath: string().min(1) }).optional()
16819
17041
  }))
16820
17042
  });
16821
17043
  var ListInputSchema = object({
@@ -17814,7 +18036,8 @@ var CompositionProblemSchema = object({
17814
18036
  "native-capability-replace",
17815
18037
  "mixed-quantity",
17816
18038
  "helper-mismatch",
17817
- "member-constraint"
18039
+ "member-constraint",
18040
+ "retention"
17818
18041
  ]),
17819
18042
  path: string(),
17820
18043
  message: string()
@@ -18048,13 +18271,17 @@ Object.freeze({
18048
18271
  latchedAt: {
18049
18272
  kind: "fixed",
18050
18273
  result: ["number", "null"]
18274
+ },
18275
+ schmitt: {
18276
+ kind: "fixed",
18277
+ result: ["boolean", "null"]
18051
18278
  }
18052
18279
  });
18053
18280
  /**
18054
18281
  * One catalog row per base reading a group helper can build (D944 §3).
18055
18282
  * Data, not a form default written into the block.
18056
18283
  */
18057
- var NOW = {
18284
+ var NOW$2 = {
18058
18285
  fieldPath: "lastFetchedAt",
18059
18286
  expr: "now"
18060
18287
  };
@@ -18068,6 +18295,8 @@ function numeric(input) {
18068
18295
  family: "numeric",
18069
18296
  deviceType: DeviceType.Sensor,
18070
18297
  memberDeviceType: DeviceType.Sensor,
18298
+ memberDeviceTypes: [DeviceType.Sensor],
18299
+ activeWhen: void 0,
18071
18300
  commandCaps: [],
18072
18301
  baseUnit: baseUnitOf(input.quantity),
18073
18302
  aggregates: NUMERIC_AGGREGATES,
@@ -18083,6 +18312,8 @@ function binary(input) {
18083
18312
  family: "binary",
18084
18313
  deviceType: DeviceType.Sensor,
18085
18314
  memberDeviceType: DeviceType.Sensor,
18315
+ memberDeviceTypes: [DeviceType.Sensor],
18316
+ activeWhen: void 0,
18086
18317
  commandCaps: [],
18087
18318
  quantity: "none",
18088
18319
  baseUnit: void 0,
@@ -18100,7 +18331,7 @@ var GROUP_TEMPLATES = [
18100
18331
  quantity: "temperature",
18101
18332
  defaultAggregate: "mean",
18102
18333
  empty: "null",
18103
- companions: [NOW]
18334
+ companions: [NOW$2]
18104
18335
  }),
18105
18336
  numeric({
18106
18337
  id: "humidity",
@@ -18111,7 +18342,7 @@ var GROUP_TEMPLATES = [
18111
18342
  quantity: "humidity",
18112
18343
  defaultAggregate: "mean",
18113
18344
  empty: "null",
18114
- companions: [NOW]
18345
+ companions: [NOW$2]
18115
18346
  }),
18116
18347
  numeric({
18117
18348
  id: "pressure",
@@ -18122,7 +18353,7 @@ var GROUP_TEMPLATES = [
18122
18353
  quantity: "pressure",
18123
18354
  defaultAggregate: "mean",
18124
18355
  empty: "null",
18125
- companions: [NOW]
18356
+ companions: [NOW$2]
18126
18357
  }),
18127
18358
  numeric({
18128
18359
  id: "illuminance",
@@ -18133,7 +18364,7 @@ var GROUP_TEMPLATES = [
18133
18364
  quantity: "illuminance",
18134
18365
  defaultAggregate: "mean",
18135
18366
  empty: "null",
18136
- companions: [NOW]
18367
+ companions: [NOW$2]
18137
18368
  }),
18138
18369
  numeric({
18139
18370
  id: "power",
@@ -18144,7 +18375,7 @@ var GROUP_TEMPLATES = [
18144
18375
  quantity: "power",
18145
18376
  defaultAggregate: "sum",
18146
18377
  empty: "omit",
18147
- companions: [NOW]
18378
+ companions: [NOW$2]
18148
18379
  }),
18149
18380
  numeric({
18150
18381
  id: "energy",
@@ -18155,7 +18386,7 @@ var GROUP_TEMPLATES = [
18155
18386
  quantity: "energy",
18156
18387
  defaultAggregate: "sum",
18157
18388
  empty: "omit",
18158
- companions: [NOW]
18389
+ companions: [NOW$2]
18159
18390
  }),
18160
18391
  numeric({
18161
18392
  id: "battery",
@@ -18190,7 +18421,7 @@ var GROUP_TEMPLATES = [
18190
18421
  quantity: "device",
18191
18422
  defaultAggregate: "mean",
18192
18423
  empty: "null",
18193
- companions: [NOW]
18424
+ companions: [NOW$2]
18194
18425
  }),
18195
18426
  binary({
18196
18427
  id: "motion",
@@ -18284,6 +18515,11 @@ var GROUP_TEMPLATES = [
18284
18515
  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.",
18285
18516
  deviceType: DeviceType.Switch,
18286
18517
  outputCap: "switch",
18518
+ outputField: "on",
18519
+ member: {
18520
+ cap: "switch",
18521
+ fieldPath: "on"
18522
+ },
18287
18523
  commandCaps: ["switch"]
18288
18524
  }),
18289
18525
  actuator({
@@ -18291,34 +18527,136 @@ var GROUP_TEMPLATES = [
18291
18527
  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.",
18292
18528
  deviceType: DeviceType.Light,
18293
18529
  outputCap: "switch",
18530
+ outputField: "on",
18531
+ member: {
18532
+ cap: "switch",
18533
+ fieldPath: "on"
18534
+ },
18294
18535
  commandCaps: [
18295
18536
  "switch",
18296
18537
  "brightness",
18297
18538
  "color"
18298
18539
  ]
18540
+ }),
18541
+ actuator({
18542
+ id: "fan",
18543
+ 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.",
18544
+ deviceType: DeviceType.Fan,
18545
+ outputCap: "switch",
18546
+ outputField: "on",
18547
+ member: {
18548
+ cap: "switch",
18549
+ fieldPath: "on"
18550
+ },
18551
+ commandCaps: ["switch", "fan-control"]
18552
+ }),
18553
+ actuator({
18554
+ id: "cover",
18555
+ 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.",
18556
+ deviceType: DeviceType.Cover,
18557
+ outputCap: "group-active",
18558
+ outputField: "active",
18559
+ member: {
18560
+ cap: "cover",
18561
+ fieldPath: "state"
18562
+ },
18563
+ activeWhen: [
18564
+ "open",
18565
+ "opening",
18566
+ "stopped"
18567
+ ],
18568
+ commandCaps: ["cover"]
18569
+ }),
18570
+ actuator({
18571
+ id: "valve",
18572
+ 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.",
18573
+ deviceType: DeviceType.Valve,
18574
+ outputCap: "group-active",
18575
+ outputField: "active",
18576
+ member: {
18577
+ cap: "valve",
18578
+ fieldPath: "state"
18579
+ },
18580
+ activeWhen: [
18581
+ "open",
18582
+ "opening",
18583
+ "stopped"
18584
+ ],
18585
+ commandCaps: ["valve"]
18586
+ }),
18587
+ actuator({
18588
+ id: "lock",
18589
+ 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.",
18590
+ deviceType: DeviceType.Lock,
18591
+ outputCap: "group-active",
18592
+ outputField: "active",
18593
+ member: {
18594
+ cap: "lock-control",
18595
+ fieldPath: "state"
18596
+ },
18597
+ activeWhen: ["locked"],
18598
+ commandCaps: ["lock-control"]
18599
+ }),
18600
+ actuator({
18601
+ id: "media-player",
18602
+ 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.",
18603
+ deviceType: DeviceType.MediaPlayer,
18604
+ outputCap: "group-active",
18605
+ outputField: "active",
18606
+ member: {
18607
+ cap: "media-player",
18608
+ fieldPath: "state"
18609
+ },
18610
+ activeWhen: ["playing", "buffering"],
18611
+ commandCaps: ["media-player"]
18612
+ }),
18613
+ actuator({
18614
+ id: "climate",
18615
+ 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.",
18616
+ deviceType: DeviceType.Thermostat,
18617
+ memberDeviceTypes: [DeviceType.Thermostat, DeviceType.Climate],
18618
+ outputCap: "group-active",
18619
+ outputField: "active",
18620
+ member: {
18621
+ cap: "climate-control",
18622
+ fieldPath: "mode"
18623
+ },
18624
+ activeWhen: [
18625
+ "heat",
18626
+ "cool",
18627
+ "auto",
18628
+ "heat_cool",
18629
+ "fan_only",
18630
+ "dry"
18631
+ ],
18632
+ commandCaps: ["climate-control"]
18299
18633
  })
18300
18634
  ];
18301
18635
  function actuator(input) {
18302
18636
  return {
18303
- ...input,
18637
+ id: input.id,
18638
+ summary: input.summary,
18639
+ deviceType: input.deviceType,
18640
+ outputCap: input.outputCap,
18641
+ outputField: input.outputField,
18642
+ commandCaps: input.commandCaps,
18304
18643
  family: "actuator",
18305
18644
  role: void 0,
18306
18645
  memberDeviceType: input.deviceType,
18307
- outputField: "on",
18646
+ memberDeviceTypes: input.memberDeviceTypes ?? [input.deviceType],
18647
+ activeWhen: input.activeWhen,
18308
18648
  quantity: "none",
18309
18649
  baseUnit: void 0,
18310
18650
  aggregates: BINARY_AGGREGATES,
18311
18651
  defaultAggregate: "any",
18312
18652
  empty: "offline",
18313
- accept: [{
18314
- cap: "switch",
18315
- fieldPath: "on"
18316
- }],
18653
+ accept: [input.member],
18317
18654
  companions: [CHANGED]
18318
18655
  };
18319
18656
  }
18320
18657
  new Map(GROUP_TEMPLATES.map((template) => [template.id, template]));
18321
18658
  DeviceFeature.LightColorRgb, DeviceFeature.LightColorHsv, DeviceFeature.LightColorMired;
18659
+ DeviceType.Camera;
18322
18660
  `${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
18323
18661
  /**
18324
18662
  * What a composition may BUILD on a device type (G2, D676): the caps a new
@@ -43333,7 +43671,7 @@ var NetworkAccessStatusSchema = object({
43333
43671
  });
43334
43672
  /**
43335
43673
  * Optional, richer endpoint shape returned by providers that expose
43336
- * MORE than one ingress concurrently (Tailscale Ingress with mixed
43674
+ * MORE than one ingress concurrently (Tailscale Funnel with mixed
43337
43675
  * serve+funnel rules, future ngrok multi-tunnel, …). Each entry carries
43338
43676
  * the originating provider config (mode + sourcePort) so the
43339
43677
  * orchestrator UI can label rows distinctly. Providers that expose only
@@ -45976,7 +46314,20 @@ var NcRuleInputSchema = object({
45976
46314
  * save by the hub's grouping guard). `.optional()`, never `.default()`: the addon cap
45977
46315
  * path does not run Zod defaults.
45978
46316
  */
45979
- groupingSec: number().int().min(5).max(60).optional()
46317
+ groupingSec: number().int().min(5).max(60).optional(),
46318
+ /**
46319
+ * ASK ME TO CONFIRM DETECTIONS (#243): a DETECTION notification of this rule
46320
+ * carries "Correct" / "Wrong" buttons (and, where the channel has room, a
46321
+ * "Wrong, it is a <class>" choice). A tap marks the track for retraining, the
46322
+ * same mark the Library writes, and records whose notification it was and
46323
+ * when. A channel with no buttons gets the same two choices as links.
46324
+ *
46325
+ * `.optional()`, never `.default()` (a Zod default does not run on the addon
46326
+ * cap path): absent and `false` both mean off, which is what every rule
46327
+ * authored before this field meant. An editor turns it off by writing
46328
+ * `false`, so it needs no `clear` key.
46329
+ */
46330
+ askVerdict: boolean().optional()
45980
46331
  });
45981
46332
  /**
45982
46333
  * Partial patch for `updateRule` — any subset of the input fields, plus the
@@ -56446,7 +56797,7 @@ var BatteryStatusSchema = object({
56446
56797
  */
56447
56798
  binary: boolean().optional().meta({ label: "Binary indicator" })
56448
56799
  });
56449
- DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat;
56800
+ DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.EventEmitter;
56450
56801
  method(object({
56451
56802
  deviceId: number(),
56452
56803
  /** Bound on the wait. Sensible range 3000–10000ms. */
@@ -58190,7 +58541,13 @@ results: array(object({
58190
58541
  /** Ms epoch of the attempt. */
58191
58542
  at: number()
58192
58543
  })) });
58193
- DeviceType.Switch, DeviceType.Light;
58544
+ DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Cover, DeviceType.Valve, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.Thermostat, DeviceType.Climate;
58545
+ object({
58546
+ active: boolean().meta({ label: "Active" }),
58547
+ /** Ms epoch when the slice was last updated. */
58548
+ lastChangedAt: number()
58549
+ });
58550
+ DeviceType.Cover, DeviceType.Valve, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.Climate, DeviceType.Thermostat;
58194
58551
  object({
58195
58552
  /** Members whose current value entered the aggregate. */
58196
58553
  included: number().int().nonnegative().meta(readingMeta("count", {
@@ -58208,7 +58565,7 @@ object({
58208
58565
  label: "Members"
58209
58566
  }))
58210
58567
  });
58211
- DeviceType.Sensor, DeviceType.Switch, DeviceType.Light;
58568
+ DeviceType.Sensor, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Cover, DeviceType.Valve, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.Thermostat, DeviceType.Climate;
58212
58569
  object({
58213
58570
  /** Radiator valve opening 0 (closed) .. 100 (open). Null = not yet known. */
58214
58571
  position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
@@ -59115,7 +59472,14 @@ DeviceType.Lock, method(object({
59115
59472
  auth: "protected"
59116
59473
  }), method(object({
59117
59474
  deviceId: number().int().nonnegative(),
59118
- code: string().min(1).optional()
59475
+ code: string().min(1).optional(),
59476
+ /**
59477
+ * Honoured by a helper lock GROUP only (D944): unlocking several doors
59478
+ * with one call is refused unless the caller says it was confirmed. A
59479
+ * single lock ignores it. The refusal lives in the callee, so no
59480
+ * automation or API caller reaches the doors by skipping a dialog.
59481
+ */
59482
+ confirm: boolean().optional()
59119
59483
  }), _void(), {
59120
59484
  kind: "mutation",
59121
59485
  auth: "protected"
@@ -59123,6 +59487,11 @@ DeviceType.Lock, method(object({
59123
59487
  kind: "mutation",
59124
59488
  auth: "protected"
59125
59489
  });
59490
+ object({
59491
+ value: number().nullable().meta(readingMeta("device", { label: "Total" })),
59492
+ lastFetchedAt: number()
59493
+ });
59494
+ DeviceType.Sensor;
59126
59495
  /**
59127
59496
  * Media-player cap. Models HA `media_player.*` (Sonos, Chromecast,
59128
59497
  * Apple TV, Spotify, Roku, generic OTT receivers, …) on
@@ -61030,9 +61399,9 @@ object({
61030
61399
  /** Cumulative energy in kilowatt-hours since the meter was reset. */
61031
61400
  kwhTotal: number().optional().meta(readingMeta("energy", { label: "Energy" })),
61032
61401
  /** Voltage in volts. */
61033
- volts: number().optional().meta(readingMeta("voltage")),
61402
+ volts: number().optional().meta(readingMeta("voltage", { label: "Voltage" })),
61034
61403
  /** Current in amperes. */
61035
- amps: number().optional().meta(readingMeta("current")),
61404
+ amps: number().optional().meta(readingMeta("current", { label: "Current" })),
61036
61405
  /** Apparent power in volt-amperes. */
61037
61406
  va: number().optional().meta(readingMeta("apparent-power")),
61038
61407
  /** Power factor (0..1) if reported. */
@@ -61040,7 +61409,23 @@ object({
61040
61409
  /** Ms epoch when the slice was last updated. */
61041
61410
  lastFetchedAt: number()
61042
61411
  });
61043
- DeviceType.Sensor;
61412
+ [
61413
+ DeviceType.Sensor,
61414
+ DeviceType.Switch,
61415
+ DeviceType.Light,
61416
+ DeviceType.Fan,
61417
+ DeviceType.Climate,
61418
+ DeviceType.Thermostat,
61419
+ DeviceType.Humidifier,
61420
+ DeviceType.WaterHeater,
61421
+ DeviceType.MediaPlayer,
61422
+ DeviceType.Washer,
61423
+ DeviceType.Dryer,
61424
+ DeviceType.Dishwasher,
61425
+ DeviceType.Vacuum,
61426
+ DeviceType.LawnMower,
61427
+ DeviceType.PetFeeder
61428
+ ].filter((type) => type !== DeviceType.Sensor);
61044
61429
  /**
61045
61430
  * Presence cap. Models HA `person.*` and `device_tracker.*` entities
61046
61431
  * on `DeviceType.Presence`. Read-only — no setters: presence is
@@ -61487,7 +61872,7 @@ object({
61487
61872
  phase: string().nullable()
61488
61873
  });
61489
61874
  Object.values(DeviceType);
61490
- DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
61875
+ DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
61491
61876
  DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch, method(object({ deviceId: number().int().nonnegative() }), object({ success: literal(true) }), {
61492
61877
  kind: "mutation",
61493
61878
  auth: "admin"
@@ -63526,7 +63911,7 @@ object({
63526
63911
  /** Ms epoch of the last state change. Useful for UI "X minutes ago". */
63527
63912
  lastChangedAt: number()
63528
63913
  });
63529
- DeviceType.Switch, DeviceType.Siren, DeviceType.Light, method(object({
63914
+ DeviceType.Switch, DeviceType.Siren, DeviceType.Light, DeviceType.Fan, method(object({
63530
63915
  deviceId: number(),
63531
63916
  on: boolean()
63532
63917
  }), _void(), {
@@ -65218,8 +65603,9 @@ method(object({}), array(TrainingBaseModelSchema).readonly(), { auth: "admin" })
65218
65603
  kind: "mutation",
65219
65604
  auth: "admin"
65220
65605
  });
65606
+ DeviceFeature.FanSpeed, DeviceFeature.FanPreset, DeviceFeature.FanDirection, DeviceFeature.FanOscillating, DeviceFeature.CoverPositionable, DeviceFeature.CoverTilt, DeviceFeature.ValvePositionable, DeviceFeature.MediaPlayerVolume, DeviceFeature.ClimateFanMode;
65221
65607
  SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
65222
- DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.Dishwasher, DeviceType.Camera, DeviceType.Camera, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
65608
+ DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.EventEmitter, DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer, DeviceType.Camera, DeviceType.Camera, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
65223
65609
  String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
65224
65610
  DeviceRole.BinarySensor, DeviceRole.MotionSensor;
65225
65611
  new Set(CAP_NAMES);
@@ -65272,7 +65658,7 @@ var AccessoryKind = {
65272
65658
  PrivacyMask: DeviceRole.PrivacyMask
65273
65659
  };
65274
65660
  AccessoryKind.Siren, AccessoryKind.Floodlight, AccessoryKind.Spotlight, AccessoryKind.PirSensor, AccessoryKind.Chime, AccessoryKind.Autotrack, AccessoryKind.Nightvision, AccessoryKind.PrivacyMask;
65275
- DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Camera, DeviceType.Hub, DeviceType.Switch, DeviceType.Siren, DeviceType.Light, DeviceType.Fan, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.Dishwasher;
65661
+ DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Camera, DeviceType.Hub, DeviceType.Switch, DeviceType.Siren, DeviceType.Light, DeviceType.Fan, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer;
65276
65662
  new Set(Object.values(DeviceType));
65277
65663
  Object.freeze({
65278
65664
  "accessories.getStatus": {
@@ -68495,6 +68881,13 @@ Object.freeze({
68495
68881
  access: "view",
68496
68882
  role: "viewer"
68497
68883
  },
68884
+ "groupActive.getStatus": {
68885
+ capName: "group-active",
68886
+ capScope: "device",
68887
+ addonId: null,
68888
+ access: "view",
68889
+ role: "viewer"
68890
+ },
68498
68891
  "groupCommands.getStatus": {
68499
68892
  capName: "group-commands",
68500
68893
  capScope: "device",
@@ -69461,6 +69854,13 @@ Object.freeze({
69461
69854
  access: "create",
69462
69855
  role: "admin"
69463
69856
  },
69857
+ "meter.getStatus": {
69858
+ capName: "meter",
69859
+ capScope: "device",
69860
+ addonId: null,
69861
+ access: "view",
69862
+ role: "viewer"
69863
+ },
69464
69864
  "metricsProvider.collectSnapshot": {
69465
69865
  capName: "metrics-provider",
69466
69866
  capScope: "system",
@@ -77559,7 +77959,39 @@ var APPLIANCE_CAP_VOCABULARY = {
77559
77959
  phrase: t("When {device} finishes", "Quando {device} finisce"),
77560
77960
  icon: "square"
77561
77961
  }
77562
- }
77962
+ },
77963
+ overrides: { byType: {
77964
+ [DeviceType.Washer]: {
77965
+ state: { running: {
77966
+ whenTrue: t("When the washing machine starts", "Quando la lavatrice inizia"),
77967
+ whenFalse: t("When the washing machine has finished", "Quando la lavatrice ha finito")
77968
+ } },
77969
+ events: {
77970
+ onStarted: { phrase: t("When the washing machine starts", "Quando la lavatrice inizia") },
77971
+ onFinished: { phrase: t("When the washing machine has finished", "Quando la lavatrice ha finito") }
77972
+ }
77973
+ },
77974
+ [DeviceType.Dryer]: {
77975
+ state: { running: {
77976
+ whenTrue: t("When the dryer starts", "Quando l'asciugatrice inizia"),
77977
+ whenFalse: t("When the dryer has finished", "Quando l'asciugatrice ha finito")
77978
+ } },
77979
+ events: {
77980
+ onStarted: { phrase: t("When the dryer starts", "Quando l'asciugatrice inizia") },
77981
+ onFinished: { phrase: t("When the dryer has finished", "Quando l'asciugatrice ha finito") }
77982
+ }
77983
+ },
77984
+ [DeviceType.Dishwasher]: {
77985
+ state: { running: {
77986
+ whenTrue: t("When the dishwasher starts", "Quando la lavastoviglie inizia"),
77987
+ whenFalse: t("When the dishwasher has finished", "Quando la lavastoviglie ha finito")
77988
+ } },
77989
+ events: {
77990
+ onStarted: { phrase: t("When the dishwasher starts", "Quando la lavastoviglie inizia") },
77991
+ onFinished: { phrase: t("When the dishwasher has finished", "Quando la lavastoviglie ha finito") }
77992
+ }
77993
+ }
77994
+ } }
77563
77995
  },
77564
77996
  update: {
77565
77997
  scope: "device",
@@ -78331,6 +78763,10 @@ var SENSOR_CAP_VOCABULARY = {
78331
78763
  icon: "flame"
78332
78764
  }]
78333
78765
  },
78766
+ "group-active": {
78767
+ scope: "device",
78768
+ noun: t("Group state", "Stato del gruppo")
78769
+ },
78334
78770
  "group-commands": {
78335
78771
  scope: "device",
78336
78772
  noun: t("Group command", "Comando di gruppo")
@@ -78387,6 +78823,17 @@ var SENSOR_CAP_VOCABULARY = {
78387
78823
  }],
78388
78824
  events: { onMotionChanged: { notOperatorFacing: "the `detected` state trigger phrases both edges, from the mirror that survives a dropped event (D49)" } }
78389
78825
  },
78826
+ meter: {
78827
+ scope: "device",
78828
+ noun: t("Meter", "Contatore"),
78829
+ state: [{
78830
+ kind: "numeric",
78831
+ field: "value",
78832
+ quantity: t("the total", "il totale"),
78833
+ label: t("Total", "Totale"),
78834
+ icon: "gauge"
78835
+ }]
78836
+ },
78390
78837
  "numeric-sensor": {
78391
78838
  scope: "device",
78392
78839
  noun: t("Sensor", "Sensore"),
@@ -78859,8 +79306,47 @@ function projectAction(cap, action) {
78859
79306
  };
78860
79307
  }
78861
79308
  Object.entries(CAP_VOCABULARY_BY_NAME).flatMap(([cap, entry]) => entry.scope === "device" ? (entry.actions ?? []).map((a) => projectAction(cap, a)) : []);
78862
- 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;
79309
+ 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;
78863
79310
  DeviceFeature.BatteryOperated;
79311
+ DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher;
79312
+ var HA_AS = "a power sensor (device_class power). Home Assistant has no laundry domain. running-state stays unexported until a null reading can be published as unavailable.";
79313
+ var HOMEKIT_REASON = "HomeKit has no laundry-appliance service. The export tab would pair an accessory with nothing on it: running-state is withheld until a null reading can be unavailable, and power is not a HomeKit service this export honours.";
79314
+ var ALEXA_REASON = "Alexa has no laundry category in this export, and neither power nor running has an Alexa interface.";
79315
+ var GOOGLE_REASON = "Google WASHER, DRYER and DISHWASHER require RunCycle. A power threshold is not that trait, and this export does not publish RunCycle.";
79316
+ var MATTER_REASON = "No Matter export is built. The closest device types are Laundry Washer (0x0073) and Laundry Dryer (0x0074); a power threshold is not the Laundry Washer Mode cluster.";
79317
+ function withheld(reason) {
79318
+ return {
79319
+ [DeviceType.Washer]: {
79320
+ exported: false,
79321
+ reason
79322
+ },
79323
+ [DeviceType.Dryer]: {
79324
+ exported: false,
79325
+ reason
79326
+ },
79327
+ [DeviceType.Dishwasher]: {
79328
+ exported: false,
79329
+ reason
79330
+ }
79331
+ };
79332
+ }
79333
+ function offered(received) {
79334
+ return {
79335
+ [DeviceType.Washer]: {
79336
+ exported: true,
79337
+ as: received
79338
+ },
79339
+ [DeviceType.Dryer]: {
79340
+ exported: true,
79341
+ as: received
79342
+ },
79343
+ [DeviceType.Dishwasher]: {
79344
+ exported: true,
79345
+ as: received
79346
+ }
79347
+ };
79348
+ }
79349
+ offered(HA_AS), withheld(HOMEKIT_REASON), withheld(ALEXA_REASON), withheld(GOOGLE_REASON), withheld(MATTER_REASON);
78864
79350
  Object.freeze({
78865
79351
  "accessories.getStatus": [{
78866
79352
  name: "deviceId",
@@ -79827,6 +80313,11 @@ Object.freeze({
79827
80313
  form: "single",
79828
80314
  optional: false
79829
80315
  }],
80316
+ "groupActive.getStatus": [{
80317
+ name: "deviceId",
80318
+ form: "single",
80319
+ optional: false
80320
+ }],
79830
80321
  "groupCommands.getStatus": [{
79831
80322
  name: "deviceId",
79832
80323
  form: "single",
@@ -80037,6 +80528,11 @@ Object.freeze({
80037
80528
  form: "single",
80038
80529
  optional: false
80039
80530
  }],
80531
+ "meter.getStatus": [{
80532
+ name: "deviceId",
80533
+ form: "single",
80534
+ optional: false
80535
+ }],
80040
80536
  "motion.getStatus": [{
80041
80537
  name: "deviceId",
80042
80538
  form: "single",
@@ -81644,7 +82140,6 @@ Object.freeze({
81644
82140
  "network-access": "ingress",
81645
82141
  "smtp-provider": "email"
81646
82142
  });
81647
- DeviceType.Camera;
81648
82143
  /**
81649
82144
  * A saved Customize assignment (D936). The schema is the type: callers use
81650
82145
  * `z.infer`, they do not restate the shape.