@apocaliss92/nodedreame 1.6.1 → 1.7.1

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/index.d.cts CHANGED
@@ -755,6 +755,52 @@ declare function decodeAiFeature(raw: AiDetectionRaw, feature: DreameAiFeature):
755
755
  */
756
756
  declare function encodeAiFeatureWrite(raw: AiDetectionRaw, feature: DreameAiFeature, value: boolean): number | string;
757
757
 
758
+ /**
759
+ * Vacuum consumable/maintenance map (ported from Tasshack `dreame-vacuum`
760
+ * v2.0.0b25 — property + action mappings). Each consumable lives on its own MIoT
761
+ * service `siid`: a remaining-life `%` property (`siid/piid`) and a "reset to
762
+ * 100%" action (`siid/aiid 1`). A model exposes only a SUBSET — which is
763
+ * discovered by PRESENCE (the device reports the life property) rather than a
764
+ * hardcoded per-model list, mirroring how the HA integration derives support.
765
+ */
766
+ /** Stable consumable keys (kebab-case so a consumer can use them verbatim). */
767
+ type DreameConsumableKey = 'main-brush' | 'side-brush' | 'filter' | 'sensor' | 'tank-filter' | 'mop-pad' | 'silver-ion' | 'detergent' | 'squeegee' | 'dust-bag';
768
+ /** One consumable's wire coordinates: remaining-life property + optional reset action. */
769
+ interface ConsumableSpec {
770
+ readonly key: DreameConsumableKey;
771
+ readonly label: string;
772
+ /** Remaining-life % property (0..100). */
773
+ readonly life: {
774
+ readonly siid: number;
775
+ readonly piid: number;
776
+ };
777
+ /** "Mark replaced / reset life" action, or null when the model exposes none. */
778
+ readonly reset: {
779
+ readonly siid: number;
780
+ readonly aiid: number;
781
+ } | null;
782
+ }
783
+ /**
784
+ * Every consumable nodedreame knows. The reset action shares the consumable's
785
+ * service `siid` with `aiid 1` (Tasshack action map). `dust-bag` has a life
786
+ * property but no reset action.
787
+ */
788
+ declare const VACUUM_CONSUMABLES: readonly ConsumableSpec[];
789
+ /** Lookup a consumable spec by key (undefined for an unknown key). */
790
+ declare function consumableSpec(key: DreameConsumableKey): ConsumableSpec | undefined;
791
+ /** Narrow an arbitrary string to a known {@link DreameConsumableKey} — lets a
792
+ * string-keyed consumer (e.g. a generic consumables cap) validate before
793
+ * calling the typed reset path with no cast. */
794
+ declare function isDreameConsumableKey(key: string): key is DreameConsumableKey;
795
+ /** A resolved consumable reading: which consumable, its remaining life %, and
796
+ * whether a reset action exists. Only the consumables the model REPORTS appear. */
797
+ interface ConsumableReading {
798
+ readonly key: DreameConsumableKey;
799
+ readonly label: string;
800
+ readonly leftPct: number;
801
+ readonly resettable: boolean;
802
+ }
803
+
758
804
  /**
759
805
  * Per-model vacuum capability records (ported from malard/node-dreame
760
806
  * src/capabilities.ts, MIT — attribution retained) plus a resolver that
@@ -1266,6 +1312,33 @@ declare class VacuumDevice extends BaseDevice<VacuumDeviceEvents> {
1266
1312
  get sideBrushLeftPct(): number | null;
1267
1313
  get filterLeftPct(): number | null;
1268
1314
  get volume(): number | null;
1315
+ /**
1316
+ * Remaining-life % (0..100) for one consumable, or `null` when the model does
1317
+ * not report it (presence == support). Call {@link refreshConsumables} first
1318
+ * on a docked robot so the cloud-shadow life values are seeded.
1319
+ */
1320
+ consumableLeftPct(key: DreameConsumableKey): number | null;
1321
+ /**
1322
+ * The consumables this model EXPOSES — discovered by presence (a reported
1323
+ * life property), mirroring how the HA integration derives support. Each
1324
+ * reading carries the current remaining-life % and whether a reset action
1325
+ * exists. Empty until the life properties have been observed (push) or seeded
1326
+ * via {@link refreshConsumables}.
1327
+ */
1328
+ get supportedConsumables(): readonly ConsumableReading[];
1329
+ /**
1330
+ * Seed EVERY consumable life property from the cloud shadow (no robot wake) so
1331
+ * {@link supportedConsumables} reflects the full set on a docked robot. The
1332
+ * consumable life values are static settings the robot rarely re-pushes over
1333
+ * MQTT, so a fresh connect surfaces only the actively-changing ones without this.
1334
+ */
1335
+ refreshConsumables(): Promise<void>;
1336
+ /**
1337
+ * Reset (mark replaced → life back to 100%) one consumable via its MIoT reset
1338
+ * action. Rejects when the model exposes no reset action for the key (e.g.
1339
+ * `dust-bag`) or the key is unknown.
1340
+ */
1341
+ resetConsumable(key: DreameConsumableKey): Promise<unknown>;
1269
1342
  /**
1270
1343
  * The raw `AI_DETECTION` value (siid 4 piid 22) — an int bitmask or a JSON
1271
1344
  * string, depending on firmware — or `null` when not yet observed. Prefer the
@@ -2245,4 +2318,4 @@ declare function createDumper(target: DumperDevice, options?: DumperOptions): Du
2245
2318
  */
