homebridge-melcloud-control 4.2.3-beta.8 → 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 +24 -31
- package/src/melcloudata.js +40 -21
- package/src/melcloudatw.js +46 -29
- package/src/melclouderv.js +37 -21
- 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;
|
|
104
|
+
device.Headers = this.headers;
|
|
114
105
|
});
|
|
115
106
|
|
|
116
107
|
if (this.logDebug) this.emit('debug', `Found ${allDevices.length} devices in building: ${building.Name || 'Unnamed'}`);
|
|
117
|
-
|
|
108
|
+
devices.push(...allDevices);
|
|
118
109
|
}
|
|
119
110
|
|
|
120
|
-
const devicesCount =
|
|
111
|
+
const devicesCount = devices.length;
|
|
121
112
|
if (devicesCount === 0) {
|
|
122
113
|
devicesList.Info = 'No devices found'
|
|
123
114
|
return devicesList;
|
|
124
115
|
}
|
|
125
116
|
|
|
126
|
-
await this.functions.saveData(this.devicesFile, devicesList.Devices);
|
|
127
|
-
if (this.logDebug) this.emit('debug', `${devicesCount} devices saved`);
|
|
128
|
-
|
|
129
117
|
devicesList.State = true;
|
|
130
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
|
+
|
|
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
|
@@ -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';
|
|
@@ -112,8 +111,13 @@ class MelCloudAta extends EventEmitter {
|
|
|
112
111
|
this.emit('mqtt', 'State', deviceData.Device);
|
|
113
112
|
}
|
|
114
113
|
|
|
114
|
+
//check state changes
|
|
115
|
+
const deviceDataHasNotChanged = JSON.stringify(deviceData) === JSON.stringify(this.deviceData);
|
|
116
|
+
if (deviceDataHasNotChanged) return;
|
|
117
|
+
this.deviceData = deviceData;
|
|
118
|
+
|
|
115
119
|
//emit info
|
|
116
|
-
this.emit('deviceInfo',
|
|
120
|
+
this.emit('deviceInfo', indoor.model, outdoor.model, serialNumber, firmwareAppVersion);
|
|
117
121
|
|
|
118
122
|
//emit state
|
|
119
123
|
this.emit('deviceState', deviceData);
|
|
@@ -124,7 +128,7 @@ class MelCloudAta extends EventEmitter {
|
|
|
124
128
|
};
|
|
125
129
|
};
|
|
126
130
|
|
|
127
|
-
async send(accountType, displayType, deviceData,
|
|
131
|
+
async send(accountType, displayType, deviceData, flag, flagData) {
|
|
128
132
|
try {
|
|
129
133
|
let method = null
|
|
130
134
|
let payload = {};
|
|
@@ -136,7 +140,7 @@ class MelCloudAta extends EventEmitter {
|
|
|
136
140
|
deviceData.Device.SetTemperature = (deviceData.Device.DefaultCoolingSetTemperature + deviceData.Device.DefaultHeatingSetTemperature) / 2;
|
|
137
141
|
}
|
|
138
142
|
|
|
139
|
-
deviceData.Device.EffectiveFlags =
|
|
143
|
+
deviceData.Device.EffectiveFlags = flag;
|
|
140
144
|
payload = {
|
|
141
145
|
DeviceID: deviceData.Device.DeviceID,
|
|
142
146
|
EffectiveFlags: deviceData.Device.EffectiveFlags,
|
|
@@ -179,7 +183,7 @@ class MelCloudAta extends EventEmitter {
|
|
|
179
183
|
}
|
|
180
184
|
}
|
|
181
185
|
|
|
182
|
-
switch (
|
|
186
|
+
switch (flag) {
|
|
183
187
|
case 'frostprotection':
|
|
184
188
|
payload = {
|
|
185
189
|
enabled: deviceData.FrostProtection.Enabled,
|
|
@@ -189,6 +193,7 @@ class MelCloudAta extends EventEmitter {
|
|
|
189
193
|
};
|
|
190
194
|
method = 'POST';
|
|
191
195
|
path = ApiUrlsHome.PostProtectionFrost;
|
|
196
|
+
deviceData.Headers.Referer = ApiUrlsHome.Referers.PostProtectionFrost.replace('deviceid', deviceData.DeviceID);
|
|
192
197
|
break;
|
|
193
198
|
case 'overheatprotection':
|
|
194
199
|
payload = {
|
|
@@ -199,6 +204,7 @@ class MelCloudAta extends EventEmitter {
|
|
|
199
204
|
};
|
|
200
205
|
method = 'POST';
|
|
201
206
|
path = ApiUrlsHome.PostProtectionOverheat;
|
|
207
|
+
deviceData.Headers.Referer = ApiUrlsHome.Referers.PostProtectionOverheat.replace('deviceid', deviceData.DeviceID);
|
|
202
208
|
break;
|
|
203
209
|
case 'holidaymode':
|
|
204
210
|
payload = {
|
|
@@ -209,27 +215,40 @@ class MelCloudAta extends EventEmitter {
|
|
|
209
215
|
};
|
|
210
216
|
method = 'POST';
|
|
211
217
|
path = ApiUrlsHome.PostHolidayMode;
|
|
218
|
+
deviceData.Headers.Referer = ApiUrlsHome.Referers.PostHolidayMode.replace('deviceid', deviceData.DeviceID);
|
|
212
219
|
break;
|
|
213
220
|
case 'schedule':
|
|
214
221
|
payload = { enabled: deviceData.ScheduleEnabled };
|
|
215
222
|
method = 'PUT';
|
|
216
|
-
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;
|
|
217
231
|
break;
|
|
218
232
|
default:
|
|
219
233
|
payload = {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
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
|
|
226
242
|
};
|
|
227
243
|
method = 'PUT';
|
|
228
|
-
path = ApiUrlsHome.
|
|
244
|
+
path = ApiUrlsHome.PutAta.replace('deviceid', deviceData.DeviceID);
|
|
245
|
+
deviceData.Headers.Referer = ApiUrlsHome.Referers.PutDeviceSettings
|
|
229
246
|
break
|
|
230
247
|
}
|
|
231
248
|
|
|
232
|
-
|
|
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)}`);
|
|
233
252
|
await axios(path, {
|
|
234
253
|
method: method,
|
|
235
254
|
baseURL: ApiUrlsHome.BaseURL,
|
|
@@ -254,7 +273,7 @@ class MelCloudAta extends EventEmitter {
|
|
|
254
273
|
|
|
255
274
|
setTimeout(() => {
|
|
256
275
|
this.lock = false
|
|
257
|
-
},
|
|
276
|
+
}, 2500);
|
|
258
277
|
}
|
|
259
278
|
};
|
|
260
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;
|