@camstack/addon-matter-broker 0.2.143 → 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 -123
  2. package/dist/addon.mjs +193 -123
  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({
@@ -48345,7 +48402,6 @@ var RecommendationReasonSchema = discriminatedUnion("kind", [
48345
48402
  modelId: string$2()
48346
48403
  }),
48347
48404
  object({ kind: literal("cpu-device") }),
48348
- object({ kind: literal("coral-untouched") }),
48349
48405
  object({ kind: literal("device-disabled") }),
48350
48406
  object({ kind: literal("device-unavailable") }),
48351
48407
  object({ kind: literal("node-offline") }),
@@ -48443,11 +48499,6 @@ var AutoTuneWarningSchema = discriminatedUnion("kind", [
48443
48499
  kind: literal("detector-store-unreadable"),
48444
48500
  error: string$2()
48445
48501
  }),
48446
- object({
48447
- kind: literal("coral-enabled"),
48448
- nodeId: string$2(),
48449
- deviceKey: string$2()
48450
- }),
48451
48502
  object({
48452
48503
  kind: literal("custom-pin-kept"),
48453
48504
  nodeId: string$2(),
@@ -55500,17 +55551,69 @@ var connectivityCapability = {
55500
55551
  volatileStateFields: ["lastChangedAt"]
55501
55552
  };
55502
55553
  /**
55503
- * Generic device-consumables capability — surfaces a device's
55504
- * maintenance items (vacuum filters/brushes, replaceable cartridges,
55505
- * descaling cycles, …) with their remaining life and an optional
55506
- * "Replaced" reset action. Device-agnostic: any provider that knows its
55507
- * device tracks consumables can register it; the cap declares no
55508
- * 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).
55509
55566
  *
55510
55567
  * Like `childLayout`, the cap is INERT until a provider sets items: no
55511
55568
  * provider populates it by guessing (no HA inference). The UI renders a
55512
55569
  * "No consumables reported" placeholder when `items` is empty.
55513
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
+ ]);
55514
55617
  /** Units a remaining-life counter is reported in. Closed: the panel renders
55515
55618
  * each. */
55516
55619
  var ConsumableRemainingUnitSchema = _enum([
@@ -55525,18 +55628,23 @@ var ConsumableRemainingSchema = object({
55525
55628
  unit: ConsumableRemainingUnitSchema
55526
55629
  });
55527
55630
  /** A single consumable item. Either a continuous `level` (remaining
55528
- * life %) or a discrete `status` may be known — both may be null when a
55529
- * provider only knows the item exists. `level` and `status` are not
55530
- * 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. */
55531
55635
  var ConsumableItemSchema = object({
55532
55636
  /** Stable id, e.g. 'main-brush'. */
55533
55637
  key: string$2().min(1),
55534
55638
  /** Display name. */
55535
55639
  label: string$2().min(1),
55536
- /** Remaining life % when known (0..100). */
55640
+ /** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
55537
55641
  level: number().min(0).max(100).nullable(),
55538
- /** Discrete state when known (binary mode). */
55539
- 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(),
55540
55648
  /** Ms epoch of the last replace, when known. */
55541
55649
  lastResetAt: number().nullable(),
55542
55650
  /** Whether `reset()` is meaningful for this item. */
@@ -55559,7 +55667,7 @@ var consumablesCapability = {
55559
55667
  kind: "widget",
55560
55668
  widgetId: "host/consumables-panel",
55561
55669
  tab: "consumables",
55562
- topTab: true,
55670
+ placement: "hero",
55563
55671
  label: "Consumables",
55564
55672
  order: 5
55565
55673
  } },
@@ -55620,9 +55728,37 @@ reset: method(object({
55620
55728
  */
55621
55729
  durability: "restored",
55622
55730
  /**
55623
- * 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.
55624
55735
  */
55625
- 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
+ },
55626
55762
  /** Clocks, not content: a re-read that changed no item costs no commit. */
55627
55763
  volatileStateFields: ["lastChangedAt", "lastFetchedAt"]
55628
55764
  };
@@ -56037,8 +56173,9 @@ onStatusChanged: { data: object({
56037
56173
  volatileStateFields: ["lastChangedAt"]
56038
56174
  };
56039
56175
  /**
56040
- * Smart-dishwasher cap — program lifecycle, door / remote-start gates,
56041
- * 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).
56042
56179
  *
56043
56180
  * Sources: native Bosch Home Connect (`dishwasher` device type). Reusable
56044
56181
  * by any integration that exposes the same program / option surface.
@@ -56086,11 +56223,6 @@ var DishwasherAvailabilitySchema = _enum([
56086
56223
  "offline",
56087
56224
  "description-missing"
56088
56225
  ]);
56089
- var DishwasherConsumableLevelSchema = _enum([
56090
- "ok",
56091
- "low",
56092
- "empty"
56093
- ]);
56094
56226
  var DishwasherStatusSchema = object({
56095
56227
  availability: DishwasherAvailabilitySchema,
56096
56228
  /** Coarse state for compact surfaces; `unavailable` whenever the appliance state is not known. */
@@ -56123,8 +56255,6 @@ var DishwasherStatusSchema = object({
56123
56255
  powerOn: boolean().nullable(),
56124
56256
  /** The raw power state (`On`, `Off`, `Standby`, …); null when not known. */
56125
56257
  powerState: string$2().nullable(),
56126
- saltLevel: DishwasherConsumableLevelSchema.nullable(),
56127
- rinseAidLevel: DishwasherConsumableLevelSchema.nullable(),
56128
56258
  /**
56129
56259
  * True while the appliance asks for its filter to be cleaned (smart-filter, filter-system or
56130
56260
  * combined care-and-filter reminder raised); false when every such reminder reads clear; null
@@ -64940,60 +65070,17 @@ method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserI
64940
65070
  auth: "admin",
64941
65071
  access: "delete"
64942
65072
  });
64943
- /**
64944
- * Robot-vacuum cap. Models HA `vacuum.*` entities — anything with a
64945
- * cleaning lifecycle plus a return-to-base / locate surface and an
64946
- * optional fan-speed selector.
64947
- *
64948
- * State follows HA's canonical vacuum lifecycle: `idle` / `cleaning` /
64949
- * `paused` / `returning` / `docked` / `error`. `batteryLevel`
64950
- * (0..100) is nullable — some vacuums don't report a battery
64951
- * percentage. `fanSpeed` is the current speed token (provider-verbatim,
64952
- * e.g. `'standard'` / `'turbo'`) and `availableFanSpeeds` lists the
64953
- * tokens the hardware accepts so the UI renders only supported choices.
64954
- *
64955
- * The `setFanSpeed` method takes the bare `speed` token — the provider
64956
- * validates it against the vacuum's own list. `locate` triggers the
64957
- * find-me chirp; `returnToBase` sends it home.
64958
- *
64959
- * Consumable / waste tanks: `cleanWater` / `dirtyWater` / `detergent` /
64960
- * `dustBin` each carry a nullable `{ level (0..100 %), status ('ok' |
64961
- * 'low' | 'full') }` reading. Native providers (e.g. Dreame, Roborock)
64962
- * SHOULD populate whichever tanks the hardware has — leave a field `null`
64963
- * only when the device has no such tank at all, and use a `TankStatus`
64964
- * with both inner fields `null` when the tank exists but its level is
64965
- * currently unknown. HA `vacuum.*` entities expose no per-tank telemetry,
64966
- * so the HA provider leaves all four `null`.
64967
- */
64968
- var VacuumStateSchema = _enum([
64969
- "idle",
64970
- "cleaning",
64971
- "paused",
64972
- "returning",
64973
- "docked",
64974
- "drying",
64975
- "error"
64976
- ]);
64977
- /**
64978
- * One consumable / waste tank on a robot vacuum (clean-water, dirty-water,
64979
- * detergent or dust-bin). A tank can report a numeric fill `level` (0..100),
64980
- * a discrete `status` (binary-style hardware), or both. Both `null` means the
64981
- * level is currently unknown; the OWNING field being `null` means the
64982
- * hardware has no such tank at all.
64983
- */
64984
- var TankStatusSchema = object({
64985
- /** Numeric fill 0..100 when the hardware reports a percentage; null otherwise. */
64986
- level: number().min(0).max(100).nullable(),
64987
- /** Discrete state when the hardware is binary-mode; null otherwise. */
64988
- status: _enum([
64989
- "ok",
64990
- "low",
64991
- "full"
64992
- ]).nullable()
64993
- });
64994
65073
  var VacuumControlStatusSchema = object({
64995
65074
  /** Lifecycle state of the vacuum. */
64996
- state: VacuumStateSchema,
65075
+ state: _enum([
65076
+ "idle",
65077
+ "cleaning",
65078
+ "paused",
65079
+ "returning",
65080
+ "docked",
65081
+ "drying",
65082
+ "error"
65083
+ ]),
64997
65084
  /** 0..100 battery percentage. Null when the device has no battery
64998
65085
  * reading. */
64999
65086
  batteryLevel: number().min(0).max(100).nullable(),
@@ -65002,14 +65089,6 @@ var VacuumControlStatusSchema = object({
65002
65089
  fanSpeed: string$2().nullable(),
65003
65090
  /** Speed tokens the hardware accepts — drives the UI selector. */
65004
65091
  availableFanSpeeds: array(string$2()),
65005
- /** Clean-water (mop) tank. Null when the hardware has no clean-water tank. */
65006
- cleanWater: TankStatusSchema.nullable(),
65007
- /** Dirty-water (recovery) tank. Null when the hardware has no dirty-water tank. */
65008
- dirtyWater: TankStatusSchema.nullable(),
65009
- /** Detergent tank. Null when the hardware has no detergent tank. */
65010
- detergent: TankStatusSchema.nullable(),
65011
- /** Dust bin. Null when the hardware has no dust bin. */
65012
- dustBin: TankStatusSchema.nullable(),
65013
65092
  /** 0..100 cleaning-completion percentage of the current task, or null. */
65014
65093
  progressPercent: number().min(0).max(100).nullable(),
65015
65094
  /** Current error code (0 / null = no error). */
@@ -65071,35 +65150,14 @@ var vacuumControlCapability = {
65071
65150
  */
65072
65151
  durability: "session",
65073
65152
  /**
65074
- * 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.
65075
65155
  */
65076
- history: { fields: {
65077
- batteryLevel: {
65078
- kind: "gauge",
65079
- unit: "%",
65080
- deadband: 2
65081
- },
65082
- "cleanWater.level": {
65083
- kind: "gauge",
65084
- unit: "%",
65085
- deadband: 2
65086
- },
65087
- "dirtyWater.level": {
65088
- kind: "gauge",
65089
- unit: "%",
65090
- deadband: 2
65091
- },
65092
- "detergent.level": {
65093
- kind: "gauge",
65094
- unit: "%",
65095
- deadband: 2
65096
- },
65097
- "dustBin.level": {
65098
- kind: "gauge",
65099
- unit: "%",
65100
- deadband: 2
65101
- }
65102
- } }
65156
+ history: { fields: { batteryLevel: {
65157
+ kind: "gauge",
65158
+ unit: "%",
65159
+ deadband: 2
65160
+ } } }
65103
65161
  };
65104
65162
  var ValveStatusSchema = object({
65105
65163
  /** Lifecycle state of the valve. */
@@ -69493,6 +69551,12 @@ Object.freeze({
69493
69551
  addonId: null,
69494
69552
  access: "create"
69495
69553
  },
69554
+ "deviceHistory.deleteOrphanSeries": {
69555
+ capName: "device-history",
69556
+ capScope: "system",
69557
+ addonId: null,
69558
+ access: "delete"
69559
+ },
69496
69560
  "deviceHistory.getDeviceEnabled": {
69497
69561
  capName: "device-history",
69498
69562
  capScope: "system",
@@ -69511,6 +69575,12 @@ Object.freeze({
69511
69575
  addonId: null,
69512
69576
  access: "view"
69513
69577
  },
69578
+ "deviceHistory.listOrphanSeries": {
69579
+ capName: "device-history",
69580
+ capScope: "system",
69581
+ addonId: null,
69582
+ access: "view"
69583
+ },
69514
69584
  "deviceHistory.listSeries": {
69515
69585
  capName: "device-history",
69516
69586
  capScope: "system",
@@ -79516,7 +79586,7 @@ var STATE_SUMMARY_VARS = [
79516
79586
  ([...RULE_TEXT], [...COMBINED_ALARM]),
79517
79587
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
79518
79588
  ([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
79519
- ([...RULE_TEXT], [...CONSUMABLE]),
79589
+ ([...RULE_TEXT], [...CONSUMABLE, ...TANK]),
79520
79590
  ([...RULE_TEXT], [...TANK]),
79521
79591
  [...RULE_TEXT],
79522
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({
@@ -48343,7 +48400,6 @@ var RecommendationReasonSchema = discriminatedUnion("kind", [
48343
48400
  modelId: string$2()
48344
48401
  }),
48345
48402
  object({ kind: literal("cpu-device") }),
48346
- object({ kind: literal("coral-untouched") }),
48347
48403
  object({ kind: literal("device-disabled") }),
48348
48404
  object({ kind: literal("device-unavailable") }),
48349
48405
  object({ kind: literal("node-offline") }),
@@ -48441,11 +48497,6 @@ var AutoTuneWarningSchema = discriminatedUnion("kind", [
48441
48497
  kind: literal("detector-store-unreadable"),
48442
48498
  error: string$2()
48443
48499
  }),
48444
- object({
48445
- kind: literal("coral-enabled"),
48446
- nodeId: string$2(),
48447
- deviceKey: string$2()
48448
- }),
48449
48500
  object({
48450
48501
  kind: literal("custom-pin-kept"),
48451
48502
  nodeId: string$2(),
@@ -55498,17 +55549,69 @@ var connectivityCapability = {
55498
55549
  volatileStateFields: ["lastChangedAt"]
55499
55550
  };
55500
55551
  /**
55501
- * Generic device-consumables capability — surfaces a device's
55502
- * maintenance items (vacuum filters/brushes, replaceable cartridges,
55503
- * descaling cycles, …) with their remaining life and an optional
55504
- * "Replaced" reset action. Device-agnostic: any provider that knows its
55505
- * device tracks consumables can register it; the cap declares no
55506
- * 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).
55507
55564
  *
55508
55565
  * Like `childLayout`, the cap is INERT until a provider sets items: no
55509
55566
  * provider populates it by guessing (no HA inference). The UI renders a
55510
55567
  * "No consumables reported" placeholder when `items` is empty.
55511
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
+ ]);
55512
55615
  /** Units a remaining-life counter is reported in. Closed: the panel renders
55513
55616
  * each. */
55514
55617
  var ConsumableRemainingUnitSchema = _enum([
@@ -55523,18 +55626,23 @@ var ConsumableRemainingSchema = object({
55523
55626
  unit: ConsumableRemainingUnitSchema
55524
55627
  });
55525
55628
  /** A single consumable item. Either a continuous `level` (remaining
55526
- * life %) or a discrete `status` may be known — both may be null when a
55527
- * provider only knows the item exists. `level` and `status` are not
55528
- * 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. */
55529
55633
  var ConsumableItemSchema = object({
55530
55634
  /** Stable id, e.g. 'main-brush'. */
55531
55635
  key: string$2().min(1),
55532
55636
  /** Display name. */
55533
55637
  label: string$2().min(1),
55534
- /** Remaining life % when known (0..100). */
55638
+ /** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
55535
55639
  level: number().min(0).max(100).nullable(),
55536
- /** Discrete state when known (binary mode). */
55537
- 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(),
55538
55646
  /** Ms epoch of the last replace, when known. */
55539
55647
  lastResetAt: number().nullable(),
55540
55648
  /** Whether `reset()` is meaningful for this item. */
@@ -55557,7 +55665,7 @@ var consumablesCapability = {
55557
55665
  kind: "widget",
55558
55666
  widgetId: "host/consumables-panel",
55559
55667
  tab: "consumables",
55560
- topTab: true,
55668
+ placement: "hero",
55561
55669
  label: "Consumables",
55562
55670
  order: 5
55563
55671
  } },
@@ -55618,9 +55726,37 @@ reset: method(object({
55618
55726
  */
55619
55727
  durability: "restored",
55620
55728
  /**
55621
- * 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.
55622
55733
  */
55623
- 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
+ },
55624
55760
  /** Clocks, not content: a re-read that changed no item costs no commit. */
55625
55761
  volatileStateFields: ["lastChangedAt", "lastFetchedAt"]
55626
55762
  };
@@ -56035,8 +56171,9 @@ onStatusChanged: { data: object({
56035
56171
  volatileStateFields: ["lastChangedAt"]
56036
56172
  };
56037
56173
  /**
56038
- * Smart-dishwasher cap — program lifecycle, door / remote-start gates,
56039
- * 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).
56040
56177
  *
56041
56178
  * Sources: native Bosch Home Connect (`dishwasher` device type). Reusable
56042
56179
  * by any integration that exposes the same program / option surface.
@@ -56084,11 +56221,6 @@ var DishwasherAvailabilitySchema = _enum([
56084
56221
  "offline",
56085
56222
  "description-missing"
56086
56223
  ]);
56087
- var DishwasherConsumableLevelSchema = _enum([
56088
- "ok",
56089
- "low",
56090
- "empty"
56091
- ]);
56092
56224
  var DishwasherStatusSchema = object({
56093
56225
  availability: DishwasherAvailabilitySchema,
56094
56226
  /** Coarse state for compact surfaces; `unavailable` whenever the appliance state is not known. */
@@ -56121,8 +56253,6 @@ var DishwasherStatusSchema = object({
56121
56253
  powerOn: boolean().nullable(),
56122
56254
  /** The raw power state (`On`, `Off`, `Standby`, …); null when not known. */
56123
56255
  powerState: string$2().nullable(),
56124
- saltLevel: DishwasherConsumableLevelSchema.nullable(),
56125
- rinseAidLevel: DishwasherConsumableLevelSchema.nullable(),
56126
56256
  /**
56127
56257
  * True while the appliance asks for its filter to be cleaned (smart-filter, filter-system or
56128
56258
  * combined care-and-filter reminder raised); false when every such reminder reads clear; null
@@ -64938,60 +65068,17 @@ method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserI
64938
65068
  auth: "admin",
64939
65069
  access: "delete"
64940
65070
  });
64941
- /**
64942
- * Robot-vacuum cap. Models HA `vacuum.*` entities — anything with a
64943
- * cleaning lifecycle plus a return-to-base / locate surface and an
64944
- * optional fan-speed selector.
64945
- *
64946
- * State follows HA's canonical vacuum lifecycle: `idle` / `cleaning` /
64947
- * `paused` / `returning` / `docked` / `error`. `batteryLevel`
64948
- * (0..100) is nullable — some vacuums don't report a battery
64949
- * percentage. `fanSpeed` is the current speed token (provider-verbatim,
64950
- * e.g. `'standard'` / `'turbo'`) and `availableFanSpeeds` lists the
64951
- * tokens the hardware accepts so the UI renders only supported choices.
64952
- *
64953
- * The `setFanSpeed` method takes the bare `speed` token — the provider
64954
- * validates it against the vacuum's own list. `locate` triggers the
64955
- * find-me chirp; `returnToBase` sends it home.
64956
- *
64957
- * Consumable / waste tanks: `cleanWater` / `dirtyWater` / `detergent` /
64958
- * `dustBin` each carry a nullable `{ level (0..100 %), status ('ok' |
64959
- * 'low' | 'full') }` reading. Native providers (e.g. Dreame, Roborock)
64960
- * SHOULD populate whichever tanks the hardware has — leave a field `null`
64961
- * only when the device has no such tank at all, and use a `TankStatus`
64962
- * with both inner fields `null` when the tank exists but its level is
64963
- * currently unknown. HA `vacuum.*` entities expose no per-tank telemetry,
64964
- * so the HA provider leaves all four `null`.
64965
- */
64966
- var VacuumStateSchema = _enum([
64967
- "idle",
64968
- "cleaning",
64969
- "paused",
64970
- "returning",
64971
- "docked",
64972
- "drying",
64973
- "error"
64974
- ]);
64975
- /**
64976
- * One consumable / waste tank on a robot vacuum (clean-water, dirty-water,
64977
- * detergent or dust-bin). A tank can report a numeric fill `level` (0..100),
64978
- * a discrete `status` (binary-style hardware), or both. Both `null` means the
64979
- * level is currently unknown; the OWNING field being `null` means the
64980
- * hardware has no such tank at all.
64981
- */
64982
- var TankStatusSchema = object({
64983
- /** Numeric fill 0..100 when the hardware reports a percentage; null otherwise. */
64984
- level: number().min(0).max(100).nullable(),
64985
- /** Discrete state when the hardware is binary-mode; null otherwise. */
64986
- status: _enum([
64987
- "ok",
64988
- "low",
64989
- "full"
64990
- ]).nullable()
64991
- });
64992
65071
  var VacuumControlStatusSchema = object({
64993
65072
  /** Lifecycle state of the vacuum. */
64994
- state: VacuumStateSchema,
65073
+ state: _enum([
65074
+ "idle",
65075
+ "cleaning",
65076
+ "paused",
65077
+ "returning",
65078
+ "docked",
65079
+ "drying",
65080
+ "error"
65081
+ ]),
64995
65082
  /** 0..100 battery percentage. Null when the device has no battery
64996
65083
  * reading. */
64997
65084
  batteryLevel: number().min(0).max(100).nullable(),
@@ -65000,14 +65087,6 @@ var VacuumControlStatusSchema = object({
65000
65087
  fanSpeed: string$2().nullable(),
65001
65088
  /** Speed tokens the hardware accepts — drives the UI selector. */
65002
65089
  availableFanSpeeds: array(string$2()),
65003
- /** Clean-water (mop) tank. Null when the hardware has no clean-water tank. */
65004
- cleanWater: TankStatusSchema.nullable(),
65005
- /** Dirty-water (recovery) tank. Null when the hardware has no dirty-water tank. */
65006
- dirtyWater: TankStatusSchema.nullable(),
65007
- /** Detergent tank. Null when the hardware has no detergent tank. */
65008
- detergent: TankStatusSchema.nullable(),
65009
- /** Dust bin. Null when the hardware has no dust bin. */
65010
- dustBin: TankStatusSchema.nullable(),
65011
65090
  /** 0..100 cleaning-completion percentage of the current task, or null. */
65012
65091
  progressPercent: number().min(0).max(100).nullable(),
65013
65092
  /** Current error code (0 / null = no error). */
@@ -65069,35 +65148,14 @@ var vacuumControlCapability = {
65069
65148
  */
65070
65149
  durability: "session",
65071
65150
  /**
65072
- * 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.
65073
65153
  */
65074
- history: { fields: {
65075
- batteryLevel: {
65076
- kind: "gauge",
65077
- unit: "%",
65078
- deadband: 2
65079
- },
65080
- "cleanWater.level": {
65081
- kind: "gauge",
65082
- unit: "%",
65083
- deadband: 2
65084
- },
65085
- "dirtyWater.level": {
65086
- kind: "gauge",
65087
- unit: "%",
65088
- deadband: 2
65089
- },
65090
- "detergent.level": {
65091
- kind: "gauge",
65092
- unit: "%",
65093
- deadband: 2
65094
- },
65095
- "dustBin.level": {
65096
- kind: "gauge",
65097
- unit: "%",
65098
- deadband: 2
65099
- }
65100
- } }
65154
+ history: { fields: { batteryLevel: {
65155
+ kind: "gauge",
65156
+ unit: "%",
65157
+ deadband: 2
65158
+ } } }
65101
65159
  };
65102
65160
  var ValveStatusSchema = object({
65103
65161
  /** Lifecycle state of the valve. */
@@ -69491,6 +69549,12 @@ Object.freeze({
69491
69549
  addonId: null,
69492
69550
  access: "create"
69493
69551
  },
69552
+ "deviceHistory.deleteOrphanSeries": {
69553
+ capName: "device-history",
69554
+ capScope: "system",
69555
+ addonId: null,
69556
+ access: "delete"
69557
+ },
69494
69558
  "deviceHistory.getDeviceEnabled": {
69495
69559
  capName: "device-history",
69496
69560
  capScope: "system",
@@ -69509,6 +69573,12 @@ Object.freeze({
69509
69573
  addonId: null,
69510
69574
  access: "view"
69511
69575
  },
69576
+ "deviceHistory.listOrphanSeries": {
69577
+ capName: "device-history",
69578
+ capScope: "system",
69579
+ addonId: null,
69580
+ access: "view"
69581
+ },
69512
69582
  "deviceHistory.listSeries": {
69513
69583
  capName: "device-history",
69514
69584
  capScope: "system",
@@ -79514,7 +79584,7 @@ var STATE_SUMMARY_VARS = [
79514
79584
  ([...RULE_TEXT], [...COMBINED_ALARM]),
79515
79585
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
79516
79586
  ([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
79517
- ([...RULE_TEXT], [...CONSUMABLE]),
79587
+ ([...RULE_TEXT], [...CONSUMABLE, ...TANK]),
79518
79588
  ([...RULE_TEXT], [...TANK]),
79519
79589
  [...RULE_TEXT],
79520
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.143",
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",