@apocaliss92/nodedreame 1.0.0 → 1.2.0

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.js CHANGED
@@ -285,6 +285,16 @@ var PropertyResultSchema = z.object({
285
285
  value: z.unknown().optional(),
286
286
  code: z.number().optional()
287
287
  }).passthrough();
288
+ var CachedPropEntrySchema = z.object({
289
+ key: z.string(),
290
+ value: z.unknown().optional(),
291
+ updateDate: z.number().optional()
292
+ }).passthrough();
293
+ var CachedPropsResponseSchema = z.object({
294
+ code: z.number().optional(),
295
+ msg: z.string().optional(),
296
+ data: z.array(CachedPropEntrySchema).optional()
297
+ }).passthrough();
288
298
  var SendCommandResponseSchema = z.object({
289
299
  code: z.number().optional(),
290
300
  msg: z.string().optional(),
@@ -474,6 +484,57 @@ async function getProperties(base, props, opts = {}) {
474
484
  const res = await sendCommand({ ...base, ...opts, method: "get_properties", params });
475
485
  return extractResultArray(res, "get_properties");
476
486
  }
487
+ async function getCachedProperties(base, props, opts = {}) {
488
+ const ctx = base.ctx ?? RequestContext.from({ ...base, host: base.apiHost });
489
+ const keys = props.map((p) => `${p.siid}.${p.piid}`).join(",");
490
+ const signal = opts.signal ?? base.signal;
491
+ const timeoutMs = opts.timeoutMs ?? base.timeoutMs;
492
+ const raw = await httpPostJsonBody({
493
+ ctx,
494
+ path: "/dreame-user-iot/iotstatus/props",
495
+ accessToken: base.session.accessToken,
496
+ body: { did: base.did, keys },
497
+ context: "cached properties",
498
+ ...signal !== void 0 ? { signal } : {},
499
+ ...timeoutMs !== void 0 ? { timeoutMs } : {}
500
+ });
501
+ const parsed = CachedPropsResponseSchema.parse(raw);
502
+ if (parsed.code !== void 0 && parsed.code !== 0) {
503
+ throw new DreameApiError(
504
+ `cached properties rejected: code=${parsed.code} msg=${parsed.msg ?? "?"}`,
505
+ 200,
506
+ parsed
507
+ );
508
+ }
509
+ return (parsed.data ?? []).flatMap((entry) => {
510
+ const [siidStr, piidStr] = entry.key.split(".");
511
+ const siid = Number(siidStr);
512
+ const piid = Number(piidStr);
513
+ if (!Number.isFinite(siid) || !Number.isFinite(piid)) {
514
+ return [];
515
+ }
516
+ const result = { siid, piid, value: coerceShadowValue(entry.value) };
517
+ if (entry.updateDate !== void 0) {
518
+ result.updateDate = entry.updateDate;
519
+ }
520
+ return [result];
521
+ });
522
+ }
523
+ function coerceShadowValue(value) {
524
+ if (typeof value !== "string") {
525
+ return value;
526
+ }
527
+ if (value === "true") {
528
+ return true;
529
+ }
530
+ if (value === "false") {
531
+ return false;
532
+ }
533
+ if (value.trim() !== "" && Number.isFinite(Number(value))) {
534
+ return Number(value);
535
+ }
536
+ return value;
537
+ }
477
538
  async function setProperties(base, writes, opts = {}) {
478
539
  const params = writes.map((p) => ({
479
540
  did: base.did,
@@ -851,6 +912,7 @@ function defaultBaseDeviceDeps() {
851
912
  return {
852
913
  createPush: (device, session, region) => new DreamePush({ device, session, region }),
853
914
  getProperties: (base, props) => getProperties(base, props),
915
+ getCachedProperties: (base, props) => getCachedProperties(base, props),
854
916
  setProperties: (base, writes) => setProperties(base, writes),
855
917
  callAction: (base, action) => callAction(base, action)
856
918
  };
@@ -939,6 +1001,23 @@ var BaseDevice = class extends TypedEmitter {
939
1001
  async refreshProperties(props) {
940
1002
  this.#assertOpen();
941
1003
  const results = await this.#deps.getProperties(this.#base(), props);
1004
+ this.#seedFromResults(results);
1005
+ return results;
1006
+ }
1007
+ /**
1008
+ * Read the CLOUD-CACHED (shadow) values of `props` WITHOUT waking the device,
1009
+ * update the cache, and emit `propertyChanged`/`stateChanged` just like
1010
+ * {@link refreshProperties} — but sourced from the cloud shadow endpoint, so
1011
+ * it works for standby/offline robots (and never surfaces a false 80001).
1012
+ */
1013
+ async refreshCachedProperties(props) {
1014
+ this.#assertOpen();
1015
+ const results = await this.#deps.getCachedProperties(this.#base(), props);
1016
+ this.#seedFromResults(results);
1017
+ return results;
1018
+ }
1019
+ /** Mirror a PropertyResult[] into the cache + emit the change events. */
1020
+ #seedFromResults(results) {
942
1021
  const changes = [];
943
1022
  for (const r of results) {
944
1023
  if (typeof r.siid === "number" && typeof r.piid === "number") {
@@ -948,7 +1027,6 @@ var BaseDevice = class extends TypedEmitter {
948
1027
  if (changes.length > 0) {
949
1028
  this.#onProperties(changes);
950
1029
  }
951
- return results;
952
1030
  }
953
1031
  /** Write a property to the device. */
954
1032
  async setProperty(write) {
@@ -1148,11 +1226,27 @@ var MiotState = /* @__PURE__ */ ((MiotState2) => {
1148
1226
  MiotState2[MiotState2["ReturnToEmpty"] = 28] = "ReturnToEmpty";
1149
1227
  MiotState2[MiotState2["WaitingForTask"] = 29] = "WaitingForTask";
1150
1228
  MiotState2[MiotState2["CleanWashboardBase"] = 30] = "CleanWashboardBase";
1229
+ MiotState2[MiotState2["ReturningToDrain"] = 31] = "ReturningToDrain";
1230
+ MiotState2[MiotState2["Draining"] = 32] = "Draining";
1151
1231
  MiotState2[MiotState2["AutoWaterDraining"] = 33] = "AutoWaterDraining";
1232
+ MiotState2[MiotState2["Emptying"] = 34] = "Emptying";
1233
+ MiotState2[MiotState2["DustBagDrying"] = 35] = "DustBagDrying";
1234
+ MiotState2[MiotState2["DustBagDryingPaused"] = 36] = "DustBagDryingPaused";
1235
+ MiotState2[MiotState2["HeadingToExtraCleaning"] = 37] = "HeadingToExtraCleaning";
1236
+ MiotState2[MiotState2["ExtraCleaning"] = 38] = "ExtraCleaning";
1237
+ MiotState2[MiotState2["FindingPetPaused"] = 95] = "FindingPetPaused";
1238
+ MiotState2[MiotState2["FindingPet"] = 96] = "FindingPet";
1152
1239
  MiotState2[MiotState2["ShortcutRunning"] = 97] = "ShortcutRunning";
1153
1240
  MiotState2[MiotState2["CameraMonitoring"] = 98] = "CameraMonitoring";
1154
1241
  MiotState2[MiotState2["CameraMonitoringPaused"] = 99] = "CameraMonitoringPaused";
1155
1242
  MiotState2[MiotState2["InitialDeepClean"] = 101] = "InitialDeepClean";
1243
+ MiotState2[MiotState2["InitialDeepCleanPaused"] = 102] = "InitialDeepCleanPaused";
1244
+ MiotState2[MiotState2["Sanitizing"] = 103] = "Sanitizing";
1245
+ MiotState2[MiotState2["SanitizingWithDry"] = 104] = "SanitizingWithDry";
1246
+ MiotState2[MiotState2["ChangingMop"] = 105] = "ChangingMop";
1247
+ MiotState2[MiotState2["ChangingMopPaused"] = 106] = "ChangingMopPaused";
1248
+ MiotState2[MiotState2["FloorMaintaining"] = 107] = "FloorMaintaining";
1249
+ MiotState2[MiotState2["FloorMaintainingPaused"] = 108] = "FloorMaintainingPaused";
1156
1250
  return MiotState2;
1157
1251
  })(MiotState || {});
1158
1252
  var ChargingStatus = /* @__PURE__ */ ((ChargingStatus2) => {
@@ -1184,21 +1278,87 @@ var CleaningMode = /* @__PURE__ */ ((CleaningMode2) => {
1184
1278
  var MiotError = /* @__PURE__ */ ((MiotError2) => {
1185
1279
  MiotError2[MiotError2["Clear"] = 0] = "Clear";
1186
1280
  MiotError2[MiotError2["WheelRotationAnomaly"] = 1] = "WheelRotationAnomaly";
1281
+ MiotError2[MiotError2["Cliff"] = 2] = "Cliff";
1282
+ MiotError2[MiotError2["Bumper"] = 3] = "Bumper";
1283
+ MiotError2[MiotError2["Gesture"] = 4] = "Gesture";
1284
+ MiotError2[MiotError2["BumperRepeat"] = 5] = "BumperRepeat";
1285
+ MiotError2[MiotError2["DropRepeat"] = 6] = "DropRepeat";
1286
+ MiotError2[MiotError2["OpticalFlow"] = 7] = "OpticalFlow";
1287
+ MiotError2[MiotError2["Box"] = 8] = "Box";
1288
+ MiotError2[MiotError2["TankBox"] = 9] = "TankBox";
1289
+ MiotError2[MiotError2["WaterBoxEmpty"] = 10] = "WaterBoxEmpty";
1290
+ MiotError2[MiotError2["BoxFull"] = 11] = "BoxFull";
1291
+ MiotError2[MiotError2["Brush"] = 12] = "Brush";
1292
+ MiotError2[MiotError2["SideBrush"] = 13] = "SideBrush";
1293
+ MiotError2[MiotError2["Fan"] = 14] = "Fan";
1294
+ MiotError2[MiotError2["LeftWheelMotor"] = 15] = "LeftWheelMotor";
1295
+ MiotError2[MiotError2["RightWheelMotor"] = 16] = "RightWheelMotor";
1296
+ MiotError2[MiotError2["TurnSuffocate"] = 17] = "TurnSuffocate";
1187
1297
  MiotError2[MiotError2["RobotLifted"] = 18] = "RobotLifted";
1188
- MiotError2[MiotError2["TaskComplete"] = 68] = "TaskComplete";
1189
- MiotError2[MiotError2["ManualMopInstallRequired"] = 74] = "ManualMopInstallRequired";
1190
- MiotError2[MiotError2["WastewaterTankFull"] = 105] = "WastewaterTankFull";
1191
- MiotError2[MiotError2["CleanWaterTankEmpty"] = 107] = "CleanWaterTankEmpty";
1192
- MiotError2[MiotError2["WashboardFilterNeedsCleaning"] = 114] = "WashboardFilterNeedsCleaning";
1193
- MiotError2[MiotError2["MopPadsMissing"] = 120] = "MopPadsMissing";
1298
+ MiotError2[MiotError2["ChargerGet"] = 19] = "ChargerGet";
1194
1299
  MiotError2[MiotError2["BatteryLow"] = 20] = "BatteryLow";
1195
1300
  MiotError2[MiotError2["ChargeFault"] = 21] = "ChargeFault";
1196
1301
  MiotError2[MiotError2["BatteryPercentageAnomaly"] = 22] = "BatteryPercentageAnomaly";
1302
+ MiotError2[MiotError2["Heart"] = 23] = "Heart";
1303
+ MiotError2[MiotError2["CameraOcclusion"] = 24] = "CameraOcclusion";
1304
+ MiotError2[MiotError2["Move"] = 25] = "Move";
1305
+ MiotError2[MiotError2["FlowShielding"] = 26] = "FlowShielding";
1306
+ MiotError2[MiotError2["InfraredShielding"] = 27] = "InfraredShielding";
1197
1307
  MiotError2[MiotError2["ChargeNoElectric"] = 28] = "ChargeNoElectric";
1198
1308
  MiotError2[MiotError2["BatteryFault"] = 29] = "BatteryFault";
1309
+ MiotError2[MiotError2["FanSpeedError"] = 30] = "FanSpeedError";
1310
+ MiotError2[MiotError2["LeftWheelSpeed"] = 31] = "LeftWheelSpeed";
1311
+ MiotError2[MiotError2["RightWheelSpeed"] = 32] = "RightWheelSpeed";
1312
+ MiotError2[MiotError2["Bmi055Acce"] = 33] = "Bmi055Acce";
1313
+ MiotError2[MiotError2["Bmi055Gyro"] = 34] = "Bmi055Gyro";
1314
+ MiotError2[MiotError2["Xv7001"] = 35] = "Xv7001";
1315
+ MiotError2[MiotError2["LeftMagnet"] = 36] = "LeftMagnet";
1316
+ MiotError2[MiotError2["RightMagnet"] = 37] = "RightMagnet";
1317
+ MiotError2[MiotError2["FlowError"] = 38] = "FlowError";
1318
+ MiotError2[MiotError2["InfraredFault"] = 39] = "InfraredFault";
1319
+ MiotError2[MiotError2["CameraFault"] = 40] = "CameraFault";
1320
+ MiotError2[MiotError2["StrongMagnet"] = 41] = "StrongMagnet";
1321
+ MiotError2[MiotError2["WaterPump"] = 42] = "WaterPump";
1322
+ MiotError2[MiotError2["Rtc"] = 43] = "Rtc";
1323
+ MiotError2[MiotError2["AutoKeyTrig"] = 44] = "AutoKeyTrig";
1324
+ MiotError2[MiotError2["P3v3"] = 45] = "P3v3";
1325
+ MiotError2[MiotError2["CameraIdle"] = 46] = "CameraIdle";
1326
+ MiotError2[MiotError2["Blocked"] = 47] = "Blocked";
1327
+ MiotError2[MiotError2["LdsError"] = 48] = "LdsError";
1328
+ MiotError2[MiotError2["LdsBumper"] = 49] = "LdsBumper";
1329
+ MiotError2[MiotError2["WaterPump2"] = 50] = "WaterPump2";
1330
+ MiotError2[MiotError2["FilterBlocked"] = 51] = "FilterBlocked";
1331
+ MiotError2[MiotError2["Edge"] = 54] = "Edge";
1332
+ MiotError2[MiotError2["Carpet"] = 55] = "Carpet";
1333
+ MiotError2[MiotError2["Laser"] = 56] = "Laser";
1334
+ MiotError2[MiotError2["Edge2"] = 57] = "Edge2";
1335
+ MiotError2[MiotError2["Ultrasonic"] = 58] = "Ultrasonic";
1336
+ MiotError2[MiotError2["NoGoZone"] = 59] = "NoGoZone";
1337
+ MiotError2[MiotError2["Route"] = 61] = "Route";
1338
+ MiotError2[MiotError2["Route2"] = 62] = "Route2";
1339
+ MiotError2[MiotError2["Blocked2"] = 63] = "Blocked2";
1340
+ MiotError2[MiotError2["Blocked3"] = 64] = "Blocked3";
1341
+ MiotError2[MiotError2["Restricted"] = 65] = "Restricted";
1342
+ MiotError2[MiotError2["Restricted2"] = 66] = "Restricted2";
1343
+ MiotError2[MiotError2["Restricted3"] = 67] = "Restricted3";
1344
+ MiotError2[MiotError2["TaskComplete"] = 68] = "TaskComplete";
1345
+ MiotError2[MiotError2["MopRemoved"] = 69] = "MopRemoved";
1346
+ MiotError2[MiotError2["MopRemoved2"] = 70] = "MopRemoved2";
1347
+ MiotError2[MiotError2["MopPadStopRotate"] = 71] = "MopPadStopRotate";
1348
+ MiotError2[MiotError2["MopPadStopRotate2"] = 72] = "MopPadStopRotate2";
1349
+ MiotError2[MiotError2["ManualMopInstallRequired"] = 74] = "ManualMopInstallRequired";
1199
1350
  MiotError2[MiotError2["LowBatteryTurnOff"] = 75] = "LowBatteryTurnOff";
1351
+ MiotError2[MiotError2["DirtyTankNotInstalled"] = 76] = "DirtyTankNotInstalled";
1352
+ MiotError2[MiotError2["RobotInHiddenRoom"] = 78] = "RobotInHiddenRoom";
1353
+ MiotError2[MiotError2["LdsFailedToLift"] = 79] = "LdsFailedToLift";
1200
1354
  MiotError2[MiotError2["RobotStuck"] = 80] = "RobotStuck";
1201
1355
  MiotError2[MiotError2["RobotStuckRepeat"] = 81] = "RobotStuckRepeat";
1356
+ MiotError2[MiotError2["SlipperyFloor"] = 82] = "SlipperyFloor";
1357
+ MiotError2[MiotError2["UnknownError"] = 84] = "UnknownError";
1358
+ MiotError2[MiotError2["CheckMopInstall"] = 85] = "CheckMopInstall";
1359
+ MiotError2[MiotError2["DirtyWaterTankFull"] = 86] = "DirtyWaterTankFull";
1360
+ MiotError2[MiotError2["RetractableLegStuck"] = 88] = "RetractableLegStuck";
1361
+ MiotError2[MiotError2["InternalError"] = 89] = "InternalError";
1202
1362
  MiotError2[MiotError2["RobotStuck2"] = 90] = "RobotStuck2";
1203
1363
  MiotError2[MiotError2["RobotStuckOnTables"] = 91] = "RobotStuckOnTables";
1204
1364
  MiotError2[MiotError2["RobotStuckOnPassage"] = 92] = "RobotStuckOnPassage";
@@ -1209,19 +1369,82 @@ var MiotError = /* @__PURE__ */ ((MiotError2) => {
1209
1369
  MiotError2[MiotError2["RobotStuckOnPet"] = 97] = "RobotStuckOnPet";
1210
1370
  MiotError2[MiotError2["RobotStuckOnSlipperySurface"] = 98] = "RobotStuckOnSlipperySurface";
1211
1371
  MiotError2[MiotError2["RobotStuckOnCarpet"] = 99] = "RobotStuckOnCarpet";
1212
- MiotError2[MiotError2["RobotStuckOnCurtain"] = 200] = "RobotStuckOnCurtain";
1213
1372
  MiotError2[MiotError2["BinFull"] = 101] = "BinFull";
1373
+ MiotError2[MiotError2["BinOpen"] = 102] = "BinOpen";
1374
+ MiotError2[MiotError2["BinOpen2"] = 103] = "BinOpen2";
1375
+ MiotError2[MiotError2["BinFull2"] = 104] = "BinFull2";
1376
+ MiotError2[MiotError2["WastewaterTankFull"] = 105] = "WastewaterTankFull";
1377
+ MiotError2[MiotError2["DirtyWaterTank"] = 106] = "DirtyWaterTank";
1378
+ MiotError2[MiotError2["CleanWaterTankEmpty"] = 107] = "CleanWaterTankEmpty";
1379
+ MiotError2[MiotError2["DirtyWaterTank2"] = 108] = "DirtyWaterTank2";
1380
+ MiotError2[MiotError2["DirtyWaterTankBlocked"] = 109] = "DirtyWaterTankBlocked";
1381
+ MiotError2[MiotError2["DirtyWaterTankPump"] = 110] = "DirtyWaterTankPump";
1382
+ MiotError2[MiotError2["MopPad"] = 111] = "MopPad";
1383
+ MiotError2[MiotError2["WetMopPad"] = 112] = "WetMopPad";
1384
+ MiotError2[MiotError2["WashboardFilterNeedsCleaning"] = 114] = "WashboardFilterNeedsCleaning";
1385
+ MiotError2[MiotError2["CleanTankLevel"] = 116] = "CleanTankLevel";
1214
1386
  MiotError2[MiotError2["StationDisconnected"] = 117] = "StationDisconnected";
1387
+ MiotError2[MiotError2["DirtyTankLevel"] = 118] = "DirtyTankLevel";
1388
+ MiotError2[MiotError2["WashboardLevel"] = 119] = "WashboardLevel";
1389
+ MiotError2[MiotError2["MopPadsMissing"] = 120] = "MopPadsMissing";
1215
1390
  MiotError2[MiotError2["DustBagFull"] = 121] = "DustBagFull";
1391
+ MiotError2[MiotError2["UnknownWarning"] = 122] = "UnknownWarning";
1392
+ MiotError2[MiotError2["SelfTestFailed"] = 123] = "SelfTestFailed";
1393
+ MiotError2[MiotError2["WashboardNotWorking"] = 124] = "WashboardNotWorking";
1394
+ MiotError2[MiotError2["DrainageFailed"] = 125] = "DrainageFailed";
1395
+ MiotError2[MiotError2["MopNotDetected"] = 126] = "MopNotDetected";
1396
+ MiotError2[MiotError2["MopHolderError"] = 127] = "MopHolderError";
1397
+ MiotError2[MiotError2["DockError"] = 128] = "DockError";
1398
+ MiotError2[MiotError2["WashFailed"] = 129] = "WashFailed";
1399
+ MiotError2[MiotError2["RobotStuckOnCurtain"] = 200] = "RobotStuckOnCurtain";
1400
+ MiotError2[MiotError2["EdgeMopStopRotate"] = 201] = "EdgeMopStopRotate";
1401
+ MiotError2[MiotError2["EdgeMopDetached"] = 202] = "EdgeMopDetached";
1402
+ MiotError2[MiotError2["ChassisLiftMalfunction"] = 203] = "ChassisLiftMalfunction";
1403
+ MiotError2[MiotError2["InternalError2"] = 207] = "InternalError2";
1404
+ MiotError2[MiotError2["MopCoverError"] = 209] = "MopCoverError";
1405
+ MiotError2[MiotError2["RollerMopError"] = 210] = "RollerMopError";
1406
+ MiotError2[MiotError2["OnboardWaterTankEmpty"] = 213] = "OnboardWaterTankEmpty";
1407
+ MiotError2[MiotError2["OnboardDirtyWaterTankFull"] = 214] = "OnboardDirtyWaterTankFull";
1408
+ MiotError2[MiotError2["MopNotInstalled"] = 215] = "MopNotInstalled";
1409
+ MiotError2[MiotError2["RollerMopError2"] = 218] = "RollerMopError2";
1410
+ MiotError2[MiotError2["FluffingRollerError"] = 222] = "FluffingRollerError";
1411
+ MiotError2[MiotError2["MopCoverError2"] = 223] = "MopCoverError2";
1412
+ MiotError2[MiotError2["BlockedByObstacle"] = 226] = "BlockedByObstacle";
1413
+ MiotError2[MiotError2["ReturnToChargeFailed"] = 1e3] = "ReturnToChargeFailed";
1216
1414
  return MiotError2;
1217
1415
  })(MiotError || {});
1218
1416
  var TaskStatus = /* @__PURE__ */ ((TaskStatus2) => {
1417
+ TaskStatus2[TaskStatus2["Completed"] = 0] = "Completed";
1219
1418
  TaskStatus2[TaskStatus2["InterruptedOrPaused"] = 1] = "InterruptedOrPaused";
1220
1419
  TaskStatus2[TaskStatus2["Active"] = 2] = "Active";
1221
1420
  TaskStatus2[TaskStatus2["Transitioning"] = 3] = "Transitioning";
1421
+ TaskStatus2[TaskStatus2["SpotCleaning"] = 4] = "SpotCleaning";
1422
+ TaskStatus2[TaskStatus2["FastMapping"] = 5] = "FastMapping";
1222
1423
  TaskStatus2[TaskStatus2["OnDockIdle"] = 6] = "OnDockIdle";
1424
+ TaskStatus2[TaskStatus2["ZoneCleaningPaused"] = 7] = "ZoneCleaningPaused";
1425
+ TaskStatus2[TaskStatus2["SegmentCleaningPaused"] = 8] = "SegmentCleaningPaused";
1426
+ TaskStatus2[TaskStatus2["SpotCleaningPaused"] = 9] = "SpotCleaningPaused";
1427
+ TaskStatus2[TaskStatus2["MapCleaningPaused"] = 10] = "MapCleaningPaused";
1428
+ TaskStatus2[TaskStatus2["DockingPaused"] = 11] = "DockingPaused";
1223
1429
  TaskStatus2[TaskStatus2["TransientPauseEdge"] = 12] = "TransientPauseEdge";
1430
+ TaskStatus2[TaskStatus2["SegmentMoppingPaused"] = 13] = "SegmentMoppingPaused";
1224
1431
  TaskStatus2[TaskStatus2["NeedsIntervention"] = 14] = "NeedsIntervention";
1432
+ TaskStatus2[TaskStatus2["AutoMoppingPaused"] = 15] = "AutoMoppingPaused";
1433
+ TaskStatus2[TaskStatus2["AutoDockingPaused"] = 16] = "AutoDockingPaused";
1434
+ TaskStatus2[TaskStatus2["SegmentDockingPaused"] = 17] = "SegmentDockingPaused";
1435
+ TaskStatus2[TaskStatus2["ZoneDockingPaused"] = 18] = "ZoneDockingPaused";
1436
+ TaskStatus2[TaskStatus2["CruisingPath"] = 20] = "CruisingPath";
1437
+ TaskStatus2[TaskStatus2["CruisingPathPaused"] = 21] = "CruisingPathPaused";
1438
+ TaskStatus2[TaskStatus2["CruisingPoint"] = 22] = "CruisingPoint";
1439
+ TaskStatus2[TaskStatus2["CruisingPointPaused"] = 23] = "CruisingPointPaused";
1440
+ TaskStatus2[TaskStatus2["SummonCleanPaused"] = 24] = "SummonCleanPaused";
1441
+ TaskStatus2[TaskStatus2["ReturningInstallMop"] = 25] = "ReturningInstallMop";
1442
+ TaskStatus2[TaskStatus2["ReturningRemoveMop"] = 26] = "ReturningRemoveMop";
1443
+ TaskStatus2[TaskStatus2["StationCleaning"] = 27] = "StationCleaning";
1444
+ TaskStatus2[TaskStatus2["PetFinding"] = 30] = "PetFinding";
1445
+ TaskStatus2[TaskStatus2["AutoCleaningWashingPaused"] = 31] = "AutoCleaningWashingPaused";
1446
+ TaskStatus2[TaskStatus2["AreaCleaningWashingPaused"] = 32] = "AreaCleaningWashingPaused";
1447
+ TaskStatus2[TaskStatus2["CustomCleaningWashingPaused"] = 33] = "CustomCleaningWashingPaused";
1225
1448
  return TaskStatus2;
1226
1449
  })(TaskStatus || {});
1227
1450
 
@@ -2342,7 +2565,7 @@ var TASK = enumLookup([
2342
2565
  12 /* TransientPauseEdge */,
2343
2566
  14 /* NeedsIntervention */
2344
2567
  ]);
2345
- var VacuumDevice = class extends BaseDevice {
2568
+ var VacuumDevice = class _VacuumDevice extends BaseDevice {
2346
2569
  #caps;
2347
2570
  #lastMap = null;
2348
2571
  constructor(input) {
@@ -2358,6 +2581,18 @@ var VacuumDevice = class extends BaseDevice {
2358
2581
  get vacuumCapabilities() {
2359
2582
  return this.#caps;
2360
2583
  }
2584
+ /**
2585
+ * The suction levels this model supports, as a {@link SuctionLevel} enum array
2586
+ * (from the capability record). Lets a consumer see which fan speeds are
2587
+ * selectable without reaching into {@link vacuumCapabilities}.
2588
+ */
2589
+ get supportedSuctionLevels() {
2590
+ return this.#caps.supportedSuctionLevels;
2591
+ }
2592
+ /** The water/mop volumes this model supports, as a {@link WaterVolume} enum array. */
2593
+ get supportedWaterVolumes() {
2594
+ return this.#caps.supportedWaterVolumes;
2595
+ }
2361
2596
  #num(siid, piid) {
2362
2597
  return asNum(this.getProperty(siid, piid)?.value);
2363
2598
  }
@@ -2557,6 +2792,16 @@ var VacuumDevice = class extends BaseDevice {
2557
2792
  const points = [[Math.round(point.x), Math.round(point.y), repeats, fan, water]];
2558
2793
  return this.#startCustom(CUSTOM_CLEAN_MODE.SPOT, { points });
2559
2794
  }
2795
+ /**
2796
+ * Seed the cache from the CLOUD SHADOW (last-known values) WITHOUT waking the
2797
+ * robot — reads {@link VacuumDevice.DEFAULT_PROPS} from the cloud-cached
2798
+ * endpoint. After it resolves, every typed getter (status/battery/suction/
2799
+ * water/cleaningMode/error/charging…) reflects the cached values, so a
2800
+ * standby/docked vacuum reports its state exactly as the Dreamehome app does.
2801
+ */
2802
+ async refreshFromCache() {
2803
+ await this.refreshCachedProperties([..._VacuumDevice.DEFAULT_PROPS]);
2804
+ }
2560
2805
  // -- maps ---------------------------------------------------------------
2561
2806
  /** The most-recently-decoded map, or `null` until {@link getMap} succeeds. */
2562
2807
  get lastMap() {
@@ -2710,6 +2955,83 @@ var MowerTaskStatus = /* @__PURE__ */ ((MowerTaskStatus2) => {
2710
2955
  MowerTaskStatus2[MowerTaskStatus2["SpotIncomplete"] = 7] = "SpotIncomplete";
2711
2956
  return MowerTaskStatus2;
2712
2957
  })(MowerTaskStatus || {});
2958
+ var MowerFault = /* @__PURE__ */ ((MowerFault2) => {
2959
+ MowerFault2[MowerFault2["NoDeviceCode"] = 0] = "NoDeviceCode";
2960
+ MowerFault2[MowerFault2["Tilted"] = 1] = "Tilted";
2961
+ MowerFault2[MowerFault2["Trapped"] = 2] = "Trapped";
2962
+ MowerFault2[MowerFault2["NarrowPathToStation"] = 3] = "NarrowPathToStation";
2963
+ MowerFault2[MowerFault2["LeftWheel"] = 4] = "LeftWheel";
2964
+ MowerFault2[MowerFault2["RightWheel"] = 5] = "RightWheel";
2965
+ MowerFault2[MowerFault2["LiftMotor"] = 6] = "LiftMotor";
2966
+ MowerFault2[MowerFault2["Cutter"] = 7] = "Cutter";
2967
+ MowerFault2[MowerFault2["SidedMotor"] = 8] = "SidedMotor";
2968
+ MowerFault2[MowerFault2["CrashPlate"] = 9] = "CrashPlate";
2969
+ MowerFault2[MowerFault2["Charging"] = 10] = "Charging";
2970
+ MowerFault2[MowerFault2["BatteryOverheat"] = 11] = "BatteryOverheat";
2971
+ MowerFault2[MowerFault2["LidarCovered"] = 12] = "LidarCovered";
2972
+ MowerFault2[MowerFault2["LidarOverheatWithoutMap"] = 13] = "LidarOverheatWithoutMap";
2973
+ MowerFault2[MowerFault2["LidarOverheatWithMap"] = 14] = "LidarOverheatWithMap";
2974
+ MowerFault2[MowerFault2["LidarOverheat"] = 15] = "LidarOverheat";
2975
+ MowerFault2[MowerFault2["LidarDirty"] = 16] = "LidarDirty";
2976
+ MowerFault2[MowerFault2["LidarAbnormal"] = 17] = "LidarAbnormal";
2977
+ MowerFault2[MowerFault2["LocationWeak"] = 18] = "LocationWeak";
2978
+ MowerFault2[MowerFault2["LocationLost"] = 19] = "LocationLost";
2979
+ MowerFault2[MowerFault2["Sensor"] = 20] = "Sensor";
2980
+ MowerFault2[MowerFault2["InForbiddenArea"] = 21] = "InForbiddenArea";
2981
+ MowerFault2[MowerFault2["OutOfMap"] = 22] = "OutOfMap";
2982
+ MowerFault2[MowerFault2["EmergencyStop"] = 23] = "EmergencyStop";
2983
+ MowerFault2[MowerFault2["BatteryLow"] = 24] = "BatteryLow";
2984
+ MowerFault2[MowerFault2["MapFileCrack"] = 25] = "MapFileCrack";
2985
+ MowerFault2[MowerFault2["AwayFromMap"] = 26] = "AwayFromMap";
2986
+ MowerFault2[MowerFault2["HumanDetected"] = 27] = "HumanDetected";
2987
+ MowerFault2[MowerFault2["BladeLoss"] = 28] = "BladeLoss";
2988
+ MowerFault2[MowerFault2["StationLoss"] = 29] = "StationLoss";
2989
+ MowerFault2[MowerFault2["MaintainLoss"] = 30] = "MaintainLoss";
2990
+ MowerFault2[MowerFault2["BackChargeFailed"] = 31] = "BackChargeFailed";
2991
+ MowerFault2[MowerFault2["DockingFailed"] = 32] = "DockingFailed";
2992
+ MowerFault2[MowerFault2["LocatingFailedWithMap"] = 33] = "LocatingFailedWithMap";
2993
+ MowerFault2[MowerFault2["LocatingFailedWithoutMap"] = 34] = "LocatingFailedWithoutMap";
2994
+ MowerFault2[MowerFault2["LocatingAbnormal"] = 35] = "LocatingAbnormal";
2995
+ MowerFault2[MowerFault2["TaskStartFailed"] = 36] = "TaskStartFailed";
2996
+ MowerFault2[MowerFault2["PathImpassable"] = 37] = "PathImpassable";
2997
+ MowerFault2[MowerFault2["LidarDirtyWarning"] = 38] = "LidarDirtyWarning";
2998
+ MowerFault2[MowerFault2["CamDirty"] = 39] = "CamDirty";
2999
+ MowerFault2[MowerFault2["CamAbnormal"] = 40] = "CamAbnormal";
3000
+ MowerFault2[MowerFault2["CamCover"] = 41] = "CamCover";
3001
+ MowerFault2[MowerFault2["BatteryOverheatWarning"] = 42] = "BatteryOverheatWarning";
3002
+ MowerFault2[MowerFault2["BatteryTempLow"] = 43] = "BatteryTempLow";
3003
+ MowerFault2[MowerFault2["AutobuildBorder"] = 44] = "AutobuildBorder";
3004
+ MowerFault2[MowerFault2["AutobuildSide"] = 45] = "AutobuildSide";
3005
+ MowerFault2[MowerFault2["BorderFinish"] = 46] = "BorderFinish";
3006
+ MowerFault2[MowerFault2["NewMap"] = 47] = "NewMap";
3007
+ MowerFault2[MowerFault2["TaskFinish"] = 48] = "TaskFinish";
3008
+ MowerFault2[MowerFault2["DestinationNotReachable"] = 49] = "DestinationNotReachable";
3009
+ MowerFault2[MowerFault2["TaskStart"] = 50] = "TaskStart";
3010
+ MowerFault2[MowerFault2["CruiseStart"] = 51] = "CruiseStart";
3011
+ MowerFault2[MowerFault2["PointAndGoStart"] = 52] = "PointAndGoStart";
3012
+ MowerFault2[MowerFault2["ScheduleStart"] = 53] = "ScheduleStart";
3013
+ MowerFault2[MowerFault2["BatteryLowReturning"] = 54] = "BatteryLowReturning";
3014
+ MowerFault2[MowerFault2["BatteryLowScheduleSuspend"] = 55] = "BatteryLowScheduleSuspend";
3015
+ MowerFault2[MowerFault2["BadWeatherProtecting"] = 56] = "BadWeatherProtecting";
3016
+ MowerFault2[MowerFault2["RainScheduleInterupted"] = 57] = "RainScheduleInterupted";
3017
+ MowerFault2[MowerFault2["RainScheduleSuspend"] = 58] = "RainScheduleSuspend";
3018
+ MowerFault2[MowerFault2["ForzenReturning"] = 59] = "ForzenReturning";
3019
+ MowerFault2[MowerFault2["FrozenScheduleSuspend"] = 60] = "FrozenScheduleSuspend";
3020
+ MowerFault2[MowerFault2["NotDisturbReturning"] = 61] = "NotDisturbReturning";
3021
+ MowerFault2[MowerFault2["NotDisturbScheduleSuspend"] = 62] = "NotDisturbScheduleSuspend";
3022
+ MowerFault2[MowerFault2["WorkingScheduleSuspend"] = 63] = "WorkingScheduleSuspend";
3023
+ MowerFault2[MowerFault2["RemoteControlingScheduleSuspend"] = 64] = "RemoteControlingScheduleSuspend";
3024
+ MowerFault2[MowerFault2["EmergencyStoppedScheduleSuspend"] = 65] = "EmergencyStoppedScheduleSuspend";
3025
+ MowerFault2[MowerFault2["TopCoverOpenScheduleSuspend"] = 66] = "TopCoverOpenScheduleSuspend";
3026
+ MowerFault2[MowerFault2["FaultModeScheduleSuspend"] = 67] = "FaultModeScheduleSuspend";
3027
+ MowerFault2[MowerFault2["ScheduleTimeout"] = 68] = "ScheduleTimeout";
3028
+ MowerFault2[MowerFault2["StationNotConnectedToWorkingArea"] = 69] = "StationNotConnectedToWorkingArea";
3029
+ MowerFault2[MowerFault2["ContinueFromBreakpoint"] = 70] = "ContinueFromBreakpoint";
3030
+ MowerFault2[MowerFault2["IdleTimeoutReturning"] = 71] = "IdleTimeoutReturning";
3031
+ MowerFault2[MowerFault2["PauseTimeoutReturning"] = 72] = "PauseTimeoutReturning";
3032
+ MowerFault2[MowerFault2["TopCoverOpen"] = 73] = "TopCoverOpen";
3033
+ return MowerFault2;
3034
+ })(MowerFault || {});
2713
3035
 
2714
3036
  // src/models/mower/decode.ts
2715
3037
  function isRecord(v) {
@@ -3389,7 +3711,13 @@ var STATUS = enumLookup(
3389
3711
  var CHARGING2 = enumLookup(
3390
3712
  Object.values(MowerChargingStatus).filter((v) => typeof v === "number")
3391
3713
  );
3392
- var MowerDevice = class extends BaseDevice {
3714
+ var TASK_STATUS = enumLookup(
3715
+ Object.values(MowerTaskStatus).filter((v) => typeof v === "number")
3716
+ );
3717
+ var FAULT = enumLookup(
3718
+ Object.values(MowerFault).filter((v) => typeof v === "number")
3719
+ );
3720
+ var MowerDevice = class _MowerDevice extends BaseDevice {
3393
3721
  #caps;
3394
3722
  #fetchBatch;
3395
3723
  #lastMap = null;
@@ -3437,6 +3765,25 @@ var MowerDevice = class extends BaseDevice {
3437
3765
  get taskStatusRaw() {
3438
3766
  return this.#num(MOWER_PROP.TASK_STATUS.siid, MOWER_PROP.TASK_STATUS.piid);
3439
3767
  }
3768
+ /**
3769
+ * TASK_STATUS (5:104) decoded to {@link MowerTaskStatus}, or null. The donor
3770
+ * names only code 7 (SpotIncomplete); codes 2/3/10/13 are documented "Unknown
3771
+ * task status" and intentionally surface as raw via {@link taskStatusRaw}.
3772
+ */
3773
+ get taskStatus() {
3774
+ return TASK_STATUS(this.taskStatusRaw);
3775
+ }
3776
+ get faultRaw() {
3777
+ return this.#num(MOWER_PROP.DEVICE_CODE.siid, MOWER_PROP.DEVICE_CODE.piid);
3778
+ }
3779
+ /**
3780
+ * DEVICE_CODE (2:2) decoded to a {@link MowerFault} (the donor's
3781
+ * BASE_DEVICE_CODES registry, 0..73), or null for a model-specific/undocumented
3782
+ * code — which still surfaces as the raw number via {@link faultRaw}.
3783
+ */
3784
+ get fault() {
3785
+ return FAULT(this.faultRaw);
3786
+ }
3440
3787
  /** Parsed scheduling task descriptor (2:50), or null. */
3441
3788
  get task() {
3442
3789
  return parseTaskDescriptor(
@@ -3529,6 +3876,16 @@ var MowerDevice = class extends BaseDevice {
3529
3876
  }
3530
3877
  return this.#sendTask(buildSpotPayload(spotAreaIds.map((s) => Math.trunc(s))));
3531
3878
  }
3879
+ /**
3880
+ * Seed the cache from the CLOUD SHADOW (last-known values) WITHOUT waking the
3881
+ * mower — reads {@link MowerDevice.DEFAULT_PROPS} from the cloud-cached
3882
+ * endpoint. After it resolves, every typed getter (status/battery/charging/
3883
+ * coverage/task/controlAction…) reflects the cached values, so a docked/
3884
+ * standby mower reports its state exactly as the Dreamehome app does.
3885
+ */
3886
+ async refreshFromCache() {
3887
+ await this.refreshCachedProperties([..._MowerDevice.DEFAULT_PROPS]);
3888
+ }
3532
3889
  // -- maps ---------------------------------------------------------------
3533
3890
  /** The most-recently-parsed map, or `null` until {@link getMap} succeeds. */
3534
3891
  get lastMap() {
@@ -3569,6 +3926,7 @@ var MowerDevice = class extends BaseDevice {
3569
3926
  /** Props worth seeding on start() / polling — exported for the facade. */
3570
3927
  static DEFAULT_PROPS = [
3571
3928
  MOWER_PROP.STATUS,
3929
+ MOWER_PROP.DEVICE_CODE,
3572
3930
  MOWER_PROP.BATTERY,
3573
3931
  MOWER_PROP.CHARGING_STATUS,
3574
3932
  MOWER_PROP.TASK_STATUS,
@@ -3742,6 +4100,7 @@ export {
3742
4100
  MowerChargingStatus,
3743
4101
  MowerControlAction,
3744
4102
  MowerDevice,
4103
+ MowerFault,
3745
4104
  MowerStatus,
3746
4105
  MowerTaskStatus,
3747
4106
  Nodreame,