homebridge-melcloud-control 4.2.5-beta.8 → 4.2.5
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/CHANGELOG.md +12 -0
- package/README.md +19 -18
- package/config.schema.json +11 -11
- package/index.js +6 -15
- package/package.json +2 -2
- package/src/constants.js +1 -0
- package/src/deviceata.js +33 -30
- package/src/deviceatw.js +31 -28
- package/src/deviceerv.js +31 -28
- package/src/melcloud.js +3 -14
- package/src/melcloudata.js +70 -52
- package/src/melcloudatw.js +65 -45
- package/src/melclouderv.js +77 -57
- package/src/melcloudhome.js +18 -33
package/src/melcloudata.js
CHANGED
|
@@ -5,7 +5,7 @@ import Functions from './functions.js';
|
|
|
5
5
|
import { ApiUrls, ApiUrlsHome, AirConditioner } from './constants.js';
|
|
6
6
|
|
|
7
7
|
class MelCloudAta extends EventEmitter {
|
|
8
|
-
constructor(account, device, devicesFile, defaultTempsFile) {
|
|
8
|
+
constructor(account, device, devicesFile, defaultTempsFile, accountFile) {
|
|
9
9
|
super();
|
|
10
10
|
this.accountType = account.type;
|
|
11
11
|
this.logWarn = account.log?.warn;
|
|
@@ -16,6 +16,7 @@ class MelCloudAta extends EventEmitter {
|
|
|
16
16
|
this.deviceId = device.id;
|
|
17
17
|
this.devicesFile = devicesFile;
|
|
18
18
|
this.defaultTempsFile = defaultTempsFile;
|
|
19
|
+
this.accountFile = accountFile;
|
|
19
20
|
this.functions = new Functions(this.logWarn, this.logError, this.logDebug)
|
|
20
21
|
.on('warn', warn => this.emit('warn', warn))
|
|
21
22
|
.on('error', error => this.emit('error', error))
|
|
@@ -23,10 +24,10 @@ class MelCloudAta extends EventEmitter {
|
|
|
23
24
|
|
|
24
25
|
//set default values
|
|
25
26
|
this.deviceData = {};
|
|
26
|
-
this.
|
|
27
|
+
this.headers = {};
|
|
27
28
|
|
|
28
29
|
//lock flag
|
|
29
|
-
this.locks =
|
|
30
|
+
this.locks = false;
|
|
30
31
|
this.impulseGenerator = new ImpulseGenerator()
|
|
31
32
|
.on('checkState', () => this.handleWithLock(async () => {
|
|
32
33
|
await this.checkState();
|
|
@@ -53,12 +54,9 @@ class MelCloudAta extends EventEmitter {
|
|
|
53
54
|
try {
|
|
54
55
|
//read device info from file
|
|
55
56
|
const devicesData = await this.functions.readData(this.devicesFile, true);
|
|
56
|
-
|
|
57
|
-
baseURL: this.baseURL,
|
|
58
|
-
timeout: 30000,
|
|
59
|
-
headers: devicesData.Headers
|
|
60
|
-
});
|
|
57
|
+
if (!devicesData) return;
|
|
61
58
|
|
|
59
|
+
this.headers = devicesData.Headers;
|
|
62
60
|
const deviceData = devicesData.Devices.find(device => device.DeviceID === this.deviceId);
|
|
63
61
|
if (this.accountType === 'melcloudhome') {
|
|
64
62
|
deviceData.Scenes = devicesData.Scenes ?? [];
|
|
@@ -73,12 +71,7 @@ class MelCloudAta extends EventEmitter {
|
|
|
73
71
|
deviceData.Device.DefaultHeatingSetTemperature = temps?.defaultHeatingSetTemperature ?? 20;
|
|
74
72
|
deviceData.Device.DefaultCoolingSetTemperature = temps?.defaultCoolingSetTemperature ?? 24;
|
|
75
73
|
}
|
|
76
|
-
|
|
77
|
-
const safeConfig = {
|
|
78
|
-
...deviceData,
|
|
79
|
-
Headers: 'removed',
|
|
80
|
-
};
|
|
81
|
-
if (this.logDebug) this.emit('debug', `Device Data: ${JSON.stringify(safeConfig, null, 2)}`);
|
|
74
|
+
if (this.logDebug) this.emit('debug', `Device Data: ${JSON.stringify(deviceData, null, 2)}`);
|
|
82
75
|
|
|
83
76
|
//device
|
|
84
77
|
const serialNumber = deviceData.SerialNumber || '4.0.0';
|
|
@@ -104,15 +97,18 @@ class MelCloudAta extends EventEmitter {
|
|
|
104
97
|
//display info if units are not configured in MELCloud service
|
|
105
98
|
if (unitsCount === 0 && this.logDebug) if (this.logDebug) this.emit('debug', `Units are not configured in MELCloud service`);
|
|
106
99
|
|
|
100
|
+
//filter info
|
|
101
|
+
const { Device: _ignored, ...info } = deviceData;
|
|
102
|
+
|
|
107
103
|
//restFul
|
|
108
104
|
if (this.restFulEnabled) {
|
|
109
|
-
this.emit('restFul', 'info',
|
|
105
|
+
this.emit('restFul', 'info', info);
|
|
110
106
|
this.emit('restFul', 'state', deviceData.Device);
|
|
111
107
|
}
|
|
112
108
|
|
|
113
109
|
//mqtt
|
|
114
110
|
if (this.mqttEnabled) {
|
|
115
|
-
this.emit('mqtt', 'Info',
|
|
111
|
+
this.emit('mqtt', 'Info', info);
|
|
116
112
|
this.emit('mqtt', 'State', deviceData.Device);
|
|
117
113
|
}
|
|
118
114
|
|
|
@@ -140,33 +136,48 @@ class MelCloudAta extends EventEmitter {
|
|
|
140
136
|
let path = '';
|
|
141
137
|
switch (accountType) {
|
|
142
138
|
case "melcloud":
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
139
|
+
switch (flag) {
|
|
140
|
+
case 'account':
|
|
141
|
+
flagData.Account.LoginData.UseFahrenheit = flagData.UseFahrenheit;
|
|
142
|
+
payload = { data: flagData.LoginData };
|
|
143
|
+
path = ApiUrls.UpdateApplicationOptions;
|
|
144
|
+
await this.functions.saveData(this.accountFile, flagData);
|
|
145
|
+
break;
|
|
146
|
+
default:
|
|
147
|
+
if (displayType === 1 && deviceData.Device.OperationMode === 8) {
|
|
148
|
+
deviceData.Device.SetTemperature = (deviceData.Device.DefaultCoolingSetTemperature + deviceData.Device.DefaultHeatingSetTemperature) / 2;
|
|
149
|
+
}
|
|
150
|
+
deviceData.Device.EffectiveFlags = flag;
|
|
151
|
+
payload = {
|
|
152
|
+
DeviceID: deviceData.Device.DeviceID,
|
|
153
|
+
EffectiveFlags: deviceData.Device.EffectiveFlags,
|
|
154
|
+
Power: deviceData.Device.Power,
|
|
155
|
+
SetTemperature: deviceData.Device.SetTemperature,
|
|
156
|
+
SetFanSpeed: deviceData.Device.FanSpeed,
|
|
157
|
+
OperationMode: deviceData.Device.OperationMode,
|
|
158
|
+
VaneHorizontal: deviceData.Device.VaneHorizontalDirection,
|
|
159
|
+
VaneVertical: deviceData.Device.VaneVerticalDirection,
|
|
160
|
+
DefaultHeatingSetTemperature: deviceData.Device.DefaultHeatingSetTemperature,
|
|
161
|
+
DefaultCoolingSetTemperature: deviceData.Device.DefaultCoolingSetTemperature,
|
|
162
|
+
ProhibitSetTemperature: deviceData.Device.ProhibitSetTemperature,
|
|
163
|
+
ProhibitOperationMode: deviceData.Device.ProhibitOperationMode,
|
|
164
|
+
ProhibitPower: deviceData.Device.ProhibitPower,
|
|
165
|
+
HideVaneControls: deviceData.HideVaneControls,
|
|
166
|
+
HideDryModeControl: deviceData.HideDryModeControl,
|
|
167
|
+
HasPendingCommand: true
|
|
168
|
+
};
|
|
169
|
+
path = ApiUrls.SetAta;
|
|
170
|
+
break;
|
|
146
171
|
}
|
|
147
172
|
|
|
148
|
-
deviceData.Device.EffectiveFlags = flag;
|
|
149
|
-
payload = {
|
|
150
|
-
DeviceID: deviceData.Device.DeviceID,
|
|
151
|
-
EffectiveFlags: deviceData.Device.EffectiveFlags,
|
|
152
|
-
Power: deviceData.Device.Power,
|
|
153
|
-
SetTemperature: deviceData.Device.SetTemperature,
|
|
154
|
-
SetFanSpeed: deviceData.Device.FanSpeed,
|
|
155
|
-
OperationMode: deviceData.Device.OperationMode,
|
|
156
|
-
VaneHorizontal: deviceData.Device.VaneHorizontalDirection,
|
|
157
|
-
VaneVertical: deviceData.Device.VaneVerticalDirection,
|
|
158
|
-
DefaultHeatingSetTemperature: deviceData.Device.DefaultHeatingSetTemperature,
|
|
159
|
-
DefaultCoolingSetTemperature: deviceData.Device.DefaultCoolingSetTemperature,
|
|
160
|
-
ProhibitSetTemperature: deviceData.Device.ProhibitSetTemperature,
|
|
161
|
-
ProhibitOperationMode: deviceData.Device.ProhibitOperationMode,
|
|
162
|
-
ProhibitPower: deviceData.Device.ProhibitPower,
|
|
163
|
-
HideVaneControls: deviceData.HideVaneControls,
|
|
164
|
-
HideDryModeControl: deviceData.HideDryModeControl,
|
|
165
|
-
HasPendingCommand: true
|
|
166
|
-
};
|
|
167
|
-
|
|
168
173
|
if (this.logDebug) this.emit('debug', `Send Data: ${JSON.stringify(payload, null, 2)}`);
|
|
169
|
-
await
|
|
174
|
+
await axios(path, {
|
|
175
|
+
method: 'POST',
|
|
176
|
+
baseURL: ApiUrls.BaseURL,
|
|
177
|
+
timeout: 30000,
|
|
178
|
+
headers: this.headers,
|
|
179
|
+
data: payload
|
|
180
|
+
});
|
|
170
181
|
this.updateData(deviceData);
|
|
171
182
|
return true;
|
|
172
183
|
case "melcloudhome":
|
|
@@ -192,7 +203,7 @@ class MelCloudAta extends EventEmitter {
|
|
|
192
203
|
};
|
|
193
204
|
method = 'POST';
|
|
194
205
|
path = ApiUrlsHome.PostProtectionFrost;
|
|
195
|
-
|
|
206
|
+
this.headers.Referer = ApiUrlsHome.Referers.PostProtectionFrost.replace('deviceid', deviceData.DeviceID);
|
|
196
207
|
break;
|
|
197
208
|
case 'overheatprotection':
|
|
198
209
|
payload = {
|
|
@@ -203,7 +214,7 @@ class MelCloudAta extends EventEmitter {
|
|
|
203
214
|
};
|
|
204
215
|
method = 'POST';
|
|
205
216
|
path = ApiUrlsHome.PostProtectionOverheat;
|
|
206
|
-
|
|
217
|
+
this.headers.Referer = ApiUrlsHome.Referers.PostProtectionOverheat.replace('deviceid', deviceData.DeviceID);
|
|
207
218
|
break;
|
|
208
219
|
case 'holidaymode':
|
|
209
220
|
payload = {
|
|
@@ -214,19 +225,19 @@ class MelCloudAta extends EventEmitter {
|
|
|
214
225
|
};
|
|
215
226
|
method = 'POST';
|
|
216
227
|
path = ApiUrlsHome.PostHolidayMode;
|
|
217
|
-
|
|
228
|
+
this.headers.Referer = ApiUrlsHome.Referers.PostHolidayMode.replace('deviceid', deviceData.DeviceID);
|
|
218
229
|
break;
|
|
219
230
|
case 'schedule':
|
|
220
231
|
payload = { enabled: deviceData.ScheduleEnabled };
|
|
221
232
|
method = 'PUT';
|
|
222
233
|
path = ApiUrlsHome.PutScheduleEnabled.replace('deviceid', deviceData.DeviceID);
|
|
223
|
-
|
|
234
|
+
this.headers.Referer = ApiUrlsHome.Referers.PutScheduleEnabled.replace('deviceid', deviceData.DeviceID);
|
|
224
235
|
break;
|
|
225
236
|
case 'scene':
|
|
226
237
|
method = 'PUT';
|
|
227
238
|
const state = flagData.Enabled ? 'Enable' : 'Disable';
|
|
228
239
|
path = ApiUrlsHome.PutScene[state].replace('sceneid', flagData.Id);
|
|
229
|
-
|
|
240
|
+
this.headers.Referer = ApiUrlsHome.Referers.GetPutScenes;
|
|
230
241
|
break;
|
|
231
242
|
default:
|
|
232
243
|
payload = {
|
|
@@ -241,14 +252,21 @@ class MelCloudAta extends EventEmitter {
|
|
|
241
252
|
};
|
|
242
253
|
method = 'PUT';
|
|
243
254
|
path = ApiUrlsHome.PutAta.replace('deviceid', deviceData.DeviceID);
|
|
244
|
-
|
|
255
|
+
this.headers.Referer = ApiUrlsHome.Referers.PutDeviceSettings;
|
|
245
256
|
break
|
|
246
257
|
}
|
|
247
258
|
|
|
248
|
-
|
|
249
|
-
|
|
259
|
+
this.headers['Content-Type'] = 'application/json; charset=utf-8';
|
|
260
|
+
this.headers.Origin = ApiUrlsHome.Origin;
|
|
250
261
|
if (this.logDebug) this.emit('debug', `Send Data: ${JSON.stringify(payload, null, 2)}, Headers: ${JSON.stringify(this.headers, null, 2)}`);
|
|
251
|
-
await
|
|
262
|
+
await axios(path, {
|
|
263
|
+
method: method,
|
|
264
|
+
baseURL: ApiUrlsHome.BaseURL,
|
|
265
|
+
timeout: 30000,
|
|
266
|
+
headers: this.headers,
|
|
267
|
+
data: payload
|
|
268
|
+
});
|
|
269
|
+
|
|
252
270
|
this.updateData(deviceData);
|
|
253
271
|
return true;
|
|
254
272
|
default:
|
|
@@ -261,12 +279,12 @@ class MelCloudAta extends EventEmitter {
|
|
|
261
279
|
}
|
|
262
280
|
|
|
263
281
|
updateData(deviceData) {
|
|
264
|
-
this.
|
|
282
|
+
this.locks = true;
|
|
265
283
|
this.emit('deviceState', deviceData);
|
|
266
284
|
|
|
267
285
|
setTimeout(() => {
|
|
268
|
-
this.
|
|
269
|
-
},
|
|
286
|
+
this.locks = false
|
|
287
|
+
}, 5000);
|
|
270
288
|
}
|
|
271
289
|
};
|
|
272
290
|
export default MelCloudAta;
|
package/src/melcloudatw.js
CHANGED
|
@@ -5,7 +5,7 @@ import Functions from './functions.js';
|
|
|
5
5
|
import { ApiUrls, ApiUrlsHome, HeatPump } from './constants.js';
|
|
6
6
|
|
|
7
7
|
class MelCloudAtw extends EventEmitter {
|
|
8
|
-
constructor(account, device, devicesFile, defaultTempsFile) {
|
|
8
|
+
constructor(account, device, devicesFile, defaultTempsFile, accountFile) {
|
|
9
9
|
super();
|
|
10
10
|
this.accountType = account.type;
|
|
11
11
|
this.logWarn = account.log?.warn;
|
|
@@ -16,16 +16,18 @@ class MelCloudAtw extends EventEmitter {
|
|
|
16
16
|
this.deviceId = device.id;
|
|
17
17
|
this.devicesFile = devicesFile;
|
|
18
18
|
this.defaultTempsFile = defaultTempsFile;
|
|
19
|
+
this.accountFile = accountFile;
|
|
19
20
|
this.functions = new Functions(this.logWarn, this.logError, this.logDebug)
|
|
20
21
|
.on('warn', warn => this.emit('warn', warn))
|
|
21
22
|
.on('error', error => this.emit('error', error))
|
|
22
23
|
.on('debug', debug => this.emit('debug', debug));
|
|
23
24
|
|
|
24
25
|
//set default values
|
|
25
|
-
this.
|
|
26
|
+
this.deviceData = {};
|
|
27
|
+
this.headers = {};
|
|
26
28
|
|
|
27
29
|
//lock flags
|
|
28
|
-
this.locks =
|
|
30
|
+
this.locks = false;
|
|
29
31
|
this.impulseGenerator = new ImpulseGenerator()
|
|
30
32
|
.on('checkState', () => this.handleWithLock(async () => {
|
|
31
33
|
await this.checkState();
|
|
@@ -52,22 +54,14 @@ class MelCloudAtw extends EventEmitter {
|
|
|
52
54
|
try {
|
|
53
55
|
//read device info from file
|
|
54
56
|
const devicesData = await this.functions.readData(this.devicesFile, true);
|
|
55
|
-
|
|
56
|
-
baseURL: this.baseURL,
|
|
57
|
-
timeout: 30000,
|
|
58
|
-
headers: devicesData.Headers
|
|
59
|
-
});
|
|
57
|
+
if (!devicesData) return;
|
|
60
58
|
|
|
59
|
+
this.headers = devicesData.Headers;
|
|
61
60
|
const deviceData = devicesData.Devices.find(device => device.DeviceID === this.deviceId);
|
|
62
61
|
if (this.accountType === 'melcloudhome') {
|
|
63
62
|
deviceData.Scenes = devicesData.Scenes ?? [];
|
|
64
63
|
}
|
|
65
|
-
|
|
66
|
-
const safeConfig = {
|
|
67
|
-
...deviceData,
|
|
68
|
-
Headers: 'removed',
|
|
69
|
-
};
|
|
70
|
-
if (this.logDebug) this.emit('debug', `Device Data: ${JSON.stringify(safeConfig, null, 2)}`);
|
|
64
|
+
if (this.logDebug) this.emit('debug', `Device Data: ${JSON.stringify(deviceData, null, 2)}`);
|
|
71
65
|
|
|
72
66
|
//device
|
|
73
67
|
//device
|
|
@@ -96,22 +90,25 @@ class MelCloudAtw extends EventEmitter {
|
|
|
96
90
|
//display info if units are not configured in MELCloud service
|
|
97
91
|
if (unitsCount === 0 && this.logDebug) if (this.logDebug) this.emit('debug', `Units are not configured in MELCloud service`);
|
|
98
92
|
|
|
93
|
+
//filter info
|
|
94
|
+
const { Device: _ignored, ...info } = deviceData;
|
|
95
|
+
|
|
99
96
|
//restFul
|
|
100
97
|
if (this.restFulEnabled) {
|
|
101
|
-
this.emit('restFul', 'info',
|
|
98
|
+
this.emit('restFul', 'info', info);
|
|
102
99
|
this.emit('restFul', 'state', deviceData.Device);
|
|
103
100
|
}
|
|
104
101
|
|
|
105
102
|
//mqtt
|
|
106
103
|
if (this.mqttEnabled) {
|
|
107
|
-
this.emit('mqtt', 'Info',
|
|
104
|
+
this.emit('mqtt', 'Info', info);
|
|
108
105
|
this.emit('mqtt', 'State', deviceData.Device);
|
|
109
106
|
}
|
|
110
107
|
|
|
111
108
|
//check state changes
|
|
112
|
-
const deviceDataHasNotChanged = JSON.stringify(
|
|
109
|
+
const deviceDataHasNotChanged = JSON.stringify(deviceData) === JSON.stringify(this.deviceData);
|
|
113
110
|
if (deviceDataHasNotChanged) return;
|
|
114
|
-
this.
|
|
111
|
+
this.deviceData = deviceData;
|
|
115
112
|
|
|
116
113
|
//emit info
|
|
117
114
|
this.emit('deviceInfo', indoor.model, outdoor.model, serialNumber, firmwareAppVersion, hasHotWaterTank, hasZone2);
|
|
@@ -146,32 +143,49 @@ class MelCloudAtw extends EventEmitter {
|
|
|
146
143
|
let path = '';
|
|
147
144
|
switch (accountType) {
|
|
148
145
|
case "melcloud":
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
146
|
+
switch (flag) {
|
|
147
|
+
case 'account':
|
|
148
|
+
flagData.Account.LoginData.UseFahrenheit = flagData.UseFahrenheit;
|
|
149
|
+
payload = { data: flagData.LoginData };
|
|
150
|
+
path = ApiUrls.UpdateApplicationOptions;
|
|
151
|
+
await this.functions.saveData(this.accountFile, flagData);
|
|
152
|
+
break;
|
|
153
|
+
default:
|
|
154
|
+
deviceData.Device.EffectiveFlags = flag;
|
|
155
|
+
payload = {
|
|
156
|
+
DeviceID: deviceData.Device.DeviceID,
|
|
157
|
+
EffectiveFlags: deviceData.Device.EffectiveFlags,
|
|
158
|
+
Power: deviceData.Device.Power,
|
|
159
|
+
SetTemperatureZone1: deviceData.Device.SetTemperatureZone1,
|
|
160
|
+
SetTemperatureZone2: deviceData.Device.SetTemperatureZone2,
|
|
161
|
+
OperationMode: deviceData.Device.OperationMode,
|
|
162
|
+
OperationModeZone1: deviceData.Device.OperationModeZone1,
|
|
163
|
+
OperationModeZone2: deviceData.Device.OperationModeZone2,
|
|
164
|
+
SetHeatFlowTemperatureZone1: deviceData.Device.SetHeatFlowTemperatureZone1,
|
|
165
|
+
SetHeatFlowTemperatureZone2: deviceData.Device.SetHeatFlowTemperatureZone2,
|
|
166
|
+
SetCoolFlowTemperatureZone1: deviceData.Device.SetCoolFlowTemperatureZone1,
|
|
167
|
+
SetCoolFlowTemperatureZone2: deviceData.Device.SetCoolFlowTemperatureZone2,
|
|
168
|
+
SetTankWaterTemperature: deviceData.Device.SetTankWaterTemperature,
|
|
169
|
+
ForcedHotWaterMode: deviceData.Device.ForcedHotWaterMode,
|
|
170
|
+
EcoHotWater: deviceData.Device.EcoHotWater,
|
|
171
|
+
HolidayMode: deviceData.Device.HolidayMode,
|
|
172
|
+
ProhibitZone1: deviceData.Device.ProhibitHeatingZone1,
|
|
173
|
+
ProhibitZone2: deviceData.Device.ProhibitHeatingZone2,
|
|
174
|
+
ProhibitHotWater: deviceData.Device.ProhibitHotWater,
|
|
175
|
+
HasPendingCommand: true
|
|
176
|
+
}
|
|
177
|
+
path = ApiUrls.SetAtw;
|
|
178
|
+
break;
|
|
171
179
|
}
|
|
172
180
|
|
|
173
181
|
if (this.logDebug) this.emit('debug', `Send Data: ${JSON.stringify(payload, null, 2)}`);
|
|
174
|
-
await
|
|
182
|
+
await axios(path, {
|
|
183
|
+
method: 'POST',
|
|
184
|
+
baseURL: ApiUrls.BaseURL,
|
|
185
|
+
timeout: 30000,
|
|
186
|
+
headers: this.headers,
|
|
187
|
+
data: payload
|
|
188
|
+
});
|
|
175
189
|
this.updateData(deviceData);
|
|
176
190
|
return true;
|
|
177
191
|
case "melcloudhome":
|
|
@@ -224,7 +238,13 @@ class MelCloudAtw extends EventEmitter {
|
|
|
224
238
|
this.headers['Content-Type'] = 'application/json; charset=utf-8';
|
|
225
239
|
this.headers.Origin = ApiUrlsHome.Origin;
|
|
226
240
|
if (this.logDebug) this.emit('debug', `Send Data: ${JSON.stringify(payload, null, 2)}, Headers: ${JSON.stringify(this.headers, null, 2)}`);
|
|
227
|
-
await
|
|
241
|
+
await axios(path, {
|
|
242
|
+
method: method,
|
|
243
|
+
baseURL: ApiUrlsHome.BaseURL,
|
|
244
|
+
timeout: 30000,
|
|
245
|
+
headers: this.headers,
|
|
246
|
+
data: payload
|
|
247
|
+
});
|
|
228
248
|
this.updateData(deviceData);
|
|
229
249
|
return true;
|
|
230
250
|
default:
|
|
@@ -237,12 +257,12 @@ class MelCloudAtw extends EventEmitter {
|
|
|
237
257
|
}
|
|
238
258
|
|
|
239
259
|
updateData(deviceData) {
|
|
240
|
-
this.
|
|
260
|
+
this.locks = true;
|
|
241
261
|
this.emit('deviceState', deviceData);
|
|
242
262
|
|
|
243
263
|
setTimeout(() => {
|
|
244
|
-
this.
|
|
245
|
-
},
|
|
264
|
+
this.locks = false
|
|
265
|
+
}, 5000);
|
|
246
266
|
}
|
|
247
267
|
};
|
|
248
268
|
export default MelCloudAtw;
|
package/src/melclouderv.js
CHANGED
|
@@ -5,7 +5,7 @@ import Functions from './functions.js';
|
|
|
5
5
|
import { ApiUrls, ApiUrlsHome, Ventilation } from './constants.js';
|
|
6
6
|
|
|
7
7
|
class MelCloudErv extends EventEmitter {
|
|
8
|
-
constructor(account, device, devicesFile, defaultTempsFile) {
|
|
8
|
+
constructor(account, device, devicesFile, defaultTempsFile, accountFile) {
|
|
9
9
|
super();
|
|
10
10
|
this.accountType = account.type;
|
|
11
11
|
this.logWarn = account.log?.warn;
|
|
@@ -16,16 +16,18 @@ class MelCloudErv extends EventEmitter {
|
|
|
16
16
|
this.deviceId = device.id;
|
|
17
17
|
this.devicesFile = devicesFile;
|
|
18
18
|
this.defaultTempsFile = defaultTempsFile;
|
|
19
|
+
this.accountFile = accountFile;
|
|
19
20
|
this.functions = new Functions(this.logWarn, this.logError, this.logDebug)
|
|
20
21
|
.on('warn', warn => this.emit('warn', warn))
|
|
21
22
|
.on('error', error => this.emit('error', error))
|
|
22
23
|
.on('debug', debug => this.emit('debug', debug));
|
|
23
24
|
|
|
24
25
|
//set default values
|
|
25
|
-
this.
|
|
26
|
+
this.deviceData = {};
|
|
27
|
+
this.headers = {};
|
|
26
28
|
|
|
27
29
|
//lock flags
|
|
28
|
-
this.locks =
|
|
30
|
+
this.locks = false;
|
|
29
31
|
this.impulseGenerator = new ImpulseGenerator()
|
|
30
32
|
.on('checkState', () => this.handleWithLock(async () => {
|
|
31
33
|
await this.checkState();
|
|
@@ -52,12 +54,9 @@ class MelCloudErv extends EventEmitter {
|
|
|
52
54
|
try {
|
|
53
55
|
//read device info from file
|
|
54
56
|
const devicesData = await this.functions.readData(this.devicesFile, true);
|
|
55
|
-
|
|
56
|
-
baseURL: this.baseURL,
|
|
57
|
-
timeout: 30000,
|
|
58
|
-
headers: devicesData.Headers
|
|
59
|
-
});
|
|
57
|
+
if (!devicesData) return;
|
|
60
58
|
|
|
59
|
+
this.headers = devicesData.Headers;
|
|
61
60
|
const deviceData = devicesData.Devices.find(device => device.DeviceID === this.deviceId);
|
|
62
61
|
if (this.accountType === 'melcloudhome') {
|
|
63
62
|
deviceData.Scenes = devicesData.Scenes ?? [];
|
|
@@ -67,12 +66,7 @@ class MelCloudErv extends EventEmitter {
|
|
|
67
66
|
deviceData.Device.DefaultHeatingSetTemperature = temps?.defaultHeatingSetTemperature ?? 20;
|
|
68
67
|
deviceData.Device.DefaultCoolingSetTemperature = temps?.defaultCoolingSetTemperature ?? 24;
|
|
69
68
|
}
|
|
70
|
-
|
|
71
|
-
const safeConfig = {
|
|
72
|
-
...deviceData,
|
|
73
|
-
Headers: 'removed',
|
|
74
|
-
};
|
|
75
|
-
if (this.logDebug) this.emit('debug', `Device Data: ${JSON.stringify(safeConfig, null, 2)}`);
|
|
69
|
+
if (this.logDebug) this.emit('debug', `Device Data: ${JSON.stringify(deviceData, null, 2)}`);
|
|
76
70
|
|
|
77
71
|
//device
|
|
78
72
|
const serialNumber = deviceData.SerialNumber || '4.0.0';
|
|
@@ -98,22 +92,25 @@ class MelCloudErv extends EventEmitter {
|
|
|
98
92
|
//display info if units are not configured in MELCloud service
|
|
99
93
|
if (unitsCount === 0 && this.logDebug) if (this.logDebug) this.emit('debug', `Units are not configured in MELCloud service`);
|
|
100
94
|
|
|
95
|
+
//filter info
|
|
96
|
+
const { Device: _ignored, ...info } = deviceData;
|
|
97
|
+
|
|
101
98
|
//restFul
|
|
102
99
|
if (this.restFulEnabled) {
|
|
103
|
-
this.emit('restFul', 'info',
|
|
100
|
+
this.emit('restFul', 'info', info);
|
|
104
101
|
this.emit('restFul', 'state', deviceData.Device);
|
|
105
102
|
}
|
|
106
103
|
|
|
107
104
|
//mqtt
|
|
108
105
|
if (this.mqttEnabled) {
|
|
109
|
-
this.emit('mqtt', 'Info',
|
|
106
|
+
this.emit('mqtt', 'Info', info);
|
|
110
107
|
this.emit('mqtt', 'State', deviceData.Device);
|
|
111
108
|
}
|
|
112
109
|
|
|
113
110
|
//check state changes
|
|
114
|
-
const deviceDataHasNotChanged = JSON.stringify(
|
|
111
|
+
const deviceDataHasNotChanged = JSON.stringify(deviceData) === JSON.stringify(this.deviceData);
|
|
115
112
|
if (deviceDataHasNotChanged) return;
|
|
116
|
-
this.
|
|
113
|
+
this.deviceData = deviceData;
|
|
117
114
|
|
|
118
115
|
//emit info
|
|
119
116
|
this.emit('deviceInfo', indoor.model, outdoor.model, serialNumber, firmwareAppVersion);
|
|
@@ -134,47 +131,64 @@ class MelCloudErv extends EventEmitter {
|
|
|
134
131
|
let path = '';
|
|
135
132
|
switch (accountType) {
|
|
136
133
|
case "melcloud":
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
case
|
|
148
|
-
|
|
149
|
-
|
|
134
|
+
switch (flag) {
|
|
135
|
+
case 'account':
|
|
136
|
+
flagData.Account.LoginData.UseFahrenheit = flagData.UseFahrenheit;
|
|
137
|
+
payload = { data: flagData.LoginData };
|
|
138
|
+
path = ApiUrls.UpdateApplicationOptions;
|
|
139
|
+
await this.functions.saveData(this.accountFile, flagData);
|
|
140
|
+
break;
|
|
141
|
+
default:
|
|
142
|
+
//set target temp based on display mode and ventilation mode
|
|
143
|
+
switch (displayType) {
|
|
144
|
+
case 1: //Heather/Cooler
|
|
145
|
+
switch (deviceData.Device.VentilationMode) {
|
|
146
|
+
case 0: //LOSNAY
|
|
147
|
+
deviceData.Device.SetTemperature = deviceData.Device.DefaultHeatingSetTemperature;
|
|
148
|
+
break;
|
|
149
|
+
case 1: //BYPASS
|
|
150
|
+
deviceData.Device.SetTemperature = deviceData.Device.DefaultCoolingSetTemperature;
|
|
151
|
+
break;
|
|
152
|
+
case 2: //AUTO
|
|
153
|
+
const setTemperature = (deviceData.Device.DefaultCoolingSetTemperature + deviceData.Device.DefaultHeatingSetTemperature) / 2;
|
|
154
|
+
deviceData.Device.SetTemperature = setTemperature;
|
|
155
|
+
break;
|
|
156
|
+
};
|
|
157
|
+
case 2: //Thermostat
|
|
158
|
+
deviceData.Device.SetTemperature = deviceData.Device.SetTemperature;
|
|
150
159
|
break;
|
|
151
160
|
};
|
|
152
|
-
|
|
153
|
-
|
|
161
|
+
|
|
162
|
+
//device state
|
|
163
|
+
deviceData.Device.EffectiveFlags = flag;
|
|
164
|
+
payload = {
|
|
165
|
+
DeviceID: deviceData.Device.DeviceID,
|
|
166
|
+
EffectiveFlags: deviceData.Device.EffectiveFlags,
|
|
167
|
+
Power: deviceData.Device.Power,
|
|
168
|
+
SetTemperature: deviceData.Device.SetTemperature,
|
|
169
|
+
SetFanSpeed: deviceData.Device.SetFanSpeed,
|
|
170
|
+
OperationMode: deviceData.Device.OperationMode,
|
|
171
|
+
VentilationMode: deviceData.Device.VentilationMode,
|
|
172
|
+
DefaultCoolingSetTemperature: deviceData.Device.DefaultCoolingSetTemperature,
|
|
173
|
+
DefaultHeatingSetTemperature: deviceData.Device.DefaultHeatingSetTemperature,
|
|
174
|
+
HideRoomTemperature: deviceData.Device.HideRoomTemperature,
|
|
175
|
+
HideSupplyTemperature: deviceData.Device.HideSupplyTemperature,
|
|
176
|
+
HideOutdoorTemperature: deviceData.Device.HideOutdoorTemperature,
|
|
177
|
+
NightPurgeMode: deviceData.Device.NightPurgeMode,
|
|
178
|
+
HasPendingCommand: true
|
|
179
|
+
}
|
|
180
|
+
path = ApiUrls.SetErv;
|
|
154
181
|
break;
|
|
155
|
-
};
|
|
156
|
-
|
|
157
|
-
//device state
|
|
158
|
-
deviceData.Device.EffectiveFlags = flag;
|
|
159
|
-
payload = {
|
|
160
|
-
DeviceID: deviceData.Device.DeviceID,
|
|
161
|
-
EffectiveFlags: deviceData.Device.EffectiveFlags,
|
|
162
|
-
Power: deviceData.Device.Power,
|
|
163
|
-
SetTemperature: deviceData.Device.SetTemperature,
|
|
164
|
-
SetFanSpeed: deviceData.Device.SetFanSpeed,
|
|
165
|
-
OperationMode: deviceData.Device.OperationMode,
|
|
166
|
-
VentilationMode: deviceData.Device.VentilationMode,
|
|
167
|
-
DefaultCoolingSetTemperature: deviceData.Device.DefaultCoolingSetTemperature,
|
|
168
|
-
DefaultHeatingSetTemperature: deviceData.Device.DefaultHeatingSetTemperature,
|
|
169
|
-
HideRoomTemperature: deviceData.Device.HideRoomTemperature,
|
|
170
|
-
HideSupplyTemperature: deviceData.Device.HideSupplyTemperature,
|
|
171
|
-
HideOutdoorTemperature: deviceData.Device.HideOutdoorTemperature,
|
|
172
|
-
NightPurgeMode: deviceData.Device.NightPurgeMode,
|
|
173
|
-
HasPendingCommand: true
|
|
174
182
|
}
|
|
175
183
|
|
|
176
184
|
if (this.logDebug) this.emit('debug', `Send Data: ${JSON.stringify(payload, null, 2)}`);
|
|
177
|
-
await
|
|
185
|
+
await axios(path, {
|
|
186
|
+
method: 'POST',
|
|
187
|
+
baseURL: ApiUrls.BaseURL,
|
|
188
|
+
timeout: 30000,
|
|
189
|
+
headers: this.headers,
|
|
190
|
+
data: payload
|
|
191
|
+
});
|
|
178
192
|
this.updateData(deviceData);
|
|
179
193
|
return true;
|
|
180
194
|
case "melcloudhome":
|
|
@@ -231,7 +245,13 @@ class MelCloudErv extends EventEmitter {
|
|
|
231
245
|
this.headers['Content-Type'] = 'application/json; charset=utf-8';
|
|
232
246
|
this.headers.Origin = ApiUrlsHome.Origin;
|
|
233
247
|
if (this.logDebug) this.emit('debug', `Send Data: ${JSON.stringify(payload, null, 2)}, Headers: ${JSON.stringify(this.headers, null, 2)}`);
|
|
234
|
-
await
|
|
248
|
+
await axios(path, {
|
|
249
|
+
method: method,
|
|
250
|
+
baseURL: ApiUrlsHome.BaseURL,
|
|
251
|
+
timeout: 30000,
|
|
252
|
+
headers: this.headers,
|
|
253
|
+
data: payload
|
|
254
|
+
});
|
|
235
255
|
this.updateData(deviceData);
|
|
236
256
|
return true;
|
|
237
257
|
default:
|
|
@@ -244,12 +264,12 @@ class MelCloudErv extends EventEmitter {
|
|
|
244
264
|
}
|
|
245
265
|
|
|
246
266
|
updateData(deviceData) {
|
|
247
|
-
this.
|
|
267
|
+
this.locks = true;
|
|
248
268
|
this.emit('deviceState', deviceData);
|
|
249
269
|
|
|
250
270
|
setTimeout(() => {
|
|
251
|
-
this.
|
|
252
|
-
},
|
|
271
|
+
this.locks = false
|
|
272
|
+
}, 5000);
|
|
253
273
|
}
|
|
254
274
|
};
|
|
255
275
|
export default MelCloudErv;
|