homebridge-melcloud-control 4.0.0-beta.2 → 4.0.0-beta.21

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
@@ -76,7 +76,7 @@ class MelCloudPlatform {
76
76
  const accountFile = `${prefDir}/${accountName}_Account`;
77
77
  const buildingsFile = `${prefDir}/${accountName}_Buildings`;
78
78
  const devicesFile = `${prefDir}/${accountName}_Devices`;
79
- const coociesFile = `${prefDir}/${accountName}_Coocies`;
79
+ const cookiesFile = `${prefDir}/${accountName}_Cookies`;
80
80
 
81
81
 
82
82
  //set account refresh interval
@@ -88,14 +88,14 @@ class MelCloudPlatform {
88
88
  .on('start', async () => {
89
89
  try {
90
90
  //melcloud account
91
- const melCloud = new MelCloud(user, passwd, language, accountFile, buildingsFile, devicesFile, coociesFile, logLevel.warn, logLevel.debug, false)
91
+ const melCloud = new MelCloud(user, passwd, language, accountFile, buildingsFile, devicesFile, cookiesFile, logLevel.warn, logLevel.debug, false)
92
92
  .on('success', (msg) => logLevel.success && log.success(`${accountName}, ${msg}`))
93
93
  .on('info', (msg) => logLevel.info && log.info(`${accountName}, ${msg}`))
94
94
  .on('debug', (msg) => logLevel.debug && log.info(`${accountName}, debug: ${msg}`))
95
95
  .on('warn', (msg) => logLevel.warn && log.warn(`${accountName}, ${msg}`))
96
96
  .on('error', (msg) => logLevel.error && log.error(`${accountName}, ${msg}`));
97
97
 
98
- await melCloud.connectHomeCoocies()
98
+ await melCloud.connectHomeCookies();
99
99
  return;
100
100
 
101
101
 
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.2",
4
+ "version": "4.0.0-beta.21",
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
@@ -7,7 +7,7 @@ import Functions from './functions.js';
7
7
  import { ApiUrls, ApiUrlsHome } from './constants.js';
8
8
 
9
9
  class MelCloud extends EventEmitter {
10
- constructor(user, passwd, language, accountFile, buildingsFile, devicesFile, coociesFile, logWarn, logDebug, requestConfig) {
10
+ constructor(user, passwd, language, accountFile, buildingsFile, devicesFile, cookiesFile, logWarn, logDebug, requestConfig) {
11
11
  super();
12
12
  this.user = user;
13
13
  this.passwd = passwd;
@@ -15,7 +15,7 @@ class MelCloud extends EventEmitter {
15
15
  this.accountFile = accountFile;
16
16
  this.buildingsFile = buildingsFile;
17
17
  this.devicesFile = devicesFile;
18
- this.coociesFile = coociesFile;
18
+ this.cookiesFile = cookiesFile;
19
19
  this.logWarn = logWarn;
20
20
  this.logDebug = logDebug;
21
21
  this.requestConfig = requestConfig;
@@ -213,73 +213,80 @@ class MelCloud extends EventEmitter {
213
213
  }
214
214
  }
215
215
 
216
- async connectHomeCoocies() {
217
- const loginUrl = new URL('https://live-melcloudhome.auth.eu-west-1.amazoncognito.com/login');
218
- loginUrl.searchParams.set('client_id', '3g4d5l5kivuqi7oia68gib7uso');
219
- loginUrl.searchParams.set('redirect_uri', 'https://auth.melcloudhome.com/signin-oidc-meu');
220
- loginUrl.searchParams.set('response_type', 'code');
221
- loginUrl.searchParams.set('scope', 'openid profile');
222
- loginUrl.searchParams.set('response_mode', 'form_post');
223
-
224
-
225
-
226
- const browser = await puppeteer.launch({
227
- headless: true,
228
- args: ['--no-sandbox', '--disable-setuid-sandbox']
229
- });
230
-
231
- const page = await browser.newPage();
232
-
233
- // Otwórz stronę logowania
234
- this.emit('warn', `Opening login page...`);
235
- await page.goto(loginUrl, { waitUntil: 'networkidle2' });
236
-
237
- // Wpisz login i hasło
238
- this.emit('warn', `Typing credentials...`);
239
- await page.type('input[name="username"]', this.user, { delay: 50 });
240
- await page.type('input[name="password"]', this.passwd, { delay: 50 });
241
-
242
- // Kliknij "Sign in" (przycisk AWS Cognito)
243
- let buttonFound = false;
244
- for (const selector of buttonSelectors) {
245
- const button = await page.$(selector);
246
- if (button) {
247
- console.log(`Found submit button: ${selector}`);
248
- await Promise.all([
249
- button.click(),
250
- page.waitForNavigation({ waitUntil: 'networkidle2', timeout: 15000 })
251
- ]);
252
- buttonFound = true;
253
- break;
216
+ async connectHomeCookies() {
217
+ try {
218
+ const loginUrl = 'https://melcloudhome.com';
219
+ const browser = await puppeteer.launch({ headless: true, args: ['--no-sandbox', '--disable-setuid-sandbox'] });
220
+ const page = await browser.newPage();
221
+
222
+ this.emit('warn', 'Opening login page...');
223
+ await page.goto(loginUrl, { waitUntil: 'networkidle2' });
224
+
225
+ // Kliknij przycisk logowania
226
+ const buttons = await page.$$('button.btn--blue'); // wszystkie buttony z klasą btn--blue
227
+ let loginBtn = null;
228
+ for (const btn of buttons) {
229
+ const text = await page.evaluate(el => el.textContent, btn);
230
+ if (text.trim() === 'Zaloguj') {
231
+ loginBtn = btn;
232
+ break;
233
+ }
254
234
  }
255
- }
256
235
 
257
- if (!buttonFound) {
258
- throw new Error('❌ Could not find login button on the page.');
259
- }
236
+ if (!loginBtn) throw new Error('Login button not found on homepage');
237
+
238
+ await Promise.all([
239
+ loginBtn.click(),
240
+ page.waitForNavigation({ waitUntil: 'networkidle2', timeout: 20000 })
241
+ ]);
242
+
243
+ // Poczekaj, aż strona przekieruje do Cognito login
244
+ await page.waitForSelector('input[name="username"]', { timeout: 15000 });
260
245
 
261
- // Poczekaj aż załaduje się MELCloud Home
262
- this.emit('warn', `Waiting for redirect to melcloudhome.com...`);
263
- await page.waitForTimeout(5000);
246
+ this.emit('warn', 'Typing credentials...');
247
+ await page.type('input[name="username"]', this.user, { delay: 50 });
248
+ await page.type('input[name="password"]', this.passwd, { delay: 50 });
264
249
 
265
- // Pobierz cookies dla domeny melcloudhome.com
266
- const cookies = await page.cookies();
250
+ // Kliknij przycisk logowania
251
+ const button1 = await page.$('input[type="submit"]');
252
+ await Promise.all([
253
+ button1.click(),
254
+ page.waitForNavigation({ waitUntil: 'networkidle2', timeout: 20000 })
255
+ ]);
267
256
 
268
- // Znajdź __Secure-monitorandcontrolC1 i C2
269
- const c1 = cookies.find(c => c.name === '__Secure-monitorandcontrolC1')?.value || null;
270
- const c2 = cookies.find(c => c.name === '__Secure-monitorandcontrolC2')?.value || null;
257
+ let c1 = null, c2 = null;
258
+ const start = Date.now();
271
259
 
272
- // Zapisz do pliku
273
- const data = { C1: c1, C2: c2, date: new Date().toISOString() };
274
- await this.functions.saveData(this.coociesFile, data);
260
+ // Loop max 20s, czekamy aż pojawią się cookies
261
+ while ((!c1 || !c2) && Date.now() - start < 20000) {
262
+ const cookies = await page.cookies();
263
+ c1 = cookies.find(c => c.name === '__Secure-monitorandcontrolC1')?.value || c1;
264
+ c2 = cookies.find(c => c.name === '__Secure-monitorandcontrolC2')?.value || c2;
265
+ if (!c1 || !c2) await new Promise(r => setTimeout(r, 500));
266
+ }
267
+
268
+ if (!c1 || !c2) {
269
+ await browser.close();
270
+ throw new Error('❌ Cookies C1/C2 not found after login');
271
+ }
275
272
 
276
- await browser.close();
273
+ // Zapis do pliku
274
+ const data = { C1: c1, C2: c2, date: new Date().toISOString() };
275
+ await this.functions.saveData(this.cookiesFile, data);
277
276
 
278
- this.emit('warn', `Login successful.`);
277
+ this.emit('warn', 'Login successful.');
278
+ return data;
279
279
 
280
- return false;
280
+ } catch (err) {
281
+ this.emit('error', `Login failed: ${err.message}`);
282
+ return null;
283
+ } finally {
284
+ await browser.close();
285
+ }
281
286
  }
282
287
 
288
+
289
+
283
290
  async send(accountInfo) {
284
291
  try {
285
292
  const options = { data: accountInfo };