2246
2319
  declare function createClientDumper(client: Nodreame, options?: DumperOptions): Dumper[];
2247
2320
 
2248
- export { AI_FEATURE_BIT, AI_FEATURE_JSON_KEY, type AiDetectionRaw, BaseDevice, type BaseDeviceEvents, type BatchDeviceDataFetcher, type CapabilityResolver, ChargingStatus, type CleanOpts, CleaningMode, type CreateDeviceArgs, DefaultCapabilityResolver, type DeviceCapabilities, type DeviceDump, type DeviceEvent, type DreameAiFeature, DreameApiError, DreameAuthError, type DreameCloudState, type DreameDevice, DreameDeviceOfflineError, DreameError, type DreameRegion, type DreameSession, DreameTransportError, type DumperOptions, LIBRARY_NAME, MODEL_CAPABILITIES as MOWER_MODEL_CAPABILITIES, type MapBoundingBox, type MapCleanedAreaOverlay, type MapDimensions, type MapFrameType, type MapLayer, type MapLayerType, type MapLowLyingArea, type MapObstacle, type MapPath, type MapPathType, type MapPoint, type MapPose, type MapRestrictedArea, type MapRoom, type MapRoomWall, type MapRun, type MapSegment, type MapStorey, type MapVirtualWall, type MapWallsInfo, type MiotAction, MiotError, type MiotProp, MiotState, type MowerAvailableMap, type MowerCapabilities, MowerCapabilityResolver, MowerChargingStatus, type MowerContour, MowerControlAction, type MowerControlState, MowerDevice, type MowerDeviceInput, MowerFault, type MowerMap, type MowerMapBoundary, type MowerMowPath, type MowerPathEntry, type MowerPoint, type MowerSpotArea, MowerStatus, type MowerTaskDescriptor, MowerTaskStatus, type MowerZone, Nodreame, type NodreameDeps, type NodreameEvents, type NodreameOptions, type OssFetchInput, type OssFetcherLike, type PropertyChangedEvent, type PropertyResult, type PropertyState, type PropertyWrite, type RenderMowerSvgOptions, type RenderVacuumPngOptions, type StateChangedEvent, SuctionLevel, TaskStatus, MODEL_CAPABILITIES$1 as VACUUM_MODEL_CAPABILITIES, type VacuumCapabilities, VacuumCapabilityResolver, VacuumDevice, type VacuumGetMapInput, type VacuumMap, WaterVolume, createClientDumper, createDumper, decodeAiFeature, encodeAiFeatureWrite, getMowerCapabilities, getVacuumCapabilities, renderMowerSvg, renderVacuumPng, resolveCapabilities };
2321
+ export { AI_FEATURE_BIT, AI_FEATURE_JSON_KEY, type AiDetectionRaw, BaseDevice, type BaseDeviceEvents, type BatchDeviceDataFetcher, type CapabilityResolver, ChargingStatus, type CleanOpts, CleaningMode, type ConsumableReading, type ConsumableSpec, type CreateDeviceArgs, DefaultCapabilityResolver, type DeviceCapabilities, type DeviceDump, type DeviceEvent, type DreameAiFeature, DreameApiError, DreameAuthError, type DreameCloudState, type DreameConsumableKey, type DreameDevice, DreameDeviceOfflineError, DreameError, type DreameRegion, type DreameSession, DreameTransportError, type DumperOptions, LIBRARY_NAME, MODEL_CAPABILITIES as MOWER_MODEL_CAPABILITIES, type MapBoundingBox, type MapCleanedAreaOverlay, type MapDimensions, type MapFrameType, type MapLayer, type MapLayerType, type MapLowLyingArea, type MapObstacle, type MapPath, type MapPathType, type MapPoint, type MapPose, type MapRestrictedArea, type MapRoom, type MapRoomWall, type MapRun, type MapSegment, type MapStorey, type MapVirtualWall, type MapWallsInfo, type MiotAction, MiotError, type MiotProp, MiotState, type MowerAvailableMap, type MowerCapabilities, MowerCapabilityResolver, MowerChargingStatus, type MowerContour, MowerControlAction, type MowerControlState, MowerDevice, type MowerDeviceInput, MowerFault, type MowerMap, type MowerMapBoundary, type MowerMowPath, type MowerPathEntry, type MowerPoint, type MowerSpotArea, MowerStatus, type MowerTaskDescriptor, MowerTaskStatus, type MowerZone, Nodreame, type NodreameDeps, type NodreameEvents, type NodreameOptions, type OssFetchInput, type OssFetcherLike, type PropertyChangedEvent, type PropertyResult, type PropertyState, type PropertyWrite, type RenderMowerSvgOptions, type RenderVacuumPngOptions, type StateChangedEvent, SuctionLevel, TaskStatus, VACUUM_CONSUMABLES, MODEL_CAPABILITIES$1 as VACUUM_MODEL_CAPABILITIES, type VacuumCapabilities, VacuumCapabilityResolver, VacuumDevice, type VacuumGetMapInput, type VacuumMap, WaterVolume, consumableSpec, createClientDumper, createDumper, decodeAiFeature, encodeAiFeatureWrite, getMowerCapabilities, getVacuumCapabilities, isDreameConsumableKey, renderMowerSvg, renderVacuumPng, resolveCapabilities };
package/dist/index.d.ts CHANGED
@@ -755,6 +755,52 @@ declare function decodeAiFeature(raw: AiDetectionRaw, feature: DreameAiFeature):
755
755
  */
