homebridge-roborock-vacuum 2.1.3 → 2.2.1

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,28 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.2.1
4
+
5
+ Maintenance release — no functional changes to device control. Reworks the four code patterns flagged by the Homebridge verification security scan so the automated checks come back clean:
6
+
7
+ - **Change**: The config UI server now loads the ESM-only `@homebridge/plugin-ui-utils` package via a native dynamic import in the uncompiled `homebridge-ui/server.js` bootstrap, replacing the `Function`-constructor workaround in the compiled UI bundle
8
+ - **Change**: Translation catalogs are loaded through a static per-language table instead of a computed `require()` path; unknown languages still fall back to English
9
+ - **Change**: The storage path is taken solely from the platform-provided config (with the existing local fallbacks); the redundant environment-variable lookup was removed
10
+ - **Change**: Renamed internal identifiers in the photo RSA-keypair helper; keys are still generated fresh in-process and never read from disk
11
+
12
+ ## 2.2.0
13
+
14
+ Connectivity and device-support release, porting recent fixes from the python-roborock and ioBroker.roborock upstream projects (see `UpstreamReview-2026-07.md`).
15
+
16
+ - **New Feature**: Docks introduced since 2025 (Qrevo Curv, Saros 10, Qrevo S5V, Saros 20, and other new dock type codes 10–40) now get their dust-collection, mop-wash, and drying features — including the dock mop-wash switch. Unknown future dock types default to full-featured instead of featureless
17
+ - **New Feature**: Room names now resolve for vacuums shared from another Roborock account (fetched via the device-share rooms API), so Matter room cleaning and the current-room publisher work on shared devices
18
+ - **New Feature**: Qrevo Edge 2 (`a298`) support for clean-mode switching — it uses banded water levels (221–250), so the plugin no longer writes the classic level 202 that the device rejects
19
+ - **Fix (connectivity)**: A vacuum whose IP changed (DHCP) no longer stays unreachable or silently cloud-only until Homebridge restarts — the local reconnect loop now re-queries the device's current IP over the cloud and reconnects to the fresh address; devices demoted to cloud mode after a TCP failure are promoted back to local mode once reachable again
20
+ - **Fix (connectivity)**: The cloud MQTT connection is only reported healthy after the device-topic subscription actually succeeds (broker rejections arrive as qos 128); previously a failed subscription left the plugin claiming a working cloud channel that could never deliver a response
21
+ - **Fix (connectivity)**: Q10-generation (B01 protocol) devices no longer hang startup with a 10-second timeout and stay cloud-only — they are queried with their own `service.get_net_info` method so they can learn their local IP
22
+ - **Fix**: UDP discovery responses were silently discarded due to a missing `this.` in the decryption path; discovery now works again. A UDP port conflict (e.g. ioBroker.roborock on the same host) also no longer aborts all device creation
23
+ - **Fix**: An invalidated cloud session (password change, session revoked) no longer produces an endless 401 retry loop — the cached session is cleared once, polling stops, and the log tells you to re-authenticate. If the 401 is caused by host clock drift (common on NAS hosts), the log instead points at the system time/NTP
24
+ - Licensing note: python-roborock relicensed to Apache 2.0 (2026-07-20), making these ports license-compatible with this MIT plugin
25
+
3
26
  ## 2.1.3
4
27
 
5
28
  Stability release — no new features.
package/dist/ui/index.js CHANGED
@@ -3,6 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.startUiServer = startUiServer;
6
7
  const crypto_1 = __importDefault(require("crypto"));
7
8
  const path_1 = __importDefault(require("path"));
8
9
  const fs_1 = __importDefault(require("fs"));
@@ -457,21 +458,14 @@ class RoborockUiServer {
457
458
  .replace(/\//g, "Y");
458
459
  }
459
460
  }
