homebridge-roborock-matter 3.4.7 → 3.4.8

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/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.4.8
4
+
5
+ **Selecting "Vacuum" and getting a vacuum-and-mop was not a display bug — one timed-out command cancelled the one that mattered.** skmzwanke reported in [#8](https://github.com/mathiashornbek/homebridge-roborock-matter/issues/8) that he selected Vacuum for a single room and the robot mopped it anyway, and his 3.4.5 log names the cause outright.
6
+
7
+ On a v1 robot the difference between "Vacuum" and "Vacuum and mop" **is** the water-box mode: choosing Vacuum sends water-box OFF. Fan power only picks a suction level within the chosen mode. The prep sequence sent fan power first and, if that command timed out, returned — so the water command was never sent at all. In his log, `set_custom_mode` timed out after two seconds, `set_water_box_custom_mode` never appeared, and the robot kept the mopping setting it already had from the Roborock app. A cosmetic command that did not answer in time cancelled the one carrying the user's actual choice.
8
+
9
+ - **The water command now goes out first, and no command in the sequence is cancelled by another's failure.** Dropping the early return cannot delay the start: the caller already races the whole prep against its own timeout, so the early return was buying latency protection that was paid for one level up.
10
+ - **A partial apply is now announced at warn level**, naming the robot and what was not confirmed. It was a debug line before, which meant that on a default log level the robot simply did the wrong job in silence while the Matter tile reported the mode that had been selected. That mismatch took two rounds of #8 to pin down.
11
+ - **The rule is enumerated over the sequence, not over the two commands in it today:** no clean-mode prep command may return out of the middle of the sequence. A third setting added later is covered by construction.
12
+
3
13
  ## 3.4.7
4
14
 
5
15
  **The diagnostic report told Q7 owners their robot had tried to reach the LAN and failed. It never tried.** Following [#7](https://github.com/mathiashornbek/homebridge-roborock-matter/issues/7), jawnlydon unpaired his robot from Apple Home, uninstalled the plugin, reinstalled it and paired fresh — and his report still read `markedRemote: true`, `remoteReason: marked-remote-after-connect-failure`, `connectionStatus: Cloud fallback`, "usually because LAN TCP was not connected at that moment". His `roborock.vacuum.sc05` speaks the B01 protocol, which has no LAN request surface at all: the plugin marks these robots cloud-only at startup precisely so it never opens a local socket to them. Every line above described a network fault that could not occur, and he spent an evening chasing it.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "homebridge-roborock-matter",
3
- "version": "3.4.7",
3
+ "version": "3.4.8",
4
4
  "description": "The most complete Roborock plugin for Apple Home. Supports the entire Roborock lineup — from the classic S-series to the new 2025 Q7 series that no other plugin can control. Sign in with your Roborock account and get native start/stop, room cleaning, suction levels, battery, and live 'cleaning in the kitchen' room tracking. Verified by Homebridge.",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -2355,6 +2355,49 @@ class Roborock {
2355
2355
  return;
2356
2356
  }
2357
2357
 
2358
+ // The water command goes first, and no failure below cancels a later
2359
+ // command.
2360
+ //
2361
+ // On a v1 robot the difference between "Vacuum" and "Vacuum and mop" IS
2362
+ // the water-box mode: selecting Vacuum sends water-box OFF. Fan power is a
2363
+ // suction level *within* the chosen mode. The fan command used to run
2364
+ // first and, on timeout, return — skipping the water command entirely. So
2365
+ // skmzwanke selected Vacuum in Apple Home, the fan command timed out after
2366
+ // two seconds, the water command was never sent, and his Saros 10 ran a
2367
+ // vacuum-and-mop over the room he had asked to be vacuumed (#8). A
2368
+ // cosmetic command that did not answer in time cancelled the one that
2369
+ // carried the user's actual choice.
2370
+ //
2371
+ // Dropping the early return cannot run the start command late: the caller
2372
+ // races this whole sequence against its own prep timeout, which is what
2373
+ // bounds the delay. The early return was buying latency protection that
2374
+ // was already paid for one level up.
2375
+ const failedCommands = [];
2376
+
2377
+ if (Number.isInteger(settings?.waterBoxMode)) {
2378
+ const waterCommands = this.getMatterWaterModeCommandCandidates(duid);
2379
+
2380
+ if (waterCommands.length === 0) {
2381
+ this.log.debug(
2382
+ `Matter clean mode requested water mode ${settings.waterBoxMode} for ${duid}, but no supported Roborock water command was detected.`
2383
+ );
2384
+ } else {
2385
+ try {
2386
+ await this.runFirstMatterSettingCommand(
2387
+ duid,
2388
+ waterCommands,
2389
+ settings.waterBoxMode,
2390
+ commandOptions
2391
+ );
2392
+ } catch (error) {
2393
+ failedCommands.push("water mode");
2394
+ this.log.debug(
2395
+ `Matter clean mode water commands failed for ${duid}; continuing with start command. ${error.message || error}`
2396
+ );
2397
+ }
2398
+ }
2399
+ }
2400
+
2358
2401
  if (
2359
2402
  Number.isInteger(settings?.fanPower) &&
2360
2403
  this.getMatterCleanModeCapabilities(duid).canControlFanPower
@@ -2372,40 +2415,21 @@ class Roborock {
2372
2415
  "set_custom_mode",
2373
2416
  error
2374
2417
  );
2375
- if (this.isMatterSettingTimeoutError(error)) {
2376
- this.log.debug(
2377
- `Matter clean mode fan command timed out for ${duid}; skipping remaining clean-mode prep and continuing with start command. ${error.message || error}`
2378
- );
2379
- return;
2380
- }
2418
+ failedCommands.push("suction level");
2381
2419
  this.log.debug(
2382
2420
  `Matter clean mode fan command failed for ${duid}; continuing with start command. ${error.message || error}`
2383
2421
  );
2384
2422
  }
2385
2423
  }
2386
2424
 
2387
- if (!Number.isInteger(settings?.waterBoxMode)) {
2388
- return;
2389
- }
2390
-
2391
- const waterCommands = this.getMatterWaterModeCommandCandidates(duid);
2392
- if (waterCommands.length === 0) {
2393
- this.log.debug(
2394
- `Matter clean mode requested water mode ${settings.waterBoxMode} for ${duid}, but no supported Roborock water command was detected.`
2395
- );
2396
- return;
2397
- }
2398
-
2399
- try {
2400
- await this.runFirstMatterSettingCommand(
2401
- duid,
2402
- waterCommands,
2403
- settings.waterBoxMode,
2404
- commandOptions
2405
- );
2406
- } catch (error) {
2407
- this.log.debug(
2408
- `Matter clean mode water commands failed for ${duid}; continuing with start command. ${error.message || error}`
2425
+ // At warn level on purpose. The clean is about to start and the Matter
2426
+ // tile will report the mode the user selected, so a silent partial apply
2427
+ // leaves the tile stating something the robot is not doing. That mismatch
2428
+ // is exactly what took two rounds of #8 to pin down, and the log is where
2429
+ // the next person will look.
2430
+ if (failedCommands.length > 0) {
2431
+ this.log.warn(
2432
+ `Roborock did not confirm the ${failedCommands.join(" and ")} for ${this.describeDevice(duid)} before starting; the robot may keep its previous settings for this run, so the clean may not match the mode selected in your controller.`
2409
2433
  );
2410
2434
  }
2411
2435
  }
@@ -2521,11 +2545,6 @@ class Roborock {
2521
2545
  ].some((pattern) => message.includes(pattern));
2522
2546
  }
2523
2547
 
2524
- isMatterSettingTimeoutError(error) {
2525
- const message = `${error?.message || error || ""}`.toLowerCase();
2526
- return message.includes("request") && message.includes("timed out after");
2527
- }
2528
-
2529
2548
  /**
2530
2549
  * Self-healing capability detection for periodic poll commands: once a
2531
2550
  * robot definitively answers a request with an "unsupported"-class error,