756
756
  declare function encodeAiFeatureWrite(raw: AiDetectionRaw, feature: DreameAiFeature, value: boolean): number | string;
757
757
 
758
+ /**
759
+ * Vacuum consumable/maintenance map (ported from Tasshack `dreame-vacuum`
760
+ * v2.0.0b25 — property + action mappings). Each consumable lives on its own MIoT
761
+ * service `siid`: a remaining-life `%` property (`siid/piid`) and a "reset to
762
+ * 100%" action (`siid/aiid 1`). A model exposes only a SUBSET — which is
763
+ * discovered by PRESENCE (the device reports the life property) rather than a
764
+ * hardcoded per-model list, mirroring how the HA integration derives support.
765
+ */
766
+ /** Stable consumable keys (kebab-case so a consumer can use them verbatim). */
767
+ type DreameConsumableKey = 'main-brush' | 'side-brush' | 'filter' | 'sensor' | 'tank-filter' | 'mop-pad' | 'silver-ion' | 'detergent' | 'squeegee' | 'dust-bag';
768
+ /** One consumable's wire coordinates: remaining-life property + optional reset action. */
769
+ interface ConsumableSpec {
770
+ readonly key: DreameConsumableKey;
771
+ readonly label: string;
772
+ /** Remaining-life % property (0..100). */
773
+ readonly life: {
774
+ readonly siid: number;
775
+ readonly piid: number;
776
+ };
777
+ /** "Mark replaced / reset life" action, or null when the model exposes none. */
778
+ readonly reset: {
779
+ readonly siid: number;
780
+ readonly aiid: number;
781
+ } | null;
782
+ }
783
+ /**
784
+ * Every consumable nodedreame knows. The reset action shares the consumable's
785
+ * service `siid` with `aiid 1` (Tasshack action map). `dust-bag` has a life
786
+ * property but no reset action.
787
+ */
788
+ declare const VACUUM_CONSUMABLES: readonly ConsumableSpec[];
789
+ /** Lookup a consumable spec by key (undefined for an unknown key). */
790
+ declare function consumableSpec(key: DreameConsumableKey): ConsumableSpec | undefined;
791
+ /** Narrow an arbitrary string to a known {@link DreameConsumableKey} — lets a
792
+ * string-keyed consumer (e.g. a generic consumables cap) validate before
793
+ * calling the typed reset path with no cast. */
794
+ declare function isDreameConsumableKey(key: string): key is DreameConsumableKey;
795
+ /** A resolved consumable reading: which consumable, its remaining life %, and
796
+ * whether a reset action exists. Only the consumables the model REPORTS appear. */
797
+ interface ConsumableReading {
798
+ readonly key: DreameConsumableKey;
799
+ readonly label: string;
800
+ readonly leftPct: number;
801
+ readonly resettable: boolean;
802
+ }
803
+
758
804
  /**
759
805
  * Per-model vacuum capability records (ported from malard/node-dreame
760
806
  * src/capabilities.ts, MIT — attribution retained) plus a resolver that
@@ -1266,6 +1312,33 @@ declare class VacuumDevice extends BaseDevice<VacuumDeviceEvents> {
1266
1312
  get sideBrushLeftPct(): number | null;
1267
1313
  get filterLeftPct(): number | null;
1268
1314
  get volume(): number | null;
1315
+ /**
1316
+ * Remaining-life % (0..100) for one consumable, or `null` when the model does
1317
+ * not report it (presence == support). Call {@link refreshConsumables} first
1318
+ * on a docked robot so the cloud-shadow life values are seeded.
1319
+ */
1320
+ consumableLeftPct(key: DreameConsumableKey): number | null;
1321
+ /**
1322
+ * The consumables this model EXPOSES — discovered by presence (a reported
1323
+ * life property), mirroring how the HA integration derives support. Each
1324
+ * reading carries the current remaining-life % and whether a reset action
1325
+ * exists. Empty until the life properties have been observed (push) or seeded
1326
+ * via {@link refreshConsumables}.
1327
+ */
1328
+ get supportedConsumables(): readonly ConsumableReading[];
1329
+ /**
1330
+ * Seed EVERY consumable life property from the cloud shadow (no robot wake) so
1331
+ * {@link supportedConsumables} reflects the full set on a docked robot. The
1332
+ * consumable life values are static settings the robot rarely re-pushes over
1333
+ * MQTT, so a fresh connect surfaces only the actively-changing ones without this.
1334
+ */
1335
+ refreshConsumables(): Promise<void>;
1336
+ /**
1337
+ * Reset (mark replaced → life back to 100%) one consumable via its MIoT reset
1338
+ * action. Rejects when the model exposes no reset action for the key (e.g.
1339
+ * `dust-bag`) or the key is unknown.
1340
+ */
1341
+ resetConsumable(key: DreameConsumableKey): Promise<unknown>;
1269
1342
  /**
1270
1343
  * The raw `AI_DETECTION` value (siid 4 piid 22) — an int bitmask or a JSON
1271
1344
  * string, depending on firmware — or `null` when not yet observed. Prefer the
@@ -2245,4 +2318,4 @@ declare function createDumper(target: DumperDevice, options?: DumperOptions): Du
2245
2318
  */