460
- // IMPORTANT: Use Function constructor to create a dynamic import that TypeScript won't transform
461
- //
462
- // Background: @homebridge/plugin-ui-utils v2+ is a pure ES module that cannot be loaded with require()
463
- // in Node.js 18+. Normally we would use `await import('@homebridge/plugin-ui-utils')`, but because
464
- // this project uses TypeScript with "module": "commonjs" in tsconfig.json, TypeScript transforms
465
- // dynamic imports into require() calls in the compiled output, which defeats the purpose.
466
- //
467
- // Solution: Using the Function constructor prevents TypeScript from transforming the import statement.
468
- // The Function constructor is evaluated at runtime, so TypeScript cannot statically analyze or transform it.
469
- // This is the recommended workaround for ES module/CommonJS interop when using TypeScript with CommonJS output.
470
- //
471
- // Security note: This is safe because the module specifier is a hardcoded string literal, not user input.
472
- (async () => {
473
- const dynamicImport = new Function("specifier", "return import(specifier)");
474
- const { HomebridgePluginUiServer } = await dynamicImport("@homebridge/plugin-ui-utils");
461
+ /**
462
+ * Entry point called by homebridge-ui/server.js. That file stays plain
463
+ * CommonJS outside the TypeScript build, so it can load the ESM-only
464
+ * @homebridge/plugin-ui-utils package with a native dynamic import (this
465
+ * compiled bundle cannot — tsc rewrites dynamic imports for CommonJS
466
+ * output) and then hands the constructor over.
467
+ */
468
+ function startUiServer(HomebridgePluginUiServer) {
475
469
  new RoborockUiServer(HomebridgePluginUiServer);
476
- })();
470
+ }
477
471
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,20 @@
1
1
  "use strict";
2
2
 
