homebridge-roborock-matter 3.28.0 → 3.30.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/CHANGELOG.md +119 -0
- package/README.md +10 -4
- package/config.schema.json +7 -1
- package/dist/hap_schedule_accessory.js +697 -89
- package/dist/hap_schedule_accessory.js.map +1 -1
- package/dist/hap_schedule_api.js +100 -0
- package/dist/hap_schedule_api.js.map +1 -1
- package/dist/matter_vacuum_accessory.js +120 -16
- package/dist/matter_vacuum_accessory.js.map +1 -1
- package/dist/platform.js +192 -15
- package/dist/platform.js.map +1 -1
- package/homebridge-ui/public/index.html +15 -1
- package/homebridge-ui/public/index.js +16 -0
- package/package.json +1 -1
- package/roborockLib/lib/hawkSignature.js +212 -0
- package/roborockLib/lib/parseCloudSceneSchedules.js +77 -0
- package/roborockLib/lib/redactSecrets.js +88 -0
- package/roborockLib/lib/unansweredMethodBreaker.js +227 -0
- package/roborockLib/lib/vacuum.js +1 -1
- package/roborockLib/roborockAPI.js +424 -53
- package/test-support/operational-state-writes.js +61 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,124 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 3.30.0
|
|
4
|
+
|
|
5
|
+
**The water-tank notification that repeated every two minutes was us. Three people reported it, and for three releases this project told them it was Apple.**
|
|
6
|
+
|
|
7
|
+
### The bug, and the measurement that had been wrong since 3.14.0
|
|
8
|
+
|
|
9
|
+
#5 (Wazza151, a70), #9 (vp-debug12, a75, with the screenshot and the Spanish wording) and #26 (n0rt0nthec4t, Q Revo S) all reported the same thing: with the clean-water tank empty, the Home app repeats _"fill the water tank — <robot> will start cleaning when the tank is filled"_ roughly every 2 minutes.
|
|
10
|
+
|
|
11
|
+
The answer here was that Apple re-raises a standing block and nothing on this side can stop it. That answer had a measurement behind it, which is why it survived so long: writing the same `{ errorStateId: 68 }` three times in a row produces one change event, so the plugin could not be the source. The measurement was correct. **The premise was not.** It was taken against `@matter/main` **0.18.0-alpha**. Homebridge 2.4.0 ships **0.17.9**, and 0.17.9 does not behave the same way.
|
|
12
|
+
|
|
13
|
+
Measured on 17 Sep 2026 against 0.17.9, one attribute at a time, with a standing `operationalError: 68`:
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
operationalState, same value (0x42) ....... 68 -> 0 WIPED
|
|
17
|
+
operationalState, different value (0x41) .. 68 -> 0 WIPED
|
|
18
|
+
currentPhase, same value .................. 68 -> 68 kept
|
|
19
|
+
currentPhase, different value ............. 68 -> 68 kept
|
|
20
|
+
phaseList ................................. 68 -> 68 kept
|
|
21
|
+
operationalStateList ...................... 68 -> 68 kept
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
**Any write of `operationalState` clears `operationalError`, including a write of the value already stored.** This plugin's 60-second heartbeat re-writes the whole cluster as a self-healing safety net, so every minute it was clearing the tank fault and re-raising it — and matter.js emits the cluster's `OperationalError` event on the `0 -> 68` edge. Six heartbeats produced six attribute changes and three events: one roughly every two minutes.
|
|
25
|
+
|
|
26
|
+
That is the notification. It was not Apple re-raising a block. It was the plugin raising it again, sixty times an hour.
|
|
27
|
+
|
|
28
|
+
### The fix
|
|
29
|
+
|
|
30
|
+
`operationalState` and `operationalError` are now written in separate transactions, error last, and **an unchanged `operationalState` is not written at all** — the one place where the forced heartbeat is deliberately overruled, because forcing it there can only wipe the fault. Re-measured with the rule in place: 20 heartbeats with a standing tank fault produce **0 attribute changes and 0 events**. Clearing the tank and emptying it again still produce exactly one each, and a genuine state change still re-asserts the fault, because matter.js really did clear it.
|
|
31
|
+
|
|
32
|
+
If you turned `enableMatterTankFaultReporting` off to stop the notifications, you can turn it back on.
|
|
33
|
+
|
|
34
|
+
### A robot that stops answering is left alone
|
|
35
|
+
|
|
36
|
+
A Roborock request that draws no reply costs a full 10-second pending request, and nothing here noticed that the same request had failed the same way a hundred times before. Measured on robots that were otherwise working perfectly:
|
|
37
|
+
|
|
38
|
+
- `Stueetage` (`a70`) on my own server: `get_map_v1` had failed **95 times in a row** when I looked, and 225 twelve days earlier. That robot has never answered the request; it was asked every ten seconds of every clean regardless.
|
|
39
|
+
- #9 (`a75`): 40 in a row, while the robot answered everything else.
|
|
40
|
+
- #22 (`a144`) and #24 (`a51`): **647** suppressed timeout warnings in a single session, across seven different methods.
|
|
41
|
+
|
|
42
|
+
There is now one register that counts consecutive no-answers per robot per method. Six in a row and that one request is left alone for six hours, then tried once more; one answer puts it straight back. A permanently silent method costs **9 requests a day instead of 8,640**.
|
|
43
|
+
|
|
44
|
+
Three things it deliberately never does. It never trips on a **refusal** — a robot that answers "I do not support that" has answered, and conflating the two would hide a real reply behind a silence. It never trips on a **transport error** — `EAI_AGAIN`, a dropped MQTT link or "not connected" is the network's problem and it comes back on its own. And it is **not wired to `get_status` or to the command path**: the Home tile lives on `get_status`, and a command you just pressed must always be sent.
|
|
45
|
+
|
|
46
|
+
When it does give up it says so once, in full sentences, and writes it into the diagnostic report — so "this robot stopped answering X" survives in something you can paste, rather than only in a log line that scrolled past hours ago.
|
|
47
|
+
|
|
48
|
+
### Unchecking the switch settings now actually removes the tiles
|
|
49
|
+
|
|
50
|
+
From #22, in the reporter's words: _"When unchecking schedules / routines, the cache does not get deleted. So, although unchecked, tiles still appear in HomeKit."_
|
|
51
|
+
|
|
52
|
+
He was right. The removal walked the coordinators that run had built — a list that is **empty at startup**, because they are built further down the same function, after the branch that handles the setting being off returns. So on the restart after unchecking the box, the only thing holding the tiles — the accessory Homebridge restored from its own cache — was never looked at. The switches went on working because Homebridge had restored them, and the setting appeared to do nothing.
|
|
53
|
+
|
|
54
|
+
The other half of the same report: _"initially I had schedules checked. Then I checked routines and got the error. There were still only tiles for schedules. After that I reset the whole plugin and had tiles for both."_ Registration only ever happened on the path that **creates** a coordinator. One that survived took the reuse path on the next sync, and the reuse path registered nothing — switches were added to an accessory the bridge no longer knew about. Resetting the plugin worked because it emptied the cache and forced the creation path.
|
|
55
|
+
|
|
56
|
+
Both halves are fixed, and both are pinned by tests that use a cached accessory rather than a fresh one, because that is the case that was broken.
|
|
57
|
+
|
|
58
|
+
### iOS 27
|
|
59
|
+
|
|
60
|
+
Released 14 September. The Home changes are cameras, Apple Intelligence summaries, 4K HomeKit Secure Video, energy monitoring, Apple TV, Thread 1.4 and a simplified Matter configuration interface. **Nothing documented touches robot vacuums, the RVC clusters or bridges.**
|
|
61
|
+
|
|
62
|
+
Measured rather than assumed, on my own hardware after updating: `Subscription … reported invalid by peer` still fired nine times in three minutes on 16 September, and the only "reestablished" lines followed a Homebridge restart. So the hope in #7 that iOS 27 would fix the stuck "Updating…" tile is **not** supported by what my own controller does. Nothing in this release depends on iOS 27, and nothing in it is needed by it.
|
|
63
|
+
|
|
64
|
+
### Smaller things
|
|
65
|
+
|
|
66
|
+
- **Renaming a Routine in the Roborock app** now says, once, that the new name reached Homebridge and that the Home app keeps the name it stored when the switch first appeared — so a stale name in Apple Home has a visible reason and a one-second fix, instead of looking like the rename was lost (#22).
|
|
67
|
+
- **"No room mappings returned"** now says what to do about it: the usual reason is that the rooms on the map have not been named yet. Open the Roborock app, edit the map, name each room. From #25, which the reporter closed himself with exactly that discovery.
|
|
68
|
+
- **The Q7 fault list was left alone on purpose.** Eight days of measurement suggested widening the informational set from `{0, 407, 2100, 2102}` to eleven codes. Two guard tests refused it — one says 501 is not shared across B01 families, the other says codes upstream cannot explain must keep surfacing, because silencing them would be a guess. On inspection the unmapped-code notice already logs once per code per session, so the noise was a fraction of what it looked like, and the guards were right. The change was reverted. That is what those tests are for.
|
|
69
|
+
|
|
70
|
+
## 3.29.0
|
|
71
|
+
|
|
72
|
+
**Schedules that live on your Routines, Routines you can run from Apple Home — and a debug log that is safe to paste.**
|
|
73
|
+
|
|
74
|
+
### The last measurement in #22, and what it said
|
|
75
|
+
|
|
76
|
+
3.27.0 asked the two remaining candidate routes which methods they take, with a positive and a negative control so the answer would mean something. The reporter ran it, and the reading was clean on all 4 lines:
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
OPTIONS user/scene → the resource allows: POST,OPTIONS
|
|
80
|
+
OPTIONS user/scene/<id>/enable → the resource allows: PUT,OPTIONS
|
|
81
|
+
OPTIONS user/scene/device/<duid> (positive control) → the resource allows: GET,HEAD,OPTIONS
|
|
82
|
+
OPTIONS user/scene/<id>/no-such-subresource-control (negative control) → 400, no Allow
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
The positive control described a route this run had already read, and the negative control stayed silent — so a `PUT` on `enable` is a real reading, not the server handing out headers to anything. That named a verb and a route. It did not name a payload, and I said in that thread I would not guess one against somebody else's account.
|
|
86
|
+
|
|
87
|
+
So I measured it against **mine**. I have 6 Routines on my S8 Pro Ultra, 2 of them on timers, and the account API is the same one the reporter's robot talks to. In order, each step read back before the next:
|
|
88
|
+
|
|
89
|
+
- `PUT user/scene/<id>/param` with the Routine's own param object, unchanged, as a JSON body → `success:true`. The server re-created the trigger under a new id and changed nothing else. **That is the no-op write I promised.**
|
|
90
|
+
- `PUT user/scene/<id>/enable` with a JSON body → `400 parameter.error`. With a **form** body `enabled=true` → `success:true`, nothing changed (it was already on). With `enabled=false` → the scene-level `enabled` went false; the timer's own flag did not move. Set back to true, confirmed.
|
|
91
|
+
- `PUT …/param` with the TIMER trigger's nested `enabled` set to false → the flag went false, the action came back byte for byte, the scene-level flag stayed true — **exactly the change the reporter's app made when he switched a schedule off**. Set back to true, confirmed.
|
|
92
|
+
|
|
93
|
+
Two routes, two shapes, both measured on the route the feature needs. The `Allow` gate did not retire: every write still asks the route which verbs it takes before the first write of a session, and a route that stops offering `PUT` stops being written to. `DELETE` — the one verb the singular scene resource offers — is not sent by anything in this plugin, and a test reads the source to keep it that way.
|
|
94
|
+
|
|
95
|
+
### Why no write ever worked before, and why this one does
|
|
96
|
+
|
|
97
|
+
Every request to the account API is signed over 7 slots, and this plugin — like the ioBroker adapter it descends from — signed the last 2 empty. Right for every bodiless GET and POST it made; fatal for any write with a body, which the cloud answers with `401 auth.err.invalid.token`. The body slot is now `md5` of the exact bytes sent, which is python-roborock's formula and the one the mock server in `Python-roborock/local_roborock_server` verifies against; a form body hashes as the sorted `k=v&k=v` string. Query strings stay unused — my measurement of the query slot came back 401, so whatever the app does there, the 2 open-source implementations do not know it either, and no route here needs one.
|
|
98
|
+
|
|
99
|
+
### Schedules on Routines, in the same accessory
|
|
100
|
+
|
|
101
|
+
A robot that refuses `get_server_timer` with `-10007 "Not FCC robot"` — the Saros 10R in #22 — is now recognised as saying where **not** to look: the device-side list is not asked again that session, the refusal is 1 info line instead of a warning every refresh, and the schedules are read from the account's Routines instead. A timer-driven Routine appears in the existing `<robot> Schedules` accessory as a switch **named after the Routine** (`Saugen+`, `Hinten`, `Vorne`); device-side schedules keep their `Schedule 1`, `Schedule 2` numbering, and adding a Routine never renumbers them.
|
|
102
|
+
|
|
103
|
+
The switch shows what the app's own schedule toggle shows: Routine enabled **and** timer enabled. Off rewrites the Routine's param with the timer flag false — from a **fresh** reading of the Routine, never the cached one, because the write replaces the whole param and a room list edited in the app 3 minutes earlier would otherwise be reverted by a switch that meant to change 1 flag. On sets it true, and re-enables the Routine itself if the app had disabled it at Routine level. Verification is the same read-back the device-side switches have always had; there is no `upd_timer` fallback for a Routine, because there is no second route to fall back to.
|
|
104
|
+
|
|
105
|
+
Two sources on one robot are read together. A source that fails on the first refresh after a restart fails the refresh as a whole, as before — the alternative would have been applying the other source's list and deleting every switch the failed source owns. A source that fails later keeps its previous reading while the other is applied. A `4xx` from the Routine route (a robot shared from another account, say) is remembered for the session like a refusal, and the device-side switches carry on.
|
|
106
|
+
|
|
107
|
+
### Routines as switches
|
|
108
|
+
|
|
109
|
+
New, optional, off by default: **Add Home app Routine switches** gives each robot a `<robot> Routines` accessory with 1 momentary switch per Routine you created in the app, named as in the app. On sends the same `execute` the app's play button sends — the 1 scene write every open-source client agrees on — and the switch turns itself off 1.5 s later, like the action switches. `Hey Siri, turn on Saugen+` runs it; a Home automation can run a Routine the way it runs a scene. The accessory is registered only once it has a switch to show and unregistered when a trustworthy reading says there are none, so an empty tile never appears. The reporter said he would rather run his Routines from HomeKit than keep the app's schedules; this is that.
|
|
110
|
+
|
|
111
|
+
### The debug log no longer prints your local keys
|
|
112
|
+
|
|
113
|
+
The `HomeData notifyDeviceUpdater:` debug line printed the cloud's home data whole — and that payload carries every robot's `localKey` (the AES key for the LAN protocol) and serial number. Users are asked to paste debug logs into issues, and 3 such logs were public in #22 before I read one closely enough. The line now goes through a redactor that masks `localKey`, `sn`, the account token and the whole `rriot` signing block, including inside the JSON-in-a-string the state actually arrives as. If you posted a debug log from an earlier version somewhere public, consider removing it.
|
|
114
|
+
|
|
115
|
+
### Housekeeping
|
|
116
|
+
|
|
117
|
+
- The debug probe from 3.23–3.27 asks 1 more `OPTIONS` (`/param`), so a pasted log shows both write routes' `Allow` headers.
|
|
118
|
+
- `homebridge-ui`: a Routines checkbox next to Schedules; `config.schema.json`: `enableHomeKitRoutineSwitches`.
|
|
119
|
+
|
|
120
|
+
85 new tests: the signature against an independent implementation of the formula and through a real axios instance; the param builder on the real Routine shapes; the gated writes; the 2-source refresh, the refusal, the 4xx, the fresh-read-before-write; the Routines accessory; the redaction; the platform registration. Run against 3.28.0, 3 of them pass and 82 fail or cannot load.
|
|
121
|
+
|
|
3
122
|
## 3.28.0
|
|
4
123
|
|
|
5
124
|
**Startup and network traffic, measured rather than felt.**
|
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.
|
|
40
|
+
- 🛡️ **Verified by Homebridge.** Reviewed and endorsed by the Homebridge team. 1998 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
|
|
|
@@ -46,7 +46,8 @@ This is the most feature-packed, most thoroughly engineered Roborock plugin for
|
|
|
46
46
|
| 🤖 **Full control from Apple Home** | Start, stop, pause and send the robot home to its dock — from the Home app or Siri |
|
|
47
47
|
| 🕹️ **Switches for automations** | Optional per-robot Start Cleaning, Return to Dock, Pause and Find switches — Apple Home does not offer a dock action for a Matter vacuum ([details](#automations-in-apple-home)) |
|
|
48
48
|
| 🎯 **Sensors as automation triggers** | Optional per-robot Docked, Cleaning and Water Tank Empty contact sensors — a Matter vacuum is not offered as an automation trigger at all, and a contact sensor is ([details](#automations-in-apple-home)) |
|
|
49
|
-
| 🗓️ **Roborock schedules as switches** | Optional per-robot switches that turn the schedules you made in the Roborock app on and off ([details](#automations-in-apple-home))
|
|
49
|
+
| 🗓️ **Roborock schedules as switches** | Optional per-robot switches that turn the schedules you made in the Roborock app on and off — device-side ones and the timers on your Routines ([details](#automations-in-apple-home)) |
|
|
50
|
+
| ▶️ **Routines as switches** | Optional per-robot momentary switches that run a Routine from the Roborock app, so Siri and Home automations can start one by name ([details](#automations-in-apple-home)) |
|
|
50
51
|
| 🚪 **Clean specific rooms** | Pick rooms right in Apple Home, with the names you gave them in the Roborock app — multi-floor homes included |
|
|
51
52
|
| 📍 **Live room tracking** | See which room the robot is cleaning right now, updated as it moves ([details](#live-room-tracking)) |
|
|
52
53
|
| 📊 **Honest cleaning progress** | Each room goes pending → cleaning → done — and a room only counts as done when the robot was actually there |
|
|
@@ -196,7 +197,11 @@ Docked and Cleaning are more useful together than either alone, and that is the
|
|
|
196
197
|
|
|
197
198
|
**Optional Home app schedule switches reach the schedules Apple Home cannot see.** The schedules you build in the Roborock app — weekday mornings, the Saturday whole-home run — are invisible to Apple Home, so an automation cannot suspend one when you are away or on holiday. Turn on **Add Home app schedule switches** and each robot gets a grouped `Vicky Schedules` accessory holding one switch per schedule on your account. Off disables that schedule on the Roborock side; on enables it again. These switches are not momentary: each one shows whether its schedule is currently active, which is the point.
|
|
198
199
|
|
|
199
|
-
**They enable and disable, they do not author.** Days, times, rooms and clean modes stay in the Roborock app, because that is where those settings live and a switch cannot express them. A schedule deleted in the Roborock app takes its switch with it on the next refresh, and a new one gains a switch the same way.
|
|
200
|
+
**They enable and disable, they do not author.** Days, times, rooms and clean modes stay in the Roborock app, because that is where those settings live and a switch cannot express them. A schedule deleted in the Roborock app takes its switch with it on the next refresh, and a new one gains a switch the same way. Device-side schedules are named positionally — `Vicky Schedule 1`, `Vicky Schedule 2` — because the Roborock cloud does not give them names to borrow; rename them in the Home app if the order is not enough to tell them apart.
|
|
201
|
+
|
|
202
|
+
**Schedules that live on your Routines are read too.** Newer robots — a Saros 10R, for one — refuse the device-side schedule list outright (`-10007 "Not FCC robot"`) and keep every schedule you see in the app as a timer on a Routine, on your Roborock account. Those appear in the same `Vicky Schedules` accessory, named after the Routine (`Saugen+`, `Hinten`), and the switch shows what the app's own schedule toggle shows. Switching one off rewrites that Routine's timer exactly as the app does when you tap its toggle, from a fresh reading of the Routine so nothing you edited in the app moments earlier is lost; switching one on re-enables the Routine itself too if it had been disabled at Routine level. Every write is gated on the cloud route's own `Allow` header, and nothing here ever deletes a Routine. Measured on my own account before it shipped; the whole story is in [#22](https://github.com/mathiashornbek/homebridge-roborock-matter/issues/22).
|
|
203
|
+
|
|
204
|
+
**Optional Routine switches run a Routine from Apple Home.** Turn on **Add Home app Routine switches** and each robot gets a grouped `Vicky Routines` accessory holding one momentary switch per Routine you created in the Roborock app, named as in the app. Turning a switch on sends the same request as the app's play button and the switch turns itself off again after a moment — so `Hey Siri, turn on Saugen+` runs it, and a Home automation can run a Routine the way it runs a scene. Creating and editing Routines stays in the Roborock app. Requested in [#22](https://github.com/mathiashornbek/homebridge-roborock-matter/issues/22).
|
|
200
205
|
|
|
201
206
|
**A cloud hiccup does not delete your tiles.** If the schedule refresh fails, the switches are kept and their handlers reattached rather than unregistered — a failed request is not evidence that your schedules are gone, and an accessory that vanishes takes its room assignment, its name and every automation pointing at it along. Requested in [#3](https://github.com/mathiashornbek/homebridge-roborock-matter/issues/3) and contributed by [@pponce](https://github.com/pponce).
|
|
202
207
|
|
|
@@ -253,12 +258,13 @@ The complete path — robot → plugin → Homebridge → matter.js store — wa
|
|
|
253
258
|
- **Pairing fails with "Accessory not found", and the robot works fine in the Homebridge UI:** that combination is a network path, not a plugin fault — the robot is running, the plugin is publishing, and only the phone cannot reach the node it is being asked to commission. **Try the pairing again with the phone on your 2.4 GHz SSID.** That, and nothing else, is what fixed it for the reporter in [#21](https://github.com/mathiashornbek/homebridge-roborock-matter/issues/21) after both codes had failed repeatedly: routers that keep the bands on separate segments, or that run client isolation on one of them, break commissioning while leaving every other symptom looking healthy. Worth checking in the same pass: the phone and Homebridge on the same subnet, IPv6 enabled on the router, and an Apple TV or HomePod present as a home hub. See also [the switches and sensors need their own pairing](#the-switches-and-sensors-need-their-own-pairing--a-different-qr-code) if you are unsure which of the QR codes you are scanning.
|
|
254
259
|
- **Apple Home shows Manufacturer "Homebridge", and the Model row repeats the robot's _name_:** that is a Homebridge version, not a plugin setting, and there is nothing to configure here. The plugin hands Homebridge `Roborock` plus the real model name for every robot, but for an _external_ Matter accessory — which every robot vacuum is — Homebridge `2.4.0` and earlier hardcode the vendor name and derive the product name from the display name instead (the `basicInformation` block in `dist/matter/server/ServerLifecycle.js`). Fixed upstream in [homebridge/homebridge#3996](https://github.com/homebridge/homebridge/pull/3996) and shipping since `homebridge@2.4.1-beta.3`, where that same block reads the plugin's values whenever the node is external. **Nothing needs re-pairing when you get there:** both attributes are Fixed quality in Matter and are therefore never persisted, so the correct values simply apply on the next restart. The **Serial Number** and **Firmware** rows are unaffected and are already correct on `2.4.0` — the serial is the one Roborock has on file for that robot, falling back to its internal device id if your account carries none.
|
|
255
260
|
- **The Roborock app does not appear on the accessory page in Apple Home, and no plugin change can put it there:** Apple keys that card to the Matter **Vendor ID** in the node's attestation certificate, not to the Manufacturer row above it. Homebridge commissions every node with the Matter _test_ vendor ID `0xFFF1` (`DEFAULT_VENDOR_ID` in `dist/matter/server/ServerConfig.js`; it appears as `vendorId=65521` in the pairing log line), because an uncertified node may not claim a certified manufacturer's ID. Getting the card would take Roborock certifying this bridge, not a setting. The Manufacturer row is free text and unrelated to the ID, which is exactly why that one is fixable and this one is not.
|
|
261
|
+
- **A debug log is safe to paste since 3.29.0:** the home-data dump in the debug log used to carry each robot's local AES key and serial number; both are masked now (`<redacted>`), along with the account token and its signing block. If you posted a debug log from an earlier version somewhere public, consider removing it.
|
|
256
262
|
- **Debug logging needs two switches, not one:** the plugin's own **Debug Mode** only decides whether it _calls_ the debug logger — Homebridge decides whether anything is _printed_, and it suppresses plugin debug output unless Homebridge itself runs with `-D`. Turn on **Homebridge Settings → Homebridge Debug Mode** as well, or the log will look exactly the same as before.
|
|
257
263
|
- **Startup without network:** the plugin retries the Roborock cloud with increasing backoff (up to 10 attempts) and never crash-loops Homebridge; wrong credentials stop cleanly with a clear log message.
|
|
258
264
|
|
|
259
265
|
## Contributing
|
|
260
266
|
|
|
261
|
-
Model reports, diagnostics exports, and pull requests are very welcome. The codebase ships with
|
|
267
|
+
Model reports, diagnostics exports, and pull requests are very welcome. The codebase ships with 1998 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.
|
|
262
268
|
|
|
263
269
|
## Support the project
|
|
264
270
|
|
package/config.schema.json
CHANGED
|
@@ -145,7 +145,13 @@
|
|
|
145
145
|
},
|
|
146
146
|
"enableHomeKitScheduleSwitches": {
|
|
147
147
|
"title": "Add Home app schedule switches",
|
|
148
|
-
"description": "Publishes one grouped \"<robot> Schedules\" accessory per robot, holding one switch for each schedule you created in the Roborock app. Turning a switch off disables that schedule on your Roborock account; turning it on enables it again — so an Apple Home automation or Siri can suspend the weekday clean without opening the Roborock app. The switches only enable and disable existing schedules; creating and editing them stays in the Roborock app, because that is where the days, times and rooms live. Requested in issue #3. Off by default, because turning it on adds accessories to your Home app. IMPORTANT — THESE NEED THEIR OWN PAIRING, exactly like the action switches above: the robot reaches Apple Home over Matter, but these are HomeKit accessories on this plugin's Homebridge child bridge, which is paired separately. Go to Plugins -> homebridge-roborock-matter -> the three-dot menu -> Child Bridge Config, make sure Enable HAP is ON, restart, then press Connect to HomeKit on that same screen and scan THAT QR code.",
|
|
148
|
+
"description": "Publishes one grouped \"<robot> Schedules\" accessory per robot, holding one switch for each schedule you created in the Roborock app — both the device-side schedules older robots keep and the timers on the app's Routines, which is where newer robots such as the Saros 10R keep every schedule (issue #22). Turning a switch off disables that schedule on your Roborock account; turning it on enables it again — so an Apple Home automation or Siri can suspend the weekday clean without opening the Roborock app. The switches only enable and disable existing schedules; creating and editing them stays in the Roborock app, because that is where the days, times and rooms live. Requested in issue #3. Off by default, because turning it on adds accessories to your Home app. IMPORTANT — THESE NEED THEIR OWN PAIRING, exactly like the action switches above: the robot reaches Apple Home over Matter, but these are HomeKit accessories on this plugin's Homebridge child bridge, which is paired separately. Go to Plugins -> homebridge-roborock-matter -> the three-dot menu -> Child Bridge Config, make sure Enable HAP is ON, restart, then press Connect to HomeKit on that same screen and scan THAT QR code.",
|
|
149
|
+
"type": "boolean",
|
|
150
|
+
"default": false
|
|
151
|
+
},
|
|
152
|
+
"enableHomeKitRoutineSwitches": {
|
|
153
|
+
"title": "Add Home app Routine switches",
|
|
154
|
+
"description": "Publishes one grouped \"<robot> Routines\" accessory per robot, holding one momentary switch for each Routine you created in the Roborock app. Turning a switch on runs that Routine — the same request the app's play button sends — and the switch turns itself off again after a moment, so Siri can start a Routine by its name and an Apple Home automation can run one the way it runs a scene (issue #22). Creating and editing Routines stays in the Roborock app. Off by default, because turning it on adds accessories to your Home app, and it needs the same child-bridge pairing as the schedule switches above. Requires the Home app switches master setting.",
|
|
149
155
|
"type": "boolean",
|
|
150
156
|
"default": false
|
|
151
157
|
},
|