homebridge-melcloud-control 4.0.0-beta.29 → 4.0.0-beta.3

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 cookiesFile = `${prefDir}/${accountName}_Cookies`;
79
+ const coociesFile = `${prefDir}/${accountName}_Coocies`;
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, cookiesFile, logLevel.warn, logLevel.debug, false)
91
+ const melCloud = new MelCloud(user, passwd, language, accountFile, buildingsFile, devicesFile, coociesFile, 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.connectHomeCookies();
98
+ await melCloud.connectHomeCoocies()
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.29",
4
+ "version": "4.0.0-beta.3",
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, cookiesFile, logWarn, logDebug, requestConfig) {
10
+ constructor(user, passwd, language, accountFile, buildingsFile, devicesFile, coociesFile, 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.cookiesFile = cookiesFile;
18
+ this.coociesFile = coociesFile;
19
19
  this.logWarn = logWarn;
20
20
  this.logDebug = logDebug;
21
21
  this.requestConfig = requestConfig;
@@ -213,114 +213,83 @@ class MelCloud extends EventEmitter {
213
213
  }
214
214
  }
215
215
 
216
- async loginToMelcloudHome() {
217
- try {
218
- const form = new URLSearchParams();
219
- form.append('user[email]', this.user);
220
- form.append('user[password]', this.passwd);
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');
221
223
 
222
- const response = await axios({
223
- method: 'POST',
224
- baseURL: EnphaseUrls.BaseUrl,
225
- url: EnphaseUrls.Login,
226
- headers: {
227
- 'Content-Type': 'application/x-www-form-urlencoded'
228
- },
229
- data: form,
230
- timeout: 10000
231
- });
232
224
 
233
- if (response.status !== 200) {
234
- if (this.logError) this.emit('error', `Login failed with status code: ${response.status}`);
235
- return null;
236
- }
237
225
 
238
- const cookie = response.headers['set-cookie'];
239
- if (!cookie) {
240
- if (this.logWarn) this.emit('warn', `No cookie returned from login. Response headers: ${JSON.stringify(response.headers)}`);
241
- return null;
242
- }
243
-
244
- return cookie;
245
- } catch (error) {
246
- throw new Error(`Login to Enlighten error: ${error}`);
247
- }
248
- }
226
+ const browser = await puppeteer.launch({
227
+ headless: true,
228
+ args: ['--no-sandbox', '--disable-setuid-sandbox']
229
+ });
249
230
 
250
- async connectHomeCookies() {
251
- const loginUrl = 'https://melcloudhome.com';
252
- const browser = await puppeteer.launch({ headless: true, args: ['--no-sandbox', '--disable-setuid-sandbox'] });
253
231
  const page = await browser.newPage();
254
232
 
255
- try {
256
- this.emit('warn', 'Opening login page...');
257
- await page.goto(loginUrl, { waitUntil: 'networkidle2' });
258
-
259
- // Kliknij przycisk logowania
260
- const buttons = await page.$$('button.btn--blue');
261
- let loginBtn = null;
262
- for (const btn of buttons) {
263
- const text = await page.evaluate(el => el.textContent, btn);
264
- if (text.trim() === 'Zaloguj') {
265
- loginBtn = btn;
266
- break;
267
- }
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
+ // Sprawdź kilka możliwych wariantów
243
+ const buttonSelectors = [
244
+ 'button[type="submit"]',
245
+ 'input[type="submit"]',
246
+ 'button[name="signIn"]',
247
+ 'button.btn-primary',
248
+ 'button:has-text("Sign in")',
249
+ 'button:has-text("Zaloguj")'
250
+ ];
251
+
252
+ // Kliknij "Sign in" (przycisk AWS Cognito)
253
+ let buttonFound = false;
254
+ for (const selector of buttonSelectors) {
255
+ const button = await page.$(selector);
256
+ if (button) {
257
+ console.log(`Found submit button: ${selector}`);
258
+ await Promise.all([
259
+ button.click(),
260
+ page.waitForNavigation({ waitUntil: 'networkidle2', timeout: 15000 })
261
+ ]);
262
+ buttonFound = true;
263
+ break;
268
264
  }
265
+ }
269
266
 
270
- if (!loginBtn) throw new Error('Login button not found on homepage');
271
-
272
- await Promise.all([
273
- loginBtn.click(),
274
- page.waitForNavigation({ waitUntil: 'networkidle2', timeout: 20000 })
275
- ]);
276
-
277
- // Poczekaj, aż strona przekieruje do Cognito login
278
- await page.waitForSelector('input[name="username"]', { timeout: 15000 });
279
-
280
- this.emit('warn', 'Typing credentials...');
281
- await page.type('input[name="username"]', this.user, { delay: 50 });
282
- await page.type('input[name="password"]', this.passwd, { delay: 50 });
267
+ if (!buttonFound) {
268
+ throw new Error('❌ Could not find login button on the page.');
269
+ }
283
270
 
284
- // Kliknij przycisk logowania
285
- const button1 = await page.$('input[type="submit"]');
286
- await Promise.all([
287
- button1.click(),
288
- page.waitForNavigation({ waitUntil: 'networkidle2', timeout: 20000 })
289
- ]);
271
+ // Poczekaj załaduje się MELCloud Home
272
+ this.emit('warn', `Waiting for redirect to melcloudhome.com...`);
273
+ await page.waitForTimeout(5000);
290
274
 
291
- let c1 = null, c2 = null;
292
- const start = Date.now();
275
+ // Pobierz cookies dla domeny melcloudhome.com
276
+ const cookies = await page.cookies();
293
277
 
294
- // Loop max 20s, czekamy aż pojawią się cookies
295
- while ((!c1 || !c2) && Date.now() - start < 20000) {
296
- const cookies = await page.cookies();
297
- c1 = cookies.find(c => c.name === '__Secure-monitorandcontrolC1')?.value || c1;
298
- c2 = cookies.find(c => c.name === '__Secure-monitorandcontrolC2')?.value || c2;
299
- if (!c1 || !c2) await new Promise(r => setTimeout(r, 500));
300
- }
278
+ // Znajdź __Secure-monitorandcontrolC1 i C2
279
+ const c1 = cookies.find(c => c.name === '__Secure-monitorandcontrolC1')?.value || null;
280
+ const c2 = cookies.find(c => c.name === '__Secure-monitorandcontrolC2')?.value || null;
301
281
 
302
- if (!c1 || !c2) {
303
- await browser.close();
304
- throw new Error('❌ Cookies C1/C2 not found after login');
305
- }
282
+ // Zapisz do pliku
283
+ const data = { C1: c1, C2: c2, date: new Date().toISOString() };
284
+ await this.functions.saveData(this.coociesFile, data);
306
285
 
307
- // Zapis do pliku
308
- const data = { C1: c1, C2: c2, date: new Date().toISOString() };
309
- await this.functions.saveData(this.cookiesFile, data);
286
+ await browser.close();
310
287
 
311
- this.emit('warn', 'Login successful.');
312
- return data;
288
+ this.emit('warn', `Login successful.`);
313
289
 
314
- } catch (err) {
315
- this.emit('error', `Login failed: ${err.message}`);
316
- return null;
317
- } finally {
318
- await browser.close();
319
- }
290
+ return false;
320
291
  }
321
292
 
322
-
323
-
324
293
  async send(accountInfo) {
325
294
  try {
326
295
  const options = { data: accountInfo };