homebridge-melcloud-control 4.2.3-beta.7 → 4.2.4
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 +11 -0
- package/README.md +36 -21
- package/config.schema.json +433 -25
- package/homebridge-ui/public/index.html +86 -16
- package/index.js +3 -3
- package/package.json +2 -2
- package/src/constants.js +48 -5
- package/src/deviceata.js +274 -155
- package/src/deviceatw.js +334 -218
- package/src/deviceerv.js +250 -126
- package/src/melcloud.js +25 -33
- package/src/melcloudata.js +35 -21
- package/src/melcloudatw.js +46 -29
- package/src/melclouderv.js +37 -21
- package/src/melcloudhome.js +77 -38
package/src/melcloud.js
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import axios from 'axios';
|
|
2
|
-
import { exec } from 'child_process';
|
|
3
|
-
import { promisify } from 'util';
|
|
4
2
|
import EventEmitter from 'events';
|
|
5
3
|
import ImpulseGenerator from './impulsegenerator.js';
|
|
6
4
|
import Functions from './functions.js';
|
|
7
|
-
import { ApiUrls
|
|
8
|
-
const execPromise = promisify(exec);
|
|
5
|
+
import { ApiUrls } from './constants.js';
|
|
9
6
|
|
|
10
7
|
class MelCloud extends EventEmitter {
|
|
11
8
|
constructor(account, accountFile, buildingsFile, devicesFile, pluginStart = false) {
|
|
@@ -20,7 +17,8 @@ class MelCloud extends EventEmitter {
|
|
|
20
17
|
this.accountFile = accountFile;
|
|
21
18
|
this.buildingsFile = buildingsFile;
|
|
22
19
|
this.devicesFile = devicesFile;
|
|
23
|
-
this.
|
|
20
|
+
this.headers = {};
|
|
21
|
+
|
|
24
22
|
this.functions = new Functions(this.logWarn, this.logError, this.logDebug)
|
|
25
23
|
.on('warn', warn => this.emit('warn', warn))
|
|
26
24
|
.on('error', error => this.emit('error', error))
|
|
@@ -29,13 +27,9 @@ class MelCloud extends EventEmitter {
|
|
|
29
27
|
if (pluginStart) {
|
|
30
28
|
//lock flags
|
|
31
29
|
this.locks = {
|
|
32
|
-
connect: false,
|
|
33
30
|
checkDevicesList: false
|
|
34
31
|
};
|
|
35
32
|
this.impulseGenerator = new ImpulseGenerator()
|
|
36
|
-
.on('connect', () => this.handleWithLock('connect', async () => {
|
|
37
|
-
await this.connect(true);
|
|
38
|
-
}))
|
|
39
33
|
.on('checkDevicesList', () => this.handleWithLock('checkDevicesList', async () => {
|
|
40
34
|
await this.checkDevicesList();
|
|
41
35
|
}))
|
|
@@ -61,18 +55,13 @@ class MelCloud extends EventEmitter {
|
|
|
61
55
|
// MELCloud
|
|
62
56
|
async checkDevicesList() {
|
|
63
57
|
try {
|
|
64
|
-
const devicesList = { State: false, Info: null, Devices: [] }
|
|
65
|
-
const headers = {
|
|
66
|
-
'X-MitsContextKey': this.contextKey,
|
|
67
|
-
'Content-Type': 'application/json'
|
|
68
|
-
}
|
|
69
|
-
|
|
58
|
+
const devicesList = { State: false, Info: null, Devices: [], Scenes: [] }
|
|
70
59
|
if (this.logDebug) this.emit('debug', `Scanning for devices...`);
|
|
71
60
|
const listDevicesData = await axios(ApiUrls.ListDevices, {
|
|
72
61
|
method: 'GET',
|
|
73
62
|
baseURL: ApiUrls.BaseURL,
|
|
74
63
|
timeout: 15000,
|
|
75
|
-
headers: headers
|
|
64
|
+
headers: this.headers
|
|
76
65
|
});
|
|
77
66
|
|
|
78
67
|
if (!listDevicesData || !listDevicesData.data) {
|
|
@@ -91,6 +80,7 @@ class MelCloud extends EventEmitter {
|
|
|
91
80
|
await this.functions.saveData(this.buildingsFile, buildingsList);
|
|
92
81
|
if (this.logDebug) this.emit('debug', `Buildings list saved`);
|
|
93
82
|
|
|
83
|
+
const devices = [];
|
|
94
84
|
for (const building of buildingsList) {
|
|
95
85
|
if (!building.Structure) {
|
|
96
86
|
this.emit('warn', `Building missing structure: ${building.BuildingName || 'Unnamed'}`);
|
|
@@ -111,24 +101,26 @@ class MelCloud extends EventEmitter {
|
|
|
111
101
|
// Zamiana ID na string
|
|
112
102
|
allDevices.forEach(device => {
|
|
113
103
|
device.DeviceID = String(device.DeviceID);
|
|
114
|
-
device.Headers = headers;
|
|
104
|
+
device.Headers = this.headers;
|
|
115
105
|
});
|
|
116
106
|
|
|
117
107
|
if (this.logDebug) this.emit('debug', `Found ${allDevices.length} devices in building: ${building.Name || 'Unnamed'}`);
|
|
118
|
-
|
|
108
|
+
devices.push(...allDevices);
|
|
119
109
|
}
|
|
120
110
|
|
|
121
|
-
const devicesCount =
|
|
111
|
+
const devicesCount = devices.length;
|
|
122
112
|
if (devicesCount === 0) {
|
|
123
113
|
devicesList.Info = 'No devices found'
|
|
124
114
|
return devicesList;
|
|
125
115
|
}
|
|
126
116
|
|
|
127
|
-
await this.functions.saveData(this.devicesFile, devicesList.Devices);
|
|
128
|
-
if (this.logDebug) this.emit('debug', `${devicesCount} devices saved`);
|
|
129
|
-
|
|
130
117
|
devicesList.State = true;
|
|
131
118
|
devicesList.Info = `Found ${devicesCount} devices`;
|
|
119
|
+
devicesList.Devices = devices;
|
|
120
|
+
|
|
121
|
+
await this.functions.saveData(this.devicesFile, devicesList);
|
|
122
|
+
if (this.logDebug) this.emit('debug', `${devicesCount} devices saved`);
|
|
123
|
+
|
|
132
124
|
return devicesList;
|
|
133
125
|
} catch (error) {
|
|
134
126
|
throw new Error(`Check devices list error: ${error.message}`);
|
|
@@ -139,7 +131,7 @@ class MelCloud extends EventEmitter {
|
|
|
139
131
|
if (this.logDebug) this.emit('debug', `Connecting to MELCloud`);
|
|
140
132
|
|
|
141
133
|
try {
|
|
142
|
-
const accountInfo = { State: false, Info: '', LoginData: null,
|
|
134
|
+
const accountInfo = { State: false, Info: '', LoginData: null, Headers: {}, UseFahrenheit: false }
|
|
143
135
|
|
|
144
136
|
const payload = {
|
|
145
137
|
Email: this.user,
|
|
@@ -175,12 +167,16 @@ class MelCloud extends EventEmitter {
|
|
|
175
167
|
accountInfo.Info = 'Context key missing'
|
|
176
168
|
return accountInfo;
|
|
177
169
|
}
|
|
178
|
-
|
|
170
|
+
|
|
171
|
+
this.headers = {
|
|
172
|
+
'X-MitsContextKey': contextKey,
|
|
173
|
+
'Content-Type': 'application/json'
|
|
174
|
+
};
|
|
179
175
|
|
|
180
176
|
accountInfo.State = true;
|
|
181
177
|
accountInfo.Info = 'Connect to MELCloud Success';
|
|
182
178
|
accountInfo.LoginData = loginData;
|
|
183
|
-
accountInfo.
|
|
179
|
+
accountInfo.Headers = this.headers;
|
|
184
180
|
await this.functions.saveData(this.accountFile, accountInfo);
|
|
185
181
|
|
|
186
182
|
return accountInfo
|
|
@@ -191,18 +187,14 @@ class MelCloud extends EventEmitter {
|
|
|
191
187
|
|
|
192
188
|
async send(accountInfo) {
|
|
193
189
|
try {
|
|
194
|
-
const
|
|
190
|
+
const payload = { data: accountInfo.LoginData };
|
|
191
|
+
await axios(ApiUrls.UpdateApplicationOptions, {
|
|
195
192
|
method: 'POST',
|
|
196
193
|
baseURL: ApiUrls.BaseURL,
|
|
197
194
|
timeout: 15000,
|
|
198
|
-
headers:
|
|
199
|
-
|
|
200
|
-
'content-type': 'application/json'
|
|
201
|
-
}
|
|
195
|
+
headers: accountInfo.Headers,
|
|
196
|
+
data: payload
|
|
202
197
|
});
|
|
203
|
-
|
|
204
|
-
const payload = { data: accountInfo.LoginData };
|
|
205
|
-
await axiosInstance(ApiUrls.UpdateApplicationOptions, payload);
|
|
206
198
|
await this.functions.saveData(this.accountFile, accountInfo);
|
|
207
199
|
return true;
|
|
208
200
|
} catch (error) {
|
package/src/melcloudata.js
CHANGED
|
@@ -24,7 +24,7 @@ class MelCloudAta extends EventEmitter {
|
|
|
24
24
|
//set default values
|
|
25
25
|
this.deviceData = {};
|
|
26
26
|
|
|
27
|
-
//lock
|
|
27
|
+
//lock flag
|
|
28
28
|
this.locks = true;
|
|
29
29
|
this.impulseGenerator = new ImpulseGenerator()
|
|
30
30
|
.on('checkState', () => this.handleWithLock(async () => {
|
|
@@ -52,11 +52,11 @@ class MelCloudAta extends EventEmitter {
|
|
|
52
52
|
try {
|
|
53
53
|
//read device info from file
|
|
54
54
|
const devicesData = await this.functions.readData(this.devicesFile, true);
|
|
55
|
-
const
|
|
55
|
+
const scenes = devicesData.Scenes ?? [];
|
|
56
|
+
const deviceData = devicesData.Devices.find(device => device.DeviceID === this.deviceId);
|
|
56
57
|
|
|
57
58
|
if (this.accountType === 'melcloudhome') {
|
|
58
|
-
deviceData.
|
|
59
|
-
deviceData.Device.FirmwareAppVersion = deviceData.ConnectedInterfaceIdentifier || '4.0.0';
|
|
59
|
+
deviceData.Scenes = scenes;
|
|
60
60
|
deviceData.Device.OperationMode = AirConditioner.OperationModeMapStringToEnum[deviceData.Device.OperationMode] ?? deviceData.Device.OperationMode;
|
|
61
61
|
deviceData.Device.ActualFanSpeed = AirConditioner.FanSpeedMapStringToEnum[deviceData.Device.ActualFanSpeed] ?? deviceData.Device.ActualFanSpeed;
|
|
62
62
|
deviceData.Device.SetFanSpeed = AirConditioner.FanSpeedMapStringToEnum[deviceData.Device.SetFanSpeed] ?? deviceData.Device.SetFanSpeed;
|
|
@@ -76,13 +76,12 @@ class MelCloudAta extends EventEmitter {
|
|
|
76
76
|
if (this.logDebug) this.emit('debug', `Device Data: ${JSON.stringify(safeConfig, null, 2)}`);
|
|
77
77
|
|
|
78
78
|
//device
|
|
79
|
-
const serialNumber = deviceData.SerialNumber;
|
|
80
|
-
const firmwareAppVersion = deviceData.Device?.FirmwareAppVersion;
|
|
79
|
+
const serialNumber = deviceData.SerialNumber || '4.0.0';
|
|
80
|
+
const firmwareAppVersion = deviceData.Device?.FirmwareAppVersion || '4.0.0';
|
|
81
81
|
|
|
82
82
|
//units
|
|
83
83
|
const units = Array.isArray(deviceData.Device?.Units) ? deviceData.Device?.Units : [];
|
|
84
84
|
const unitsCount = units.length;
|
|
85
|
-
const manufacturer = 'Mitsubishi';
|
|
86
85
|
|
|
87
86
|
const { indoor, outdoor } = units.reduce((acc, unit) => {
|
|
88
87
|
const target = unit.IsIndoor ? 'indoor' : 'outdoor';
|
|
@@ -118,7 +117,7 @@ class MelCloudAta extends EventEmitter {
|
|
|
118
117
|
this.deviceData = deviceData;
|
|
119
118
|
|
|
120
119
|
//emit info
|
|
121
|
-
this.emit('deviceInfo',
|
|
120
|
+
this.emit('deviceInfo', indoor.model, outdoor.model, serialNumber, firmwareAppVersion);
|
|
122
121
|
|
|
123
122
|
//emit state
|
|
124
123
|
this.emit('deviceState', deviceData);
|
|
@@ -129,7 +128,7 @@ class MelCloudAta extends EventEmitter {
|
|
|
129
128
|
};
|
|
130
129
|
};
|
|
131
130
|
|
|
132
|
-
async send(accountType, displayType, deviceData,
|
|
131
|
+
async send(accountType, displayType, deviceData, flag, flagData) {
|
|
133
132
|
try {
|
|
134
133
|
let method = null
|
|
135
134
|
let payload = {};
|
|
@@ -141,7 +140,7 @@ class MelCloudAta extends EventEmitter {
|
|
|
141
140
|
deviceData.Device.SetTemperature = (deviceData.Device.DefaultCoolingSetTemperature + deviceData.Device.DefaultHeatingSetTemperature) / 2;
|
|
142
141
|
}
|
|
143
142
|
|
|
144
|
-
deviceData.Device.EffectiveFlags =
|
|
143
|
+
deviceData.Device.EffectiveFlags = flag;
|
|
145
144
|
payload = {
|
|
146
145
|
DeviceID: deviceData.Device.DeviceID,
|
|
147
146
|
EffectiveFlags: deviceData.Device.EffectiveFlags,
|
|
@@ -184,7 +183,7 @@ class MelCloudAta extends EventEmitter {
|
|
|
184
183
|
}
|
|
185
184
|
}
|
|
186
185
|
|
|
187
|
-
switch (
|
|
186
|
+
switch (flag) {
|
|
188
187
|
case 'frostprotection':
|
|
189
188
|
payload = {
|
|
190
189
|
enabled: deviceData.FrostProtection.Enabled,
|
|
@@ -194,6 +193,7 @@ class MelCloudAta extends EventEmitter {
|
|
|
194
193
|
};
|
|
195
194
|
method = 'POST';
|
|
196
195
|
path = ApiUrlsHome.PostProtectionFrost;
|
|
196
|
+
deviceData.Headers.Referer = ApiUrlsHome.Referers.PostProtectionFrost.replace('deviceid', deviceData.DeviceID);
|
|
197
197
|
break;
|
|
198
198
|
case 'overheatprotection':
|
|
199
199
|
payload = {
|
|
@@ -204,6 +204,7 @@ class MelCloudAta extends EventEmitter {
|
|
|
204
204
|
};
|
|
205
205
|
method = 'POST';
|
|
206
206
|
path = ApiUrlsHome.PostProtectionOverheat;
|
|
207
|
+
deviceData.Headers.Referer = ApiUrlsHome.Referers.PostProtectionOverheat.replace('deviceid', deviceData.DeviceID);
|
|
207
208
|
break;
|
|
208
209
|
case 'holidaymode':
|
|
209
210
|
payload = {
|
|
@@ -214,27 +215,40 @@ class MelCloudAta extends EventEmitter {
|
|
|
214
215
|
};
|
|
215
216
|
method = 'POST';
|
|
216
217
|
path = ApiUrlsHome.PostHolidayMode;
|
|
218
|
+
deviceData.Headers.Referer = ApiUrlsHome.Referers.PostHolidayMode.replace('deviceid', deviceData.DeviceID);
|
|
217
219
|
break;
|
|
218
220
|
case 'schedule':
|
|
219
221
|
payload = { enabled: deviceData.ScheduleEnabled };
|
|
220
222
|
method = 'PUT';
|
|
221
|
-
path = ApiUrlsHome.
|
|
223
|
+
path = ApiUrlsHome.PutScheduleEnabled.replace('deviceid', deviceData.DeviceID);
|
|
224
|
+
deviceData.Headers.Referer = ApiUrlsHome.Referers.PutScheduleEnabled.replace('deviceid', deviceData.DeviceID);
|
|
225
|
+
break;
|
|
226
|
+
case 'scene':
|
|
227
|
+
method = 'PUT';
|
|
228
|
+
const state = flagData.Enabled ? 'Enable' : 'Disable';
|
|
229
|
+
path = ApiUrlsHome.PutScene[state].replace('sceneid', flagData.Id);
|
|
230
|
+
deviceData.Headers.Referer = ApiUrlsHome.Referers.GetPutScenes;
|
|
222
231
|
break;
|
|
223
232
|
default:
|
|
224
233
|
payload = {
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
234
|
+
power: deviceData.Device.Power,
|
|
235
|
+
setTemperature: deviceData.Device.SetTemperature,
|
|
236
|
+
setFanSpeed: String(deviceData.Device.SetFanSpeed),
|
|
237
|
+
operationMode: AirConditioner.OperationModeMapEnumToString[deviceData.Device.OperationMode],
|
|
238
|
+
vaneHorizontalDirection: AirConditioner.VaneHorizontalDirectionMapEnumToString[deviceData.Device.VaneHorizontalDirection],
|
|
239
|
+
vaneVerticalDirection: AirConditioner.VaneVerticalDirectionMapEnumToString[deviceData.Device.VaneVerticalDirection],
|
|
240
|
+
temperatureIncrementOverride: null,
|
|
241
|
+
inStandbyMode: null
|
|
231
242
|
};
|
|
232
243
|
method = 'PUT';
|
|
233
|
-
path = ApiUrlsHome.
|
|
244
|
+
path = ApiUrlsHome.PutAta.replace('deviceid', deviceData.DeviceID);
|
|
245
|
+
deviceData.Headers.Referer = ApiUrlsHome.Referers.PutDeviceSettings
|
|
234
246
|
break
|
|
235
247
|
}
|
|
236
248
|
|
|
237
|
-
|
|
249
|
+
deviceData.Headers['Content-Type'] = 'application/json; charset=utf-8';
|
|
250
|
+
deviceData.Headers.Origin = ApiUrlsHome.Origin;
|
|
251
|
+
if (this.logDebug) this.emit('debug', `Send Data: ${JSON.stringify(payload, null, 2)}, Headers: ${JSON.stringify(deviceData.Headers, null, 2)}`);
|
|
238
252
|
await axios(path, {
|
|
239
253
|
method: method,
|
|
240
254
|
baseURL: ApiUrlsHome.BaseURL,
|
|
@@ -259,7 +273,7 @@ class MelCloudAta extends EventEmitter {
|
|
|
259
273
|
|
|
260
274
|
setTimeout(() => {
|
|
261
275
|
this.lock = false
|
|
262
|
-
},
|
|
276
|
+
}, 2500);
|
|
263
277
|
}
|
|
264
278
|
};
|
|
265
279
|
export default MelCloudAta;
|
package/src/melcloudatw.js
CHANGED
|
@@ -52,12 +52,13 @@ class MelCloudAtw extends EventEmitter {
|
|
|
52
52
|
try {
|
|
53
53
|
//read device info from file
|
|
54
54
|
const devicesData = await this.functions.readData(this.devicesFile, true);
|
|
55
|
-
const
|
|
55
|
+
const scenes = devicesData.Scenes ?? [];
|
|
56
|
+
const deviceData = devicesData.Devices.find(device => device.DeviceID === this.deviceId);
|
|
56
57
|
|
|
57
58
|
if (this.accountType === 'melcloudhome') {
|
|
58
|
-
deviceData.
|
|
59
|
-
deviceData.Device.FirmwareAppVersion = deviceData.ConnectedInterfaceIdentifier || '4.0.0';
|
|
59
|
+
deviceData.Scenes = scenes;
|
|
60
60
|
}
|
|
61
|
+
|
|
61
62
|
const safeConfig = {
|
|
62
63
|
...deviceData,
|
|
63
64
|
Headers: 'removed',
|
|
@@ -65,15 +66,15 @@ class MelCloudAtw extends EventEmitter {
|
|
|
65
66
|
if (this.logDebug) this.emit('debug', `Device Data: ${JSON.stringify(safeConfig, null, 2)}`);
|
|
66
67
|
|
|
67
68
|
//device
|
|
68
|
-
|
|
69
|
+
//device
|
|
70
|
+
const serialNumber = deviceData.SerialNumber || '4.0.0';
|
|
71
|
+
const firmwareAppVersion = deviceData.Device?.FirmwareAppVersion || '4.0.0';
|
|
69
72
|
const hasHotWaterTank = deviceData.Device?.HasHotWaterTank;
|
|
70
|
-
const firmwareAppVersion = deviceData.Device?.FirmwareAppVersion;
|
|
71
73
|
const hasZone2 = deviceData.Device?.HasZone2;
|
|
72
74
|
|
|
73
75
|
//units
|
|
74
76
|
const units = Array.isArray(deviceData.Device?.Units) ? deviceData.Device?.Units : [];
|
|
75
77
|
const unitsCount = units.length;
|
|
76
|
-
const manufacturer = 'Mitsubishi';
|
|
77
78
|
|
|
78
79
|
const { indoor, outdoor } = units.reduce((acc, unit) => {
|
|
79
80
|
const target = unit.IsIndoor ? 'indoor' : 'outdoor';
|
|
@@ -105,11 +106,11 @@ class MelCloudAtw extends EventEmitter {
|
|
|
105
106
|
|
|
106
107
|
//check state changes
|
|
107
108
|
const deviceDataHasNotChanged = JSON.stringify(devicesData) === JSON.stringify(this.devicesData);
|
|
108
|
-
if (deviceDataHasNotChanged)
|
|
109
|
+
if (deviceDataHasNotChanged) return;
|
|
109
110
|
this.devicesData = devicesData;
|
|
110
111
|
|
|
111
112
|
//emit info
|
|
112
|
-
this.emit('deviceInfo',
|
|
113
|
+
this.emit('deviceInfo', indoor.model, outdoor.model, serialNumber, firmwareAppVersion, hasHotWaterTank, hasZone2);
|
|
113
114
|
|
|
114
115
|
//emit state
|
|
115
116
|
this.emit('deviceState', deviceData);
|
|
@@ -120,7 +121,7 @@ class MelCloudAtw extends EventEmitter {
|
|
|
120
121
|
};
|
|
121
122
|
};
|
|
122
123
|
|
|
123
|
-
async send(accountType, displayType, deviceData,
|
|
124
|
+
async send(accountType, displayType, deviceData, flag, flagData) {
|
|
124
125
|
try {
|
|
125
126
|
|
|
126
127
|
//prevent to set out of range temp
|
|
@@ -141,7 +142,7 @@ class MelCloudAtw extends EventEmitter {
|
|
|
141
142
|
let path = '';
|
|
142
143
|
switch (accountType) {
|
|
143
144
|
case "melcloud":
|
|
144
|
-
deviceData.Device.EffectiveFlags =
|
|
145
|
+
deviceData.Device.EffectiveFlags = flag;
|
|
145
146
|
payload = {
|
|
146
147
|
DeviceID: deviceData.Device.DeviceID,
|
|
147
148
|
EffectiveFlags: deviceData.Device.EffectiveFlags,
|
|
@@ -176,39 +177,55 @@ class MelCloudAtw extends EventEmitter {
|
|
|
176
177
|
this.updateData(deviceData);
|
|
177
178
|
return true;
|
|
178
179
|
case "melcloudhome":
|
|
179
|
-
switch (
|
|
180
|
+
switch (flag) {
|
|
180
181
|
case 'holidaymode':
|
|
181
|
-
payload = {
|
|
182
|
+
payload = {
|
|
183
|
+
enabled: deviceData.HolidayMode.Enabled,
|
|
184
|
+
startDate: deviceData.HolidayMode.StartDate,
|
|
185
|
+
endDate: deviceData.HolidayMode.EndDate,
|
|
186
|
+
units: { "ATW": [deviceData.DeviceID] }
|
|
187
|
+
};
|
|
182
188
|
method = 'POST';
|
|
183
189
|
path = ApiUrlsHome.PostHolidayMode;
|
|
190
|
+
deviceData.Headers.Referer = ApiUrlsHome.Referers.PostHolidayMode.replace('deviceid', deviceData.DeviceID);
|
|
184
191
|
break;
|
|
185
192
|
case 'schedule':
|
|
186
193
|
payload = { enabled: deviceData.ScheduleEnabled };
|
|
187
194
|
method = 'PUT';
|
|
188
|
-
path = ApiUrlsHome.
|
|
195
|
+
path = ApiUrlsHome.PutScheduleEnabled.replace('deviceid', deviceData.DeviceID);
|
|
196
|
+
deviceData.Headers.Referer = ApiUrlsHome.Referers.PutScheduleEnabled.replace('deviceid', deviceData.DeviceID);
|
|
197
|
+
break;
|
|
198
|
+
case 'scene':
|
|
199
|
+
method = 'PUT';
|
|
200
|
+
const state = flagData.Enabled ? 'Enable' : 'Disable';
|
|
201
|
+
path = ApiUrlsHome.PutScene[state].replace('sceneid', flagData.Id);
|
|
202
|
+
deviceData.Headers.Referer = ApiUrlsHome.Referers.GetPutScenes;
|
|
189
203
|
break;
|
|
190
204
|
default:
|
|
191
205
|
payload = {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
206
|
+
power: deviceData.Device.Power,
|
|
207
|
+
setTemperatureZone1: deviceData.Device.SetTemperatureZone1,
|
|
208
|
+
setTemperatureZone2: deviceData.Device.SetTemperatureZone2,
|
|
209
|
+
operationMode: HeatPump.OperationModeMapEnumToString[deviceData.Device.OperationMode],
|
|
210
|
+
operationModeZone1: HeatPump.OperationModeMapEnumToString[deviceData.Device.OperationModeZone1],
|
|
211
|
+
operationModeZone2: HeatPump.OperationModeMapEnumToString[deviceData.Device.OperationModeZone2],
|
|
212
|
+
opetHeatFlowTemperatureZone1: deviceData.Device.SetHeatFlowTemperatureZone1,
|
|
213
|
+
setHeatFlowTemperatureZone2: deviceData.Device.SetHeatFlowTemperatureZone2,
|
|
214
|
+
setCoolFlowTemperatureZone1: deviceData.Device.SetCoolFlowTemperatureZone1,
|
|
215
|
+
setCoolFlowTemperatureZone2: deviceData.Device.SetCoolFlowTemperatureZone2,
|
|
216
|
+
setTankWaterTemperature: deviceData.Device.SetTankWaterTemperature,
|
|
217
|
+
forcedHotWaterMode: deviceData.Device.ForcedHotWaterMode,
|
|
218
|
+
ecoHotWater: deviceData.Device.EcoHotWater,
|
|
205
219
|
};
|
|
206
220
|
method = 'PUT';
|
|
207
|
-
path = ApiUrlsHome.
|
|
221
|
+
path = ApiUrlsHome.PutAtw.replace('deviceid', deviceData.DeviceID);
|
|
222
|
+
deviceData.Headers.Referer = ApiUrlsHome.Referers.PutDeviceSettings
|
|
208
223
|
break
|
|
209
224
|
}
|
|
210
225
|
|
|
211
|
-
|
|
226
|
+
deviceData.Headers['Content-Type'] = 'application/json; charset=utf-8';
|
|
227
|
+
deviceData.Headers.Origin = ApiUrlsHome.Origin;
|
|
228
|
+
if (this.logDebug) this.emit('debug', `Send Data: ${JSON.stringify(payload, null, 2)}, Headers: ${JSON.stringify(deviceData.Headers, null, 2)}`);
|
|
212
229
|
await axios(path, {
|
|
213
230
|
method: method,
|
|
214
231
|
baseURL: ApiUrlsHome.BaseURL,
|
|
@@ -233,7 +250,7 @@ class MelCloudAtw extends EventEmitter {
|
|
|
233
250
|
|
|
234
251
|
setTimeout(() => {
|
|
235
252
|
this.lock = false
|
|
236
|
-
},
|
|
253
|
+
}, 2500);
|
|
237
254
|
}
|
|
238
255
|
};
|
|
239
256
|
export default MelCloudAtw;
|
package/src/melclouderv.js
CHANGED
|
@@ -52,31 +52,31 @@ class MelCloudErv extends EventEmitter {
|
|
|
52
52
|
try {
|
|
53
53
|
//read device info from file
|
|
54
54
|
const devicesData = await this.functions.readData(this.devicesFile, true);
|
|
55
|
-
const
|
|
55
|
+
const scenes = devicesData.Scenes ?? [];
|
|
56
|
+
const deviceData = devicesData.Devices.find(device => device.DeviceID === this.deviceId);
|
|
56
57
|
|
|
57
58
|
if (this.accountType === 'melcloudhome') {
|
|
58
|
-
deviceData.
|
|
59
|
-
deviceData.Device.FirmwareAppVersion = deviceData.ConnectedInterfaceIdentifier || '4.0.0';
|
|
59
|
+
deviceData.Scenes = scenes;
|
|
60
60
|
|
|
61
61
|
//read default temps
|
|
62
62
|
const temps = await this.functions.readData(this.defaultTempsFile, true);
|
|
63
63
|
deviceData.Device.DefaultHeatingSetTemperature = temps?.defaultHeatingSetTemperature ?? 20;
|
|
64
64
|
deviceData.Device.DefaultCoolingSetTemperature = temps?.defaultCoolingSetTemperature ?? 24;
|
|
65
65
|
}
|
|
66
|
+
|
|
66
67
|
const safeConfig = {
|
|
67
68
|
...deviceData,
|
|
68
69
|
Headers: 'removed',
|
|
69
70
|
};
|
|
70
71
|
if (this.logDebug) this.emit('debug', `Device Data: ${JSON.stringify(safeConfig, null, 2)}`);
|
|
71
72
|
|
|
72
|
-
//
|
|
73
|
-
const serialNumber = deviceData.SerialNumber;
|
|
74
|
-
const firmwareAppVersion = deviceData.Device?.FirmwareAppVersion;
|
|
73
|
+
//device
|
|
74
|
+
const serialNumber = deviceData.SerialNumber || '4.0.0';
|
|
75
|
+
const firmwareAppVersion = deviceData.Device?.FirmwareAppVersion || '4.0.0';
|
|
75
76
|
|
|
76
77
|
//units
|
|
77
78
|
const units = Array.isArray(deviceData.Device?.Units) ? deviceData.Device?.Units : [];
|
|
78
79
|
const unitsCount = units.length;
|
|
79
|
-
const manufacturer = 'Mitsubishi';
|
|
80
80
|
|
|
81
81
|
const { indoor, outdoor } = units.reduce((acc, unit) => {
|
|
82
82
|
const target = unit.IsIndoor ? 'indoor' : 'outdoor';
|
|
@@ -112,7 +112,7 @@ class MelCloudErv extends EventEmitter {
|
|
|
112
112
|
this.devicesData = devicesData;
|
|
113
113
|
|
|
114
114
|
//emit info
|
|
115
|
-
this.emit('deviceInfo',
|
|
115
|
+
this.emit('deviceInfo', indoor.model, outdoor.model, serialNumber, firmwareAppVersion);
|
|
116
116
|
|
|
117
117
|
//emit state
|
|
118
118
|
this.emit('deviceState', deviceData);
|
|
@@ -123,7 +123,7 @@ class MelCloudErv extends EventEmitter {
|
|
|
123
123
|
};
|
|
124
124
|
};
|
|
125
125
|
|
|
126
|
-
async send(accountType, displayType, deviceData,
|
|
126
|
+
async send(accountType, displayType, deviceData, flag, flagData) {
|
|
127
127
|
try {
|
|
128
128
|
let method = null
|
|
129
129
|
let payload = {};
|
|
@@ -151,7 +151,7 @@ class MelCloudErv extends EventEmitter {
|
|
|
151
151
|
};
|
|
152
152
|
|
|
153
153
|
//device state
|
|
154
|
-
deviceData.Device.EffectiveFlags =
|
|
154
|
+
deviceData.Device.EffectiveFlags = flag;
|
|
155
155
|
payload = {
|
|
156
156
|
DeviceID: deviceData.Device.DeviceID,
|
|
157
157
|
EffectiveFlags: deviceData.Device.EffectiveFlags,
|
|
@@ -192,31 +192,47 @@ class MelCloudErv extends EventEmitter {
|
|
|
192
192
|
}
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
-
switch (
|
|
195
|
+
switch (flag) {
|
|
196
196
|
case 'holidaymode':
|
|
197
|
-
payload = {
|
|
197
|
+
payload = {
|
|
198
|
+
enabled: deviceData.HolidayMode.Enabled,
|
|
199
|
+
startDate: deviceData.HolidayMode.StartDate,
|
|
200
|
+
endDate: deviceData.HolidayMode.EndDate,
|
|
201
|
+
units: { "ERV": [deviceData.DeviceID] }
|
|
202
|
+
};
|
|
198
203
|
method = 'POST';
|
|
199
204
|
path = ApiUrlsHome.PostHolidayMode;
|
|
205
|
+
deviceData.Headers.Referer = ApiUrlsHome.Referers.PostHolidayMode.replace('deviceid', deviceData.DeviceID);
|
|
200
206
|
break;
|
|
201
207
|
case 'schedule':
|
|
202
208
|
payload = { enabled: deviceData.ScheduleEnabled };
|
|
203
209
|
method = 'PUT';
|
|
204
|
-
path = ApiUrlsHome.
|
|
210
|
+
path = ApiUrlsHome.PutScheduleEnabled.replace('deviceid', deviceData.DeviceID);
|
|
211
|
+
deviceData.Headers.Referer = ApiUrlsHome.Referers.PutScheduleEnabled.replace('deviceid', deviceData.DeviceID);
|
|
212
|
+
break;
|
|
213
|
+
case 'scene':
|
|
214
|
+
method = 'PUT';
|
|
215
|
+
const state = flagData.Enabled ? 'Enable' : 'Disable';
|
|
216
|
+
path = ApiUrlsHome.PutScene[state].replace('sceneid', flagData.Id);
|
|
217
|
+
deviceData.Headers.Referer = ApiUrlsHome.Referers.GetPutScenes;
|
|
205
218
|
break;
|
|
206
219
|
default:
|
|
207
220
|
payload = {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
221
|
+
power: deviceData.Device.Power,
|
|
222
|
+
setTemperature: deviceData.Device.SetTemperature,
|
|
223
|
+
setFanSpeed: String(deviceData.Device.SetFanSpeed),
|
|
224
|
+
operationMode: Ventilation.OperationModeMapEnumToString[deviceData.Device.OperationMode],
|
|
225
|
+
ventilationMode: Ventilation.VentilationModeMapEnumToString[deviceData.Device.VentilationMode],
|
|
213
226
|
};
|
|
214
227
|
method = 'PUT';
|
|
215
|
-
path = ApiUrlsHome.
|
|
228
|
+
path = ApiUrlsHome.PutErv.replace('deviceid', deviceData.DeviceID);
|
|
229
|
+
deviceData.Headers.Referer = ApiUrlsHome.Referers.PutDeviceSettings
|
|
216
230
|
break
|
|
217
231
|
}
|
|
218
232
|
|
|
219
|
-
|
|
233
|
+
deviceData.Headers['Content-Type'] = 'application/json; charset=utf-8';
|
|
234
|
+
deviceData.Headers.Origin = ApiUrlsHome.Origin;
|
|
235
|
+
if (this.logDebug) this.emit('debug', `Send Data: ${JSON.stringify(payload, null, 2)}, Headers: ${JSON.stringify(deviceData.Headers, null, 2)}`);
|
|
220
236
|
await axios(path, {
|
|
221
237
|
method: method,
|
|
222
238
|
baseURL: ApiUrlsHome.BaseURL,
|
|
@@ -241,7 +257,7 @@ class MelCloudErv extends EventEmitter {
|
|
|
241
257
|
|
|
242
258
|
setTimeout(() => {
|
|
243
259
|
this.lock = false
|
|
244
|
-
},
|
|
260
|
+
}, 2500);
|
|
245
261
|
}
|
|
246
262
|
};
|
|
247
263
|
export default MelCloudErv;
|