@camstack/addon-provider-amcrest 0.2.154 → 0.2.155

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
@@ -5467,7 +5467,7 @@ var ZodIssueCode = {
5467
5467
  var ZodFirstPartyTypeKind;
5468
5468
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5469
5469
  //#endregion
5470
- //#region ../types/dist/sleep-DJFUfKvA.mjs
5470
+ //#region ../types/dist/sleep-CUp20JkO.mjs
5471
5471
  /**
5472
5472
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5473
5473
  * window to float samples (D455).
@@ -8359,7 +8359,11 @@ var ContributionSectionSchema = object({
8359
8359
  literal(4)
8360
8360
  ]).optional(),
8361
8361
  tab: string().optional(),
8362
- location: _enum(["settings", "top-tab"]).optional(),
8362
+ location: _enum([
8363
+ "settings",
8364
+ "top-tab",
8365
+ "hero"
8366
+ ]).optional(),
8363
8367
  order: number().optional(),
8364
8368
  fields: array(any())
8365
8369
  });
@@ -13316,7 +13320,11 @@ var ConfigSectionWithValuesSchema = object({
13316
13320
  literal(4)
13317
13321
  ]).optional(),
13318
13322
  tab: string().optional(),
13319
- location: _enum(["settings", "top-tab"]).optional(),
13323
+ location: _enum([
13324
+ "settings",
13325
+ "top-tab",
13326
+ "hero"
13327
+ ]).optional(),
13320
13328
  order: number().optional(),
13321
13329
  fields: array(any())
13322
13330
  });
@@ -17196,6 +17204,52 @@ var TierStatusSchema = object({
17196
17204
  countedAt: number().nullable()
17197
17205
  });
17198
17206
  /** Operator/diagnostic view: rows per tier, last runs, refusals and drops since boot. */
17207
+ /**
17208
+ * Why a series is orphan. `device-gone`: its device is absent from the
17209
+ * successful device listings (the departure clock). `undeclared`: its `cap:`
17210
+ * key is declared by no capability any more (a field a cap removed).
17211
+ */
17212
+ var DeviceHistoryOrphanReasonSchema = _enum(["device-gone", "undeclared"]);
17213
+ /** Rows held per stored tier. */
17214
+ var TierRowsSchema = object({
17215
+ raw: number().int(),
17216
+ "5m": number().int(),
17217
+ "1h": number().int(),
17218
+ "1d": number().int()
17219
+ });
17220
+ var OrphanSeriesSchema = object({
17221
+ seriesId: number().int(),
17222
+ deviceId: number().int(),
17223
+ key: string(),
17224
+ scope: string(),
17225
+ /** The metric's display name; `null` when its metric row is gone too. */
17226
+ displayName: string().nullable(),
17227
+ reason: DeviceHistoryOrphanReasonSchema,
17228
+ /** `device-gone`: since when the device has been absent; `null` otherwise. */
17229
+ missingSince: number().nullable(),
17230
+ firstTs: number(),
17231
+ lastTs: number(),
17232
+ rows: TierRowsSchema
17233
+ });
17234
+ var DeviceHistoryOrphanDeleteRefusalSchema = _enum([
17235
+ "not-found",
17236
+ "not-orphan",
17237
+ "failed"
17238
+ ]);
17239
+ var OrphanDeleteEntrySchema = discriminatedUnion("ok", [object({
17240
+ seriesId: number().int(),
17241
+ ok: literal(true),
17242
+ deleted: TierRowsSchema
17243
+ }), object({
17244
+ seriesId: number().int(),
17245
+ ok: literal(false),
17246
+ reason: DeviceHistoryOrphanDeleteRefusalSchema
17247
+ })]);
17248
+ var OrphanListSchema = object({
17249
+ series: array(OrphanSeriesSchema).readonly(),
17250
+ /** More orphans exist than {@link DEVICE_HISTORY_ORPHAN_LIST_MAX}. */
17251
+ truncated: boolean()
17252
+ });
17199
17253
  var DeviceHistoryStatusSchema = object({
17200
17254
  startedAt: number(),
17201
17255
  /** The store is declared, series loaded and the first reconcile has answered. */
@@ -17293,7 +17347,10 @@ method(object({ deviceId: number().int() }), array(SeriesInfoSchema).readonly())
17293
17347
  }), object({ enabled: boolean() }), {
17294
17348
  kind: "mutation",
17295
17349
  auth: "admin"
17296
- }), method(object({}), DeviceHistoryStatusSchema, { auth: "admin" });
17350
+ }), 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() }), {
17351
+ kind: "mutation",
17352
+ auth: "admin"
17353
+ });
17297
17354
  var DeviceCaStatusSchema = discriminatedUnion("state", [
17298
17355
  object({ state: literal("absent") }),
17299
17356
  object({
@@ -55762,17 +55819,69 @@ var connectivityCapability = {
55762
55819
  volatileStateFields: ["lastChangedAt"]
55763
55820
  };
55764
55821
  /**
55765
- * Generic device-consumables capability — surfaces a device's
55766
- * maintenance items (vacuum filters/brushes, replaceable cartridges,
55767
- * descaling cycles, …) with their remaining life and an optional
55768
- * "Replaced" reset action. Device-agnostic: any provider that knows its
55769
- * device tracks consumables can register it; the cap declares no
55770
- * vocabulary of its own — the provider names each item verbatim.
55822
+ * Generic device-consumables capability — the ONE place a device reports what
55823
+ * it uses up or fills: wear parts (vacuum filters/brushes, cartridges,
55824
+ * descaling cycles), supplies it draws from (a vacuum's clean-water tank and
55825
+ * detergent, a dishwasher's salt and rinse aid) and waste it collects (a dirty
55826
+ * water tank, a dust bin). Each item carries its remaining life or fill and an
55827
+ * optional "Replaced" reset action. Device-agnostic: any provider that knows
55828
+ * its device tracks consumables registers it; the provider names each item
55829
+ * verbatim and says which `kind` it is.
55830
+ *
55831
+ * The admin UI renders it as ONE collapsible section directly under the
55832
+ * device page's hero card (`placement: 'hero'`), for every device bound to
55833
+ * this cap — never drawn by a device type's hero card itself (D915).
55771
55834
  *
55772
55835
  * Like `childLayout`, the cap is INERT until a provider sets items: no
55773
55836
  * provider populates it by guessing (no HA inference). The UI renders a
55774
55837
  * "No consumables reported" placeholder when `items` is empty.
55775
55838
  */
55839
+ /**
55840
+ * What an item IS, which decides which direction is bad:
55841
+ * - `wear` — a part that wears out (a brush, a filter); low life is bad.
55842
+ * - `supply` — something the device draws from (clean water, detergent,
55843
+ * salt, rinse aid); low or empty is bad.
55844
+ * - `waste` — something the device fills (dirty water, a dust bin); full is
55845
+ * bad.
55846
+ * Absent = `wear`.
55847
+ */
55848
+ var ConsumableKindSchema = _enum([
55849
+ "wear",
55850
+ "supply",
55851
+ "waste"
55852
+ ]);
55853
+ /**
55854
+ * What an item LOOKS like, which decides how a client draws it — independent
55855
+ * of `kind`, which decides which direction is bad:
55856
+ * - `part` — a part that wears (a brush, a filter, a mop pad): a wear bar,
55857
+ * remaining time and a reset.
55858
+ * - `tank` — a container of liquid (clean water, dirty water): a fill gauge.
55859
+ * - `product` — something bought and refilled (detergent, salt, rinse aid):
55860
+ * a stepped level and "refill".
55861
+ * - `bin` — a container that collects waste (a dust bin): a fill gauge
55862
+ * that warns when full.
55863
+ * Absent = derived from the kind ({@link consumableFormOf}).
55864
+ */
55865
+ var ConsumableFormSchema = _enum([
55866
+ "part",
55867
+ "tank",
55868
+ "product",
55869
+ "bin"
55870
+ ]);
55871
+ /** The provider's own discrete verdict on an item. */
55872
+ var ConsumableStatusSchema = _enum([
55873
+ "ok",
55874
+ "low",
55875
+ "empty",
55876
+ "full",
55877
+ "replace"
55878
+ ]);
55879
+ _enum([
55880
+ "ok",
55881
+ "low",
55882
+ "empty",
55883
+ "full"
55884
+ ]);
55776
55885
  /** Units a remaining-life counter is reported in. Closed: the panel renders
55777
55886
  * each. */
55778
55887
  var ConsumableRemainingUnitSchema = _enum([
@@ -55787,18 +55896,23 @@ var ConsumableRemainingSchema = object({
55787
55896
  unit: ConsumableRemainingUnitSchema
55788
55897
  });
55789
55898
  /** A single consumable item. Either a continuous `level` (remaining
55790
- * life %) or a discrete `status` may be known — both may be null when a
55791
- * provider only knows the item exists. `level` and `status` are not
55792
- * mutually exclusive; a provider may report both. */
55899
+ * life %, or fill % for a `supply` / `waste` item) or a discrete `status`
55900
+ * may be known — both may be null when a provider only knows the item
55901
+ * exists. `level` and `status` are not mutually exclusive; a provider may
55902
+ * report both. */
55793
55903
  var ConsumableItemSchema = object({
55794
55904
  /** Stable id, e.g. 'main-brush'. */
55795
55905
  key: string().min(1),
55796
55906
  /** Display name. */
55797
55907
  label: string().min(1),
55798
- /** Remaining life % when known (0..100). */
55908
+ /** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
55799
55909
  level: number().min(0).max(100).nullable(),
55800
- /** Discrete state when known (binary mode). */
55801
- status: _enum(["ok", "replace"]).nullable(),
55910
+ /** The provider's discrete verdict when known (binary mode). */
55911
+ status: ConsumableStatusSchema.nullable(),
55912
+ /** What the item is — decides whether low or full is bad. Absent = `wear`. */
55913
+ kind: ConsumableKindSchema.optional(),
55914
+ /** How the item is drawn (part, tank, product, bin). Absent = derived from `kind`. */
55915
+ form: ConsumableFormSchema.optional(),
55802
55916
  /** Ms epoch of the last replace, when known. */
55803
55917
  lastResetAt: number().nullable(),
55804
55918
  /** Whether `reset()` is meaningful for this item. */
@@ -55821,7 +55935,7 @@ var consumablesCapability = {
55821
55935
  kind: "widget",
55822
55936
  widgetId: "host/consumables-panel",
55823
55937
  tab: "consumables",
55824
- topTab: true,
55938
+ placement: "hero",
55825
55939
  label: "Consumables",
55826
55940
  order: 5
55827
55941
  } },
@@ -55882,9 +55996,37 @@ reset: method(object({
55882
55996
  */
55883
55997
  durability: "restored",
55884
55998
  /**
55885
- * History (D850): none — `items` is an array keyed by runtime ids; a history path never enters it.
55999
+ * History (D850, D917): one series per (item field, item `key`) — the item key
56000
+ * is the series scope, the item `label` names it. A vacuum tank's fill, a
56001
+ * brush's remaining life and a dishwasher's salt are each recorded the moment
56002
+ * their provider reports them; an item that appears later gets its series.
55886
56003
  */
55887
- history: "none",
56004
+ history: {
56005
+ fields: {},
56006
+ items: {
56007
+ path: "items",
56008
+ key: "key",
56009
+ label: "label",
56010
+ fields: {
56011
+ level: {
56012
+ kind: "gauge",
56013
+ unit: "%",
56014
+ deadband: 2,
56015
+ displayName: "Level"
56016
+ },
56017
+ status: {
56018
+ kind: "enum",
56019
+ displayName: "Status"
56020
+ },
56021
+ "remaining.value": {
56022
+ kind: "gauge",
56023
+ unitFrom: "remaining.unit",
56024
+ deadband: 1,
56025
+ displayName: "Remaining"
56026
+ }
56027
+ }
56028
+ }
56029
+ },
55888
56030
  /** Clocks, not content: a re-read that changed no item costs no commit. */
55889
56031
  volatileStateFields: ["lastChangedAt", "lastFetchedAt"]
55890
56032
  };
@@ -56299,8 +56441,9 @@ onStatusChanged: { data: object({
56299
56441
  volatileStateFields: ["lastChangedAt"]
56300
56442
  };
56301
56443
  /**
56302
- * Smart-dishwasher cap — program lifecycle, door / remote-start gates,
56303
- * consumable levels (salt, rinse aid) and common program options.
56444
+ * Smart-dishwasher cap — program lifecycle, door / remote-start gates and
56445
+ * common program options. Salt and rinse aid are NOT here: they are items of
56446
+ * the device's `consumables` cap, like every other device's (D915).
56304
56447
  *
56305
56448
  * Sources: native Bosch Home Connect (`dishwasher` device type). Reusable
56306
56449
  * by any integration that exposes the same program / option surface.
@@ -56348,11 +56491,6 @@ var DishwasherAvailabilitySchema = _enum([
56348
56491
  "offline",
56349
56492
  "description-missing"
56350
56493
  ]);
56351
- var DishwasherConsumableLevelSchema = _enum([
56352
- "ok",
56353
- "low",
56354
- "empty"
56355
- ]);
56356
56494
  var DishwasherStatusSchema = object({
56357
56495
  availability: DishwasherAvailabilitySchema,
56358
56496
  /** Coarse state for compact surfaces; `unavailable` whenever the appliance state is not known. */
@@ -56385,8 +56523,6 @@ var DishwasherStatusSchema = object({
56385
56523
  powerOn: boolean().nullable(),
56386
56524
  /** The raw power state (`On`, `Off`, `Standby`, …); null when not known. */
56387
56525
  powerState: string().nullable(),
56388
- saltLevel: DishwasherConsumableLevelSchema.nullable(),
56389
- rinseAidLevel: DishwasherConsumableLevelSchema.nullable(),
56390
56526
  /**
56391
56527
  * True while the appliance asks for its filter to be cleaned (smart-filter, filter-system or
56392
56528
  * combined care-and-filter reminder raised); false when every such reminder reads clear; null
@@ -65664,60 +65800,17 @@ method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserI
65664
65800
  auth: "admin",
65665
65801
  access: "delete"
65666
65802
  });
65667
- /**
65668
- * Robot-vacuum cap. Models HA `vacuum.*` entities — anything with a
65669
- * cleaning lifecycle plus a return-to-base / locate surface and an
65670
- * optional fan-speed selector.
65671
- *
65672
- * State follows HA's canonical vacuum lifecycle: `idle` / `cleaning` /
65673
- * `paused` / `returning` / `docked` / `error`. `batteryLevel`
65674
- * (0..100) is nullable — some vacuums don't report a battery
65675
- * percentage. `fanSpeed` is the current speed token (provider-verbatim,
65676
- * e.g. `'standard'` / `'turbo'`) and `availableFanSpeeds` lists the
65677
- * tokens the hardware accepts so the UI renders only supported choices.
65678
- *
65679
- * The `setFanSpeed` method takes the bare `speed` token — the provider
65680
- * validates it against the vacuum's own list. `locate` triggers the
65681
- * find-me chirp; `returnToBase` sends it home.
65682
- *
65683
- * Consumable / waste tanks: `cleanWater` / `dirtyWater` / `detergent` /
65684
- * `dustBin` each carry a nullable `{ level (0..100 %), status ('ok' |
65685
- * 'low' | 'full') }` reading. Native providers (e.g. Dreame, Roborock)
65686
- * SHOULD populate whichever tanks the hardware has — leave a field `null`
65687
- * only when the device has no such tank at all, and use a `TankStatus`
65688
- * with both inner fields `null` when the tank exists but its level is
65689
- * currently unknown. HA `vacuum.*` entities expose no per-tank telemetry,
65690
- * so the HA provider leaves all four `null`.
65691
- */
65692
- var VacuumStateSchema = _enum([
65693
- "idle",
65694
- "cleaning",
65695
- "paused",
65696
- "returning",
65697
- "docked",
65698
- "drying",
65699
- "error"
65700
- ]);
65701
- /**
65702
- * One consumable / waste tank on a robot vacuum (clean-water, dirty-water,
65703
- * detergent or dust-bin). A tank can report a numeric fill `level` (0..100),
65704
- * a discrete `status` (binary-style hardware), or both. Both `null` means the
65705
- * level is currently unknown; the OWNING field being `null` means the
65706
- * hardware has no such tank at all.
65707
- */
65708
- var TankStatusSchema = object({
65709
- /** Numeric fill 0..100 when the hardware reports a percentage; null otherwise. */
65710
- level: number().min(0).max(100).nullable(),
65711
- /** Discrete state when the hardware is binary-mode; null otherwise. */
65712
- status: _enum([
65713
- "ok",
65714
- "low",
65715
- "full"
65716
- ]).nullable()
65717
- });
65718
65803
  var VacuumControlStatusSchema = object({
65719
65804
  /** Lifecycle state of the vacuum. */
65720
- state: VacuumStateSchema,
65805
+ state: _enum([
65806
+ "idle",
65807
+ "cleaning",
65808
+ "paused",
65809
+ "returning",
65810
+ "docked",
65811
+ "drying",
65812
+ "error"
65813
+ ]),
65721
65814
  /** 0..100 battery percentage. Null when the device has no battery
65722
65815
  * reading. */
65723
65816
  batteryLevel: number().min(0).max(100).nullable(),
@@ -65726,14 +65819,6 @@ var VacuumControlStatusSchema = object({
65726
65819
  fanSpeed: string().nullable(),
65727
65820
  /** Speed tokens the hardware accepts — drives the UI selector. */
65728
65821
  availableFanSpeeds: array(string()),
65729
- /** Clean-water (mop) tank. Null when the hardware has no clean-water tank. */
65730
- cleanWater: TankStatusSchema.nullable(),
65731
- /** Dirty-water (recovery) tank. Null when the hardware has no dirty-water tank. */
65732
- dirtyWater: TankStatusSchema.nullable(),
65733
- /** Detergent tank. Null when the hardware has no detergent tank. */
65734
- detergent: TankStatusSchema.nullable(),
65735
- /** Dust bin. Null when the hardware has no dust bin. */
65736
- dustBin: TankStatusSchema.nullable(),
65737
65822
  /** 0..100 cleaning-completion percentage of the current task, or null. */
65738
65823
  progressPercent: number().min(0).max(100).nullable(),
65739
65824
  /** Current error code (0 / null = no error). */
@@ -65795,35 +65880,14 @@ var vacuumControlCapability = {
65795
65880
  */
65796
65881
  durability: "session",
65797
65882
  /**
65798
- * History (D850): recorded series. Tank levels are fixed-object paths (`cleanWater.level`, ...).
65883
+ * History (D850): recorded series. The tanks moved to `consumables` (D915), whose
65884
+ * items are keyed by runtime ids and record no history.
65799
65885
  */
65800
- history: { fields: {
65801
- batteryLevel: {
65802
- kind: "gauge",
65803
- unit: "%",
65804
- deadband: 2
65805
- },
65806
- "cleanWater.level": {
65807
- kind: "gauge",
65808
- unit: "%",
65809
- deadband: 2
65810
- },
65811
- "dirtyWater.level": {
65812
- kind: "gauge",
65813
- unit: "%",
65814
- deadband: 2
65815
- },
65816
- "detergent.level": {
65817
- kind: "gauge",
65818
- unit: "%",
65819
- deadband: 2
65820
- },
65821
- "dustBin.level": {
65822
- kind: "gauge",
65823
- unit: "%",
65824
- deadband: 2
65825
- }
65826
- } }
65886
+ history: { fields: { batteryLevel: {
65887
+ kind: "gauge",
65888
+ unit: "%",
65889
+ deadband: 2
65890
+ } } }
65827
65891
  };
65828
65892
  var ValveStatusSchema = object({
65829
65893
  /** Lifecycle state of the valve. */
@@ -70221,6 +70285,12 @@ Object.freeze({
70221
70285
  addonId: null,
70222
70286
  access: "create"
70223
70287
  },
70288
+ "deviceHistory.deleteOrphanSeries": {
70289
+ capName: "device-history",
70290
+ capScope: "system",
70291
+ addonId: null,
70292
+ access: "delete"
70293
+ },
70224
70294
  "deviceHistory.getDeviceEnabled": {
70225
70295
  capName: "device-history",
70226
70296
  capScope: "system",
@@ -70239,6 +70309,12 @@ Object.freeze({
70239
70309
  addonId: null,
70240
70310
  access: "view"
70241
70311
  },
70312
+ "deviceHistory.listOrphanSeries": {
70313
+ capName: "device-history",
70314
+ capScope: "system",
70315
+ addonId: null,
70316
+ access: "view"
70317
+ },
70242
70318
  "deviceHistory.listSeries": {
70243
70319
  capName: "device-history",
70244
70320
  capScope: "system",
@@ -80450,7 +80526,7 @@ var STATE_SUMMARY_VARS = [
80450
80526
  ([...RULE_TEXT], [...COMBINED_ALARM]),
80451
80527
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
80452
80528
  ([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
80453
- ([...RULE_TEXT], [...CONSUMABLE]),
80529
+ ([...RULE_TEXT], [...CONSUMABLE, ...TANK]),
80454
80530
  ([...RULE_TEXT], [...TANK]),
80455
80531
  [...RULE_TEXT],
80456
80532
  ([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
package/dist/addon.mjs CHANGED
@@ -5446,7 +5446,7 @@ var ZodIssueCode = {
5446
5446
  var ZodFirstPartyTypeKind;
5447
5447
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5448
5448
  //#endregion
5449
- //#region ../types/dist/sleep-DJFUfKvA.mjs
5449
+ //#region ../types/dist/sleep-CUp20JkO.mjs
5450
5450
  /**
5451
5451
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5452
5452
  * window to float samples (D455).
@@ -8338,7 +8338,11 @@ var ContributionSectionSchema = object({
8338
8338
  literal(4)
8339
8339
  ]).optional(),
8340
8340
  tab: string().optional(),
8341
- location: _enum(["settings", "top-tab"]).optional(),
8341
+ location: _enum([
8342
+ "settings",
8343
+ "top-tab",
8344
+ "hero"
8345
+ ]).optional(),
8342
8346
  order: number().optional(),
8343
8347
  fields: array(any())
8344
8348
  });
@@ -13295,7 +13299,11 @@ var ConfigSectionWithValuesSchema = object({
13295
13299
  literal(4)
13296
13300
  ]).optional(),
13297
13301
  tab: string().optional(),
13298
- location: _enum(["settings", "top-tab"]).optional(),
13302
+ location: _enum([
13303
+ "settings",
13304
+ "top-tab",
13305
+ "hero"
13306
+ ]).optional(),
13299
13307
  order: number().optional(),
13300
13308
  fields: array(any())
13301
13309
  });
@@ -17175,6 +17183,52 @@ var TierStatusSchema = object({
17175
17183
  countedAt: number().nullable()
17176
17184
  });
17177
17185
  /** Operator/diagnostic view: rows per tier, last runs, refusals and drops since boot. */
17186
+ /**
17187
+ * Why a series is orphan. `device-gone`: its device is absent from the
17188
+ * successful device listings (the departure clock). `undeclared`: its `cap:`
17189
+ * key is declared by no capability any more (a field a cap removed).
17190
+ */
17191
+ var DeviceHistoryOrphanReasonSchema = _enum(["device-gone", "undeclared"]);
17192
+ /** Rows held per stored tier. */
17193
+ var TierRowsSchema = object({
17194
+ raw: number().int(),
17195
+ "5m": number().int(),
17196
+ "1h": number().int(),
17197
+ "1d": number().int()
17198
+ });
17199
+ var OrphanSeriesSchema = object({
17200
+ seriesId: number().int(),
17201
+ deviceId: number().int(),
17202
+ key: string(),
17203
+ scope: string(),
17204
+ /** The metric's display name; `null` when its metric row is gone too. */
17205
+ displayName: string().nullable(),
17206
+ reason: DeviceHistoryOrphanReasonSchema,
17207
+ /** `device-gone`: since when the device has been absent; `null` otherwise. */
17208
+ missingSince: number().nullable(),
17209
+ firstTs: number(),
17210
+ lastTs: number(),
17211
+ rows: TierRowsSchema
17212
+ });
17213
+ var DeviceHistoryOrphanDeleteRefusalSchema = _enum([
17214
+ "not-found",
17215
+ "not-orphan",
17216
+ "failed"
17217
+ ]);
17218
+ var OrphanDeleteEntrySchema = discriminatedUnion("ok", [object({
17219
+ seriesId: number().int(),
17220
+ ok: literal(true),
17221
+ deleted: TierRowsSchema
17222
+ }), object({
17223
+ seriesId: number().int(),
17224
+ ok: literal(false),
17225
+ reason: DeviceHistoryOrphanDeleteRefusalSchema
17226
+ })]);
17227
+ var OrphanListSchema = object({
17228
+ series: array(OrphanSeriesSchema).readonly(),
17229
+ /** More orphans exist than {@link DEVICE_HISTORY_ORPHAN_LIST_MAX}. */
17230
+ truncated: boolean()
17231
+ });
17178
17232
  var DeviceHistoryStatusSchema = object({
17179
17233
  startedAt: number(),
17180
17234
  /** The store is declared, series loaded and the first reconcile has answered. */
@@ -17272,7 +17326,10 @@ method(object({ deviceId: number().int() }), array(SeriesInfoSchema).readonly())
17272
17326
  }), object({ enabled: boolean() }), {
17273
17327
  kind: "mutation",
17274
17328
  auth: "admin"
17275
- }), method(object({}), DeviceHistoryStatusSchema, { auth: "admin" });
17329
+ }), 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() }), {
17330
+ kind: "mutation",
17331
+ auth: "admin"
17332
+ });
17276
17333
  var DeviceCaStatusSchema = discriminatedUnion("state", [
17277
17334
  object({ state: literal("absent") }),
17278
17335
  object({
@@ -55741,17 +55798,69 @@ var connectivityCapability = {
55741
55798
  volatileStateFields: ["lastChangedAt"]
55742
55799
  };
55743
55800
  /**
55744
- * Generic device-consumables capability — surfaces a device's
55745
- * maintenance items (vacuum filters/brushes, replaceable cartridges,
55746
- * descaling cycles, …) with their remaining life and an optional
55747
- * "Replaced" reset action. Device-agnostic: any provider that knows its
55748
- * device tracks consumables can register it; the cap declares no
55749
- * vocabulary of its own — the provider names each item verbatim.
55801
+ * Generic device-consumables capability — the ONE place a device reports what
55802
+ * it uses up or fills: wear parts (vacuum filters/brushes, cartridges,
55803
+ * descaling cycles), supplies it draws from (a vacuum's clean-water tank and
55804
+ * detergent, a dishwasher's salt and rinse aid) and waste it collects (a dirty
55805
+ * water tank, a dust bin). Each item carries its remaining life or fill and an
55806
+ * optional "Replaced" reset action. Device-agnostic: any provider that knows
55807
+ * its device tracks consumables registers it; the provider names each item
55808
+ * verbatim and says which `kind` it is.
55809
+ *
55810
+ * The admin UI renders it as ONE collapsible section directly under the
55811
+ * device page's hero card (`placement: 'hero'`), for every device bound to
55812
+ * this cap — never drawn by a device type's hero card itself (D915).
55750
55813
  *
55751
55814
  * Like `childLayout`, the cap is INERT until a provider sets items: no
55752
55815
  * provider populates it by guessing (no HA inference). The UI renders a
55753
55816
  * "No consumables reported" placeholder when `items` is empty.
55754
55817
  */
55818
+ /**
55819
+ * What an item IS, which decides which direction is bad:
55820
+ * - `wear` — a part that wears out (a brush, a filter); low life is bad.
55821
+ * - `supply` — something the device draws from (clean water, detergent,
55822
+ * salt, rinse aid); low or empty is bad.
55823
+ * - `waste` — something the device fills (dirty water, a dust bin); full is
55824
+ * bad.
55825
+ * Absent = `wear`.
55826
+ */
55827
+ var ConsumableKindSchema = _enum([
55828
+ "wear",
55829
+ "supply",
55830
+ "waste"
55831
+ ]);
55832
+ /**
55833
+ * What an item LOOKS like, which decides how a client draws it — independent
55834
+ * of `kind`, which decides which direction is bad:
55835
+ * - `part` — a part that wears (a brush, a filter, a mop pad): a wear bar,
55836
+ * remaining time and a reset.
55837
+ * - `tank` — a container of liquid (clean water, dirty water): a fill gauge.
55838
+ * - `product` — something bought and refilled (detergent, salt, rinse aid):
55839
+ * a stepped level and "refill".
55840
+ * - `bin` — a container that collects waste (a dust bin): a fill gauge
55841
+ * that warns when full.
55842
+ * Absent = derived from the kind ({@link consumableFormOf}).
55843
+ */
55844
+ var ConsumableFormSchema = _enum([
55845
+ "part",
55846
+ "tank",
55847
+ "product",
55848
+ "bin"
55849
+ ]);
55850
+ /** The provider's own discrete verdict on an item. */
55851
+ var ConsumableStatusSchema = _enum([
55852
+ "ok",
55853
+ "low",
55854
+ "empty",
55855
+ "full",
55856
+ "replace"
55857
+ ]);
55858
+ _enum([
55859
+ "ok",
55860
+ "low",
55861
+ "empty",
55862
+ "full"
55863
+ ]);
55755
55864
  /** Units a remaining-life counter is reported in. Closed: the panel renders
55756
55865
  * each. */
55757
55866
  var ConsumableRemainingUnitSchema = _enum([
@@ -55766,18 +55875,23 @@ var ConsumableRemainingSchema = object({
55766
55875
  unit: ConsumableRemainingUnitSchema
55767
55876
  });
55768
55877
  /** A single consumable item. Either a continuous `level` (remaining
55769
- * life %) or a discrete `status` may be known — both may be null when a
55770
- * provider only knows the item exists. `level` and `status` are not
55771
- * mutually exclusive; a provider may report both. */
55878
+ * life %, or fill % for a `supply` / `waste` item) or a discrete `status`
55879
+ * may be known — both may be null when a provider only knows the item
55880
+ * exists. `level` and `status` are not mutually exclusive; a provider may
55881
+ * report both. */
55772
55882
  var ConsumableItemSchema = object({
55773
55883
  /** Stable id, e.g. 'main-brush'. */
55774
55884
  key: string().min(1),
55775
55885
  /** Display name. */
55776
55886
  label: string().min(1),
55777
- /** Remaining life % when known (0..100). */
55887
+ /** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
55778
55888
  level: number().min(0).max(100).nullable(),
55779
- /** Discrete state when known (binary mode). */
55780
- status: _enum(["ok", "replace"]).nullable(),
55889
+ /** The provider's discrete verdict when known (binary mode). */
55890
+ status: ConsumableStatusSchema.nullable(),
55891
+ /** What the item is — decides whether low or full is bad. Absent = `wear`. */
55892
+ kind: ConsumableKindSchema.optional(),
55893
+ /** How the item is drawn (part, tank, product, bin). Absent = derived from `kind`. */
55894
+ form: ConsumableFormSchema.optional(),
55781
55895
  /** Ms epoch of the last replace, when known. */
55782
55896
  lastResetAt: number().nullable(),
55783
55897
  /** Whether `reset()` is meaningful for this item. */
@@ -55800,7 +55914,7 @@ var consumablesCapability = {
55800
55914
  kind: "widget",
55801
55915
  widgetId: "host/consumables-panel",
55802
55916
  tab: "consumables",
55803
- topTab: true,
55917
+ placement: "hero",
55804
55918
  label: "Consumables",
55805
55919
  order: 5
55806
55920
  } },
@@ -55861,9 +55975,37 @@ reset: method(object({
55861
55975
  */
55862
55976
  durability: "restored",
55863
55977
  /**
55864
- * History (D850): none — `items` is an array keyed by runtime ids; a history path never enters it.
55978
+ * History (D850, D917): one series per (item field, item `key`) — the item key
55979
+ * is the series scope, the item `label` names it. A vacuum tank's fill, a
55980
+ * brush's remaining life and a dishwasher's salt are each recorded the moment
55981
+ * their provider reports them; an item that appears later gets its series.
55865
55982
  */
55866
- history: "none",
55983
+ history: {
55984
+ fields: {},
55985
+ items: {
55986
+ path: "items",
55987
+ key: "key",
55988
+ label: "label",
55989
+ fields: {
55990
+ level: {
55991
+ kind: "gauge",
55992
+ unit: "%",
55993
+ deadband: 2,
55994
+ displayName: "Level"
55995
+ },
55996
+ status: {
55997
+ kind: "enum",
55998
+ displayName: "Status"
55999
+ },
56000
+ "remaining.value": {
56001
+ kind: "gauge",
56002
+ unitFrom: "remaining.unit",
56003
+ deadband: 1,
56004
+ displayName: "Remaining"
56005
+ }
56006
+ }
56007
+ }
56008
+ },
55867
56009
  /** Clocks, not content: a re-read that changed no item costs no commit. */
55868
56010
  volatileStateFields: ["lastChangedAt", "lastFetchedAt"]
55869
56011
  };
@@ -56278,8 +56420,9 @@ onStatusChanged: { data: object({
56278
56420
  volatileStateFields: ["lastChangedAt"]
56279
56421
  };
56280
56422
  /**
56281
- * Smart-dishwasher cap — program lifecycle, door / remote-start gates,
56282
- * consumable levels (salt, rinse aid) and common program options.
56423
+ * Smart-dishwasher cap — program lifecycle, door / remote-start gates and
56424
+ * common program options. Salt and rinse aid are NOT here: they are items of
56425
+ * the device's `consumables` cap, like every other device's (D915).
56283
56426
  *
56284
56427
  * Sources: native Bosch Home Connect (`dishwasher` device type). Reusable
56285
56428
  * by any integration that exposes the same program / option surface.
@@ -56327,11 +56470,6 @@ var DishwasherAvailabilitySchema = _enum([
56327
56470
  "offline",
56328
56471
  "description-missing"
56329
56472
  ]);
56330
- var DishwasherConsumableLevelSchema = _enum([
56331
- "ok",
56332
- "low",
56333
- "empty"
56334
- ]);
56335
56473
  var DishwasherStatusSchema = object({
56336
56474
  availability: DishwasherAvailabilitySchema,
56337
56475
  /** Coarse state for compact surfaces; `unavailable` whenever the appliance state is not known. */
@@ -56364,8 +56502,6 @@ var DishwasherStatusSchema = object({
56364
56502
  powerOn: boolean().nullable(),
56365
56503
  /** The raw power state (`On`, `Off`, `Standby`, …); null when not known. */
56366
56504
  powerState: string().nullable(),
56367
- saltLevel: DishwasherConsumableLevelSchema.nullable(),
56368
- rinseAidLevel: DishwasherConsumableLevelSchema.nullable(),
56369
56505
  /**
56370
56506
  * True while the appliance asks for its filter to be cleaned (smart-filter, filter-system or
56371
56507
  * combined care-and-filter reminder raised); false when every such reminder reads clear; null
@@ -65643,60 +65779,17 @@ method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserI
65643
65779
  auth: "admin",
65644
65780
  access: "delete"
65645
65781
  });
65646
- /**
65647
- * Robot-vacuum cap. Models HA `vacuum.*` entities — anything with a
65648
- * cleaning lifecycle plus a return-to-base / locate surface and an
65649
- * optional fan-speed selector.
65650
- *
65651
- * State follows HA's canonical vacuum lifecycle: `idle` / `cleaning` /
65652
- * `paused` / `returning` / `docked` / `error`. `batteryLevel`
65653
- * (0..100) is nullable — some vacuums don't report a battery
65654
- * percentage. `fanSpeed` is the current speed token (provider-verbatim,
65655
- * e.g. `'standard'` / `'turbo'`) and `availableFanSpeeds` lists the
65656
- * tokens the hardware accepts so the UI renders only supported choices.
65657
- *
65658
- * The `setFanSpeed` method takes the bare `speed` token — the provider
65659
- * validates it against the vacuum's own list. `locate` triggers the
65660
- * find-me chirp; `returnToBase` sends it home.
65661
- *
65662
- * Consumable / waste tanks: `cleanWater` / `dirtyWater` / `detergent` /
65663
- * `dustBin` each carry a nullable `{ level (0..100 %), status ('ok' |
65664
- * 'low' | 'full') }` reading. Native providers (e.g. Dreame, Roborock)
65665
- * SHOULD populate whichever tanks the hardware has — leave a field `null`
65666
- * only when the device has no such tank at all, and use a `TankStatus`
65667
- * with both inner fields `null` when the tank exists but its level is
65668
- * currently unknown. HA `vacuum.*` entities expose no per-tank telemetry,
65669
- * so the HA provider leaves all four `null`.
65670
- */
65671
- var VacuumStateSchema = _enum([
65672
- "idle",
65673
- "cleaning",
65674
- "paused",
65675
- "returning",
65676
- "docked",
65677
- "drying",
65678
- "error"
65679
- ]);
65680
- /**
65681
- * One consumable / waste tank on a robot vacuum (clean-water, dirty-water,
65682
- * detergent or dust-bin). A tank can report a numeric fill `level` (0..100),
65683
- * a discrete `status` (binary-style hardware), or both. Both `null` means the
65684
- * level is currently unknown; the OWNING field being `null` means the
65685
- * hardware has no such tank at all.
65686
- */
65687
- var TankStatusSchema = object({
65688
- /** Numeric fill 0..100 when the hardware reports a percentage; null otherwise. */
65689
- level: number().min(0).max(100).nullable(),
65690
- /** Discrete state when the hardware is binary-mode; null otherwise. */
65691
- status: _enum([
65692
- "ok",
65693
- "low",
65694
- "full"
65695
- ]).nullable()
65696
- });
65697
65782
  var VacuumControlStatusSchema = object({
65698
65783
  /** Lifecycle state of the vacuum. */
65699
- state: VacuumStateSchema,
65784
+ state: _enum([
65785
+ "idle",
65786
+ "cleaning",
65787
+ "paused",
65788
+ "returning",
65789
+ "docked",
65790
+ "drying",
65791
+ "error"
65792
+ ]),
65700
65793
  /** 0..100 battery percentage. Null when the device has no battery
65701
65794
  * reading. */
65702
65795
  batteryLevel: number().min(0).max(100).nullable(),
@@ -65705,14 +65798,6 @@ var VacuumControlStatusSchema = object({
65705
65798
  fanSpeed: string().nullable(),
65706
65799
  /** Speed tokens the hardware accepts — drives the UI selector. */
65707
65800
  availableFanSpeeds: array(string()),
65708
- /** Clean-water (mop) tank. Null when the hardware has no clean-water tank. */
65709
- cleanWater: TankStatusSchema.nullable(),
65710
- /** Dirty-water (recovery) tank. Null when the hardware has no dirty-water tank. */
65711
- dirtyWater: TankStatusSchema.nullable(),
65712
- /** Detergent tank. Null when the hardware has no detergent tank. */
65713
- detergent: TankStatusSchema.nullable(),
65714
- /** Dust bin. Null when the hardware has no dust bin. */
65715
- dustBin: TankStatusSchema.nullable(),
65716
65801
  /** 0..100 cleaning-completion percentage of the current task, or null. */
65717
65802
  progressPercent: number().min(0).max(100).nullable(),
65718
65803
  /** Current error code (0 / null = no error). */
@@ -65774,35 +65859,14 @@ var vacuumControlCapability = {
65774
65859
  */
65775
65860
  durability: "session",
65776
65861
  /**
65777
- * History (D850): recorded series. Tank levels are fixed-object paths (`cleanWater.level`, ...).
65862
+ * History (D850): recorded series. The tanks moved to `consumables` (D915), whose
65863
+ * items are keyed by runtime ids and record no history.
65778
65864
  */
65779
- history: { fields: {
65780
- batteryLevel: {
65781
- kind: "gauge",
65782
- unit: "%",
65783
- deadband: 2
65784
- },
65785
- "cleanWater.level": {
65786
- kind: "gauge",
65787
- unit: "%",
65788
- deadband: 2
65789
- },
65790
- "dirtyWater.level": {
65791
- kind: "gauge",
65792
- unit: "%",
65793
- deadband: 2
65794
- },
65795
- "detergent.level": {
65796
- kind: "gauge",
65797
- unit: "%",
65798
- deadband: 2
65799
- },
65800
- "dustBin.level": {
65801
- kind: "gauge",
65802
- unit: "%",
65803
- deadband: 2
65804
- }
65805
- } }
65865
+ history: { fields: { batteryLevel: {
65866
+ kind: "gauge",
65867
+ unit: "%",
65868
+ deadband: 2
65869
+ } } }
65806
65870
  };
65807
65871
  var ValveStatusSchema = object({
65808
65872
  /** Lifecycle state of the valve. */
@@ -70200,6 +70264,12 @@ Object.freeze({
70200
70264
  addonId: null,
70201
70265
  access: "create"
70202
70266
  },
70267
+ "deviceHistory.deleteOrphanSeries": {
70268
+ capName: "device-history",
70269
+ capScope: "system",
70270
+ addonId: null,
70271
+ access: "delete"
70272
+ },
70203
70273
  "deviceHistory.getDeviceEnabled": {
70204
70274
  capName: "device-history",
70205
70275
  capScope: "system",
@@ -70218,6 +70288,12 @@ Object.freeze({
70218
70288
  addonId: null,
70219
70289
  access: "view"
70220
70290
  },
70291
+ "deviceHistory.listOrphanSeries": {
70292
+ capName: "device-history",
70293
+ capScope: "system",
70294
+ addonId: null,
70295
+ access: "view"
70296
+ },
70221
70297
  "deviceHistory.listSeries": {
70222
70298
  capName: "device-history",
70223
70299
  capScope: "system",
@@ -80429,7 +80505,7 @@ var STATE_SUMMARY_VARS = [
80429
80505
  ([...RULE_TEXT], [...COMBINED_ALARM]),
80430
80506
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
80431
80507
  ([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
80432
- ([...RULE_TEXT], [...CONSUMABLE]),
80508
+ ([...RULE_TEXT], [...CONSUMABLE, ...TANK]),
80433
80509
  ([...RULE_TEXT], [...TANK]),
80434
80510
  [...RULE_TEXT],
80435
80511
  ([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-amcrest",
3
- "version": "0.2.154",
3
+ "version": "0.2.155",
4
4
  "description": "Amcrest/Dahua camera device provider addon for CamStack — Dahua CGI over HTTP(S) with digest auth (snapshot, RTSP catalog, PTZ, image/day-night config)",
5
5
  "keywords": [
6
6
  "camstack",