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 +3 -3
- package/package.json +1 -1
- package/src/melcloud.js +62 -93
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
|
|
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,
|
|
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.
|
|
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.
|
|
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,
|
|
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.
|
|
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
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
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
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
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
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
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
|
-
|
|
271
|
-
|
|
272
|
-
|
|
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
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
button1.click(),
|
|
288
|
-
page.waitForNavigation({ waitUntil: 'networkidle2', timeout: 20000 })
|
|
289
|
-
]);
|
|
271
|
+
// Poczekaj aż załaduje się MELCloud Home
|
|
272
|
+
this.emit('warn', `Waiting for redirect to melcloudhome.com...`);
|
|
273
|
+
await page.waitForTimeout(5000);
|
|
290
274
|
|
|
291
|
-
|
|
292
|
-
|
|
275
|
+
// Pobierz cookies dla domeny melcloudhome.com
|
|
276
|
+
const cookies = await page.cookies();
|
|
293
277
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
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
|
-
|
|
303
|
-
|
|
304
|
-
|
|
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
|
-
|
|
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
|
-
|
|
312
|
-
return data;
|
|
288
|
+
this.emit('warn', `Login successful.`);
|
|
313
289
|
|
|
314
|
-
|
|
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 };
|