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