homebridge-melcloud-control 4.0.0-beta.2 → 4.0.0-beta.20
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 +58 -61
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 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,
|
|
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.
|
|
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.
|
|
4
|
+
"version": "4.0.0-beta.20",
|
|
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, 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.
|
|
18
|
+
this.cookiesFile = cookiesFile;
|
|
19
19
|
this.logWarn = logWarn;
|
|
20
20
|
this.logDebug = logDebug;
|
|
21
21
|
this.requestConfig = requestConfig;
|
|
@@ -213,72 +213,69 @@ class MelCloud extends EventEmitter {
|
|
|
213
213
|
}
|
|
214
214
|
}
|
|
215
215
|
|
|
216
|
-
async
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
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 loginBtn = await page.$x("//button[contains(text(), 'Zaloguj')]");
|
|
227
|
+
if (!loginBtn || loginBtn.length === 0) throw new Error('Login button not found on homepage');
|
|
228
|
+
await Promise.all([
|
|
229
|
+
loginBtn[0].click(),
|
|
230
|
+
page.waitForNavigation({ waitUntil: 'networkidle2', timeout: 20000 })
|
|
231
|
+
]);
|
|
232
|
+
|
|
233
|
+
// Poczekaj, aż strona przekieruje do Cognito login
|
|
234
|
+
await page.waitForSelector('input[name="username"]', { timeout: 15000 });
|
|
235
|
+
|
|
236
|
+
this.emit('warn', 'Typing credentials...');
|
|
237
|
+
await page.type('input[name="username"]', this.user, { delay: 50 });
|
|
238
|
+
await page.type('input[name="password"]', this.passwd, { delay: 50 });
|
|
239
|
+
|
|
240
|
+
// Kliknij przycisk logowania
|
|
241
|
+
const button1 = await page.$('input[type="submit"]');
|
|
242
|
+
await Promise.all([
|
|
243
|
+
button1.click(),
|
|
244
|
+
page.waitForNavigation({ waitUntil: 'networkidle2', timeout: 20000 })
|
|
245
|
+
]);
|
|
246
|
+
|
|
247
|
+
let c1 = null, c2 = null;
|
|
248
|
+
const start = Date.now();
|
|
249
|
+
|
|
250
|
+
// Loop max 20s, czekamy aż pojawią się cookies
|
|
251
|
+
while ((!c1 || !c2) && Date.now() - start < 20000) {
|
|
252
|
+
const cookies = await page.cookies();
|
|
253
|
+
c1 = cookies.find(c => c.name === '__Secure-monitorandcontrolC1')?.value || c1;
|
|
254
|
+
c2 = cookies.find(c => c.name === '__Secure-monitorandcontrolC2')?.value || c2;
|
|
255
|
+
if (!c1 || !c2) await new Promise(r => setTimeout(r, 500));
|
|
254
256
|
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
if (!buttonFound) {
|
|
258
|
-
throw new Error('❌ Could not find login button on the page.');
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
// Poczekaj aż załaduje się MELCloud Home
|
|
262
|
-
this.emit('warn', `Waiting for redirect to melcloudhome.com...`);
|
|
263
|
-
await page.waitForTimeout(5000);
|
|
264
257
|
|
|
265
|
-
|
|
266
|
-
|
|
258
|
+
if (!c1 || !c2) {
|
|
259
|
+
await browser.close();
|
|
260
|
+
throw new Error('❌ Cookies C1/C2 not found after login');
|
|
261
|
+
}
|
|
267
262
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
263
|
+
// Zapis do pliku
|
|
264
|
+
const data = { C1: c1, C2: c2, date: new Date().toISOString() };
|
|
265
|
+
await this.functions.saveData(this.cookiesFile, data);
|
|
271
266
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
await this.functions.saveData(this.coociesFile, data);
|
|
267
|
+
this.emit('warn', 'Login successful.');
|
|
268
|
+
return data;
|
|
275
269
|
|
|
276
|
-
|
|
270
|
+
} catch (err) {
|
|
271
|
+
this.emit('error', `Login failed: ${err.message}`);
|
|
272
|
+
return null;
|
|
273
|
+
} finally {
|
|
274
|
+
await browser.close();
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
277
|
|
|
278
|
-
this.emit('warn', `Login successful.`);
|
|
279
278
|
|
|
280
|
-
return false;
|
|
281
|
-
}
|
|
282
279
|
|
|
283
280
|
async send(accountInfo) {
|
|
284
281
|
try {
|