@camstack/addon-provider-amcrest 0.2.153 → 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 -123
  2. package/dist/addon.mjs +193 -123
  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({
@@ -48117,7 +48174,6 @@ var RecommendationReasonSchema = discriminatedUnion("kind", [
48117
48174
  modelId: string()
48118
48175
  }),
48119
48176
  object({ kind: literal("cpu-device") }),
48120
- object({ kind: literal("coral-untouched") }),
48121
48177
  object({ kind: literal("device-disabled") }),
48122
48178
  object({ kind: literal("device-unavailable") }),
48123
48179
  object({ kind: literal("node-offline") }),
@@ -48215,11 +48271,6 @@ var AutoTuneWarningSchema = discriminatedUnion("kind", [
48215
48271
  kind: literal("detector-store-unreadable"),
48216
48272
  error: string()
48217
48273
  }),
48218
- object({
48219
- kind: literal("coral-enabled"),
48220
- nodeId: string(),
48221
- deviceKey: string()
48222
- }),
48223
48274
  object({
48224
48275
  kind: literal("custom-pin-kept"),
48225
48276
  nodeId: string(),
@@ -55768,17 +55819,69 @@ var connectivityCapability = {
55768
55819
  volatileStateFields: ["lastChangedAt"]
55769
55820
  };
55770
55821
  /**
55771
- * Generic device-consumables capability — surfaces a device's
55772
- * maintenance items (vacuum filters/brushes, replaceable cartridges,
55773
- * descaling cycles, …) with their remaining life and an optional
55774
- * "Replaced" reset action. Device-agnostic: any provider that knows its
55775
- * device tracks consumables can register it; the cap declares no
55776
- * 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).
55777
55834
  *
55778
55835
  * Like `childLayout`, the cap is INERT until a provider sets items: no
55779
55836
  * provider populates it by guessing (no HA inference). The UI renders a
55780
55837
  * "No consumables reported" placeholder when `items` is empty.
55781
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
+ ]);
55782
55885
  /** Units a remaining-life counter is reported in. Closed: the panel renders
55783
55886
  * each. */
55784
55887
  var ConsumableRemainingUnitSchema = _enum([
@@ -55793,18 +55896,23 @@ var ConsumableRemainingSchema = object({
55793
55896
  unit: ConsumableRemainingUnitSchema
55794
55897
  });
55795
55898
  /** A single consumable item. Either a continuous `level` (remaining
55796
- * life %) or a discrete `status` may be known — both may be null when a
55797
- * provider only knows the item exists. `level` and `status` are not
55798
- * 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. */
55799
55903
  var ConsumableItemSchema = object({
55800
55904
  /** Stable id, e.g. 'main-brush'. */
55801
55905
  key: string().min(1),
55802
55906
  /** Display name. */
55803
55907
  label: string().min(1),
55804
- /** Remaining life % when known (0..100). */
55908
+ /** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
55805
55909
  level: number().min(0).max(100).nullable(),
55806
- /** Discrete state when known (binary mode). */
55807
- 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(),
55808
55916
  /** Ms epoch of the last replace, when known. */
55809
55917
  lastResetAt: number().nullable(),
55810
55918
  /** Whether `reset()` is meaningful for this item. */
@@ -55827,7 +55935,7 @@ var consumablesCapability = {
55827
55935
  kind: "widget",
55828
55936
  widgetId: "host/consumables-panel",
55829
55937
  tab: "consumables",
55830
- topTab: true,
55938
+ placement: "hero",
55831
55939
  label: "Consumables",
55832
55940
  order: 5
55833
55941
  } },
@@ -55888,9 +55996,37 @@ reset: method(object({
55888
55996
  */
55889
55997
  durability: "restored",
55890
55998
  /**
55891
- * 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.
55892
56003
  */
55893
- 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
+ },
55894
56030
  /** Clocks, not content: a re-read that changed no item costs no commit. */
55895
56031
  volatileStateFields: ["lastChangedAt", "lastFetchedAt"]
55896
56032
  };
@@ -56305,8 +56441,9 @@ onStatusChanged: { data: object({
56305
56441
  volatileStateFields: ["lastChangedAt"]
56306
56442
  };
56307
56443
  /**
56308
- * Smart-dishwasher cap — program lifecycle, door / remote-start gates,
56309
- * 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).
56310
56447
  *
56311
56448
  * Sources: native Bosch Home Connect (`dishwasher` device type). Reusable
56312
56449
  * by any integration that exposes the same program / option surface.
@@ -56354,11 +56491,6 @@ var DishwasherAvailabilitySchema = _enum([
56354
56491
  "offline",
56355
56492
  "description-missing"
56356
56493
  ]);
56357
- var DishwasherConsumableLevelSchema = _enum([
56358
- "ok",
56359
- "low",
56360
- "empty"
56361
- ]);
56362
56494
  var DishwasherStatusSchema = object({
56363
56495
  availability: DishwasherAvailabilitySchema,
56364
56496
  /** Coarse state for compact surfaces; `unavailable` whenever the appliance state is not known. */
@@ -56391,8 +56523,6 @@ var DishwasherStatusSchema = object({
56391
56523
  powerOn: boolean().nullable(),
56392
56524
  /** The raw power state (`On`, `Off`, `Standby`, …); null when not known. */
56393
56525
  powerState: string().nullable(),
56394
- saltLevel: DishwasherConsumableLevelSchema.nullable(),
56395
- rinseAidLevel: DishwasherConsumableLevelSchema.nullable(),
56396
56526
  /**
56397
56527
  * True while the appliance asks for its filter to be cleaned (smart-filter, filter-system or
56398
56528
  * combined care-and-filter reminder raised); false when every such reminder reads clear; null
@@ -65670,60 +65800,17 @@ method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserI
65670
65800
  auth: "admin",
65671
65801
  access: "delete"
65672
65802
  });
65673
- /**
65674
- * Robot-vacuum cap. Models HA `vacuum.*` entities — anything with a
65675
- * cleaning lifecycle plus a return-to-base / locate surface and an
65676
- * optional fan-speed selector.
65677
- *
65678
- * State follows HA's canonical vacuum lifecycle: `idle` / `cleaning` /
65679
- * `paused` / `returning` / `docked` / `error`. `batteryLevel`
65680
- * (0..100) is nullable — some vacuums don't report a battery
65681
- * percentage. `fanSpeed` is the current speed token (provider-verbatim,
65682
- * e.g. `'standard'` / `'turbo'`) and `availableFanSpeeds` lists the
65683
- * tokens the hardware accepts so the UI renders only supported choices.
65684
- *
65685
- * The `setFanSpeed` method takes the bare `speed` token — the provider
65686
- * validates it against the vacuum's own list. `locate` triggers the
65687
- * find-me chirp; `returnToBase` sends it home.
65688
- *
65689
- * Consumable / waste tanks: `cleanWater` / `dirtyWater` / `detergent` /
65690
- * `dustBin` each carry a nullable `{ level (0..100 %), status ('ok' |
65691
- * 'low' | 'full') }` reading. Native providers (e.g. Dreame, Roborock)
65692
- * SHOULD populate whichever tanks the hardware has — leave a field `null`
65693
- * only when the device has no such tank at all, and use a `TankStatus`
65694
- * with both inner fields `null` when the tank exists but its level is
65695
- * currently unknown. HA `vacuum.*` entities expose no per-tank telemetry,
65696
- * so the HA provider leaves all four `null`.
65697
- */
65698
- var VacuumStateSchema = _enum([
65699
- "idle",
65700
- "cleaning",
65701
- "paused",
65702
- "returning",
65703
- "docked",
65704
- "drying",
65705
- "error"
65706
- ]);
65707
- /**
65708
- * One consumable / waste tank on a robot vacuum (clean-water, dirty-water,
65709
- * detergent or dust-bin). A tank can report a numeric fill `level` (0..100),
65710
- * a discrete `status` (binary-style hardware), or both. Both `null` means the
65711
- * level is currently unknown; the OWNING field being `null` means the
65712
- * hardware has no such tank at all.
65713
- */
65714
- var TankStatusSchema = object({
65715
- /** Numeric fill 0..100 when the hardware reports a percentage; null otherwise. */
65716
- level: number().min(0).max(100).nullable(),
65717
- /** Discrete state when the hardware is binary-mode; null otherwise. */
65718
- status: _enum([
65719
- "ok",
65720
- "low",
65721
- "full"
65722
- ]).nullable()
65723
- });
65724
65803
  var VacuumControlStatusSchema = object({
65725
65804
  /** Lifecycle state of the vacuum. */
65726
- state: VacuumStateSchema,
65805
+ state: _enum([
65806
+ "idle",
65807
+ "cleaning",
65808
+ "paused",
65809
+ "returning",
65810
+ "docked",
65811
+ "drying",
65812
+ "error"
65813
+ ]),
65727
65814
  /** 0..100 battery percentage. Null when the device has no battery
65728
65815
  * reading. */
65729
65816
  batteryLevel: number().min(0).max(100).nullable(),
@@ -65732,14 +65819,6 @@ var VacuumControlStatusSchema = object({
65732
65819
  fanSpeed: string().nullable(),
65733
65820
  /** Speed tokens the hardware accepts — drives the UI selector. */
65734
65821
  availableFanSpeeds: array(string()),
65735
- /** Clean-water (mop) tank. Null when the hardware has no clean-water tank. */
65736
- cleanWater: TankStatusSchema.nullable(),
65737
- /** Dirty-water (recovery) tank. Null when the hardware has no dirty-water tank. */
65738
- dirtyWater: TankStatusSchema.nullable(),
65739
- /** Detergent tank. Null when the hardware has no detergent tank. */
65740
- detergent: TankStatusSchema.nullable(),
65741
- /** Dust bin. Null when the hardware has no dust bin. */
65742
- dustBin: TankStatusSchema.nullable(),
65743
65822
  /** 0..100 cleaning-completion percentage of the current task, or null. */
65744
65823
  progressPercent: number().min(0).max(100).nullable(),
65745
65824
  /** Current error code (0 / null = no error). */
@@ -65801,35 +65880,14 @@ var vacuumControlCapability = {
65801
65880
  */
65802
65881
  durability: "session",
65803
65882
  /**
65804
- * 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.
65805
65885
  */
65806
- history: { fields: {
65807
- batteryLevel: {
65808
- kind: "gauge",
65809
- unit: "%",
65810
- deadband: 2
65811
- },
65812
- "cleanWater.level": {
65813
- kind: "gauge",
65814
- unit: "%",
65815
- deadband: 2
65816
- },
65817
- "dirtyWater.level": {
65818
- kind: "gauge",
65819
- unit: "%",
65820
- deadband: 2
65821
- },
65822
- "detergent.level": {
65823
- kind: "gauge",
65824
- unit: "%",
65825
- deadband: 2
65826
- },
65827
- "dustBin.level": {
65828
- kind: "gauge",
65829
- unit: "%",
65830
- deadband: 2
65831
- }
65832
- } }
65886
+ history: { fields: { batteryLevel: {
65887
+ kind: "gauge",
65888
+ unit: "%",
65889
+ deadband: 2
65890
+ } } }
65833
65891
  };
65834
65892
  var ValveStatusSchema = object({
65835
65893
  /** Lifecycle state of the valve. */
@@ -70227,6 +70285,12 @@ Object.freeze({
70227
70285
  addonId: null,
70228
70286
  access: "create"
70229
70287
  },
70288
+ "deviceHistory.deleteOrphanSeries": {
70289
+ capName: "device-history",
70290
+ capScope: "system",
70291
+ addonId: null,
70292
+ access: "delete"
70293
+ },
70230
70294
  "deviceHistory.getDeviceEnabled": {
70231
70295
  capName: "device-history",
70232
70296
  capScope: "system",
@@ -70245,6 +70309,12 @@ Object.freeze({
70245
70309
  addonId: null,
70246
70310
  access: "view"
70247
70311
  },
70312
+ "deviceHistory.listOrphanSeries": {
70313
+ capName: "device-history",
70314
+ capScope: "system",
70315
+ addonId: null,
70316
+ access: "view"
70317
+ },
70248
70318
  "deviceHistory.listSeries": {
70249
70319
  capName: "device-history",
70250
70320
  capScope: "system",
@@ -80456,7 +80526,7 @@ var STATE_SUMMARY_VARS = [
80456
80526
  ([...RULE_TEXT], [...COMBINED_ALARM]),
80457
80527
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
80458
80528
  ([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
80459
- ([...RULE_TEXT], [...CONSUMABLE]),
80529
+ ([...RULE_TEXT], [...CONSUMABLE, ...TANK]),
80460
80530
  ([...RULE_TEXT], [...TANK]),
80461
80531
  [...RULE_TEXT],
80462
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({
@@ -48096,7 +48153,6 @@ var RecommendationReasonSchema = discriminatedUnion("kind", [
48096
48153
  modelId: string()
48097
48154
  }),
48098
48155
  object({ kind: literal("cpu-device") }),
48099
- object({ kind: literal("coral-untouched") }),
48100
48156
  object({ kind: literal("device-disabled") }),
48101
48157
  object({ kind: literal("device-unavailable") }),
48102
48158
  object({ kind: literal("node-offline") }),
@@ -48194,11 +48250,6 @@ var AutoTuneWarningSchema = discriminatedUnion("kind", [
48194
48250
  kind: literal("detector-store-unreadable"),
48195
48251
  error: string()
48196
48252
  }),
48197
- object({
48198
- kind: literal("coral-enabled"),
48199
- nodeId: string(),
48200
- deviceKey: string()
48201
- }),
48202
48253
  object({
48203
48254
  kind: literal("custom-pin-kept"),
48204
48255
  nodeId: string(),
@@ -55747,17 +55798,69 @@ var connectivityCapability = {
55747
55798
  volatileStateFields: ["lastChangedAt"]
55748
55799
  };
55749
55800
  /**
55750
- * Generic device-consumables capability — surfaces a device's
55751
- * maintenance items (vacuum filters/brushes, replaceable cartridges,
55752
- * descaling cycles, …) with their remaining life and an optional
55753
- * "Replaced" reset action. Device-agnostic: any provider that knows its
55754
- * device tracks consumables can register it; the cap declares no
55755
- * 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).
55756
55813
  *
55757
55814
  * Like `childLayout`, the cap is INERT until a provider sets items: no
55758
55815
  * provider populates it by guessing (no HA inference). The UI renders a
55759
55816
  * "No consumables reported" placeholder when `items` is empty.
55760
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
+ ]);
55761
55864
  /** Units a remaining-life counter is reported in. Closed: the panel renders
55762
55865
  * each. */
55763
55866
  var ConsumableRemainingUnitSchema = _enum([
@@ -55772,18 +55875,23 @@ var ConsumableRemainingSchema = object({
55772
55875
  unit: ConsumableRemainingUnitSchema
55773
55876
  });
55774
55877
  /** A single consumable item. Either a continuous `level` (remaining
55775
- * life %) or a discrete `status` may be known — both may be null when a
55776
- * provider only knows the item exists. `level` and `status` are not
55777
- * 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. */
55778
55882
  var ConsumableItemSchema = object({
55779
55883
  /** Stable id, e.g. 'main-brush'. */
55780
55884
  key: string().min(1),
55781
55885
  /** Display name. */
55782
55886
  label: string().min(1),
55783
- /** Remaining life % when known (0..100). */
55887
+ /** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
55784
55888
  level: number().min(0).max(100).nullable(),
55785
- /** Discrete state when known (binary mode). */
55786
- 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(),
55787
55895
  /** Ms epoch of the last replace, when known. */
55788
55896
  lastResetAt: number().nullable(),
55789
55897
  /** Whether `reset()` is meaningful for this item. */
@@ -55806,7 +55914,7 @@ var consumablesCapability = {
55806
55914
  kind: "widget",
55807
55915
  widgetId: "host/consumables-panel",
55808
55916
  tab: "consumables",
55809
- topTab: true,
55917
+ placement: "hero",
55810
55918
  label: "Consumables",
55811
55919
  order: 5
55812
55920
  } },
@@ -55867,9 +55975,37 @@ reset: method(object({
55867
55975
  */
55868
55976
  durability: "restored",
55869
55977
  /**
55870
- * 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.
55871
55982
  */
55872
- 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
+ },
55873
56009
  /** Clocks, not content: a re-read that changed no item costs no commit. */
55874
56010
  volatileStateFields: ["lastChangedAt", "lastFetchedAt"]
55875
56011
  };
@@ -56284,8 +56420,9 @@ onStatusChanged: { data: object({
56284
56420
  volatileStateFields: ["lastChangedAt"]
56285
56421
  };
56286
56422
  /**
56287
- * Smart-dishwasher cap — program lifecycle, door / remote-start gates,
56288
- * 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).
56289
56426
  *
56290
56427
  * Sources: native Bosch Home Connect (`dishwasher` device type). Reusable
56291
56428
  * by any integration that exposes the same program / option surface.
@@ -56333,11 +56470,6 @@ var DishwasherAvailabilitySchema = _enum([
56333
56470
  "offline",
56334
56471
  "description-missing"
56335
56472
  ]);
56336
- var DishwasherConsumableLevelSchema = _enum([
56337
- "ok",
56338
- "low",
56339
- "empty"
56340
- ]);
56341
56473
  var DishwasherStatusSchema = object({
56342
56474
  availability: DishwasherAvailabilitySchema,
56343
56475
  /** Coarse state for compact surfaces; `unavailable` whenever the appliance state is not known. */
@@ -56370,8 +56502,6 @@ var DishwasherStatusSchema = object({
56370
56502
  powerOn: boolean().nullable(),
56371
56503
  /** The raw power state (`On`, `Off`, `Standby`, …); null when not known. */
56372
56504
  powerState: string().nullable(),
56373
- saltLevel: DishwasherConsumableLevelSchema.nullable(),
56374
- rinseAidLevel: DishwasherConsumableLevelSchema.nullable(),
56375
56505
  /**
56376
56506
  * True while the appliance asks for its filter to be cleaned (smart-filter, filter-system or
56377
56507
  * combined care-and-filter reminder raised); false when every such reminder reads clear; null
@@ -65649,60 +65779,17 @@ method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserI
65649
65779
  auth: "admin",
65650
65780
  access: "delete"
65651
65781
  });
65652
- /**
65653
- * Robot-vacuum cap. Models HA `vacuum.*` entities — anything with a
65654
- * cleaning lifecycle plus a return-to-base / locate surface and an
65655
- * optional fan-speed selector.
65656
- *
65657
- * State follows HA's canonical vacuum lifecycle: `idle` / `cleaning` /
65658
- * `paused` / `returning` / `docked` / `error`. `batteryLevel`
65659
- * (0..100) is nullable — some vacuums don't report a battery
65660
- * percentage. `fanSpeed` is the current speed token (provider-verbatim,
65661
- * e.g. `'standard'` / `'turbo'`) and `availableFanSpeeds` lists the
65662
- * tokens the hardware accepts so the UI renders only supported choices.
65663
- *
65664
- * The `setFanSpeed` method takes the bare `speed` token — the provider
65665
- * validates it against the vacuum's own list. `locate` triggers the
65666
- * find-me chirp; `returnToBase` sends it home.
65667
- *
65668
- * Consumable / waste tanks: `cleanWater` / `dirtyWater` / `detergent` /
65669
- * `dustBin` each carry a nullable `{ level (0..100 %), status ('ok' |
65670
- * 'low' | 'full') }` reading. Native providers (e.g. Dreame, Roborock)
65671
- * SHOULD populate whichever tanks the hardware has — leave a field `null`
65672
- * only when the device has no such tank at all, and use a `TankStatus`
65673
- * with both inner fields `null` when the tank exists but its level is
65674
- * currently unknown. HA `vacuum.*` entities expose no per-tank telemetry,
65675
- * so the HA provider leaves all four `null`.
65676
- */
65677
- var VacuumStateSchema = _enum([
65678
- "idle",
65679
- "cleaning",
65680
- "paused",
65681
- "returning",
65682
- "docked",
65683
- "drying",
65684
- "error"
65685
- ]);
65686
- /**
65687
- * One consumable / waste tank on a robot vacuum (clean-water, dirty-water,
65688
- * detergent or dust-bin). A tank can report a numeric fill `level` (0..100),
65689
- * a discrete `status` (binary-style hardware), or both. Both `null` means the
65690
- * level is currently unknown; the OWNING field being `null` means the
65691
- * hardware has no such tank at all.
65692
- */
65693
- var TankStatusSchema = object({
65694
- /** Numeric fill 0..100 when the hardware reports a percentage; null otherwise. */
65695
- level: number().min(0).max(100).nullable(),
65696
- /** Discrete state when the hardware is binary-mode; null otherwise. */
65697
- status: _enum([
65698
- "ok",
65699
- "low",
65700
- "full"
65701
- ]).nullable()
65702
- });
65703
65782
  var VacuumControlStatusSchema = object({
65704
65783
  /** Lifecycle state of the vacuum. */
65705
- state: VacuumStateSchema,
65784
+ state: _enum([
65785
+ "idle",
65786
+ "cleaning",
65787
+ "paused",
65788
+ "returning",
65789
+ "docked",
65790
+ "drying",
65791
+ "error"
65792
+ ]),
65706
65793
  /** 0..100 battery percentage. Null when the device has no battery
65707
65794
  * reading. */
65708
65795
  batteryLevel: number().min(0).max(100).nullable(),
@@ -65711,14 +65798,6 @@ var VacuumControlStatusSchema = object({
65711
65798
  fanSpeed: string().nullable(),
65712
65799
  /** Speed tokens the hardware accepts — drives the UI selector. */
65713
65800
  availableFanSpeeds: array(string()),
65714
- /** Clean-water (mop) tank. Null when the hardware has no clean-water tank. */
65715
- cleanWater: TankStatusSchema.nullable(),
65716
- /** Dirty-water (recovery) tank. Null when the hardware has no dirty-water tank. */
65717
- dirtyWater: TankStatusSchema.nullable(),
65718
- /** Detergent tank. Null when the hardware has no detergent tank. */
65719
- detergent: TankStatusSchema.nullable(),
65720
- /** Dust bin. Null when the hardware has no dust bin. */
65721
- dustBin: TankStatusSchema.nullable(),
65722
65801
  /** 0..100 cleaning-completion percentage of the current task, or null. */
65723
65802
  progressPercent: number().min(0).max(100).nullable(),
65724
65803
  /** Current error code (0 / null = no error). */
@@ -65780,35 +65859,14 @@ var vacuumControlCapability = {
65780
65859
  */
65781
65860
  durability: "session",
65782
65861
  /**
65783
- * 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.
65784
65864
  */
65785
- history: { fields: {
65786
- batteryLevel: {
65787
- kind: "gauge",
65788
- unit: "%",
65789
- deadband: 2
65790
- },
65791
- "cleanWater.level": {
65792
- kind: "gauge",
65793
- unit: "%",
65794
- deadband: 2
65795
- },
65796
- "dirtyWater.level": {
65797
- kind: "gauge",
65798
- unit: "%",
65799
- deadband: 2
65800
- },
65801
- "detergent.level": {
65802
- kind: "gauge",
65803
- unit: "%",
65804
- deadband: 2
65805
- },
65806
- "dustBin.level": {
65807
- kind: "gauge",
65808
- unit: "%",
65809
- deadband: 2
65810
- }
65811
- } }
65865
+ history: { fields: { batteryLevel: {
65866
+ kind: "gauge",
65867
+ unit: "%",
65868
+ deadband: 2
65869
+ } } }
65812
65870
  };
65813
65871
  var ValveStatusSchema = object({
65814
65872
  /** Lifecycle state of the valve. */
@@ -70206,6 +70264,12 @@ Object.freeze({
70206
70264
  addonId: null,
70207
70265
  access: "create"
70208
70266
  },
70267
+ "deviceHistory.deleteOrphanSeries": {
70268
+ capName: "device-history",
70269
+ capScope: "system",
70270
+ addonId: null,
70271
+ access: "delete"
70272
+ },
70209
70273
  "deviceHistory.getDeviceEnabled": {
70210
70274
  capName: "device-history",
70211
70275
  capScope: "system",
@@ -70224,6 +70288,12 @@ Object.freeze({
70224
70288
  addonId: null,
70225
70289
  access: "view"
70226
70290
  },
70291
+ "deviceHistory.listOrphanSeries": {
70292
+ capName: "device-history",
70293
+ capScope: "system",
70294
+ addonId: null,
70295
+ access: "view"
70296
+ },
70227
70297
  "deviceHistory.listSeries": {
70228
70298
  capName: "device-history",
70229
70299
  capScope: "system",
@@ -80435,7 +80505,7 @@ var STATE_SUMMARY_VARS = [
80435
80505
  ([...RULE_TEXT], [...COMBINED_ALARM]),
80436
80506
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
80437
80507
  ([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
80438
- ([...RULE_TEXT], [...CONSUMABLE]),
80508
+ ([...RULE_TEXT], [...CONSUMABLE, ...TANK]),
80439
80509
  ([...RULE_TEXT], [...TANK]),
80440
80510
  [...RULE_TEXT],
80441
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.153",
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",