homebridge-melcloud-control 4.0.0-beta.28 → 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.28",
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,100 +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
- }
226
+ const browser = await puppeteer.launch({
227
+ headless: true,
228
+ args: ['--no-sandbox', '--disable-setuid-sandbox']
229
+ });
243
230
 
244
- return cookie;
245
- } catch (error) {
246
- throw new Error(`Login to Enlighten error: ${error}`);
247
- }
248
- }
249
-
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
- ]);
267
+ if (!buttonFound) {
268
+ throw new Error('❌ Could not find login button on the page.');
269
+ }
276
270
 
277
- // Poczekaj,strona przekieruje do Cognito login
278
- await page.waitForSelector('input[name="username"]', { timeout: 15000 });
271
+ // Poczekaj aż załaduje się MELCloud Home
272
+ this.emit('warn', `Waiting for redirect to melcloudhome.com...`);
273
+ await page.waitForTimeout(5000);
279
274
 
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 });
275
+ // Pobierz cookies dla domeny melcloudhome.com
276
+ const cookies = await page.cookies();
283
277
 
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
- ]);
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;
290
281
 
291
- // Pobierz treść strony po zalogowaniu
292
- const responseHtml = await page.content(); // jeśli chcesz HTML
293
- this.emit('warn', `Login failed: ${responseHtml}`);
282
+ // Zapisz do pliku
283
+ const data = { C1: c1, C2: c2, date: new Date().toISOString() };
284
+ await this.functions.saveData(this.coociesFile, data);
294
285
 
295
- //await this.functions.saveData(this.cookiesFile, data);
286
+ await browser.close();
296
287
 
297
- this.emit('warn', 'Login successful.');
298
- return data;
288
+ this.emit('warn', `Login successful.`);
299
289
 
300
- } catch (err) {
301
- this.emit('error', `Login failed: ${err.message}`);
302
- return null;
303
- } finally {
304
- await browser.close();
305
- }
290
+ return false;
306
291
  }
307
292
 
308
-
309
-
310
293
  async send(accountInfo) {
311
294
  try {
312
295
  const options = { data: accountInfo };