homebridge-roborock-matter 2.9.1 → 2.9.2
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 +5 -0
- package/README.md +1 -1
- package/docs/issue-3958-reply.md +29 -0
- package/docs/matter-battery-issue-draft.md +57 -66
- package/package.json +1 -1
- package/roborockLib/lib/deviceFeatures.js +16 -0
- package/roborockLib/roborockAPI.js +8 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.9.2
|
|
4
|
+
|
|
5
|
+
- **Max+ ("Grundig"/"Deep Clean") suction mode now announced on the S8 Pro Ultra.** Field report from a re-paired fleet: the S8 Pro Ultra only showed four suction levels because Max+ was gated to B01/Q7. The classic gate now uses the upstream-vetted per-model feature data (`set_custom_mode_max_plus` in the model's action list) — currently confirming the S8 Pro Ultra (`a70`); further models are added as feature data or field reports with diagnostics exports confirm the level. NOTE: the robot must be re-paired once for the new mode to appear (Matter locks the mode list at commissioning).
|
|
6
|
+
- Battery documentation corrected after upstream verification on homebridge#3958: `batPercentRemaining` is quality **Q (quieter)** as of Matter 1.4 (reports ARE sent via subscription, 10 s throttle) — a spec-compliant controller applies them; Apple Home in steady state does not. No plugin architecture change needed; the bridge already does the right thing.
|
|
7
|
+
|
|
3
8
|
## 2.9.1
|
|
4
9
|
|
|
5
10
|
Deep performance pass over the live-room hot paths, with honest before/after measurements.
|
package/README.md
CHANGED
|
@@ -96,7 +96,7 @@ Everything is configurable from the Homebridge UI. The essentials:
|
|
|
96
96
|
|
|
97
97
|
## Battery percentage in Apple Home
|
|
98
98
|
|
|
99
|
-
Apple Home renders the battery percentage from pairing time and
|
|
99
|
+
Apple Home renders the battery percentage from pairing time and refreshes it only on a fresh read (commissioning, hub restart) — while charging state on the very same cluster updates live. This is a controller-side limitation, not a plugin bug, and it is being investigated upstream with the Homebridge team ([homebridge#3958](https://github.com/homebridge/homebridge/issues/3958)). Current state of knowledge: as of Matter 1.4 the attribute carries the **"quieter" (Q)** reporting quality — reports ARE sent over the subscription (rate-limited to one per 10 s), a Homebridge maintainer verified that a spec-compliant matter.js controller receives and applies them, yet Apple Home in steady state does not. The likely permanent fix is on Apple's side (Apple Feedback).
|
|
100
100
|
|
|
101
101
|
<details>
|
|
102
102
|
<summary>The full evidence chain and workarounds</summary>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Svar til bwp91 på homebridge#3958 — klar til at poste
|
|
2
|
+
|
|
3
|
+
```markdown
|
|
4
|
+
Thank you — this is exactly the kind of verification I was hoping for, and
|
|
5
|
+
the C → Q correction is a genuinely important update. You're right that my
|
|
6
|
+
analysis was written against the older changes-omitted reading of the
|
|
7
|
+
attribute; I've already corrected the plugin's documentation to reflect the
|
|
8
|
+
Matter 1.4 Q (quieter) quality and your subscription trace
|
|
9
|
+
(mathiashornbek/homebridge-roborock-matter@main, README + docs).
|
|
10
|
+
|
|
11
|
+
Your controller log also explains two things I had observed but couldn't
|
|
12
|
+
fully reconcile: the resync nudge's null → value transition "working" at the
|
|
13
|
+
wire level while Apple still never converged, and `batChargeState` updating
|
|
14
|
+
live throughout. Both are consistent with the reports leaving the bridge and
|
|
15
|
+
Apple simply not applying Q-quality percentage reports in steady state.
|
|
16
|
+
|
|
17
|
+
I'll run the verification you suggested on my production setup (three
|
|
18
|
+
robots: one V1, two B01) — Homebridge with matter.js debug logging through a
|
|
19
|
+
full charge cycle, watching for the subscription flushes carrying
|
|
20
|
+
`batPercentRemaining` — and post the log excerpts here. If I can get
|
|
21
|
+
chip-tool set up on the same network I'll add a subscription trace from that
|
|
22
|
+
side too.
|
|
23
|
+
|
|
24
|
+
Assuming both confirm what your trace already shows, I'll file the Apple
|
|
25
|
+
Feedback report about the controller's handling of Q-quality PowerSource
|
|
26
|
+
attributes and link it here so others can dupe it. Thanks again for digging
|
|
27
|
+
in — happy to test any builds if something changes in the Homebridge Matter
|
|
28
|
+
layer down the road.
|
|
29
|
+
```
|
|
@@ -1,66 +1,57 @@
|
|
|
1
|
-
# Matter PowerSource `batPercentRemaining`
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
Matter
|
|
11
|
-
matter.js store
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
##
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
Consider a device-side mitigation in the Homebridge Matter layer for bridged
|
|
60
|
-
accessories — for example bumping the cluster data version or scheduling a
|
|
61
|
-
periodic re-announce for changes-omitted attributes whose value has drifted —
|
|
62
|
-
so controllers that rely purely on subscriptions eventually converge. This
|
|
63
|
-
would fix frozen battery percentages for every bridged plugin at once, in one
|
|
64
|
-
place.
|
|
65
|
-
|
|
66
|
-
Happy to provide full logs, store dumps, and to test builds.
|
|
1
|
+
# Matter PowerSource `batPercentRemaining` — investigation record
|
|
2
|
+
|
|
3
|
+
Filed upstream as
|
|
4
|
+
[homebridge/homebridge#3958](https://github.com/homebridge/homebridge/issues/3958)
|
|
5
|
+
on 2026-07-15. This document tracks the current state of knowledge; the
|
|
6
|
+
original report text lives in the issue.
|
|
7
|
+
|
|
8
|
+
## Symptom
|
|
9
|
+
|
|
10
|
+
A Matter RVC bridged through Homebridge 2's Matter API publishes battery
|
|
11
|
+
updates continuously; the matter.js store verifiably carries the live value;
|
|
12
|
+
`batChargeState` on the same PowerSource cluster updates live in Apple Home —
|
|
13
|
+
but the rendered battery **percentage** stays at its commissioning-time value
|
|
14
|
+
until a fresh read (re-pair or Matter hub restart).
|
|
15
|
+
|
|
16
|
+
## Corrected analysis (per Homebridge maintainer verification, 2026-07-15)
|
|
17
|
+
|
|
18
|
+
The original analysis assumed the attribute carries the Matter reporting
|
|
19
|
+
quality **C (changes omitted)** — never reported via subscription, controllers
|
|
20
|
+
must poll. That was true of older spec revisions, **but as of Matter 1.4 the
|
|
21
|
+
attribute is quality Q (quieter)** , and matter.js 0.17.x (shipped with every
|
|
22
|
+
Homebridge 2.1.x release) models it accordingly:
|
|
23
|
+
|
|
24
|
+
- **Q (quieter):** reported via subscription, rate-limited to at most one
|
|
25
|
+
report per 10 seconds, plus an immediate report on any null ↔ value
|
|
26
|
+
transition.
|
|
27
|
+
|
|
28
|
+
A Homebridge maintainer (bwp91) commissioned a matter.js controller against a
|
|
29
|
+
bridge exposing `PowerSource(Battery, Rechargeable)` — the same setup
|
|
30
|
+
Homebridge builds — and logged the subscription: percentage changes propagate
|
|
31
|
+
exactly as Q prescribes (immediate first report, deferred follow-up inside the
|
|
32
|
+
10 s window, correct application after an interleaved `batChargeState` bump).
|
|
33
|
+
The "stale cluster data version" theory does not hold on the controller side.
|
|
34
|
+
|
|
35
|
+
## Where that leaves things
|
|
36
|
+
|
|
37
|
+
- The bridge **emits** the reports; a spec-compliant controller **applies**
|
|
38
|
+
them. Apple Home in steady state does not — consistent with Apple's
|
|
39
|
+
controller still treating the attribute under the older changes-omitted
|
|
40
|
+
rules and refreshing only on a fresh read.
|
|
41
|
+
- The plugin's boot-time resync nudge (null → value transition) does hit the
|
|
42
|
+
wire immediately (maintainer-confirmed) and remains useful for controllers
|
|
43
|
+
that re-prime their subscriptions; Apple still does not converge.
|
|
44
|
+
- **No device-side fix exists**: bumping the data version or re-announcing
|
|
45
|
+
only produces more of the reports Apple already receives and ignores.
|
|
46
|
+
|
|
47
|
+
## Next verification steps (requested upstream)
|
|
48
|
+
|
|
49
|
+
1. Run Homebridge with matter.js debug logging during a battery change and
|
|
50
|
+
capture the subscription flushes carrying `batPercentRemaining` — proves
|
|
51
|
+
the reports leave THIS bridge specifically.
|
|
52
|
+
2. Optionally subscribe with `chip-tool` and confirm it sees (and applies)
|
|
53
|
+
the live values.
|
|
54
|
+
|
|
55
|
+
If both confirm reports going out, the permanent fix belongs with Apple
|
|
56
|
+
(Apple Feedback report about the controller's handling of Q-quality
|
|
57
|
+
PowerSource attributes). The upstream issue stays open in the meantime.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "homebridge-roborock-matter",
|
|
3
|
-
"version": "2.9.
|
|
3
|
+
"version": "2.9.2",
|
|
4
4
|
"description": "Matter-only Homebridge plugin publishing Roborock robot vacuums (including 2025 B01/Q7-series) as native Matter accessories for Apple Home. Fork of homebridge-roborock-vacuum2.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -1345,7 +1345,23 @@ class deviceFeatures {
|
|
|
1345
1345
|
}
|
|
1346
1346
|
}
|
|
1347
1347
|
|
|
1348
|
+
// Classic v1 models whose upstream-vetted per-model action list includes
|
|
1349
|
+
// `set_custom_mode_max_plus` — the verified signal that the robot's firmware
|
|
1350
|
+
// accepts the Max+ suction level (v1 fan power 108). Keep this in sync with
|
|
1351
|
+
// the modelConfig action lists in processSupportedFeatures above; models are
|
|
1352
|
+
// only added here once the upstream feature data (or a field report with a
|
|
1353
|
+
// diagnostics export) confirms the level.
|
|
1354
|
+
const MAX_PLUS_FAN_POWER_MODELS = new Set([
|
|
1355
|
+
"roborock.vacuum.a70", // S8 Pro Ultra
|
|
1356
|
+
]);
|
|
1357
|
+
|
|
1358
|
+
/** @param {string} model */
|
|
1359
|
+
function supportsMaxPlusFanPower(model) {
|
|
1360
|
+
return MAX_PLUS_FAN_POWER_MODELS.has(model);
|
|
1361
|
+
}
|
|
1362
|
+
|
|
1348
1363
|
module.exports = {
|
|
1349
1364
|
deviceFeatures,
|
|
1350
1365
|
stateCodes,
|
|
1366
|
+
supportsMaxPlusFanPower,
|
|
1351
1367
|
};
|
|
@@ -14,6 +14,8 @@ const roborock_mqtt_connector =
|
|
|
14
14
|
const rrMessage = require("./lib/message").message;
|
|
15
15
|
const vacuum_class = require("./lib/vacuum").vacuum;
|
|
16
16
|
const deviceFeatures = require("./lib/deviceFeatures").deviceFeatures;
|
|
17
|
+
const supportsMaxPlusFanPower =
|
|
18
|
+
require("./lib/deviceFeatures").supportsMaxPlusFanPower;
|
|
17
19
|
const RRMapParser = require("./lib/RRMapParser");
|
|
18
20
|
const messageQueueHandler =
|
|
19
21
|
require("./lib/messageQueueHandler").messageQueueHandler;
|
|
@@ -1944,6 +1946,12 @@ class Roborock {
|
|
|
1944
1946
|
canVacuum: true,
|
|
1945
1947
|
canMop: hasWaterModeSchema || hasMopSchema || hasMopFeature,
|
|
1946
1948
|
canControlFanPower,
|
|
1949
|
+
// Max+ (fan power 108) only where the upstream-vetted per-model
|
|
1950
|
+
// feature data confirms the level (e.g. S8 Pro Ultra) — field
|
|
1951
|
+
// reports with diagnostics exports extend the list.
|
|
1952
|
+
canMaxPlusFanPower: supportsMaxPlusFanPower(
|
|
1953
|
+
this.getProductAttribute(duid, "model")
|
|
1954
|
+
),
|
|
1947
1955
|
canControlWater:
|
|
1948
1956
|
hasWaterModeSchema ||
|
|
1949
1957
|
this.hasVacuumFeature(duid, [
|