homebridge-roborock-matter 3.4.8 → 3.4.9
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 +4 -0
- package/README.md +1 -1
- package/package.json +1 -1
- package/roborockLib/lib/b01Q7Adapter.js +38 -1
- package/roborockLib/roborockAPI.js +29 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 3.4.9
|
|
4
|
+
|
|
5
|
+
- **A live-room miss now says where the rooms actually are.** Two Q7s produced position cells around 22,000 while a Roborock map is a couple of thousand cells across at most — so those robots were never "between rooms", their computed position was nowhere near the map. One of them reported x exactly equal to y, which is arithmetic rather than a place a robot stood. The position on its own cannot separate a unit mismatch from a wrong origin, so the miss line now carries the range the room outlines occupy plus the map origin and resolution the transform used. This changes no behaviour; it turns the next log from a hypothesis into a measurement. The bounding box is computed only on the failure path, so a run that resolves every position pays nothing.
|
|
6
|
+
|
|
3
7
|
## 3.4.8
|
|
4
8
|
|
|
5
9
|
**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.
|
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. 463 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
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "homebridge-roborock-matter",
|
|
3
|
-
"version": "3.4.
|
|
3
|
+
"version": "3.4.9",
|
|
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": {
|
|
@@ -504,7 +504,9 @@ function resolveLiveRoomId(liveState) {
|
|
|
504
504
|
* @returns {{roomId: number | null,
|
|
505
505
|
* reason: "resolved" | "no-map-header" | "no-pose" | "no-room-outlines" | "pose-outside-outlines",
|
|
506
506
|
* outlineCount: number,
|
|
507
|
-
* cell: {x: number, y: number} | null
|
|
507
|
+
* cell: {x: number, y: number} | null,
|
|
508
|
+
* outlineBounds?: {minX: number, minY: number, maxX: number, maxY: number} | null,
|
|
509
|
+
* head?: {minX: number, minY: number, resolution: number}}}
|
|
508
510
|
*/
|
|
509
511
|
function describeLiveRoomResolution(liveState) {
|
|
510
512
|
const head = liveState?.head;
|
|
@@ -541,9 +543,44 @@ function describeLiveRoomResolution(liveState) {
|
|
|
541
543
|
reason: "pose-outside-outlines",
|
|
542
544
|
outlineCount,
|
|
543
545
|
cell,
|
|
546
|
+
outlineBounds: outlineBoundingBox(chains),
|
|
547
|
+
head: { minX: head.minX, minY: head.minY, resolution },
|
|
544
548
|
};
|
|
545
549
|
}
|
|
546
550
|
|
|
551
|
+
/**
|
|
552
|
+
* Bounding box of every room outline, in the same cell space the
|
|
553
|
+
* point-in-polygon test uses.
|
|
554
|
+
*
|
|
555
|
+
* Field logs showed two Q7s reporting position cells around 22,000 while a
|
|
556
|
+
* Roborock map is at most a couple of thousand cells across — so the position
|
|
557
|
+
* is not "between rooms", it is nowhere near the map. Whether that is a unit
|
|
558
|
+
* mismatch (pose in millimetres against a resolution in metres) or a wrong
|
|
559
|
+
* origin cannot be told from the position alone: it needs the range the
|
|
560
|
+
* outlines actually occupy. Printing both next to each other turns a guess
|
|
561
|
+
* into a measurement.
|
|
562
|
+
*
|
|
563
|
+
* @param {Array<{points: Array<{x: number, y: number}>}>} chains
|
|
564
|
+
* @returns {{minX: number, minY: number, maxX: number, maxY: number} | null}
|
|
565
|
+
*/
|
|
566
|
+
function outlineBoundingBox(chains) {
|
|
567
|
+
let minX = Infinity;
|
|
568
|
+
let minY = Infinity;
|
|
569
|
+
let maxX = -Infinity;
|
|
570
|
+
let maxY = -Infinity;
|
|
571
|
+
|
|
572
|
+
for (const chain of chains) {
|
|
573
|
+
for (const point of chain.points || []) {
|
|
574
|
+
if (point.x < minX) minX = point.x;
|
|
575
|
+
if (point.y < minY) minY = point.y;
|
|
576
|
+
if (point.x > maxX) maxX = point.x;
|
|
577
|
+
if (point.y > maxY) maxY = point.y;
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
return Number.isFinite(minX) ? { minX, minY, maxX, maxY } : null;
|
|
582
|
+
}
|
|
583
|
+
|
|
547
584
|
/**
|
|
548
585
|
* Standard ray-casting point-in-polygon test over a room boundary chain.
|
|
549
586
|
* @param {number} x @param {number} y
|
|
@@ -95,6 +95,34 @@ const B01_LIVE_ROOM_MISS_REASONS = {
|
|
|
95
95
|
"the robot's position did not fall inside any known room outline (it may be between rooms, or the map may still be building)",
|
|
96
96
|
};
|
|
97
97
|
|
|
98
|
+
/**
|
|
99
|
+
* The outline range and map origin, appended to a live-room miss.
|
|
100
|
+
*
|
|
101
|
+
* A position cell on its own cannot distinguish "the robot is between rooms"
|
|
102
|
+
* from "the position was computed in the wrong units" — and the field logs
|
|
103
|
+
* showed cells near 22,000 where a Roborock map is a couple of thousand cells
|
|
104
|
+
* at most. Printing the range the outlines occupy, plus the origin and
|
|
105
|
+
* resolution the transform used, makes the difference measurable from one log
|
|
106
|
+
* line instead of inferable from none.
|
|
107
|
+
*
|
|
108
|
+
* @param {{outlineBounds?: {minX: number, minY: number, maxX: number, maxY: number} | null,
|
|
109
|
+
* head?: {minX: number, minY: number, resolution: number}}} resolution
|
|
110
|
+
* @returns {string}
|
|
111
|
+
*/
|
|
112
|
+
function describeOutlineBounds(resolution) {
|
|
113
|
+
const bounds = resolution?.outlineBounds;
|
|
114
|
+
if (!bounds) {
|
|
115
|
+
return "";
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const head = resolution.head;
|
|
119
|
+
const origin = head
|
|
120
|
+
? `, map origin ${head.minX},${head.minY} at ${head.resolution}/cell`
|
|
121
|
+
: "";
|
|
122
|
+
|
|
123
|
+
return `, outlines span ${Math.round(bounds.minX)}-${Math.round(bounds.maxX)} x ${Math.round(bounds.minY)}-${Math.round(bounds.maxY)}${origin}`;
|
|
124
|
+
}
|
|
125
|
+
|
|
98
126
|
const B01_STATUS_TICK_MS = 15000;
|
|
99
127
|
const B01_STATUS_FORCED_GAP_MS = 1500;
|
|
100
128
|
const B01_STATUS_ACTIVE_GAP_MS = 12000;
|
|
@@ -4291,7 +4319,7 @@ class Roborock {
|
|
|
4291
4319
|
// because they call for different fixes.
|
|
4292
4320
|
liveState.unresolvedPoseCount =
|
|
4293
4321
|
(liveState.unresolvedPoseCount || 0) + 1;
|
|
4294
|
-
const message = `Live room for ${this.describeDevice(duid)}: ${B01_LIVE_ROOM_MISS_REASONS[resolution2.reason]} (attempt ${liveState.unresolvedPoseCount} this run, ${resolution2.outlineCount} room outline(s) in the map${resolution2.cell ? `, position cell ${Math.round(resolution2.cell.x)},${Math.round(resolution2.cell.y)}` : ""}).`;
|
|
4322
|
+
const message = `Live room for ${this.describeDevice(duid)}: ${B01_LIVE_ROOM_MISS_REASONS[resolution2.reason]} (attempt ${liveState.unresolvedPoseCount} this run, ${resolution2.outlineCount} room outline(s) in the map${resolution2.cell ? `, position cell ${Math.round(resolution2.cell.x)},${Math.round(resolution2.cell.y)}` : ""}${describeOutlineBounds(resolution2)}).`;
|
|
4295
4323
|
if (liveState.unresolvedPoseCount % 5 === 0) {
|
|
4296
4324
|
this.log.info(message);
|
|
4297
4325
|
} else {
|