homebridge-melcloud-control 4.0.0-beta.413 → 4.0.0-beta.415

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/index.js CHANGED
@@ -89,7 +89,7 @@ class MelCloudPlatform {
89
89
  .on('start', async () => {
90
90
  try {
91
91
  //melcloud account
92
- const melCloud = new MelCloud(accountType, user, passwd, language, accountFile, buildingsFile, devicesFile, logLevel.warn, logLevel.debug, false)
92
+ const melCloud = new MelCloud(accountType, user, passwd, language, accountFile, buildingsFile, devicesFile, logLevel.warn, logLevel.error, logLevel.debug, false)
93
93
  .on('success', (msg) => logLevel.success && log.success(`${accountName}, ${msg}`))
94
94
  .on('info', (msg) => logLevel.info && log.info(`${accountName}, ${msg}`))
95
95
  .on('debug', (msg) => logLevel.debug && log.info(`${accountName}, debug: ${msg}`))
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "displayName": "MELCloud Control",
3
3
  "name": "homebridge-melcloud-control",
4
- "version": "4.0.0-beta.413",
4
+ "version": "4.0.0-beta.415",
5
5
  "description": "Homebridge plugin to control Mitsubishi Air Conditioner, Heat Pump and Energy Recovery Ventilation.",
6
6
  "license": "MIT",
7
7
  "author": "grzegorz914",
package/src/melcloud.js CHANGED
@@ -9,7 +9,7 @@ import Functions from './functions.js';
9
9
  import { ApiUrls, ApiUrlsHome } from './constants.js';
10
10
 
11
11
  class MelCloud extends EventEmitter {
12
- constructor(accountType, user, passwd, language, accountFile, buildingsFile, devicesFile, logWarn, logDebug, requestConfig) {
12
+ constructor(accountType, user, passwd, language, accountFile, buildingsFile, devicesFile, logWarn, logError, logDebug, requestConfig) {
13
13
  super();
14
14
  this.accountType = accountType;
15
15
  this.user = user;
@@ -19,6 +19,7 @@ class MelCloud extends EventEmitter {
19
19
  this.buildingsFile = buildingsFile;
20
20
  this.devicesFile = devicesFile;
21
21
  this.logWarn = logWarn;
22
+ this.logError= logError;
22
23
  this.logDebug = logDebug;
23
24
  this.requestConfig = requestConfig;
24
25
  this.devicesId = [];
@@ -73,7 +74,7 @@ class MelCloud extends EventEmitter {
73
74
  const listDevicesData = await axiosInstance.get(ApiUrls.ListDevices);
74
75
 
75
76
  if (!listDevicesData || !listDevicesData.data) {
76
- this.emit('warn', `Invalid or empty response from MELCloud API`);
77
+ if (this.logWarn) this.emit('warn', `Invalid or empty response from MELCloud API`);
77
78
  return null;
78
79
  }
79
80
 
@@ -83,7 +84,7 @@ class MelCloud extends EventEmitter {
83
84
  this.emit('debug', `Buildings: ${JSON.stringify(buildingsList, null, 2)}`);
84
85
 
85
86
  if (!Array.isArray(buildingsList) || buildingsList.length === 0) {
86
- this.emit('warn', `No buildings found in MELCloud account`);
87
+ if (this.logWarn) this.emit('warn', `No buildings found in MELCloud account`);
87
88
  return null;
88
89
  }
89
90
 
@@ -129,7 +130,7 @@ class MelCloud extends EventEmitter {
129
130
  }
130
131
 
131
132
  if (devices.length === 0) {
132
- this.emit('warn', `No devices found in any building`);
133
+ if (this.logWarn) this.emit('warn', `No devices found in any building`);
133
134
  return null;
134
135
  }
135
136
 
@@ -342,10 +343,10 @@ class MelCloud extends EventEmitter {
342
343
 
343
344
  const page = await browser.newPage();
344
345
 
345
- page.on('error', err => this.emit('warn', `Page crashed: ${err.message}`));
346
- page.on('pageerror', err => this.emit('warn', `Browser error: ${err.message}`));
347
- page.on('close', () => this.emit('warn', 'Page was closed unexpectedly'));
348
- browser.on('disconnected', () => this.emit('warn', 'Browser disconnected unexpectedly'));
346
+ page.on('error', err => this.emit('error', `Page crashed: ${err.message}`));
347
+ page.on('pageerror', err => this.emit('error', `Browser error: ${err.message}`));
348
+ page.on('close', () => this.emit('debug', 'Page was closed unexpectedly'));
349
+ browser.on('disconnected', () => this.emit('debug', 'Browser disconnected unexpectedly'));
349
350
 
350
351
  page.setDefaultTimeout(30000);
351
352
  page.setDefaultNavigationTimeout(30000);
@@ -362,12 +363,12 @@ class MelCloud extends EventEmitter {
362
363
  }
363
364
  }
364
365
  if (!loginBtn) {
365
- this.emit('warn', 'Login button not found');
366
+ if (this.logWarn) this.emit('warn', 'Login button not found');
366
367
  return null;
367
368
  }
368
369
 
369
370
  if (page.isClosed()) {
370
- this.emit('warn', 'Page closed before login click');
371
+ if (this.logWarn) this.emit('warn', 'Page closed before login click');
371
372
  return null;
372
373
  }
373
374
 
@@ -382,12 +383,12 @@ class MelCloud extends EventEmitter {
382
383
  const usernameInput = await page.$('input[name="username"]');
383
384
  const passwordInput = await page.$('input[name="password"]');
384
385
  if (!usernameInput || !passwordInput) {
385
- this.emit('warn', 'Username or password input not found');
386
+ if (this.logWarn) this.emit('warn', 'Username or password input not found');
386
387
  return null;
387
388
  }
388
389
 
389
390
  if (page.isClosed()) {
390
- this.emit('warn', 'Page closed before typing credentials');
391
+ if (this.logWarn) this.emit('warn', 'Page closed before typing credentials');
391
392
  return null;
392
393
  }
393
394
 
@@ -396,12 +397,12 @@ class MelCloud extends EventEmitter {
396
397
 
397
398
  const submitButton = await page.$('input[type="submit"], button[type="submit"]');
398
399
  if (!submitButton) {
399
- this.emit('warn', 'Submit button not found on login form');
400
+ if (this.logWarn) this.emit('warn', 'Submit button not found on login form');
400
401
  return null;
401
402
  }
402
403
 
403
404
  if (page.isClosed()) {
404
- this.emit('warn', 'Page closed before submitting form');
405
+ if (this.logWarn) this.emit('warn', 'Page closed before submitting form');
405
406
  return null;
406
407
  }
407
408
 
@@ -415,13 +416,13 @@ class MelCloud extends EventEmitter {
415
416
 
416
417
  const pageText = await page.content();
417
418
  if (pageText.includes('incorrect') || pageText.includes('Invalid') || pageText.includes('nieprawidłowe')) {
418
- this.emit('warn', 'Login failed: incorrect email or password');
419
+ if (this.logWarn) this.emit('warn', 'Login failed: incorrect email or password');
419
420
  return null;
420
421
  }
421
422
 
422
423
  const captchaPresent = await page.$('iframe[src*="captcha"], div[class*="captcha"]');
423
424
  if (captchaPresent) {
424
- this.emit('warn', 'Login blocked by CAPTCHA. Manual verification required.');
425
+ if (this.logWarn) this.emit('warn', 'Login blocked by CAPTCHA. Manual verification required.');
425
426
  return null;
426
427
  }
427
428
 
@@ -435,7 +436,7 @@ class MelCloud extends EventEmitter {
435
436
  }
436
437
 
437
438
  if (!c1 || !c2) {
438
- this.emit('warn', 'Cookies C1/C2 missing after login');
439
+ if (this.logWarn) this.emit('warn', 'Cookies C1/C2 missing after login');
439
440
  return null;
440
441
  }
441
442
 
@@ -456,7 +457,7 @@ class MelCloud extends EventEmitter {
456
457
  // Puppeteer / system error handling
457
458
  if (error.message.includes('libnspr4.so') || error.message.includes('Failed to launch the browser process')) {
458
459
  const inDocker = await this.functions.isRunningInDocker();
459
- this.emit('warn', `Missing system libraries detected.`);
460
+ if (this.logError) this.emit('error', `Missing system libraries detected.`);
460
461
 
461
462
  const installCmd =
462
463
  'apt-get update && apt-get install -y ' +
@@ -465,7 +466,7 @@ class MelCloud extends EventEmitter {
465
466
  'libgbm1 libasound2 libxshmfence1 fonts-liberation libappindicator3-1 libu2f-udev';
466
467
 
467
468
  if (inDocker) {
468
- this.emit('warn', `Running in Docker — attempting automatic fix...`);
469
+ if (this.logWarn) this.emit('warn', `Running in Docker — attempting automatic fix...`);
469
470
  try {
470
471
  const { execSync } = require('child_process');
471
472
  execSync(installCmd, { stdio: 'inherit' });
@@ -486,7 +487,7 @@ class MelCloud extends EventEmitter {
486
487
  try {
487
488
  await browser.close();
488
489
  } catch (closeErr) {
489
- this.emit('warn', `Failed to close Puppeteer browser: ${closeErr.message}`);
490
+ if (this.logError) this.emit('error', `Failed to close Puppeteer browser: ${closeErr.message}`);
490
491
  }
491
492
  }
492
493
  }
@@ -59,7 +59,7 @@ class MelCloudHomeToken extends EventEmitter {
59
59
  const csrf = dom.window.document.querySelector('input[name="_csrf"]')?.value;
60
60
 
61
61
  if (!csrf) {
62
- this.emit('warn', 'CSRF token not found');
62
+ if (this.logWarn) this.emit('warn', 'CSRF token not found');
63
63
  return null;
64
64
  }
65
65
 
@@ -85,7 +85,7 @@ class MelCloudHomeToken extends EventEmitter {
85
85
  });
86
86
 
87
87
  if (response.status === 400) {
88
- this.emit('warn', `Login failed: ${response.data}`);
88
+ if (this.logWarn) this.emit('warn', `Login failed: ${response.data}`);
89
89
  return null;
90
90
  }
91
91
 
@@ -106,7 +106,7 @@ class MelCloudHomeToken extends EventEmitter {
106
106
  return code || null;
107
107
 
108
108
  } catch (err) {
109
- this.emit('warn', `loginToMelCloudHome error: ${err}`);
109
+ if (this.logWarn) this.emit('warn', `loginToMelCloudHome error: ${err}`);
110
110
  return null;
111
111
  }
112
112
  }
@@ -120,7 +120,7 @@ class MelCloudHomeToken extends EventEmitter {
120
120
  if (locationHeader && locationHeader.startsWith('melcloudhome://')) {
121
121
  const match = locationHeader.match(/[?&]code=([^&]+)/);
122
122
  if (match) {
123
- this.emit('warn', `Found code in Location header: ${match[1]}`);
123
+ if (this.logWarn) this.emit('warn', `Found code in Location header: ${match[1]}`);
124
124
  resolve(match[1]);
125
125
  return;
126
126
  }
@@ -132,14 +132,14 @@ class MelCloudHomeToken extends EventEmitter {
132
132
  const formActionMatch = data.match(/action="([^"]+)"/);
133
133
 
134
134
  if (formCodeMatch && formStateMatch && formActionMatch) {
135
- this.emit('warn', 'Found form_post, submitting...');
135
+ if (this.logWarn) this.emit('warn', 'Found form_post, submitting...');
136
136
  try {
137
137
  const code = await this.submitFormPost(formActionMatch[1], formCodeMatch[1], formStateMatch[1]);
138
- this.emit('warn', `submitFormPost returned code: ${code}`);
138
+ if (this.logWarn) this.emit('warn', `submitFormPost returned code: ${code}`);
139
139
  resolve(code);
140
140
  return;
141
141
  } catch (err) {
142
- this.emit('warn', `submitFormPost failed: ${err}`);
142
+ if (this.logWarn) this.emit('warn', `submitFormPost failed: ${err}`);
143
143
  reject(err);
144
144
  return;
145
145
  }
@@ -148,29 +148,29 @@ class MelCloudHomeToken extends EventEmitter {
148
148
  // 3️⃣ JS redirect in body
149
149
  const bodyCodeMatch = data.match(/melcloudhome:\/\/[^"'\s]*[?&]code=([^&"'\s]+)/);
150
150
  if (bodyCodeMatch) {
151
- this.emit('warn', `Found code in body: ${bodyCodeMatch[1]}`);
151
+ if (this.logWarn) this.emit('warn', `Found code in body: ${bodyCodeMatch[1]}`);
152
152
  resolve(bodyCodeMatch[1]);
153
153
  return;
154
154
  }
155
155
 
156
156
  // 4️⃣ Follow redirect
157
157
  if (locationHeader && ['301', '302', '303'].includes(headers['status'] || '')) {
158
- this.emit('warn', `Following redirect to ${locationHeader}`);
158
+ if (this.logWarn) this.emit('warn', `Following redirect to ${locationHeader}`);
159
159
  try {
160
160
  const code = await followRedirect(locationHeader);
161
161
  resolve(code);
162
162
  return;
163
163
  } catch (err) {
164
- this.emit('warn', `Follow redirect failed: ${err}`);
164
+ if (this.logWarn) this.emit('warn', `Follow redirect failed: ${err}`);
165
165
  reject(err);
166
166
  return;
167
167
  }
168
168
  }
169
169
 
170
- this.emit('warn', 'Authorization code not found in response');
170
+ if (this.logWarn) this.emit('warn', 'Authorization code not found in response');
171
171
  reject(new Error('Authorization code not found'));
172
172
  } catch (err) {
173
- this.emit('warn', `extractCodeFromResponse error: ${err}`);
173
+ if (this.logWarn) this.emit('warn', `extractCodeFromResponse error: ${err}`);
174
174
  reject(err);
175
175
  }
176
176
  });
@@ -178,7 +178,7 @@ class MelCloudHomeToken extends EventEmitter {
178
178
 
179
179
  async submitFormPost(actionUrl, code, state) {
180
180
  const formData = new URLSearchParams({ code, state });
181
- this.emit('warn', `Submitting form_post to ${actionUrl}`);
181
+ if (this.logWarn) this.emit('warn', `Submitting form_post to ${actionUrl}`);
182
182
  const res = await this.client.post(actionUrl, formData.toString(), {
183
183
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
184
184
  maxRedirects: 0,
@@ -191,7 +191,7 @@ class MelCloudHomeToken extends EventEmitter {
191
191
  if (match) return match[1];
192
192
  }
193
193
 
194
- this.emit('warn', 'Code not found after form_post submission');
194
+ if (this.logWarn) this.emit('warn', 'Code not found after form_post submission');
195
195
  throw new Error('Code not found after form_post submission');
196
196
  }
197
197
 
@@ -213,7 +213,7 @@ class MelCloudHomeToken extends EventEmitter {
213
213
  });
214
214
 
215
215
  const tokens = tokenResponse.data;
216
- this.emit('warn', `Token obtained: ${JSON.stringify(tokens)}`);
216
+ if (this.logWarn) this.emit('warn', `Token obtained: ${JSON.stringify(tokens)}`);
217
217
  return tokens;
218
218
 
219
219
  } catch (err) {
package/src/restful.js CHANGED
@@ -65,7 +65,7 @@ class RestFul extends EventEmitter {
65
65
 
66
66
  // Start the server
67
67
  app.listen(this.port, () => {
68
- this.emit('connected', `RESTful started on port: ${this.restFulPort}`);
68
+ this.emit('connected', `RESTful started on port: ${this.port}`);
69
69
  });
70
70
  } catch (error) {
71
71
  if (this.logWarn) this.emit('warn', `RESTful Connect error: ${error}`);