2246
2319
  declare function createClientDumper(client: Nodreame, options?: DumperOptions): Dumper[];
2247
2320
 
2248
- export { AI_FEATURE_BIT, AI_FEATURE_JSON_KEY, type AiDetectionRaw, BaseDevice, type BaseDeviceEvents, type BatchDeviceDataFetcher, type CapabilityResolver, ChargingStatus, type CleanOpts, CleaningMode, type CreateDeviceArgs, DefaultCapabilityResolver, type DeviceCapabilities, type DeviceDump, type DeviceEvent, type DreameAiFeature, DreameApiError, DreameAuthError, type DreameCloudState, type DreameDevice, DreameDeviceOfflineError, DreameError, type DreameRegion, type DreameSession, DreameTransportError, type DumperOptions, LIBRARY_NAME, MODEL_CAPABILITIES as MOWER_MODEL_CAPABILITIES, type MapBoundingBox, type MapCleanedAreaOverlay, type MapDimensions, type MapFrameType, type MapLayer, type MapLayerType, type MapLowLyingArea, type MapObstacle, type MapPath, type MapPathType, type MapPoint, type MapPose, type MapRestrictedArea, type MapRoom, type MapRoomWall, type MapRun, type MapSegment, type MapStorey, type MapVirtualWall, type MapWallsInfo, type MiotAction, MiotError, type MiotProp, MiotState, type MowerAvailableMap, type MowerCapabilities, MowerCapabilityResolver, MowerChargingStatus, type MowerContour, MowerControlAction, type MowerControlState, MowerDevice, type MowerDeviceInput, MowerFault, type MowerMap, type MowerMapBoundary, type MowerMowPath, type MowerPathEntry, type MowerPoint, type MowerSpotArea, MowerStatus, type MowerTaskDescriptor, MowerTaskStatus, type MowerZone, Nodreame, type NodreameDeps, type NodreameEvents, type NodreameOptions, type OssFetchInput, type OssFetcherLike, type PropertyChangedEvent, type PropertyResult, type PropertyState, type PropertyWrite, type RenderMowerSvgOptions, type RenderVacuumPngOptions, type StateChangedEvent, SuctionLevel, TaskStatus, MODEL_CAPABILITIES$1 as VACUUM_MODEL_CAPABILITIES, type VacuumCapabilities, VacuumCapabilityResolver, VacuumDevice, type VacuumGetMapInput, type VacuumMap, WaterVolume, createClientDumper, createDumper, decodeAiFeature, encodeAiFeatureWrite, getMowerCapabilities, getVacuumCapabilities, renderMowerSvg, renderVacuumPng, resolveCapabilities };
2321
+ export { AI_FEATURE_BIT, AI_FEATURE_JSON_KEY, type AiDetectionRaw, BaseDevice, type BaseDeviceEvents, type BatchDeviceDataFetcher, type CapabilityResolver, ChargingStatus, type CleanOpts, CleaningMode, type ConsumableReading, type ConsumableSpec, type CreateDeviceArgs, DefaultCapabilityResolver, type DeviceCapabilities, type DeviceDump, type DeviceEvent, type DreameAiFeature, DreameApiError, DreameAuthError, type DreameCloudState, type DreameConsumableKey, type DreameDevice, DreameDeviceOfflineError, DreameError, type DreameRegion, type DreameSession, DreameTransportError, type DumperOptions, LIBRARY_NAME, MODEL_CAPABILITIES as MOWER_MODEL_CAPABILITIES, type MapBoundingBox, type MapCleanedAreaOverlay, type MapDimensions, type MapFrameType, type MapLayer, type MapLayerType, type MapLowLyingArea, type MapObstacle, type MapPath, type MapPathType, type MapPoint, type MapPose, type MapRestrictedArea, type MapRoom, type MapRoomWall, type MapRun, type MapSegment, type MapStorey, type MapVirtualWall, type MapWallsInfo, type MiotAction, MiotError, type MiotProp, MiotState, type MowerAvailableMap, type MowerCapabilities, MowerCapabilityResolver, MowerChargingStatus, type MowerContour, MowerControlAction, type MowerControlState, MowerDevice, type MowerDeviceInput, MowerFault, type MowerMap, type MowerMapBoundary, type MowerMowPath, type MowerPathEntry, type MowerPoint, type MowerSpotArea, MowerStatus, type MowerTaskDescriptor, MowerTaskStatus, type MowerZone, Nodreame, type NodreameDeps, type NodreameEvents, type NodreameOptions, type OssFetchInput, type OssFetcherLike, type PropertyChangedEvent, type PropertyResult, type PropertyState, type PropertyWrite, type RenderMowerSvgOptions, type RenderVacuumPngOptions, type StateChangedEvent, SuctionLevel, TaskStatus, VACUUM_CONSUMABLES, MODEL_CAPABILITIES$1 as VACUUM_MODEL_CAPABILITIES, type VacuumCapabilities, VacuumCapabilityResolver, VacuumDevice, type VacuumGetMapInput, type VacuumMap, WaterVolume, consumableSpec, createClientDumper, createDumper, decodeAiFeature, encodeAiFeatureWrite, getMowerCapabilities, getVacuumCapabilities, isDreameConsumableKey, renderMowerSvg, renderVacuumPng, resolveCapabilities };
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // src/support/version.ts
2
2
  var LIBRARY_NAME = "nodedreame";
