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.
@@ -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 { ApiUrlsHome, LanguageLocaleMap } from './constants.js';
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(ApiUrlsHome.GetUserScenes, { method: 'GET', });
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(ApiUrlsHome.GetUserContext, { method: 'GET' });
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
- // Fallback to Puppeteer's bundled Chromium
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
- try {
234
- const puppeteerPath = puppeteer.executablePath();
235
- if (puppeteerPath && puppeteerPath.length > 0) {
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
- } else {
239
- accountInfo.Info = `Puppeteer returned empty Chromium path`;
255
+ } catch (error) {
256
+ accountInfo.Info = `Failed to get Puppeteer Chromium path: ${error.message}`;
240
257
  return accountInfo;
241
258
  }
242
- } catch (error) {
243
- accountInfo.Info = `Failed to get Puppeteer Chromium path: ${error.message}`;
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(`${ApiUrlsHome.WebSocketURL}`)) {
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': ApiUrlsHome.BaseURL,
314
+ 'Origin': ApiUrls.Home.Base,
297
315
  'Pragma': 'no-cache',
298
316
  'Cache-Control': 'no-cache'
299
317
  };
300
- const webSocket = new WebSocket(`${ApiUrlsHome.WebSocketURL}${hash}`, { headers: headers })
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(ApiUrlsHome.BaseURL, { waitUntil: ['domcontentloaded', 'networkidle2'], timeout: GLOBAL_TIMEOUT });
364
+ await page.goto(ApiUrls.Home.Base, { waitUntil: ['domcontentloaded', 'networkidle2'], timeout: GLOBAL_TIMEOUT });
347
365
  } catch (error) {
348
- accountInfo.Info = `Navigation to ${ApiUrlsHome.BaseURL} failed: ${error.message}`;
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': ApiUrlsHome.Dashboard,
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: ApiUrlsHome.BaseURL,
437
+ baseURL: ApiUrls.Home.Base,
420
438
  timeout: 30000,
421
439
  headers: headers
422
440
  })