@apocaliss92/nodedreame 1.1.0 → 1.3.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
@@ -1,5 +1,6 @@
1
1
  // src/support/version.ts
2
2
  var LIBRARY_NAME = "nodedreame";
3
+ var LIBRARY_VERSION = "1.3.0";
3
4
 
4
5
  // src/transport/errors.ts
5
6
  var DreameError = class extends Error {
@@ -1226,11 +1227,27 @@ var MiotState = /* @__PURE__ */ ((MiotState2) => {
1226
1227
  MiotState2[MiotState2["ReturnToEmpty"] = 28] = "ReturnToEmpty";
1227
1228
  MiotState2[MiotState2["WaitingForTask"] = 29] = "WaitingForTask";
1228
1229
  MiotState2[MiotState2["CleanWashboardBase"] = 30] = "CleanWashboardBase";
1230
+ MiotState2[MiotState2["ReturningToDrain"] = 31] = "ReturningToDrain";
1231
+ MiotState2[MiotState2["Draining"] = 32] = "Draining";
1229
1232
  MiotState2[MiotState2["AutoWaterDraining"] = 33] = "AutoWaterDraining";
1233
+ MiotState2[MiotState2["Emptying"] = 34] = "Emptying";
1234
+ MiotState2[MiotState2["DustBagDrying"] = 35] = "DustBagDrying";
1235
+ MiotState2[MiotState2["DustBagDryingPaused"] = 36] = "DustBagDryingPaused";
1236
+ MiotState2[MiotState2["HeadingToExtraCleaning"] = 37] = "HeadingToExtraCleaning";
1237
+ MiotState2[MiotState2["ExtraCleaning"] = 38] = "ExtraCleaning";
1238
+ MiotState2[MiotState2["FindingPetPaused"] = 95] = "FindingPetPaused";
1239
+ MiotState2[MiotState2["FindingPet"] = 96] = "FindingPet";
1230
1240
  MiotState2[MiotState2["ShortcutRunning"] = 97] = "ShortcutRunning";
1231
1241
  MiotState2[MiotState2["CameraMonitoring"] = 98] = "CameraMonitoring";
1232
1242
  MiotState2[MiotState2["CameraMonitoringPaused"] = 99] = "CameraMonitoringPaused";
1233
1243
  MiotState2[MiotState2["InitialDeepClean"] = 101] = "InitialDeepClean";
1244
+ MiotState2[MiotState2["InitialDeepCleanPaused"] = 102] = "InitialDeepCleanPaused";
1245
+ MiotState2[MiotState2["Sanitizing"] = 103] = "Sanitizing";
1246
+ MiotState2[MiotState2["SanitizingWithDry"] = 104] = "SanitizingWithDry";
1247
+ MiotState2[MiotState2["ChangingMop"] = 105] = "ChangingMop";
1248
+ MiotState2[MiotState2["ChangingMopPaused"] = 106] = "ChangingMopPaused";
1249
+ MiotState2[MiotState2["FloorMaintaining"] = 107] = "FloorMaintaining";
1250
+ MiotState2[MiotState2["FloorMaintainingPaused"] = 108] = "FloorMaintainingPaused";
1234
1251
  return MiotState2;
1235
1252
  })(MiotState || {});
1236
1253
  var ChargingStatus = /* @__PURE__ */ ((ChargingStatus2) => {
@@ -1262,21 +1279,87 @@ var CleaningMode = /* @__PURE__ */ ((CleaningMode2) => {
1262
1279
  var MiotError = /* @__PURE__ */ ((MiotError2) => {
1263
1280
  MiotError2[MiotError2["Clear"] = 0] = "Clear";
1264
1281
  MiotError2[MiotError2["WheelRotationAnomaly"] = 1] = "WheelRotationAnomaly";
1282
+ MiotError2[MiotError2["Cliff"] = 2] = "Cliff";
1283
+ MiotError2[MiotError2["Bumper"] = 3] = "Bumper";
1284
+ MiotError2[MiotError2["Gesture"] = 4] = "Gesture";
1285
+ MiotError2[MiotError2["BumperRepeat"] = 5] = "BumperRepeat";
1286
+ MiotError2[MiotError2["DropRepeat"] = 6] = "DropRepeat";
1287
+ MiotError2[MiotError2["OpticalFlow"] = 7] = "OpticalFlow";
1288
+ MiotError2[MiotError2["Box"] = 8] = "Box";
1289
+ MiotError2[MiotError2["TankBox"] = 9] = "TankBox";
1290
+ MiotError2[MiotError2["WaterBoxEmpty"] = 10] = "WaterBoxEmpty";
1291
+ MiotError2[MiotError2["BoxFull"] = 11] = "BoxFull";
1292
+ MiotError2[MiotError2["Brush"] = 12] = "Brush";
1293
+ MiotError2[MiotError2["SideBrush"] = 13] = "SideBrush";
1294
+ MiotError2[MiotError2["Fan"] = 14] = "Fan";
1295
+ MiotError2[MiotError2["LeftWheelMotor"] = 15] = "LeftWheelMotor";
1296
+ MiotError2[MiotError2["RightWheelMotor"] = 16] = "RightWheelMotor";
1297
+ MiotError2[MiotError2["TurnSuffocate"] = 17] = "TurnSuffocate";
1265
1298
  MiotError2[MiotError2["RobotLifted"] = 18] = "RobotLifted";
1266
- MiotError2[MiotError2["TaskComplete"] = 68] = "TaskComplete";
1267
- MiotError2[MiotError2["ManualMopInstallRequired"] = 74] = "ManualMopInstallRequired";
1268
- MiotError2[MiotError2["WastewaterTankFull"] = 105] = "WastewaterTankFull";
1269
- MiotError2[MiotError2["CleanWaterTankEmpty"] = 107] = "CleanWaterTankEmpty";
1270
- MiotError2[MiotError2["WashboardFilterNeedsCleaning"] = 114] = "WashboardFilterNeedsCleaning";
1271
- MiotError2[MiotError2["MopPadsMissing"] = 120] = "MopPadsMissing";
1299
+ MiotError2[MiotError2["ChargerGet"] = 19] = "ChargerGet";
1272
1300
  MiotError2[MiotError2["BatteryLow"] = 20] = "BatteryLow";
1273
1301
  MiotError2[MiotError2["ChargeFault"] = 21] = "ChargeFault";
1274
1302
  MiotError2[MiotError2["BatteryPercentageAnomaly"] = 22] = "BatteryPercentageAnomaly";
1303
+ MiotError2[MiotError2["Heart"] = 23] = "Heart";
1304
+ MiotError2[MiotError2["CameraOcclusion"] = 24] = "CameraOcclusion";
1305
+ MiotError2[MiotError2["Move"] = 25] = "Move";
1306
+ MiotError2[MiotError2["FlowShielding"] = 26] = "FlowShielding";
1307
+ MiotError2[MiotError2["InfraredShielding"] = 27] = "InfraredShielding";
1275
1308
  MiotError2[MiotError2["ChargeNoElectric"] = 28] = "ChargeNoElectric";
1276
1309
  MiotError2[MiotError2["BatteryFault"] = 29] = "BatteryFault";
1310
+ MiotError2[MiotError2["FanSpeedError"] = 30] = "FanSpeedError";
1311
+ MiotError2[MiotError2["LeftWheelSpeed"] = 31] = "LeftWheelSpeed";
1312
+ MiotError2[MiotError2["RightWheelSpeed"] = 32] = "RightWheelSpeed";
1313
+ MiotError2[MiotError2["Bmi055Acce"] = 33] = "Bmi055Acce";
1314
+ MiotError2[MiotError2["Bmi055Gyro"] = 34] = "Bmi055Gyro";
1315
+ MiotError2[MiotError2["Xv7001"] = 35] = "Xv7001";
1316
+ MiotError2[MiotError2["LeftMagnet"] = 36] = "LeftMagnet";
1317
+ MiotError2[MiotError2["RightMagnet"] = 37] = "RightMagnet";
1318
+ MiotError2[MiotError2["FlowError"] = 38] = "FlowError";
1319
+ MiotError2[MiotError2["InfraredFault"] = 39] = "InfraredFault";
1320
+ MiotError2[MiotError2["CameraFault"] = 40] = "CameraFault";
1321
+ MiotError2[MiotError2["StrongMagnet"] = 41] = "StrongMagnet";
1322
+ MiotError2[MiotError2["WaterPump"] = 42] = "WaterPump";
1323
+ MiotError2[MiotError2["Rtc"] = 43] = "Rtc";
1324
+ MiotError2[MiotError2["AutoKeyTrig"] = 44] = "AutoKeyTrig";
1325
+ MiotError2[MiotError2["P3v3"] = 45] = "P3v3";
1326
+ MiotError2[MiotError2["CameraIdle"] = 46] = "CameraIdle";
1327
+ MiotError2[MiotError2["Blocked"] = 47] = "Blocked";
1328
+ MiotError2[MiotError2["LdsError"] = 48] = "LdsError";
1329
+ MiotError2[MiotError2["LdsBumper"] = 49] = "LdsBumper";
1330
+ MiotError2[MiotError2["WaterPump2"] = 50] = "WaterPump2";
1331
+ MiotError2[MiotError2["FilterBlocked"] = 51] = "FilterBlocked";
1332
+ MiotError2[MiotError2["Edge"] = 54] = "Edge";
1333
+ MiotError2[MiotError2["Carpet"] = 55] = "Carpet";
1334
+ MiotError2[MiotError2["Laser"] = 56] = "Laser";
1335
+ MiotError2[MiotError2["Edge2"] = 57] = "Edge2";
1336
+ MiotError2[MiotError2["Ultrasonic"] = 58] = "Ultrasonic";
1337
+ MiotError2[MiotError2["NoGoZone"] = 59] = "NoGoZone";
1338
+ MiotError2[MiotError2["Route"] = 61] = "Route";
1339
+ MiotError2[MiotError2["Route2"] = 62] = "Route2";
1340
+ MiotError2[MiotError2["Blocked2"] = 63] = "Blocked2";
1341
+ MiotError2[MiotError2["Blocked3"] = 64] = "Blocked3";
1342
+ MiotError2[MiotError2["Restricted"] = 65] = "Restricted";
1343
+ MiotError2[MiotError2["Restricted2"] = 66] = "Restricted2";
1344
+ MiotError2[MiotError2["Restricted3"] = 67] = "Restricted3";
1345
+ MiotError2[MiotError2["TaskComplete"] = 68] = "TaskComplete";
1346
+ MiotError2[MiotError2["MopRemoved"] = 69] = "MopRemoved";
1347
+ MiotError2[MiotError2["MopRemoved2"] = 70] = "MopRemoved2";
1348
+ MiotError2[MiotError2["MopPadStopRotate"] = 71] = "MopPadStopRotate";
1349
+ MiotError2[MiotError2["MopPadStopRotate2"] = 72] = "MopPadStopRotate2";
1350
+ MiotError2[MiotError2["ManualMopInstallRequired"] = 74] = "ManualMopInstallRequired";
1277
1351
  MiotError2[MiotError2["LowBatteryTurnOff"] = 75] = "LowBatteryTurnOff";
1352
+ MiotError2[MiotError2["DirtyTankNotInstalled"] = 76] = "DirtyTankNotInstalled";
1353
+ MiotError2[MiotError2["RobotInHiddenRoom"] = 78] = "RobotInHiddenRoom";
1354
+ MiotError2[MiotError2["LdsFailedToLift"] = 79] = "LdsFailedToLift";
1278
1355
  MiotError2[MiotError2["RobotStuck"] = 80] = "RobotStuck";
1279
1356
  MiotError2[MiotError2["RobotStuckRepeat"] = 81] = "RobotStuckRepeat";
1357
+ MiotError2[MiotError2["SlipperyFloor"] = 82] = "SlipperyFloor";
1358
+ MiotError2[MiotError2["UnknownError"] = 84] = "UnknownError";
1359
+ MiotError2[MiotError2["CheckMopInstall"] = 85] = "CheckMopInstall";
1360
+ MiotError2[MiotError2["DirtyWaterTankFull"] = 86] = "DirtyWaterTankFull";
1361
+ MiotError2[MiotError2["RetractableLegStuck"] = 88] = "RetractableLegStuck";
1362
+ MiotError2[MiotError2["InternalError"] = 89] = "InternalError";
1280
1363
  MiotError2[MiotError2["RobotStuck2"] = 90] = "RobotStuck2";
1281
1364
  MiotError2[MiotError2["RobotStuckOnTables"] = 91] = "RobotStuckOnTables";
1282
1365
  MiotError2[MiotError2["RobotStuckOnPassage"] = 92] = "RobotStuckOnPassage";
@@ -1287,19 +1370,82 @@ var MiotError = /* @__PURE__ */ ((MiotError2) => {
1287
1370
  MiotError2[MiotError2["RobotStuckOnPet"] = 97] = "RobotStuckOnPet";
1288
1371
  MiotError2[MiotError2["RobotStuckOnSlipperySurface"] = 98] = "RobotStuckOnSlipperySurface";
1289
1372
  MiotError2[MiotError2["RobotStuckOnCarpet"] = 99] = "RobotStuckOnCarpet";
1290
- MiotError2[MiotError2["RobotStuckOnCurtain"] = 200] = "RobotStuckOnCurtain";
1291
1373
  MiotError2[MiotError2["BinFull"] = 101] = "BinFull";
1374
+ MiotError2[MiotError2["BinOpen"] = 102] = "BinOpen";
1375
+ MiotError2[MiotError2["BinOpen2"] = 103] = "BinOpen2";
1376
+ MiotError2[MiotError2["BinFull2"] = 104] = "BinFull2";
1377
+ MiotError2[MiotError2["WastewaterTankFull"] = 105] = "WastewaterTankFull";
1378
+ MiotError2[MiotError2["DirtyWaterTank"] = 106] = "DirtyWaterTank";
1379
+ MiotError2[MiotError2["CleanWaterTankEmpty"] = 107] = "CleanWaterTankEmpty";
1380
+ MiotError2[MiotError2["DirtyWaterTank2"] = 108] = "DirtyWaterTank2";
1381
+ MiotError2[MiotError2["DirtyWaterTankBlocked"] = 109] = "DirtyWaterTankBlocked";
1382
+ MiotError2[MiotError2["DirtyWaterTankPump"] = 110] = "DirtyWaterTankPump";
1383
+ MiotError2[MiotError2["MopPad"] = 111] = "MopPad";
1384
+ MiotError2[MiotError2["WetMopPad"] = 112] = "WetMopPad";
1385
+ MiotError2[MiotError2["WashboardFilterNeedsCleaning"] = 114] = "WashboardFilterNeedsCleaning";
1386
+ MiotError2[MiotError2["CleanTankLevel"] = 116] = "CleanTankLevel";
1292
1387
  MiotError2[MiotError2["StationDisconnected"] = 117] = "StationDisconnected";
1388
+ MiotError2[MiotError2["DirtyTankLevel"] = 118] = "DirtyTankLevel";
1389
+ MiotError2[MiotError2["WashboardLevel"] = 119] = "WashboardLevel";
1390
+ MiotError2[MiotError2["MopPadsMissing"] = 120] = "MopPadsMissing";
1293
1391
  MiotError2[MiotError2["DustBagFull"] = 121] = "DustBagFull";
1392
+ MiotError2[MiotError2["UnknownWarning"] = 122] = "UnknownWarning";
1393
+ MiotError2[MiotError2["SelfTestFailed"] = 123] = "SelfTestFailed";
1394
+ MiotError2[MiotError2["WashboardNotWorking"] = 124] = "WashboardNotWorking";
1395
+ MiotError2[MiotError2["DrainageFailed"] = 125] = "DrainageFailed";
1396
+ MiotError2[MiotError2["MopNotDetected"] = 126] = "MopNotDetected";
1397
+ MiotError2[MiotError2["MopHolderError"] = 127] = "MopHolderError";
1398
+ MiotError2[MiotError2["DockError"] = 128] = "DockError";
1399
+ MiotError2[MiotError2["WashFailed"] = 129] = "WashFailed";
1400
+ MiotError2[MiotError2["RobotStuckOnCurtain"] = 200] = "RobotStuckOnCurtain";
1401
+ MiotError2[MiotError2["EdgeMopStopRotate"] = 201] = "EdgeMopStopRotate";
1402
+ MiotError2[MiotError2["EdgeMopDetached"] = 202] = "EdgeMopDetached";
1403
+ MiotError2[MiotError2["ChassisLiftMalfunction"] = 203] = "ChassisLiftMalfunction";
1404
+ MiotError2[MiotError2["InternalError2"] = 207] = "InternalError2";
1405
+ MiotError2[MiotError2["MopCoverError"] = 209] = "MopCoverError";
1406
+ MiotError2[MiotError2["RollerMopError"] = 210] = "RollerMopError";
1407
+ MiotError2[MiotError2["OnboardWaterTankEmpty"] = 213] = "OnboardWaterTankEmpty";
1408
+ MiotError2[MiotError2["OnboardDirtyWaterTankFull"] = 214] = "OnboardDirtyWaterTankFull";
1409
+ MiotError2[MiotError2["MopNotInstalled"] = 215] = "MopNotInstalled";
1410
+ MiotError2[MiotError2["RollerMopError2"] = 218] = "RollerMopError2";
1411
+ MiotError2[MiotError2["FluffingRollerError"] = 222] = "FluffingRollerError";
1412
+ MiotError2[MiotError2["MopCoverError2"] = 223] = "MopCoverError2";
1413
+ MiotError2[MiotError2["BlockedByObstacle"] = 226] = "BlockedByObstacle";
1414
+ MiotError2[MiotError2["ReturnToChargeFailed"] = 1e3] = "ReturnToChargeFailed";
1294
1415
  return MiotError2;
1295
1416
  })(MiotError || {});
1296
1417
  var TaskStatus = /* @__PURE__ */ ((TaskStatus2) => {
1418
+ TaskStatus2[TaskStatus2["Completed"] = 0] = "Completed";
1297
1419
  TaskStatus2[TaskStatus2["InterruptedOrPaused"] = 1] = "InterruptedOrPaused";
1298
1420
  TaskStatus2[TaskStatus2["Active"] = 2] = "Active";
1299
1421
  TaskStatus2[TaskStatus2["Transitioning"] = 3] = "Transitioning";
1422
+ TaskStatus2[TaskStatus2["SpotCleaning"] = 4] = "SpotCleaning";
1423
+ TaskStatus2[TaskStatus2["FastMapping"] = 5] = "FastMapping";
1300
1424
  TaskStatus2[TaskStatus2["OnDockIdle"] = 6] = "OnDockIdle";
1425
+ TaskStatus2[TaskStatus2["ZoneCleaningPaused"] = 7] = "ZoneCleaningPaused";
1426
+ TaskStatus2[TaskStatus2["SegmentCleaningPaused"] = 8] = "SegmentCleaningPaused";
1427
+ TaskStatus2[TaskStatus2["SpotCleaningPaused"] = 9] = "SpotCleaningPaused";
1428
+ TaskStatus2[TaskStatus2["MapCleaningPaused"] = 10] = "MapCleaningPaused";
1429
+ TaskStatus2[TaskStatus2["DockingPaused"] = 11] = "DockingPaused";
1301
1430
  TaskStatus2[TaskStatus2["TransientPauseEdge"] = 12] = "TransientPauseEdge";
1431
+ TaskStatus2[TaskStatus2["SegmentMoppingPaused"] = 13] = "SegmentMoppingPaused";
1302
1432
  TaskStatus2[TaskStatus2["NeedsIntervention"] = 14] = "NeedsIntervention";
1433
+ TaskStatus2[TaskStatus2["AutoMoppingPaused"] = 15] = "AutoMoppingPaused";
1434
+ TaskStatus2[TaskStatus2["AutoDockingPaused"] = 16] = "AutoDockingPaused";
1435
+ TaskStatus2[TaskStatus2["SegmentDockingPaused"] = 17] = "SegmentDockingPaused";
1436
+ TaskStatus2[TaskStatus2["ZoneDockingPaused"] = 18] = "ZoneDockingPaused";
1437
+ TaskStatus2[TaskStatus2["CruisingPath"] = 20] = "CruisingPath";
1438
+ TaskStatus2[TaskStatus2["CruisingPathPaused"] = 21] = "CruisingPathPaused";
1439
+ TaskStatus2[TaskStatus2["CruisingPoint"] = 22] = "CruisingPoint";
1440
+ TaskStatus2[TaskStatus2["CruisingPointPaused"] = 23] = "CruisingPointPaused";
1441
+ TaskStatus2[TaskStatus2["SummonCleanPaused"] = 24] = "SummonCleanPaused";
1442
+ TaskStatus2[TaskStatus2["ReturningInstallMop"] = 25] = "ReturningInstallMop";
1443
+ TaskStatus2[TaskStatus2["ReturningRemoveMop"] = 26] = "ReturningRemoveMop";
1444
+ TaskStatus2[TaskStatus2["StationCleaning"] = 27] = "StationCleaning";
1445
+ TaskStatus2[TaskStatus2["PetFinding"] = 30] = "PetFinding";
1446
+ TaskStatus2[TaskStatus2["AutoCleaningWashingPaused"] = 31] = "AutoCleaningWashingPaused";
1447
+ TaskStatus2[TaskStatus2["AreaCleaningWashingPaused"] = 32] = "AreaCleaningWashingPaused";
1448
+ TaskStatus2[TaskStatus2["CustomCleaningWashingPaused"] = 33] = "CustomCleaningWashingPaused";
1303
1449
  return TaskStatus2;
1304
1450
  })(TaskStatus || {});
1305
1451
 
@@ -2436,6 +2582,18 @@ var VacuumDevice = class _VacuumDevice extends BaseDevice {
2436
2582
  get vacuumCapabilities() {
2437
2583
  return this.#caps;
2438
2584
  }
2585
+ /**
2586
+ * The suction levels this model supports, as a {@link SuctionLevel} enum array
2587
+ * (from the capability record). Lets a consumer see which fan speeds are
2588
+ * selectable without reaching into {@link vacuumCapabilities}.
2589
+ */
2590
+ get supportedSuctionLevels() {
2591
+ return this.#caps.supportedSuctionLevels;
2592
+ }
2593
+ /** The water/mop volumes this model supports, as a {@link WaterVolume} enum array. */
2594
+ get supportedWaterVolumes() {
2595
+ return this.#caps.supportedWaterVolumes;
2596
+ }
2439
2597
  #num(siid, piid) {
2440
2598
  return asNum(this.getProperty(siid, piid)?.value);
2441
2599
  }
@@ -2612,11 +2770,11 @@ var VacuumDevice = class _VacuumDevice extends BaseDevice {
2612
2770
  }
2613
2771
  this.#requireCap(this.#caps.canCleanPerRoom, "cleanZones", "per-room cleaning");
2614
2772
  const { repeats, fan, water } = this.#resolveCleanOpts(opts);
2615
- const areas = zones.map((z3) => [
2616
- Math.round(z3.x0),
2617
- Math.round(z3.y0),
2618
- Math.round(z3.x1),
2619
- Math.round(z3.y1),
2773
+ const areas = zones.map((z4) => [
2774
+ Math.round(z4.x0),
2775
+ Math.round(z4.y0),
2776
+ Math.round(z4.x1),
2777
+ Math.round(z4.y1),
2620
2778
  repeats,
2621
2779
  fan,
2622
2780
  water
@@ -2798,6 +2956,83 @@ var MowerTaskStatus = /* @__PURE__ */ ((MowerTaskStatus2) => {
2798
2956
  MowerTaskStatus2[MowerTaskStatus2["SpotIncomplete"] = 7] = "SpotIncomplete";
2799
2957
  return MowerTaskStatus2;
2800
2958
  })(MowerTaskStatus || {});
2959
+ var MowerFault = /* @__PURE__ */ ((MowerFault2) => {
2960
+ MowerFault2[MowerFault2["NoDeviceCode"] = 0] = "NoDeviceCode";
2961
+ MowerFault2[MowerFault2["Tilted"] = 1] = "Tilted";
2962
+ MowerFault2[MowerFault2["Trapped"] = 2] = "Trapped";
2963
+ MowerFault2[MowerFault2["NarrowPathToStation"] = 3] = "NarrowPathToStation";
2964
+ MowerFault2[MowerFault2["LeftWheel"] = 4] = "LeftWheel";
2965
+ MowerFault2[MowerFault2["RightWheel"] = 5] = "RightWheel";
2966
+ MowerFault2[MowerFault2["LiftMotor"] = 6] = "LiftMotor";
2967
+ MowerFault2[MowerFault2["Cutter"] = 7] = "Cutter";
2968
+ MowerFault2[MowerFault2["SidedMotor"] = 8] = "SidedMotor";
2969
+ MowerFault2[MowerFault2["CrashPlate"] = 9] = "CrashPlate";
2970
+ MowerFault2[MowerFault2["Charging"] = 10] = "Charging";
2971
+ MowerFault2[MowerFault2["BatteryOverheat"] = 11] = "BatteryOverheat";
2972
+ MowerFault2[MowerFault2["LidarCovered"] = 12] = "LidarCovered";
2973
+ MowerFault2[MowerFault2["LidarOverheatWithoutMap"] = 13] = "LidarOverheatWithoutMap";
2974
+ MowerFault2[MowerFault2["LidarOverheatWithMap"] = 14] = "LidarOverheatWithMap";
2975
+ MowerFault2[MowerFault2["LidarOverheat"] = 15] = "LidarOverheat";
2976
+ MowerFault2[MowerFault2["LidarDirty"] = 16] = "LidarDirty";
2977
+ MowerFault2[MowerFault2["LidarAbnormal"] = 17] = "LidarAbnormal";
2978
+ MowerFault2[MowerFault2["LocationWeak"] = 18] = "LocationWeak";
2979
+ MowerFault2[MowerFault2["LocationLost"] = 19] = "LocationLost";
2980
+ MowerFault2[MowerFault2["Sensor"] = 20] = "Sensor";
2981
+ MowerFault2[MowerFault2["InForbiddenArea"] = 21] = "InForbiddenArea";
2982
+ MowerFault2[MowerFault2["OutOfMap"] = 22] = "OutOfMap";
2983
+ MowerFault2[MowerFault2["EmergencyStop"] = 23] = "EmergencyStop";
2984
+ MowerFault2[MowerFault2["BatteryLow"] = 24] = "BatteryLow";
2985
+ MowerFault2[MowerFault2["MapFileCrack"] = 25] = "MapFileCrack";
2986
+ MowerFault2[MowerFault2["AwayFromMap"] = 26] = "AwayFromMap";
2987
+ MowerFault2[MowerFault2["HumanDetected"] = 27] = "HumanDetected";
2988
+ MowerFault2[MowerFault2["BladeLoss"] = 28] = "BladeLoss";
2989
+ MowerFault2[MowerFault2["StationLoss"] = 29] = "StationLoss";
2990
+ MowerFault2[MowerFault2["MaintainLoss"] = 30] = "MaintainLoss";
2991
+ MowerFault2[MowerFault2["BackChargeFailed"] = 31] = "BackChargeFailed";
2992
+ MowerFault2[MowerFault2["DockingFailed"] = 32] = "DockingFailed";
2993
+ MowerFault2[MowerFault2["LocatingFailedWithMap"] = 33] = "LocatingFailedWithMap";
2994
+ MowerFault2[MowerFault2["LocatingFailedWithoutMap"] = 34] = "LocatingFailedWithoutMap";
2995
+ MowerFault2[MowerFault2["LocatingAbnormal"] = 35] = "LocatingAbnormal";
2996
+ MowerFault2[MowerFault2["TaskStartFailed"] = 36] = "TaskStartFailed";
2997
+ MowerFault2[MowerFault2["PathImpassable"] = 37] = "PathImpassable";
2998
+ MowerFault2[MowerFault2["LidarDirtyWarning"] = 38] = "LidarDirtyWarning";
2999
+ MowerFault2[MowerFault2["CamDirty"] = 39] = "CamDirty";
3000
+ MowerFault2[MowerFault2["CamAbnormal"] = 40] = "CamAbnormal";
3001
+ MowerFault2[MowerFault2["CamCover"] = 41] = "CamCover";
3002
+ MowerFault2[MowerFault2["BatteryOverheatWarning"] = 42] = "BatteryOverheatWarning";
3003
+ MowerFault2[MowerFault2["BatteryTempLow"] = 43] = "BatteryTempLow";
3004
+ MowerFault2[MowerFault2["AutobuildBorder"] = 44] = "AutobuildBorder";
3005
+ MowerFault2[MowerFault2["AutobuildSide"] = 45] = "AutobuildSide";
3006
+ MowerFault2[MowerFault2["BorderFinish"] = 46] = "BorderFinish";
3007
+ MowerFault2[MowerFault2["NewMap"] = 47] = "NewMap";
3008
+ MowerFault2[MowerFault2["TaskFinish"] = 48] = "TaskFinish";
3009
+ MowerFault2[MowerFault2["DestinationNotReachable"] = 49] = "DestinationNotReachable";
3010
+ MowerFault2[MowerFault2["TaskStart"] = 50] = "TaskStart";
3011
+ MowerFault2[MowerFault2["CruiseStart"] = 51] = "CruiseStart";
3012
+ MowerFault2[MowerFault2["PointAndGoStart"] = 52] = "PointAndGoStart";
3013
+ MowerFault2[MowerFault2["ScheduleStart"] = 53] = "ScheduleStart";
3014
+ MowerFault2[MowerFault2["BatteryLowReturning"] = 54] = "BatteryLowReturning";
3015
+ MowerFault2[MowerFault2["BatteryLowScheduleSuspend"] = 55] = "BatteryLowScheduleSuspend";
3016
+ MowerFault2[MowerFault2["BadWeatherProtecting"] = 56] = "BadWeatherProtecting";
3017
+ MowerFault2[MowerFault2["RainScheduleInterupted"] = 57] = "RainScheduleInterupted";
3018
+ MowerFault2[MowerFault2["RainScheduleSuspend"] = 58] = "RainScheduleSuspend";
3019
+ MowerFault2[MowerFault2["ForzenReturning"] = 59] = "ForzenReturning";
3020
+ MowerFault2[MowerFault2["FrozenScheduleSuspend"] = 60] = "FrozenScheduleSuspend";
3021
+ MowerFault2[MowerFault2["NotDisturbReturning"] = 61] = "NotDisturbReturning";
3022
+ MowerFault2[MowerFault2["NotDisturbScheduleSuspend"] = 62] = "NotDisturbScheduleSuspend";
3023
+ MowerFault2[MowerFault2["WorkingScheduleSuspend"] = 63] = "WorkingScheduleSuspend";
3024
+ MowerFault2[MowerFault2["RemoteControlingScheduleSuspend"] = 64] = "RemoteControlingScheduleSuspend";
3025
+ MowerFault2[MowerFault2["EmergencyStoppedScheduleSuspend"] = 65] = "EmergencyStoppedScheduleSuspend";
3026
+ MowerFault2[MowerFault2["TopCoverOpenScheduleSuspend"] = 66] = "TopCoverOpenScheduleSuspend";
3027
+ MowerFault2[MowerFault2["FaultModeScheduleSuspend"] = 67] = "FaultModeScheduleSuspend";
3028
+ MowerFault2[MowerFault2["ScheduleTimeout"] = 68] = "ScheduleTimeout";
3029
+ MowerFault2[MowerFault2["StationNotConnectedToWorkingArea"] = 69] = "StationNotConnectedToWorkingArea";
3030
+ MowerFault2[MowerFault2["ContinueFromBreakpoint"] = 70] = "ContinueFromBreakpoint";
3031
+ MowerFault2[MowerFault2["IdleTimeoutReturning"] = 71] = "IdleTimeoutReturning";
3032
+ MowerFault2[MowerFault2["PauseTimeoutReturning"] = 72] = "PauseTimeoutReturning";
3033
+ MowerFault2[MowerFault2["TopCoverOpen"] = 73] = "TopCoverOpen";
3034
+ return MowerFault2;
3035
+ })(MowerFault || {});
2801
3036
 
2802
3037
  // src/models/mower/decode.ts
2803
3038
  function isRecord(v) {
@@ -3477,6 +3712,12 @@ var STATUS = enumLookup(
3477
3712
  var CHARGING2 = enumLookup(
3478
3713
  Object.values(MowerChargingStatus).filter((v) => typeof v === "number")
3479
3714
  );
3715
+ var TASK_STATUS = enumLookup(
3716
+ Object.values(MowerTaskStatus).filter((v) => typeof v === "number")
3717
+ );
3718
+ var FAULT = enumLookup(
3719
+ Object.values(MowerFault).filter((v) => typeof v === "number")
3720
+ );
3480
3721
  var MowerDevice = class _MowerDevice extends BaseDevice {
3481
3722
  #caps;
3482
3723
  #fetchBatch;
@@ -3525,6 +3766,25 @@ var MowerDevice = class _MowerDevice extends BaseDevice {
3525
3766
  get taskStatusRaw() {
3526
3767
  return this.#num(MOWER_PROP.TASK_STATUS.siid, MOWER_PROP.TASK_STATUS.piid);
3527
3768
  }
3769
+ /**
3770
+ * TASK_STATUS (5:104) decoded to {@link MowerTaskStatus}, or null. The donor
3771
+ * names only code 7 (SpotIncomplete); codes 2/3/10/13 are documented "Unknown
3772
+ * task status" and intentionally surface as raw via {@link taskStatusRaw}.
3773
+ */
3774
+ get taskStatus() {
3775
+ return TASK_STATUS(this.taskStatusRaw);
3776
+ }
3777
+ get faultRaw() {
3778
+ return this.#num(MOWER_PROP.DEVICE_CODE.siid, MOWER_PROP.DEVICE_CODE.piid);
3779
+ }
3780
+ /**
3781
+ * DEVICE_CODE (2:2) decoded to a {@link MowerFault} (the donor's
3782
+ * BASE_DEVICE_CODES registry, 0..73), or null for a model-specific/undocumented
3783
+ * code — which still surfaces as the raw number via {@link faultRaw}.
3784
+ */
3785
+ get fault() {
3786
+ return FAULT(this.faultRaw);
3787
+ }
3528
3788
  /** Parsed scheduling task descriptor (2:50), or null. */
3529
3789
  get task() {
3530
3790
  return parseTaskDescriptor(
@@ -3599,7 +3859,7 @@ var MowerDevice = class _MowerDevice extends BaseDevice {
3599
3859
  if (zoneIds.length === 0) {
3600
3860
  throw new RangeError("startMowingZones: zoneIds must not be empty");
3601
3861
  }
3602
- return this.#sendTask(buildZonePayload(zoneIds.map((z3) => Math.trunc(z3))));
3862
+ return this.#sendTask(buildZonePayload(zoneIds.map((z4) => Math.trunc(z4))));
3603
3863
  }
3604
3864
  /** Edge / contour mowing (2:50 o:101). Contour ids are two-int pairs [[1,0]]. */
3605
3865
  async startMowingEdges(contourIds) {
@@ -3667,6 +3927,7 @@ var MowerDevice = class _MowerDevice extends BaseDevice {
3667
3927
  /** Props worth seeding on start() / polling — exported for the facade. */
3668
3928
  static DEFAULT_PROPS = [
3669
3929
  MOWER_PROP.STATUS,
3930
+ MOWER_PROP.DEVICE_CODE,
3670
3931
  MOWER_PROP.BATTERY,
3671
3932
  MOWER_PROP.CHARGING_STATUS,
3672
3933
  MOWER_PROP.TASK_STATUS,
@@ -3822,6 +4083,429 @@ var Nodreame = class extends TypedEmitter {
3822
4083
  await Promise.all(this.#devices.map((d) => d.applySession(session)));
3823
4084
  }
3824
4085
  };
4086
+
4087
+ // src/diagnostics/redact.ts
4088
+ var REDACTED = "[redacted]";
4089
+ var SENSITIVE_KEY_FRAGMENTS = [
4090
+ // identity / secrets
4091
+ "did",
4092
+ "uid",
4093
+ "token",
4094
+ // accessToken, refreshToken, refresh_token, token_type stripped too (safe)
4095
+ "mac",
4096
+ "serial",
4097
+ "email",
4098
+ "account",
4099
+ "password",
4100
+ "passwd",
4101
+ "secret",
4102
+ "authorization",
4103
+ "auth",
4104
+ "credential",
4105
+ "apikey",
4106
+ "api_key",
4107
+ "clientid",
4108
+ "client_id",
4109
+ // location / PII
4110
+ "gps",
4111
+ "coordinate",
4112
+ "latitude",
4113
+ "longitude",
4114
+ "lat",
4115
+ "lon",
4116
+ "lng",
4117
+ "ssid",
4118
+ "wifi",
4119
+ "bssid",
4120
+ "ipaddr",
4121
+ "localip",
4122
+ "binddomain",
4123
+ "host",
4124
+ "address",
4125
+ "room",
4126
+ "area_name",
4127
+ "areaname",
4128
+ "segmentname",
4129
+ "segment_name",
4130
+ // map binary / geometry (location-revealing)
4131
+ "map_info",
4132
+ "mapinfo",
4133
+ "mapblob",
4134
+ // free-text device names that may carry PII. NOTE: the bare fragment `name` is
4135
+ // intentionally NOT listed — it would over-match the catalog's command `name`
4136
+ // field (an enum-derived, non-sensitive label). The specific custom-name
4137
+ // fields below cover every PII-bearing case.
4138
+ "customname",
4139
+ "devicename",
4140
+ "nickname"
4141
+ ];
4142
+ var EXACT_SENSITIVE_KEYS = /* @__PURE__ */ new Set(["ip"]);
4143
+ function isSensitiveKey(key2) {
4144
+ const lower = key2.toLowerCase();
4145
+ if (EXACT_SENSITIVE_KEYS.has(lower)) {
4146
+ return true;
4147
+ }
4148
+ return SENSITIVE_KEY_FRAGMENTS.some((frag) => lower.includes(frag));
4149
+ }
4150
+ function isPlainObject(v) {
4151
+ return typeof v === "object" && v !== null && !Array.isArray(v);
4152
+ }
4153
+ function redact(value) {
4154
+ if (Array.isArray(value)) {
4155
+ return value.map((v) => redact(v));
4156
+ }
4157
+ if (isPlainObject(value)) {
4158
+ const out = {};
4159
+ for (const [k, v] of Object.entries(value)) {
4160
+ out[k] = isSensitiveKey(k) ? REDACTED : redact(v);
4161
+ }
4162
+ return out;
4163
+ }
4164
+ return value;
4165
+ }
4166
+
4167
+ // src/diagnostics/dump-format.ts
4168
+ import { z as z3 } from "zod";
4169
+ var DumpScalarSchema = z3.union([z3.string(), z3.number(), z3.boolean()]);
4170
+ var PropertyObservationSchema = z3.object({
4171
+ values: z3.array(DumpScalarSchema),
4172
+ unmapped: z3.array(DumpScalarSchema),
4173
+ enum: z3.string().optional(),
4174
+ count: z3.number(),
4175
+ firstSeen: z3.number(),
4176
+ lastSeen: z3.number()
4177
+ });
4178
+ var EventObservationSchema = z3.object({
4179
+ at: z3.number(),
4180
+ type: z3.string(),
4181
+ data: z3.unknown().optional()
4182
+ });
4183
+ var RawFrameSchema = z3.object({
4184
+ at: z3.number(),
4185
+ source: z3.string(),
4186
+ payload: z3.unknown()
4187
+ });
4188
+ var CommandSchema = z3.object({
4189
+ name: z3.string(),
4190
+ siid: z3.number().optional(),
4191
+ aiid: z3.number().optional()
4192
+ });
4193
+ var SensorSchema = z3.object({
4194
+ model: z3.string(),
4195
+ channel: z3.number().optional()
4196
+ });
4197
+ var DeviceDumpSchema = z3.object({
4198
+ schemaVersion: z3.literal(1),
4199
+ library: z3.union([z3.literal("nodedreame"), z3.literal("nodewitt")]),
4200
+ libraryVersion: z3.string(),
4201
+ device: z3.object({
4202
+ model: z3.string(),
4203
+ firmware: z3.string().optional(),
4204
+ region: z3.string().optional(),
4205
+ type: z3.string().optional()
4206
+ }),
4207
+ observations: z3.object({
4208
+ properties: z3.record(z3.string(), PropertyObservationSchema),
4209
+ events: z3.array(EventObservationSchema),
4210
+ rawFrames: z3.array(RawFrameSchema).optional()
4211
+ }),
4212
+ catalog: z3.object({
4213
+ commands: z3.array(CommandSchema).optional(),
4214
+ capabilities: z3.record(z3.string(), z3.unknown()).optional(),
4215
+ sensors: z3.array(SensorSchema).optional()
4216
+ }),
4217
+ meta: z3.object({
4218
+ startedAt: z3.number(),
4219
+ durationMs: z3.number(),
4220
+ generatedAt: z3.number()
4221
+ })
4222
+ });
4223
+
4224
+ // src/diagnostics/dumper.ts
4225
+ function commandsForFamily(family) {
4226
+ const commands = [];
4227
+ if (family === "vacuum") {
4228
+ for (const [name, ref] of Object.entries(VACUUM_ACTION)) {
4229
+ commands.push({ name, siid: ref.siid, aiid: ref.aiid });
4230
+ }
4231
+ } else if (family === "mower") {
4232
+ for (const [name, ref] of Object.entries(MOWER_ACTION)) {
4233
+ commands.push({ name, siid: ref.siid, aiid: ref.aiid });
4234
+ }
4235
+ }
4236
+ return commands;
4237
+ }
4238
+ function decoderFor(enumName, members) {
4239
+ const lookup = enumLookup(members);
4240
+ return { enumName, isMember: (raw) => lookup(raw) !== null };
4241
+ }
4242
+ function vacuumDecoders() {
4243
+ return {
4244
+ "2.1": decoderFor(
4245
+ "MiotState",
4246
+ Object.values(MiotState).filter((v) => typeof v === "number")
4247
+ ),
4248
+ "3.2": decoderFor(
4249
+ "ChargingStatus",
4250
+ Object.values(ChargingStatus).filter((v) => typeof v === "number")
4251
+ ),
4252
+ "4.4": decoderFor(
4253
+ "SuctionLevel",
4254
+ Object.values(SuctionLevel).filter((v) => typeof v === "number")
4255
+ ),
4256
+ "4.5": decoderFor(
4257
+ "WaterVolume",
4258
+ Object.values(WaterVolume).filter((v) => typeof v === "number")
4259
+ ),
4260
+ "2.6": decoderFor(
4261
+ "CleaningMode",
4262
+ Object.values(CleaningMode).filter((v) => typeof v === "number")
4263
+ ),
4264
+ "4.1": decoderFor(
4265
+ "TaskStatus",
4266
+ Object.values(TaskStatus).filter((v) => typeof v === "number")
4267
+ )
4268
+ };
4269
+ }
4270
+ function mowerDecoders() {
4271
+ return {
4272
+ "2.1": decoderFor(
4273
+ "MowerStatus",
4274
+ Object.values(MowerStatus).filter((v) => typeof v === "number")
4275
+ ),
4276
+ "3.2": decoderFor(
4277
+ "MowerChargingStatus",
4278
+ Object.values(MowerChargingStatus).filter(
4279
+ (v) => typeof v === "number"
4280
+ )
4281
+ ),
4282
+ "5.104": decoderFor(
4283
+ "MowerTaskStatus",
4284
+ Object.values(MowerTaskStatus).filter((v) => typeof v === "number")
4285
+ ),
4286
+ "2.2": decoderFor(
4287
+ "MowerFault",
4288
+ Object.values(MowerFault).filter((v) => typeof v === "number")
4289
+ )
4290
+ };
4291
+ }
4292
+ function toScalar(value) {
4293
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
4294
+ return value;
4295
+ }
4296
+ return null;
4297
+ }
4298
+ var PropertyAccumulator = class {
4299
+ #decoders;
4300
+ #entries = /* @__PURE__ */ new Map();
4301
+ constructor(decoders = {}) {
4302
+ this.#decoders = decoders;
4303
+ }
4304
+ record(siid, piid, rawValue, at) {
4305
+ const key2 = `${siid}.${piid}`;
4306
+ const scalar = toScalar(rawValue);
4307
+ let entry = this.#entries.get(key2);
4308
+ if (!entry) {
4309
+ entry = { values: [], unmapped: [], count: 0, firstSeen: at, lastSeen: at };
4310
+ this.#entries.set(key2, entry);
4311
+ }
4312
+ entry.count += 1;
4313
+ entry.lastSeen = at;
4314
+ if (scalar === null) {
4315
+ return;
4316
+ }
4317
+ if (!entry.values.includes(scalar)) {
4318
+ entry.values.push(scalar);
4319
+ }
4320
+ const decoder = this.#decoders[key2];
4321
+ if (decoder && typeof scalar === "number" && !decoder.isMember(scalar)) {
4322
+ if (!entry.unmapped.includes(scalar)) {
4323
+ entry.unmapped.push(scalar);
4324
+ }
4325
+ }
4326
+ }
4327
+ snapshot() {
4328
+ const out = {};
4329
+ for (const [key2, e] of this.#entries) {
4330
+ const decoder = this.#decoders[key2];
4331
+ const base = {
4332
+ values: [...e.values],
4333
+ unmapped: [...e.unmapped],
4334
+ count: e.count,
4335
+ firstSeen: e.firstSeen,
4336
+ lastSeen: e.lastSeen
4337
+ };
4338
+ out[key2] = decoder ? { ...base, enum: decoder.enumName } : base;
4339
+ }
4340
+ return out;
4341
+ }
4342
+ };
4343
+ var DEFAULT_REFRESH_INTERVAL_MS = 3e4;
4344
+ var DEFAULT_MAX_RAW_FRAMES = 500;
4345
+ var Dumper = class {
4346
+ #device;
4347
+ #opts;
4348
+ #acc;
4349
+ #events = [];
4350
+ #rawFrames = [];
4351
+ #catalog;
4352
+ #type;
4353
+ #onProperty;
4354
+ #onEvent;
4355
+ #timer = null;
4356
+ #startedAt = 0;
4357
+ #started = false;
4358
+ constructor(device, catalog, type, decoders, options = {}) {
4359
+ this.#device = device;
4360
+ this.#catalog = catalog;
4361
+ this.#type = type;
4362
+ this.#acc = new PropertyAccumulator(decoders);
4363
+ this.#opts = {
4364
+ captureRawFrames: options.captureRawFrames ?? false,
4365
+ maxRawFrames: options.maxRawFrames ?? DEFAULT_MAX_RAW_FRAMES,
4366
+ refreshIntervalMs: options.refreshIntervalMs ?? DEFAULT_REFRESH_INTERVAL_MS
4367
+ };
4368
+ this.#onProperty = (e) => {
4369
+ this.#acc.record(e.siid, e.piid, e.value, Date.now());
4370
+ this.#pushRaw("mqtt:property", e);
4371
+ };
4372
+ this.#onEvent = (e) => {
4373
+ this.#events.push({
4374
+ at: Date.now(),
4375
+ type: `${e.siid}.${e.eiid}`,
4376
+ data: { arguments: e.arguments }
4377
+ });
4378
+ this.#pushRaw("mqtt:event", e);
4379
+ };
4380
+ }
4381
+ /** Attach to the live stream + arm the periodic shadow refresh. Idempotent. */
4382
+ async start() {
4383
+ if (this.#started) {
4384
+ return;
4385
+ }
4386
+ this.#started = true;
4387
+ this.#startedAt = Date.now();
4388
+ this.#device.on("propertyChanged", this.#onProperty);
4389
+ this.#device.on("event", this.#onEvent);
4390
+ await this.#refresh();
4391
+ if (this.#opts.refreshIntervalMs > 0 && this.#device.refreshFromCache) {
4392
+ this.#timer = setInterval(() => void this.#refresh(), this.#opts.refreshIntervalMs);
4393
+ this.#timer.unref?.();
4394
+ }
4395
+ }
4396
+ /** Detach every listener + clear the timer. Idempotent. */
4397
+ stop() {
4398
+ if (!this.#started) {
4399
+ return Promise.resolve();
4400
+ }
4401
+ this.#started = false;
4402
+ if (this.#timer) {
4403
+ clearInterval(this.#timer);
4404
+ this.#timer = null;
4405
+ }
4406
+ this.#device.off("propertyChanged", this.#onProperty);
4407
+ this.#device.off("event", this.#onEvent);
4408
+ return Promise.resolve();
4409
+ }
4410
+ /** Build the anonymized, schema-valid dump. Works live or after {@link stop}. */
4411
+ export() {
4412
+ const now = Date.now();
4413
+ const dump = {
4414
+ schemaVersion: 1,
4415
+ library: "nodedreame",
4416
+ libraryVersion: LIBRARY_VERSION,
4417
+ device: {
4418
+ model: this.#device.model,
4419
+ type: this.#type
4420
+ },
4421
+ observations: {
4422
+ properties: this.#acc.snapshot(),
4423
+ events: [...this.#events],
4424
+ ...this.#opts.captureRawFrames ? { rawFrames: this.#redactFrames() } : {}
4425
+ },
4426
+ catalog: this.#catalog,
4427
+ meta: {
4428
+ startedAt: this.#startedAt,
4429
+ durationMs: Math.max(0, now - this.#startedAt),
4430
+ generatedAt: now
4431
+ }
4432
+ };
4433
+ const anonymized = redact(dump);
4434
+ return DeviceDumpSchema.parse(anonymized);
4435
+ }
4436
+ /** Deterministic pretty JSON of {@link export}. */
4437
+ exportJson() {
4438
+ return JSON.stringify(this.export(), null, 2);
4439
+ }
4440
+ async #refresh() {
4441
+ if (this.#device.refreshFromCache) {
4442
+ try {
4443
+ await this.#device.refreshFromCache();
4444
+ } catch {
4445
+ }
4446
+ }
4447
+ }
4448
+ #pushRaw(source, payload) {
4449
+ if (!this.#opts.captureRawFrames) {
4450
+ return;
4451
+ }
4452
+ this.#rawFrames.push({ at: Date.now(), source, payload });
4453
+ if (this.#rawFrames.length > this.#opts.maxRawFrames) {
4454
+ this.#rawFrames.shift();
4455
+ }
4456
+ }
4457
+ #redactFrames() {
4458
+ return this.#rawFrames.map((f) => ({ at: f.at, source: f.source, payload: redact(f.payload) }));
4459
+ }
4460
+ };
4461
+ function familyOf(device) {
4462
+ if (device instanceof VacuumDevice) {
4463
+ return "vacuum";
4464
+ }
4465
+ if (device instanceof MowerDevice) {
4466
+ return "mower";
4467
+ }
4468
+ if (!(device instanceof BaseDevice)) {
4469
+ if (device.model.startsWith("dreame.vacuum.")) {
4470
+ return "vacuum";
4471
+ }
4472
+ if (device.model.startsWith("dreame.mower.")) {
4473
+ return "mower";
4474
+ }
4475
+ }
4476
+ return "device";
4477
+ }
4478
+ function decodersFor(device) {
4479
+ switch (familyOf(device)) {
4480
+ case "vacuum":
4481
+ return vacuumDecoders();
4482
+ case "mower":
4483
+ return mowerDecoders();
4484
+ default:
4485
+ return {};
4486
+ }
4487
+ }
4488
+ function typeFor(device) {
4489
+ return familyOf(device);
4490
+ }
4491
+ function catalogFor(device) {
4492
+ return {
4493
+ commands: commandsForFamily(familyOf(device)),
4494
+ capabilities: { tokens: [...device.capabilities.list()] }
4495
+ };
4496
+ }
4497
+ function createDumper(target, options) {
4498
+ return new Dumper(
4499
+ target,
4500
+ catalogFor(target),
4501
+ typeFor(target),
4502
+ decodersFor(target),
4503
+ options ?? {}
4504
+ );
4505
+ }
4506
+ function createClientDumper(client, options) {
4507
+ return client.devices.map((d) => createDumper(d, options));
4508
+ }
3825
4509
  export {
3826
4510
  BaseDevice,
3827
4511
  ChargingStatus,
@@ -3840,6 +4524,7 @@ export {
3840
4524
  MowerChargingStatus,
3841
4525
  MowerControlAction,
3842
4526
  MowerDevice,
4527
+ MowerFault,
3843
4528
  MowerStatus,
3844
4529
  MowerTaskStatus,
3845
4530
  Nodreame,
@@ -3849,6 +4534,8 @@ export {
3849
4534
  VacuumCapabilityResolver,
3850
4535
  VacuumDevice,
3851
4536
  WaterVolume,
4537
+ createClientDumper,
4538
+ createDumper,
3852
4539
  getMowerCapabilities,
3853
4540
  getVacuumCapabilities,
3854
4541
  renderMowerSvg,