3
- var LIBRARY_VERSION = "1.6.1";
3
+ var LIBRARY_VERSION = "1.7.1";
4
4
 
5
5
  // src/transport/errors.ts
6
6
  var DreameError = class extends Error {
@@ -1570,6 +1570,26 @@ function encodeAiFeatureWrite(raw, feature, value) {
1570
1570
  );
1571
1571
  }
1572
1572
 
1573
+ // src/models/vacuum/consumables.ts
1574
+ var VACUUM_CONSUMABLES = [
1575
+ { key: "main-brush", label: "Main Brush", life: { siid: 9, piid: 2 }, reset: { siid: 9, aiid: 1 } },
1576
+ { key: "side-brush", label: "Side Brush", life: { siid: 10, piid: 2 }, reset: { siid: 10, aiid: 1 } },
1577
+ { key: "filter", label: "Filter", life: { siid: 11, piid: 1 }, reset: { siid: 11, aiid: 1 } },
1578
+ { key: "sensor", label: "Sensor", life: { siid: 16, piid: 1 }, reset: { siid: 16, aiid: 1 } },
1579
+ { key: "tank-filter", label: "Tank Filter", life: { siid: 17, piid: 1 }, reset: { siid: 17, aiid: 1 } },
1580
+ { key: "mop-pad", label: "Mop Pad", life: { siid: 18, piid: 1 }, reset: { siid: 18, aiid: 1 } },
1581
+ { key: "silver-ion", label: "Silver-ion", life: { siid: 19, piid: 2 }, reset: { siid: 19, aiid: 1 } },
1582
+ { key: "detergent", label: "Detergent", life: { siid: 20, piid: 1 }, reset: { siid: 20, aiid: 1 } },
1583
+ { key: "squeegee", label: "Squeegee", life: { siid: 24, piid: 1 }, reset: { siid: 24, aiid: 1 } },
1584
+ { key: "dust-bag", label: "Dust Bag", life: { siid: 27, piid: 17 }, reset: null }
1585
+ ];
1586
+ function consumableSpec(key2) {
1587
+ return VACUUM_CONSUMABLES.find((c) => c.key === key2);
1588
+ }
1589
+ function isDreameConsumableKey(key2) {
1590
+ return VACUUM_CONSUMABLES.some((c) => c.key === key2);
1591
+ }
1592
+
1573
1593
  // src/models/vacuum/capabilities.ts
