homebridge-melcloud-control 4.3.5-beta.16 → 4.3.5-beta.18
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 +6 -8
- package/package.json +1 -1
- package/src/deviceata.js +3 -4
- package/src/deviceatw.js +2 -3
- package/src/deviceerv.js +2 -3
- package/src/melcloud.js +2 -5
- package/src/melcloudata.js +53 -61
- package/src/melcloudatw.js +49 -48
- package/src/melclouderv.js +59 -5
- package/src/melcloudhome.js +7 -8
package/index.js
CHANGED
|
@@ -74,7 +74,6 @@ class MelCloudPlatform {
|
|
|
74
74
|
//define directory and file paths
|
|
75
75
|
const accountFile = `${prefDir}/${accountName}_Account`;
|
|
76
76
|
const buildingsFile = `${prefDir}/${accountName}_Buildings`;
|
|
77
|
-
const devicesFile = `${prefDir}/${accountName}_Devices`;
|
|
78
77
|
|
|
79
78
|
//set account refresh interval
|
|
80
79
|
const refreshInterval = (account.refreshInterval ?? 120) * 1000
|
|
@@ -90,11 +89,11 @@ class MelCloudPlatform {
|
|
|
90
89
|
switch (account.type) {
|
|
91
90
|
case 'melcloud':
|
|
92
91
|
timmers = [{ name: 'checkDevicesList', sampling: refreshInterval }];
|
|
93
|
-
melcloud = new MelCloud(account, accountFile, buildingsFile,
|
|
92
|
+
melcloud = new MelCloud(account, accountFile, buildingsFile, true);
|
|
94
93
|
break;
|
|
95
94
|
case 'melcloudhome':
|
|
96
|
-
timmers = [{ name: 'connect', sampling: 3300000 }, { name: 'checkDevicesList', sampling:
|
|
97
|
-
melcloud = new MelCloudHome(account, accountFile, buildingsFile,
|
|
95
|
+
timmers = [{ name: 'connect', sampling: 3300000 }, { name: 'checkDevicesList', sampling: 3000 }];
|
|
96
|
+
melcloud = new MelCloudHome(account, accountFile, buildingsFile, true);
|
|
98
97
|
break;
|
|
99
98
|
default:
|
|
100
99
|
if (logLevel.warn) log.warn(`Unknown account type: ${account.type}.`);
|
|
@@ -154,7 +153,6 @@ class MelCloudPlatform {
|
|
|
154
153
|
const deviceName = device.name;
|
|
155
154
|
const deviceType = device.type;
|
|
156
155
|
const deviceTypeString = device.typeString;
|
|
157
|
-
const deviceRefreshInterval = (device.refreshInterval ?? 5) * 1000;
|
|
158
156
|
const defaultTempsFile = `${prefDir}/${accountName}_${device.id}_Temps`;
|
|
159
157
|
|
|
160
158
|
// set rest ful port
|
|
@@ -182,15 +180,15 @@ class MelCloudPlatform {
|
|
|
182
180
|
let configuredDevice;
|
|
183
181
|
switch (deviceType) {
|
|
184
182
|
case 0: //ATA
|
|
185
|
-
configuredDevice = new DeviceAta(api, account, device,
|
|
183
|
+
configuredDevice = new DeviceAta(api, account, device, defaultTempsFile, accountInfo, accountFile, melcloud);
|
|
186
184
|
break;
|
|
187
185
|
case 1: //ATW
|
|
188
|
-
configuredDevice = new DeviceAtw(api, account, device,
|
|
186
|
+
configuredDevice = new DeviceAtw(api, account, device, defaultTempsFile, accountInfo, accountFile, melcloud);
|
|
189
187
|
break;
|
|
190
188
|
case 2:
|
|
191
189
|
break;
|
|
192
190
|
case 3: //ERV
|
|
193
|
-
configuredDevice = new DeviceErv(api, account, device,
|
|
191
|
+
configuredDevice = new DeviceErv(api, account, device, defaultTempsFile, accountInfo, accountFile, melcloud);
|
|
194
192
|
break;
|
|
195
193
|
default:
|
|
196
194
|
if (logLevel.warn) log.warn(`${accountName}, ${deviceTypeString}, ${deviceName}, unknown device: ${deviceType}.`);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"displayName": "MELCloud Control",
|
|
3
3
|
"name": "homebridge-melcloud-control",
|
|
4
|
-
"version": "4.3.5-beta.
|
|
4
|
+
"version": "4.3.5-beta.18",
|
|
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
|
@@ -7,7 +7,7 @@ import { TemperatureDisplayUnits, AirConditioner } from './constants.js';
|
|
|
7
7
|
let Accessory, Characteristic, Service, Categories, AccessoryUUID;
|
|
8
8
|
|
|
9
9
|
class DeviceAta extends EventEmitter {
|
|
10
|
-
constructor(api, account, device,
|
|
10
|
+
constructor(api, account, device, defaultTempsFile, accountInfo, accountFile, melcloud) {
|
|
11
11
|
super();
|
|
12
12
|
|
|
13
13
|
Accessory = api.platformAccessory;
|
|
@@ -49,7 +49,6 @@ class DeviceAta extends EventEmitter {
|
|
|
49
49
|
this.buttons = (device.buttonsSensors || []).filter(button => (button.displayType ?? 0) > 0);
|
|
50
50
|
|
|
51
51
|
//files
|
|
52
|
-
this.devicesFile = devicesFile;
|
|
53
52
|
this.defaultTempsFile = defaultTempsFile;
|
|
54
53
|
this.accountInfo = accountInfo;
|
|
55
54
|
this.accountFile = accountFile;
|
|
@@ -1321,7 +1320,7 @@ class DeviceAta extends EventEmitter {
|
|
|
1321
1320
|
async start() {
|
|
1322
1321
|
try {
|
|
1323
1322
|
//melcloud device
|
|
1324
|
-
this.melCloudAta = new MelCloudAta(this.account, this.device, this.
|
|
1323
|
+
this.melCloudAta = new MelCloudAta(this.account, this.device, this.defaultTempsFile, this.accountFile, this.melcloud)
|
|
1325
1324
|
.on('deviceInfo', (modelIndoor, modelOutdoor, serialNumber, firmwareAppVersion) => {
|
|
1326
1325
|
if (this.logDeviceInfo && this.displayDeviceInfo) {
|
|
1327
1326
|
this.emit('devInfo', `---- ${this.deviceTypeString}: ${this.deviceName} ----`);
|
|
@@ -1878,7 +1877,7 @@ class DeviceAta extends EventEmitter {
|
|
|
1878
1877
|
if (this.restFul.enable || this.mqtt.enable) await this.externalIntegrations();
|
|
1879
1878
|
|
|
1880
1879
|
//prepare accessory
|
|
1881
|
-
await new Promise(r => setTimeout(r,
|
|
1880
|
+
await new Promise(r => setTimeout(r, 5000));
|
|
1882
1881
|
const accessory = await this.prepareAccessory();
|
|
1883
1882
|
return accessory;
|
|
1884
1883
|
} catch (error) {
|
package/src/deviceatw.js
CHANGED
|
@@ -7,7 +7,7 @@ import { TemperatureDisplayUnits, HeatPump } from './constants.js';
|
|
|
7
7
|
let Accessory, Characteristic, Service, Categories, AccessoryUUID;
|
|
8
8
|
|
|
9
9
|
class DeviceAtw extends EventEmitter {
|
|
10
|
-
constructor(api, account, device,
|
|
10
|
+
constructor(api, account, device, defaultTempsFile, accountInfo, accountFile, melcloud) {
|
|
11
11
|
super();
|
|
12
12
|
|
|
13
13
|
Accessory = api.platformAccessory;
|
|
@@ -53,7 +53,6 @@ class DeviceAtw extends EventEmitter {
|
|
|
53
53
|
this.buttons = (device.buttonsSensors || []).filter(button => (button.displayType ?? 0) > 0);
|
|
54
54
|
|
|
55
55
|
//files
|
|
56
|
-
this.devicesFile = devicesFile;
|
|
57
56
|
this.defaultTempsFile = defaultTempsFile;
|
|
58
57
|
this.accountInfo = accountInfo;
|
|
59
58
|
this.accountFile = accountFile;
|
|
@@ -1567,7 +1566,7 @@ class DeviceAtw extends EventEmitter {
|
|
|
1567
1566
|
async start() {
|
|
1568
1567
|
try {
|
|
1569
1568
|
//melcloud device
|
|
1570
|
-
this.melCloudAtw = new MelCloudAtw(this.account, this.device, this.
|
|
1569
|
+
this.melCloudAtw = new MelCloudAtw(this.account, this.device, this.defaultTempsFile, this.accountFile, this.melcloud)
|
|
1571
1570
|
.on('deviceInfo', (modelIndoor, modelOutdoor, serialNumber, firmwareAppVersion, supportsHotWaterTank, supportsZone2) => {
|
|
1572
1571
|
if (this.logDeviceInfo && this.displayDeviceInfo) {
|
|
1573
1572
|
this.emit('devInfo', `---- ${this.deviceTypeString}: ${this.deviceName} ----`);
|
package/src/deviceerv.js
CHANGED
|
@@ -7,7 +7,7 @@ import { TemperatureDisplayUnits, Ventilation } from './constants.js';
|
|
|
7
7
|
let Accessory, Characteristic, Service, Categories, AccessoryUUID;
|
|
8
8
|
|
|
9
9
|
class DeviceErv extends EventEmitter {
|
|
10
|
-
constructor(api, account, device,
|
|
10
|
+
constructor(api, account, device, defaultTempsFile, accountInfo, accountFile, melcloud) {
|
|
11
11
|
super();
|
|
12
12
|
|
|
13
13
|
Accessory = api.platformAccessory;
|
|
@@ -45,7 +45,6 @@ class DeviceErv extends EventEmitter {
|
|
|
45
45
|
this.buttons = (device.buttonsSensors || []).filter(button => (button.displayType ?? 0) > 0);
|
|
46
46
|
|
|
47
47
|
//files
|
|
48
|
-
this.devicesFile = devicesFile;
|
|
49
48
|
this.defaultTempsFile = defaultTempsFile;
|
|
50
49
|
this.accountInfo = accountInfo;
|
|
51
50
|
this.accountFile = accountFile;
|
|
@@ -1121,7 +1120,7 @@ class DeviceErv extends EventEmitter {
|
|
|
1121
1120
|
async start() {
|
|
1122
1121
|
try {
|
|
1123
1122
|
//melcloud device
|
|
1124
|
-
this.melCloudErv = new MelCloudErv(this.account, this.device, this.
|
|
1123
|
+
this.melCloudErv = new MelCloudErv(this.account, this.device, this.defaultTempsFile, this.accountFile, this.melcloud)
|
|
1125
1124
|
.on('deviceInfo', (modelIndoor, modelOutdoor, serialNumber, firmwareAppVersion) => {
|
|
1126
1125
|
if (this.logDeviceInfo && this.displayDeviceInfo) {
|
|
1127
1126
|
this.emit('devInfo', `---- ${this.deviceTypeString}: ${this.deviceName} ----`);
|
package/src/melcloud.js
CHANGED
|
@@ -5,7 +5,7 @@ import Functions from './functions.js';
|
|
|
5
5
|
import { ApiUrls } from './constants.js';
|
|
6
6
|
|
|
7
7
|
class MelCloud extends EventEmitter {
|
|
8
|
-
constructor(account, accountFile, buildingsFile,
|
|
8
|
+
constructor(account, accountFile, buildingsFile, pluginStart = false) {
|
|
9
9
|
super();
|
|
10
10
|
this.accountType = account.type;
|
|
11
11
|
this.user = account.user;
|
|
@@ -14,9 +14,9 @@ class MelCloud extends EventEmitter {
|
|
|
14
14
|
this.logWarn = account.log?.warn;
|
|
15
15
|
this.logError = account.log?.error;
|
|
16
16
|
this.logDebug = account.log?.debug;
|
|
17
|
+
|
|
17
18
|
this.accountFile = accountFile;
|
|
18
19
|
this.buildingsFile = buildingsFile;
|
|
19
|
-
this.devicesFile = devicesFile;
|
|
20
20
|
this.headers = {};
|
|
21
21
|
|
|
22
22
|
this.functions = new Functions(this.logWarn, this.logError, this.logDebug)
|
|
@@ -112,9 +112,6 @@ class MelCloud extends EventEmitter {
|
|
|
112
112
|
devicesList.Headers = this.headers;
|
|
113
113
|
this.emit('devicesList', devicesList);
|
|
114
114
|
|
|
115
|
-
await this.functions.saveData(this.devicesFile, devicesList);
|
|
116
|
-
if (this.logDebug) this.emit('debug', `${devicesCount} devices saved`);
|
|
117
|
-
|
|
118
115
|
return devicesList;
|
|
119
116
|
} catch (error) {
|
|
120
117
|
throw new Error(`Check devices list error: ${error.message}`);
|
package/src/melcloudata.js
CHANGED
|
@@ -4,7 +4,7 @@ import Functions from './functions.js';
|
|
|
4
4
|
import { ApiUrls, ApiUrlsHome, AirConditioner } from './constants.js';
|
|
5
5
|
|
|
6
6
|
class MelCloudAta extends EventEmitter {
|
|
7
|
-
constructor(account, device,
|
|
7
|
+
constructor(account, device, defaultTempsFile, accountFile, melcloud) {
|
|
8
8
|
super();
|
|
9
9
|
this.accountType = account.type;
|
|
10
10
|
this.logSuccess = account.log?.success;
|
|
@@ -14,7 +14,6 @@ class MelCloudAta extends EventEmitter {
|
|
|
14
14
|
this.restFulEnabled = account.restFul?.enable;
|
|
15
15
|
this.mqttEnabled = account.mqtt?.enable;
|
|
16
16
|
this.deviceId = device.id;
|
|
17
|
-
this.devicesFile = devicesFile;
|
|
18
17
|
this.defaultTempsFile = defaultTempsFile;
|
|
19
18
|
this.accountFile = accountFile;
|
|
20
19
|
this.functions = new Functions(this.logWarn, this.logError, this.logDebug)
|
|
@@ -25,81 +24,73 @@ class MelCloudAta extends EventEmitter {
|
|
|
25
24
|
//set default values
|
|
26
25
|
this.deviceData = {};
|
|
27
26
|
this.headers = {};
|
|
28
|
-
this.firstRun = true;
|
|
29
27
|
|
|
30
28
|
let deviceData = null;
|
|
31
29
|
melcloud.on('devicesList', async (devicesData) => {
|
|
32
30
|
this.headers = devicesData.Headers;
|
|
33
|
-
const webSocket = devicesData.WebSocket;
|
|
34
31
|
deviceData = devicesData.Devices.find(device => device.DeviceID === this.deviceId);
|
|
35
32
|
if (!deviceData) return;
|
|
36
33
|
deviceData.Scenes = devicesData.Scenes ?? [];
|
|
37
34
|
|
|
38
35
|
//update state
|
|
39
36
|
await this.updateState(deviceData);
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
const stringifyMessage = JSON.stringify(parsedMessage, null, 2);
|
|
45
|
-
if (parsedMessage.message === 'Forbidden') return;
|
|
37
|
+
}).on('webSocket', async (parsedMessage) => {
|
|
38
|
+
try {
|
|
39
|
+
const messageData = parsedMessage?.[0]?.Data;
|
|
40
|
+
if (!messageData || !deviceData) return;
|
|
46
41
|
|
|
47
|
-
|
|
48
|
-
|
|
42
|
+
let updateState = false;
|
|
43
|
+
const unitId = messageData?.id;
|
|
44
|
+
switch (unitId) {
|
|
45
|
+
case this.deviceId:
|
|
46
|
+
const messageType = parsedMessage[0].messageType;
|
|
47
|
+
const settings = this.functions.parseArrayNameValue(messageData.settings);
|
|
48
|
+
switch (messageType) {
|
|
49
|
+
case 'unitStateChanged':
|
|
49
50
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
case this.deviceId:
|
|
54
|
-
if (!this.logDebug) this.emit('debug', `Incoming message: ${stringifyMessage}`);
|
|
55
|
-
const messageType = parsedMessage[0].messageType;
|
|
56
|
-
const settings = this.functions.parseArrayNameValue(messageData.settings);
|
|
57
|
-
switch (messageType) {
|
|
58
|
-
case 'unitStateChanged':
|
|
51
|
+
//update values
|
|
52
|
+
for (const [key, value] of Object.entries(settings)) {
|
|
53
|
+
if (!this.functions.isValidValue(value)) continue;
|
|
59
54
|
|
|
60
|
-
//update
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
//update holiday mode
|
|
65
|
-
if (key === 'HolidayMode') {
|
|
66
|
-
deviceData.HolidayMode.Enabled = value;
|
|
67
|
-
continue;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
//update device settings
|
|
71
|
-
if (key in deviceData.Device) {
|
|
72
|
-
deviceData.Device[key] = value;
|
|
73
|
-
}
|
|
55
|
+
//update holiday mode
|
|
56
|
+
if (key === 'HolidayMode') {
|
|
57
|
+
deviceData.HolidayMode.Enabled = value;
|
|
58
|
+
continue;
|
|
74
59
|
}
|
|
75
|
-
updateState = true;
|
|
76
|
-
break;
|
|
77
|
-
case 'unitHolidayModeTriggered':
|
|
78
|
-
deviceData.Device.Power = settings.Power;
|
|
79
|
-
deviceData.HolidayMode.Enabled = settings.HolidayMode;
|
|
80
|
-
deviceData.HolidayMode.Active = messageData.active;
|
|
81
|
-
updateState = true;
|
|
82
|
-
break;
|
|
83
|
-
case 'unitWifiSignalChanged':
|
|
84
|
-
deviceData.Rssi = messageData.rssi;
|
|
85
|
-
updateState = true;
|
|
86
|
-
break;
|
|
87
|
-
default:
|
|
88
|
-
if (this.logDebug) this.emit('debug', `Unit ${unitId}, received unknown message type: ${stringifyMessage}`);
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
break;
|
|
92
|
-
default:
|
|
93
|
-
if (this.logDebug) this.emit('debug', `Incoming unknown unit id: ${stringifyMessage}`);
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
60
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
61
|
+
//update device settings
|
|
62
|
+
if (key in deviceData.Device) {
|
|
63
|
+
deviceData.Device[key] = value;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
updateState = true;
|
|
67
|
+
break;
|
|
68
|
+
case 'unitHolidayModeTriggered':
|
|
69
|
+
deviceData.Device.Power = settings.Power;
|
|
70
|
+
deviceData.HolidayMode.Enabled = settings.HolidayMode;
|
|
71
|
+
deviceData.HolidayMode.Active = messageData.active;
|
|
72
|
+
updateState = true;
|
|
73
|
+
break;
|
|
74
|
+
case 'unitWifiSignalChanged':
|
|
75
|
+
deviceData.Rssi = messageData.rssi;
|
|
76
|
+
updateState = true;
|
|
77
|
+
break;
|
|
78
|
+
default:
|
|
79
|
+
if (this.logDebug) this.emit('debug', `Unit ${unitId}, received unknown message type: ${stringifyMessage}`);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
break;
|
|
83
|
+
default:
|
|
84
|
+
if (this.logDebug) this.emit('debug', `Incoming unknown unit id: ${stringifyMessage}`);
|
|
85
|
+
return;
|
|
101
86
|
}
|
|
102
|
-
|
|
87
|
+
|
|
88
|
+
//update state
|
|
89
|
+
if (updateState) await this.updateState(deviceData);
|
|
90
|
+
} catch (error) {
|
|
91
|
+
if (this.logError) this.emit('error', `Web socket process message error: ${error}`);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
103
94
|
}
|
|
104
95
|
|
|
105
96
|
async updateState(deviceData) {
|
|
@@ -227,6 +218,7 @@ class MelCloudAta extends EventEmitter {
|
|
|
227
218
|
data: payload
|
|
228
219
|
});
|
|
229
220
|
|
|
221
|
+
this.emit('deviceState', deviceData);
|
|
230
222
|
return true;
|
|
231
223
|
case "melcloudhome":
|
|
232
224
|
switch (flag) {
|
package/src/melcloudatw.js
CHANGED
|
@@ -4,7 +4,7 @@ import Functions from './functions.js';
|
|
|
4
4
|
import { ApiUrls, ApiUrlsHome, HeatPump } from './constants.js';
|
|
5
5
|
|
|
6
6
|
class MelCloudAtw extends EventEmitter {
|
|
7
|
-
constructor(account, device,
|
|
7
|
+
constructor(account, device, defaultTempsFile, accountFile, melcloud) {
|
|
8
8
|
super();
|
|
9
9
|
this.accountType = account.type;
|
|
10
10
|
this.logSuccess = account.log?.success;
|
|
@@ -14,7 +14,6 @@ class MelCloudAtw extends EventEmitter {
|
|
|
14
14
|
this.restFulEnabled = account.restFul?.enable;
|
|
15
15
|
this.mqttEnabled = account.mqtt?.enable;
|
|
16
16
|
this.deviceId = device.id;
|
|
17
|
-
this.devicesFile = devicesFile;
|
|
18
17
|
this.defaultTempsFile = defaultTempsFile;
|
|
19
18
|
this.accountFile = accountFile;
|
|
20
19
|
this.functions = new Functions(this.logWarn, this.logError, this.logDebug)
|
|
@@ -35,58 +34,59 @@ class MelCloudAtw extends EventEmitter {
|
|
|
35
34
|
|
|
36
35
|
//update state
|
|
37
36
|
await this.updateState(deviceData);
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
///web cocket message
|
|
41
|
-
if (this.accountType === 'melcloudhome') {
|
|
37
|
+
}).on('message', async (message) => {
|
|
42
38
|
try {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
if (parsedMessage.message === 'Forbidden') return;
|
|
39
|
+
const parsedMessage = JSON.parse(message);
|
|
40
|
+
const stringifyMessage = JSON.stringify(parsedMessage, null, 2);
|
|
41
|
+
if (this.logDebug) this.emit('debug', `Incoming message: ${stringifyMessage}`);
|
|
42
|
+
if (parsedMessage.message === 'Forbidden') return;
|
|
48
43
|
|
|
49
|
-
|
|
50
|
-
|
|
44
|
+
const messageData = parsedMessage?.[0]?.Data;
|
|
45
|
+
if (!messageData || !deviceData) return;
|
|
51
46
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
47
|
+
let updateState = false;
|
|
48
|
+
const unitId = messageData?.id;
|
|
49
|
+
switch (unitId) {
|
|
50
|
+
case this.deviceId:
|
|
51
|
+
const messageType = parsedMessage[0].messageType;
|
|
52
|
+
switch (messageType) {
|
|
53
|
+
case 'unitStateChanged':
|
|
54
|
+
const settings = Object.fromEntries(
|
|
55
|
+
messageData.settings.map(({ name, value }) => {
|
|
56
|
+
let parsedValue = this.functions.convertValue(value);
|
|
57
|
+
return [name, parsedValue];
|
|
58
|
+
})
|
|
59
|
+
);
|
|
60
|
+
Object.assign(deviceData.Device, settings);
|
|
61
|
+
updateState = true;
|
|
62
|
+
break;
|
|
63
|
+
case 'unitHolidayModeTriggered':
|
|
64
|
+
deviceData.Device.Power = settings.Power;
|
|
65
|
+
deviceData.HolidayMode.Enabled = settings.HolidayMode;
|
|
66
|
+
deviceData.HolidayMode.Active = messageData.active;
|
|
67
|
+
updateState = true;
|
|
68
|
+
break;
|
|
69
|
+
case 'unitWifiSignalChanged':
|
|
70
|
+
deviceData.Rssi = messageData.rssi;
|
|
71
|
+
updateState = true;
|
|
72
|
+
break;
|
|
73
|
+
default:
|
|
74
|
+
if (this.logDebug) this.emit('debug', `Unit ${unitId}, received unknown message type: ${stringifyMessage}`);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
break;
|
|
78
|
+
default:
|
|
79
|
+
if (this.logDebug) this.emit('debug', `Incoming unknown unit id: ${stringifyMessage}`);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
81
82
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
});
|
|
83
|
+
//update state
|
|
84
|
+
if (updateState) await this.updateState(deviceData);
|
|
85
85
|
} catch (error) {
|
|
86
|
-
if (this.logError) this.emit('error', `
|
|
87
|
-
this.cleanupSocket();
|
|
86
|
+
if (this.logError) this.emit('error', `Web socket process message error: ${error}`);
|
|
88
87
|
}
|
|
89
|
-
}
|
|
88
|
+
});
|
|
89
|
+
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
async updateState(deviceData) {
|
|
@@ -223,6 +223,7 @@ class MelCloudAtw extends EventEmitter {
|
|
|
223
223
|
data: payload
|
|
224
224
|
});
|
|
225
225
|
|
|
226
|
+
this.emit('deviceState', deviceData);
|
|
226
227
|
return true;
|
|
227
228
|
case "melcloudhome":
|
|
228
229
|
switch (flag) {
|
package/src/melclouderv.js
CHANGED
|
@@ -4,7 +4,7 @@ import Functions from './functions.js';
|
|
|
4
4
|
import { ApiUrls, ApiUrlsHome, Ventilation } from './constants.js';
|
|
5
5
|
|
|
6
6
|
class MelCloudErv extends EventEmitter {
|
|
7
|
-
constructor(account, device,
|
|
7
|
+
constructor(account, device, defaultTempsFile, accountFile, melcloud) {
|
|
8
8
|
super();
|
|
9
9
|
this.accountType = account.type;
|
|
10
10
|
this.logSuccess = account.log?.success;
|
|
@@ -14,7 +14,6 @@ class MelCloudErv extends EventEmitter {
|
|
|
14
14
|
this.restFulEnabled = account.restFul?.enable;
|
|
15
15
|
this.mqttEnabled = account.mqtt?.enable;
|
|
16
16
|
this.deviceId = device.id;
|
|
17
|
-
this.devicesFile = devicesFile;
|
|
18
17
|
this.defaultTempsFile = defaultTempsFile;
|
|
19
18
|
this.accountFile = accountFile;
|
|
20
19
|
this.functions = new Functions(this.logWarn, this.logError, this.logDebug)
|
|
@@ -35,14 +34,68 @@ class MelCloudErv extends EventEmitter {
|
|
|
35
34
|
|
|
36
35
|
//update state
|
|
37
36
|
await this.updateState(deviceData);
|
|
38
|
-
})
|
|
37
|
+
}).on('webSocket', async (parsedMessage) => {
|
|
38
|
+
try {
|
|
39
|
+
const messageData = parsedMessage?.[0]?.Data;
|
|
40
|
+
if (!messageData || !deviceData) return;
|
|
41
|
+
|
|
42
|
+
let updateState = false;
|
|
43
|
+
const unitId = messageData?.id;
|
|
44
|
+
switch (unitId) {
|
|
45
|
+
case this.deviceId:
|
|
46
|
+
const messageType = parsedMessage[0].messageType;
|
|
47
|
+
const settings = this.functions.parseArrayNameValue(messageData.settings);
|
|
48
|
+
switch (messageType) {
|
|
49
|
+
case 'unitStateChanged':
|
|
50
|
+
|
|
51
|
+
//update values
|
|
52
|
+
for (const [key, value] of Object.entries(settings)) {
|
|
53
|
+
if (!this.functions.isValidValue(value)) continue;
|
|
54
|
+
|
|
55
|
+
//update holiday mode
|
|
56
|
+
if (key === 'HolidayMode') {
|
|
57
|
+
deviceData.HolidayMode.Enabled = value;
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
//update device settings
|
|
62
|
+
if (key in deviceData.Device) {
|
|
63
|
+
deviceData.Device[key] = value;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
updateState = true;
|
|
67
|
+
break;
|
|
68
|
+
case 'unitHolidayModeTriggered':
|
|
69
|
+
deviceData.Device.Power = settings.Power;
|
|
70
|
+
deviceData.HolidayMode.Enabled = settings.HolidayMode;
|
|
71
|
+
deviceData.HolidayMode.Active = messageData.active;
|
|
72
|
+
updateState = true;
|
|
73
|
+
break;
|
|
74
|
+
case 'unitWifiSignalChanged':
|
|
75
|
+
deviceData.Rssi = messageData.rssi;
|
|
76
|
+
updateState = true;
|
|
77
|
+
break;
|
|
78
|
+
default:
|
|
79
|
+
if (this.logDebug) this.emit('debug', `Unit ${unitId}, received unknown message type: ${stringifyMessage}`);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
break;
|
|
83
|
+
default:
|
|
84
|
+
if (this.logDebug) this.emit('debug', `Incoming unknown unit id: ${stringifyMessage}`);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
//update state
|
|
89
|
+
if (updateState) await this.updateState(deviceData);
|
|
90
|
+
} catch (error) {
|
|
91
|
+
if (this.logError) this.emit('error', `Web socket process message error: ${error}`);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
39
94
|
}
|
|
40
95
|
|
|
41
96
|
async updateState(deviceData) {
|
|
42
97
|
try {
|
|
43
98
|
if (this.accountType === 'melcloudhome') {
|
|
44
|
-
deviceData.Scenes = devicesData.Scenes ?? [];
|
|
45
|
-
|
|
46
99
|
//read default temps
|
|
47
100
|
const temps = await this.functions.readData(this.defaultTempsFile, true);
|
|
48
101
|
deviceData.Device.DefaultHeatingSetTemperature = temps?.defaultHeatingSetTemperature ?? 20;
|
|
@@ -174,6 +227,7 @@ class MelCloudErv extends EventEmitter {
|
|
|
174
227
|
data: payload
|
|
175
228
|
});
|
|
176
229
|
|
|
230
|
+
this.emit('deviceState', deviceData);
|
|
177
231
|
return true;
|
|
178
232
|
case "melcloudhome":
|
|
179
233
|
switch (flag) {
|
package/src/melcloudhome.js
CHANGED
|
@@ -11,7 +11,7 @@ import { ApiUrlsHome, LanguageLocaleMap } from './constants.js';
|
|
|
11
11
|
const execPromise = promisify(exec);
|
|
12
12
|
|
|
13
13
|
class MelCloudHome extends EventEmitter {
|
|
14
|
-
constructor(account, accountFile, buildingsFile,
|
|
14
|
+
constructor(account, accountFile, buildingsFile, pluginStart = false) {
|
|
15
15
|
super();
|
|
16
16
|
this.accountType = account.type;
|
|
17
17
|
this.user = account.user;
|
|
@@ -23,7 +23,7 @@ class MelCloudHome extends EventEmitter {
|
|
|
23
23
|
this.logDebug = account.log?.debug;
|
|
24
24
|
this.accountFile = accountFile;
|
|
25
25
|
this.buildingsFile = buildingsFile;
|
|
26
|
-
|
|
26
|
+
|
|
27
27
|
this.headers = {};
|
|
28
28
|
this.webSocketOptions = {};
|
|
29
29
|
this.socket = null;
|
|
@@ -253,8 +253,10 @@ class MelCloudHome extends EventEmitter {
|
|
|
253
253
|
.on('message', (message) => {
|
|
254
254
|
const parsedMessage = JSON.parse(message);
|
|
255
255
|
const stringifyMessage = JSON.stringify(parsedMessage, null, 2);
|
|
256
|
-
if (this.logDebug) this.emit('debug', `Incoming message: ${stringifyMessage}`);
|
|
257
|
-
|
|
256
|
+
if (!this.logDebug) this.emit('debug', `Incoming message: ${stringifyMessage}`);
|
|
257
|
+
if (parsedMessage.message === 'Forbidden') return;
|
|
258
|
+
|
|
259
|
+
this.emit('webSocket', parsedMessage);
|
|
258
260
|
});
|
|
259
261
|
} catch (error) {
|
|
260
262
|
if (this.logError) this.emit('error', `Socket connection failed: ${error}`);
|
|
@@ -267,10 +269,7 @@ class MelCloudHome extends EventEmitter {
|
|
|
267
269
|
devicesList.Devices = devices;
|
|
268
270
|
devicesList.Scenes = scenes;
|
|
269
271
|
devicesList.Headers = this.headers;
|
|
270
|
-
this.emit('devicesList', devicesList)
|
|
271
|
-
|
|
272
|
-
await this.functions.saveData(this.devicesFile, devicesList);
|
|
273
|
-
if (this.logDebug) this.emit('debug', `${devicesCount} devices saved`);
|
|
272
|
+
this.emit('devicesList', devicesList);;
|
|
274
273
|
|
|
275
274
|
return devicesList;
|
|
276
275
|
} catch (error) {
|