homebridge-roborock-matter 3.1.0 → 3.2.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 +11 -0
- package/homebridge-ui/public/index.html +8 -4
- package/package.json +1 -1
- package/roborockLib/roborockAPI.js +47 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 3.2.0
|
|
4
|
+
|
|
5
|
+
Field feedback on the Q7 series: the live room in Apple Home lagged badly behind the robot. One run took 90 seconds to name the first room; another took seven minutes.
|
|
6
|
+
|
|
7
|
+
- **The first room of a run now appears as soon as the robot is seen cleaning.** Two throttles were stacking. The status poll backed off to 45 seconds while the robot looked idle, so a clean started from the Roborock app or a schedule was invisible for up to that long; then the live-room map fetch applied its own 20-second gap on top, counted from the last attempt rather than from the start of the run. The idle poll is now 25 seconds, the map gap is 10 seconds, and the transition from idle to cleaning clears the gap so the first fetch goes out immediately. Steady-state pacing during a run is unchanged in spirit — the map payload is still an order of magnitude heavier than a status read and is still paced deliberately.
|
|
8
|
+
- **A robot that cannot place itself on the map now says so.** When the robot's position doesn't fall inside any known room outline, the plugin used to return silently at debug level. That is the most likely explanation for a run going minutes without a room — in the field a Q7 spent seven minutes doing exactly this — and it was indistinguishable from the feature being broken. Repeated misses are now reported at a level you can actually see, with a count.
|
|
9
|
+
|
|
10
|
+
## 3.1.1
|
|
11
|
+
|
|
12
|
+
- **The Apple Home Features checkbox still said "Returning status".** 3.1.0 renamed the setting in the config schema but not in the plugin's own settings UI, which is the one most people actually see — so the first person to install it reasonably wondered whether the update had applied at all. Both now read **Dock & Returning status**, and the description spells out that Emptying and Washing only appear while the dock is genuinely doing that, and that mop drying has no Matter equivalent.
|
|
13
|
+
|
|
3
14
|
## 3.1.0
|
|
4
15
|
|
|
5
16
|
Driven by two open model reports, plus the parts of the 3.0.2 audit that were too large to rush. Nothing here requires re-pairing unless you turn on the dock statuses below.
|
|
@@ -206,11 +206,15 @@
|
|
|
206
206
|
<label class="checkbox">
|
|
207
207
|
<input id="enable-matter-extended-states" type="checkbox" />
|
|
208
208
|
<span>
|
|
209
|
-
Returning status
|
|
209
|
+
Dock & Returning status
|
|
210
210
|
<small
|
|
211
|
-
>Shows the extended Matter Returning
|
|
212
|
-
|
|
213
|
-
|
|
211
|
+
>Shows the extended Matter states: Returning to the dock, Emptying the
|
|
212
|
+
dust bin, Washing the mop, and Updating maps. Requires removing and
|
|
213
|
+
re-pairing the robot in Apple Home once. Which of them Apple Home
|
|
214
|
+
draws is Apple's decision, and Emptying/Washing only appear while the
|
|
215
|
+
dock is actually doing that. Mop drying has no equivalent in the
|
|
216
|
+
Matter vacuum specification, so it cannot be reported. Off by default
|
|
217
|
+
for maximum Apple Home compatibility.</small
|
|
214
218
|
>
|
|
215
219
|
</span>
|
|
216
220
|
</label>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "homebridge-roborock-matter",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0",
|
|
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": {
|
|
@@ -39,8 +39,11 @@ const B01_LIVE_ROOM_CLEAR_V1_STATES = new Set([3, 8]);
|
|
|
39
39
|
|
|
40
40
|
// Minimum gap between live-room map fetch attempts while cleaning. The map
|
|
41
41
|
// payload is an order of magnitude heavier than get_status, so it rides a
|
|
42
|
-
// slower cadence than the
|
|
43
|
-
|
|
42
|
+
// slower cadence than the active status polls — but 20s meant a robot could
|
|
43
|
+
// walk through a whole small room before Apple Home named it, which is the
|
|
44
|
+
// opposite of what a "live" room display is for. 10s keeps the map traffic
|
|
45
|
+
// modest while making the room track the robot closely enough to be useful.
|
|
46
|
+
const B01_LIVE_ROOM_MIN_FETCH_GAP_MS = 10000;
|
|
44
47
|
|
|
45
48
|
// Scheduler granularity for the classic (v1-protocol) status refresh. The
|
|
46
49
|
// refresh itself is throttled per robot inside vacuum.getParameter, so this
|
|
@@ -3605,7 +3608,8 @@ class Roborock {
|
|
|
3605
3608
|
//
|
|
3606
3609
|
// The 1-second poll tick relies on getParameter's internal throttling for
|
|
3607
3610
|
// classic robots; this path must throttle itself or every tick becomes a
|
|
3608
|
-
// cloud request. Periodic refreshes
|
|
3611
|
+
// cloud request. Periodic refreshes are paced by the adaptive cadence
|
|
3612
|
+
// below, forced
|
|
3609
3613
|
// refreshes (post-command, robot pushes) at most every 1.5s, and
|
|
3610
3614
|
// concurrent callers share one in-flight request.
|
|
3611
3615
|
if (!this._b01StatusState) {
|
|
@@ -3630,9 +3634,14 @@ class Roborock {
|
|
|
3630
3634
|
// Adaptive cadence: while the robot is actively working (cleaning,
|
|
3631
3635
|
// returning, docking) every 15s loop tick is allowed through so state
|
|
3632
3636
|
// transitions reach Matter controllers within seconds; at rest the
|
|
3633
|
-
// conservative
|
|
3637
|
+
// conservative cadence below applies.
|
|
3634
3638
|
const isActive = B01_ACTIVE_V1_STATES.has(refreshState.lastKnownV1State);
|
|
3635
|
-
|
|
3639
|
+
// 45s while idle was the dominant part of the delay before a run showed
|
|
3640
|
+
// up at all: a clean started from the Roborock app or a schedule is
|
|
3641
|
+
// invisible to the plugin until the next poll gets through. 25s halves
|
|
3642
|
+
// that worst case for one extra request per robot per minute while
|
|
3643
|
+
// parked, which is negligible next to the active cadence.
|
|
3644
|
+
const minimumGapMs = options.force ? 1500 : isActive ? 12000 : 25000;
|
|
3636
3645
|
if (Date.now() - refreshState.lastAttemptAt < minimumGapMs) {
|
|
3637
3646
|
return null;
|
|
3638
3647
|
}
|
|
@@ -3646,6 +3655,23 @@ class Roborock {
|
|
|
3646
3655
|
[]
|
|
3647
3656
|
);
|
|
3648
3657
|
const v1Status = b01Q7Adapter.mapStatusToV1(data);
|
|
3658
|
+
// A run that has just started is the moment the user is watching, and
|
|
3659
|
+
// it was also the slowest: the live-room fetch below rides its own
|
|
3660
|
+
// throttle, counted from the last attempt, so the first room of a run
|
|
3661
|
+
// could wait a further gap on top of the poll that noticed the robot
|
|
3662
|
+
// at all. Clearing the stamp on the idle -> active transition makes
|
|
3663
|
+
// that first fetch immediate; the throttle still paces every fetch
|
|
3664
|
+
// after it.
|
|
3665
|
+
const wasFetching = B01_LIVE_ROOM_FETCH_V1_STATES.has(
|
|
3666
|
+
refreshState.lastKnownV1State
|
|
3667
|
+
);
|
|
3668
|
+
const isFetching = B01_LIVE_ROOM_FETCH_V1_STATES.has(v1Status.state);
|
|
3669
|
+
if (isFetching && !wasFetching) {
|
|
3670
|
+
const liveState = this._b01LiveRoomState?.get(duid);
|
|
3671
|
+
if (liveState) {
|
|
3672
|
+
liveState.lastAttemptAt = 0;
|
|
3673
|
+
}
|
|
3674
|
+
}
|
|
3649
3675
|
refreshState.lastKnownV1State = v1Status.state;
|
|
3650
3676
|
refreshState.lastV1Status = v1Status;
|
|
3651
3677
|
|
|
@@ -3970,11 +3996,24 @@ class Roborock {
|
|
|
3970
3996
|
liveState.consecutiveFailures = 0;
|
|
3971
3997
|
|
|
3972
3998
|
if (roomId === null) {
|
|
3973
|
-
this
|
|
3974
|
-
|
|
3975
|
-
|
|
3999
|
+
// Debug-only used to make this invisible, and it is the single most
|
|
4000
|
+
// likely reason a run goes minutes without naming a room: in the
|
|
4001
|
+
// field a Q7 took 7 minutes to report its first room while every
|
|
4002
|
+
// attempt in between resolved to nothing and said so only at debug
|
|
4003
|
+
// level. Count the misses and say something at a level the user
|
|
4004
|
+
// actually sees, so "no room yet" is distinguishable from "the
|
|
4005
|
+
// feature is broken".
|
|
4006
|
+
liveState.unresolvedPoseCount =
|
|
4007
|
+
(liveState.unresolvedPoseCount || 0) + 1;
|
|
4008
|
+
const message = `Live room for ${duid}: the robot's position did not fall inside any known room outline (attempt ${liveState.unresolvedPoseCount} this run). The map may still be building, or the robot may be between rooms.`;
|
|
4009
|
+
if (liveState.unresolvedPoseCount % 5 === 0) {
|
|
4010
|
+
this.log.info(message);
|
|
4011
|
+
} else {
|
|
4012
|
+
this.log.debug(message);
|
|
4013
|
+
}
|
|
3976
4014
|
return liveState.current;
|
|
3977
4015
|
}
|
|
4016
|
+
liveState.unresolvedPoseCount = 0;
|
|
3978
4017
|
|
|
3979
4018
|
const roomName =
|
|
3980
4019
|
parsed.rooms.find((room) => room.roomId === roomId)?.roomName ||
|