@camstack/addon-matter-broker 0.2.144 → 0.2.145

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
@@ -5578,7 +5578,7 @@ var ZodIssueCode = {
5578
5578
  var ZodFirstPartyTypeKind;
5579
5579
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5580
5580
  //#endregion
5581
- //#region ../types/dist/sleep-DJFUfKvA.mjs
5581
+ //#region ../types/dist/sleep-CUp20JkO.mjs
5582
5582
  /**
5583
5583
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5584
5584
  * window to float samples (D455).
@@ -8658,7 +8658,11 @@ var ContributionSectionSchema = object({
8658
8658
  literal(4)
8659
8659
  ]).optional(),
8660
8660
  tab: string$2().optional(),
8661
- location: _enum(["settings", "top-tab"]).optional(),
8661
+ location: _enum([
8662
+ "settings",
8663
+ "top-tab",
8664
+ "hero"
8665
+ ]).optional(),
8662
8666
  order: number().optional(),
8663
8667
  fields: array(any$2())
8664
8668
  });
@@ -13591,7 +13595,11 @@ var ConfigSectionWithValuesSchema = object({
13591
13595
  literal(4)
13592
13596
  ]).optional(),
13593
13597
  tab: string$2().optional(),
13594
- location: _enum(["settings", "top-tab"]).optional(),
13598
+ location: _enum([
13599
+ "settings",
13600
+ "top-tab",
13601
+ "hero"
13602
+ ]).optional(),
13595
13603
  order: number().optional(),
13596
13604
  fields: array(any$2())
13597
13605
  });
@@ -17520,6 +17528,52 @@ var TierStatusSchema = object({
17520
17528
  countedAt: number().nullable()
17521
17529
  });
17522
17530
  /** Operator/diagnostic view: rows per tier, last runs, refusals and drops since boot. */
17531
+ /**
17532
+ * Why a series is orphan. `device-gone`: its device is absent from the
17533
+ * successful device listings (the departure clock). `undeclared`: its `cap:`
17534
+ * key is declared by no capability any more (a field a cap removed).
17535
+ */
17536
+ var DeviceHistoryOrphanReasonSchema = _enum(["device-gone", "undeclared"]);
17537
+ /** Rows held per stored tier. */
17538
+ var TierRowsSchema = object({
17539
+ raw: number().int(),
17540
+ "5m": number().int(),
17541
+ "1h": number().int(),
17542
+ "1d": number().int()
17543
+ });
17544
+ var OrphanSeriesSchema = object({
17545
+ seriesId: number().int(),
17546
+ deviceId: number().int(),
17547
+ key: string$2(),
17548
+ scope: string$2(),
17549
+ /** The metric's display name; `null` when its metric row is gone too. */
17550
+ displayName: string$2().nullable(),
17551
+ reason: DeviceHistoryOrphanReasonSchema,
17552
+ /** `device-gone`: since when the device has been absent; `null` otherwise. */
17553
+ missingSince: number().nullable(),
17554
+ firstTs: number(),
17555
+ lastTs: number(),
17556
+ rows: TierRowsSchema
17557
+ });
17558
+ var DeviceHistoryOrphanDeleteRefusalSchema = _enum([
17559
+ "not-found",
17560
+ "not-orphan",
17561
+ "failed"
17562
+ ]);
17563
+ var OrphanDeleteEntrySchema = discriminatedUnion("ok", [object({
17564
+ seriesId: number().int(),
17565
+ ok: literal(true),
17566
+ deleted: TierRowsSchema
17567
+ }), object({
17568
+ seriesId: number().int(),
17569
+ ok: literal(false),
17570
+ reason: DeviceHistoryOrphanDeleteRefusalSchema
17571
+ })]);
17572
+ var OrphanListSchema = object({
17573
+ series: array(OrphanSeriesSchema).readonly(),
17574
+ /** More orphans exist than {@link DEVICE_HISTORY_ORPHAN_LIST_MAX}. */
17575
+ truncated: boolean()
17576
+ });
17523
17577
  var DeviceHistoryStatusSchema = object({
17524
17578
  startedAt: number(),
17525
17579
  /** The store is declared, series loaded and the first reconcile has answered. */
@@ -17617,7 +17671,10 @@ method(object({ deviceId: number().int() }), array(SeriesInfoSchema).readonly())
17617
17671
  }), object({ enabled: boolean() }), {
17618
17672
  kind: "mutation",
17619
17673
  auth: "admin"
17620
- }), method(object({}), DeviceHistoryStatusSchema, { auth: "admin" });
17674
+ }), 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() }), {
17675
+ kind: "mutation",
17676
+ auth: "admin"
17677
+ });
17621
17678
  var DeviceCaStatusSchema = discriminatedUnion("state", [
17622
17679
  object({ state: literal("absent") }),
17623
17680
  object({
@@ -55494,17 +55551,69 @@ var connectivityCapability = {
55494
55551
  volatileStateFields: ["lastChangedAt"]
55495
55552
  };
55496
55553
  /**
55497
- * Generic device-consumables capability — surfaces a device's
55498
- * maintenance items (vacuum filters/brushes, replaceable cartridges,
55499
- * descaling cycles, …) with their remaining life and an optional
55500
- * "Replaced" reset action. Device-agnostic: any provider that knows its
55501
- * device tracks consumables can register it; the cap declares no
55502
- * vocabulary of its own — the provider names each item verbatim.
55554
+ * Generic device-consumables capability — the ONE place a device reports what
55555
+ * it uses up or fills: wear parts (vacuum filters/brushes, cartridges,
55556
+ * descaling cycles), supplies it draws from (a vacuum's clean-water tank and
55557
+ * detergent, a dishwasher's salt and rinse aid) and waste it collects (a dirty
55558
+ * water tank, a dust bin). Each item carries its remaining life or fill and an
55559
+ * optional "Replaced" reset action. Device-agnostic: any provider that knows
55560
+ * its device tracks consumables registers it; the provider names each item
55561
+ * verbatim and says which `kind` it is.
55562
+ *
55563
+ * The admin UI renders it as ONE collapsible section directly under the
55564
+ * device page's hero card (`placement: 'hero'`), for every device bound to
55565
+ * this cap — never drawn by a device type's hero card itself (D915).
55503
55566
  *
55504
55567
  * Like `childLayout`, the cap is INERT until a provider sets items: no
55505
55568
  * provider populates it by guessing (no HA inference). The UI renders a
55506
55569
  * "No consumables reported" placeholder when `items` is empty.
55507
55570
  */
55571
+ /**
55572
+ * What an item IS, which decides which direction is bad:
55573
+ * - `wear` — a part that wears out (a brush, a filter); low life is bad.
55574
+ * - `supply` — something the device draws from (clean water, detergent,
55575
+ * salt, rinse aid); low or empty is bad.
55576
+ * - `waste` — something the device fills (dirty water, a dust bin); full is
55577
+ * bad.
55578
+ * Absent = `wear`.
55579
+ */
55580
+ var ConsumableKindSchema = _enum([
55581
+ "wear",
55582
+ "supply",
55583
+ "waste"
55584
+ ]);
55585
+ /**
55586
+ * What an item LOOKS like, which decides how a client draws it — independent
55587
+ * of `kind`, which decides which direction is bad:
55588
+ * - `part` — a part that wears (a brush, a filter, a mop pad): a wear bar,
55589
+ * remaining time and a reset.
55590
+ * - `tank` — a container of liquid (clean water, dirty water): a fill gauge.
55591
+ * - `product` — something bought and refilled (detergent, salt, rinse aid):
55592
+ * a stepped level and "refill".
55593
+ * - `bin` — a container that collects waste (a dust bin): a fill gauge
55594
+ * that warns when full.
55595
+ * Absent = derived from the kind ({@link consumableFormOf}).
55596
+ */
55597
+ var ConsumableFormSchema = _enum([
55598
+ "part",
55599
+ "tank",
55600
+ "product",
55601
+ "bin"
55602
+ ]);
55603
+ /** The provider's own discrete verdict on an item. */
55604
+ var ConsumableStatusSchema = _enum([
55605
+ "ok",
55606
+ "low",
55607
+ "empty",
55608
+ "full",
55609
+ "replace"
55610
+ ]);
55611
+ _enum([
55612
+ "ok",
55613
+ "low",
55614
+ "empty",
55615
+ "full"
55616
+ ]);
55508
55617
  /** Units a remaining-life counter is reported in. Closed: the panel renders
55509
55618
  * each. */
55510
55619
  var ConsumableRemainingUnitSchema = _enum([
@@ -55519,18 +55628,23 @@ var ConsumableRemainingSchema = object({
55519
55628
  unit: ConsumableRemainingUnitSchema
55520
55629
  });
55521
55630
  /** A single consumable item. Either a continuous `level` (remaining
55522
- * life %) or a discrete `status` may be known — both may be null when a
55523
- * provider only knows the item exists. `level` and `status` are not
55524
- * mutually exclusive; a provider may report both. */
55631
+ * life %, or fill % for a `supply` / `waste` item) or a discrete `status`
55632
+ * may be known — both may be null when a provider only knows the item
55633
+ * exists. `level` and `status` are not mutually exclusive; a provider may
55634
+ * report both. */
55525
55635
  var ConsumableItemSchema = object({
55526
55636
  /** Stable id, e.g. 'main-brush'. */
55527
55637
  key: string$2().min(1),
55528
55638
  /** Display name. */
55529
55639
  label: string$2().min(1),
55530
- /** Remaining life % when known (0..100). */
55640
+ /** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
55531
55641
  level: number().min(0).max(100).nullable(),
55532
- /** Discrete state when known (binary mode). */
55533
- status: _enum(["ok", "replace"]).nullable(),
55642
+ /** The provider's discrete verdict when known (binary mode). */
55643
+ status: ConsumableStatusSchema.nullable(),
55644
+ /** What the item is — decides whether low or full is bad. Absent = `wear`. */
55645
+ kind: ConsumableKindSchema.optional(),
55646
+ /** How the item is drawn (part, tank, product, bin). Absent = derived from `kind`. */
55647
+ form: ConsumableFormSchema.optional(),
55534
55648
  /** Ms epoch of the last replace, when known. */
55535
55649
  lastResetAt: number().nullable(),
55536
55650
  /** Whether `reset()` is meaningful for this item. */
@@ -55553,7 +55667,7 @@ var consumablesCapability = {
55553
55667
  kind: "widget",
55554
55668
  widgetId: "host/consumables-panel",
55555
55669
  tab: "consumables",
55556
- topTab: true,
55670
+ placement: "hero",
55557
55671
  label: "Consumables",
55558
55672
  order: 5
55559
55673
  } },
@@ -55614,9 +55728,37 @@ reset: method(object({
55614
55728
  */
55615
55729
  durability: "restored",
55616
55730
  /**
55617
- * History (D850): none — `items` is an array keyed by runtime ids; a history path never enters it.
55731
+ * History (D850, D917): one series per (item field, item `key`) — the item key
55732
+ * is the series scope, the item `label` names it. A vacuum tank's fill, a
55733
+ * brush's remaining life and a dishwasher's salt are each recorded the moment
55734
+ * their provider reports them; an item that appears later gets its series.
55618
55735
  */
55619
- history: "none",
55736
+ history: {
55737
+ fields: {},
55738
+ items: {
55739
+ path: "items",
55740
+ key: "key",
55741
+ label: "label",
55742
+ fields: {
55743
+ level: {
55744
+ kind: "gauge",
55745
+ unit: "%",
55746
+ deadband: 2,
55747
+ displayName: "Level"
55748
+ },
55749
+ status: {
55750
+ kind: "enum",
55751
+ displayName: "Status"
55752
+ },
55753
+ "remaining.value": {
55754
+ kind: "gauge",
55755
+ unitFrom: "remaining.unit",
55756
+ deadband: 1,
55757
+ displayName: "Remaining"
55758
+ }
55759
+ }
55760
+ }
55761
+ },
55620
55762
  /** Clocks, not content: a re-read that changed no item costs no commit. */
55621
55763
  volatileStateFields: ["lastChangedAt", "lastFetchedAt"]
55622
55764
  };
@@ -56031,8 +56173,9 @@ onStatusChanged: { data: object({
56031
56173
  volatileStateFields: ["lastChangedAt"]
56032
56174
  };
56033
56175
  /**
56034
- * Smart-dishwasher cap — program lifecycle, door / remote-start gates,
56035
- * consumable levels (salt, rinse aid) and common program options.
56176
+ * Smart-dishwasher cap — program lifecycle, door / remote-start gates and
56177
+ * common program options. Salt and rinse aid are NOT here: they are items of
56178
+ * the device's `consumables` cap, like every other device's (D915).
56036
56179
  *
56037
56180
  * Sources: native Bosch Home Connect (`dishwasher` device type). Reusable
56038
56181
  * by any integration that exposes the same program / option surface.
@@ -56080,11 +56223,6 @@ var DishwasherAvailabilitySchema = _enum([
56080
56223
  "offline",
56081
56224
  "description-missing"
56082
56225
  ]);
56083
- var DishwasherConsumableLevelSchema = _enum([
56084
- "ok",
56085
- "low",
56086
- "empty"
56087
- ]);
56088
56226
  var DishwasherStatusSchema = object({
56089
56227
  availability: DishwasherAvailabilitySchema,
56090
56228
  /** Coarse state for compact surfaces; `unavailable` whenever the appliance state is not known. */
@@ -56117,8 +56255,6 @@ var DishwasherStatusSchema = object({
56117
56255
  powerOn: boolean().nullable(),
56118
56256
  /** The raw power state (`On`, `Off`, `Standby`, …); null when not known. */
56119
56257
  powerState: string$2().nullable(),
56120
- saltLevel: DishwasherConsumableLevelSchema.nullable(),
56121
- rinseAidLevel: DishwasherConsumableLevelSchema.nullable(),
56122
56258
  /**
56123
56259
  * True while the appliance asks for its filter to be cleaned (smart-filter, filter-system or
56124
56260
  * combined care-and-filter reminder raised); false when every such reminder reads clear; null
@@ -64934,60 +65070,17 @@ method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserI
64934
65070
  auth: "admin",
64935
65071
  access: "delete"
64936
65072
  });
64937
- /**
64938
- * Robot-vacuum cap. Models HA `vacuum.*` entities — anything with a
64939
- * cleaning lifecycle plus a return-to-base / locate surface and an
64940
- * optional fan-speed selector.
64941
- *
64942
- * State follows HA's canonical vacuum lifecycle: `idle` / `cleaning` /
64943
- * `paused` / `returning` / `docked` / `error`. `batteryLevel`
64944
- * (0..100) is nullable — some vacuums don't report a battery
64945
- * percentage. `fanSpeed` is the current speed token (provider-verbatim,
64946
- * e.g. `'standard'` / `'turbo'`) and `availableFanSpeeds` lists the
64947
- * tokens the hardware accepts so the UI renders only supported choices.
64948
- *
64949
- * The `setFanSpeed` method takes the bare `speed` token — the provider
64950
- * validates it against the vacuum's own list. `locate` triggers the
64951
- * find-me chirp; `returnToBase` sends it home.
64952
- *
64953
- * Consumable / waste tanks: `cleanWater` / `dirtyWater` / `detergent` /
64954
- * `dustBin` each carry a nullable `{ level (0..100 %), status ('ok' |
64955
- * 'low' | 'full') }` reading. Native providers (e.g. Dreame, Roborock)
64956
- * SHOULD populate whichever tanks the hardware has — leave a field `null`
64957
- * only when the device has no such tank at all, and use a `TankStatus`
64958
- * with both inner fields `null` when the tank exists but its level is
64959
- * currently unknown. HA `vacuum.*` entities expose no per-tank telemetry,
64960
- * so the HA provider leaves all four `null`.
64961
- */
64962
- var VacuumStateSchema = _enum([
64963
- "idle",
64964
- "cleaning",
64965
- "paused",
64966
- "returning",
64967
- "docked",
64968
- "drying",
64969
- "error"
64970
- ]);
64971
- /**
64972
- * One consumable / waste tank on a robot vacuum (clean-water, dirty-water,
64973
- * detergent or dust-bin). A tank can report a numeric fill `level` (0..100),
64974
- * a discrete `status` (binary-style hardware), or both. Both `null` means the
64975
- * level is currently unknown; the OWNING field being `null` means the
64976
- * hardware has no such tank at all.
64977
- */
64978
- var TankStatusSchema = object({
64979
- /** Numeric fill 0..100 when the hardware reports a percentage; null otherwise. */
64980
- level: number().min(0).max(100).nullable(),
64981
- /** Discrete state when the hardware is binary-mode; null otherwise. */
64982
- status: _enum([
64983
- "ok",
64984
- "low",
64985
- "full"
64986
- ]).nullable()
64987
- });
64988
65073
  var VacuumControlStatusSchema = object({
64989
65074
  /** Lifecycle state of the vacuum. */
64990
- state: VacuumStateSchema,
65075
+ state: _enum([
65076
+ "idle",
65077
+ "cleaning",
65078
+ "paused",
65079
+ "returning",
65080
+ "docked",
65081
+ "drying",
65082
+ "error"
65083
+ ]),
64991
65084
  /** 0..100 battery percentage. Null when the device has no battery
64992
65085
  * reading. */
64993
65086
  batteryLevel: number().min(0).max(100).nullable(),
@@ -64996,14 +65089,6 @@ var VacuumControlStatusSchema = object({
64996
65089
  fanSpeed: string$2().nullable(),
64997
65090
  /** Speed tokens the hardware accepts — drives the UI selector. */
64998
65091
  availableFanSpeeds: array(string$2()),
64999
- /** Clean-water (mop) tank. Null when the hardware has no clean-water tank. */
65000
- cleanWater: TankStatusSchema.nullable(),
65001
- /** Dirty-water (recovery) tank. Null when the hardware has no dirty-water tank. */
65002
- dirtyWater: TankStatusSchema.nullable(),
65003
- /** Detergent tank. Null when the hardware has no detergent tank. */
65004
- detergent: TankStatusSchema.nullable(),
65005
- /** Dust bin. Null when the hardware has no dust bin. */
65006
- dustBin: TankStatusSchema.nullable(),
65007
65092
  /** 0..100 cleaning-completion percentage of the current task, or null. */
65008
65093
  progressPercent: number().min(0).max(100).nullable(),
65009
65094
  /** Current error code (0 / null = no error). */
@@ -65065,35 +65150,14 @@ var vacuumControlCapability = {
65065
65150
  */
65066
65151
  durability: "session",
65067
65152
  /**
65068
- * History (D850): recorded series. Tank levels are fixed-object paths (`cleanWater.level`, ...).
65153
+ * History (D850): recorded series. The tanks moved to `consumables` (D915), whose
65154
+ * items are keyed by runtime ids and record no history.
65069
65155
  */
65070
- history: { fields: {
65071
- batteryLevel: {
65072
- kind: "gauge",
65073
- unit: "%",
65074
- deadband: 2
65075
- },
65076
- "cleanWater.level": {
65077
- kind: "gauge",
65078
- unit: "%",
65079
- deadband: 2
65080
- },
65081
- "dirtyWater.level": {
65082
- kind: "gauge",
65083
- unit: "%",
65084
- deadband: 2
65085
- },
65086
- "detergent.level": {
65087
- kind: "gauge",
65088
- unit: "%",
65089
- deadband: 2
65090
- },
65091
- "dustBin.level": {
65092
- kind: "gauge",
65093
- unit: "%",
65094
- deadband: 2
65095
- }
65096
- } }
65156
+ history: { fields: { batteryLevel: {
65157
+ kind: "gauge",
65158
+ unit: "%",
65159
+ deadband: 2
65160
+ } } }
65097
65161
  };
65098
65162
  var ValveStatusSchema = object({
65099
65163
  /** Lifecycle state of the valve. */
@@ -69487,6 +69551,12 @@ Object.freeze({
69487
69551
  addonId: null,
69488
69552
  access: "create"
69489
69553
  },
69554
+ "deviceHistory.deleteOrphanSeries": {
69555
+ capName: "device-history",
69556
+ capScope: "system",
69557
+ addonId: null,
69558
+ access: "delete"
69559
+ },
69490
69560
  "deviceHistory.getDeviceEnabled": {
69491
69561
  capName: "device-history",
69492
69562
  capScope: "system",
@@ -69505,6 +69575,12 @@ Object.freeze({
69505
69575
  addonId: null,
69506
69576
  access: "view"
69507
69577
  },
69578
+ "deviceHistory.listOrphanSeries": {
69579
+ capName: "device-history",
69580
+ capScope: "system",
69581
+ addonId: null,
69582
+ access: "view"
69583
+ },
69508
69584
  "deviceHistory.listSeries": {
69509
69585
  capName: "device-history",
69510
69586
  capScope: "system",
@@ -79510,7 +79586,7 @@ var STATE_SUMMARY_VARS = [
79510
79586
  ([...RULE_TEXT], [...COMBINED_ALARM]),
79511
79587
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
79512
79588
  ([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
79513
- ([...RULE_TEXT], [...CONSUMABLE]),
79589
+ ([...RULE_TEXT], [...CONSUMABLE, ...TANK]),
79514
79590
  ([...RULE_TEXT], [...TANK]),
79515
79591
  [...RULE_TEXT],
79516
79592
  ([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
package/dist/addon.mjs CHANGED
@@ -5576,7 +5576,7 @@ var ZodIssueCode = {
5576
5576
  var ZodFirstPartyTypeKind;
5577
5577
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5578
5578
  //#endregion
5579
- //#region ../types/dist/sleep-DJFUfKvA.mjs
5579
+ //#region ../types/dist/sleep-CUp20JkO.mjs
5580
5580
  /**
5581
5581
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5582
5582
  * window to float samples (D455).
@@ -8656,7 +8656,11 @@ var ContributionSectionSchema = object({
8656
8656
  literal(4)
8657
8657
  ]).optional(),
8658
8658
  tab: string$2().optional(),
8659
- location: _enum(["settings", "top-tab"]).optional(),
8659
+ location: _enum([
8660
+ "settings",
8661
+ "top-tab",
8662
+ "hero"
8663
+ ]).optional(),
8660
8664
  order: number().optional(),
8661
8665
  fields: array(any$2())
8662
8666
  });
@@ -13589,7 +13593,11 @@ var ConfigSectionWithValuesSchema = object({
13589
13593
  literal(4)
13590
13594
  ]).optional(),
13591
13595
  tab: string$2().optional(),
13592
- location: _enum(["settings", "top-tab"]).optional(),
13596
+ location: _enum([
13597
+ "settings",
13598
+ "top-tab",
13599
+ "hero"
13600
+ ]).optional(),
13593
13601
  order: number().optional(),
13594
13602
  fields: array(any$2())
13595
13603
  });
@@ -17518,6 +17526,52 @@ var TierStatusSchema = object({
17518
17526
  countedAt: number().nullable()
17519
17527
  });
17520
17528
  /** Operator/diagnostic view: rows per tier, last runs, refusals and drops since boot. */
17529
+ /**
17530
+ * Why a series is orphan. `device-gone`: its device is absent from the
17531
+ * successful device listings (the departure clock). `undeclared`: its `cap:`
17532
+ * key is declared by no capability any more (a field a cap removed).
17533
+ */
17534
+ var DeviceHistoryOrphanReasonSchema = _enum(["device-gone", "undeclared"]);
17535
+ /** Rows held per stored tier. */
17536
+ var TierRowsSchema = object({
17537
+ raw: number().int(),
17538
+ "5m": number().int(),
17539
+ "1h": number().int(),
17540
+ "1d": number().int()
17541
+ });
17542
+ var OrphanSeriesSchema = object({
17543
+ seriesId: number().int(),
17544
+ deviceId: number().int(),
17545
+ key: string$2(),
17546
+ scope: string$2(),
17547
+ /** The metric's display name; `null` when its metric row is gone too. */
17548
+ displayName: string$2().nullable(),
17549
+ reason: DeviceHistoryOrphanReasonSchema,
17550
+ /** `device-gone`: since when the device has been absent; `null` otherwise. */
17551
+ missingSince: number().nullable(),
17552
+ firstTs: number(),
17553
+ lastTs: number(),
17554
+ rows: TierRowsSchema
17555
+ });
17556
+ var DeviceHistoryOrphanDeleteRefusalSchema = _enum([
17557
+ "not-found",
17558
+ "not-orphan",
17559
+ "failed"
17560
+ ]);
17561
+ var OrphanDeleteEntrySchema = discriminatedUnion("ok", [object({
17562
+ seriesId: number().int(),
17563
+ ok: literal(true),
17564
+ deleted: TierRowsSchema
17565
+ }), object({
17566
+ seriesId: number().int(),
17567
+ ok: literal(false),
17568
+ reason: DeviceHistoryOrphanDeleteRefusalSchema
17569
+ })]);
17570
+ var OrphanListSchema = object({
17571
+ series: array(OrphanSeriesSchema).readonly(),
17572
+ /** More orphans exist than {@link DEVICE_HISTORY_ORPHAN_LIST_MAX}. */
17573
+ truncated: boolean()
17574
+ });
17521
17575
  var DeviceHistoryStatusSchema = object({
17522
17576
  startedAt: number(),
17523
17577
  /** The store is declared, series loaded and the first reconcile has answered. */
@@ -17615,7 +17669,10 @@ method(object({ deviceId: number().int() }), array(SeriesInfoSchema).readonly())
17615
17669
  }), object({ enabled: boolean() }), {
17616
17670
  kind: "mutation",
17617
17671
  auth: "admin"
17618
- }), method(object({}), DeviceHistoryStatusSchema, { auth: "admin" });
17672
+ }), 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() }), {
17673
+ kind: "mutation",
17674
+ auth: "admin"
17675
+ });
17619
17676
  var DeviceCaStatusSchema = discriminatedUnion("state", [
17620
17677
  object({ state: literal("absent") }),
17621
17678
  object({
@@ -55492,17 +55549,69 @@ var connectivityCapability = {
55492
55549
  volatileStateFields: ["lastChangedAt"]
55493
55550
  };
55494
55551
  /**
55495
- * Generic device-consumables capability — surfaces a device's
55496
- * maintenance items (vacuum filters/brushes, replaceable cartridges,
55497
- * descaling cycles, …) with their remaining life and an optional
55498
- * "Replaced" reset action. Device-agnostic: any provider that knows its
55499
- * device tracks consumables can register it; the cap declares no
55500
- * vocabulary of its own — the provider names each item verbatim.
55552
+ * Generic device-consumables capability — the ONE place a device reports what
55553
+ * it uses up or fills: wear parts (vacuum filters/brushes, cartridges,
55554
+ * descaling cycles), supplies it draws from (a vacuum's clean-water tank and
55555
+ * detergent, a dishwasher's salt and rinse aid) and waste it collects (a dirty
55556
+ * water tank, a dust bin). Each item carries its remaining life or fill and an
55557
+ * optional "Replaced" reset action. Device-agnostic: any provider that knows
55558
+ * its device tracks consumables registers it; the provider names each item
55559
+ * verbatim and says which `kind` it is.
55560
+ *
55561
+ * The admin UI renders it as ONE collapsible section directly under the
55562
+ * device page's hero card (`placement: 'hero'`), for every device bound to
55563
+ * this cap — never drawn by a device type's hero card itself (D915).
55501
55564
  *
55502
55565
  * Like `childLayout`, the cap is INERT until a provider sets items: no
55503
55566
  * provider populates it by guessing (no HA inference). The UI renders a
55504
55567
  * "No consumables reported" placeholder when `items` is empty.
55505
55568
  */
55569
+ /**
55570
+ * What an item IS, which decides which direction is bad:
55571
+ * - `wear` — a part that wears out (a brush, a filter); low life is bad.
55572
+ * - `supply` — something the device draws from (clean water, detergent,
55573
+ * salt, rinse aid); low or empty is bad.
55574
+ * - `waste` — something the device fills (dirty water, a dust bin); full is
55575
+ * bad.
55576
+ * Absent = `wear`.
55577
+ */
55578
+ var ConsumableKindSchema = _enum([
55579
+ "wear",
55580
+ "supply",
55581
+ "waste"
55582
+ ]);
55583
+ /**
55584
+ * What an item LOOKS like, which decides how a client draws it — independent
55585
+ * of `kind`, which decides which direction is bad:
55586
+ * - `part` — a part that wears (a brush, a filter, a mop pad): a wear bar,
55587
+ * remaining time and a reset.
55588
+ * - `tank` — a container of liquid (clean water, dirty water): a fill gauge.
55589
+ * - `product` — something bought and refilled (detergent, salt, rinse aid):
55590
+ * a stepped level and "refill".
55591
+ * - `bin` — a container that collects waste (a dust bin): a fill gauge
55592
+ * that warns when full.
55593
+ * Absent = derived from the kind ({@link consumableFormOf}).
55594
+ */
55595
+ var ConsumableFormSchema = _enum([
55596
+ "part",
55597
+ "tank",
55598
+ "product",
55599
+ "bin"
55600
+ ]);
55601
+ /** The provider's own discrete verdict on an item. */
55602
+ var ConsumableStatusSchema = _enum([
55603
+ "ok",
55604
+ "low",
55605
+ "empty",
55606
+ "full",
55607
+ "replace"
55608
+ ]);
55609
+ _enum([
55610
+ "ok",
55611
+ "low",
55612
+ "empty",
55613
+ "full"
55614
+ ]);
55506
55615
  /** Units a remaining-life counter is reported in. Closed: the panel renders
55507
55616
  * each. */
55508
55617
  var ConsumableRemainingUnitSchema = _enum([
@@ -55517,18 +55626,23 @@ var ConsumableRemainingSchema = object({
55517
55626
  unit: ConsumableRemainingUnitSchema
55518
55627
  });
55519
55628
  /** A single consumable item. Either a continuous `level` (remaining
55520
- * life %) or a discrete `status` may be known — both may be null when a
55521
- * provider only knows the item exists. `level` and `status` are not
55522
- * mutually exclusive; a provider may report both. */
55629
+ * life %, or fill % for a `supply` / `waste` item) or a discrete `status`
55630
+ * may be known — both may be null when a provider only knows the item
55631
+ * exists. `level` and `status` are not mutually exclusive; a provider may
55632
+ * report both. */
55523
55633
  var ConsumableItemSchema = object({
55524
55634
  /** Stable id, e.g. 'main-brush'. */
55525
55635
  key: string$2().min(1),
55526
55636
  /** Display name. */
55527
55637
  label: string$2().min(1),
55528
- /** Remaining life % when known (0..100). */
55638
+ /** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
55529
55639
  level: number().min(0).max(100).nullable(),
55530
- /** Discrete state when known (binary mode). */
55531
- status: _enum(["ok", "replace"]).nullable(),
55640
+ /** The provider's discrete verdict when known (binary mode). */
55641
+ status: ConsumableStatusSchema.nullable(),
55642
+ /** What the item is — decides whether low or full is bad. Absent = `wear`. */
55643
+ kind: ConsumableKindSchema.optional(),
55644
+ /** How the item is drawn (part, tank, product, bin). Absent = derived from `kind`. */
55645
+ form: ConsumableFormSchema.optional(),
55532
55646
  /** Ms epoch of the last replace, when known. */
55533
55647
  lastResetAt: number().nullable(),
55534
55648
  /** Whether `reset()` is meaningful for this item. */
@@ -55551,7 +55665,7 @@ var consumablesCapability = {
55551
55665
  kind: "widget",
55552
55666
  widgetId: "host/consumables-panel",
55553
55667
  tab: "consumables",
55554
- topTab: true,
55668
+ placement: "hero",
55555
55669
  label: "Consumables",
55556
55670
  order: 5
55557
55671
  } },
@@ -55612,9 +55726,37 @@ reset: method(object({
55612
55726
  */
55613
55727
  durability: "restored",
55614
55728
  /**
55615
- * History (D850): none — `items` is an array keyed by runtime ids; a history path never enters it.
55729
+ * History (D850, D917): one series per (item field, item `key`) — the item key
55730
+ * is the series scope, the item `label` names it. A vacuum tank's fill, a
55731
+ * brush's remaining life and a dishwasher's salt are each recorded the moment
55732
+ * their provider reports them; an item that appears later gets its series.
55616
55733
  */
55617
- history: "none",
55734
+ history: {
55735
+ fields: {},
55736
+ items: {
55737
+ path: "items",
55738
+ key: "key",
55739
+ label: "label",
55740
+ fields: {
55741
+ level: {
55742
+ kind: "gauge",
55743
+ unit: "%",
55744
+ deadband: 2,
55745
+ displayName: "Level"
55746
+ },
55747
+ status: {
55748
+ kind: "enum",
55749
+ displayName: "Status"
55750
+ },
55751
+ "remaining.value": {
55752
+ kind: "gauge",
55753
+ unitFrom: "remaining.unit",
55754
+ deadband: 1,
55755
+ displayName: "Remaining"
55756
+ }
55757
+ }
55758
+ }
55759
+ },
55618
55760
  /** Clocks, not content: a re-read that changed no item costs no commit. */
55619
55761
  volatileStateFields: ["lastChangedAt", "lastFetchedAt"]
55620
55762
  };
@@ -56029,8 +56171,9 @@ onStatusChanged: { data: object({
56029
56171
  volatileStateFields: ["lastChangedAt"]
56030
56172
  };
56031
56173
  /**
56032
- * Smart-dishwasher cap — program lifecycle, door / remote-start gates,
56033
- * consumable levels (salt, rinse aid) and common program options.
56174
+ * Smart-dishwasher cap — program lifecycle, door / remote-start gates and
56175
+ * common program options. Salt and rinse aid are NOT here: they are items of
56176
+ * the device's `consumables` cap, like every other device's (D915).
56034
56177
  *
56035
56178
  * Sources: native Bosch Home Connect (`dishwasher` device type). Reusable
56036
56179
  * by any integration that exposes the same program / option surface.
@@ -56078,11 +56221,6 @@ var DishwasherAvailabilitySchema = _enum([
56078
56221
  "offline",
56079
56222
  "description-missing"
56080
56223
  ]);
56081
- var DishwasherConsumableLevelSchema = _enum([
56082
- "ok",
56083
- "low",
56084
- "empty"
56085
- ]);
56086
56224
  var DishwasherStatusSchema = object({
56087
56225
  availability: DishwasherAvailabilitySchema,
56088
56226
  /** Coarse state for compact surfaces; `unavailable` whenever the appliance state is not known. */
@@ -56115,8 +56253,6 @@ var DishwasherStatusSchema = object({
56115
56253
  powerOn: boolean().nullable(),
56116
56254
  /** The raw power state (`On`, `Off`, `Standby`, …); null when not known. */
56117
56255
  powerState: string$2().nullable(),
56118
- saltLevel: DishwasherConsumableLevelSchema.nullable(),
56119
- rinseAidLevel: DishwasherConsumableLevelSchema.nullable(),
56120
56256
  /**
56121
56257
  * True while the appliance asks for its filter to be cleaned (smart-filter, filter-system or
56122
56258
  * combined care-and-filter reminder raised); false when every such reminder reads clear; null
@@ -64932,60 +65068,17 @@ method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserI
64932
65068
  auth: "admin",
64933
65069
  access: "delete"
64934
65070
  });
64935
- /**
64936
- * Robot-vacuum cap. Models HA `vacuum.*` entities — anything with a
64937
- * cleaning lifecycle plus a return-to-base / locate surface and an
64938
- * optional fan-speed selector.
64939
- *
64940
- * State follows HA's canonical vacuum lifecycle: `idle` / `cleaning` /
64941
- * `paused` / `returning` / `docked` / `error`. `batteryLevel`
64942
- * (0..100) is nullable — some vacuums don't report a battery
64943
- * percentage. `fanSpeed` is the current speed token (provider-verbatim,
64944
- * e.g. `'standard'` / `'turbo'`) and `availableFanSpeeds` lists the
64945
- * tokens the hardware accepts so the UI renders only supported choices.
64946
- *
64947
- * The `setFanSpeed` method takes the bare `speed` token — the provider
64948
- * validates it against the vacuum's own list. `locate` triggers the
64949
- * find-me chirp; `returnToBase` sends it home.
64950
- *
64951
- * Consumable / waste tanks: `cleanWater` / `dirtyWater` / `detergent` /
64952
- * `dustBin` each carry a nullable `{ level (0..100 %), status ('ok' |
64953
- * 'low' | 'full') }` reading. Native providers (e.g. Dreame, Roborock)
64954
- * SHOULD populate whichever tanks the hardware has — leave a field `null`
64955
- * only when the device has no such tank at all, and use a `TankStatus`
64956
- * with both inner fields `null` when the tank exists but its level is
64957
- * currently unknown. HA `vacuum.*` entities expose no per-tank telemetry,
64958
- * so the HA provider leaves all four `null`.
64959
- */
64960
- var VacuumStateSchema = _enum([
64961
- "idle",
64962
- "cleaning",
64963
- "paused",
64964
- "returning",
64965
- "docked",
64966
- "drying",
64967
- "error"
64968
- ]);
64969
- /**
64970
- * One consumable / waste tank on a robot vacuum (clean-water, dirty-water,
64971
- * detergent or dust-bin). A tank can report a numeric fill `level` (0..100),
64972
- * a discrete `status` (binary-style hardware), or both. Both `null` means the
64973
- * level is currently unknown; the OWNING field being `null` means the
64974
- * hardware has no such tank at all.
64975
- */
64976
- var TankStatusSchema = object({
64977
- /** Numeric fill 0..100 when the hardware reports a percentage; null otherwise. */
64978
- level: number().min(0).max(100).nullable(),
64979
- /** Discrete state when the hardware is binary-mode; null otherwise. */
64980
- status: _enum([
64981
- "ok",
64982
- "low",
64983
- "full"
64984
- ]).nullable()
64985
- });
64986
65071
  var VacuumControlStatusSchema = object({
64987
65072
  /** Lifecycle state of the vacuum. */
64988
- state: VacuumStateSchema,
65073
+ state: _enum([
65074
+ "idle",
65075
+ "cleaning",
65076
+ "paused",
65077
+ "returning",
65078
+ "docked",
65079
+ "drying",
65080
+ "error"
65081
+ ]),
64989
65082
  /** 0..100 battery percentage. Null when the device has no battery
64990
65083
  * reading. */
64991
65084
  batteryLevel: number().min(0).max(100).nullable(),
@@ -64994,14 +65087,6 @@ var VacuumControlStatusSchema = object({
64994
65087
  fanSpeed: string$2().nullable(),
64995
65088
  /** Speed tokens the hardware accepts — drives the UI selector. */
64996
65089
  availableFanSpeeds: array(string$2()),
64997
- /** Clean-water (mop) tank. Null when the hardware has no clean-water tank. */
64998
- cleanWater: TankStatusSchema.nullable(),
64999
- /** Dirty-water (recovery) tank. Null when the hardware has no dirty-water tank. */
65000
- dirtyWater: TankStatusSchema.nullable(),
65001
- /** Detergent tank. Null when the hardware has no detergent tank. */
65002
- detergent: TankStatusSchema.nullable(),
65003
- /** Dust bin. Null when the hardware has no dust bin. */
65004
- dustBin: TankStatusSchema.nullable(),
65005
65090
  /** 0..100 cleaning-completion percentage of the current task, or null. */
65006
65091
  progressPercent: number().min(0).max(100).nullable(),
65007
65092
  /** Current error code (0 / null = no error). */
@@ -65063,35 +65148,14 @@ var vacuumControlCapability = {
65063
65148
  */
65064
65149
  durability: "session",
65065
65150
  /**
65066
- * History (D850): recorded series. Tank levels are fixed-object paths (`cleanWater.level`, ...).
65151
+ * History (D850): recorded series. The tanks moved to `consumables` (D915), whose
65152
+ * items are keyed by runtime ids and record no history.
65067
65153
  */
65068
- history: { fields: {
65069
- batteryLevel: {
65070
- kind: "gauge",
65071
- unit: "%",
65072
- deadband: 2
65073
- },
65074
- "cleanWater.level": {
65075
- kind: "gauge",
65076
- unit: "%",
65077
- deadband: 2
65078
- },
65079
- "dirtyWater.level": {
65080
- kind: "gauge",
65081
- unit: "%",
65082
- deadband: 2
65083
- },
65084
- "detergent.level": {
65085
- kind: "gauge",
65086
- unit: "%",
65087
- deadband: 2
65088
- },
65089
- "dustBin.level": {
65090
- kind: "gauge",
65091
- unit: "%",
65092
- deadband: 2
65093
- }
65094
- } }
65154
+ history: { fields: { batteryLevel: {
65155
+ kind: "gauge",
65156
+ unit: "%",
65157
+ deadband: 2
65158
+ } } }
65095
65159
  };
65096
65160
  var ValveStatusSchema = object({
65097
65161
  /** Lifecycle state of the valve. */
@@ -69485,6 +69549,12 @@ Object.freeze({
69485
69549
  addonId: null,
69486
69550
  access: "create"
69487
69551
  },
69552
+ "deviceHistory.deleteOrphanSeries": {
69553
+ capName: "device-history",
69554
+ capScope: "system",
69555
+ addonId: null,
69556
+ access: "delete"
69557
+ },
69488
69558
  "deviceHistory.getDeviceEnabled": {
69489
69559
  capName: "device-history",
69490
69560
  capScope: "system",
@@ -69503,6 +69573,12 @@ Object.freeze({
69503
69573
  addonId: null,
69504
69574
  access: "view"
69505
69575
  },
69576
+ "deviceHistory.listOrphanSeries": {
69577
+ capName: "device-history",
69578
+ capScope: "system",
69579
+ addonId: null,
69580
+ access: "view"
69581
+ },
69506
69582
  "deviceHistory.listSeries": {
69507
69583
  capName: "device-history",
69508
69584
  capScope: "system",
@@ -79508,7 +79584,7 @@ var STATE_SUMMARY_VARS = [
79508
79584
  ([...RULE_TEXT], [...COMBINED_ALARM]),
79509
79585
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
79510
79586
  ([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
79511
- ([...RULE_TEXT], [...CONSUMABLE]),
79587
+ ([...RULE_TEXT], [...CONSUMABLE, ...TANK]),
79512
79588
  ([...RULE_TEXT], [...TANK]),
79513
79589
  [...RULE_TEXT],
79514
79590
  ([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-matter-broker",
3
- "version": "0.2.144",
3
+ "version": "0.2.145",
4
4
  "description": "Matter broker addon for CamStack — owns a Matter fabric (commissioning + the long-lived controller) via the matter.js controller and brokers commissioned Matter nodes into CamStack",
5
5
  "keywords": [
6
6
  "camstack",