homebridge-melcloud-control 4.0.0-beta.260 → 4.0.0-beta.262
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/package.json +3 -2
- package/src/melcloud.js +75 -8
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.262",
|
|
5
5
|
"description": "Homebridge plugin to control Mitsubishi Air Conditioner, Heat Pump and Energy Recovery Ventilation.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "grzegorz914",
|
|
@@ -42,7 +42,8 @@
|
|
|
42
42
|
"puppeteer": "^24.26.1",
|
|
43
43
|
"axios-cookiejar-support": "^6.0.4",
|
|
44
44
|
"tough-cookie": "^6.0.0",
|
|
45
|
-
"cheerio": "^1.1.2"
|
|
45
|
+
"cheerio": "^1.1.2",
|
|
46
|
+
"node-fetch": "^3.3.2"
|
|
46
47
|
},
|
|
47
48
|
"keywords": [
|
|
48
49
|
"homebridge",
|
package/src/melcloud.js
CHANGED
|
@@ -7,6 +7,8 @@ import MelCloudHomeToken from './melcloudhometoken.js';
|
|
|
7
7
|
import ImpulseGenerator from './impulsegenerator.js';
|
|
8
8
|
import Functions from './functions.js';
|
|
9
9
|
import { ApiUrls, ApiUrlsHome } from './constants.js';
|
|
10
|
+
import fetch from 'node-fetch';
|
|
11
|
+
import { URLSearchParams } from 'url';
|
|
10
12
|
|
|
11
13
|
class MelCloud extends EventEmitter {
|
|
12
14
|
constructor(accountType, user, passwd, language, accountFile, buildingsFile, devicesFile, logWarn, logDebug, requestConfig) {
|
|
@@ -175,14 +177,6 @@ class MelCloud extends EventEmitter {
|
|
|
175
177
|
}
|
|
176
178
|
|
|
177
179
|
// MELCloud Home
|
|
178
|
-
async connectToMelCloudHome() {
|
|
179
|
-
const oauth = new MelCloudHomeToken();
|
|
180
|
-
this.tokens = await oauth.getTokensWithCredentials(this.user, this.passwd);
|
|
181
|
-
this.emit('warn', `Token ${JSON.stringify(this.tokens, null, 2)}`);
|
|
182
|
-
//this.axiosInstance.defaults.headers['Authorization'] = `Bearer ${this.tokens.accessToken}`;
|
|
183
|
-
return false;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
180
|
async checkMelcloudHomeDevicesList(contextKey) {
|
|
187
181
|
try {
|
|
188
182
|
const axiosInstance = axios.create({
|
|
@@ -286,6 +280,79 @@ class MelCloud extends EventEmitter {
|
|
|
286
280
|
}
|
|
287
281
|
}
|
|
288
282
|
|
|
283
|
+
async connectToMelCloudHome() {
|
|
284
|
+
let browser;
|
|
285
|
+
try {
|
|
286
|
+
browser = await puppeteer.launch({
|
|
287
|
+
headless: true,
|
|
288
|
+
args: ['--no-sandbox', '--disable-setuid-sandbox']
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
const page = await browser.newPage();
|
|
292
|
+
await page.goto(ApiUrlsHome.BaseURL, { waitUntil: 'networkidle2' });
|
|
293
|
+
|
|
294
|
+
// Kliknięcie przycisku logowania
|
|
295
|
+
const loginBtn = await page.$x("//button[contains(text(),'Log In') or contains(text(),'Zaloguj')]");
|
|
296
|
+
if (loginBtn.length === 0) throw new Error('Login button not found');
|
|
297
|
+
await Promise.all([
|
|
298
|
+
loginBtn[0].click(),
|
|
299
|
+
page.waitForNavigation({ waitUntil: 'networkidle2' })
|
|
300
|
+
]);
|
|
301
|
+
|
|
302
|
+
// Wpisanie loginu i hasła
|
|
303
|
+
await page.type('input[name="username"]', this.user, { delay: 50 });
|
|
304
|
+
await page.type('input[name="password"]', this.passwd, { delay: 50 });
|
|
305
|
+
|
|
306
|
+
// Kliknięcie submit
|
|
307
|
+
const submitBtn = await page.$('input[type="submit"]');
|
|
308
|
+
if (!submitBtn) throw new Error('Submit button not found');
|
|
309
|
+
await Promise.all([
|
|
310
|
+
submitBtn.click(),
|
|
311
|
+
page.waitForNavigation({ waitUntil: 'networkidle2' })
|
|
312
|
+
]);
|
|
313
|
+
|
|
314
|
+
// Wyłapanie kodu z URL
|
|
315
|
+
const currentUrl = page.url();
|
|
316
|
+
const codeMatch = currentUrl.match(/[?&]code=([^&]+)/);
|
|
317
|
+
if (!codeMatch) throw new Error('Authorization code not found in URL');
|
|
318
|
+
const authorizationCode = codeMatch[1];
|
|
319
|
+
|
|
320
|
+
// Zamknięcie przeglądarki
|
|
321
|
+
await browser.close();
|
|
322
|
+
|
|
323
|
+
// Pobranie tokenów
|
|
324
|
+
const params = new URLSearchParams();
|
|
325
|
+
params.append('grant_type', 'authorization_code');
|
|
326
|
+
params.append('code', authorizationCode);
|
|
327
|
+
params.append('client_id', 'melCloudWeb');
|
|
328
|
+
params.append('redirect_uri', 'melcloudhome://');
|
|
329
|
+
|
|
330
|
+
const tokenResp = await fetch('https://auth.melcloudhome.com/connect/token', {
|
|
331
|
+
method: 'POST',
|
|
332
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
333
|
+
body: params.toString()
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
if (!tokenResp.ok) {
|
|
337
|
+
const errText = await tokenResp.text();
|
|
338
|
+
throw new Error(`Token request failed: ${errText}`);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
const tokenData = await tokenResp.json();
|
|
342
|
+
this.emit('debug', `Token: ${JSON.stringify(tokenData, null, 2)}`);
|
|
343
|
+
return {
|
|
344
|
+
accessToken: tokenData.access_token,
|
|
345
|
+
refreshToken: tokenData.refresh_token,
|
|
346
|
+
expiresIn: tokenData.expires_in
|
|
347
|
+
};
|
|
348
|
+
|
|
349
|
+
} catch (error) {
|
|
350
|
+
if (browser) await browser.close().catch(() => { });
|
|
351
|
+
throw error;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
|
|
289
356
|
async connectToMelCloudHome1(refresh = false) {
|
|
290
357
|
if (this.logDebug) this.emit('debug', `Connecting to MELCloud Home`);
|
|
291
358
|
|