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