homebridge-melcloud-control 4.3.5-beta.1 → 4.3.5-beta.11
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 +10 -13
- package/package.json +1 -1
- package/src/deviceata.js +4 -14
- package/src/deviceatw.js +4 -14
- package/src/deviceerv.js +4 -13
- package/src/melcloud.js +1 -0
- package/src/melcloudata.js +77 -140
- package/src/melcloudatw.js +60 -151
- package/src/melclouderv.js +13 -43
- package/src/melcloudhome.js +12 -7
package/index.js
CHANGED
|
@@ -85,22 +85,22 @@ class MelCloudPlatform {
|
|
|
85
85
|
.on('start', async () => {
|
|
86
86
|
try {
|
|
87
87
|
//melcloud account
|
|
88
|
-
let
|
|
88
|
+
let melcloud;
|
|
89
89
|
let timmers = []
|
|
90
90
|
switch (account.type) {
|
|
91
91
|
case 'melcloud':
|
|
92
92
|
timmers = [{ name: 'checkDevicesList', sampling: refreshInterval }];
|
|
93
|
-
|
|
93
|
+
melcloud = new MelCloud(account, accountFile, buildingsFile, devicesFile, true);
|
|
94
94
|
break;
|
|
95
95
|
case 'melcloudhome':
|
|
96
96
|
timmers = [{ name: 'connect', sampling: 3300000 }, { name: 'checkDevicesList', sampling: 3000 }];
|
|
97
|
-
|
|
97
|
+
melcloud = new MelCloudHome(account, accountFile, buildingsFile, devicesFile, true);
|
|
98
98
|
break;
|
|
99
99
|
default:
|
|
100
100
|
if (logLevel.warn) log.warn(`Unknown account type: ${account.type}.`);
|
|
101
101
|
return;
|
|
102
102
|
}
|
|
103
|
-
|
|
103
|
+
melcloud.on('success', (msg) => log.success(`${accountName}, ${msg}`))
|
|
104
104
|
.on('info', (msg) => log.info(`${accountName}, ${msg}`))
|
|
105
105
|
.on('debug', (msg) => log.info(`${accountName}, debug: ${msg}`))
|
|
106
106
|
.on('warn', (msg) => log.warn(`${accountName}, ${msg}`))
|
|
@@ -109,7 +109,7 @@ class MelCloudPlatform {
|
|
|
109
109
|
//connect
|
|
110
110
|
let accountInfo;
|
|
111
111
|
try {
|
|
112
|
-
accountInfo = await
|
|
112
|
+
accountInfo = await melcloud.connect();
|
|
113
113
|
if (!accountInfo.State) {
|
|
114
114
|
if (logLevel.warn) log.warn(`${accountName}, ${accountInfo.Info}`);
|
|
115
115
|
return;
|
|
@@ -123,7 +123,7 @@ class MelCloudPlatform {
|
|
|
123
123
|
//check devices list
|
|
124
124
|
let devicesList;
|
|
125
125
|
try {
|
|
126
|
-
devicesList = await
|
|
126
|
+
devicesList = await melcloud.checkDevicesList();
|
|
127
127
|
if (!devicesList.State) {
|
|
128
128
|
if (logLevel.warn) log.warn(`${accountName}, ${devicesList.Info}`);
|
|
129
129
|
return;
|
|
@@ -179,15 +179,15 @@ class MelCloudPlatform {
|
|
|
179
179
|
let configuredDevice;
|
|
180
180
|
switch (deviceType) {
|
|
181
181
|
case 0: //ATA
|
|
182
|
-
configuredDevice = new DeviceAta(api, account, device, devicesFile, defaultTempsFile, accountInfo, accountFile
|
|
182
|
+
configuredDevice = new DeviceAta(api, account, device, devicesFile, defaultTempsFile, accountInfo, accountFile, melcloud);
|
|
183
183
|
break;
|
|
184
184
|
case 1: //ATW
|
|
185
|
-
configuredDevice = new DeviceAtw(api, account, device, devicesFile, defaultTempsFile, accountInfo, accountFile,
|
|
185
|
+
configuredDevice = new DeviceAtw(api, account, device, devicesFile, defaultTempsFile, accountInfo, accountFile, melcloud);
|
|
186
186
|
break;
|
|
187
187
|
case 2:
|
|
188
188
|
break;
|
|
189
189
|
case 3: //ERV
|
|
190
|
-
configuredDevice = new DeviceErv(api, account, device, devicesFile, defaultTempsFile, accountInfo, accountFile,
|
|
190
|
+
configuredDevice = new DeviceErv(api, account, device, devicesFile, defaultTempsFile, accountInfo, accountFile, melcloud);
|
|
191
191
|
break;
|
|
192
192
|
default:
|
|
193
193
|
if (logLevel.warn) log.warn(`${accountName}, ${deviceTypeString}, ${deviceName}, unknown device: ${deviceType}.`);
|
|
@@ -205,14 +205,11 @@ class MelCloudPlatform {
|
|
|
205
205
|
if (accessory) {
|
|
206
206
|
api.publishExternalAccessories(PluginName, [accessory]);
|
|
207
207
|
if (logLevel.success) log.success(`${accountName}, ${deviceTypeString}, ${deviceName}, Published as external accessory.`);
|
|
208
|
-
|
|
209
|
-
//start impulse generators for device
|
|
210
|
-
await configuredDevice.startStopImpulseGenerator(true, [{ name: 'checkState', sampling: deviceRefreshInterval }]);
|
|
211
208
|
}
|
|
212
209
|
}
|
|
213
210
|
|
|
214
211
|
//start account impulse generator
|
|
215
|
-
await
|
|
212
|
+
await melcloud.impulseGenerator.state(true, timmers, false);
|
|
216
213
|
|
|
217
214
|
//stop start impulse generator
|
|
218
215
|
await impulseGenerator.state(false);
|
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.11",
|
|
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, devicesFile, defaultTempsFile, accountInfo, accountFile,
|
|
10
|
+
constructor(api, account, device, devicesFile, defaultTempsFile, accountInfo, accountFile, melcloud) {
|
|
11
11
|
super();
|
|
12
12
|
|
|
13
13
|
Accessory = api.platformAccessory;
|
|
@@ -17,7 +17,7 @@ class DeviceAta extends EventEmitter {
|
|
|
17
17
|
AccessoryUUID = api.hap.uuid;
|
|
18
18
|
|
|
19
19
|
//account config
|
|
20
|
-
this.
|
|
20
|
+
this.melcloud = melcloud;
|
|
21
21
|
this.account = account;
|
|
22
22
|
this.accountType = account.type;
|
|
23
23
|
this.accountName = account.name;
|
|
@@ -108,16 +108,6 @@ class DeviceAta extends EventEmitter {
|
|
|
108
108
|
this.accessory = {};
|
|
109
109
|
};
|
|
110
110
|
|
|
111
|
-
async startStopImpulseGenerator(state, timers = []) {
|
|
112
|
-
try {
|
|
113
|
-
//start impulse generator
|
|
114
|
-
await this.melCloudAta.impulseGenerator.state(state, timers)
|
|
115
|
-
return true;
|
|
116
|
-
} catch (error) {
|
|
117
|
-
throw new Error(`Impulse generator start error: ${error}`);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
111
|
async externalIntegrations() {
|
|
122
112
|
//RESTFul server
|
|
123
113
|
const restFulEnabled = this.restFul.enable || false;
|
|
@@ -1331,7 +1321,7 @@ class DeviceAta extends EventEmitter {
|
|
|
1331
1321
|
async start() {
|
|
1332
1322
|
try {
|
|
1333
1323
|
//melcloud device
|
|
1334
|
-
this.melCloudAta = new MelCloudAta(this.account, this.device, this.devicesFile, this.defaultTempsFile, this.accountFile, this.
|
|
1324
|
+
this.melCloudAta = new MelCloudAta(this.account, this.device, this.devicesFile, this.defaultTempsFile, this.accountFile, this.melcloud)
|
|
1335
1325
|
.on('deviceInfo', (modelIndoor, modelOutdoor, serialNumber, firmwareAppVersion) => {
|
|
1336
1326
|
if (this.logDeviceInfo && this.displayDeviceInfo) {
|
|
1337
1327
|
this.emit('devInfo', `---- ${this.deviceTypeString}: ${this.deviceName} ----`);
|
|
@@ -1888,7 +1878,7 @@ class DeviceAta extends EventEmitter {
|
|
|
1888
1878
|
if (this.restFul.enable || this.mqtt.enable) await this.externalIntegrations();
|
|
1889
1879
|
|
|
1890
1880
|
//check state
|
|
1891
|
-
await this.melCloudAta.
|
|
1881
|
+
await this.melCloudAta.updateState();
|
|
1892
1882
|
|
|
1893
1883
|
//prepare accessory
|
|
1894
1884
|
const accessory = await this.prepareAccessory();
|
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, devicesFile, defaultTempsFile, accountInfo, accountFile) {
|
|
10
|
+
constructor(api, account, device, devicesFile, defaultTempsFile, accountInfo, accountFile, melcloud) {
|
|
11
11
|
super();
|
|
12
12
|
|
|
13
13
|
Accessory = api.platformAccessory;
|
|
@@ -17,6 +17,7 @@ class DeviceAtw extends EventEmitter {
|
|
|
17
17
|
AccessoryUUID = api.hap.uuid;
|
|
18
18
|
|
|
19
19
|
//account config
|
|
20
|
+
this.melcloud = melcloud;
|
|
20
21
|
this.account = account;
|
|
21
22
|
this.accountType = account.type;
|
|
22
23
|
this.accountName = account.name;
|
|
@@ -111,17 +112,6 @@ class DeviceAtw extends EventEmitter {
|
|
|
111
112
|
this.accessory = {};
|
|
112
113
|
};
|
|
113
114
|
|
|
114
|
-
async startStopImpulseGenerator(state, timers = []) {
|
|
115
|
-
try {
|
|
116
|
-
//start impulse generator
|
|
117
|
-
await this.melCloudAtw.impulseGenerator.state(state, timers)
|
|
118
|
-
return true;
|
|
119
|
-
} catch (error) {
|
|
120
|
-
throw new Error(`Impulse generator start error: ${error}`);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
|
|
125
115
|
async externalIntegrations() {
|
|
126
116
|
//RESTFul server
|
|
127
117
|
const restFulEnabled = this.restFul.enable || false;
|
|
@@ -1577,7 +1567,7 @@ class DeviceAtw extends EventEmitter {
|
|
|
1577
1567
|
async start() {
|
|
1578
1568
|
try {
|
|
1579
1569
|
//melcloud device
|
|
1580
|
-
this.melCloudAtw = new MelCloudAtw(this.account, this.device, this.devicesFile, this.defaultTempsFile, this.accountFile)
|
|
1570
|
+
this.melCloudAtw = new MelCloudAtw(this.account, this.device, this.devicesFile, this.defaultTempsFile, this.accountFile, this.melcloud)
|
|
1581
1571
|
.on('deviceInfo', (modelIndoor, modelOutdoor, serialNumber, firmwareAppVersion, supportsHotWaterTank, supportsZone2) => {
|
|
1582
1572
|
if (this.logDeviceInfo && this.displayDeviceInfo) {
|
|
1583
1573
|
this.emit('devInfo', `---- ${this.deviceTypeString}: ${this.deviceName} ----`);
|
|
@@ -2317,7 +2307,7 @@ class DeviceAtw extends EventEmitter {
|
|
|
2317
2307
|
if (this.restFul.enable || this.mqtt.enable) await this.externalIntegrations();
|
|
2318
2308
|
|
|
2319
2309
|
//check state
|
|
2320
|
-
await this.melCloudAtw.
|
|
2310
|
+
await this.melCloudAtw.updateState();
|
|
2321
2311
|
|
|
2322
2312
|
//prepare accessory
|
|
2323
2313
|
const accessory = await this.prepareAccessory();
|
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, devicesFile, defaultTempsFile, accountInfo, accountFile) {
|
|
10
|
+
constructor(api, account, device, devicesFile, defaultTempsFile, accountInfo, accountFile, melcloud) {
|
|
11
11
|
super();
|
|
12
12
|
|
|
13
13
|
Accessory = api.platformAccessory;
|
|
@@ -17,6 +17,7 @@ class DeviceErv extends EventEmitter {
|
|
|
17
17
|
AccessoryUUID = api.hap.uuid;
|
|
18
18
|
|
|
19
19
|
//account config
|
|
20
|
+
this.melcloud = melcloud;
|
|
20
21
|
this.account = account;
|
|
21
22
|
this.accountType = account.type;
|
|
22
23
|
this.accountName = account.name;
|
|
@@ -103,16 +104,6 @@ class DeviceErv extends EventEmitter {
|
|
|
103
104
|
this.accessory = {};
|
|
104
105
|
};
|
|
105
106
|
|
|
106
|
-
async startStopImpulseGenerator(state, timers = []) {
|
|
107
|
-
try {
|
|
108
|
-
//start impulse generator
|
|
109
|
-
await this.melCloudErv.impulseGenerator.state(state, timers)
|
|
110
|
-
return true;
|
|
111
|
-
} catch (error) {
|
|
112
|
-
throw new Error(`Impulse generator start error: ${error}`);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
107
|
async externalIntegrations() {
|
|
117
108
|
//RESTFul server
|
|
118
109
|
const restFulEnabled = this.restFul.enable || false;
|
|
@@ -1130,7 +1121,7 @@ class DeviceErv extends EventEmitter {
|
|
|
1130
1121
|
async start() {
|
|
1131
1122
|
try {
|
|
1132
1123
|
//melcloud device
|
|
1133
|
-
this.melCloudErv = new MelCloudErv(this.account, this.device, this.devicesFile, this.defaultTempsFile, this.accountFile)
|
|
1124
|
+
this.melCloudErv = new MelCloudErv(this.account, this.device, this.devicesFile, this.defaultTempsFile, this.accountFile, this.melcloud)
|
|
1134
1125
|
.on('deviceInfo', (modelIndoor, modelOutdoor, serialNumber, firmwareAppVersion) => {
|
|
1135
1126
|
if (this.logDeviceInfo && this.displayDeviceInfo) {
|
|
1136
1127
|
this.emit('devInfo', `---- ${this.deviceTypeString}: ${this.deviceName} ----`);
|
|
@@ -1590,7 +1581,7 @@ class DeviceErv extends EventEmitter {
|
|
|
1590
1581
|
if (this.restFul.enable || this.mqtt.enable) await this.externalIntegrations();
|
|
1591
1582
|
|
|
1592
1583
|
//check state
|
|
1593
|
-
await this.melCloudErv.
|
|
1584
|
+
await this.melCloudErv.updateState();
|
|
1594
1585
|
|
|
1595
1586
|
//prepare accessory
|
|
1596
1587
|
const accessory = await this.prepareAccessory();
|
package/src/melcloud.js
CHANGED
|
@@ -110,6 +110,7 @@ class MelCloud extends EventEmitter {
|
|
|
110
110
|
devicesList.Info = `Found ${devicesCount} devices`;
|
|
111
111
|
devicesList.Devices = devices;
|
|
112
112
|
devicesList.Headers = this.headers;
|
|
113
|
+
this.emit('devicesList', devicesList);
|
|
113
114
|
|
|
114
115
|
await this.functions.saveData(this.devicesFile, devicesList);
|
|
115
116
|
if (this.logDebug) this.emit('debug', `${devicesCount} devices saved`);
|
package/src/melcloudata.js
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import WebSocket from 'ws';
|
|
2
1
|
import axios from 'axios';
|
|
3
2
|
import EventEmitter from 'events';
|
|
4
|
-
import ImpulseGenerator from './impulsegenerator.js';
|
|
5
3
|
import Functions from './functions.js';
|
|
6
4
|
import { ApiUrls, ApiUrlsHome, AirConditioner } from './constants.js';
|
|
7
5
|
|
|
8
6
|
class MelCloudAta extends EventEmitter {
|
|
9
|
-
constructor(account, device, devicesFile, defaultTempsFile, accountFile,
|
|
7
|
+
constructor(account, device, devicesFile, defaultTempsFile, accountFile, melcloud) {
|
|
10
8
|
super();
|
|
11
9
|
this.accountType = account.type;
|
|
12
10
|
this.logSuccess = account.log?.success;
|
|
@@ -19,7 +17,6 @@ class MelCloudAta extends EventEmitter {
|
|
|
19
17
|
this.devicesFile = devicesFile;
|
|
20
18
|
this.defaultTempsFile = defaultTempsFile;
|
|
21
19
|
this.accountFile = accountFile;
|
|
22
|
-
this.webSocket = webSocket;
|
|
23
20
|
this.functions = new Functions(this.logWarn, this.logError, this.logDebug)
|
|
24
21
|
.on('warn', warn => this.emit('warn', warn))
|
|
25
22
|
.on('error', error => this.emit('error', error))
|
|
@@ -28,47 +25,86 @@ class MelCloudAta extends EventEmitter {
|
|
|
28
25
|
//set default values
|
|
29
26
|
this.deviceData = {};
|
|
30
27
|
this.headers = {};
|
|
31
|
-
this.
|
|
32
|
-
this.connecting = false;
|
|
33
|
-
this.socketConnected = false;
|
|
34
|
-
this.heartbeat = null;
|
|
35
|
-
|
|
36
|
-
//lock flag
|
|
37
|
-
this.locks = false;
|
|
38
|
-
this.impulseGenerator = new ImpulseGenerator()
|
|
39
|
-
.on('checkState', () => this.handleWithLock(async () => {
|
|
40
|
-
await this.checkState();
|
|
41
|
-
}))
|
|
42
|
-
.on('state', (state) => {
|
|
43
|
-
this.emit(state ? 'success' : 'warn', `Impulse generator ${state ? 'started' : 'stopped'}`);
|
|
44
|
-
});
|
|
45
|
-
}
|
|
28
|
+
this.firtRun = true;
|
|
46
29
|
|
|
47
|
-
|
|
48
|
-
|
|
30
|
+
let deviceData = null;
|
|
31
|
+
melcloud.on('devicesList', async (devicesData) => {
|
|
32
|
+
this.headers = devicesData.Headers;
|
|
33
|
+
const webSocket = devicesData.webSocket;
|
|
34
|
+
deviceData = devicesData.Devices.find(device => device.DeviceID === this.deviceId);
|
|
35
|
+
if (!deviceData) return;
|
|
36
|
+
deviceData.Scenes = devicesData.Scenes ?? [];
|
|
49
37
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}
|
|
38
|
+
//web cocket message
|
|
39
|
+
if (this.accountType === 'melcloudhome' && this.firtRun) {
|
|
40
|
+
this.firtRun = false;
|
|
41
|
+
try {
|
|
42
|
+
webSocket.on('message', async (message) => {
|
|
43
|
+
const parsedMessage = JSON.parse(message);
|
|
44
|
+
const stringifyMessage = JSON.stringify(parsedMessage, null, 2);
|
|
45
|
+
if (parsedMessage.message === 'Forbidden') return;
|
|
59
46
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
clearInterval(this.heartbeat);
|
|
63
|
-
this.heartbeat = null;
|
|
64
|
-
}
|
|
47
|
+
const messageData = parsedMessage?.[0]?.Data;
|
|
48
|
+
if (!messageData || !deviceData) return;
|
|
65
49
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
50
|
+
let updateState = false;
|
|
51
|
+
const unitId = messageData?.id;
|
|
52
|
+
switch (unitId) {
|
|
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':
|
|
59
|
+
|
|
60
|
+
//update values
|
|
61
|
+
for (const [key, value] of Object.entries(settings)) {
|
|
62
|
+
if (!this.functions.isValidValue(value)) continue;
|
|
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
|
+
}
|
|
74
|
+
}
|
|
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
|
+
|
|
97
|
+
//update state
|
|
98
|
+
if (updateState) await this.updateState(deviceData);
|
|
99
|
+
});
|
|
100
|
+
} catch (error) {
|
|
101
|
+
if (this.logError) this.emit('error', `Socket connection failed: ${error}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
70
104
|
|
|
71
|
-
|
|
105
|
+
//update state
|
|
106
|
+
await this.updateState(deviceData);
|
|
107
|
+
});
|
|
72
108
|
}
|
|
73
109
|
|
|
74
110
|
async updateState(deviceData) {
|
|
@@ -144,95 +180,6 @@ class MelCloudAta extends EventEmitter {
|
|
|
144
180
|
};
|
|
145
181
|
};
|
|
146
182
|
|
|
147
|
-
async checkState() {
|
|
148
|
-
try {
|
|
149
|
-
//read device info from file
|
|
150
|
-
const devicesData = await this.functions.readData(this.devicesFile, true);
|
|
151
|
-
if (!devicesData) return;
|
|
152
|
-
|
|
153
|
-
this.headers = devicesData.Headers;
|
|
154
|
-
const deviceData = devicesData.Devices.find(device => device.DeviceID === this.deviceId);
|
|
155
|
-
if (!deviceData) return;
|
|
156
|
-
deviceData.Scenes = devicesData.Scenes ?? [];
|
|
157
|
-
|
|
158
|
-
//web cocket connection
|
|
159
|
-
if (this.accountType === 'melcloudhome' && !this.connecting) {
|
|
160
|
-
this.connecting = true;
|
|
161
|
-
|
|
162
|
-
try {
|
|
163
|
-
this.webSocket.on('message', async (message) => {
|
|
164
|
-
const parsedMessage = JSON.parse(message);
|
|
165
|
-
const stringifyMessage = JSON.stringify(parsedMessage, null, 2);
|
|
166
|
-
if (parsedMessage.message === 'Forbidden') return;
|
|
167
|
-
|
|
168
|
-
const messageData = parsedMessage?.[0]?.Data;
|
|
169
|
-
if (!messageData) return;
|
|
170
|
-
|
|
171
|
-
let updateState = false;
|
|
172
|
-
const unitId = messageData?.id;
|
|
173
|
-
switch (unitId) {
|
|
174
|
-
case this.deviceId:
|
|
175
|
-
if (!this.logDebug) this.emit('debug', `Incoming message: ${stringifyMessage}`);
|
|
176
|
-
const messageType = parsedMessage[0].messageType;
|
|
177
|
-
const settings = this.functions.parseArrayNameValue(messageData.settings);
|
|
178
|
-
switch (messageType) {
|
|
179
|
-
case 'unitStateChanged':
|
|
180
|
-
|
|
181
|
-
//update values
|
|
182
|
-
for (const [key, value] of Object.entries(settings)) {
|
|
183
|
-
if (!this.functions.isValidValue(value)) continue;
|
|
184
|
-
|
|
185
|
-
//update holiday mode
|
|
186
|
-
if (key === 'HolidayMode') {
|
|
187
|
-
deviceData.HolidayMode.Enabled = value;
|
|
188
|
-
continue;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
//update device settings
|
|
192
|
-
if (key in deviceData.Device) {
|
|
193
|
-
deviceData.Device[key] = value;
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
updateState = true;
|
|
197
|
-
break;
|
|
198
|
-
case 'unitHolidayModeTriggered':
|
|
199
|
-
deviceData.Device.Power = settings.Power;
|
|
200
|
-
deviceData.HolidayMode.Enabled = settings.HolidayMode;
|
|
201
|
-
deviceData.HolidayMode.Active = messageData.active;
|
|
202
|
-
updateState = true;
|
|
203
|
-
break;
|
|
204
|
-
case 'unitWifiSignalChanged':
|
|
205
|
-
deviceData.Rssi = messageData.rssi;
|
|
206
|
-
updateState = true;
|
|
207
|
-
break;
|
|
208
|
-
default:
|
|
209
|
-
if (!this.logDebug) this.emit('debug', `Unit ${unitId}, received unknown message type: ${stringifyMessage}`);
|
|
210
|
-
return;
|
|
211
|
-
}
|
|
212
|
-
break;
|
|
213
|
-
default:
|
|
214
|
-
if (!this.logDebug) this.emit('debug', `Incoming unknown unit id: ${stringifyMessage}`);
|
|
215
|
-
return;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
//update state
|
|
219
|
-
if (updateState) await this.updateState(deviceData);
|
|
220
|
-
});
|
|
221
|
-
} catch (error) {
|
|
222
|
-
if (this.logError) this.emit('error', `Socket connection failed: ${error}`);
|
|
223
|
-
this.cleanupSocket();
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
//update state
|
|
228
|
-
await this.updateState(deviceData);
|
|
229
|
-
|
|
230
|
-
return true;
|
|
231
|
-
} catch (error) {
|
|
232
|
-
throw new Error(`Check state error: ${error.message}`);
|
|
233
|
-
};
|
|
234
|
-
};
|
|
235
|
-
|
|
236
183
|
async send(accountType, displayType, deviceData, flag, flagData) {
|
|
237
184
|
try {
|
|
238
185
|
let method = null
|
|
@@ -284,7 +231,7 @@ class MelCloudAta extends EventEmitter {
|
|
|
284
231
|
headers: headers,
|
|
285
232
|
data: payload
|
|
286
233
|
});
|
|
287
|
-
|
|
234
|
+
|
|
288
235
|
return true;
|
|
289
236
|
case "melcloudhome":
|
|
290
237
|
switch (flag) {
|
|
@@ -375,7 +322,6 @@ class MelCloudAta extends EventEmitter {
|
|
|
375
322
|
data: payload
|
|
376
323
|
});
|
|
377
324
|
|
|
378
|
-
this.updateData(deviceData, updateState);
|
|
379
325
|
return true;
|
|
380
326
|
default:
|
|
381
327
|
return;
|
|
@@ -385,14 +331,5 @@ class MelCloudAta extends EventEmitter {
|
|
|
385
331
|
throw new Error(`Send data error: ${error.message}`);
|
|
386
332
|
}
|
|
387
333
|
}
|
|
388
|
-
|
|
389
|
-
updateData(deviceData, updateState = true) {
|
|
390
|
-
this.locks = true;
|
|
391
|
-
if (updateState) this.emit('deviceState', deviceData);
|
|
392
|
-
|
|
393
|
-
setTimeout(() => {
|
|
394
|
-
this.locks = false
|
|
395
|
-
}, 5000);
|
|
396
|
-
}
|
|
397
334
|
};
|
|
398
335
|
export default MelCloudAta;
|
package/src/melcloudatw.js
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import WebSocket from 'ws';
|
|
2
1
|
import axios from 'axios';
|
|
3
2
|
import EventEmitter from 'events';
|
|
4
|
-
import ImpulseGenerator from './impulsegenerator.js';
|
|
5
3
|
import Functions from './functions.js';
|
|
6
4
|
import { ApiUrls, ApiUrlsHome, HeatPump } from './constants.js';
|
|
7
5
|
|
|
8
6
|
class MelCloudAtw extends EventEmitter {
|
|
9
|
-
constructor(account, device, devicesFile, defaultTempsFile, accountFile) {
|
|
7
|
+
constructor(account, device, devicesFile, defaultTempsFile, accountFile, melcloud) {
|
|
10
8
|
super();
|
|
11
9
|
this.accountType = account.type;
|
|
12
10
|
this.logSuccess = account.log?.success;
|
|
@@ -27,47 +25,68 @@ class MelCloudAtw extends EventEmitter {
|
|
|
27
25
|
//set default values
|
|
28
26
|
this.deviceData = {};
|
|
29
27
|
this.headers = {};
|
|
30
|
-
this.socket = null;
|
|
31
|
-
this.connecting = false;
|
|
32
|
-
this.socketConnected = false;
|
|
33
|
-
this.heartbeat = null;
|
|
34
28
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
.
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
.on('state', (state) => {
|
|
42
|
-
this.emit(state ? 'success' : 'warn', `Impulse generator ${state ? 'started' : 'stopped'}`);
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
async handleWithLock(fn) {
|
|
47
|
-
if (this.locks) return;
|
|
48
|
-
|
|
49
|
-
this.locks = true;
|
|
50
|
-
try {
|
|
51
|
-
await fn();
|
|
52
|
-
} catch (error) {
|
|
53
|
-
this.emit('error', `Inpulse generator error: ${error}`);
|
|
54
|
-
} finally {
|
|
55
|
-
this.locks = false;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
29
|
+
let deviceData = null;
|
|
30
|
+
melcloud.on('devicesList', async (devicesData) => {
|
|
31
|
+
this.headers = devicesData.Headers;
|
|
32
|
+
deviceData = devicesData.Devices.find(device => device.DeviceID === this.deviceId);
|
|
33
|
+
if (!deviceData) return;
|
|
34
|
+
deviceData.Scenes = devicesData.Scenes ?? [];
|
|
58
35
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
36
|
+
//update state
|
|
37
|
+
await this.updateState(deviceData);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
///web cocket message
|
|
41
|
+
if (this.accountType === 'melcloudhome') {
|
|
42
|
+
try {
|
|
43
|
+
melcloud.webSocket.on('message', async (message) => {
|
|
44
|
+
const parsedMessage = JSON.parse(message);
|
|
45
|
+
const stringifyMessage = JSON.stringify(parsedMessage, null, 2);
|
|
46
|
+
if (this.logDebug) this.emit('debug', `Incoming message: ${stringifyMessage}`);
|
|
47
|
+
if (parsedMessage.message === 'Forbidden') return;
|
|
48
|
+
|
|
49
|
+
const messageData = parsedMessage?.[0]?.Data;
|
|
50
|
+
if (!messageData || !deviceData) return;
|
|
51
|
+
|
|
52
|
+
let updateState = false;
|
|
53
|
+
const unitId = messageData?.id;
|
|
54
|
+
switch (unitId) {
|
|
55
|
+
case this.deviceId:
|
|
56
|
+
const messageType = parsedMessage[0].messageType;
|
|
57
|
+
switch (messageType) {
|
|
58
|
+
case 'unitStateChanged':
|
|
59
|
+
const settings = Object.fromEntries(
|
|
60
|
+
messageData.settings.map(({ name, value }) => {
|
|
61
|
+
let parsedValue = this.functions.convertValue(value);
|
|
62
|
+
return [name, parsedValue];
|
|
63
|
+
})
|
|
64
|
+
);
|
|
65
|
+
Object.assign(deviceData.Device, settings);
|
|
66
|
+
updateState = true;
|
|
67
|
+
break;
|
|
68
|
+
case 'unitWifiSignalChanged':
|
|
69
|
+
deviceData.Rssi = messageData.rssi;
|
|
70
|
+
updateState = true;
|
|
71
|
+
break;
|
|
72
|
+
default:
|
|
73
|
+
if (this.logDebug) this.emit('debug', `Unit ${unitId}, received unknown message type: ${stringifyMessage}`);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
break;
|
|
77
|
+
default:
|
|
78
|
+
if (this.logDebug) this.emit('debug', `Incoming unknown unit id: ${stringifyMessage}`);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
64
81
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
82
|
+
//update state
|
|
83
|
+
if (updateState) await this.updateState(deviceData);
|
|
84
|
+
});
|
|
85
|
+
} catch (error) {
|
|
86
|
+
if (this.logError) this.emit('error', `Socket connection failed: ${error}`);
|
|
87
|
+
this.cleanupSocket();
|
|
88
|
+
}
|
|
68
89
|
}
|
|
69
|
-
|
|
70
|
-
this.socketConnected = false;
|
|
71
90
|
}
|
|
72
91
|
|
|
73
92
|
async updateState(deviceData) {
|
|
@@ -137,106 +156,6 @@ class MelCloudAtw extends EventEmitter {
|
|
|
137
156
|
};
|
|
138
157
|
};
|
|
139
158
|
|
|
140
|
-
async checkState() {
|
|
141
|
-
try {
|
|
142
|
-
//read device info from file
|
|
143
|
-
const devicesData = await this.functions.readData(this.devicesFile, true);
|
|
144
|
-
if (!devicesData) return;
|
|
145
|
-
|
|
146
|
-
this.headers = devicesData.Headers;
|
|
147
|
-
const deviceData = devicesData.Devices.find(device => device.DeviceID === this.deviceId);
|
|
148
|
-
if (!deviceData) return;
|
|
149
|
-
deviceData.Scenes = devicesData.Scenes ?? [];
|
|
150
|
-
|
|
151
|
-
//web cocket connection
|
|
152
|
-
if (this.accountType === 'melcloudhome' && !this.connecting && !this.socketConnected) {
|
|
153
|
-
this.connecting = true;
|
|
154
|
-
|
|
155
|
-
const url = `${ApiUrlsHome.WebSocketURL}${devicesData.WebSocketOptions.Hash}`;
|
|
156
|
-
try {
|
|
157
|
-
const socket = new WebSocket(url, { headers: devicesData.WebSocketOptions.Headers })
|
|
158
|
-
.on('error', (error) => {
|
|
159
|
-
if (this.logError) this.emit('error', `Socket error: ${error}`);
|
|
160
|
-
socket.close();
|
|
161
|
-
})
|
|
162
|
-
.on('close', () => {
|
|
163
|
-
if (this.logDebug) this.emit('debug', `Socket closed`);
|
|
164
|
-
this.cleanupSocket();
|
|
165
|
-
})
|
|
166
|
-
.on('open', () => {
|
|
167
|
-
this.socket = socket;
|
|
168
|
-
this.socketConnected = true;
|
|
169
|
-
this.connecting = false;
|
|
170
|
-
if (this.logSuccess) this.emit('success', `Socket Connect Success`);
|
|
171
|
-
|
|
172
|
-
// heartbeat
|
|
173
|
-
this.heartbeat = setInterval(() => {
|
|
174
|
-
if (socket.readyState === socket.OPEN) {
|
|
175
|
-
if (this.logDebug) this.emit('debug', `Socket send heartbeat`);
|
|
176
|
-
socket.ping();
|
|
177
|
-
}
|
|
178
|
-
}, 30000);
|
|
179
|
-
})
|
|
180
|
-
.on('pong', () => {
|
|
181
|
-
if (this.logDebug) this.emit('debug', `Socket received heartbeat`);
|
|
182
|
-
})
|
|
183
|
-
.on('message', async (message) => {
|
|
184
|
-
const parsedMessage = JSON.parse(message);
|
|
185
|
-
const stringifyMessage = JSON.stringify(parsedMessage, null, 2);
|
|
186
|
-
if (this.logDebug) this.emit('debug', `Incoming message: ${stringifyMessage}`);
|
|
187
|
-
if (parsedMessage.message === 'Forbidden') return;
|
|
188
|
-
|
|
189
|
-
const messageData = parsedMessage?.[0]?.Data;
|
|
190
|
-
if (!messageData) return;
|
|
191
|
-
|
|
192
|
-
let updateState = false;
|
|
193
|
-
const unitId = messageData?.id;
|
|
194
|
-
switch (unitId) {
|
|
195
|
-
case this.deviceId:
|
|
196
|
-
const messageType = parsedMessage[0].messageType;
|
|
197
|
-
switch (messageType) {
|
|
198
|
-
case 'unitStateChanged':
|
|
199
|
-
const settings = Object.fromEntries(
|
|
200
|
-
messageData.settings.map(({ name, value }) => {
|
|
201
|
-
let parsedValue = this.functions.convertValue(value);
|
|
202
|
-
return [name, parsedValue];
|
|
203
|
-
})
|
|
204
|
-
);
|
|
205
|
-
Object.assign(deviceData.Device, settings);
|
|
206
|
-
updateState = true;
|
|
207
|
-
break;
|
|
208
|
-
case 'unitWifiSignalChanged':
|
|
209
|
-
deviceData.Rssi = messageData.rssi;
|
|
210
|
-
updateState = true;
|
|
211
|
-
break;
|
|
212
|
-
default:
|
|
213
|
-
if (this.logDebug) this.emit('debug', `Unit ${unitId}, received unknown message type: ${stringifyMessage}`);
|
|
214
|
-
return;
|
|
215
|
-
}
|
|
216
|
-
break;
|
|
217
|
-
default:
|
|
218
|
-
if (this.logDebug) this.emit('debug', `Incoming unknown unit id: ${stringifyMessage}`);
|
|
219
|
-
return;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
//update state
|
|
223
|
-
if (updateState) await this.updateState(deviceData);
|
|
224
|
-
});
|
|
225
|
-
} catch (error) {
|
|
226
|
-
if (this.logError) this.emit('error', `Socket connection failed: ${error}`);
|
|
227
|
-
this.cleanupSocket();
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
//update state
|
|
232
|
-
await this.updateState(deviceData);
|
|
233
|
-
|
|
234
|
-
return true;
|
|
235
|
-
} catch (error) {
|
|
236
|
-
throw new Error(`Check state error: ${error.message}`);
|
|
237
|
-
};
|
|
238
|
-
};
|
|
239
|
-
|
|
240
159
|
async send(accountType, displayType, deviceData, flag, flagData) {
|
|
241
160
|
try {
|
|
242
161
|
|
|
@@ -303,7 +222,7 @@ class MelCloudAtw extends EventEmitter {
|
|
|
303
222
|
headers: headers,
|
|
304
223
|
data: payload
|
|
305
224
|
});
|
|
306
|
-
|
|
225
|
+
|
|
307
226
|
return true;
|
|
308
227
|
case "melcloudhome":
|
|
309
228
|
switch (flag) {
|
|
@@ -363,7 +282,6 @@ class MelCloudAtw extends EventEmitter {
|
|
|
363
282
|
data: payload
|
|
364
283
|
});
|
|
365
284
|
|
|
366
|
-
this.updateData(deviceData, updateState);
|
|
367
285
|
return true;
|
|
368
286
|
default:
|
|
369
287
|
return;
|
|
@@ -373,14 +291,5 @@ class MelCloudAtw extends EventEmitter {
|
|
|
373
291
|
throw new Error(`Send data error: ${error.message}`);
|
|
374
292
|
}
|
|
375
293
|
}
|
|
376
|
-
|
|
377
|
-
updateData(deviceData, updateState = true) {
|
|
378
|
-
this.locks = true;
|
|
379
|
-
if (updateState) this.emit('deviceState', deviceData);
|
|
380
|
-
|
|
381
|
-
setTimeout(() => {
|
|
382
|
-
this.locks = false
|
|
383
|
-
}, 5000);
|
|
384
|
-
}
|
|
385
294
|
};
|
|
386
295
|
export default MelCloudAtw;
|
package/src/melclouderv.js
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import WebSocket from 'ws';
|
|
2
1
|
import axios from 'axios';
|
|
3
2
|
import EventEmitter from 'events';
|
|
4
|
-
import ImpulseGenerator from './impulsegenerator.js';
|
|
5
3
|
import Functions from './functions.js';
|
|
6
4
|
import { ApiUrls, ApiUrlsHome, Ventilation } from './constants.js';
|
|
7
5
|
|
|
8
6
|
class MelCloudErv extends EventEmitter {
|
|
9
|
-
constructor(account, device, devicesFile, defaultTempsFile, accountFile) {
|
|
7
|
+
constructor(account, device, devicesFile, defaultTempsFile, accountFile, melcloud) {
|
|
10
8
|
super();
|
|
11
9
|
this.accountType = account.type;
|
|
12
10
|
this.logSuccess = account.log?.success;
|
|
@@ -28,39 +26,20 @@ class MelCloudErv extends EventEmitter {
|
|
|
28
26
|
this.deviceData = {};
|
|
29
27
|
this.headers = {};
|
|
30
28
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
.
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
.on('state', (state) => {
|
|
38
|
-
this.emit(state ? 'success' : 'warn', `Impulse generator ${state ? 'started' : 'stopped'}`);
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
async handleWithLock(fn) {
|
|
43
|
-
if (this.locks) return;
|
|
29
|
+
let deviceData = null;
|
|
30
|
+
melcloud.on('devicesList', async (devicesData) => {
|
|
31
|
+
this.headers = devicesData.Headers;
|
|
32
|
+
deviceData = devicesData.Devices.find(device => device.DeviceID === this.deviceId);
|
|
33
|
+
if (!deviceData) return;
|
|
34
|
+
deviceData.Scenes = devicesData.Scenes ?? [];
|
|
44
35
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
} catch (error) {
|
|
49
|
-
this.emit('error', `Inpulse generator error: ${error}`);
|
|
50
|
-
} finally {
|
|
51
|
-
this.locks = false;
|
|
52
|
-
}
|
|
36
|
+
//update state
|
|
37
|
+
await this.updateState(deviceData);
|
|
38
|
+
}); this.firstRun = true;
|
|
53
39
|
}
|
|
54
40
|
|
|
55
|
-
async
|
|
41
|
+
async updateState(deviceData) {
|
|
56
42
|
try {
|
|
57
|
-
//read device info from file
|
|
58
|
-
const devicesData = await this.functions.readData(this.devicesFile, true);
|
|
59
|
-
if (!devicesData) return;
|
|
60
|
-
|
|
61
|
-
this.headers = devicesData.Headers;
|
|
62
|
-
const deviceData = devicesData.Devices.find(device => device.DeviceID === this.deviceId);
|
|
63
|
-
if (!deviceData) return;
|
|
64
43
|
if (this.accountType === 'melcloudhome') {
|
|
65
44
|
deviceData.Scenes = devicesData.Scenes ?? [];
|
|
66
45
|
|
|
@@ -194,7 +173,7 @@ class MelCloudErv extends EventEmitter {
|
|
|
194
173
|
headers: headers,
|
|
195
174
|
data: payload
|
|
196
175
|
});
|
|
197
|
-
|
|
176
|
+
|
|
198
177
|
return true;
|
|
199
178
|
case "melcloudhome":
|
|
200
179
|
switch (flag) {
|
|
@@ -257,7 +236,7 @@ class MelCloudErv extends EventEmitter {
|
|
|
257
236
|
headers: headers,
|
|
258
237
|
data: payload
|
|
259
238
|
});
|
|
260
|
-
|
|
239
|
+
|
|
261
240
|
return true;
|
|
262
241
|
default:
|
|
263
242
|
return;
|
|
@@ -267,14 +246,5 @@ class MelCloudErv extends EventEmitter {
|
|
|
267
246
|
throw new Error(`Send data error: ${error.message}`);
|
|
268
247
|
}
|
|
269
248
|
}
|
|
270
|
-
|
|
271
|
-
updateData(deviceData, updateState = true) {
|
|
272
|
-
this.locks = true;
|
|
273
|
-
if (updateState) this.emit('deviceState', deviceData);
|
|
274
|
-
|
|
275
|
-
setTimeout(() => {
|
|
276
|
-
this.locks = false
|
|
277
|
-
}, 5000);
|
|
278
|
-
}
|
|
279
249
|
};
|
|
280
250
|
export default MelCloudErv;
|
package/src/melcloudhome.js
CHANGED
|
@@ -225,31 +225,35 @@ class MelCloudHome extends EventEmitter {
|
|
|
225
225
|
|
|
226
226
|
try {
|
|
227
227
|
const url = `${ApiUrlsHome.WebSocketURL}${this.webSocketOptions.Hash}`;
|
|
228
|
-
|
|
228
|
+
this.socket = new WebSocket(url, { headers: this.webSocketOptions.Headers })
|
|
229
229
|
.on('error', (error) => {
|
|
230
230
|
if (this.logError) this.emit('error', `Socket error: ${error}`);
|
|
231
|
-
socket.close();
|
|
231
|
+
this.socket.close();
|
|
232
232
|
})
|
|
233
233
|
.on('close', () => {
|
|
234
234
|
if (this.logDebug) this.emit('debug', `Socket closed`);
|
|
235
235
|
this.cleanupSocket();
|
|
236
236
|
})
|
|
237
237
|
.on('open', () => {
|
|
238
|
-
this.socket = socket;
|
|
239
238
|
this.socketConnected = true;
|
|
240
239
|
this.connecting = false;
|
|
241
240
|
if (this.logSuccess) this.emit('success', `Socket Connect Success`);
|
|
242
241
|
|
|
243
242
|
// heartbeat
|
|
244
243
|
this.heartbeat = setInterval(() => {
|
|
245
|
-
if (socket.readyState === socket.OPEN) {
|
|
246
|
-
if (
|
|
247
|
-
socket.ping();
|
|
244
|
+
if (this.socket.readyState === this.socket.OPEN) {
|
|
245
|
+
if (this.logDebug) this.emit('debug', `Socket send heartbeat`);
|
|
246
|
+
this.socket.ping();
|
|
248
247
|
}
|
|
249
248
|
}, 30000);
|
|
250
249
|
})
|
|
251
250
|
.on('pong', () => {
|
|
252
|
-
if (
|
|
251
|
+
if (this.logDebug) this.emit('debug', `Socket received heartbeat`);
|
|
252
|
+
})
|
|
253
|
+
.on('message', (message) => {
|
|
254
|
+
const parsedMessage = JSON.parse(message);
|
|
255
|
+
const stringifyMessage = JSON.stringify(parsedMessage, null, 2);
|
|
256
|
+
if (this.logDebug) this.emit('debug', `Incoming message: ${stringifyMessage}`);
|
|
253
257
|
});
|
|
254
258
|
} catch (error) {
|
|
255
259
|
if (this.logError) this.emit('error', `Socket connection failed: ${error}`);
|
|
@@ -263,6 +267,7 @@ class MelCloudHome extends EventEmitter {
|
|
|
263
267
|
devicesList.Scenes = scenes;
|
|
264
268
|
devicesList.Headers = this.headers;
|
|
265
269
|
devicesList.WebSocket = this.socket;
|
|
270
|
+
this.emit('devicesList', devicesList);
|
|
266
271
|
|
|
267
272
|
await this.functions.saveData(this.devicesFile, devicesList);
|
|
268
273
|
if (this.logDebug) this.emit('debug', `${devicesCount} devices saved`);
|