homebridge-roborock-matter 3.17.2 → 3.17.3

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.17.3
4
+
5
+ **Q7- and Q10-series robots no longer spend a cloud request per poll on an answer the plugin cannot read.** Reported with a diagnostics export by [@niclasreich](https://github.com/niclasreich) in [#14](https://github.com/mathiashornbek/homebridge-roborock-matter/issues/14), whose Q10 S5 (`roborock.vacuum.ss07`) logged `Failed to execute get_room_mapping … method prop.get timed out after 10 seconds` while the MQTT connection was reported as up.
6
+
7
+ The two method names in that line disagree, and that was the clue. `get_room_mapping` is the caller's label; `prop.get` is what actually went on the wire. The classic room-mapping routine opens by fetching `get_status` in order to read `map_status` and derive a floor number — and on these robots `get_status` translates to a real `prop.get`. `map_status` is a v1-only field that a Q7/Q10 status dictionary has never carried, so the reply could not have been used whatever it said. The request itself was already answered locally from the dialect's neutral table without touching the network, which is exactly why the existing skip did not catch this: the harmless call was making a second, expensive one.
8
+
9
+ The classic flow is now skipped outright for these robots, which is where their room data was never coming from in the first place — it arrives over the protobuf map channel. That removes one cloud round-trip per poll cycle per robot, along with the `No room mappings returned` notice and the empty room-list announcement that repeated at the same rate. Robots on the classic protocol are unaffected and still read `map_status` exactly as before.
10
+
11
+ **This does not by itself explain a robot that ignores commands from Apple Home**, which is the other half of that report; it removes a wasted request and the misleading error line it produced.
12
+
3
13
  ## 3.17.2
4
14
 
5
15
  **The Qrevo CurvX's dock can now offer the Empty Bin switch.** Reported with a diagnostics export, and then settled by hand, by [@jcoz00](https://github.com/jcoz00) in [#6](https://github.com/mathiashornbek/homebridge-roborock-matter/issues/6). His a185 reports `dock_type: 20`, and the dock table this plugin inherited stops at 9 — so the CurvX fell through to "unknown dock" and was treated as having no auto-empty capability, which kept the optional Empty Bin switch added in 3.17.0 from ever being offered for it. Dock type 20 is now a named, recognised auto-empty dock.
package/README.md CHANGED
@@ -37,7 +37,7 @@ This is the most feature-packed, most thoroughly engineered Roborock plugin for
37
37
  - 📍 **See where it's cleaning — live.** Apple Home shows _"Cleaning — Kitchen"_ with the room the robot is actually inside, updating as it moves from room to room. Works even for cleans started from the robot's button or the Roborock app. No other Homebridge plugin does this.
38
38
  - 🧭 **One robot, one tile — and as many robots as you own.** Sign in once and your whole fleet comes along: every vacuum on your account appears as its own clean, native accessory in Apple Home. No clutter of fake fans and helper switches, and rooms appear with the names you gave them in the Roborock app.
39
39
  - ⚡ **Fast and reliable.** Commands go directly to the robot over your own network whenever possible, with the Roborock cloud as automatic backup — and built-in diagnostics in the settings if you ever want to look under the hood.
40
- - 🛡️ **Verified by Homebridge.** Reviewed and endorsed by the Homebridge team. 1438 automated tests, zero known vulnerabilities, no analytics, and a startup designed to never crash your Homebridge — even when your Wi-Fi or the Roborock cloud has a bad day.
40
+ - 🛡️ **Verified by Homebridge.** Reviewed and endorsed by the Homebridge team. 1449 automated tests, zero known vulnerabilities, no analytics, and a startup designed to never crash your Homebridge — even when your Wi-Fi or the Roborock cloud has a bad day.
41
41
 
42
42
  ## Features
43
43
 
@@ -252,7 +252,7 @@ The complete path — robot → plugin → Homebridge → matter.js store — wa
252
252
 
253
253
  ## Contributing
254
254
 
255
- Model reports, diagnostics exports, and pull requests are very welcome. The codebase ships with 1438 tests (protocol fixtures verified against the [python-roborock](https://github.com/Python-roborock/python-roborock) reference), strict TypeScript checking, and CI across Node 22/24 × Homebridge 1.11/2.x — `npm test` before you push and you're set.
255
+ Model reports, diagnostics exports, and pull requests are very welcome. The codebase ships with 1449 tests (protocol fixtures verified against the [python-roborock](https://github.com/Python-roborock/python-roborock) reference), strict TypeScript checking, and CI across Node 22/24 × Homebridge 1.11/2.x — `npm test` before you push and you're set.
256
256
 
257
257
  ## Support the project
258
258
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "homebridge-roborock-matter",
3
- "version": "3.17.2",
3
+ "version": "3.17.3",
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": {
@@ -765,6 +765,19 @@ class vacuum {
765
765
  this.adapter.manageDeviceIntervals(duid);
766
766
  }
767
767
  } else if (parameter == "get_room_mapping") {
768
+ // Room data on B01/Q7 robots travels over the protobuf map channel,
769
+ // and `get_room_mapping` itself is answered from the dialect's neutral
770
+ // table without touching the network — so this branch looked free.
771
+ // It is not: it opens by fetching `get_status` to read `map_status`,
772
+ // a v1-only field that Q7 status dictionaries have never carried, and
773
+ // on B01 `get_status` translates to a real `prop.get`. That is one
774
+ // cloud round-trip per poll cycle per robot spent on an answer this
775
+ // code cannot read — reported under the caller's label, which is why
776
+ // #14's log line names `get_room_mapping` but times out on `prop.get`.
777
+ if (this.adapter.isB01Device?.(duid)) {
778
+ return;
779
+ }
780
+
768
781
  const deviceStatus = await sendParameterRequest("get_status", []);
769
782
  const mapStatus = Array.isArray(deviceStatus)
770
783
  ? deviceStatus[0]?.["map_status"]
@@ -982,9 +982,7 @@ class Roborock {
982
982
  }
983
983
 
984
984
  getRoomMappingsForDevice(duid) {
985
- if (
986
- this.getVacuumDeviceInfo(duid, "pv") === b01Q7Adapter.B01_PROTOCOL_VERSION
987
- ) {
985
+ if (this.isB01Device(duid)) {
988
986
  return this.getB01RoomCache(duid).map((room) => ({
989
987
  segmentId: room.roomId,
990
988
  mapId: 0,
@@ -1025,9 +1023,7 @@ class Roborock {
1025
1023
  // the canonical mapId 0. Reporting 0 here keeps the Matter room-clean
1026
1024
  // flow from attempting a map switch (load_multi_map has no Q7
1027
1025
  // equivalent) before sending the segment command.
1028
- if (
1029
- this.getVacuumDeviceInfo(duid, "pv") === b01Q7Adapter.B01_PROTOCOL_VERSION
1030
- ) {
1026
+ if (this.isB01Device(duid)) {
1031
1027
  return 0;
1032
1028
  }
1033
1029
 
@@ -2308,10 +2304,7 @@ class Roborock {
2308
2304
  this.vacuums[duid].getStatusIntervall = () => {
2309
2305
  // B01/Q7 status is owned by the dedicated 15s loop; the per-device
2310
2306
  // tick would only burn cycles hitting the attempt throttle.
2311
- if (
2312
- this.getVacuumDeviceInfo(duid, "pv") ===
2313
- b01Q7Adapter.B01_PROTOCOL_VERSION
2314
- ) {
2307
+ if (this.isB01Device(duid)) {
2315
2308
  return null;
2316
2309
  }
2317
2310
  this.clearInterval(this.vacuums[duid].getStatusIntervalHandle);
@@ -2396,9 +2389,7 @@ class Roborock {
2396
2389
  // with no electronic mop/water control, so Matter must never expose mop
2397
2390
  // modes for them regardless of what the generic cloud schema claims.
2398
2391
  // Suction (Q7 "wind") is controllable via the B01 adapter.
2399
- if (
2400
- this.getVacuumDeviceInfo(duid, "pv") === b01Q7Adapter.B01_PROTOCOL_VERSION
2401
- ) {
2392
+ if (this.isB01Device(duid)) {
2402
2393
  return {
2403
2394
  // Q7 robots mop with a manually filled tank: expose the mop/vacuum
2404
2395
  // mode switch, but never water-level status or control.
@@ -5070,6 +5061,22 @@ class Roborock {
5070
5061
  }
5071
5062
  }
5072
5063
 
5064
+ /**
5065
+ * True when this robot speaks the B01/Q7 dialect rather than classic v1.
5066
+ *
5067
+ * Four places wrote this comparison out by hand before it had a name, and
5068
+ * `vacuum.js` was about to need a fifth. It decides which wire protocol a
5069
+ * robot speaks, so it gets one spelling.
5070
+ *
5071
+ * @param {string} duid
5072
+ * @returns {boolean}
5073
+ */
5074
+ isB01Device(duid) {
5075
+ return (
5076
+ this.getVacuumDeviceInfo(duid, "pv") === b01Q7Adapter.B01_PROTOCOL_VERSION
5077
+ );
5078
+ }
5079
+
5073
5080
  /**
5074
5081
  * A device's name for log messages, falling back to the duid.
5075
5082
  *