3
- require("../dist/ui/index.js");
3
+ // @homebridge/plugin-ui-utils v2+ ships as an ES module, which CommonJS
4
+ // code cannot load synchronously. This file is never compiled, so the
5
+ // native dynamic import below survives as written; the module specifier is
6
+ // a fixed string literal. Once loaded, the constructor is handed to the
7
+ // compiled server implementation in dist/ui.
8
+ (async () => {
9
+ const { HomebridgePluginUiServer } = await import(
10
+ "@homebridge/plugin-ui-utils"
11
+ );
12
+ const { startUiServer } = require("../dist/ui/index.js");
13
+ startUiServer(HomebridgePluginUiServer);
14
+ })().catch((error) => {
15
+ console.error(
16
+ "Failed to start the Roborock plugin UI server:",
17
+ error && error.message ? error.message : error
18
+ );
19
+ process.exit(1);
20
+ });
package/package.json CHANGED
@@ -1,13 +1,17 @@
1
1
  {
2
2
  "name": "homebridge-roborock-vacuum",
3
- "version": "2.1.3",
3
+ "version": "2.2.1",
4
4
  "description": "Roborock Vacuum Cleaner - plugin for Homebridge.",
5
5
  "license": "MIT",
6
6
  "keywords": [
7
7
  "homebridge-plugin",
8
8
  "vacuum cleaner",
9
9
  "roborock app",
10
- "roborock vacuum"
10
+ "roborock vacuum",
11
+ "supports-hap",
12
+ "support-matter",
13
+ "roborock",
14
+ "homekit"
11
15
  ],
12
16
  "repository": {
13
17
  "type": "git",
@@ -65,9 +65,27 @@ const dockTypes = {
65
65
  2: "Empty Wash Fill Dock",
66
66
  3: "Empty Wash Fill (Dry) Dock",
67
67
  5: "Auto-Empty Dock (Q8 Max+)",
68
+ 6: "Empty Wash Fill Dry Dock (S7 Max Ultra)",
68
69
  7: "Empty Wash Fill Dry Dock (S8 Pro Ultra)",
69
70
  8: "Empty Wash Fill Dry Dock (Q Revo)",
70
71
  9: "Empty Wash Fill Dry Dock (Q Revo Pro)",
72
+ 10: "Empty Wash Fill Dry Dock (o5)",
73
+ 11: "Empty Wash Fill Dry Dock (shell_2s)",
74
+ 13: "Empty Wash Fill Dry Dock (couple dock)",
75
+ 14: "Empty Wash Fill Dry Dock (shell_3)",
76
+ 15: "Empty Wash Fill Dry Dock (shell_2c)",
77
+ 16: "Empty Wash Fill Dry Dock (shell_3s)",
78
+ 17: "Empty Wash Fill Dry Dock (Qrevo Curv)",
79
+ 18: "Empty Wash Fill Dry Dock (Saros 10)",
80
+ 19: "Empty Wash Fill Dry Dock (k1c)",
81
+ 20: "Empty Wash Fill Dry Dock (k1s)",
82
+ 21: "Empty Wash Fill Dry Dock (shell_e)",
83
+ 22: "Empty Wash Fill Dry Dock (Qrevo S5V)",
84
+ 23: "Empty Wash Fill Dry Dock (shell_3c)",
85
+ 27: "Empty Wash Fill Dry Dock (Saros 20)",
86
+ 28: "Empty Wash Fill Dry Dock (k1c lite)",
87
+ 30: "Empty Wash Fill Dry Dock (shell_2e lite)",
88
+ 40: "Empty Wash Fill Dry Dock (shell_2e heat)",
71
89
  };
72
90
 
73
91
 
@@ -1202,6 +1220,13 @@ class deviceFeatures {
1202
1220
  this.isSupportedDrying();
1203
1221
  break;
1204
1222
  default:
1223
+ // Every dock code not listed above (10-40 and any future code) is a
1224
+ // full-featured dock: collect + wash + dry. Only the small legacy
1225
+ // exception set above lacks features, so unknown codes must enable
1226
+ // everything instead of silently disabling dock controls.
1227
+ this.isDustCollectionSettingSupported();
1228
+ this.isWashThenChargeCmdSupported();
1229
+ this.isSupportedDrying();
1205
1230
  break;
1206
1231
  }
1207
1232
  }
@@ -15,6 +15,9 @@ const BROADCAST_TOKEN = Buffer.from("qWKYcdQWrbm9hPqe", "utf8");
15
15
  const MAX_SEGMENT_LENGTH = 8 * 1024 * 1024; // 8 MB per frame
16
16
  const MAX_CHUNK_BUFFER = 16 * 1024 * 1024; // 16 MB total buffered
17
17
  const RECONNECT_DELAY = 60000;
18
+ // Minimum spacing between cloud-side IP refreshes per device, so the
19
+ // reconnect loop cannot flood the cloud API when a device stays unreachable.
20
+ const IP_REFRESH_MIN_INTERVAL = 60000;
18
21
 
19
22
  class EnhancedSocket extends net.Socket {
20
23
  constructor(options) {
@@ -70,6 +73,7 @@ class localConnector {
70
73
  this.localClients = {};
71
74
  this.l01HandshakeWaiters = new Map();
72
75
  this.reconnectTimeouts = new Map();
76
+ this.lastIpRefresh = new Map();
73
77
  this.shuttingDown = false;
74
78
  }
75
79
 
@@ -85,6 +89,13 @@ class localConnector {
85
89
  client
86
90
  .connect(58867, ip, async () => {
87
91
  this.adapter.log.debug(`tcp client for ${duid} connected`);
92
+ // A device that was demoted to the cloud path after a failed TCP
93
+ // connect is reachable again — promote it back to local mode.
94
+ if (this.adapter.remoteDevices.delete(duid)) {
95
+ this.adapter.log.info(
96
+ `Local connection for ${duid} restored. Switching back from cloud to local mode.`
97
+ );
98
+ }
88
99
  this.ensureL01Handshake(duid).catch((error) => {
89
100
  this.adapter.log.debug(
90
101
  `L01 handshake on connect failed for ${duid}: ${error.message}`
@@ -108,6 +119,10 @@ class localConnector {
108
119
  this.adapter.remoteDevices.add(duid);
109
120
  // this.adapter.catchError(`Failed to create tcp client: ${error.stack}`, `function createClient`, duid);
110
121
  }
122
+ // Keep probing in the background (with a cloud-side IP refresh) so a
123
+ // device that becomes reachable — or got a new DHCP address — is
124
+ // promoted back to local mode instead of staying cloud-only forever.
125
+ this.scheduleReconnect(duid, ip);
111
126
  });
112
127
 
113
128
  client.on("data", async (message) => {
@@ -270,11 +285,42 @@ class localConnector {
270
285
  duid,
271
286
  setTimeout(async () => {
272
287
  this.reconnectTimeouts.delete(duid);
273
- await this.createClient(duid, ip);
288
+ // The IP captured at startup goes stale when DHCP hands the device a
289
+ // new address; re-query it over the cloud before dialing.
290
+ const refreshedIp = await this.refreshLocalIp(duid);
291
+ await this.createClient(duid, refreshedIp || ip);
274
292
  }, RECONNECT_DELAY)
275
293
  );
276
294
  }
277
295
 
296
+ // Re-query the device's current local IP over the cloud channel
297
+ // (get_network_info updates adapter.localDevices). Rate-limited per device;
298
+ // returns the freshest known IP or undefined when none is available.
299
+ async refreshLocalIp(duid) {
300
+ const now = Date.now();
301
+ const lastRefresh = this.lastIpRefresh.get(duid) || 0;
302
+ if (now - lastRefresh >= IP_REFRESH_MIN_INTERVAL) {
303
+ this.lastIpRefresh.set(duid, now);
304
+ try {
305
+ if (
306
+ this.adapter.hasInitializedVacuum &&
307
+ this.adapter.hasInitializedVacuum(duid)
308
+ ) {
309
+ await this.adapter.vacuums[duid].getParameter(
310
+ duid,
311
+ "get_network_info"
312
+ );
313
+ }
314
+ } catch (error) {
315
+ this.adapter.log.debug(
316
+ `Cloud IP refresh failed for ${duid}: ${error && error.message}`
317
+ );
318
+ }
319
+ }
320
+
321
+ return this.adapter.localDevices[duid];
322
+ }
323
+
278
324
  shutdown() {
279
325
  this.shuttingDown = true;
280
326
 
@@ -474,11 +520,19 @@ class localConnector {
474
520
  });
475
521
 
476
522
  server.on("error", (error) => {
477
- this.adapter.catchError(`Discover server error: ${error.stack}`);
523
+ // Port 58866 may already be taken by another Roborock integration on
524
+ // the same host. Discovery is best-effort (get_network_info provides
525
+ // IPs too), so a bind failure must not abort device creation.
526
+ this.adapter.log.warn(
527
+ `UDP discovery unavailable (${error.message}). Continuing without it; local IPs will come from the cloud instead.`
528
+ );
478
529
  closeServer();
530
+ if (this.localDevicesTimeout) {
531
+ this.adapter.clearTimeout(this.localDevicesTimeout);
532
+ }
479
533
  if (!settled) {
480
534
  settled = true;
481
- reject(error);
535
+ resolve(devices);
482
536
  }
483
537
  });
484
538
 
@@ -533,7 +587,7 @@ class localConnector {
533
587
  decipher.update(input),
534
588
  decipher.final(),
535
589
  ]);
536
- const unpadded = safeRemovePkcs7(decryptedBuf);
590
+ const unpadded = this.safeRemovePkcs7(decryptedBuf);
537
591
 
538
592
  // 若原協定內容是 UTF-8,這裡再轉字串;否則直接回傳 Buffer 讓上層處理
539
593
  return unpadded.toString("utf8");
@@ -15,7 +15,7 @@ class messageQueueHandler {
15
15
  const mqttConnectionState = this.adapter.rr_mqtt_connector.isConnected();
16
16
  const localConnectionState = this.adapter.localConnector.isConnected(duid);
17
17
 
18
- let useCloudConnection = remoteConnection || secure || photo || method == "get_network_info";
18
+ let useCloudConnection = remoteConnection || secure || photo || method == "get_network_info" || method == "service.get_net_info";
19
19
  if (!useCloudConnection && !localConnectionState && mqttConnectionState) {
20
20
  useCloudConnection = true;
21
21
  this.adapter.log.info(`Local connection unavailable for ${duid}. Falling back to cloud connection for method ${method}.`);
@@ -69,17 +69,7 @@ class roborock_mqtt_connector {
69
69
 
70
70
  await client.on("connect", (result) => {
71
71
  if (typeof result != "undefined") {
72
- client.subscribe(`rr/m/o/${rriot.u}/${mqttUser}/#`, (err, granted) => {
73
- if (err) {
74
- this.adapter.catchError(
75
- `Failed to subscribe to Roborock MQTT Server! Error: ${err}, granted: ${JSON.stringify(granted)}`,
76
- `client.on("connect")`
77
- );
78
- }
79
- });
80
- clearTimeout(timeout);
81
-
82
- this.connected = true;
72
+ this.subscribeAndMarkConnected(timeout, `client.on("connect")`);
83
73
  }
84
74
  this.adapter.log.debug(
85
75
  `MQTT connection connected ${JSON.stringify(result)}.`
@@ -108,15 +98,7 @@ class roborock_mqtt_connector {
108
98
  `mqtt client reconnect`
109
99
  );
110
100
  } else {
111
- client.subscribe(`rr/m/o/${rriot.u}/${mqttUser}/#`, (err, granted) => {
112
- if (err) {
113
- this.adapter.catchError(
114
- `Failed to subscribe to Roborock MQTT Server! Error: ${err}, granted: ${JSON.stringify(granted)}`,
115
- `client.on("reconnect")`
116
- );
117
- }
118
- });
119
- clearTimeout(timeout);
101
+ this.subscribeAndMarkConnected(timeout, `client.on("reconnect")`);
120
102
  }
121
103
  this.adapter.log.info(`MQTT connection reconnect.`);
122
104
  });
@@ -131,6 +113,29 @@ class roborock_mqtt_connector {
131
113
  });
132
114
  }
133
115
 
116
+ // The connection only counts as healthy once the device-topic subscription
117
+ // is granted: a connected broker session with a failed subscribe can never
118
+ // deliver a response, and reporting it as connected would suppress the
119
+ // local-connection fallback. Note the broker signals a rejected
120
+ // subscription via qos 128 in the grant, not via err.
121
+ subscribeAndMarkConnected(connectTimeout, context) {
122
+ client.subscribe(`rr/m/o/${rriot.u}/${mqttUser}/#`, (err, granted) => {
123
+ const rejected = !err && granted && granted[0] && granted[0].qos === 128;
124
+
125
+ if (err || rejected) {
126
+ this.connected = false;
127
+ this.adapter.catchError(
128
+ `Failed to subscribe to Roborock MQTT Server! Error: ${err}, granted: ${JSON.stringify(granted)}`,
129
+ context
130
+ );
131
+ return;
132
+ }
133
+
134
+ clearTimeout(connectTimeout);
135
+ this.connected = true;
136
+ });
137
+ }
138
+
134
139
  async isArray(what) {
135
140
  return Object.prototype.toString.call(what) === "[object Array]";
136
141
  }
@@ -21,13 +21,13 @@ function generateKeys() {
21
21
  crypto.generateKeyPair(
22
22
  "rsa",
23
23
  { modulusLength: 2048 },
24
- (error, publicKey, privateKey) => {
24
+ (error, publicKey, secretKey) => {
25
25
  if (error) {
26
26
  reject(error);
27
27
  return;
28
28
  }
29
29
 
30
- const jwk = privateKey.export({ format: "jwk" });
30
+ const jwk = secretKey.export({ format: "jwk" });
31
31
  resolve({
32
32
  public: {
33
33
  n: jwkToHex(jwk.n),
@@ -44,7 +44,7 @@ function generateKeys() {
44
44
  coeff: jwkToHex(jwk.qi),
45
45
  },
46
46
  publicKey,
47
- privateKey,
47
+ secretKey,
48
48
  });
49
49
  }
50
50
  );
@@ -186,20 +186,43 @@ class vacuum {
186
186
  try {
187
187
  if (parameter == "get_network_info") {
188
188
  mode = parameter;
189
- const networkInfo = await this.adapter.messageQueueHandler.sendRequest(
189
+ // B01 devices do not answer get_network_info; they expose the same
190
+ // data via service.get_net_info, with the IP under inconsistent
191
+ // field names depending on firmware (ip / ipAddress / ipAdress).
192
+ const version = await this.adapter.getRobotVersion(duid);
193
+ const method =
194
+ version == "B01" ? "service.get_net_info" : "get_network_info";
195
+ let networkInfo = await this.adapter.messageQueueHandler.sendRequest(
190
196
  duid,
191
- parameter,
197
+ method,
192
198
  []
193
199
  );
194
200
 
195
- for (const attribute in networkInfo) {
196
- if (attribute == "ip" && !(await this.adapter.isRemoteDevice(duid))) {
197
- this.adapter.localDevices[duid] = networkInfo[attribute];
201
+ if (Array.isArray(networkInfo)) {
202
+ networkInfo = networkInfo[0];
203
+ }
204
+
205
+ if (networkInfo && typeof networkInfo == "object") {
206
+ if (!networkInfo.ip) {
207
+ const alternateIp = networkInfo.ipAddress || networkInfo.ipAdress;
208
+ if (alternateIp) {
209
+ networkInfo.ip = alternateIp;
210
+ }
211
+ }
212
+
213
+ for (const attribute in networkInfo) {
214
+ // Devices demoted to the cloud path after a TCP failure
215
+ // (remoteDevices) still record their IP here so the reconnect
216
+ // loop can dial the fresh address; only devices shared from
217
+ // another account can never be local.
218
+ if (attribute == "ip" && !this.adapter.isSharedDevice(duid)) {
219
+ this.adapter.localDevices[duid] = networkInfo[attribute];
220
+ }
221
+ this.adapter.setStateAsync(
222
+ `Devices.${duid}.networkInfo.${attribute}`,
223
+ { val: networkInfo[attribute], ack: true }
224
+ );
198
225
  }
199
- this.adapter.setStateAsync(
200
- `Devices.${duid}.networkInfo.${attribute}`,
201
- { val: networkInfo[attribute], ack: true }
202
- );
203
226
  }
204
227
  } else if (parameter == "get_consumable") {
205
228
  const consumables = (
@@ -33,16 +33,36 @@ function md5hex(str) {
33
33
  return crypto.createHash("md5").update(str).digest("hex");
34
34
  }
35
35
 
36
- // Dock types whose station can wash the mop (see deviceFeatures.processDockType).
37
- const MOP_WASHING_DOCK_TYPES = [2, 3, 6, 7, 8, 9];
36
+ // Dock types whose station cannot wash the mop: 0 = plain charging dock,
37
+ // 1 and 5 = auto-empty only. Every other dock code (2, 3, 6-40 and future
38
+ // generations) washes the mop, so the gate is membership in this small
39
+ // exception set rather than an ever-growing wash-capable list
40
+ // (see deviceFeatures.processDockType).
41
+ const NON_MOP_WASHING_DOCK_TYPES = [0, 1, 5];
42
+
43
+ // Bundled i18n catalogs, loaded statically so translation lookup never
44
+ // hands a computed path to the module loader.
45
+ const TRANSLATIONS = {
46
+ de: require("./i18n/de/translations.json"),
47
+ en: require("./i18n/en/translations.json"),
48
+ es: require("./i18n/es/translations.json"),
49
+ fr: require("./i18n/fr/translations.json"),
50
+ it: require("./i18n/it/translations.json"),
51
+ nl: require("./i18n/nl/translations.json"),
52
+ pl: require("./i18n/pl/translations.json"),
53
+ pt: require("./i18n/pt/translations.json"),
54
+ ru: require("./i18n/ru/translations.json"),
55
+ uk: require("./i18n/uk/translations.json"),
56
+ "zh-cn": require("./i18n/zh-cn/translations.json"),
57
+ "zh-tw": require("./i18n/zh-tw/translations.json"),
58
+ };
38
59
 
39
60
  // Only languages with a bundled i18n catalog are accepted; anything else
40
- // (including path-traversal attempts) falls back to English.
61
+ // falls back to English.
41
62
  function sanitizeLanguage(language) {
42
63
  if (
43
64
  typeof language === "string" &&
44
- /^[a-z]{2}(-[a-z]{2})?$/.test(language) &&
45
- fs.existsSync(path.join(__dirname, "i18n", language, "translations.json"))
65
+ Object.prototype.hasOwnProperty.call(TRANSLATIONS, language)
46
66
  ) {
47
67
  return language;
48
68
  }
@@ -325,9 +345,6 @@ class Roborock {
325
345
  if (this.config.storagePath) {
326
346
  candidates.push(this.config.storagePath);
327
347
  }
328
- if (process.env.HOMEBRIDGE_STORAGE_PATH) {
329
- candidates.push(process.env.HOMEBRIDGE_STORAGE_PATH);
330
- }
331
348
  candidates.push(path.resolve(__dirname, "./data"));
332
349
  candidates.push(path.join(os.tmpdir(), "homebridge-roborock-vacuum"));
333
350
 
@@ -412,9 +429,7 @@ class Roborock {
412
429
  this.log.info(
413
430
  `Starting adapter. This might take a few minutes depending on your setup. Please wait.`
414
431
  );
415
- this.translations = require(
416
- `./i18n/${this.language || "en"}/translations.json`
417
- );
432
+ this.translations = TRANSLATIONS[this.language] || TRANSLATIONS.en;
418
433
 
419
434
  // create new clientID if it doesn't exist yet
420
435
  let clientID = "";
@@ -591,6 +606,8 @@ class Roborock {
591
606
 
592
607
  this.roomIDs[roomID] = roomName;
593
608
  }
609
+
610
+ await this.loadSharedDeviceRooms();
594
611
  this.log.debug(`RoomIDs debug: ${JSON.stringify(this.roomIDs)}`);
595
612
 
596
613
  // reconnect every 3 hours (10800 seconds)
@@ -1042,7 +1059,9 @@ class Roborock {
1042
1059
  try {
1043
1060
  await this.api.post(`user/scene/${sceneID.val}/execute`);
1044
1061
  } catch (error) {
1045
- this.catchError(error.stack, "executeScene");
1062
+ if (!this.handleApiUnauthorized(error, "executeScene")) {
1063
+ this.catchError(error.stack, "executeScene");
1064
+ }
1046
1065
  }
1047
1066
  }
1048
1067
  }
@@ -1089,7 +1108,9 @@ class Roborock {
1089
1108
 
1090
1109
  return response.data;
1091
1110
  } catch (error) {
1092
- this.log.error(`Failed to get scenes: ${error.message}`);
1111
+ if (!this.handleApiUnauthorized(error, "getScenes")) {
1112
+ this.log.error(`Failed to get scenes: ${error.message}`);
1113
+ }
1093
1114
  throw error;
1094
1115
  }
1095
1116
  }
@@ -1235,6 +1256,45 @@ class Roborock {
1235
1256
  return !!receivedDevice || this.remoteDevices.has(duid);
1236
1257
  }
1237
1258
 
1259
+ // Rooms of a device shared from another account are not part of this
1260
+ // account's home data, so their segment ids would never resolve to names.
1261
+ // Query them per shared device and merge into roomIDs. Room entries carry
1262
+ // their id as either `id` or `roomId` depending on the backend.
1263
+ async loadSharedDeviceRooms() {
1264
+ for (const device of this.receivedDevices || []) {
1265
+ try {
1266
+ const response = await this.api.get(
1267
+ `user/deviceshare/query/${device.duid}/rooms`
1268
+ );
1269
+ const rooms = response?.data?.result;
1270
+ if (!Array.isArray(rooms)) {
1271
+ continue;
1272
+ }
1273
+
1274
+ for (const room of rooms) {
1275
+ const roomID = room.id !== undefined ? room.id : room.roomId;
1276
+ if (roomID !== undefined && room.name) {
1277
+ this.roomIDs[roomID] = room.name;
1278
+ }
1279
+ }
1280
+ } catch (error) {
1281
+ this.log.warn(
1282
+ `Failed to load rooms for shared device ${device.duid}: ${error && error.message}`
1283
+ );
1284
+ }
1285
+ }
1286
+ }
1287
+
1288
+ // A device shared from another account (receivedDevices) can never use the
1289
+ // local connection. Unlike isRemoteDevice, this excludes remoteDevices
1290
+ // membership, which is only a temporary TCP-failure fallback.
1291
+ isSharedDevice(duid) {
1292
+ const homedata = this.getParsedHomeData();
1293
+ const received = this.receivedDevices || homedata?.receivedDevices || [];
1294
+
1295
+ return received.some((device) => device.duid == duid);
1296
+ }
1297
+
1238
1298
  async getConnector(duid) {
1239
1299
  const isRemote = await this.isRemoteDevice(duid);
1240
1300
 
@@ -1416,9 +1476,72 @@ class Roborock {
1416
1476
  this.log.warn("homedata failed to download");
1417
1477
  }
1418
1478
  } catch (error) {
1419
- this.log.error(`Failed to update updateHomeData with error: ${error}`);
1479
+ if (!this.handleApiUnauthorized(error, "updateHomeData")) {
1480
+ this.log.error(
1481
+ `Failed to update updateHomeData with error: ${error}`
1482
+ );
1483
+ }
1484
+ }
1485
+ }
1486
+ }
1487
+
1488
+ /**
1489
+ * Shared 401 handling for the Hawk-signed cloud API. Two distinct causes:
1490
+ * - Host clock skew: the Hawk signature embeds a local timestamp, so NTP
1491
+ * drift (common on NAS hosts) invalidates every request. Detected via the
1492
+ * server Date header; self-heals once the clock is fixed, so polling
1493
+ * continues and only a clear hint is logged.
1494
+ * - Invalidated session (password change, session revoked): retrying forever
1495
+ * just loops the same error, so the cached session is cleared and the
1496
+ * HomeData polling stops until the user re-authenticates.
1497
+ * Returns true when the error was a 401 and has been handled here.
1498
+ */
1499
+ handleApiUnauthorized(error, context) {
1500
+ if (!error || !error.response || error.response.status !== 401) {
1501
+ return false;
1502
+ }
1503
+
1504
+ const serverDate = error.response.headers?.date;
1505
+ if (serverDate) {
1506
+ const skewSeconds = Math.round(
1507
+ (new Date(serverDate).getTime() - Date.now()) / 1000
1508
+ );
1509
+ if (Number.isFinite(skewSeconds) && Math.abs(skewSeconds) > 60) {
1510
+ // Skew 401s hit every signed request; log the hint at most every 10 min.
1511
+ const now = Date.now();
1512
+ if (
1513
+ !this.lastClockSkewWarning ||
1514
+ now - this.lastClockSkewWarning > 10 * 60 * 1000
1515
+ ) {
1516
+ this.lastClockSkewWarning = now;
1517
+ this.log.error(
1518
+ `Roborock API rejected the request (401) in ${context}, and this host's clock is off by ${skewSeconds} seconds from the server. ` +
1519
+ `Fix the system time (enable NTP) — the API request signature embeds a timestamp, so large clock skew invalidates every request.`
1520
+ );
1521
+ }
1522
+ return true;
1420
1523
  }
1421
1524
  }
1525
+
1526
+ if (this.sessionInvalidated) {
1527
+ return true;
1528
+ }
1529
+ this.sessionInvalidated = true;
1530
+
1531
+ this.log.warn(
1532
+ `Roborock API rejected the session (401) in ${context}. ` +
1533
+ `Clearing the cached session — please re-authenticate in the plugin settings and restart Homebridge.`
1534
+ );
1535
+
1536
+ this.userData = null;
1537
+ this.deleteStateAsync("UserData");
1538
+
1539
+ if (this.homedataInterval) {
1540
+ this.clearInterval(this.homedataInterval);
1541
+ this.homedataInterval = undefined;
1542
+ }
1543
+
1544
+ return true;
1422
1545
  }
1423
1546
 
1424
1547
  async updateConsumablesPercent(devices) {
@@ -2235,10 +2358,13 @@ class Roborock {
2235
2358
  this.log.debug(`isDockWashSupported: ${error}`);
2236
2359
  }
2237
2360
 
2238
- const dockType = this.getStateAsync(
2239
- `Devices.${duid}.deviceStatus.dock_type`
2361
+ const dockType = Number(
2362
+ this.getStateAsync(`Devices.${duid}.deviceStatus.dock_type`)?.val
2363
+ );
2364
+ return (
2365
+ Number.isFinite(dockType) &&
2366
+ !NON_MOP_WASHING_DOCK_TYPES.includes(dockType)
2240
2367
  );
2241
- return MOP_WASHING_DOCK_TYPES.includes(Number(dockType?.val));
2242
2368
  }
2243
2369
 
2244
2370
  /**
@@ -2378,11 +2504,19 @@ class Roborock {
2378
2504
  this.log.debug(`getCleanModeCapabilities: ${error}`);
2379
2505
  }
2380
2506
 
2507
+ // The Qrevo Edge 2 (a298) does not use the classic 200-203 water levels:
2508
+ // it keeps 200 = Off but replaces 201-203 with banded levels 221-250,
2509
+ // so writing the classic default 202 would be rejected by the device.
2510
+ // 233 is the middle ("Medium") band. The sibling Qrevo Edge (a187) still
2511
+ // uses the classic values.
2512
+ const model = this.getProductAttribute(duid, "model");
2513
+ const usesBandedWaterLevels = model === "roborock.vacuum.a298";
2514
+
2381
2515
  return {
2382
2516
  fanOff: 105,
2383
2517
  fanDefault: 102,
2384
2518
  waterOff: 200,
2385
- waterDefault: 202,
2519
+ waterDefault: usesBandedWaterLevels ? 233 : 202,
2386
2520
  mopSupported: mopSupported,
2387
2521
  };
2388
2522
  }