@camstack/addon-provider-homematic 1.2.153 → 1.2.154

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.
Files changed (3) hide show
  1. package/dist/addon.js +193 -117
  2. package/dist/addon.mjs +193 -117
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -5573,7 +5573,7 @@ var ZodIssueCode = {
5573
5573
  var ZodFirstPartyTypeKind;
5574
5574
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5575
5575
  //#endregion
5576
- //#region ../types/dist/sleep-DJFUfKvA.mjs
5576
+ //#region ../types/dist/sleep-CUp20JkO.mjs
5577
5577
  /**
5578
5578
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5579
5579
  * window to float samples (D455).
@@ -8653,7 +8653,11 @@ var ContributionSectionSchema = object({
8653
8653
  literal(4)
8654
8654
  ]).optional(),
8655
8655
  tab: string().optional(),
8656
- location: _enum(["settings", "top-tab"]).optional(),
8656
+ location: _enum([
8657
+ "settings",
8658
+ "top-tab",
8659
+ "hero"
8660
+ ]).optional(),
8657
8661
  order: number().optional(),
8658
8662
  fields: array(any())
8659
8663
  });
@@ -13586,7 +13590,11 @@ var ConfigSectionWithValuesSchema = object({
13586
13590
  literal(4)
13587
13591
  ]).optional(),
13588
13592
  tab: string().optional(),
13589
- location: _enum(["settings", "top-tab"]).optional(),
13593
+ location: _enum([
13594
+ "settings",
13595
+ "top-tab",
13596
+ "hero"
13597
+ ]).optional(),
13590
13598
  order: number().optional(),
13591
13599
  fields: array(any())
13592
13600
  });
@@ -17515,6 +17523,52 @@ var TierStatusSchema = object({
17515
17523
  countedAt: number().nullable()
17516
17524
  });
17517
17525
  /** Operator/diagnostic view: rows per tier, last runs, refusals and drops since boot. */
17526
+ /**
17527
+ * Why a series is orphan. `device-gone`: its device is absent from the
17528
+ * successful device listings (the departure clock). `undeclared`: its `cap:`
17529
+ * key is declared by no capability any more (a field a cap removed).
17530
+ */
17531
+ var DeviceHistoryOrphanReasonSchema = _enum(["device-gone", "undeclared"]);
17532
+ /** Rows held per stored tier. */
17533
+ var TierRowsSchema = object({
17534
+ raw: number().int(),
17535
+ "5m": number().int(),
17536
+ "1h": number().int(),
17537
+ "1d": number().int()
17538
+ });
17539
+ var OrphanSeriesSchema = object({
17540
+ seriesId: number().int(),
17541
+ deviceId: number().int(),
17542
+ key: string(),
17543
+ scope: string(),
17544
+ /** The metric's display name; `null` when its metric row is gone too. */
17545
+ displayName: string().nullable(),
17546
+ reason: DeviceHistoryOrphanReasonSchema,
17547
+ /** `device-gone`: since when the device has been absent; `null` otherwise. */
17548
+ missingSince: number().nullable(),
17549
+ firstTs: number(),
17550
+ lastTs: number(),
17551
+ rows: TierRowsSchema
17552
+ });
17553
+ var DeviceHistoryOrphanDeleteRefusalSchema = _enum([
17554
+ "not-found",
17555
+ "not-orphan",
17556
+ "failed"
17557
+ ]);
17558
+ var OrphanDeleteEntrySchema = discriminatedUnion("ok", [object({
17559
+ seriesId: number().int(),
17560
+ ok: literal(true),
17561
+ deleted: TierRowsSchema
17562
+ }), object({
17563
+ seriesId: number().int(),
17564
+ ok: literal(false),
17565
+ reason: DeviceHistoryOrphanDeleteRefusalSchema
17566
+ })]);
17567
+ var OrphanListSchema = object({
17568
+ series: array(OrphanSeriesSchema).readonly(),
17569
+ /** More orphans exist than {@link DEVICE_HISTORY_ORPHAN_LIST_MAX}. */
17570
+ truncated: boolean()
17571
+ });
17518
17572
  var DeviceHistoryStatusSchema = object({
17519
17573
  startedAt: number(),
17520
17574
  /** The store is declared, series loaded and the first reconcile has answered. */
@@ -17612,7 +17666,10 @@ method(object({ deviceId: number().int() }), array(SeriesInfoSchema).readonly())
17612
17666
  }), object({ enabled: boolean() }), {
17613
17667
  kind: "mutation",
17614
17668
  auth: "admin"
17615
- }), method(object({}), DeviceHistoryStatusSchema, { auth: "admin" });
17669
+ }), method(object({}), DeviceHistoryStatusSchema, { auth: "admin" }), method(object({}), OrphanListSchema, { auth: "admin" }), method(object({ seriesIds: array(number().int()).min(1).max(50) }), object({ results: array(OrphanDeleteEntrySchema).readonly() }), {
17670
+ kind: "mutation",
17671
+ auth: "admin"
17672
+ });
17616
17673
  var DeviceCaStatusSchema = discriminatedUnion("state", [
17617
17674
  object({ state: literal("absent") }),
17618
17675
  object({
@@ -55585,17 +55642,69 @@ var connectivityCapability = {
55585
55642
  volatileStateFields: ["lastChangedAt"]
55586
55643
  };
55587
55644
  /**
55588
- * Generic device-consumables capability — surfaces a device's
55589
- * maintenance items (vacuum filters/brushes, replaceable cartridges,
55590
- * descaling cycles, …) with their remaining life and an optional
55591
- * "Replaced" reset action. Device-agnostic: any provider that knows its
55592
- * device tracks consumables can register it; the cap declares no
55593
- * vocabulary of its own — the provider names each item verbatim.
55645
+ * Generic device-consumables capability — the ONE place a device reports what
55646
+ * it uses up or fills: wear parts (vacuum filters/brushes, cartridges,
55647
+ * descaling cycles), supplies it draws from (a vacuum's clean-water tank and
55648
+ * detergent, a dishwasher's salt and rinse aid) and waste it collects (a dirty
55649
+ * water tank, a dust bin). Each item carries its remaining life or fill and an
55650
+ * optional "Replaced" reset action. Device-agnostic: any provider that knows
55651
+ * its device tracks consumables registers it; the provider names each item
55652
+ * verbatim and says which `kind` it is.
55653
+ *
55654
+ * The admin UI renders it as ONE collapsible section directly under the
55655
+ * device page's hero card (`placement: 'hero'`), for every device bound to
55656
+ * this cap — never drawn by a device type's hero card itself (D915).
55594
55657
  *
55595
55658
  * Like `childLayout`, the cap is INERT until a provider sets items: no
55596
55659
  * provider populates it by guessing (no HA inference). The UI renders a
55597
55660
  * "No consumables reported" placeholder when `items` is empty.
55598
55661
  */
55662
+ /**
55663
+ * What an item IS, which decides which direction is bad:
55664
+ * - `wear` — a part that wears out (a brush, a filter); low life is bad.
55665
+ * - `supply` — something the device draws from (clean water, detergent,
55666
+ * salt, rinse aid); low or empty is bad.
55667
+ * - `waste` — something the device fills (dirty water, a dust bin); full is
55668
+ * bad.
55669
+ * Absent = `wear`.
55670
+ */
55671
+ var ConsumableKindSchema = _enum([
55672
+ "wear",
55673
+ "supply",
55674
+ "waste"
55675
+ ]);
55676
+ /**
55677
+ * What an item LOOKS like, which decides how a client draws it — independent
55678
+ * of `kind`, which decides which direction is bad:
55679
+ * - `part` — a part that wears (a brush, a filter, a mop pad): a wear bar,
55680
+ * remaining time and a reset.
55681
+ * - `tank` — a container of liquid (clean water, dirty water): a fill gauge.
55682
+ * - `product` — something bought and refilled (detergent, salt, rinse aid):
55683
+ * a stepped level and "refill".
55684
+ * - `bin` — a container that collects waste (a dust bin): a fill gauge
55685
+ * that warns when full.
55686
+ * Absent = derived from the kind ({@link consumableFormOf}).
55687
+ */
55688
+ var ConsumableFormSchema = _enum([
55689
+ "part",
55690
+ "tank",
55691
+ "product",
55692
+ "bin"
55693
+ ]);
55694
+ /** The provider's own discrete verdict on an item. */
55695
+ var ConsumableStatusSchema = _enum([
55696
+ "ok",
55697
+ "low",
55698
+ "empty",
55699
+ "full",
55700
+ "replace"
55701
+ ]);
55702
+ _enum([
55703
+ "ok",
55704
+ "low",
55705
+ "empty",
55706
+ "full"
55707
+ ]);
55599
55708
  /** Units a remaining-life counter is reported in. Closed: the panel renders
55600
55709
  * each. */
55601
55710
  var ConsumableRemainingUnitSchema = _enum([
@@ -55610,18 +55719,23 @@ var ConsumableRemainingSchema = object({
55610
55719
  unit: ConsumableRemainingUnitSchema
55611
55720
  });
55612
55721
  /** A single consumable item. Either a continuous `level` (remaining
55613
- * life %) or a discrete `status` may be known — both may be null when a
55614
- * provider only knows the item exists. `level` and `status` are not
55615
- * mutually exclusive; a provider may report both. */
55722
+ * life %, or fill % for a `supply` / `waste` item) or a discrete `status`
55723
+ * may be known — both may be null when a provider only knows the item
55724
+ * exists. `level` and `status` are not mutually exclusive; a provider may
55725
+ * report both. */
55616
55726
  var ConsumableItemSchema = object({
55617
55727
  /** Stable id, e.g. 'main-brush'. */
55618
55728
  key: string().min(1),
55619
55729
  /** Display name. */
55620
55730
  label: string().min(1),
55621
- /** Remaining life % when known (0..100). */
55731
+ /** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
55622
55732
  level: number().min(0).max(100).nullable(),
55623
- /** Discrete state when known (binary mode). */
55624
- status: _enum(["ok", "replace"]).nullable(),
55733
+ /** The provider's discrete verdict when known (binary mode). */
55734
+ status: ConsumableStatusSchema.nullable(),
55735
+ /** What the item is — decides whether low or full is bad. Absent = `wear`. */
55736
+ kind: ConsumableKindSchema.optional(),
55737
+ /** How the item is drawn (part, tank, product, bin). Absent = derived from `kind`. */
55738
+ form: ConsumableFormSchema.optional(),
55625
55739
  /** Ms epoch of the last replace, when known. */
55626
55740
  lastResetAt: number().nullable(),
55627
55741
  /** Whether `reset()` is meaningful for this item. */
@@ -55644,7 +55758,7 @@ var consumablesCapability = {
55644
55758
  kind: "widget",
55645
55759
  widgetId: "host/consumables-panel",
55646
55760
  tab: "consumables",
55647
- topTab: true,
55761
+ placement: "hero",
55648
55762
  label: "Consumables",
55649
55763
  order: 5
55650
55764
  } },
@@ -55705,9 +55819,37 @@ reset: method(object({
55705
55819
  */
55706
55820
  durability: "restored",
55707
55821
  /**
55708
- * History (D850): none — `items` is an array keyed by runtime ids; a history path never enters it.
55822
+ * History (D850, D917): one series per (item field, item `key`) — the item key
55823
+ * is the series scope, the item `label` names it. A vacuum tank's fill, a
55824
+ * brush's remaining life and a dishwasher's salt are each recorded the moment
55825
+ * their provider reports them; an item that appears later gets its series.
55709
55826
  */
55710
- history: "none",
55827
+ history: {
55828
+ fields: {},
55829
+ items: {
55830
+ path: "items",
55831
+ key: "key",
55832
+ label: "label",
55833
+ fields: {
55834
+ level: {
55835
+ kind: "gauge",
55836
+ unit: "%",
55837
+ deadband: 2,
55838
+ displayName: "Level"
55839
+ },
55840
+ status: {
55841
+ kind: "enum",
55842
+ displayName: "Status"
55843
+ },
55844
+ "remaining.value": {
55845
+ kind: "gauge",
55846
+ unitFrom: "remaining.unit",
55847
+ deadband: 1,
55848
+ displayName: "Remaining"
55849
+ }
55850
+ }
55851
+ }
55852
+ },
55711
55853
  /** Clocks, not content: a re-read that changed no item costs no commit. */
55712
55854
  volatileStateFields: ["lastChangedAt", "lastFetchedAt"]
55713
55855
  };
@@ -56122,8 +56264,9 @@ onStatusChanged: { data: object({
56122
56264
  volatileStateFields: ["lastChangedAt"]
56123
56265
  };
56124
56266
  /**
56125
- * Smart-dishwasher cap — program lifecycle, door / remote-start gates,
56126
- * consumable levels (salt, rinse aid) and common program options.
56267
+ * Smart-dishwasher cap — program lifecycle, door / remote-start gates and
56268
+ * common program options. Salt and rinse aid are NOT here: they are items of
56269
+ * the device's `consumables` cap, like every other device's (D915).
56127
56270
  *
56128
56271
  * Sources: native Bosch Home Connect (`dishwasher` device type). Reusable
56129
56272
  * by any integration that exposes the same program / option surface.
@@ -56171,11 +56314,6 @@ var DishwasherAvailabilitySchema = _enum([
56171
56314
  "offline",
56172
56315
  "description-missing"
56173
56316
  ]);
56174
- var DishwasherConsumableLevelSchema = _enum([
56175
- "ok",
56176
- "low",
56177
- "empty"
56178
- ]);
56179
56317
  var DishwasherStatusSchema = object({
56180
56318
  availability: DishwasherAvailabilitySchema,
56181
56319
  /** Coarse state for compact surfaces; `unavailable` whenever the appliance state is not known. */
@@ -56208,8 +56346,6 @@ var DishwasherStatusSchema = object({
56208
56346
  powerOn: boolean().nullable(),
56209
56347
  /** The raw power state (`On`, `Off`, `Standby`, …); null when not known. */
56210
56348
  powerState: string().nullable(),
56211
- saltLevel: DishwasherConsumableLevelSchema.nullable(),
56212
- rinseAidLevel: DishwasherConsumableLevelSchema.nullable(),
56213
56349
  /**
56214
56350
  * True while the appliance asks for its filter to be cleaned (smart-filter, filter-system or
56215
56351
  * combined care-and-filter reminder raised); false when every such reminder reads clear; null
@@ -65025,60 +65161,17 @@ method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserI
65025
65161
  auth: "admin",
65026
65162
  access: "delete"
65027
65163
  });
65028
- /**
65029
- * Robot-vacuum cap. Models HA `vacuum.*` entities — anything with a
65030
- * cleaning lifecycle plus a return-to-base / locate surface and an
65031
- * optional fan-speed selector.
65032
- *
65033
- * State follows HA's canonical vacuum lifecycle: `idle` / `cleaning` /
65034
- * `paused` / `returning` / `docked` / `error`. `batteryLevel`
65035
- * (0..100) is nullable — some vacuums don't report a battery
65036
- * percentage. `fanSpeed` is the current speed token (provider-verbatim,
65037
- * e.g. `'standard'` / `'turbo'`) and `availableFanSpeeds` lists the
65038
- * tokens the hardware accepts so the UI renders only supported choices.
65039
- *
65040
- * The `setFanSpeed` method takes the bare `speed` token — the provider
65041
- * validates it against the vacuum's own list. `locate` triggers the
65042
- * find-me chirp; `returnToBase` sends it home.
65043
- *
65044
- * Consumable / waste tanks: `cleanWater` / `dirtyWater` / `detergent` /
65045
- * `dustBin` each carry a nullable `{ level (0..100 %), status ('ok' |
65046
- * 'low' | 'full') }` reading. Native providers (e.g. Dreame, Roborock)
65047
- * SHOULD populate whichever tanks the hardware has — leave a field `null`
65048
- * only when the device has no such tank at all, and use a `TankStatus`
65049
- * with both inner fields `null` when the tank exists but its level is
65050
- * currently unknown. HA `vacuum.*` entities expose no per-tank telemetry,
65051
- * so the HA provider leaves all four `null`.
65052
- */
65053
- var VacuumStateSchema = _enum([
65054
- "idle",
65055
- "cleaning",
65056
- "paused",
65057
- "returning",
65058
- "docked",
65059
- "drying",
65060
- "error"
65061
- ]);
65062
- /**
65063
- * One consumable / waste tank on a robot vacuum (clean-water, dirty-water,
65064
- * detergent or dust-bin). A tank can report a numeric fill `level` (0..100),
65065
- * a discrete `status` (binary-style hardware), or both. Both `null` means the
65066
- * level is currently unknown; the OWNING field being `null` means the
65067
- * hardware has no such tank at all.
65068
- */
65069
- var TankStatusSchema = object({
65070
- /** Numeric fill 0..100 when the hardware reports a percentage; null otherwise. */
65071
- level: number().min(0).max(100).nullable(),
65072
- /** Discrete state when the hardware is binary-mode; null otherwise. */
65073
- status: _enum([
65074
- "ok",
65075
- "low",
65076
- "full"
65077
- ]).nullable()
65078
- });
65079
65164
  var VacuumControlStatusSchema = object({
65080
65165
  /** Lifecycle state of the vacuum. */
65081
- state: VacuumStateSchema,
65166
+ state: _enum([
65167
+ "idle",
65168
+ "cleaning",
65169
+ "paused",
65170
+ "returning",
65171
+ "docked",
65172
+ "drying",
65173
+ "error"
65174
+ ]),
65082
65175
  /** 0..100 battery percentage. Null when the device has no battery
65083
65176
  * reading. */
65084
65177
  batteryLevel: number().min(0).max(100).nullable(),
@@ -65087,14 +65180,6 @@ var VacuumControlStatusSchema = object({
65087
65180
  fanSpeed: string().nullable(),
65088
65181
  /** Speed tokens the hardware accepts — drives the UI selector. */
65089
65182
  availableFanSpeeds: array(string()),
65090
- /** Clean-water (mop) tank. Null when the hardware has no clean-water tank. */
65091
- cleanWater: TankStatusSchema.nullable(),
65092
- /** Dirty-water (recovery) tank. Null when the hardware has no dirty-water tank. */
65093
- dirtyWater: TankStatusSchema.nullable(),
65094
- /** Detergent tank. Null when the hardware has no detergent tank. */
65095
- detergent: TankStatusSchema.nullable(),
65096
- /** Dust bin. Null when the hardware has no dust bin. */
65097
- dustBin: TankStatusSchema.nullable(),
65098
65183
  /** 0..100 cleaning-completion percentage of the current task, or null. */
65099
65184
  progressPercent: number().min(0).max(100).nullable(),
65100
65185
  /** Current error code (0 / null = no error). */
@@ -65156,35 +65241,14 @@ var vacuumControlCapability = {
65156
65241
  */
65157
65242
  durability: "session",
65158
65243
  /**
65159
- * History (D850): recorded series. Tank levels are fixed-object paths (`cleanWater.level`, ...).
65244
+ * History (D850): recorded series. The tanks moved to `consumables` (D915), whose
65245
+ * items are keyed by runtime ids and record no history.
65160
65246
  */
65161
- history: { fields: {
65162
- batteryLevel: {
65163
- kind: "gauge",
65164
- unit: "%",
65165
- deadband: 2
65166
- },
65167
- "cleanWater.level": {
65168
- kind: "gauge",
65169
- unit: "%",
65170
- deadband: 2
65171
- },
65172
- "dirtyWater.level": {
65173
- kind: "gauge",
65174
- unit: "%",
65175
- deadband: 2
65176
- },
65177
- "detergent.level": {
65178
- kind: "gauge",
65179
- unit: "%",
65180
- deadband: 2
65181
- },
65182
- "dustBin.level": {
65183
- kind: "gauge",
65184
- unit: "%",
65185
- deadband: 2
65186
- }
65187
- } }
65247
+ history: { fields: { batteryLevel: {
65248
+ kind: "gauge",
65249
+ unit: "%",
65250
+ deadband: 2
65251
+ } } }
65188
65252
  };
65189
65253
  var ValveStatusSchema = object({
65190
65254
  /** Lifecycle state of the valve. */
@@ -69578,6 +69642,12 @@ Object.freeze({
69578
69642
  addonId: null,
69579
69643
  access: "create"
69580
69644
  },
69645
+ "deviceHistory.deleteOrphanSeries": {
69646
+ capName: "device-history",
69647
+ capScope: "system",
69648
+ addonId: null,
69649
+ access: "delete"
69650
+ },
69581
69651
  "deviceHistory.getDeviceEnabled": {
69582
69652
  capName: "device-history",
69583
69653
  capScope: "system",
@@ -69596,6 +69666,12 @@ Object.freeze({
69596
69666
  addonId: null,
69597
69667
  access: "view"
69598
69668
  },
69669
+ "deviceHistory.listOrphanSeries": {
69670
+ capName: "device-history",
69671
+ capScope: "system",
69672
+ addonId: null,
69673
+ access: "view"
69674
+ },
69599
69675
  "deviceHistory.listSeries": {
69600
69676
  capName: "device-history",
69601
69677
  capScope: "system",
@@ -79601,7 +79677,7 @@ var STATE_SUMMARY_VARS = [
79601
79677
  ([...RULE_TEXT], [...COMBINED_ALARM]),
79602
79678
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
79603
79679
  ([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
79604
- ([...RULE_TEXT], [...CONSUMABLE]),
79680
+ ([...RULE_TEXT], [...CONSUMABLE, ...TANK]),
79605
79681
  ([...RULE_TEXT], [...TANK]),
79606
79682
  [...RULE_TEXT],
79607
79683
  ([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
package/dist/addon.mjs CHANGED
@@ -5574,7 +5574,7 @@ var ZodIssueCode = {
5574
5574
  var ZodFirstPartyTypeKind;
5575
5575
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5576
5576
  //#endregion
5577
- //#region ../types/dist/sleep-DJFUfKvA.mjs
5577
+ //#region ../types/dist/sleep-CUp20JkO.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).
@@ -8654,7 +8654,11 @@ var ContributionSectionSchema = object({
8654
8654
  literal(4)
8655
8655
  ]).optional(),
8656
8656
  tab: string().optional(),
8657
- location: _enum(["settings", "top-tab"]).optional(),
8657
+ location: _enum([
8658
+ "settings",
8659
+ "top-tab",
8660
+ "hero"
8661
+ ]).optional(),
8658
8662
  order: number().optional(),
8659
8663
  fields: array(any())
8660
8664
  });
@@ -13587,7 +13591,11 @@ var ConfigSectionWithValuesSchema = object({
13587
13591
  literal(4)
13588
13592
  ]).optional(),
13589
13593
  tab: string().optional(),
13590
- location: _enum(["settings", "top-tab"]).optional(),
13594
+ location: _enum([
13595
+ "settings",
13596
+ "top-tab",
13597
+ "hero"
13598
+ ]).optional(),
13591
13599
  order: number().optional(),
13592
13600
  fields: array(any())
13593
13601
  });
@@ -17516,6 +17524,52 @@ var TierStatusSchema = object({
17516
17524
  countedAt: number().nullable()
17517
17525
  });
17518
17526
  /** Operator/diagnostic view: rows per tier, last runs, refusals and drops since boot. */
17527
+ /**
17528
+ * Why a series is orphan. `device-gone`: its device is absent from the
17529
+ * successful device listings (the departure clock). `undeclared`: its `cap:`
17530
+ * key is declared by no capability any more (a field a cap removed).
17531
+ */
17532
+ var DeviceHistoryOrphanReasonSchema = _enum(["device-gone", "undeclared"]);
17533
+ /** Rows held per stored tier. */
17534
+ var TierRowsSchema = object({
17535
+ raw: number().int(),
17536
+ "5m": number().int(),
17537
+ "1h": number().int(),
17538
+ "1d": number().int()
17539
+ });
17540
+ var OrphanSeriesSchema = object({
17541
+ seriesId: number().int(),
17542
+ deviceId: number().int(),
17543
+ key: string(),
17544
+ scope: string(),
17545
+ /** The metric's display name; `null` when its metric row is gone too. */
17546
+ displayName: string().nullable(),
17547
+ reason: DeviceHistoryOrphanReasonSchema,
17548
+ /** `device-gone`: since when the device has been absent; `null` otherwise. */
17549
+ missingSince: number().nullable(),
17550
+ firstTs: number(),
17551
+ lastTs: number(),
17552
+ rows: TierRowsSchema
17553
+ });
17554
+ var DeviceHistoryOrphanDeleteRefusalSchema = _enum([
17555
+ "not-found",
17556
+ "not-orphan",
17557
+ "failed"
17558
+ ]);
17559
+ var OrphanDeleteEntrySchema = discriminatedUnion("ok", [object({
17560
+ seriesId: number().int(),
17561
+ ok: literal(true),
17562
+ deleted: TierRowsSchema
17563
+ }), object({
17564
+ seriesId: number().int(),
17565
+ ok: literal(false),
17566
+ reason: DeviceHistoryOrphanDeleteRefusalSchema
17567
+ })]);
17568
+ var OrphanListSchema = object({
17569
+ series: array(OrphanSeriesSchema).readonly(),
17570
+ /** More orphans exist than {@link DEVICE_HISTORY_ORPHAN_LIST_MAX}. */
17571
+ truncated: boolean()
17572
+ });
17519
17573
  var DeviceHistoryStatusSchema = object({
17520
17574
  startedAt: number(),
17521
17575
  /** The store is declared, series loaded and the first reconcile has answered. */
@@ -17613,7 +17667,10 @@ method(object({ deviceId: number().int() }), array(SeriesInfoSchema).readonly())
17613
17667
  }), object({ enabled: boolean() }), {
17614
17668
  kind: "mutation",
17615
17669
  auth: "admin"
17616
- }), method(object({}), DeviceHistoryStatusSchema, { auth: "admin" });
17670
+ }), method(object({}), DeviceHistoryStatusSchema, { auth: "admin" }), method(object({}), OrphanListSchema, { auth: "admin" }), method(object({ seriesIds: array(number().int()).min(1).max(50) }), object({ results: array(OrphanDeleteEntrySchema).readonly() }), {
17671
+ kind: "mutation",
17672
+ auth: "admin"
17673
+ });
17617
17674
  var DeviceCaStatusSchema = discriminatedUnion("state", [
17618
17675
  object({ state: literal("absent") }),
17619
17676
  object({
@@ -55586,17 +55643,69 @@ var connectivityCapability = {
55586
55643
  volatileStateFields: ["lastChangedAt"]
55587
55644
  };
55588
55645
  /**
55589
- * Generic device-consumables capability — surfaces a device's
55590
- * maintenance items (vacuum filters/brushes, replaceable cartridges,
55591
- * descaling cycles, …) with their remaining life and an optional
55592
- * "Replaced" reset action. Device-agnostic: any provider that knows its
55593
- * device tracks consumables can register it; the cap declares no
55594
- * vocabulary of its own — the provider names each item verbatim.
55646
+ * Generic device-consumables capability — the ONE place a device reports what
55647
+ * it uses up or fills: wear parts (vacuum filters/brushes, cartridges,
55648
+ * descaling cycles), supplies it draws from (a vacuum's clean-water tank and
55649
+ * detergent, a dishwasher's salt and rinse aid) and waste it collects (a dirty
55650
+ * water tank, a dust bin). Each item carries its remaining life or fill and an
55651
+ * optional "Replaced" reset action. Device-agnostic: any provider that knows
55652
+ * its device tracks consumables registers it; the provider names each item
55653
+ * verbatim and says which `kind` it is.
55654
+ *
55655
+ * The admin UI renders it as ONE collapsible section directly under the
55656
+ * device page's hero card (`placement: 'hero'`), for every device bound to
55657
+ * this cap — never drawn by a device type's hero card itself (D915).
55595
55658
  *
55596
55659
  * Like `childLayout`, the cap is INERT until a provider sets items: no
55597
55660
  * provider populates it by guessing (no HA inference). The UI renders a
55598
55661
  * "No consumables reported" placeholder when `items` is empty.
55599
55662
  */
55663
+ /**
55664
+ * What an item IS, which decides which direction is bad:
55665
+ * - `wear` — a part that wears out (a brush, a filter); low life is bad.
55666
+ * - `supply` — something the device draws from (clean water, detergent,
55667
+ * salt, rinse aid); low or empty is bad.
55668
+ * - `waste` — something the device fills (dirty water, a dust bin); full is
55669
+ * bad.
55670
+ * Absent = `wear`.
55671
+ */
55672
+ var ConsumableKindSchema = _enum([
55673
+ "wear",
55674
+ "supply",
55675
+ "waste"
55676
+ ]);
55677
+ /**
55678
+ * What an item LOOKS like, which decides how a client draws it — independent
55679
+ * of `kind`, which decides which direction is bad:
55680
+ * - `part` — a part that wears (a brush, a filter, a mop pad): a wear bar,
55681
+ * remaining time and a reset.
55682
+ * - `tank` — a container of liquid (clean water, dirty water): a fill gauge.
55683
+ * - `product` — something bought and refilled (detergent, salt, rinse aid):
55684
+ * a stepped level and "refill".
55685
+ * - `bin` — a container that collects waste (a dust bin): a fill gauge
55686
+ * that warns when full.
55687
+ * Absent = derived from the kind ({@link consumableFormOf}).
55688
+ */
55689
+ var ConsumableFormSchema = _enum([
55690
+ "part",
55691
+ "tank",
55692
+ "product",
55693
+ "bin"
55694
+ ]);
55695
+ /** The provider's own discrete verdict on an item. */
55696
+ var ConsumableStatusSchema = _enum([
55697
+ "ok",
55698
+ "low",
55699
+ "empty",
55700
+ "full",
55701
+ "replace"
55702
+ ]);
55703
+ _enum([
55704
+ "ok",
55705
+ "low",
55706
+ "empty",
55707
+ "full"
55708
+ ]);
55600
55709
  /** Units a remaining-life counter is reported in. Closed: the panel renders
55601
55710
  * each. */
55602
55711
  var ConsumableRemainingUnitSchema = _enum([
@@ -55611,18 +55720,23 @@ var ConsumableRemainingSchema = object({
55611
55720
  unit: ConsumableRemainingUnitSchema
55612
55721
  });
55613
55722
  /** A single consumable item. Either a continuous `level` (remaining
55614
- * life %) or a discrete `status` may be known — both may be null when a
55615
- * provider only knows the item exists. `level` and `status` are not
55616
- * mutually exclusive; a provider may report both. */
55723
+ * life %, or fill % for a `supply` / `waste` item) or a discrete `status`
55724
+ * may be known — both may be null when a provider only knows the item
55725
+ * exists. `level` and `status` are not mutually exclusive; a provider may
55726
+ * report both. */
55617
55727
  var ConsumableItemSchema = object({
55618
55728
  /** Stable id, e.g. 'main-brush'. */
55619
55729
  key: string().min(1),
55620
55730
  /** Display name. */
55621
55731
  label: string().min(1),
55622
- /** Remaining life % when known (0..100). */
55732
+ /** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
55623
55733
  level: number().min(0).max(100).nullable(),
55624
- /** Discrete state when known (binary mode). */
55625
- status: _enum(["ok", "replace"]).nullable(),
55734
+ /** The provider's discrete verdict when known (binary mode). */
55735
+ status: ConsumableStatusSchema.nullable(),
55736
+ /** What the item is — decides whether low or full is bad. Absent = `wear`. */
55737
+ kind: ConsumableKindSchema.optional(),
55738
+ /** How the item is drawn (part, tank, product, bin). Absent = derived from `kind`. */
55739
+ form: ConsumableFormSchema.optional(),
55626
55740
  /** Ms epoch of the last replace, when known. */
55627
55741
  lastResetAt: number().nullable(),
55628
55742
  /** Whether `reset()` is meaningful for this item. */
@@ -55645,7 +55759,7 @@ var consumablesCapability = {
55645
55759
  kind: "widget",
55646
55760
  widgetId: "host/consumables-panel",
55647
55761
  tab: "consumables",
55648
- topTab: true,
55762
+ placement: "hero",
55649
55763
  label: "Consumables",
55650
55764
  order: 5
55651
55765
  } },
@@ -55706,9 +55820,37 @@ reset: method(object({
55706
55820
  */
55707
55821
  durability: "restored",
55708
55822
  /**
55709
- * History (D850): none — `items` is an array keyed by runtime ids; a history path never enters it.
55823
+ * History (D850, D917): one series per (item field, item `key`) — the item key
55824
+ * is the series scope, the item `label` names it. A vacuum tank's fill, a
55825
+ * brush's remaining life and a dishwasher's salt are each recorded the moment
55826
+ * their provider reports them; an item that appears later gets its series.
55710
55827
  */
55711
- history: "none",
55828
+ history: {
55829
+ fields: {},
55830
+ items: {
55831
+ path: "items",
55832
+ key: "key",
55833
+ label: "label",
55834
+ fields: {
55835
+ level: {
55836
+ kind: "gauge",
55837
+ unit: "%",
55838
+ deadband: 2,
55839
+ displayName: "Level"
55840
+ },
55841
+ status: {
55842
+ kind: "enum",
55843
+ displayName: "Status"
55844
+ },
55845
+ "remaining.value": {
55846
+ kind: "gauge",
55847
+ unitFrom: "remaining.unit",
55848
+ deadband: 1,
55849
+ displayName: "Remaining"
55850
+ }
55851
+ }
55852
+ }
55853
+ },
55712
55854
  /** Clocks, not content: a re-read that changed no item costs no commit. */
55713
55855
  volatileStateFields: ["lastChangedAt", "lastFetchedAt"]
55714
55856
  };
@@ -56123,8 +56265,9 @@ onStatusChanged: { data: object({
56123
56265
  volatileStateFields: ["lastChangedAt"]
56124
56266
  };
56125
56267
  /**
56126
- * Smart-dishwasher cap — program lifecycle, door / remote-start gates,
56127
- * consumable levels (salt, rinse aid) and common program options.
56268
+ * Smart-dishwasher cap — program lifecycle, door / remote-start gates and
56269
+ * common program options. Salt and rinse aid are NOT here: they are items of
56270
+ * the device's `consumables` cap, like every other device's (D915).
56128
56271
  *
56129
56272
  * Sources: native Bosch Home Connect (`dishwasher` device type). Reusable
56130
56273
  * by any integration that exposes the same program / option surface.
@@ -56172,11 +56315,6 @@ var DishwasherAvailabilitySchema = _enum([
56172
56315
  "offline",
56173
56316
  "description-missing"
56174
56317
  ]);
56175
- var DishwasherConsumableLevelSchema = _enum([
56176
- "ok",
56177
- "low",
56178
- "empty"
56179
- ]);
56180
56318
  var DishwasherStatusSchema = object({
56181
56319
  availability: DishwasherAvailabilitySchema,
56182
56320
  /** Coarse state for compact surfaces; `unavailable` whenever the appliance state is not known. */
@@ -56209,8 +56347,6 @@ var DishwasherStatusSchema = object({
56209
56347
  powerOn: boolean().nullable(),
56210
56348
  /** The raw power state (`On`, `Off`, `Standby`, …); null when not known. */
56211
56349
  powerState: string().nullable(),
56212
- saltLevel: DishwasherConsumableLevelSchema.nullable(),
56213
- rinseAidLevel: DishwasherConsumableLevelSchema.nullable(),
56214
56350
  /**
56215
56351
  * True while the appliance asks for its filter to be cleaned (smart-filter, filter-system or
56216
56352
  * combined care-and-filter reminder raised); false when every such reminder reads clear; null
@@ -65026,60 +65162,17 @@ method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserI
65026
65162
  auth: "admin",
65027
65163
  access: "delete"
65028
65164
  });
65029
- /**
65030
- * Robot-vacuum cap. Models HA `vacuum.*` entities — anything with a
65031
- * cleaning lifecycle plus a return-to-base / locate surface and an
65032
- * optional fan-speed selector.
65033
- *
65034
- * State follows HA's canonical vacuum lifecycle: `idle` / `cleaning` /
65035
- * `paused` / `returning` / `docked` / `error`. `batteryLevel`
65036
- * (0..100) is nullable — some vacuums don't report a battery
65037
- * percentage. `fanSpeed` is the current speed token (provider-verbatim,
65038
- * e.g. `'standard'` / `'turbo'`) and `availableFanSpeeds` lists the
65039
- * tokens the hardware accepts so the UI renders only supported choices.
65040
- *
65041
- * The `setFanSpeed` method takes the bare `speed` token — the provider
65042
- * validates it against the vacuum's own list. `locate` triggers the
65043
- * find-me chirp; `returnToBase` sends it home.
65044
- *
65045
- * Consumable / waste tanks: `cleanWater` / `dirtyWater` / `detergent` /
65046
- * `dustBin` each carry a nullable `{ level (0..100 %), status ('ok' |
65047
- * 'low' | 'full') }` reading. Native providers (e.g. Dreame, Roborock)
65048
- * SHOULD populate whichever tanks the hardware has — leave a field `null`
65049
- * only when the device has no such tank at all, and use a `TankStatus`
65050
- * with both inner fields `null` when the tank exists but its level is
65051
- * currently unknown. HA `vacuum.*` entities expose no per-tank telemetry,
65052
- * so the HA provider leaves all four `null`.
65053
- */
65054
- var VacuumStateSchema = _enum([
65055
- "idle",
65056
- "cleaning",
65057
- "paused",
65058
- "returning",
65059
- "docked",
65060
- "drying",
65061
- "error"
65062
- ]);
65063
- /**
65064
- * One consumable / waste tank on a robot vacuum (clean-water, dirty-water,
65065
- * detergent or dust-bin). A tank can report a numeric fill `level` (0..100),
65066
- * a discrete `status` (binary-style hardware), or both. Both `null` means the
65067
- * level is currently unknown; the OWNING field being `null` means the
65068
- * hardware has no such tank at all.
65069
- */
65070
- var TankStatusSchema = object({
65071
- /** Numeric fill 0..100 when the hardware reports a percentage; null otherwise. */
65072
- level: number().min(0).max(100).nullable(),
65073
- /** Discrete state when the hardware is binary-mode; null otherwise. */
65074
- status: _enum([
65075
- "ok",
65076
- "low",
65077
- "full"
65078
- ]).nullable()
65079
- });
65080
65165
  var VacuumControlStatusSchema = object({
65081
65166
  /** Lifecycle state of the vacuum. */
65082
- state: VacuumStateSchema,
65167
+ state: _enum([
65168
+ "idle",
65169
+ "cleaning",
65170
+ "paused",
65171
+ "returning",
65172
+ "docked",
65173
+ "drying",
65174
+ "error"
65175
+ ]),
65083
65176
  /** 0..100 battery percentage. Null when the device has no battery
65084
65177
  * reading. */
65085
65178
  batteryLevel: number().min(0).max(100).nullable(),
@@ -65088,14 +65181,6 @@ var VacuumControlStatusSchema = object({
65088
65181
  fanSpeed: string().nullable(),
65089
65182
  /** Speed tokens the hardware accepts — drives the UI selector. */
65090
65183
  availableFanSpeeds: array(string()),
65091
- /** Clean-water (mop) tank. Null when the hardware has no clean-water tank. */
65092
- cleanWater: TankStatusSchema.nullable(),
65093
- /** Dirty-water (recovery) tank. Null when the hardware has no dirty-water tank. */
65094
- dirtyWater: TankStatusSchema.nullable(),
65095
- /** Detergent tank. Null when the hardware has no detergent tank. */
65096
- detergent: TankStatusSchema.nullable(),
65097
- /** Dust bin. Null when the hardware has no dust bin. */
65098
- dustBin: TankStatusSchema.nullable(),
65099
65184
  /** 0..100 cleaning-completion percentage of the current task, or null. */
65100
65185
  progressPercent: number().min(0).max(100).nullable(),
65101
65186
  /** Current error code (0 / null = no error). */
@@ -65157,35 +65242,14 @@ var vacuumControlCapability = {
65157
65242
  */
65158
65243
  durability: "session",
65159
65244
  /**
65160
- * History (D850): recorded series. Tank levels are fixed-object paths (`cleanWater.level`, ...).
65245
+ * History (D850): recorded series. The tanks moved to `consumables` (D915), whose
65246
+ * items are keyed by runtime ids and record no history.
65161
65247
  */
65162
- history: { fields: {
65163
- batteryLevel: {
65164
- kind: "gauge",
65165
- unit: "%",
65166
- deadband: 2
65167
- },
65168
- "cleanWater.level": {
65169
- kind: "gauge",
65170
- unit: "%",
65171
- deadband: 2
65172
- },
65173
- "dirtyWater.level": {
65174
- kind: "gauge",
65175
- unit: "%",
65176
- deadband: 2
65177
- },
65178
- "detergent.level": {
65179
- kind: "gauge",
65180
- unit: "%",
65181
- deadband: 2
65182
- },
65183
- "dustBin.level": {
65184
- kind: "gauge",
65185
- unit: "%",
65186
- deadband: 2
65187
- }
65188
- } }
65248
+ history: { fields: { batteryLevel: {
65249
+ kind: "gauge",
65250
+ unit: "%",
65251
+ deadband: 2
65252
+ } } }
65189
65253
  };
65190
65254
  var ValveStatusSchema = object({
65191
65255
  /** Lifecycle state of the valve. */
@@ -69579,6 +69643,12 @@ Object.freeze({
69579
69643
  addonId: null,
69580
69644
  access: "create"
69581
69645
  },
69646
+ "deviceHistory.deleteOrphanSeries": {
69647
+ capName: "device-history",
69648
+ capScope: "system",
69649
+ addonId: null,
69650
+ access: "delete"
69651
+ },
69582
69652
  "deviceHistory.getDeviceEnabled": {
69583
69653
  capName: "device-history",
69584
69654
  capScope: "system",
@@ -69597,6 +69667,12 @@ Object.freeze({
69597
69667
  addonId: null,
69598
69668
  access: "view"
69599
69669
  },
69670
+ "deviceHistory.listOrphanSeries": {
69671
+ capName: "device-history",
69672
+ capScope: "system",
69673
+ addonId: null,
69674
+ access: "view"
69675
+ },
69600
69676
  "deviceHistory.listSeries": {
69601
69677
  capName: "device-history",
69602
69678
  capScope: "system",
@@ -79602,7 +79678,7 @@ var STATE_SUMMARY_VARS = [
79602
79678
  ([...RULE_TEXT], [...COMBINED_ALARM]),
79603
79679
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
79604
79680
  ([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
79605
- ([...RULE_TEXT], [...CONSUMABLE]),
79681
+ ([...RULE_TEXT], [...CONSUMABLE, ...TANK]),
79606
79682
  ([...RULE_TEXT], [...TANK]),
79607
79683
  [...RULE_TEXT],
79608
79684
  ([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-homematic",
3
- "version": "1.2.153",
3
+ "version": "1.2.154",
4
4
  "description": "Homematic / HomematicIP (CCU3 / RaspberryMatic) device-provider addon for CamStack — wraps the nodehomematic library",
5
5
  "keywords": [
6
6
  "camstack",