@camstack/addon-provider-homematic 1.2.152 → 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 -123
  2. package/dist/addon.mjs +193 -123
  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({
@@ -48453,7 +48510,6 @@ var RecommendationReasonSchema = discriminatedUnion("kind", [
48453
48510
  modelId: string()
48454
48511
  }),
48455
48512
  object({ kind: literal("cpu-device") }),
48456
- object({ kind: literal("coral-untouched") }),
48457
48513
  object({ kind: literal("device-disabled") }),
48458
48514
  object({ kind: literal("device-unavailable") }),
48459
48515
  object({ kind: literal("node-offline") }),
@@ -48551,11 +48607,6 @@ var AutoTuneWarningSchema = discriminatedUnion("kind", [
48551
48607
  kind: literal("detector-store-unreadable"),
48552
48608
  error: string()
48553
48609
  }),
48554
- object({
48555
- kind: literal("coral-enabled"),
48556
- nodeId: string(),
48557
- deviceKey: string()
48558
- }),
48559
48610
  object({
48560
48611
  kind: literal("custom-pin-kept"),
48561
48612
  nodeId: string(),
@@ -55591,17 +55642,69 @@ var connectivityCapability = {
55591
55642
  volatileStateFields: ["lastChangedAt"]
55592
55643
  };
55593
55644
  /**
55594
- * Generic device-consumables capability — surfaces a device's
55595
- * maintenance items (vacuum filters/brushes, replaceable cartridges,
55596
- * descaling cycles, …) with their remaining life and an optional
55597
- * "Replaced" reset action. Device-agnostic: any provider that knows its
55598
- * device tracks consumables can register it; the cap declares no
55599
- * 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).
55600
55657
  *
55601
55658
  * Like `childLayout`, the cap is INERT until a provider sets items: no
55602
55659
  * provider populates it by guessing (no HA inference). The UI renders a
55603
55660
  * "No consumables reported" placeholder when `items` is empty.
55604
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
+ ]);
55605
55708
  /** Units a remaining-life counter is reported in. Closed: the panel renders
55606
55709
  * each. */
55607
55710
  var ConsumableRemainingUnitSchema = _enum([
@@ -55616,18 +55719,23 @@ var ConsumableRemainingSchema = object({
55616
55719
  unit: ConsumableRemainingUnitSchema
55617
55720
  });
55618
55721
  /** A single consumable item. Either a continuous `level` (remaining
55619
- * life %) or a discrete `status` may be known — both may be null when a
55620
- * provider only knows the item exists. `level` and `status` are not
55621
- * 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. */
55622
55726
  var ConsumableItemSchema = object({
55623
55727
  /** Stable id, e.g. 'main-brush'. */
55624
55728
  key: string().min(1),
55625
55729
  /** Display name. */
55626
55730
  label: string().min(1),
55627
- /** Remaining life % when known (0..100). */
55731
+ /** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
55628
55732
  level: number().min(0).max(100).nullable(),
55629
- /** Discrete state when known (binary mode). */
55630
- 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(),
55631
55739
  /** Ms epoch of the last replace, when known. */
55632
55740
  lastResetAt: number().nullable(),
55633
55741
  /** Whether `reset()` is meaningful for this item. */
@@ -55650,7 +55758,7 @@ var consumablesCapability = {
55650
55758
  kind: "widget",
55651
55759
  widgetId: "host/consumables-panel",
55652
55760
  tab: "consumables",
55653
- topTab: true,
55761
+ placement: "hero",
55654
55762
  label: "Consumables",
55655
55763
  order: 5
55656
55764
  } },
@@ -55711,9 +55819,37 @@ reset: method(object({
55711
55819
  */
55712
55820
  durability: "restored",
55713
55821
  /**
55714
- * 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.
55715
55826
  */
55716
- 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
+ },
55717
55853
  /** Clocks, not content: a re-read that changed no item costs no commit. */
55718
55854
  volatileStateFields: ["lastChangedAt", "lastFetchedAt"]
55719
55855
  };
@@ -56128,8 +56264,9 @@ onStatusChanged: { data: object({
56128
56264
  volatileStateFields: ["lastChangedAt"]
56129
56265
  };
56130
56266
  /**
56131
- * Smart-dishwasher cap — program lifecycle, door / remote-start gates,
56132
- * 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).
56133
56270
  *
56134
56271
  * Sources: native Bosch Home Connect (`dishwasher` device type). Reusable
56135
56272
  * by any integration that exposes the same program / option surface.
@@ -56177,11 +56314,6 @@ var DishwasherAvailabilitySchema = _enum([
56177
56314
  "offline",
56178
56315
  "description-missing"
56179
56316
  ]);
56180
- var DishwasherConsumableLevelSchema = _enum([
56181
- "ok",
56182
- "low",
56183
- "empty"
56184
- ]);
56185
56317
  var DishwasherStatusSchema = object({
56186
56318
  availability: DishwasherAvailabilitySchema,
56187
56319
  /** Coarse state for compact surfaces; `unavailable` whenever the appliance state is not known. */
@@ -56214,8 +56346,6 @@ var DishwasherStatusSchema = object({
56214
56346
  powerOn: boolean().nullable(),
56215
56347
  /** The raw power state (`On`, `Off`, `Standby`, …); null when not known. */
56216
56348
  powerState: string().nullable(),
56217
- saltLevel: DishwasherConsumableLevelSchema.nullable(),
56218
- rinseAidLevel: DishwasherConsumableLevelSchema.nullable(),
56219
56349
  /**
56220
56350
  * True while the appliance asks for its filter to be cleaned (smart-filter, filter-system or
56221
56351
  * combined care-and-filter reminder raised); false when every such reminder reads clear; null
@@ -65031,60 +65161,17 @@ method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserI
65031
65161
  auth: "admin",
65032
65162
  access: "delete"
65033
65163
  });
65034
- /**
65035
- * Robot-vacuum cap. Models HA `vacuum.*` entities — anything with a
65036
- * cleaning lifecycle plus a return-to-base / locate surface and an
65037
- * optional fan-speed selector.
65038
- *
65039
- * State follows HA's canonical vacuum lifecycle: `idle` / `cleaning` /
65040
- * `paused` / `returning` / `docked` / `error`. `batteryLevel`
65041
- * (0..100) is nullable — some vacuums don't report a battery
65042
- * percentage. `fanSpeed` is the current speed token (provider-verbatim,
65043
- * e.g. `'standard'` / `'turbo'`) and `availableFanSpeeds` lists the
65044
- * tokens the hardware accepts so the UI renders only supported choices.
65045
- *
65046
- * The `setFanSpeed` method takes the bare `speed` token — the provider
65047
- * validates it against the vacuum's own list. `locate` triggers the
65048
- * find-me chirp; `returnToBase` sends it home.
65049
- *
65050
- * Consumable / waste tanks: `cleanWater` / `dirtyWater` / `detergent` /
65051
- * `dustBin` each carry a nullable `{ level (0..100 %), status ('ok' |
65052
- * 'low' | 'full') }` reading. Native providers (e.g. Dreame, Roborock)
65053
- * SHOULD populate whichever tanks the hardware has — leave a field `null`
65054
- * only when the device has no such tank at all, and use a `TankStatus`
65055
- * with both inner fields `null` when the tank exists but its level is
65056
- * currently unknown. HA `vacuum.*` entities expose no per-tank telemetry,
65057
- * so the HA provider leaves all four `null`.
65058
- */
65059
- var VacuumStateSchema = _enum([
65060
- "idle",
65061
- "cleaning",
65062
- "paused",
65063
- "returning",
65064
- "docked",
65065
- "drying",
65066
- "error"
65067
- ]);
65068
- /**
65069
- * One consumable / waste tank on a robot vacuum (clean-water, dirty-water,
65070
- * detergent or dust-bin). A tank can report a numeric fill `level` (0..100),
65071
- * a discrete `status` (binary-style hardware), or both. Both `null` means the
65072
- * level is currently unknown; the OWNING field being `null` means the
65073
- * hardware has no such tank at all.
65074
- */
65075
- var TankStatusSchema = object({
65076
- /** Numeric fill 0..100 when the hardware reports a percentage; null otherwise. */
65077
- level: number().min(0).max(100).nullable(),
65078
- /** Discrete state when the hardware is binary-mode; null otherwise. */
65079
- status: _enum([
65080
- "ok",
65081
- "low",
65082
- "full"
65083
- ]).nullable()
65084
- });
65085
65164
  var VacuumControlStatusSchema = object({
65086
65165
  /** Lifecycle state of the vacuum. */
65087
- state: VacuumStateSchema,
65166
+ state: _enum([
65167
+ "idle",
65168
+ "cleaning",
65169
+ "paused",
65170
+ "returning",
65171
+ "docked",
65172
+ "drying",
65173
+ "error"
65174
+ ]),
65088
65175
  /** 0..100 battery percentage. Null when the device has no battery
65089
65176
  * reading. */
65090
65177
  batteryLevel: number().min(0).max(100).nullable(),
@@ -65093,14 +65180,6 @@ var VacuumControlStatusSchema = object({
65093
65180
  fanSpeed: string().nullable(),
65094
65181
  /** Speed tokens the hardware accepts — drives the UI selector. */
65095
65182
  availableFanSpeeds: array(string()),
65096
- /** Clean-water (mop) tank. Null when the hardware has no clean-water tank. */
65097
- cleanWater: TankStatusSchema.nullable(),
65098
- /** Dirty-water (recovery) tank. Null when the hardware has no dirty-water tank. */
65099
- dirtyWater: TankStatusSchema.nullable(),
65100
- /** Detergent tank. Null when the hardware has no detergent tank. */
65101
- detergent: TankStatusSchema.nullable(),
65102
- /** Dust bin. Null when the hardware has no dust bin. */
65103
- dustBin: TankStatusSchema.nullable(),
65104
65183
  /** 0..100 cleaning-completion percentage of the current task, or null. */
65105
65184
  progressPercent: number().min(0).max(100).nullable(),
65106
65185
  /** Current error code (0 / null = no error). */
@@ -65162,35 +65241,14 @@ var vacuumControlCapability = {
65162
65241
  */
65163
65242
  durability: "session",
65164
65243
  /**
65165
- * 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.
65166
65246
  */
65167
- history: { fields: {
65168
- batteryLevel: {
65169
- kind: "gauge",
65170
- unit: "%",
65171
- deadband: 2
65172
- },
65173
- "cleanWater.level": {
65174
- kind: "gauge",
65175
- unit: "%",
65176
- deadband: 2
65177
- },
65178
- "dirtyWater.level": {
65179
- kind: "gauge",
65180
- unit: "%",
65181
- deadband: 2
65182
- },
65183
- "detergent.level": {
65184
- kind: "gauge",
65185
- unit: "%",
65186
- deadband: 2
65187
- },
65188
- "dustBin.level": {
65189
- kind: "gauge",
65190
- unit: "%",
65191
- deadband: 2
65192
- }
65193
- } }
65247
+ history: { fields: { batteryLevel: {
65248
+ kind: "gauge",
65249
+ unit: "%",
65250
+ deadband: 2
65251
+ } } }
65194
65252
  };
65195
65253
  var ValveStatusSchema = object({
65196
65254
  /** Lifecycle state of the valve. */
@@ -69584,6 +69642,12 @@ Object.freeze({
69584
69642
  addonId: null,
69585
69643
  access: "create"
69586
69644
  },
69645
+ "deviceHistory.deleteOrphanSeries": {
69646
+ capName: "device-history",
69647
+ capScope: "system",
69648
+ addonId: null,
69649
+ access: "delete"
69650
+ },
69587
69651
  "deviceHistory.getDeviceEnabled": {
69588
69652
  capName: "device-history",
69589
69653
  capScope: "system",
@@ -69602,6 +69666,12 @@ Object.freeze({
69602
69666
  addonId: null,
69603
69667
  access: "view"
69604
69668
  },
69669
+ "deviceHistory.listOrphanSeries": {
69670
+ capName: "device-history",
69671
+ capScope: "system",
69672
+ addonId: null,
69673
+ access: "view"
69674
+ },
69605
69675
  "deviceHistory.listSeries": {
69606
69676
  capName: "device-history",
69607
69677
  capScope: "system",
@@ -79607,7 +79677,7 @@ var STATE_SUMMARY_VARS = [
79607
79677
  ([...RULE_TEXT], [...COMBINED_ALARM]),
79608
79678
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
79609
79679
  ([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
79610
- ([...RULE_TEXT], [...CONSUMABLE]),
79680
+ ([...RULE_TEXT], [...CONSUMABLE, ...TANK]),
79611
79681
  ([...RULE_TEXT], [...TANK]),
79612
79682
  [...RULE_TEXT],
79613
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({
@@ -48454,7 +48511,6 @@ var RecommendationReasonSchema = discriminatedUnion("kind", [
48454
48511
  modelId: string()
48455
48512
  }),
48456
48513
  object({ kind: literal("cpu-device") }),
48457
- object({ kind: literal("coral-untouched") }),
48458
48514
  object({ kind: literal("device-disabled") }),
48459
48515
  object({ kind: literal("device-unavailable") }),
48460
48516
  object({ kind: literal("node-offline") }),
@@ -48552,11 +48608,6 @@ var AutoTuneWarningSchema = discriminatedUnion("kind", [
48552
48608
  kind: literal("detector-store-unreadable"),
48553
48609
  error: string()
48554
48610
  }),
48555
- object({
48556
- kind: literal("coral-enabled"),
48557
- nodeId: string(),
48558
- deviceKey: string()
48559
- }),
48560
48611
  object({
48561
48612
  kind: literal("custom-pin-kept"),
48562
48613
  nodeId: string(),
@@ -55592,17 +55643,69 @@ var connectivityCapability = {
55592
55643
  volatileStateFields: ["lastChangedAt"]
55593
55644
  };
55594
55645
  /**
55595
- * Generic device-consumables capability — surfaces a device's
55596
- * maintenance items (vacuum filters/brushes, replaceable cartridges,
55597
- * descaling cycles, …) with their remaining life and an optional
55598
- * "Replaced" reset action. Device-agnostic: any provider that knows its
55599
- * device tracks consumables can register it; the cap declares no
55600
- * 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).
55601
55658
  *
55602
55659
  * Like `childLayout`, the cap is INERT until a provider sets items: no
55603
55660
  * provider populates it by guessing (no HA inference). The UI renders a
55604
55661
  * "No consumables reported" placeholder when `items` is empty.
55605
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
+ ]);
55606
55709
  /** Units a remaining-life counter is reported in. Closed: the panel renders
55607
55710
  * each. */
55608
55711
  var ConsumableRemainingUnitSchema = _enum([
@@ -55617,18 +55720,23 @@ var ConsumableRemainingSchema = object({
55617
55720
  unit: ConsumableRemainingUnitSchema
55618
55721
  });
55619
55722
  /** A single consumable item. Either a continuous `level` (remaining
55620
- * life %) or a discrete `status` may be known — both may be null when a
55621
- * provider only knows the item exists. `level` and `status` are not
55622
- * 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. */
55623
55727
  var ConsumableItemSchema = object({
55624
55728
  /** Stable id, e.g. 'main-brush'. */
55625
55729
  key: string().min(1),
55626
55730
  /** Display name. */
55627
55731
  label: string().min(1),
55628
- /** Remaining life % when known (0..100). */
55732
+ /** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
55629
55733
  level: number().min(0).max(100).nullable(),
55630
- /** Discrete state when known (binary mode). */
55631
- 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(),
55632
55740
  /** Ms epoch of the last replace, when known. */
55633
55741
  lastResetAt: number().nullable(),
55634
55742
  /** Whether `reset()` is meaningful for this item. */
@@ -55651,7 +55759,7 @@ var consumablesCapability = {
55651
55759
  kind: "widget",
55652
55760
  widgetId: "host/consumables-panel",
55653
55761
  tab: "consumables",
55654
- topTab: true,
55762
+ placement: "hero",
55655
55763
  label: "Consumables",
55656
55764
  order: 5
55657
55765
  } },
@@ -55712,9 +55820,37 @@ reset: method(object({
55712
55820
  */
55713
55821
  durability: "restored",
55714
55822
  /**
55715
- * 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.
55716
55827
  */
55717
- 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
+ },
55718
55854
  /** Clocks, not content: a re-read that changed no item costs no commit. */
55719
55855
  volatileStateFields: ["lastChangedAt", "lastFetchedAt"]
55720
55856
  };
@@ -56129,8 +56265,9 @@ onStatusChanged: { data: object({
56129
56265
  volatileStateFields: ["lastChangedAt"]
56130
56266
  };
56131
56267
  /**
56132
- * Smart-dishwasher cap — program lifecycle, door / remote-start gates,
56133
- * 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).
56134
56271
  *
56135
56272
  * Sources: native Bosch Home Connect (`dishwasher` device type). Reusable
56136
56273
  * by any integration that exposes the same program / option surface.
@@ -56178,11 +56315,6 @@ var DishwasherAvailabilitySchema = _enum([
56178
56315
  "offline",
56179
56316
  "description-missing"
56180
56317
  ]);
56181
- var DishwasherConsumableLevelSchema = _enum([
56182
- "ok",
56183
- "low",
56184
- "empty"
56185
- ]);
56186
56318
  var DishwasherStatusSchema = object({
56187
56319
  availability: DishwasherAvailabilitySchema,
56188
56320
  /** Coarse state for compact surfaces; `unavailable` whenever the appliance state is not known. */
@@ -56215,8 +56347,6 @@ var DishwasherStatusSchema = object({
56215
56347
  powerOn: boolean().nullable(),
56216
56348
  /** The raw power state (`On`, `Off`, `Standby`, …); null when not known. */
56217
56349
  powerState: string().nullable(),
56218
- saltLevel: DishwasherConsumableLevelSchema.nullable(),
56219
- rinseAidLevel: DishwasherConsumableLevelSchema.nullable(),
56220
56350
  /**
56221
56351
  * True while the appliance asks for its filter to be cleaned (smart-filter, filter-system or
56222
56352
  * combined care-and-filter reminder raised); false when every such reminder reads clear; null
@@ -65032,60 +65162,17 @@ method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserI
65032
65162
  auth: "admin",
65033
65163
  access: "delete"
65034
65164
  });
65035
- /**
65036
- * Robot-vacuum cap. Models HA `vacuum.*` entities — anything with a
65037
- * cleaning lifecycle plus a return-to-base / locate surface and an
65038
- * optional fan-speed selector.
65039
- *
65040
- * State follows HA's canonical vacuum lifecycle: `idle` / `cleaning` /
65041
- * `paused` / `returning` / `docked` / `error`. `batteryLevel`
65042
- * (0..100) is nullable — some vacuums don't report a battery
65043
- * percentage. `fanSpeed` is the current speed token (provider-verbatim,
65044
- * e.g. `'standard'` / `'turbo'`) and `availableFanSpeeds` lists the
65045
- * tokens the hardware accepts so the UI renders only supported choices.
65046
- *
65047
- * The `setFanSpeed` method takes the bare `speed` token — the provider
65048
- * validates it against the vacuum's own list. `locate` triggers the
65049
- * find-me chirp; `returnToBase` sends it home.
65050
- *
65051
- * Consumable / waste tanks: `cleanWater` / `dirtyWater` / `detergent` /
65052
- * `dustBin` each carry a nullable `{ level (0..100 %), status ('ok' |
65053
- * 'low' | 'full') }` reading. Native providers (e.g. Dreame, Roborock)
65054
- * SHOULD populate whichever tanks the hardware has — leave a field `null`
65055
- * only when the device has no such tank at all, and use a `TankStatus`
65056
- * with both inner fields `null` when the tank exists but its level is
65057
- * currently unknown. HA `vacuum.*` entities expose no per-tank telemetry,
65058
- * so the HA provider leaves all four `null`.
65059
- */
65060
- var VacuumStateSchema = _enum([
65061
- "idle",
65062
- "cleaning",
65063
- "paused",
65064
- "returning",
65065
- "docked",
65066
- "drying",
65067
- "error"
65068
- ]);
65069
- /**
65070
- * One consumable / waste tank on a robot vacuum (clean-water, dirty-water,
65071
- * detergent or dust-bin). A tank can report a numeric fill `level` (0..100),
65072
- * a discrete `status` (binary-style hardware), or both. Both `null` means the
65073
- * level is currently unknown; the OWNING field being `null` means the
65074
- * hardware has no such tank at all.
65075
- */
65076
- var TankStatusSchema = object({
65077
- /** Numeric fill 0..100 when the hardware reports a percentage; null otherwise. */
65078
- level: number().min(0).max(100).nullable(),
65079
- /** Discrete state when the hardware is binary-mode; null otherwise. */
65080
- status: _enum([
65081
- "ok",
65082
- "low",
65083
- "full"
65084
- ]).nullable()
65085
- });
65086
65165
  var VacuumControlStatusSchema = object({
65087
65166
  /** Lifecycle state of the vacuum. */
65088
- state: VacuumStateSchema,
65167
+ state: _enum([
65168
+ "idle",
65169
+ "cleaning",
65170
+ "paused",
65171
+ "returning",
65172
+ "docked",
65173
+ "drying",
65174
+ "error"
65175
+ ]),
65089
65176
  /** 0..100 battery percentage. Null when the device has no battery
65090
65177
  * reading. */
65091
65178
  batteryLevel: number().min(0).max(100).nullable(),
@@ -65094,14 +65181,6 @@ var VacuumControlStatusSchema = object({
65094
65181
  fanSpeed: string().nullable(),
65095
65182
  /** Speed tokens the hardware accepts — drives the UI selector. */
65096
65183
  availableFanSpeeds: array(string()),
65097
- /** Clean-water (mop) tank. Null when the hardware has no clean-water tank. */
65098
- cleanWater: TankStatusSchema.nullable(),
65099
- /** Dirty-water (recovery) tank. Null when the hardware has no dirty-water tank. */
65100
- dirtyWater: TankStatusSchema.nullable(),
65101
- /** Detergent tank. Null when the hardware has no detergent tank. */
65102
- detergent: TankStatusSchema.nullable(),
65103
- /** Dust bin. Null when the hardware has no dust bin. */
65104
- dustBin: TankStatusSchema.nullable(),
65105
65184
  /** 0..100 cleaning-completion percentage of the current task, or null. */
65106
65185
  progressPercent: number().min(0).max(100).nullable(),
65107
65186
  /** Current error code (0 / null = no error). */
@@ -65163,35 +65242,14 @@ var vacuumControlCapability = {
65163
65242
  */
65164
65243
  durability: "session",
65165
65244
  /**
65166
- * 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.
65167
65247
  */
65168
- history: { fields: {
65169
- batteryLevel: {
65170
- kind: "gauge",
65171
- unit: "%",
65172
- deadband: 2
65173
- },
65174
- "cleanWater.level": {
65175
- kind: "gauge",
65176
- unit: "%",
65177
- deadband: 2
65178
- },
65179
- "dirtyWater.level": {
65180
- kind: "gauge",
65181
- unit: "%",
65182
- deadband: 2
65183
- },
65184
- "detergent.level": {
65185
- kind: "gauge",
65186
- unit: "%",
65187
- deadband: 2
65188
- },
65189
- "dustBin.level": {
65190
- kind: "gauge",
65191
- unit: "%",
65192
- deadband: 2
65193
- }
65194
- } }
65248
+ history: { fields: { batteryLevel: {
65249
+ kind: "gauge",
65250
+ unit: "%",
65251
+ deadband: 2
65252
+ } } }
65195
65253
  };
65196
65254
  var ValveStatusSchema = object({
65197
65255
  /** Lifecycle state of the valve. */
@@ -69585,6 +69643,12 @@ Object.freeze({
69585
69643
  addonId: null,
69586
69644
  access: "create"
69587
69645
  },
69646
+ "deviceHistory.deleteOrphanSeries": {
69647
+ capName: "device-history",
69648
+ capScope: "system",
69649
+ addonId: null,
69650
+ access: "delete"
69651
+ },
69588
69652
  "deviceHistory.getDeviceEnabled": {
69589
69653
  capName: "device-history",
69590
69654
  capScope: "system",
@@ -69603,6 +69667,12 @@ Object.freeze({
69603
69667
  addonId: null,
69604
69668
  access: "view"
69605
69669
  },
69670
+ "deviceHistory.listOrphanSeries": {
69671
+ capName: "device-history",
69672
+ capScope: "system",
69673
+ addonId: null,
69674
+ access: "view"
69675
+ },
69606
69676
  "deviceHistory.listSeries": {
69607
69677
  capName: "device-history",
69608
69678
  capScope: "system",
@@ -79608,7 +79678,7 @@ var STATE_SUMMARY_VARS = [
79608
79678
  ([...RULE_TEXT], [...COMBINED_ALARM]),
79609
79679
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
79610
79680
  ([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
79611
- ([...RULE_TEXT], [...CONSUMABLE]),
79681
+ ([...RULE_TEXT], [...CONSUMABLE, ...TANK]),
79612
79682
  ([...RULE_TEXT], [...TANK]),
79613
79683
  [...RULE_TEXT],
79614
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.152",
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",