@camstack/addon-provider-tuya 0.2.141 → 0.2.143

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
@@ -6251,7 +6251,7 @@ var ZodIssueCode = {
6251
6251
  var ZodFirstPartyTypeKind;
6252
6252
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
6253
6253
  //#endregion
6254
- //#region ../types/dist/sleep-DJFUfKvA.mjs
6254
+ //#region ../types/dist/sleep-CUp20JkO.mjs
6255
6255
  /**
6256
6256
  * The audio chunk plane's byte format, and the ONE expansion from a coded
6257
6257
  * window to float samples (D455).
@@ -9143,7 +9143,11 @@ var ContributionSectionSchema = object({
9143
9143
  literal(4)
9144
9144
  ]).optional(),
9145
9145
  tab: string().optional(),
9146
- location: _enum(["settings", "top-tab"]).optional(),
9146
+ location: _enum([
9147
+ "settings",
9148
+ "top-tab",
9149
+ "hero"
9150
+ ]).optional(),
9147
9151
  order: number().optional(),
9148
9152
  fields: array(any())
9149
9153
  });
@@ -14076,7 +14080,11 @@ var ConfigSectionWithValuesSchema = object({
14076
14080
  literal(4)
14077
14081
  ]).optional(),
14078
14082
  tab: string().optional(),
14079
- location: _enum(["settings", "top-tab"]).optional(),
14083
+ location: _enum([
14084
+ "settings",
14085
+ "top-tab",
14086
+ "hero"
14087
+ ]).optional(),
14080
14088
  order: number().optional(),
14081
14089
  fields: array(any())
14082
14090
  });
@@ -17956,6 +17964,52 @@ var TierStatusSchema = object({
17956
17964
  countedAt: number().nullable()
17957
17965
  });
17958
17966
  /** Operator/diagnostic view: rows per tier, last runs, refusals and drops since boot. */
17967
+ /**
17968
+ * Why a series is orphan. `device-gone`: its device is absent from the
17969
+ * successful device listings (the departure clock). `undeclared`: its `cap:`
17970
+ * key is declared by no capability any more (a field a cap removed).
17971
+ */
17972
+ var DeviceHistoryOrphanReasonSchema = _enum(["device-gone", "undeclared"]);
17973
+ /** Rows held per stored tier. */
17974
+ var TierRowsSchema = object({
17975
+ raw: number().int(),
17976
+ "5m": number().int(),
17977
+ "1h": number().int(),
17978
+ "1d": number().int()
17979
+ });
17980
+ var OrphanSeriesSchema = object({
17981
+ seriesId: number().int(),
17982
+ deviceId: number().int(),
17983
+ key: string(),
17984
+ scope: string(),
17985
+ /** The metric's display name; `null` when its metric row is gone too. */
17986
+ displayName: string().nullable(),
17987
+ reason: DeviceHistoryOrphanReasonSchema,
17988
+ /** `device-gone`: since when the device has been absent; `null` otherwise. */
17989
+ missingSince: number().nullable(),
17990
+ firstTs: number(),
17991
+ lastTs: number(),
17992
+ rows: TierRowsSchema
17993
+ });
17994
+ var DeviceHistoryOrphanDeleteRefusalSchema = _enum([
17995
+ "not-found",
17996
+ "not-orphan",
17997
+ "failed"
17998
+ ]);
17999
+ var OrphanDeleteEntrySchema = discriminatedUnion("ok", [object({
18000
+ seriesId: number().int(),
18001
+ ok: literal(true),
18002
+ deleted: TierRowsSchema
18003
+ }), object({
18004
+ seriesId: number().int(),
18005
+ ok: literal(false),
18006
+ reason: DeviceHistoryOrphanDeleteRefusalSchema
18007
+ })]);
18008
+ var OrphanListSchema = object({
18009
+ series: array(OrphanSeriesSchema).readonly(),
18010
+ /** More orphans exist than {@link DEVICE_HISTORY_ORPHAN_LIST_MAX}. */
18011
+ truncated: boolean()
18012
+ });
17959
18013
  var DeviceHistoryStatusSchema = object({
17960
18014
  startedAt: number(),
17961
18015
  /** The store is declared, series loaded and the first reconcile has answered. */
@@ -18053,7 +18107,10 @@ method(object({ deviceId: number().int() }), array(SeriesInfoSchema).readonly())
18053
18107
  }), object({ enabled: boolean() }), {
18054
18108
  kind: "mutation",
18055
18109
  auth: "admin"
18056
- }), method(object({}), DeviceHistoryStatusSchema, { auth: "admin" });
18110
+ }), 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() }), {
18111
+ kind: "mutation",
18112
+ auth: "admin"
18113
+ });
18057
18114
  var DeviceCaStatusSchema = discriminatedUnion("state", [
18058
18115
  object({ state: literal("absent") }),
18059
18116
  object({
@@ -48781,7 +48838,6 @@ var RecommendationReasonSchema = discriminatedUnion("kind", [
48781
48838
  modelId: string()
48782
48839
  }),
48783
48840
  object({ kind: literal("cpu-device") }),
48784
- object({ kind: literal("coral-untouched") }),
48785
48841
  object({ kind: literal("device-disabled") }),
48786
48842
  object({ kind: literal("device-unavailable") }),
48787
48843
  object({ kind: literal("node-offline") }),
@@ -48879,11 +48935,6 @@ var AutoTuneWarningSchema = discriminatedUnion("kind", [
48879
48935
  kind: literal("detector-store-unreadable"),
48880
48936
  error: string()
48881
48937
  }),
48882
- object({
48883
- kind: literal("coral-enabled"),
48884
- nodeId: string(),
48885
- deviceKey: string()
48886
- }),
48887
48938
  object({
48888
48939
  kind: literal("custom-pin-kept"),
48889
48940
  nodeId: string(),
@@ -55927,17 +55978,69 @@ var connectivityCapability = {
55927
55978
  volatileStateFields: ["lastChangedAt"]
55928
55979
  };
55929
55980
  /**
55930
- * Generic device-consumables capability — surfaces a device's
55931
- * maintenance items (vacuum filters/brushes, replaceable cartridges,
55932
- * descaling cycles, …) with their remaining life and an optional
55933
- * "Replaced" reset action. Device-agnostic: any provider that knows its
55934
- * device tracks consumables can register it; the cap declares no
55935
- * vocabulary of its own — the provider names each item verbatim.
55981
+ * Generic device-consumables capability — the ONE place a device reports what
55982
+ * it uses up or fills: wear parts (vacuum filters/brushes, cartridges,
55983
+ * descaling cycles), supplies it draws from (a vacuum's clean-water tank and
55984
+ * detergent, a dishwasher's salt and rinse aid) and waste it collects (a dirty
55985
+ * water tank, a dust bin). Each item carries its remaining life or fill and an
55986
+ * optional "Replaced" reset action. Device-agnostic: any provider that knows
55987
+ * its device tracks consumables registers it; the provider names each item
55988
+ * verbatim and says which `kind` it is.
55989
+ *
55990
+ * The admin UI renders it as ONE collapsible section directly under the
55991
+ * device page's hero card (`placement: 'hero'`), for every device bound to
55992
+ * this cap — never drawn by a device type's hero card itself (D915).
55936
55993
  *
55937
55994
  * Like `childLayout`, the cap is INERT until a provider sets items: no
55938
55995
  * provider populates it by guessing (no HA inference). The UI renders a
55939
55996
  * "No consumables reported" placeholder when `items` is empty.
55940
55997
  */
55998
+ /**
55999
+ * What an item IS, which decides which direction is bad:
56000
+ * - `wear` — a part that wears out (a brush, a filter); low life is bad.
56001
+ * - `supply` — something the device draws from (clean water, detergent,
56002
+ * salt, rinse aid); low or empty is bad.
56003
+ * - `waste` — something the device fills (dirty water, a dust bin); full is
56004
+ * bad.
56005
+ * Absent = `wear`.
56006
+ */
56007
+ var ConsumableKindSchema = _enum([
56008
+ "wear",
56009
+ "supply",
56010
+ "waste"
56011
+ ]);
56012
+ /**
56013
+ * What an item LOOKS like, which decides how a client draws it — independent
56014
+ * of `kind`, which decides which direction is bad:
56015
+ * - `part` — a part that wears (a brush, a filter, a mop pad): a wear bar,
56016
+ * remaining time and a reset.
56017
+ * - `tank` — a container of liquid (clean water, dirty water): a fill gauge.
56018
+ * - `product` — something bought and refilled (detergent, salt, rinse aid):
56019
+ * a stepped level and "refill".
56020
+ * - `bin` — a container that collects waste (a dust bin): a fill gauge
56021
+ * that warns when full.
56022
+ * Absent = derived from the kind ({@link consumableFormOf}).
56023
+ */
56024
+ var ConsumableFormSchema = _enum([
56025
+ "part",
56026
+ "tank",
56027
+ "product",
56028
+ "bin"
56029
+ ]);
56030
+ /** The provider's own discrete verdict on an item. */
56031
+ var ConsumableStatusSchema = _enum([
56032
+ "ok",
56033
+ "low",
56034
+ "empty",
56035
+ "full",
56036
+ "replace"
56037
+ ]);
56038
+ _enum([
56039
+ "ok",
56040
+ "low",
56041
+ "empty",
56042
+ "full"
56043
+ ]);
55941
56044
  /** Units a remaining-life counter is reported in. Closed: the panel renders
55942
56045
  * each. */
55943
56046
  var ConsumableRemainingUnitSchema = _enum([
@@ -55952,18 +56055,23 @@ var ConsumableRemainingSchema = object({
55952
56055
  unit: ConsumableRemainingUnitSchema
55953
56056
  });
55954
56057
  /** A single consumable item. Either a continuous `level` (remaining
55955
- * life %) or a discrete `status` may be known — both may be null when a
55956
- * provider only knows the item exists. `level` and `status` are not
55957
- * mutually exclusive; a provider may report both. */
56058
+ * life %, or fill % for a `supply` / `waste` item) or a discrete `status`
56059
+ * may be known — both may be null when a provider only knows the item
56060
+ * exists. `level` and `status` are not mutually exclusive; a provider may
56061
+ * report both. */
55958
56062
  var ConsumableItemSchema = object({
55959
56063
  /** Stable id, e.g. 'main-brush'. */
55960
56064
  key: string().min(1),
55961
56065
  /** Display name. */
55962
56066
  label: string().min(1),
55963
- /** Remaining life % when known (0..100). */
56067
+ /** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
55964
56068
  level: number().min(0).max(100).nullable(),
55965
- /** Discrete state when known (binary mode). */
55966
- status: _enum(["ok", "replace"]).nullable(),
56069
+ /** The provider's discrete verdict when known (binary mode). */
56070
+ status: ConsumableStatusSchema.nullable(),
56071
+ /** What the item is — decides whether low or full is bad. Absent = `wear`. */
56072
+ kind: ConsumableKindSchema.optional(),
56073
+ /** How the item is drawn (part, tank, product, bin). Absent = derived from `kind`. */
56074
+ form: ConsumableFormSchema.optional(),
55967
56075
  /** Ms epoch of the last replace, when known. */
55968
56076
  lastResetAt: number().nullable(),
55969
56077
  /** Whether `reset()` is meaningful for this item. */
@@ -55986,7 +56094,7 @@ var consumablesCapability = {
55986
56094
  kind: "widget",
55987
56095
  widgetId: "host/consumables-panel",
55988
56096
  tab: "consumables",
55989
- topTab: true,
56097
+ placement: "hero",
55990
56098
  label: "Consumables",
55991
56099
  order: 5
55992
56100
  } },
@@ -56047,9 +56155,37 @@ reset: method(object({
56047
56155
  */
56048
56156
  durability: "restored",
56049
56157
  /**
56050
- * History (D850): none — `items` is an array keyed by runtime ids; a history path never enters it.
56158
+ * History (D850, D917): one series per (item field, item `key`) — the item key
56159
+ * is the series scope, the item `label` names it. A vacuum tank's fill, a
56160
+ * brush's remaining life and a dishwasher's salt are each recorded the moment
56161
+ * their provider reports them; an item that appears later gets its series.
56051
56162
  */
56052
- history: "none",
56163
+ history: {
56164
+ fields: {},
56165
+ items: {
56166
+ path: "items",
56167
+ key: "key",
56168
+ label: "label",
56169
+ fields: {
56170
+ level: {
56171
+ kind: "gauge",
56172
+ unit: "%",
56173
+ deadband: 2,
56174
+ displayName: "Level"
56175
+ },
56176
+ status: {
56177
+ kind: "enum",
56178
+ displayName: "Status"
56179
+ },
56180
+ "remaining.value": {
56181
+ kind: "gauge",
56182
+ unitFrom: "remaining.unit",
56183
+ deadband: 1,
56184
+ displayName: "Remaining"
56185
+ }
56186
+ }
56187
+ }
56188
+ },
56053
56189
  /** Clocks, not content: a re-read that changed no item costs no commit. */
56054
56190
  volatileStateFields: ["lastChangedAt", "lastFetchedAt"]
56055
56191
  };
@@ -56464,8 +56600,9 @@ onStatusChanged: { data: object({
56464
56600
  volatileStateFields: ["lastChangedAt"]
56465
56601
  };
56466
56602
  /**
56467
- * Smart-dishwasher cap — program lifecycle, door / remote-start gates,
56468
- * consumable levels (salt, rinse aid) and common program options.
56603
+ * Smart-dishwasher cap — program lifecycle, door / remote-start gates and
56604
+ * common program options. Salt and rinse aid are NOT here: they are items of
56605
+ * the device's `consumables` cap, like every other device's (D915).
56469
56606
  *
56470
56607
  * Sources: native Bosch Home Connect (`dishwasher` device type). Reusable
56471
56608
  * by any integration that exposes the same program / option surface.
@@ -56513,11 +56650,6 @@ var DishwasherAvailabilitySchema = _enum([
56513
56650
  "offline",
56514
56651
  "description-missing"
56515
56652
  ]);
56516
- var DishwasherConsumableLevelSchema = _enum([
56517
- "ok",
56518
- "low",
56519
- "empty"
56520
- ]);
56521
56653
  var DishwasherStatusSchema = object({
56522
56654
  availability: DishwasherAvailabilitySchema,
56523
56655
  /** Coarse state for compact surfaces; `unavailable` whenever the appliance state is not known. */
@@ -56550,8 +56682,6 @@ var DishwasherStatusSchema = object({
56550
56682
  powerOn: boolean().nullable(),
56551
56683
  /** The raw power state (`On`, `Off`, `Standby`, …); null when not known. */
56552
56684
  powerState: string().nullable(),
56553
- saltLevel: DishwasherConsumableLevelSchema.nullable(),
56554
- rinseAidLevel: DishwasherConsumableLevelSchema.nullable(),
56555
56685
  /**
56556
56686
  * True while the appliance asks for its filter to be cleaned (smart-filter, filter-system or
56557
56687
  * combined care-and-filter reminder raised); false when every such reminder reads clear; null
@@ -65367,60 +65497,17 @@ method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserI
65367
65497
  auth: "admin",
65368
65498
  access: "delete"
65369
65499
  });
65370
- /**
65371
- * Robot-vacuum cap. Models HA `vacuum.*` entities — anything with a
65372
- * cleaning lifecycle plus a return-to-base / locate surface and an
65373
- * optional fan-speed selector.
65374
- *
65375
- * State follows HA's canonical vacuum lifecycle: `idle` / `cleaning` /
65376
- * `paused` / `returning` / `docked` / `error`. `batteryLevel`
65377
- * (0..100) is nullable — some vacuums don't report a battery
65378
- * percentage. `fanSpeed` is the current speed token (provider-verbatim,
65379
- * e.g. `'standard'` / `'turbo'`) and `availableFanSpeeds` lists the
65380
- * tokens the hardware accepts so the UI renders only supported choices.
65381
- *
65382
- * The `setFanSpeed` method takes the bare `speed` token — the provider
65383
- * validates it against the vacuum's own list. `locate` triggers the
65384
- * find-me chirp; `returnToBase` sends it home.
65385
- *
65386
- * Consumable / waste tanks: `cleanWater` / `dirtyWater` / `detergent` /
65387
- * `dustBin` each carry a nullable `{ level (0..100 %), status ('ok' |
65388
- * 'low' | 'full') }` reading. Native providers (e.g. Dreame, Roborock)
65389
- * SHOULD populate whichever tanks the hardware has — leave a field `null`
65390
- * only when the device has no such tank at all, and use a `TankStatus`
65391
- * with both inner fields `null` when the tank exists but its level is
65392
- * currently unknown. HA `vacuum.*` entities expose no per-tank telemetry,
65393
- * so the HA provider leaves all four `null`.
65394
- */
65395
- var VacuumStateSchema = _enum([
65396
- "idle",
65397
- "cleaning",
65398
- "paused",
65399
- "returning",
65400
- "docked",
65401
- "drying",
65402
- "error"
65403
- ]);
65404
- /**
65405
- * One consumable / waste tank on a robot vacuum (clean-water, dirty-water,
65406
- * detergent or dust-bin). A tank can report a numeric fill `level` (0..100),
65407
- * a discrete `status` (binary-style hardware), or both. Both `null` means the
65408
- * level is currently unknown; the OWNING field being `null` means the
65409
- * hardware has no such tank at all.
65410
- */
65411
- var TankStatusSchema = object({
65412
- /** Numeric fill 0..100 when the hardware reports a percentage; null otherwise. */
65413
- level: number().min(0).max(100).nullable(),
65414
- /** Discrete state when the hardware is binary-mode; null otherwise. */
65415
- status: _enum([
65416
- "ok",
65417
- "low",
65418
- "full"
65419
- ]).nullable()
65420
- });
65421
65500
  var VacuumControlStatusSchema = object({
65422
65501
  /** Lifecycle state of the vacuum. */
65423
- state: VacuumStateSchema,
65502
+ state: _enum([
65503
+ "idle",
65504
+ "cleaning",
65505
+ "paused",
65506
+ "returning",
65507
+ "docked",
65508
+ "drying",
65509
+ "error"
65510
+ ]),
65424
65511
  /** 0..100 battery percentage. Null when the device has no battery
65425
65512
  * reading. */
65426
65513
  batteryLevel: number().min(0).max(100).nullable(),
@@ -65429,14 +65516,6 @@ var VacuumControlStatusSchema = object({
65429
65516
  fanSpeed: string().nullable(),
65430
65517
  /** Speed tokens the hardware accepts — drives the UI selector. */
65431
65518
  availableFanSpeeds: array(string()),
65432
- /** Clean-water (mop) tank. Null when the hardware has no clean-water tank. */
65433
- cleanWater: TankStatusSchema.nullable(),
65434
- /** Dirty-water (recovery) tank. Null when the hardware has no dirty-water tank. */
65435
- dirtyWater: TankStatusSchema.nullable(),
65436
- /** Detergent tank. Null when the hardware has no detergent tank. */
65437
- detergent: TankStatusSchema.nullable(),
65438
- /** Dust bin. Null when the hardware has no dust bin. */
65439
- dustBin: TankStatusSchema.nullable(),
65440
65519
  /** 0..100 cleaning-completion percentage of the current task, or null. */
65441
65520
  progressPercent: number().min(0).max(100).nullable(),
65442
65521
  /** Current error code (0 / null = no error). */
@@ -65498,35 +65577,14 @@ var vacuumControlCapability = {
65498
65577
  */
65499
65578
  durability: "session",
65500
65579
  /**
65501
- * History (D850): recorded series. Tank levels are fixed-object paths (`cleanWater.level`, ...).
65580
+ * History (D850): recorded series. The tanks moved to `consumables` (D915), whose
65581
+ * items are keyed by runtime ids and record no history.
65502
65582
  */
65503
- history: { fields: {
65504
- batteryLevel: {
65505
- kind: "gauge",
65506
- unit: "%",
65507
- deadband: 2
65508
- },
65509
- "cleanWater.level": {
65510
- kind: "gauge",
65511
- unit: "%",
65512
- deadband: 2
65513
- },
65514
- "dirtyWater.level": {
65515
- kind: "gauge",
65516
- unit: "%",
65517
- deadband: 2
65518
- },
65519
- "detergent.level": {
65520
- kind: "gauge",
65521
- unit: "%",
65522
- deadband: 2
65523
- },
65524
- "dustBin.level": {
65525
- kind: "gauge",
65526
- unit: "%",
65527
- deadband: 2
65528
- }
65529
- } }
65583
+ history: { fields: { batteryLevel: {
65584
+ kind: "gauge",
65585
+ unit: "%",
65586
+ deadband: 2
65587
+ } } }
65530
65588
  };
65531
65589
  var ValveStatusSchema = object({
65532
65590
  /** Lifecycle state of the valve. */
@@ -69920,6 +69978,12 @@ Object.freeze({
69920
69978
  addonId: null,
69921
69979
  access: "create"
69922
69980
  },
69981
+ "deviceHistory.deleteOrphanSeries": {
69982
+ capName: "device-history",
69983
+ capScope: "system",
69984
+ addonId: null,
69985
+ access: "delete"
69986
+ },
69923
69987
  "deviceHistory.getDeviceEnabled": {
69924
69988
  capName: "device-history",
69925
69989
  capScope: "system",
@@ -69938,6 +70002,12 @@ Object.freeze({
69938
70002
  addonId: null,
69939
70003
  access: "view"
69940
70004
  },
70005
+ "deviceHistory.listOrphanSeries": {
70006
+ capName: "device-history",
70007
+ capScope: "system",
70008
+ addonId: null,
70009
+ access: "view"
70010
+ },
69941
70011
  "deviceHistory.listSeries": {
69942
70012
  capName: "device-history",
69943
70013
  capScope: "system",
@@ -79943,7 +80013,7 @@ var STATE_SUMMARY_VARS = [
79943
80013
  ([...RULE_TEXT], [...COMBINED_ALARM]),
79944
80014
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
79945
80015
  ([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
79946
- ([...RULE_TEXT], [...CONSUMABLE]),
80016
+ ([...RULE_TEXT], [...CONSUMABLE, ...TANK]),
79947
80017
  ([...RULE_TEXT], [...TANK]),
79948
80018
  [...RULE_TEXT],
79949
80019
  ([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
package/dist/addon.mjs CHANGED
@@ -6250,7 +6250,7 @@ var ZodIssueCode = {
6250
6250
  var ZodFirstPartyTypeKind;
6251
6251
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
6252
6252
  //#endregion
6253
- //#region ../types/dist/sleep-DJFUfKvA.mjs
6253
+ //#region ../types/dist/sleep-CUp20JkO.mjs
6254
6254
  /**
6255
6255
  * The audio chunk plane's byte format, and the ONE expansion from a coded
6256
6256
  * window to float samples (D455).
@@ -9142,7 +9142,11 @@ var ContributionSectionSchema = object({
9142
9142
  literal(4)
9143
9143
  ]).optional(),
9144
9144
  tab: string().optional(),
9145
- location: _enum(["settings", "top-tab"]).optional(),
9145
+ location: _enum([
9146
+ "settings",
9147
+ "top-tab",
9148
+ "hero"
9149
+ ]).optional(),
9146
9150
  order: number().optional(),
9147
9151
  fields: array(any())
9148
9152
  });
@@ -14075,7 +14079,11 @@ var ConfigSectionWithValuesSchema = object({
14075
14079
  literal(4)
14076
14080
  ]).optional(),
14077
14081
  tab: string().optional(),
14078
- location: _enum(["settings", "top-tab"]).optional(),
14082
+ location: _enum([
14083
+ "settings",
14084
+ "top-tab",
14085
+ "hero"
14086
+ ]).optional(),
14079
14087
  order: number().optional(),
14080
14088
  fields: array(any())
14081
14089
  });
@@ -17955,6 +17963,52 @@ var TierStatusSchema = object({
17955
17963
  countedAt: number().nullable()
17956
17964
  });
17957
17965
  /** Operator/diagnostic view: rows per tier, last runs, refusals and drops since boot. */
17966
+ /**
17967
+ * Why a series is orphan. `device-gone`: its device is absent from the
17968
+ * successful device listings (the departure clock). `undeclared`: its `cap:`
17969
+ * key is declared by no capability any more (a field a cap removed).
17970
+ */
17971
+ var DeviceHistoryOrphanReasonSchema = _enum(["device-gone", "undeclared"]);
17972
+ /** Rows held per stored tier. */
17973
+ var TierRowsSchema = object({
17974
+ raw: number().int(),
17975
+ "5m": number().int(),
17976
+ "1h": number().int(),
17977
+ "1d": number().int()
17978
+ });
17979
+ var OrphanSeriesSchema = object({
17980
+ seriesId: number().int(),
17981
+ deviceId: number().int(),
17982
+ key: string(),
17983
+ scope: string(),
17984
+ /** The metric's display name; `null` when its metric row is gone too. */
17985
+ displayName: string().nullable(),
17986
+ reason: DeviceHistoryOrphanReasonSchema,
17987
+ /** `device-gone`: since when the device has been absent; `null` otherwise. */
17988
+ missingSince: number().nullable(),
17989
+ firstTs: number(),
17990
+ lastTs: number(),
17991
+ rows: TierRowsSchema
17992
+ });
17993
+ var DeviceHistoryOrphanDeleteRefusalSchema = _enum([
17994
+ "not-found",
17995
+ "not-orphan",
17996
+ "failed"
17997
+ ]);
17998
+ var OrphanDeleteEntrySchema = discriminatedUnion("ok", [object({
17999
+ seriesId: number().int(),
18000
+ ok: literal(true),
18001
+ deleted: TierRowsSchema
18002
+ }), object({
18003
+ seriesId: number().int(),
18004
+ ok: literal(false),
18005
+ reason: DeviceHistoryOrphanDeleteRefusalSchema
18006
+ })]);
18007
+ var OrphanListSchema = object({
18008
+ series: array(OrphanSeriesSchema).readonly(),
18009
+ /** More orphans exist than {@link DEVICE_HISTORY_ORPHAN_LIST_MAX}. */
18010
+ truncated: boolean()
18011
+ });
17958
18012
  var DeviceHistoryStatusSchema = object({
17959
18013
  startedAt: number(),
17960
18014
  /** The store is declared, series loaded and the first reconcile has answered. */
@@ -18052,7 +18106,10 @@ method(object({ deviceId: number().int() }), array(SeriesInfoSchema).readonly())
18052
18106
  }), object({ enabled: boolean() }), {
18053
18107
  kind: "mutation",
18054
18108
  auth: "admin"
18055
- }), method(object({}), DeviceHistoryStatusSchema, { auth: "admin" });
18109
+ }), 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() }), {
18110
+ kind: "mutation",
18111
+ auth: "admin"
18112
+ });
18056
18113
  var DeviceCaStatusSchema = discriminatedUnion("state", [
18057
18114
  object({ state: literal("absent") }),
18058
18115
  object({
@@ -48780,7 +48837,6 @@ var RecommendationReasonSchema = discriminatedUnion("kind", [
48780
48837
  modelId: string()
48781
48838
  }),
48782
48839
  object({ kind: literal("cpu-device") }),
48783
- object({ kind: literal("coral-untouched") }),
48784
48840
  object({ kind: literal("device-disabled") }),
48785
48841
  object({ kind: literal("device-unavailable") }),
48786
48842
  object({ kind: literal("node-offline") }),
@@ -48878,11 +48934,6 @@ var AutoTuneWarningSchema = discriminatedUnion("kind", [
48878
48934
  kind: literal("detector-store-unreadable"),
48879
48935
  error: string()
48880
48936
  }),
48881
- object({
48882
- kind: literal("coral-enabled"),
48883
- nodeId: string(),
48884
- deviceKey: string()
48885
- }),
48886
48937
  object({
48887
48938
  kind: literal("custom-pin-kept"),
48888
48939
  nodeId: string(),
@@ -55926,17 +55977,69 @@ var connectivityCapability = {
55926
55977
  volatileStateFields: ["lastChangedAt"]
55927
55978
  };
55928
55979
  /**
55929
- * Generic device-consumables capability — surfaces a device's
55930
- * maintenance items (vacuum filters/brushes, replaceable cartridges,
55931
- * descaling cycles, …) with their remaining life and an optional
55932
- * "Replaced" reset action. Device-agnostic: any provider that knows its
55933
- * device tracks consumables can register it; the cap declares no
55934
- * vocabulary of its own — the provider names each item verbatim.
55980
+ * Generic device-consumables capability — the ONE place a device reports what
55981
+ * it uses up or fills: wear parts (vacuum filters/brushes, cartridges,
55982
+ * descaling cycles), supplies it draws from (a vacuum's clean-water tank and
55983
+ * detergent, a dishwasher's salt and rinse aid) and waste it collects (a dirty
55984
+ * water tank, a dust bin). Each item carries its remaining life or fill and an
55985
+ * optional "Replaced" reset action. Device-agnostic: any provider that knows
55986
+ * its device tracks consumables registers it; the provider names each item
55987
+ * verbatim and says which `kind` it is.
55988
+ *
55989
+ * The admin UI renders it as ONE collapsible section directly under the
55990
+ * device page's hero card (`placement: 'hero'`), for every device bound to
55991
+ * this cap — never drawn by a device type's hero card itself (D915).
55935
55992
  *
55936
55993
  * Like `childLayout`, the cap is INERT until a provider sets items: no
55937
55994
  * provider populates it by guessing (no HA inference). The UI renders a
55938
55995
  * "No consumables reported" placeholder when `items` is empty.
55939
55996
  */
55997
+ /**
55998
+ * What an item IS, which decides which direction is bad:
55999
+ * - `wear` — a part that wears out (a brush, a filter); low life is bad.
56000
+ * - `supply` — something the device draws from (clean water, detergent,
56001
+ * salt, rinse aid); low or empty is bad.
56002
+ * - `waste` — something the device fills (dirty water, a dust bin); full is
56003
+ * bad.
56004
+ * Absent = `wear`.
56005
+ */
56006
+ var ConsumableKindSchema = _enum([
56007
+ "wear",
56008
+ "supply",
56009
+ "waste"
56010
+ ]);
56011
+ /**
56012
+ * What an item LOOKS like, which decides how a client draws it — independent
56013
+ * of `kind`, which decides which direction is bad:
56014
+ * - `part` — a part that wears (a brush, a filter, a mop pad): a wear bar,
56015
+ * remaining time and a reset.
56016
+ * - `tank` — a container of liquid (clean water, dirty water): a fill gauge.
56017
+ * - `product` — something bought and refilled (detergent, salt, rinse aid):
56018
+ * a stepped level and "refill".
56019
+ * - `bin` — a container that collects waste (a dust bin): a fill gauge
56020
+ * that warns when full.
56021
+ * Absent = derived from the kind ({@link consumableFormOf}).
56022
+ */
56023
+ var ConsumableFormSchema = _enum([
56024
+ "part",
56025
+ "tank",
56026
+ "product",
56027
+ "bin"
56028
+ ]);
56029
+ /** The provider's own discrete verdict on an item. */
56030
+ var ConsumableStatusSchema = _enum([
56031
+ "ok",
56032
+ "low",
56033
+ "empty",
56034
+ "full",
56035
+ "replace"
56036
+ ]);
56037
+ _enum([
56038
+ "ok",
56039
+ "low",
56040
+ "empty",
56041
+ "full"
56042
+ ]);
55940
56043
  /** Units a remaining-life counter is reported in. Closed: the panel renders
55941
56044
  * each. */
55942
56045
  var ConsumableRemainingUnitSchema = _enum([
@@ -55951,18 +56054,23 @@ var ConsumableRemainingSchema = object({
55951
56054
  unit: ConsumableRemainingUnitSchema
55952
56055
  });
55953
56056
  /** A single consumable item. Either a continuous `level` (remaining
55954
- * life %) or a discrete `status` may be known — both may be null when a
55955
- * provider only knows the item exists. `level` and `status` are not
55956
- * mutually exclusive; a provider may report both. */
56057
+ * life %, or fill % for a `supply` / `waste` item) or a discrete `status`
56058
+ * may be known — both may be null when a provider only knows the item
56059
+ * exists. `level` and `status` are not mutually exclusive; a provider may
56060
+ * report both. */
55957
56061
  var ConsumableItemSchema = object({
55958
56062
  /** Stable id, e.g. 'main-brush'. */
55959
56063
  key: string().min(1),
55960
56064
  /** Display name. */
55961
56065
  label: string().min(1),
55962
- /** Remaining life % when known (0..100). */
56066
+ /** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
55963
56067
  level: number().min(0).max(100).nullable(),
55964
- /** Discrete state when known (binary mode). */
55965
- status: _enum(["ok", "replace"]).nullable(),
56068
+ /** The provider's discrete verdict when known (binary mode). */
56069
+ status: ConsumableStatusSchema.nullable(),
56070
+ /** What the item is — decides whether low or full is bad. Absent = `wear`. */
56071
+ kind: ConsumableKindSchema.optional(),
56072
+ /** How the item is drawn (part, tank, product, bin). Absent = derived from `kind`. */
56073
+ form: ConsumableFormSchema.optional(),
55966
56074
  /** Ms epoch of the last replace, when known. */
55967
56075
  lastResetAt: number().nullable(),
55968
56076
  /** Whether `reset()` is meaningful for this item. */
@@ -55985,7 +56093,7 @@ var consumablesCapability = {
55985
56093
  kind: "widget",
55986
56094
  widgetId: "host/consumables-panel",
55987
56095
  tab: "consumables",
55988
- topTab: true,
56096
+ placement: "hero",
55989
56097
  label: "Consumables",
55990
56098
  order: 5
55991
56099
  } },
@@ -56046,9 +56154,37 @@ reset: method(object({
56046
56154
  */
56047
56155
  durability: "restored",
56048
56156
  /**
56049
- * History (D850): none — `items` is an array keyed by runtime ids; a history path never enters it.
56157
+ * History (D850, D917): one series per (item field, item `key`) — the item key
56158
+ * is the series scope, the item `label` names it. A vacuum tank's fill, a
56159
+ * brush's remaining life and a dishwasher's salt are each recorded the moment
56160
+ * their provider reports them; an item that appears later gets its series.
56050
56161
  */
56051
- history: "none",
56162
+ history: {
56163
+ fields: {},
56164
+ items: {
56165
+ path: "items",
56166
+ key: "key",
56167
+ label: "label",
56168
+ fields: {
56169
+ level: {
56170
+ kind: "gauge",
56171
+ unit: "%",
56172
+ deadband: 2,
56173
+ displayName: "Level"
56174
+ },
56175
+ status: {
56176
+ kind: "enum",
56177
+ displayName: "Status"
56178
+ },
56179
+ "remaining.value": {
56180
+ kind: "gauge",
56181
+ unitFrom: "remaining.unit",
56182
+ deadband: 1,
56183
+ displayName: "Remaining"
56184
+ }
56185
+ }
56186
+ }
56187
+ },
56052
56188
  /** Clocks, not content: a re-read that changed no item costs no commit. */
56053
56189
  volatileStateFields: ["lastChangedAt", "lastFetchedAt"]
56054
56190
  };
@@ -56463,8 +56599,9 @@ onStatusChanged: { data: object({
56463
56599
  volatileStateFields: ["lastChangedAt"]
56464
56600
  };
56465
56601
  /**
56466
- * Smart-dishwasher cap — program lifecycle, door / remote-start gates,
56467
- * consumable levels (salt, rinse aid) and common program options.
56602
+ * Smart-dishwasher cap — program lifecycle, door / remote-start gates and
56603
+ * common program options. Salt and rinse aid are NOT here: they are items of
56604
+ * the device's `consumables` cap, like every other device's (D915).
56468
56605
  *
56469
56606
  * Sources: native Bosch Home Connect (`dishwasher` device type). Reusable
56470
56607
  * by any integration that exposes the same program / option surface.
@@ -56512,11 +56649,6 @@ var DishwasherAvailabilitySchema = _enum([
56512
56649
  "offline",
56513
56650
  "description-missing"
56514
56651
  ]);
56515
- var DishwasherConsumableLevelSchema = _enum([
56516
- "ok",
56517
- "low",
56518
- "empty"
56519
- ]);
56520
56652
  var DishwasherStatusSchema = object({
56521
56653
  availability: DishwasherAvailabilitySchema,
56522
56654
  /** Coarse state for compact surfaces; `unavailable` whenever the appliance state is not known. */
@@ -56549,8 +56681,6 @@ var DishwasherStatusSchema = object({
56549
56681
  powerOn: boolean().nullable(),
56550
56682
  /** The raw power state (`On`, `Off`, `Standby`, …); null when not known. */
56551
56683
  powerState: string().nullable(),
56552
- saltLevel: DishwasherConsumableLevelSchema.nullable(),
56553
- rinseAidLevel: DishwasherConsumableLevelSchema.nullable(),
56554
56684
  /**
56555
56685
  * True while the appliance asks for its filter to be cleaned (smart-filter, filter-system or
56556
56686
  * combined care-and-filter reminder raised); false when every such reminder reads clear; null
@@ -65366,60 +65496,17 @@ method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserI
65366
65496
  auth: "admin",
65367
65497
  access: "delete"
65368
65498
  });
65369
- /**
65370
- * Robot-vacuum cap. Models HA `vacuum.*` entities — anything with a
65371
- * cleaning lifecycle plus a return-to-base / locate surface and an
65372
- * optional fan-speed selector.
65373
- *
65374
- * State follows HA's canonical vacuum lifecycle: `idle` / `cleaning` /
65375
- * `paused` / `returning` / `docked` / `error`. `batteryLevel`
65376
- * (0..100) is nullable — some vacuums don't report a battery
65377
- * percentage. `fanSpeed` is the current speed token (provider-verbatim,
65378
- * e.g. `'standard'` / `'turbo'`) and `availableFanSpeeds` lists the
65379
- * tokens the hardware accepts so the UI renders only supported choices.
65380
- *
65381
- * The `setFanSpeed` method takes the bare `speed` token — the provider
65382
- * validates it against the vacuum's own list. `locate` triggers the
65383
- * find-me chirp; `returnToBase` sends it home.
65384
- *
65385
- * Consumable / waste tanks: `cleanWater` / `dirtyWater` / `detergent` /
65386
- * `dustBin` each carry a nullable `{ level (0..100 %), status ('ok' |
65387
- * 'low' | 'full') }` reading. Native providers (e.g. Dreame, Roborock)
65388
- * SHOULD populate whichever tanks the hardware has — leave a field `null`
65389
- * only when the device has no such tank at all, and use a `TankStatus`
65390
- * with both inner fields `null` when the tank exists but its level is
65391
- * currently unknown. HA `vacuum.*` entities expose no per-tank telemetry,
65392
- * so the HA provider leaves all four `null`.
65393
- */
65394
- var VacuumStateSchema = _enum([
65395
- "idle",
65396
- "cleaning",
65397
- "paused",
65398
- "returning",
65399
- "docked",
65400
- "drying",
65401
- "error"
65402
- ]);
65403
- /**
65404
- * One consumable / waste tank on a robot vacuum (clean-water, dirty-water,
65405
- * detergent or dust-bin). A tank can report a numeric fill `level` (0..100),
65406
- * a discrete `status` (binary-style hardware), or both. Both `null` means the
65407
- * level is currently unknown; the OWNING field being `null` means the
65408
- * hardware has no such tank at all.
65409
- */
65410
- var TankStatusSchema = object({
65411
- /** Numeric fill 0..100 when the hardware reports a percentage; null otherwise. */
65412
- level: number().min(0).max(100).nullable(),
65413
- /** Discrete state when the hardware is binary-mode; null otherwise. */
65414
- status: _enum([
65415
- "ok",
65416
- "low",
65417
- "full"
65418
- ]).nullable()
65419
- });
65420
65499
  var VacuumControlStatusSchema = object({
65421
65500
  /** Lifecycle state of the vacuum. */
65422
- state: VacuumStateSchema,
65501
+ state: _enum([
65502
+ "idle",
65503
+ "cleaning",
65504
+ "paused",
65505
+ "returning",
65506
+ "docked",
65507
+ "drying",
65508
+ "error"
65509
+ ]),
65423
65510
  /** 0..100 battery percentage. Null when the device has no battery
65424
65511
  * reading. */
65425
65512
  batteryLevel: number().min(0).max(100).nullable(),
@@ -65428,14 +65515,6 @@ var VacuumControlStatusSchema = object({
65428
65515
  fanSpeed: string().nullable(),
65429
65516
  /** Speed tokens the hardware accepts — drives the UI selector. */
65430
65517
  availableFanSpeeds: array(string()),
65431
- /** Clean-water (mop) tank. Null when the hardware has no clean-water tank. */
65432
- cleanWater: TankStatusSchema.nullable(),
65433
- /** Dirty-water (recovery) tank. Null when the hardware has no dirty-water tank. */
65434
- dirtyWater: TankStatusSchema.nullable(),
65435
- /** Detergent tank. Null when the hardware has no detergent tank. */
65436
- detergent: TankStatusSchema.nullable(),
65437
- /** Dust bin. Null when the hardware has no dust bin. */
65438
- dustBin: TankStatusSchema.nullable(),
65439
65518
  /** 0..100 cleaning-completion percentage of the current task, or null. */
65440
65519
  progressPercent: number().min(0).max(100).nullable(),
65441
65520
  /** Current error code (0 / null = no error). */
@@ -65497,35 +65576,14 @@ var vacuumControlCapability = {
65497
65576
  */
65498
65577
  durability: "session",
65499
65578
  /**
65500
- * History (D850): recorded series. Tank levels are fixed-object paths (`cleanWater.level`, ...).
65579
+ * History (D850): recorded series. The tanks moved to `consumables` (D915), whose
65580
+ * items are keyed by runtime ids and record no history.
65501
65581
  */
65502
- history: { fields: {
65503
- batteryLevel: {
65504
- kind: "gauge",
65505
- unit: "%",
65506
- deadband: 2
65507
- },
65508
- "cleanWater.level": {
65509
- kind: "gauge",
65510
- unit: "%",
65511
- deadband: 2
65512
- },
65513
- "dirtyWater.level": {
65514
- kind: "gauge",
65515
- unit: "%",
65516
- deadband: 2
65517
- },
65518
- "detergent.level": {
65519
- kind: "gauge",
65520
- unit: "%",
65521
- deadband: 2
65522
- },
65523
- "dustBin.level": {
65524
- kind: "gauge",
65525
- unit: "%",
65526
- deadband: 2
65527
- }
65528
- } }
65582
+ history: { fields: { batteryLevel: {
65583
+ kind: "gauge",
65584
+ unit: "%",
65585
+ deadband: 2
65586
+ } } }
65529
65587
  };
65530
65588
  var ValveStatusSchema = object({
65531
65589
  /** Lifecycle state of the valve. */
@@ -69919,6 +69977,12 @@ Object.freeze({
69919
69977
  addonId: null,
69920
69978
  access: "create"
69921
69979
  },
69980
+ "deviceHistory.deleteOrphanSeries": {
69981
+ capName: "device-history",
69982
+ capScope: "system",
69983
+ addonId: null,
69984
+ access: "delete"
69985
+ },
69922
69986
  "deviceHistory.getDeviceEnabled": {
69923
69987
  capName: "device-history",
69924
69988
  capScope: "system",
@@ -69937,6 +70001,12 @@ Object.freeze({
69937
70001
  addonId: null,
69938
70002
  access: "view"
69939
70003
  },
70004
+ "deviceHistory.listOrphanSeries": {
70005
+ capName: "device-history",
70006
+ capScope: "system",
70007
+ addonId: null,
70008
+ access: "view"
70009
+ },
69940
70010
  "deviceHistory.listSeries": {
69941
70011
  capName: "device-history",
69942
70012
  capScope: "system",
@@ -79942,7 +80012,7 @@ var STATE_SUMMARY_VARS = [
79942
80012
  ([...RULE_TEXT], [...COMBINED_ALARM]),
79943
80013
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
79944
80014
  ([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
79945
- ([...RULE_TEXT], [...CONSUMABLE]),
80015
+ ([...RULE_TEXT], [...CONSUMABLE, ...TANK]),
79946
80016
  ([...RULE_TEXT], [...TANK]),
79947
80017
  [...RULE_TEXT],
79948
80018
  ([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-tuya",
3
- "version": "0.2.141",
3
+ "version": "0.2.143",
4
4
  "description": "Tuya / Smart Life device-provider addon for CamStack — account-onboarded (Tuya IoT cloud fetch of device localKeys) + LOCAL DP control via the @apocaliss92/nodetuya encrypted-LAN client, exposing switch / water-heater-family kettle entities",
5
5
  "keywords": [
6
6
  "camstack",