homebridge-melcloud-control 4.4.1-beta.1 → 4.4.1-beta.11
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/README.md +29 -29
- package/config.schema.json +64 -64
- package/index.js +32 -32
- package/package.json +2 -2
- package/src/constants.js +62 -50
- package/src/deviceata.js +2 -6
- package/src/deviceatw.js +2 -6
- package/src/deviceerv.js +25 -30
- package/src/functions.js +120 -94
- package/src/melcloud.js +4 -4
- package/src/melcloudata.js +15 -11
- package/src/melcloudatw.js +14 -10
- package/src/melclouderv.js +20 -8
- package/src/melcloudhome.js +39 -21
package/src/melcloudhome.js
CHANGED
|
@@ -7,7 +7,7 @@ import EventEmitter from 'events';
|
|
|
7
7
|
import puppeteer from 'puppeteer';
|
|
8
8
|
import ImpulseGenerator from './impulsegenerator.js';
|
|
9
9
|
import Functions from './functions.js';
|
|
10
|
-
import {
|
|
10
|
+
import { ApiUrls, LanguageLocaleMap } from './constants.js';
|
|
11
11
|
const execPromise = promisify(exec);
|
|
12
12
|
|
|
13
13
|
class MelCloudHome extends EventEmitter {
|
|
@@ -17,7 +17,6 @@ class MelCloudHome extends EventEmitter {
|
|
|
17
17
|
this.user = account.user;
|
|
18
18
|
this.passwd = account.passwd;
|
|
19
19
|
this.language = account.language;
|
|
20
|
-
this.logSuccess = account.log?.success;
|
|
21
20
|
this.logWarn = account.log?.warn;
|
|
22
21
|
this.logError = account.log?.error;
|
|
23
22
|
this.logDebug = account.log?.debug;
|
|
@@ -79,7 +78,7 @@ class MelCloudHome extends EventEmitter {
|
|
|
79
78
|
async checkScenesList() {
|
|
80
79
|
try {
|
|
81
80
|
if (this.logDebug) this.emit('debug', `Scanning for scenes`);
|
|
82
|
-
const listScenesData = await this.client(
|
|
81
|
+
const listScenesData = await this.client(ApiUrls.Home.Get.Scenes, { method: 'GET', });
|
|
83
82
|
|
|
84
83
|
const scenesList = listScenesData.data;
|
|
85
84
|
if (this.logDebug) this.emit('debug', `Scenes: ${JSON.stringify(scenesList, null, 2)}`);
|
|
@@ -111,7 +110,7 @@ class MelCloudHome extends EventEmitter {
|
|
|
111
110
|
try {
|
|
112
111
|
const devicesList = { State: false, Info: null, Devices: [], Scenes: [] }
|
|
113
112
|
if (this.logDebug) this.emit('debug', `Scanning for devices`);
|
|
114
|
-
const listDevicesData = await this.client(
|
|
113
|
+
const listDevicesData = await this.client(ApiUrls.Home.Get.ListDevices, { method: 'GET' });
|
|
115
114
|
|
|
116
115
|
const userContext = listDevicesData.data;
|
|
117
116
|
const buildings = userContext.buildings ?? [];
|
|
@@ -225,26 +224,45 @@ class MelCloudHome extends EventEmitter {
|
|
|
225
224
|
try {
|
|
226
225
|
const accountInfo = { State: false, Info: '', Account: {}, UseFahrenheit: false };
|
|
227
226
|
|
|
228
|
-
// Get Chromium path
|
|
227
|
+
// Get Chromium path from resolver
|
|
229
228
|
let chromiumPath = await this.functions.ensureChromiumInstalled();
|
|
230
229
|
|
|
231
|
-
//
|
|
230
|
+
// Detect architecture again (cheap & explicit)
|
|
231
|
+
const { stdout: archOut } = await execPromise('uname -m');
|
|
232
|
+
const arch = archOut.trim();
|
|
233
|
+
const isARM =
|
|
234
|
+
arch.startsWith('arm') ||
|
|
235
|
+
arch.startsWith('aarch64') ||
|
|
236
|
+
arch.startsWith('aarch');
|
|
237
|
+
|
|
238
|
+
// Detect QNAP
|
|
239
|
+
const isQnap =
|
|
240
|
+
fs.existsSync('/etc/config/uLinux.conf') ||
|
|
241
|
+
fs.existsSync('/etc/config/qpkg.conf');
|
|
242
|
+
|
|
243
|
+
// Conditional Puppeteer fallback
|
|
232
244
|
if (!chromiumPath) {
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
245
|
+
if (!isARM && !isQnap) {
|
|
246
|
+
try {
|
|
247
|
+
const puppeteerPath = puppeteer.executablePath();
|
|
248
|
+
if (!puppeteerPath) {
|
|
249
|
+
accountInfo.Info = 'Puppeteer returned empty Chromium path';
|
|
250
|
+
return accountInfo;
|
|
251
|
+
}
|
|
252
|
+
|
|
236
253
|
chromiumPath = puppeteerPath;
|
|
237
254
|
if (this.logDebug) this.emit('debug', `Using Puppeteer bundled Chromium at ${chromiumPath}`);
|
|
238
|
-
}
|
|
239
|
-
accountInfo.Info = `
|
|
255
|
+
} catch (error) {
|
|
256
|
+
accountInfo.Info = `Failed to get Puppeteer Chromium path: ${error.message}`;
|
|
240
257
|
return accountInfo;
|
|
241
258
|
}
|
|
242
|
-
}
|
|
243
|
-
accountInfo.Info =
|
|
259
|
+
} else {
|
|
260
|
+
accountInfo.Info = 'Chromium not available for this platform. Install system Chromium.';
|
|
244
261
|
return accountInfo;
|
|
245
262
|
}
|
|
246
263
|
}
|
|
247
264
|
|
|
265
|
+
|
|
248
266
|
// Verify Chromium executable
|
|
249
267
|
try {
|
|
250
268
|
const { stdout } = await execPromise(`"${chromiumPath}" --version`);
|
|
@@ -282,7 +300,7 @@ class MelCloudHome extends EventEmitter {
|
|
|
282
300
|
await client.send('Network.enable')
|
|
283
301
|
client.on('Network.webSocketCreated', ({ url }) => {
|
|
284
302
|
try {
|
|
285
|
-
if (url.startsWith(`${
|
|
303
|
+
if (url.startsWith(`${ApiUrls.Home.WebSocket}`)) {
|
|
286
304
|
const params = new URL(url).searchParams;
|
|
287
305
|
const hash = params.get('hash');
|
|
288
306
|
if (this.logDebug) this.emit('debug', `Web socket hash detected: ${hash}`);
|
|
@@ -293,11 +311,11 @@ class MelCloudHome extends EventEmitter {
|
|
|
293
311
|
|
|
294
312
|
try {
|
|
295
313
|
const headers = {
|
|
296
|
-
'Origin':
|
|
314
|
+
'Origin': ApiUrls.Home.Base,
|
|
297
315
|
'Pragma': 'no-cache',
|
|
298
316
|
'Cache-Control': 'no-cache'
|
|
299
317
|
};
|
|
300
|
-
const webSocket = new WebSocket(`${
|
|
318
|
+
const webSocket = new WebSocket(`${ApiUrls.Home.WebSocket}${hash}`, { headers: headers })
|
|
301
319
|
.on('error', (error) => {
|
|
302
320
|
if (this.logError) this.emit('error', `Web socket error: ${error}`);
|
|
303
321
|
try {
|
|
@@ -326,7 +344,7 @@ class MelCloudHome extends EventEmitter {
|
|
|
326
344
|
})
|
|
327
345
|
.on('message', (message) => {
|
|
328
346
|
const parsedMessage = JSON.parse(message);
|
|
329
|
-
if (this.logDebug) this.emit('debug', `Incoming message: ${JSON.stringify(parsedMessage, null, 2)}`);
|
|
347
|
+
if (!this.logDebug) this.emit('debug', `Incoming message: ${JSON.stringify(parsedMessage, null, 2)}`);
|
|
330
348
|
if (parsedMessage.message === 'Forbidden') return;
|
|
331
349
|
|
|
332
350
|
this.emit('webSocket', parsedMessage);
|
|
@@ -343,9 +361,9 @@ class MelCloudHome extends EventEmitter {
|
|
|
343
361
|
});
|
|
344
362
|
|
|
345
363
|
try {
|
|
346
|
-
await page.goto(
|
|
364
|
+
await page.goto(ApiUrls.Home.Base, { waitUntil: ['domcontentloaded', 'networkidle2'], timeout: GLOBAL_TIMEOUT });
|
|
347
365
|
} catch (error) {
|
|
348
|
-
accountInfo.Info = `Navigation to ${
|
|
366
|
+
accountInfo.Info = `Navigation to ${ApiUrls.Home.Base} failed: ${error.message}`;
|
|
349
367
|
return accountInfo;
|
|
350
368
|
}
|
|
351
369
|
|
|
@@ -407,7 +425,7 @@ class MelCloudHome extends EventEmitter {
|
|
|
407
425
|
'Accept-Language': LanguageLocaleMap[this.language],
|
|
408
426
|
'Cookie': cookies,
|
|
409
427
|
'Priority': 'u=3, i',
|
|
410
|
-
'Referer':
|
|
428
|
+
'Referer': ApiUrls.Home.Dashboard,
|
|
411
429
|
'Sec-Fetch-Dest': 'empty',
|
|
412
430
|
'Sec-Fetch-Mode': 'cors',
|
|
413
431
|
'Sec-Fetch-Site': 'same-origin',
|
|
@@ -416,7 +434,7 @@ class MelCloudHome extends EventEmitter {
|
|
|
416
434
|
};
|
|
417
435
|
|
|
418
436
|
this.client = axios.create({
|
|
419
|
-
baseURL:
|
|
437
|
+
baseURL: ApiUrls.Home.Base,
|
|
420
438
|
timeout: 30000,
|
|
421
439
|
headers: headers
|
|
422
440
|
})
|