1574
1594
  var X50_AI_FEATURES = [
1575
1595
  "obstacleDetection",
@@ -2771,6 +2791,51 @@ var VacuumDevice = class _VacuumDevice extends BaseDevice {
2771
2791
  get volume() {
2772
2792
  return this.#num(SETTINGS_PROP.VOLUME.siid, SETTINGS_PROP.VOLUME.piid);
2773
2793
  }
2794
+ // -- consumables --------------------------------------------------------
2795
+ /**
2796
+ * Remaining-life % (0..100) for one consumable, or `null` when the model does
2797
+ * not report it (presence == support). Call {@link refreshConsumables} first
2798
+ * on a docked robot so the cloud-shadow life values are seeded.
2799
+ */
2800
+ consumableLeftPct(key2) {
2801
+ const spec = consumableSpec(key2);
2802
+ if (spec === void 0) return null;
2803
+ return this.#num(spec.life.siid, spec.life.piid);
2804
+ }
2805
+ /**
2806
+ * The consumables this model EXPOSES — discovered by presence (a reported
2807
+ * life property), mirroring how the HA integration derives support. Each
2808
+ * reading carries the current remaining-life % and whether a reset action
2809
+ * exists. Empty until the life properties have been observed (push) or seeded
2810
+ * via {@link refreshConsumables}.
2811
+ */
2812
+ get supportedConsumables() {
2813
+ return VACUUM_CONSUMABLES.flatMap((spec) => {
2814
+ const leftPct = this.#num(spec.life.siid, spec.life.piid);
2815
+ return leftPct === null ? [] : [{ key: spec.key, label: spec.label, leftPct, resettable: spec.reset !== null }];
2816
+ });
2817
+ }
2818
+ /**
2819
+ * Seed EVERY consumable life property from the cloud shadow (no robot wake) so
2820
+ * {@link supportedConsumables} reflects the full set on a docked robot. The
2821
+ * consumable life values are static settings the robot rarely re-pushes over
2822
+ * MQTT, so a fresh connect surfaces only the actively-changing ones without this.
2823
+ */
2824
+ async refreshConsumables() {
2825
+ await this.refreshCachedProperties(VACUUM_CONSUMABLES.map((c) => c.life));
2826
+ }
2827
+ /**
2828
+ * Reset (mark replaced → life back to 100%) one consumable via its MIoT reset
2829
+ * action. Rejects when the model exposes no reset action for the key (e.g.
2830
+ * `dust-bag`) or the key is unknown.
2831
+ */
2832
+ async resetConsumable(key2) {
2833
+ const spec = consumableSpec(key2);
2834
+ if (spec === void 0 || spec.reset === null) {
2835
+ throw new DreameError(`resetConsumable: no reset action for consumable "${key2}"`);
2836
+ }
2837
+ return this.callAction(spec.reset.siid, spec.reset.aiid, []);
2838
+ }
2774
2839
  // -- AI obstacle-detection ----------------------------------------------
2775
2840
  /**
2776
2841
  * The raw `AI_DETECTION` value (siid 4 piid 22) — an int bitmask or a JSON
@@ -4755,16 +4820,19 @@ export {
4755
4820
  Nodreame,
4756
4821
  SuctionLevel,
4757
4822
  TaskStatus,
4823
+ VACUUM_CONSUMABLES,
4758
4824
  MODEL_CAPABILITIES as VACUUM_MODEL_CAPABILITIES,
4759
4825
  VacuumCapabilityResolver,
4760
4826
  VacuumDevice,
4761
4827
  WaterVolume,
4828
+ consumableSpec,
4762
4829
  createClientDumper,
4763
4830
  createDumper,
4764
4831
  decodeAiFeature,
4765
4832
  encodeAiFeatureWrite,
4766
4833
  getMowerCapabilities,
4767
4834
  getVacuumCapabilities,
4835
+ isDreameConsumableKey,
4768
4836
  renderMowerSvg,
4769
4837
  renderVacuumPng,
4770
4838
  resolveCapabilities