@camstack/addon-provider-dreame 0.2.149 → 0.2.151
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.
- package/dist/addon.js +302 -149
- package/dist/addon.mjs +302 -149
- package/package.json +1 -1
package/dist/addon.js
CHANGED
|
@@ -5476,7 +5476,7 @@ var ZodIssueCode$1 = {
|
|
|
5476
5476
|
var ZodFirstPartyTypeKind$1;
|
|
5477
5477
|
ZodFirstPartyTypeKind$1 || (ZodFirstPartyTypeKind$1 = {});
|
|
5478
5478
|
//#endregion
|
|
5479
|
-
//#region ../types/dist/sleep-
|
|
5479
|
+
//#region ../types/dist/sleep-CUp20JkO.mjs
|
|
5480
5480
|
/**
|
|
5481
5481
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5482
5482
|
* window to float samples (D455).
|
|
@@ -8368,7 +8368,11 @@ var ContributionSectionSchema = object({
|
|
|
8368
8368
|
literal(4)
|
|
8369
8369
|
]).optional(),
|
|
8370
8370
|
tab: string().optional(),
|
|
8371
|
-
location: _enum([
|
|
8371
|
+
location: _enum([
|
|
8372
|
+
"settings",
|
|
8373
|
+
"top-tab",
|
|
8374
|
+
"hero"
|
|
8375
|
+
]).optional(),
|
|
8372
8376
|
order: number().optional(),
|
|
8373
8377
|
fields: array(any())
|
|
8374
8378
|
});
|
|
@@ -13315,7 +13319,11 @@ var ConfigSectionWithValuesSchema = object({
|
|
|
13315
13319
|
literal(4)
|
|
13316
13320
|
]).optional(),
|
|
13317
13321
|
tab: string().optional(),
|
|
13318
|
-
location: _enum([
|
|
13322
|
+
location: _enum([
|
|
13323
|
+
"settings",
|
|
13324
|
+
"top-tab",
|
|
13325
|
+
"hero"
|
|
13326
|
+
]).optional(),
|
|
13319
13327
|
order: number().optional(),
|
|
13320
13328
|
fields: array(any())
|
|
13321
13329
|
});
|
|
@@ -17195,6 +17203,52 @@ var TierStatusSchema = object({
|
|
|
17195
17203
|
countedAt: number().nullable()
|
|
17196
17204
|
});
|
|
17197
17205
|
/** Operator/diagnostic view: rows per tier, last runs, refusals and drops since boot. */
|
|
17206
|
+
/**
|
|
17207
|
+
* Why a series is orphan. `device-gone`: its device is absent from the
|
|
17208
|
+
* successful device listings (the departure clock). `undeclared`: its `cap:`
|
|
17209
|
+
* key is declared by no capability any more (a field a cap removed).
|
|
17210
|
+
*/
|
|
17211
|
+
var DeviceHistoryOrphanReasonSchema = _enum(["device-gone", "undeclared"]);
|
|
17212
|
+
/** Rows held per stored tier. */
|
|
17213
|
+
var TierRowsSchema = object({
|
|
17214
|
+
raw: number().int(),
|
|
17215
|
+
"5m": number().int(),
|
|
17216
|
+
"1h": number().int(),
|
|
17217
|
+
"1d": number().int()
|
|
17218
|
+
});
|
|
17219
|
+
var OrphanSeriesSchema = object({
|
|
17220
|
+
seriesId: number().int(),
|
|
17221
|
+
deviceId: number().int(),
|
|
17222
|
+
key: string(),
|
|
17223
|
+
scope: string(),
|
|
17224
|
+
/** The metric's display name; `null` when its metric row is gone too. */
|
|
17225
|
+
displayName: string().nullable(),
|
|
17226
|
+
reason: DeviceHistoryOrphanReasonSchema,
|
|
17227
|
+
/** `device-gone`: since when the device has been absent; `null` otherwise. */
|
|
17228
|
+
missingSince: number().nullable(),
|
|
17229
|
+
firstTs: number(),
|
|
17230
|
+
lastTs: number(),
|
|
17231
|
+
rows: TierRowsSchema
|
|
17232
|
+
});
|
|
17233
|
+
var DeviceHistoryOrphanDeleteRefusalSchema = _enum([
|
|
17234
|
+
"not-found",
|
|
17235
|
+
"not-orphan",
|
|
17236
|
+
"failed"
|
|
17237
|
+
]);
|
|
17238
|
+
var OrphanDeleteEntrySchema = discriminatedUnion("ok", [object({
|
|
17239
|
+
seriesId: number().int(),
|
|
17240
|
+
ok: literal(true),
|
|
17241
|
+
deleted: TierRowsSchema
|
|
17242
|
+
}), object({
|
|
17243
|
+
seriesId: number().int(),
|
|
17244
|
+
ok: literal(false),
|
|
17245
|
+
reason: DeviceHistoryOrphanDeleteRefusalSchema
|
|
17246
|
+
})]);
|
|
17247
|
+
var OrphanListSchema = object({
|
|
17248
|
+
series: array(OrphanSeriesSchema).readonly(),
|
|
17249
|
+
/** More orphans exist than {@link DEVICE_HISTORY_ORPHAN_LIST_MAX}. */
|
|
17250
|
+
truncated: boolean()
|
|
17251
|
+
});
|
|
17198
17252
|
var DeviceHistoryStatusSchema = object({
|
|
17199
17253
|
startedAt: number(),
|
|
17200
17254
|
/** The store is declared, series loaded and the first reconcile has answered. */
|
|
@@ -17292,7 +17346,10 @@ method(object({ deviceId: number().int() }), array(SeriesInfoSchema).readonly())
|
|
|
17292
17346
|
}), object({ enabled: boolean() }), {
|
|
17293
17347
|
kind: "mutation",
|
|
17294
17348
|
auth: "admin"
|
|
17295
|
-
}), method(object({}), DeviceHistoryStatusSchema, { auth: "admin" })
|
|
17349
|
+
}), 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() }), {
|
|
17350
|
+
kind: "mutation",
|
|
17351
|
+
auth: "admin"
|
|
17352
|
+
});
|
|
17296
17353
|
var DeviceCaStatusSchema = discriminatedUnion("state", [
|
|
17297
17354
|
object({ state: literal("absent") }),
|
|
17298
17355
|
object({
|
|
@@ -48032,7 +48089,6 @@ var RecommendationReasonSchema = discriminatedUnion("kind", [
|
|
|
48032
48089
|
modelId: string()
|
|
48033
48090
|
}),
|
|
48034
48091
|
object({ kind: literal("cpu-device") }),
|
|
48035
|
-
object({ kind: literal("coral-untouched") }),
|
|
48036
48092
|
object({ kind: literal("device-disabled") }),
|
|
48037
48093
|
object({ kind: literal("device-unavailable") }),
|
|
48038
48094
|
object({ kind: literal("node-offline") }),
|
|
@@ -48130,11 +48186,6 @@ var AutoTuneWarningSchema = discriminatedUnion("kind", [
|
|
|
48130
48186
|
kind: literal("detector-store-unreadable"),
|
|
48131
48187
|
error: string()
|
|
48132
48188
|
}),
|
|
48133
|
-
object({
|
|
48134
|
-
kind: literal("coral-enabled"),
|
|
48135
|
-
nodeId: string(),
|
|
48136
|
-
deviceKey: string()
|
|
48137
|
-
}),
|
|
48138
48189
|
object({
|
|
48139
48190
|
kind: literal("custom-pin-kept"),
|
|
48140
48191
|
nodeId: string(),
|
|
@@ -55195,17 +55246,73 @@ var connectivityCapability = {
|
|
|
55195
55246
|
volatileStateFields: ["lastChangedAt"]
|
|
55196
55247
|
};
|
|
55197
55248
|
/**
|
|
55198
|
-
* Generic device-consumables capability —
|
|
55199
|
-
*
|
|
55200
|
-
* descaling cycles,
|
|
55201
|
-
*
|
|
55202
|
-
*
|
|
55203
|
-
*
|
|
55249
|
+
* Generic device-consumables capability — the ONE place a device reports what
|
|
55250
|
+
* it uses up or fills: wear parts (vacuum filters/brushes, cartridges,
|
|
55251
|
+
* descaling cycles), supplies it draws from (a vacuum's clean-water tank and
|
|
55252
|
+
* detergent, a dishwasher's salt and rinse aid) and waste it collects (a dirty
|
|
55253
|
+
* water tank, a dust bin). Each item carries its remaining life or fill and an
|
|
55254
|
+
* optional "Replaced" reset action. Device-agnostic: any provider that knows
|
|
55255
|
+
* its device tracks consumables registers it; the provider names each item
|
|
55256
|
+
* verbatim and says which `kind` it is.
|
|
55257
|
+
*
|
|
55258
|
+
* The admin UI renders it as ONE collapsible section directly under the
|
|
55259
|
+
* device page's hero card (`placement: 'hero'`), for every device bound to
|
|
55260
|
+
* this cap — never drawn by a device type's hero card itself (D915).
|
|
55204
55261
|
*
|
|
55205
55262
|
* Like `childLayout`, the cap is INERT until a provider sets items: no
|
|
55206
55263
|
* provider populates it by guessing (no HA inference). The UI renders a
|
|
55207
55264
|
* "No consumables reported" placeholder when `items` is empty.
|
|
55208
55265
|
*/
|
|
55266
|
+
/**
|
|
55267
|
+
* What an item IS, which decides which direction is bad:
|
|
55268
|
+
* - `wear` — a part that wears out (a brush, a filter); low life is bad.
|
|
55269
|
+
* - `supply` — something the device draws from (clean water, detergent,
|
|
55270
|
+
* salt, rinse aid); low or empty is bad.
|
|
55271
|
+
* - `waste` — something the device fills (dirty water, a dust bin); full is
|
|
55272
|
+
* bad.
|
|
55273
|
+
* Absent = `wear`.
|
|
55274
|
+
*/
|
|
55275
|
+
var ConsumableKindSchema = _enum([
|
|
55276
|
+
"wear",
|
|
55277
|
+
"supply",
|
|
55278
|
+
"waste"
|
|
55279
|
+
]);
|
|
55280
|
+
/**
|
|
55281
|
+
* What an item LOOKS like, which decides how a client draws it — independent
|
|
55282
|
+
* of `kind`, which decides which direction is bad:
|
|
55283
|
+
* - `part` — a part that wears (a brush, a filter, a mop pad): a wear bar,
|
|
55284
|
+
* remaining time and a reset.
|
|
55285
|
+
* - `tank` — a container of liquid (clean water, dirty water): a fill gauge.
|
|
55286
|
+
* - `product` — something bought and refilled (detergent, salt, rinse aid):
|
|
55287
|
+
* a stepped level and "refill".
|
|
55288
|
+
* - `bin` — a container that collects waste (a dust bin): a fill gauge
|
|
55289
|
+
* that warns when full.
|
|
55290
|
+
* Absent = derived from the kind ({@link consumableFormOf}).
|
|
55291
|
+
*/
|
|
55292
|
+
var ConsumableFormSchema = _enum([
|
|
55293
|
+
"part",
|
|
55294
|
+
"tank",
|
|
55295
|
+
"product",
|
|
55296
|
+
"bin"
|
|
55297
|
+
]);
|
|
55298
|
+
/** The provider's own discrete verdict on an item. */
|
|
55299
|
+
var ConsumableStatusSchema = _enum([
|
|
55300
|
+
"ok",
|
|
55301
|
+
"low",
|
|
55302
|
+
"empty",
|
|
55303
|
+
"full",
|
|
55304
|
+
"replace"
|
|
55305
|
+
]);
|
|
55306
|
+
_enum([
|
|
55307
|
+
"ok",
|
|
55308
|
+
"low",
|
|
55309
|
+
"empty",
|
|
55310
|
+
"full"
|
|
55311
|
+
]);
|
|
55312
|
+
/** The kind of an item, with the documented default for an absent one. */
|
|
55313
|
+
function consumableKindOf(item) {
|
|
55314
|
+
return item.kind ?? "wear";
|
|
55315
|
+
}
|
|
55209
55316
|
/** Units a remaining-life counter is reported in. Closed: the panel renders
|
|
55210
55317
|
* each. */
|
|
55211
55318
|
var ConsumableRemainingUnitSchema = _enum([
|
|
@@ -55220,18 +55327,23 @@ var ConsumableRemainingSchema = object({
|
|
|
55220
55327
|
unit: ConsumableRemainingUnitSchema
|
|
55221
55328
|
});
|
|
55222
55329
|
/** A single consumable item. Either a continuous `level` (remaining
|
|
55223
|
-
* life
|
|
55224
|
-
*
|
|
55225
|
-
* mutually exclusive; a provider may
|
|
55330
|
+
* life %, or fill % for a `supply` / `waste` item) or a discrete `status`
|
|
55331
|
+
* may be known — both may be null when a provider only knows the item
|
|
55332
|
+
* exists. `level` and `status` are not mutually exclusive; a provider may
|
|
55333
|
+
* report both. */
|
|
55226
55334
|
var ConsumableItemSchema = object({
|
|
55227
55335
|
/** Stable id, e.g. 'main-brush'. */
|
|
55228
55336
|
key: string().min(1),
|
|
55229
55337
|
/** Display name. */
|
|
55230
55338
|
label: string().min(1),
|
|
55231
|
-
/** Remaining life % when known (0..100). */
|
|
55339
|
+
/** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
|
|
55232
55340
|
level: number().min(0).max(100).nullable(),
|
|
55233
|
-
/**
|
|
55234
|
-
status:
|
|
55341
|
+
/** The provider's discrete verdict when known (binary mode). */
|
|
55342
|
+
status: ConsumableStatusSchema.nullable(),
|
|
55343
|
+
/** What the item is — decides whether low or full is bad. Absent = `wear`. */
|
|
55344
|
+
kind: ConsumableKindSchema.optional(),
|
|
55345
|
+
/** How the item is drawn (part, tank, product, bin). Absent = derived from `kind`. */
|
|
55346
|
+
form: ConsumableFormSchema.optional(),
|
|
55235
55347
|
/** Ms epoch of the last replace, when known. */
|
|
55236
55348
|
lastResetAt: number().nullable(),
|
|
55237
55349
|
/** Whether `reset()` is meaningful for this item. */
|
|
@@ -55254,7 +55366,7 @@ var consumablesCapability = {
|
|
|
55254
55366
|
kind: "widget",
|
|
55255
55367
|
widgetId: "host/consumables-panel",
|
|
55256
55368
|
tab: "consumables",
|
|
55257
|
-
|
|
55369
|
+
placement: "hero",
|
|
55258
55370
|
label: "Consumables",
|
|
55259
55371
|
order: 5
|
|
55260
55372
|
} },
|
|
@@ -55315,9 +55427,37 @@ reset: method(object({
|
|
|
55315
55427
|
*/
|
|
55316
55428
|
durability: "restored",
|
|
55317
55429
|
/**
|
|
55318
|
-
* History (D850):
|
|
55430
|
+
* History (D850, D917): one series per (item field, item `key`) — the item key
|
|
55431
|
+
* is the series scope, the item `label` names it. A vacuum tank's fill, a
|
|
55432
|
+
* brush's remaining life and a dishwasher's salt are each recorded the moment
|
|
55433
|
+
* their provider reports them; an item that appears later gets its series.
|
|
55319
55434
|
*/
|
|
55320
|
-
history:
|
|
55435
|
+
history: {
|
|
55436
|
+
fields: {},
|
|
55437
|
+
items: {
|
|
55438
|
+
path: "items",
|
|
55439
|
+
key: "key",
|
|
55440
|
+
label: "label",
|
|
55441
|
+
fields: {
|
|
55442
|
+
level: {
|
|
55443
|
+
kind: "gauge",
|
|
55444
|
+
unit: "%",
|
|
55445
|
+
deadband: 2,
|
|
55446
|
+
displayName: "Level"
|
|
55447
|
+
},
|
|
55448
|
+
status: {
|
|
55449
|
+
kind: "enum",
|
|
55450
|
+
displayName: "Status"
|
|
55451
|
+
},
|
|
55452
|
+
"remaining.value": {
|
|
55453
|
+
kind: "gauge",
|
|
55454
|
+
unitFrom: "remaining.unit",
|
|
55455
|
+
deadband: 1,
|
|
55456
|
+
displayName: "Remaining"
|
|
55457
|
+
}
|
|
55458
|
+
}
|
|
55459
|
+
}
|
|
55460
|
+
},
|
|
55321
55461
|
/** Clocks, not content: a re-read that changed no item costs no commit. */
|
|
55322
55462
|
volatileStateFields: ["lastChangedAt", "lastFetchedAt"]
|
|
55323
55463
|
};
|
|
@@ -55732,8 +55872,9 @@ onStatusChanged: { data: object({
|
|
|
55732
55872
|
volatileStateFields: ["lastChangedAt"]
|
|
55733
55873
|
};
|
|
55734
55874
|
/**
|
|
55735
|
-
* Smart-dishwasher cap — program lifecycle, door / remote-start gates
|
|
55736
|
-
*
|
|
55875
|
+
* Smart-dishwasher cap — program lifecycle, door / remote-start gates and
|
|
55876
|
+
* common program options. Salt and rinse aid are NOT here: they are items of
|
|
55877
|
+
* the device's `consumables` cap, like every other device's (D915).
|
|
55737
55878
|
*
|
|
55738
55879
|
* Sources: native Bosch Home Connect (`dishwasher` device type). Reusable
|
|
55739
55880
|
* by any integration that exposes the same program / option surface.
|
|
@@ -55781,11 +55922,6 @@ var DishwasherAvailabilitySchema = _enum([
|
|
|
55781
55922
|
"offline",
|
|
55782
55923
|
"description-missing"
|
|
55783
55924
|
]);
|
|
55784
|
-
var DishwasherConsumableLevelSchema = _enum([
|
|
55785
|
-
"ok",
|
|
55786
|
-
"low",
|
|
55787
|
-
"empty"
|
|
55788
|
-
]);
|
|
55789
55925
|
var DishwasherStatusSchema = object({
|
|
55790
55926
|
availability: DishwasherAvailabilitySchema,
|
|
55791
55927
|
/** Coarse state for compact surfaces; `unavailable` whenever the appliance state is not known. */
|
|
@@ -55818,8 +55954,6 @@ var DishwasherStatusSchema = object({
|
|
|
55818
55954
|
powerOn: boolean().nullable(),
|
|
55819
55955
|
/** The raw power state (`On`, `Off`, `Standby`, …); null when not known. */
|
|
55820
55956
|
powerState: string().nullable(),
|
|
55821
|
-
saltLevel: DishwasherConsumableLevelSchema.nullable(),
|
|
55822
|
-
rinseAidLevel: DishwasherConsumableLevelSchema.nullable(),
|
|
55823
55957
|
/**
|
|
55824
55958
|
* True while the appliance asks for its filter to be cleaned (smart-filter, filter-system or
|
|
55825
55959
|
* combined care-and-filter reminder raised); false when every such reminder reads clear; null
|
|
@@ -64783,60 +64917,17 @@ method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserI
|
|
|
64783
64917
|
auth: "admin",
|
|
64784
64918
|
access: "delete"
|
|
64785
64919
|
});
|
|
64786
|
-
/**
|
|
64787
|
-
* Robot-vacuum cap. Models HA `vacuum.*` entities — anything with a
|
|
64788
|
-
* cleaning lifecycle plus a return-to-base / locate surface and an
|
|
64789
|
-
* optional fan-speed selector.
|
|
64790
|
-
*
|
|
64791
|
-
* State follows HA's canonical vacuum lifecycle: `idle` / `cleaning` /
|
|
64792
|
-
* `paused` / `returning` / `docked` / `error`. `batteryLevel`
|
|
64793
|
-
* (0..100) is nullable — some vacuums don't report a battery
|
|
64794
|
-
* percentage. `fanSpeed` is the current speed token (provider-verbatim,
|
|
64795
|
-
* e.g. `'standard'` / `'turbo'`) and `availableFanSpeeds` lists the
|
|
64796
|
-
* tokens the hardware accepts so the UI renders only supported choices.
|
|
64797
|
-
*
|
|
64798
|
-
* The `setFanSpeed` method takes the bare `speed` token — the provider
|
|
64799
|
-
* validates it against the vacuum's own list. `locate` triggers the
|
|
64800
|
-
* find-me chirp; `returnToBase` sends it home.
|
|
64801
|
-
*
|
|
64802
|
-
* Consumable / waste tanks: `cleanWater` / `dirtyWater` / `detergent` /
|
|
64803
|
-
* `dustBin` each carry a nullable `{ level (0..100 %), status ('ok' |
|
|
64804
|
-
* 'low' | 'full') }` reading. Native providers (e.g. Dreame, Roborock)
|
|
64805
|
-
* SHOULD populate whichever tanks the hardware has — leave a field `null`
|
|
64806
|
-
* only when the device has no such tank at all, and use a `TankStatus`
|
|
64807
|
-
* with both inner fields `null` when the tank exists but its level is
|
|
64808
|
-
* currently unknown. HA `vacuum.*` entities expose no per-tank telemetry,
|
|
64809
|
-
* so the HA provider leaves all four `null`.
|
|
64810
|
-
*/
|
|
64811
|
-
var VacuumStateSchema = _enum([
|
|
64812
|
-
"idle",
|
|
64813
|
-
"cleaning",
|
|
64814
|
-
"paused",
|
|
64815
|
-
"returning",
|
|
64816
|
-
"docked",
|
|
64817
|
-
"drying",
|
|
64818
|
-
"error"
|
|
64819
|
-
]);
|
|
64820
|
-
/**
|
|
64821
|
-
* One consumable / waste tank on a robot vacuum (clean-water, dirty-water,
|
|
64822
|
-
* detergent or dust-bin). A tank can report a numeric fill `level` (0..100),
|
|
64823
|
-
* a discrete `status` (binary-style hardware), or both. Both `null` means the
|
|
64824
|
-
* level is currently unknown; the OWNING field being `null` means the
|
|
64825
|
-
* hardware has no such tank at all.
|
|
64826
|
-
*/
|
|
64827
|
-
var TankStatusSchema = object({
|
|
64828
|
-
/** Numeric fill 0..100 when the hardware reports a percentage; null otherwise. */
|
|
64829
|
-
level: number().min(0).max(100).nullable(),
|
|
64830
|
-
/** Discrete state when the hardware is binary-mode; null otherwise. */
|
|
64831
|
-
status: _enum([
|
|
64832
|
-
"ok",
|
|
64833
|
-
"low",
|
|
64834
|
-
"full"
|
|
64835
|
-
]).nullable()
|
|
64836
|
-
});
|
|
64837
64920
|
var VacuumControlStatusSchema = object({
|
|
64838
64921
|
/** Lifecycle state of the vacuum. */
|
|
64839
|
-
state:
|
|
64922
|
+
state: _enum([
|
|
64923
|
+
"idle",
|
|
64924
|
+
"cleaning",
|
|
64925
|
+
"paused",
|
|
64926
|
+
"returning",
|
|
64927
|
+
"docked",
|
|
64928
|
+
"drying",
|
|
64929
|
+
"error"
|
|
64930
|
+
]),
|
|
64840
64931
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
64841
64932
|
* reading. */
|
|
64842
64933
|
batteryLevel: number().min(0).max(100).nullable(),
|
|
@@ -64845,14 +64936,6 @@ var VacuumControlStatusSchema = object({
|
|
|
64845
64936
|
fanSpeed: string().nullable(),
|
|
64846
64937
|
/** Speed tokens the hardware accepts — drives the UI selector. */
|
|
64847
64938
|
availableFanSpeeds: array(string()),
|
|
64848
|
-
/** Clean-water (mop) tank. Null when the hardware has no clean-water tank. */
|
|
64849
|
-
cleanWater: TankStatusSchema.nullable(),
|
|
64850
|
-
/** Dirty-water (recovery) tank. Null when the hardware has no dirty-water tank. */
|
|
64851
|
-
dirtyWater: TankStatusSchema.nullable(),
|
|
64852
|
-
/** Detergent tank. Null when the hardware has no detergent tank. */
|
|
64853
|
-
detergent: TankStatusSchema.nullable(),
|
|
64854
|
-
/** Dust bin. Null when the hardware has no dust bin. */
|
|
64855
|
-
dustBin: TankStatusSchema.nullable(),
|
|
64856
64939
|
/** 0..100 cleaning-completion percentage of the current task, or null. */
|
|
64857
64940
|
progressPercent: number().min(0).max(100).nullable(),
|
|
64858
64941
|
/** Current error code (0 / null = no error). */
|
|
@@ -64914,35 +64997,14 @@ var vacuumControlCapability = {
|
|
|
64914
64997
|
*/
|
|
64915
64998
|
durability: "session",
|
|
64916
64999
|
/**
|
|
64917
|
-
* History (D850): recorded series.
|
|
65000
|
+
* History (D850): recorded series. The tanks moved to `consumables` (D915), whose
|
|
65001
|
+
* items are keyed by runtime ids and record no history.
|
|
64918
65002
|
*/
|
|
64919
|
-
history: { fields: {
|
|
64920
|
-
|
|
64921
|
-
|
|
64922
|
-
|
|
64923
|
-
|
|
64924
|
-
},
|
|
64925
|
-
"cleanWater.level": {
|
|
64926
|
-
kind: "gauge",
|
|
64927
|
-
unit: "%",
|
|
64928
|
-
deadband: 2
|
|
64929
|
-
},
|
|
64930
|
-
"dirtyWater.level": {
|
|
64931
|
-
kind: "gauge",
|
|
64932
|
-
unit: "%",
|
|
64933
|
-
deadband: 2
|
|
64934
|
-
},
|
|
64935
|
-
"detergent.level": {
|
|
64936
|
-
kind: "gauge",
|
|
64937
|
-
unit: "%",
|
|
64938
|
-
deadband: 2
|
|
64939
|
-
},
|
|
64940
|
-
"dustBin.level": {
|
|
64941
|
-
kind: "gauge",
|
|
64942
|
-
unit: "%",
|
|
64943
|
-
deadband: 2
|
|
64944
|
-
}
|
|
64945
|
-
} }
|
|
65003
|
+
history: { fields: { batteryLevel: {
|
|
65004
|
+
kind: "gauge",
|
|
65005
|
+
unit: "%",
|
|
65006
|
+
deadband: 2
|
|
65007
|
+
} } }
|
|
64946
65008
|
};
|
|
64947
65009
|
var ValveStatusSchema = object({
|
|
64948
65010
|
/** Lifecycle state of the valve. */
|
|
@@ -69352,6 +69414,12 @@ Object.freeze({
|
|
|
69352
69414
|
addonId: null,
|
|
69353
69415
|
access: "create"
|
|
69354
69416
|
},
|
|
69417
|
+
"deviceHistory.deleteOrphanSeries": {
|
|
69418
|
+
capName: "device-history",
|
|
69419
|
+
capScope: "system",
|
|
69420
|
+
addonId: null,
|
|
69421
|
+
access: "delete"
|
|
69422
|
+
},
|
|
69355
69423
|
"deviceHistory.getDeviceEnabled": {
|
|
69356
69424
|
capName: "device-history",
|
|
69357
69425
|
capScope: "system",
|
|
@@ -69370,6 +69438,12 @@ Object.freeze({
|
|
|
69370
69438
|
addonId: null,
|
|
69371
69439
|
access: "view"
|
|
69372
69440
|
},
|
|
69441
|
+
"deviceHistory.listOrphanSeries": {
|
|
69442
|
+
capName: "device-history",
|
|
69443
|
+
capScope: "system",
|
|
69444
|
+
addonId: null,
|
|
69445
|
+
access: "view"
|
|
69446
|
+
},
|
|
69373
69447
|
"deviceHistory.listSeries": {
|
|
69374
69448
|
capName: "device-history",
|
|
69375
69449
|
capScope: "system",
|
|
@@ -79375,7 +79449,7 @@ var STATE_SUMMARY_VARS = [
|
|
|
79375
79449
|
([...RULE_TEXT], [...COMBINED_ALARM]),
|
|
79376
79450
|
([...RULE_TEXT], [...DEVICE_EVENTS]),
|
|
79377
79451
|
([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
|
|
79378
|
-
([...RULE_TEXT], [...CONSUMABLE]),
|
|
79452
|
+
([...RULE_TEXT], [...CONSUMABLE, ...TANK]),
|
|
79379
79453
|
([...RULE_TEXT], [...TANK]),
|
|
79380
79454
|
[...RULE_TEXT],
|
|
79381
79455
|
([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
|
|
@@ -135245,8 +135319,7 @@ function dirtyWaterTankStatus(value, errorCode) {
|
|
|
135245
135319
|
return null;
|
|
135246
135320
|
}
|
|
135247
135321
|
/**
|
|
135248
|
-
* The four
|
|
135249
|
-
* dust-bin) decoded from the model's {@link VacuumCapabilities}, with the
|
|
135322
|
+
* The four tanks (clean-water / dirty-water / detergent / dust-bin) decoded from the model's {@link VacuumCapabilities}, with the
|
|
135250
135323
|
* discrete `status` populated from the live MIoT enum props when supplied. Pure.
|
|
135251
135324
|
*
|
|
135252
135325
|
* The nodedreame library exposes NO tank FILL-LEVEL telemetry — the cloud shadow
|
|
@@ -135277,6 +135350,57 @@ function decodeVacuumTanks(caps, props, errorCode = null) {
|
|
|
135277
135350
|
dustBin: tank(Boolean(caps?.canAutoEmpty), props ? dustBinTankStatus(props.dustCollection, props.dustBagStatus) : null)
|
|
135278
135351
|
};
|
|
135279
135352
|
}
|
|
135353
|
+
/** How each tank is named and what it is, in the order the panel lists them. */
|
|
135354
|
+
var TANK_ITEMS = [
|
|
135355
|
+
{
|
|
135356
|
+
key: "cleanWater",
|
|
135357
|
+
label: "Clean water tank",
|
|
135358
|
+
kind: "supply",
|
|
135359
|
+
form: "tank"
|
|
135360
|
+
},
|
|
135361
|
+
{
|
|
135362
|
+
key: "dirtyWater",
|
|
135363
|
+
label: "Dirty water tank",
|
|
135364
|
+
kind: "waste",
|
|
135365
|
+
form: "tank"
|
|
135366
|
+
},
|
|
135367
|
+
{
|
|
135368
|
+
key: "detergent",
|
|
135369
|
+
label: "Detergent",
|
|
135370
|
+
kind: "supply",
|
|
135371
|
+
form: "product"
|
|
135372
|
+
},
|
|
135373
|
+
{
|
|
135374
|
+
key: "dustBin",
|
|
135375
|
+
label: "Dust bin",
|
|
135376
|
+
kind: "waste",
|
|
135377
|
+
form: "bin"
|
|
135378
|
+
}
|
|
135379
|
+
];
|
|
135380
|
+
/**
|
|
135381
|
+
* The tanks as `consumables` items (D915): every PRESENT tank becomes a
|
|
135382
|
+
* `supply` (clean water, detergent) or `waste` (dirty water, dust bin) item
|
|
135383
|
+
* keyed by its old field name, drawn as a `tank` (the two water tanks), a
|
|
135384
|
+
* `product` (detergent) or a `bin` (the dust bin) — the key the notification centre's tank
|
|
135385
|
+
* episodes were built on, so an open episode carries on. A tank is never
|
|
135386
|
+
* resettable: emptying or refilling it is the reset. Pure.
|
|
135387
|
+
*/
|
|
135388
|
+
function vacuumTankItems(tanks) {
|
|
135389
|
+
return TANK_ITEMS.flatMap(({ key, label, kind, form }) => {
|
|
135390
|
+
const tank = tanks[key];
|
|
135391
|
+
if (tank === null) return [];
|
|
135392
|
+
return [{
|
|
135393
|
+
key,
|
|
135394
|
+
label,
|
|
135395
|
+
level: tank.level,
|
|
135396
|
+
status: tank.status,
|
|
135397
|
+
kind,
|
|
135398
|
+
form,
|
|
135399
|
+
lastResetAt: null,
|
|
135400
|
+
resettable: false
|
|
135401
|
+
}];
|
|
135402
|
+
});
|
|
135403
|
+
}
|
|
135280
135404
|
/**
|
|
135281
135405
|
* Clamp a raw consumable percentage to `[0, 100]`, or return `null` when the
|
|
135282
135406
|
* value is absent / non-finite. The library reports remaining life as a 0..100
|
|
@@ -135305,7 +135429,8 @@ function buildVacuumConsumableItems(readings) {
|
|
|
135305
135429
|
level: clampConsumablePct(c.leftPct),
|
|
135306
135430
|
status: null,
|
|
135307
135431
|
lastResetAt: null,
|
|
135308
|
-
resettable: c.resettable
|
|
135432
|
+
resettable: c.resettable,
|
|
135433
|
+
form: "part"
|
|
135309
135434
|
}));
|
|
135310
135435
|
}
|
|
135311
135436
|
/** Structural equality of two JSON-shaped values, key order ignored. */
|
|
@@ -182690,7 +182815,8 @@ function buildMowerConsumables(readings) {
|
|
|
182690
182815
|
level: r.remainingPercent,
|
|
182691
182816
|
status: null,
|
|
182692
182817
|
lastResetAt: null,
|
|
182693
|
-
resettable: true
|
|
182818
|
+
resettable: true,
|
|
182819
|
+
form: "part"
|
|
182694
182820
|
}));
|
|
182695
182821
|
}
|
|
182696
182822
|
//#endregion
|
|
@@ -182714,7 +182840,7 @@ var CONSUMABLES_COLD_START = {
|
|
|
182714
182840
|
lastFetchedAt: 0
|
|
182715
182841
|
};
|
|
182716
182842
|
function itemEqual(a, b) {
|
|
182717
|
-
return a.key === b.key && a.label === b.label && a.level === b.level && a.status === b.status && a.lastResetAt === b.lastResetAt && a.resettable === b.resettable;
|
|
182843
|
+
return a.key === b.key && a.label === b.label && a.level === b.level && a.status === b.status && a.lastResetAt === b.lastResetAt && a.resettable === b.resettable && a.kind === b.kind && a.remaining?.value === b.remaining?.value && a.remaining?.unit === b.remaining?.unit;
|
|
182718
182844
|
}
|
|
182719
182845
|
function itemsEqual(a, b) {
|
|
182720
182846
|
return a.length === b.length && a.every((item, i) => {
|
|
@@ -183704,6 +183830,31 @@ var DreameSwitchDevice = class extends DreameChildDevice {
|
|
|
183704
183830
|
};
|
|
183705
183831
|
//#endregion
|
|
183706
183832
|
//#region src/devices/dreame-vacuum-consumables.ts
|
|
183833
|
+
/**
|
|
183834
|
+
* The vacuum's `consumables` slice: when it is re-read, and what a reset does.
|
|
183835
|
+
*
|
|
183836
|
+
* The life %s and their time-left twins are settings the robot rarely re-pushes
|
|
183837
|
+
* over MQTT, and the library does not poll them. So they are re-read from the
|
|
183838
|
+
* cloud SHADOW (no robot wake) on activate, every {@link CONSUMABLES_REFRESH_MS},
|
|
183839
|
+
* and on the edge INTO `docked` — the moment a run has just used them up. The
|
|
183840
|
+
* same read reseeds the station tank-status props (dirty water, dust bag, …),
|
|
183841
|
+
* which otherwise arrive only as pushes.
|
|
183842
|
+
*
|
|
183843
|
+
* A reset goes through the library, which re-reads the item it reset (live,
|
|
183844
|
+
* else shadow) before it resolves; the slice is rebuilt from that. A shadow
|
|
183845
|
+
* answer may still be the pre-reset value, so it earns ONE follow-up refresh.
|
|
183846
|
+
*
|
|
183847
|
+
* The TANKS ride the same slice (D915): every push hands over the tank items
|
|
183848
|
+
* the device decoded, appended after the wear items. Either half may be
|
|
183849
|
+
* unknown for a while after a restart — the shadow has not answered, or a
|
|
183850
|
+
* refresh lands before the first push brought the tanks — and the slice is
|
|
183851
|
+
* `restored`, so an unknown half keeps the restored rows instead of erasing
|
|
183852
|
+
* them.
|
|
183853
|
+
*/
|
|
183854
|
+
/** A tank item (`supply` / `waste`) as opposed to a wear item. */
|
|
183855
|
+
function isTankItem(item) {
|
|
183856
|
+
return consumableKindOf(item) !== "wear";
|
|
183857
|
+
}
|
|
183707
183858
|
/** Hourly: a consumable moves by hours of cleaning, and the dock edge covers a run. */
|
|
183708
183859
|
var CONSUMABLES_REFRESH_MS = 60 * 6e4;
|
|
183709
183860
|
/** Time for the robot to report a reset to the cloud before the shadow is re-read. */
|
|
@@ -183720,6 +183871,8 @@ var DreameVacuumConsumables = class {
|
|
|
183720
183871
|
#refresher;
|
|
183721
183872
|
/** Last pushed lifecycle state; `null` until the first push after boot. */
|
|
183722
183873
|
#prevState = null;
|
|
183874
|
+
/** Last pushed tank items; `null` until the first push after boot. */
|
|
183875
|
+
#tanks = null;
|
|
183723
183876
|
constructor(deps) {
|
|
183724
183877
|
this.#deps = deps;
|
|
183725
183878
|
this.#refresher = new DreameConsumablesRefresher({
|
|
@@ -183739,12 +183892,14 @@ var DreameVacuumConsumables = class {
|
|
|
183739
183892
|
this.#refresher.stop();
|
|
183740
183893
|
}
|
|
183741
183894
|
/**
|
|
183742
|
-
* Every `stateChanged` push: replay the cache
|
|
183743
|
-
* an item changed) and refresh on the edge into
|
|
183744
|
-
* boot is not an edge — activation already
|
|
183745
|
-
* between station routines (`drying` →
|
|
183895
|
+
* Every `stateChanged` push: replay the cache and the pushed tanks into the
|
|
183896
|
+
* slice (written only if an item changed) and refresh on the edge into
|
|
183897
|
+
* `docked`. The first push after boot is not an edge — activation already
|
|
183898
|
+
* reads — and neither is a hop between station routines (`drying` →
|
|
183899
|
+
* `docked`): only the end of a RUN is.
|
|
183746
183900
|
*/
|
|
183747
|
-
onPush(state) {
|
|
183901
|
+
onPush(state, tanks) {
|
|
183902
|
+
this.#tanks = tanks;
|
|
183748
183903
|
this.#apply(false);
|
|
183749
183904
|
const enteredDock = this.#prevState !== null && DOCK_EDGE_FROM.has(this.#prevState) && state === "docked";
|
|
183750
183905
|
this.#prevState = state;
|
|
@@ -183794,7 +183949,11 @@ var DreameVacuumConsumables = class {
|
|
|
183794
183949
|
const { store, resolveVacuum, now } = this.#deps;
|
|
183795
183950
|
const vacuum = resolveVacuum();
|
|
183796
183951
|
if (vacuum === null) return;
|
|
183797
|
-
|
|
183952
|
+
const prev = store.getCapState("consumables")?.items ?? [];
|
|
183953
|
+
const read = buildVacuumConsumableItems(vacuum.supportedConsumables);
|
|
183954
|
+
const wear = read.length > 0 ? read : prev.filter((item) => !isTankItem(item));
|
|
183955
|
+
const tanks = this.#tanks ?? prev.filter(isTankItem);
|
|
183956
|
+
writeConsumables(store, [...wear, ...tanks], (now ?? Date.now)(), landed);
|
|
183798
183957
|
}
|
|
183799
183958
|
};
|
|
183800
183959
|
function resetMeta(result) {
|
|
@@ -183814,10 +183973,6 @@ var CONTROL_COLD_START = {
|
|
|
183814
183973
|
batteryLevel: null,
|
|
183815
183974
|
fanSpeed: null,
|
|
183816
183975
|
availableFanSpeeds: [],
|
|
183817
|
-
cleanWater: null,
|
|
183818
|
-
dirtyWater: null,
|
|
183819
|
-
detergent: null,
|
|
183820
|
-
dustBin: null,
|
|
183821
183976
|
progressPercent: null,
|
|
183822
183977
|
errorCode: null,
|
|
183823
183978
|
errorLabel: null,
|
|
@@ -183833,11 +183988,13 @@ var CONTROL_COLD_START = {
|
|
|
183833
183988
|
* `setFanSpeed`→`setSuction()` (token validated against the model's supported
|
|
183834
183989
|
* suction levels).
|
|
183835
183990
|
*
|
|
183836
|
-
*
|
|
183837
|
-
*
|
|
183838
|
-
*
|
|
183839
|
-
*
|
|
183840
|
-
*
|
|
183991
|
+
* Tanks (clean water / dirty water / detergent / dust bin) are `supply` /
|
|
183992
|
+
* `waste` items of the `consumables` slice (D915), not `vacuum-control` fields:
|
|
183993
|
+
* the library exposes NO tank fill LEVEL, so `level` is always null. PRESENCE
|
|
183994
|
+
* comes from the model capability flags and a discrete `status` from the
|
|
183995
|
+
* station's tank-status enum props (`decodeVacuumTanks`, ids in
|
|
183996
|
+
* `VACUUM_TANK_PROPS`); an absent tank is no item, an unknown status is `null`
|
|
183997
|
+
* — never `ok`.
|
|
183841
183998
|
*
|
|
183842
183999
|
* Consumables: whatever the model REPORTS (the library's presence-driven
|
|
183843
184000
|
* `supportedConsumables`), re-read from the cloud shadow on activate, hourly and
|
|
@@ -183961,16 +184118,12 @@ var DreameVacuumDevice = class extends DreameChildDevice {
|
|
|
183961
184118
|
recomputeSlice() {
|
|
183962
184119
|
const vacuum = this.resolveVacuum();
|
|
183963
184120
|
if (vacuum === null) return;
|
|
183964
|
-
const tanks = decodeVacuumTanks(vacuum.vacuumCapabilities, this.readTankProps(), vacuum.errorCode);
|
|
184121
|
+
const tanks = vacuumTankItems(decodeVacuumTanks(vacuum.vacuumCapabilities, this.readTankProps(), vacuum.errorCode));
|
|
183965
184122
|
const controlSlice = {
|
|
183966
184123
|
state: mapMiotStateToVacuumState(vacuum.status),
|
|
183967
184124
|
batteryLevel: clampBatteryLevel$1(vacuum.battery),
|
|
183968
184125
|
fanSpeed: suctionLevelToken(vacuum.suction),
|
|
183969
184126
|
availableFanSpeeds: supportedFanSpeedTokens(vacuum.supportedSuctionLevels),
|
|
183970
|
-
cleanWater: tanks.cleanWater,
|
|
183971
|
-
dirtyWater: tanks.dirtyWater,
|
|
183972
|
-
detergent: tanks.detergent,
|
|
183973
|
-
dustBin: tanks.dustBin,
|
|
183974
184127
|
progressPercent: clampPercent$1(vacuum.taskProgressPct),
|
|
183975
184128
|
errorCode: vacuum.errorCode,
|
|
183976
184129
|
errorLabel: vacuum.errorCode ? `Error ${vacuum.errorCode}` : null,
|
|
@@ -183978,7 +184131,7 @@ var DreameVacuumDevice = class extends DreameChildDevice {
|
|
|
183978
184131
|
};
|
|
183979
184132
|
const toWrite = nextVacuumControlSlice(this.runtimeState.getCapState(CAP_NAME$1), controlSlice);
|
|
183980
184133
|
if (toWrite !== null) this.runtimeState.setCapState(CAP_NAME$1, toWrite);
|
|
183981
|
-
this.consumables.onPush(controlSlice.state);
|
|
184134
|
+
this.consumables.onPush(controlSlice.state, tanks);
|
|
183982
184135
|
}
|
|
183983
184136
|
/**
|
|
183984
184137
|
* Read the tank-status MIoT enum props ({@link VACUUM_TANK_PROPS}) from the
|