homebridge-roborock-vacuum 1.2.3 → 1.2.4
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "homebridge-roborock-vacuum",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.4",
|
|
4
4
|
"description": "Roborock Vacuum Cleaner - plugin for Homebridge.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
@@ -33,17 +33,17 @@
|
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"abstract-things": "0.9.0",
|
|
36
|
-
"axios": "^1.
|
|
36
|
+
"axios": "^1.11.0",
|
|
37
37
|
"binary-parser": "^2.2.1",
|
|
38
38
|
"chalk": "4.1.2",
|
|
39
39
|
"crc-32": "^1.2.2",
|
|
40
40
|
"debug": "4.3.5",
|
|
41
41
|
"deep-equal": "2.2.3",
|
|
42
|
-
"express": "^4.21.
|
|
42
|
+
"express": "^4.21.2",
|
|
43
43
|
"jszip": "^3.10.1",
|
|
44
|
-
"mqtt": "^5.
|
|
44
|
+
"mqtt": "^5.14.0",
|
|
45
45
|
"node-forge": "^1.3.1",
|
|
46
|
-
"rxjs": "^7.
|
|
46
|
+
"rxjs": "^7.8.2",
|
|
47
47
|
"semver": "7.6.2",
|
|
48
48
|
"tinkerhub-discovery": "0.3.1",
|
|
49
49
|
"yargs": "15.4.1"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
{
|
|
2
|
-
"val": "{\"uid\":1466357,\"tokentype\":\"\",\"token\":\"rr6238c899155830:1JZxT5AINkUhb5JDyL8S+w==:
|
|
2
|
+
"val": "{\"uid\":1466357,\"tokentype\":\"\",\"token\":\"rr6238c899155830:1JZxT5AINkUhb5JDyL8S+w==:0198e43aaf3174e3af11c0741cb4d6bc\",\"rruid\":\"rr6238c899155830\",\"region\":\"us\",\"countrycode\":\"886\",\"country\":\"TW\",\"nickname\":\"tasict\",\"rriot\":{\"u\":\"1RQsQJ2o8bxMCo6F45pICu\",\"s\":\"hSvNfL\",\"h\":\"FqZ6lwhKjH\",\"k\":\"HM375uvZ\",\"r\":{\"r\":\"US\",\"a\":\"https://api-us.roborock.com\",\"m\":\"ssl://mqtt-us.roborock.com:8883\",\"l\":\"https://wood-us.roborock.com\"}},\"tuyaDeviceState\":0,\"avatarurl\":\"https://files.roborock.com/iot/default_avatar.png\"}",
|
|
3
3
|
"ack": true
|
|
4
4
|
}
|
|
@@ -192,6 +192,12 @@ class localConnector {
|
|
|
192
192
|
server.on("message", (msg) => {
|
|
193
193
|
const parsedMessage = localMessageParser.parse(msg);
|
|
194
194
|
const decodedMessage = this.decryptECB(parsedMessage.payload, BROADCAST_TOKEN); // this might be decryptCBC for A01. Haven't checked this yet
|
|
195
|
+
|
|
196
|
+
if(decodedMessage == null){
|
|
197
|
+
this.adapter.log.debug(`getLocalDevices: decodedMessage is null`);
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
|
|
195
201
|
const parsedDecodedMessage = JSON.parse(decodedMessage);
|
|
196
202
|
this.adapter.log.debug(`getLocalDevices parsedDecodedMessage: ${JSON.stringify(parsedDecodedMessage)}`);
|
|
197
203
|
|
|
@@ -224,15 +230,53 @@ class localConnector {
|
|
|
224
230
|
});
|
|
225
231
|
}
|
|
226
232
|
|
|
227
|
-
|
|
228
|
-
|
|
233
|
+
safeRemovePkcs7(buf) {
|
|
234
|
+
if (!buf || buf.length === 0) return Buffer.alloc(0);
|
|
235
|
+
const pad = buf[buf.length - 1];
|
|
236
|
+
// 僅在 1..16 且最後 pad 個 byte 都等於 pad 時才移除
|
|
237
|
+
if (pad > 0 && pad <= 16) {
|
|
238
|
+
for (let i = 0; i < pad; i++) {
|
|
239
|
+
if (buf[buf.length - 1 - i] !== pad) return buf; // padding 形狀不對,視為無 padding
|
|
240
|
+
}
|
|
241
|
+
return buf.slice(0, buf.length - pad);
|
|
242
|
+
}
|
|
243
|
+
return buf; // 看起來沒有標準 PKCS#7 padding
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
decryptECB(encrypted, aesKey) {
|
|
247
|
+
// --- 1) Key/輸入檢查 ---
|
|
248
|
+
const key = Buffer.isBuffer(aesKey) ? aesKey : Buffer.from(aesKey);
|
|
249
|
+
if (key.length !== 16) {
|
|
250
|
+
// AES-128 需要 16 bytes 的 key
|
|
251
|
+
return null;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
const input = Buffer.isBuffer(encrypted) ? encrypted : Buffer.from(encrypted, "latin1"); // "binary" 等同 latin1
|
|
255
|
+
if (input.length === 0 || (input.length % 16) !== 0) {
|
|
256
|
+
// 密文長度不是 16 的倍數,多半是封包不完整;丟回 null 讓上層忽略本次
|
|
257
|
+
return null;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
try {
|
|
261
|
+
// --- 2) 固定用 Buffer,關閉自動 padding(你要自己移除) ---
|
|
262
|
+
const decipher = crypto.createDecipheriv("aes-128-ecb", key, null);
|
|
229
263
|
decipher.setAutoPadding(false);
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
264
|
+
|
|
265
|
+
const decryptedBuf = Buffer.concat([decipher.update(input), decipher.final()]);
|
|
266
|
+
const unpadded = safeRemovePkcs7(decryptedBuf);
|
|
267
|
+
|
|
268
|
+
// 若原協定內容是 UTF-8,這裡再轉字串;否則直接回傳 Buffer 讓上層處理
|
|
269
|
+
return unpadded.toString("utf8");
|
|
270
|
+
} catch (err) {
|
|
271
|
+
// 例如 wrong final block length、key 不對等情況
|
|
272
|
+
// 這裡不要讓程式炸掉,直接忽略這個封包
|
|
273
|
+
// 你也可以在這裡做一次 debug log
|
|
274
|
+
// console.debug("decryptECB error:", err);
|
|
275
|
+
return null;
|
|
233
276
|
}
|
|
277
|
+
}
|
|
234
278
|
|
|
235
|
-
|
|
279
|
+
removePadding(str) {
|
|
236
280
|
const paddingLength = str.charCodeAt(str.length - 1);
|
|
237
281
|
return str.slice(0, -paddingLength);
|
|
238
282
|
}
|