homebridge-melcloud-control 4.0.0-beta.114 → 4.0.0-beta.116
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 +8 -6
- package/package.json +1 -1
- package/src/deviceata.js +2 -3
- package/src/melcloud.js +32 -24
- package/src/melcloudata.js +34 -34
package/index.js
CHANGED
|
@@ -30,8 +30,8 @@ class MelCloudPlatform {
|
|
|
30
30
|
api.on('didFinishLaunching', async () => {
|
|
31
31
|
//loop through accounts
|
|
32
32
|
for (const account of config.accounts) {
|
|
33
|
-
const
|
|
34
|
-
if (
|
|
33
|
+
const accountType = account.accountType || 'disabled';
|
|
34
|
+
if (accountType === 'disabled') continue;
|
|
35
35
|
|
|
36
36
|
const accountName = account.name;
|
|
37
37
|
const user = account.user;
|
|
@@ -90,7 +90,7 @@ class MelCloudPlatform {
|
|
|
90
90
|
.on('start', async () => {
|
|
91
91
|
try {
|
|
92
92
|
//melcloud account
|
|
93
|
-
const melCloud = new MelCloud(
|
|
93
|
+
const melCloud = new MelCloud(accountType, user, passwd, language, accountFile, buildingsFile, devicesFile, logLevel.warn, logLevel.debug, false)
|
|
94
94
|
.on('success', (msg) => logLevel.success && log.success(`${accountName}, ${msg}`))
|
|
95
95
|
.on('info', (msg) => logLevel.info && log.info(`${accountName}, ${msg}`))
|
|
96
96
|
.on('debug', (msg) => logLevel.debug && log.info(`${accountName}, debug: ${msg}`))
|
|
@@ -146,7 +146,7 @@ class MelCloudPlatform {
|
|
|
146
146
|
let configuredDevice;
|
|
147
147
|
switch (deviceType) {
|
|
148
148
|
case 0: //ATA
|
|
149
|
-
configuredDevice = new DeviceAta(api, account, device,
|
|
149
|
+
configuredDevice = new DeviceAta(api, account, device, devicesFile, useFahrenheit, restFul, mqtt);
|
|
150
150
|
break;
|
|
151
151
|
case 1: //ATW
|
|
152
152
|
configuredDevice = new DeviceAtw(api, account, device, contextKey, devicesFile, useFahrenheit, restFul, mqtt);
|
|
@@ -181,8 +181,10 @@ class MelCloudPlatform {
|
|
|
181
181
|
api.publishExternalAccessories(PluginName, [accessory]);
|
|
182
182
|
if (logLevel.success) log.success(`${accountName}, ${deviceTypeText}, ${deviceName}, Published as external accessory.`);
|
|
183
183
|
|
|
184
|
-
//start impulse generators
|
|
185
|
-
|
|
184
|
+
//start impulse generators\
|
|
185
|
+
const timmers = accountType === 'melcloudhome' ? [{ name: 'connect', sampling: 150000 }, { name: 'checkDevicesList', sampling: deviceRefreshInterval }] : [{ name: 'checkDevicesList', sampling: refreshInterval }];
|
|
186
|
+
const impulseGenerator = configuredDevice.getImpulseGenerator();
|
|
187
|
+
await melCloud.impulseGenerator.state(true, timmers);
|
|
186
188
|
await configuredDevice.startStopImpulseGenerator(true, [{ name: 'checkState', sampling: deviceRefreshInterval }]);
|
|
187
189
|
|
|
188
190
|
//stop impulse generator
|
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.116",
|
|
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/deviceata.js
CHANGED
|
@@ -6,7 +6,7 @@ import { TemperatureDisplayUnits, AirConditioner, ApiUrlsHome } from './constant
|
|
|
6
6
|
let Accessory, Characteristic, Service, Categories, AccessoryUUID;
|
|
7
7
|
|
|
8
8
|
class DeviceAta extends EventEmitter {
|
|
9
|
-
constructor(api, account, device,
|
|
9
|
+
constructor(api, account, device, devicesFile, useFahrenheit, restFul, mqtt) {
|
|
10
10
|
super();
|
|
11
11
|
|
|
12
12
|
Accessory = api.platformAccessory;
|
|
@@ -31,7 +31,6 @@ class DeviceAta extends EventEmitter {
|
|
|
31
31
|
this.logInfo = account.log?.info || false;
|
|
32
32
|
this.logWarn = account.log?.warn || false;
|
|
33
33
|
this.logDebug = account.log?.debug || false;
|
|
34
|
-
this.contextKey = contextKey;
|
|
35
34
|
this.accountName = account.name;
|
|
36
35
|
this.deviceId = device.id;
|
|
37
36
|
this.deviceName = device.name;
|
|
@@ -920,7 +919,7 @@ class DeviceAta extends EventEmitter {
|
|
|
920
919
|
async start() {
|
|
921
920
|
try {
|
|
922
921
|
//melcloud device
|
|
923
|
-
this.melCloudAta = new MelCloudAta(this.device, this.
|
|
922
|
+
this.melCloudAta = new MelCloudAta(this.device, this.devicesFile)
|
|
924
923
|
.on('deviceInfo', (manufacturer, modelIndoor, modelOutdoor, serialNumber, firmwareAppVersion) => {
|
|
925
924
|
if (this.logDeviceInfo && this.displayDeviceInfo) {
|
|
926
925
|
this.emit('devInfo', `---- ${this.deviceTypeText}: ${this.deviceName} ----`);
|
package/src/melcloud.js
CHANGED
|
@@ -7,9 +7,9 @@ import Functions from './functions.js';
|
|
|
7
7
|
import { ApiUrls, ApiUrlsHome } from './constants.js';
|
|
8
8
|
|
|
9
9
|
class MelCloud extends EventEmitter {
|
|
10
|
-
constructor(
|
|
10
|
+
constructor(accountType, user, passwd, language, accountFile, buildingsFile, devicesFile, logWarn, logDebug, requestConfig) {
|
|
11
11
|
super();
|
|
12
|
-
this.
|
|
12
|
+
this.accountType = accountType;
|
|
13
13
|
this.user = user;
|
|
14
14
|
this.passwd = passwd;
|
|
15
15
|
this.language = language;
|
|
@@ -45,6 +45,13 @@ class MelCloud extends EventEmitter {
|
|
|
45
45
|
|
|
46
46
|
if (!requestConfig) {
|
|
47
47
|
this.impulseGenerator = new ImpulseGenerator()
|
|
48
|
+
.on('connect', async () => {
|
|
49
|
+
try {
|
|
50
|
+
await this.connect();
|
|
51
|
+
} catch (error) {
|
|
52
|
+
this.emit('error', `Impulse generator error: ${error}`);
|
|
53
|
+
}
|
|
54
|
+
})
|
|
48
55
|
.on('checkDevicesList', async () => {
|
|
49
56
|
try {
|
|
50
57
|
await this.checkDevicesList(this.contextKey);
|
|
@@ -213,7 +220,7 @@ class MelCloud extends EventEmitter {
|
|
|
213
220
|
);
|
|
214
221
|
|
|
215
222
|
// Funkcja tworząca finalny obiekt Device
|
|
216
|
-
const createDevice = (device, type) => {
|
|
223
|
+
const createDevice = (device, type, contextKey) => {
|
|
217
224
|
// Settings już kapitalizowane w nazwach
|
|
218
225
|
const settingsArray = device.Settings || [];
|
|
219
226
|
|
|
@@ -241,6 +248,7 @@ class MelCloud extends EventEmitter {
|
|
|
241
248
|
|
|
242
249
|
return {
|
|
243
250
|
...rest,
|
|
251
|
+
ContextKey: contextKey,
|
|
244
252
|
Type: type,
|
|
245
253
|
DeviceID: Id,
|
|
246
254
|
DeviceName: GivenDisplayName,
|
|
@@ -249,9 +257,9 @@ class MelCloud extends EventEmitter {
|
|
|
249
257
|
};
|
|
250
258
|
|
|
251
259
|
return [
|
|
252
|
-
...(building.airToAirUnits || []).map(d => createDevice(capitalizeKeys(d), 0)),
|
|
253
|
-
...(building.airToWaterUnits || []).map(d => createDevice(capitalizeKeys(d), 1)),
|
|
254
|
-
...(building.airToVentilationUnits || []).map(d => createDevice(capitalizeKeys(d), 3))
|
|
260
|
+
...(building.airToAirUnits || []).map(d => createDevice(capitalizeKeys(d), 0, this.contextKey)),
|
|
261
|
+
...(building.airToWaterUnits || []).map(d => createDevice(capitalizeKeys(d), 1, this.contextKey)),
|
|
262
|
+
...(building.airToVentilationUnits || []).map(d => createDevice(capitalizeKeys(d), 3, this.contextKey))
|
|
255
263
|
];
|
|
256
264
|
});
|
|
257
265
|
|
|
@@ -292,13 +300,13 @@ class MelCloud extends EventEmitter {
|
|
|
292
300
|
if (!loginBtn && this.logWarn) this.emit('warn', `Login button not found`);
|
|
293
301
|
|
|
294
302
|
// Set credentials and login
|
|
295
|
-
await Promise.all([loginBtn.click(), page.waitForNavigation({ waitUntil: 'networkidle2', timeout:
|
|
296
|
-
await page.waitForSelector('input[name="username"]', { timeout:
|
|
303
|
+
await Promise.all([loginBtn.click(), page.waitForNavigation({ waitUntil: 'networkidle2', timeout: 5000 })]);
|
|
304
|
+
await page.waitForSelector('input[name="username"]', { timeout: 5000 });
|
|
297
305
|
await page.type('input[name="username"]', this.user, { delay: 50 });
|
|
298
306
|
await page.type('input[name="password"]', this.passwd, { delay: 50 });
|
|
299
307
|
|
|
300
308
|
const button1 = await page.$('input[type="submit"]');
|
|
301
|
-
await Promise.all([button1.click(), page.waitForNavigation({ waitUntil: 'networkidle2', timeout:
|
|
309
|
+
await Promise.all([button1.click(), page.waitForNavigation({ waitUntil: 'networkidle2', timeout: 5000 })]);
|
|
302
310
|
|
|
303
311
|
// Get cookies C1 and C2
|
|
304
312
|
let c1 = null, c2 = null;
|
|
@@ -332,23 +340,9 @@ class MelCloud extends EventEmitter {
|
|
|
332
340
|
}
|
|
333
341
|
}
|
|
334
342
|
|
|
335
|
-
async connect() {
|
|
336
|
-
let response = {};
|
|
337
|
-
switch (this.displayType) {
|
|
338
|
-
case "melcloud":
|
|
339
|
-
response = await this.connectToMelCloud();
|
|
340
|
-
return response
|
|
341
|
-
case "melcloudhome":
|
|
342
|
-
response = await this.connectToMelCloudHome();
|
|
343
|
-
return response
|
|
344
|
-
default:
|
|
345
|
-
return response
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
|
|
349
343
|
async checkDevicesList(contextKey) {
|
|
350
344
|
let devices = [];
|
|
351
|
-
switch (this.
|
|
345
|
+
switch (this.accountType) {
|
|
352
346
|
case "melcloud":
|
|
353
347
|
devices = await this.checkMelcloudDevicesList(contextKey);
|
|
354
348
|
return devices
|
|
@@ -360,6 +354,20 @@ class MelCloud extends EventEmitter {
|
|
|
360
354
|
}
|
|
361
355
|
}
|
|
362
356
|
|
|
357
|
+
async connect() {
|
|
358
|
+
let response = {};
|
|
359
|
+
switch (this.accountType) {
|
|
360
|
+
case "melcloud":
|
|
361
|
+
response = await this.connectToMelCloud();
|
|
362
|
+
return response
|
|
363
|
+
case "melcloudhome":
|
|
364
|
+
response = await this.connectToMelCloudHome();
|
|
365
|
+
return response
|
|
366
|
+
default:
|
|
367
|
+
return response
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
363
371
|
async send(accountInfo) {
|
|
364
372
|
try {
|
|
365
373
|
const options = { data: accountInfo };
|
package/src/melcloudata.js
CHANGED
|
@@ -6,7 +6,7 @@ import Functions from './functions.js';
|
|
|
6
6
|
import { ApiUrls, ApiUrlsHome, AirConditioner } from './constants.js';
|
|
7
7
|
|
|
8
8
|
class MelCloudAta extends EventEmitter {
|
|
9
|
-
constructor(device,
|
|
9
|
+
constructor(device, devicesFile) {
|
|
10
10
|
super();
|
|
11
11
|
this.accountType = device.displayType
|
|
12
12
|
this.deviceId = device.id;
|
|
@@ -26,37 +26,7 @@ class MelCloudAta extends EventEmitter {
|
|
|
26
26
|
keepAlive: false,
|
|
27
27
|
rejectUnauthorized: false
|
|
28
28
|
})
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
this.axiosInstancePost = axios.create({
|
|
32
|
-
method: 'POST',
|
|
33
|
-
baseURL: ApiUrls.BaseURL,
|
|
34
|
-
headers: {
|
|
35
|
-
'X-MitsContextKey': contextKey,
|
|
36
|
-
'content-type': 'application/json'
|
|
37
|
-
},
|
|
38
|
-
withCredentials: true,
|
|
39
|
-
...this.axiosDefaults
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
this.axiosInstancePut = axios.create({
|
|
43
|
-
method: 'PUT',
|
|
44
|
-
baseURL: ApiUrlsHome.BaseURL,
|
|
45
|
-
headers: {
|
|
46
|
-
'Accept': '*/*',
|
|
47
|
-
'Accept-Language': 'en-US,en;q=0.9',
|
|
48
|
-
'Cookie': contextKey,
|
|
49
|
-
'User-Agent': 'homebridge-melcloud-control/4.0.0',
|
|
50
|
-
'DNT': '1',
|
|
51
|
-
'Origin': 'https://melcloudhome.com',
|
|
52
|
-
'Referer': 'https://melcloudhome.com/dashboard',
|
|
53
|
-
'Sec-Fetch-Dest': 'empty',
|
|
54
|
-
'Sec-Fetch-Mode': 'cors',
|
|
55
|
-
'Sec-Fetch-Site': 'same-origin',
|
|
56
|
-
'X-CSRF': '1'
|
|
57
|
-
},
|
|
58
|
-
...this.axiosDefaults
|
|
59
|
-
});
|
|
29
|
+
};;
|
|
60
30
|
|
|
61
31
|
//lock flags
|
|
62
32
|
this.locks = {
|
|
@@ -241,6 +211,17 @@ class MelCloudAta extends EventEmitter {
|
|
|
241
211
|
switch (accountType) {
|
|
242
212
|
case "melcloud":
|
|
243
213
|
try {
|
|
214
|
+
const axiosInstancePost = axios.create({
|
|
215
|
+
method: 'POST',
|
|
216
|
+
baseURL: ApiUrls.BaseURL,
|
|
217
|
+
headers: {
|
|
218
|
+
'X-MitsContextKey': deviceData.ContextKey,
|
|
219
|
+
'content-type': 'application/json'
|
|
220
|
+
},
|
|
221
|
+
withCredentials: true,
|
|
222
|
+
...this.axiosDefaults
|
|
223
|
+
});
|
|
224
|
+
|
|
244
225
|
//set target temp based on display mode and operation mode
|
|
245
226
|
switch (displayMode) {
|
|
246
227
|
case 1: //Heather/Cooler
|
|
@@ -297,7 +278,7 @@ class MelCloudAta extends EventEmitter {
|
|
|
297
278
|
}
|
|
298
279
|
}
|
|
299
280
|
|
|
300
|
-
await
|
|
281
|
+
await axiosInstancePost(ApiUrls.SetAta, payload);
|
|
301
282
|
this.updateData(deviceData);
|
|
302
283
|
return true;
|
|
303
284
|
} catch (error) {
|
|
@@ -305,6 +286,25 @@ class MelCloudAta extends EventEmitter {
|
|
|
305
286
|
};
|
|
306
287
|
case "melcloudhome":
|
|
307
288
|
try {
|
|
289
|
+
const axiosInstancePut = axios.create({
|
|
290
|
+
method: 'PUT',
|
|
291
|
+
baseURL: ApiUrlsHome.BaseURL,
|
|
292
|
+
headers: {
|
|
293
|
+
'Accept': '*/*',
|
|
294
|
+
'Accept-Language': 'en-US,en;q=0.9',
|
|
295
|
+
'Cookie': deviceData.ContextKey,
|
|
296
|
+
'User-Agent': 'homebridge-melcloud-control/4.0.0',
|
|
297
|
+
'DNT': '1',
|
|
298
|
+
'Origin': 'https://melcloudhome.com',
|
|
299
|
+
'Referer': 'https://melcloudhome.com/dashboard',
|
|
300
|
+
'Sec-Fetch-Dest': 'empty',
|
|
301
|
+
'Sec-Fetch-Mode': 'cors',
|
|
302
|
+
'Sec-Fetch-Site': 'same-origin',
|
|
303
|
+
'X-CSRF': '1'
|
|
304
|
+
},
|
|
305
|
+
...this.axiosDefaults
|
|
306
|
+
});
|
|
307
|
+
|
|
308
308
|
//set target temp based on display mode and operation mode
|
|
309
309
|
switch (displayMode) {
|
|
310
310
|
case 1: //Heather/Cooler
|
|
@@ -354,7 +354,7 @@ class MelCloudAta extends EventEmitter {
|
|
|
354
354
|
this.emit('warn', JSON.stringify(deviceData.Device, null, 2));
|
|
355
355
|
this.emit('warn', JSON.stringify(payload, null, 2));
|
|
356
356
|
const path = ApiUrlsHome.SetAta.replace('deviceid', deviceData.DeviceID);
|
|
357
|
-
await
|
|
357
|
+
await axiosInstancePut(path, payload);
|
|
358
358
|
this.updateData(deviceData);
|
|
359
359
|
return true;
|
|
360
360
|
} catch (error) {
|