homebridge-melcloud-control 2.5.0-beta.49 → 2.5.0-beta.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/config.schema.json +0 -192
- package/homebridge-ui/public/index.html +33 -66
- package/homebridge-ui/server.js +42 -10
- package/index.js +1 -1
- package/package.json +1 -1
- package/src/melcloud.js +59 -68
package/config.schema.json
CHANGED
|
@@ -205,165 +205,6 @@
|
|
|
205
205
|
"description": "Here select the language used in MELCloud account.",
|
|
206
206
|
"required": true
|
|
207
207
|
},
|
|
208
|
-
"ataDevices": {
|
|
209
|
-
"title": "Devices ATA",
|
|
210
|
-
"type": "array",
|
|
211
|
-
"items": {
|
|
212
|
-
"type": "object",
|
|
213
|
-
"properties": {
|
|
214
|
-
"name": {
|
|
215
|
-
"title": "Name",
|
|
216
|
-
"type": "string",
|
|
217
|
-
"required": false
|
|
218
|
-
},
|
|
219
|
-
"id": {
|
|
220
|
-
"title": "ID",
|
|
221
|
-
"type": "integer",
|
|
222
|
-
"required": false
|
|
223
|
-
},
|
|
224
|
-
"type": {
|
|
225
|
-
"title": "Type",
|
|
226
|
-
"type": "integer",
|
|
227
|
-
"required": false
|
|
228
|
-
},
|
|
229
|
-
"displayMode": {
|
|
230
|
-
"title": "Control",
|
|
231
|
-
"type": "integer",
|
|
232
|
-
"minimum": 0,
|
|
233
|
-
"maximum": 2,
|
|
234
|
-
"oneOf": [
|
|
235
|
-
{
|
|
236
|
-
"title": "None/Disabled",
|
|
237
|
-
"enum": [
|
|
238
|
-
0
|
|
239
|
-
]
|
|
240
|
-
},
|
|
241
|
-
{
|
|
242
|
-
"title": "Heater/Cooler",
|
|
243
|
-
"enum": [
|
|
244
|
-
0
|
|
245
|
-
]
|
|
246
|
-
},
|
|
247
|
-
{
|
|
248
|
-
"title": "Thermostat",
|
|
249
|
-
"enum": [
|
|
250
|
-
1
|
|
251
|
-
]
|
|
252
|
-
}
|
|
253
|
-
],
|
|
254
|
-
"description": "Select device control mode displayed in HomeKit app.",
|
|
255
|
-
"required": true
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
},
|
|
259
|
-
"required": false
|
|
260
|
-
},
|
|
261
|
-
"atwDevices": {
|
|
262
|
-
"title": "Devices ATW",
|
|
263
|
-
"type": "array",
|
|
264
|
-
"items": {
|
|
265
|
-
"type": "object",
|
|
266
|
-
"properties": {
|
|
267
|
-
"name": {
|
|
268
|
-
"title": "Name",
|
|
269
|
-
"type": "string",
|
|
270
|
-
"required": false
|
|
271
|
-
},
|
|
272
|
-
"id": {
|
|
273
|
-
"title": "Mode",
|
|
274
|
-
"type": "integer",
|
|
275
|
-
"required": false
|
|
276
|
-
},
|
|
277
|
-
"type": {
|
|
278
|
-
"title": "Type",
|
|
279
|
-
"type": "integer",
|
|
280
|
-
"required": false
|
|
281
|
-
},
|
|
282
|
-
"displayMode": {
|
|
283
|
-
"title": "Control",
|
|
284
|
-
"type": "integer",
|
|
285
|
-
"minimum": 0,
|
|
286
|
-
"maximum": 2,
|
|
287
|
-
"oneOf": [
|
|
288
|
-
{
|
|
289
|
-
"title": "None/Disabled",
|
|
290
|
-
"enum": [
|
|
291
|
-
0
|
|
292
|
-
]
|
|
293
|
-
},
|
|
294
|
-
{
|
|
295
|
-
"title": "Heater/Cooler",
|
|
296
|
-
"enum": [
|
|
297
|
-
0
|
|
298
|
-
]
|
|
299
|
-
},
|
|
300
|
-
{
|
|
301
|
-
"title": "Thermostat",
|
|
302
|
-
"enum": [
|
|
303
|
-
1
|
|
304
|
-
]
|
|
305
|
-
}
|
|
306
|
-
],
|
|
307
|
-
"description": "Select device control mode displayed in HomeKit app.",
|
|
308
|
-
"required": true
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
},
|
|
312
|
-
"required": false
|
|
313
|
-
},
|
|
314
|
-
"ervDevices": {
|
|
315
|
-
"title": "Devices ERV",
|
|
316
|
-
"type": "array",
|
|
317
|
-
"items": {
|
|
318
|
-
"type": "object",
|
|
319
|
-
"properties": {
|
|
320
|
-
"name": {
|
|
321
|
-
"title": "Name",
|
|
322
|
-
"type": "string",
|
|
323
|
-
"required": false
|
|
324
|
-
},
|
|
325
|
-
"id": {
|
|
326
|
-
"title": "Mode",
|
|
327
|
-
"type": "integer",
|
|
328
|
-
"required": false
|
|
329
|
-
},
|
|
330
|
-
"type": {
|
|
331
|
-
"title": "Type",
|
|
332
|
-
"type": "integer",
|
|
333
|
-
"required": false
|
|
334
|
-
},
|
|
335
|
-
"displayMode": {
|
|
336
|
-
"title": "Control",
|
|
337
|
-
"type": "integer",
|
|
338
|
-
"minimum": 0,
|
|
339
|
-
"maximum": 2,
|
|
340
|
-
"oneOf": [
|
|
341
|
-
{
|
|
342
|
-
"title": "None/Disabled",
|
|
343
|
-
"enum": [
|
|
344
|
-
0
|
|
345
|
-
]
|
|
346
|
-
},
|
|
347
|
-
{
|
|
348
|
-
"title": "Heater/Cooler",
|
|
349
|
-
"enum": [
|
|
350
|
-
0
|
|
351
|
-
]
|
|
352
|
-
},
|
|
353
|
-
{
|
|
354
|
-
"title": "Thermostat",
|
|
355
|
-
"enum": [
|
|
356
|
-
1
|
|
357
|
-
]
|
|
358
|
-
}
|
|
359
|
-
],
|
|
360
|
-
"description": "Select device control mode displayed in HomeKit app.",
|
|
361
|
-
"required": true
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
},
|
|
365
|
-
"required": false
|
|
366
|
-
},
|
|
367
208
|
"ataDisplayMode": {
|
|
368
209
|
"title": "Control",
|
|
369
210
|
"type": "integer",
|
|
@@ -1588,17 +1429,6 @@
|
|
|
1588
1429
|
"key": "accounts[]",
|
|
1589
1430
|
"title": "Air Conditioner",
|
|
1590
1431
|
"items": [
|
|
1591
|
-
{
|
|
1592
|
-
"key": "accounts[].ataDevices",
|
|
1593
|
-
"type": "tabarray",
|
|
1594
|
-
"title": "{{ value.name }}",
|
|
1595
|
-
"items": [
|
|
1596
|
-
"accounts[].ataDevices[].name",
|
|
1597
|
-
"accounts[].ataDevices[].id",
|
|
1598
|
-
"accounts[].ataDevices[].type",
|
|
1599
|
-
"accounts[].ataDevices[].displayMode"
|
|
1600
|
-
]
|
|
1601
|
-
},
|
|
1602
1432
|
"accounts[].ataDisplayMode",
|
|
1603
1433
|
"accounts[].ataPresets",
|
|
1604
1434
|
{
|
|
@@ -1668,17 +1498,6 @@
|
|
|
1668
1498
|
"key": "accounts[]",
|
|
1669
1499
|
"title": "Heat Pump",
|
|
1670
1500
|
"items": [
|
|
1671
|
-
{
|
|
1672
|
-
"key": "accounts[].atwDevices",
|
|
1673
|
-
"type": "tabarray",
|
|
1674
|
-
"title": "{{ value.name }}",
|
|
1675
|
-
"items": [
|
|
1676
|
-
"accounts[].atwDevices[].name",
|
|
1677
|
-
"accounts[].atwDevices[].id",
|
|
1678
|
-
"accounts[].atwDevices[].type",
|
|
1679
|
-
"accounts[].atwDevices[].displayMode"
|
|
1680
|
-
]
|
|
1681
|
-
},
|
|
1682
1501
|
"accounts[].atwDisplayMode",
|
|
1683
1502
|
"accounts[].atwPresets",
|
|
1684
1503
|
{
|
|
@@ -1743,17 +1562,6 @@
|
|
|
1743
1562
|
"key": "accounts[]",
|
|
1744
1563
|
"title": "Energy Recovery Ventilation",
|
|
1745
1564
|
"items": [
|
|
1746
|
-
{
|
|
1747
|
-
"key": "accounts[].ervDevices",
|
|
1748
|
-
"type": "tabarray",
|
|
1749
|
-
"title": "{{ value.name }}",
|
|
1750
|
-
"items": [
|
|
1751
|
-
"accounts[].ervDevices[].name",
|
|
1752
|
-
"accounts[].ervDevices[].id",
|
|
1753
|
-
"accounts[].ervDevices[].type",
|
|
1754
|
-
"accounts[].ervDevices[].displayMode"
|
|
1755
|
-
]
|
|
1756
|
-
},
|
|
1757
1565
|
"accounts[].ervDisplayMode",
|
|
1758
1566
|
"accounts[].ervPresets",
|
|
1759
1567
|
{
|
|
@@ -6,48 +6,21 @@
|
|
|
6
6
|
<div id="melCloudAccount" style="display: none;" class="card card-body">
|
|
7
7
|
<form id="configForm">
|
|
8
8
|
<div class="text-center">
|
|
9
|
-
<label id="accountName" style="font-size: 23px">Account</label><br>
|
|
9
|
+
<label id="accountName" style="font-size: 23px">Account Name</label><br>
|
|
10
10
|
<label id="info" style="text-align: center; font-size: 17px;">MELCloud</label><br><br>
|
|
11
11
|
</div>
|
|
12
12
|
<div class="form-group">
|
|
13
13
|
<label for="name">Name</label>
|
|
14
14
|
<input id="name" type="text" class="form-control"><br>
|
|
15
|
-
<label for="user">User
|
|
15
|
+
<label for="user">MELCloud User</label>
|
|
16
16
|
<input id="user" type="text" class="form-control"><br>
|
|
17
|
-
<label for="passwd">Password</label>
|
|
18
|
-
<input id="passwd" type="
|
|
17
|
+
<label for="passwd">MELCloud Password</label>
|
|
18
|
+
<input id="passwd" type="text" class="form-control"><br>
|
|
19
19
|
<label for="language">Language</label>
|
|
20
|
-
<
|
|
21
|
-
<option value="0">English</option>
|
|
22
|
-
<option value="1">Български</option>
|
|
23
|
-
<option value="2">Čeština</option>
|
|
24
|
-
<option value="3">Dansk</option>
|
|
25
|
-
<option value="4">Deutsch</option>
|
|
26
|
-
<option value="5">Eesti</option>
|
|
27
|
-
<option value="6">Español</option>
|
|
28
|
-
<option value="7">Français</option>
|
|
29
|
-
<option value="8">Հայերեն</option>
|
|
30
|
-
<option value="9">Latviešu</option>
|
|
31
|
-
<option value="10">Lietuvių</option>
|
|
32
|
-
<option value="11">Magyar</option>
|
|
33
|
-
<option value="12">Nederlands</option>
|
|
34
|
-
<option value="13">Norwegian</option>
|
|
35
|
-
<option value="14">Polski</option>
|
|
36
|
-
<option value="15">Português</option>
|
|
37
|
-
<option value="16">Русский</option>
|
|
38
|
-
<option value="17">Suomi</option>
|
|
39
|
-
<option value="18">Svenska</option>
|
|
40
|
-
<option value="19">Svenska</option>
|
|
41
|
-
<option value="20">Українська</option>
|
|
42
|
-
<option value="21">Türkçe</option>
|
|
43
|
-
<option value="22">Ελληνικά</option>
|
|
44
|
-
<option value="23">Hrvatski</option>
|
|
45
|
-
<option value="24">Română</option>
|
|
46
|
-
<option value="25">Slovenščina</option>
|
|
47
|
-
</select>
|
|
20
|
+
<input id="language" type="text" class="form-control"><br>
|
|
48
21
|
</div>
|
|
49
22
|
<div class="text-center">
|
|
50
|
-
<button id="logIn" type="button" class="btn btn-primary">
|
|
23
|
+
<button id="logIn" type="button" class="btn btn-primary">Log In</button>
|
|
51
24
|
<button id="configButton" type="button" class="btn btn-primary"><i class="fas fa-gear"></i></button>
|
|
52
25
|
</div>
|
|
53
26
|
</form>
|
|
@@ -83,8 +56,6 @@
|
|
|
83
56
|
const setRemoveAtribute = j === i ? document.getElementById(`button${j}`).setAttribute("class", "btn btn-secondary") : document.getElementById(`button${j}`).setAttribute("class", "btn btn-primary");
|
|
84
57
|
}
|
|
85
58
|
|
|
86
|
-
//const devicesCount = pluginConfig[0].accounts[i].devicesAta.length ?? 0;
|
|
87
|
-
//document.getElementById('info').innerHTML = `MELCloud configured ${devicesCount} ${devicesCount} ${devicesCount !== 1 ? 'devices' : 'device'}.`;
|
|
88
59
|
document.getElementById('accountName').innerHTML = pluginConfig[0].accounts[i].name || '';
|
|
89
60
|
document.getElementById('name').value = pluginConfig[0].accounts[i].name || '';
|
|
90
61
|
document.getElementById('user').value = pluginConfig[0].accounts[i].user || '';
|
|
@@ -92,8 +63,7 @@
|
|
|
92
63
|
document.getElementById('language').value = pluginConfig[0].accounts[i].language || '';
|
|
93
64
|
|
|
94
65
|
const accountConfigured = pluginConfig[0].accounts[i].name && pluginConfig[0].accounts[i].user && pluginConfig[0].accounts[i].passwd && pluginConfig[0].accounts[i].language;
|
|
95
|
-
const
|
|
96
|
-
document.getElementById('configButton').setAttribute('disabled');
|
|
66
|
+
const setButtonName = accountConfigured ? document.getElementById('logIn').removeAttribute('disabled') : document.getElementById('logIn').setAttribute('disabled');
|
|
97
67
|
await homebridge.updatePluginConfig(pluginConfig);
|
|
98
68
|
this.deviceIndex = i;
|
|
99
69
|
});
|
|
@@ -112,7 +82,7 @@
|
|
|
112
82
|
pluginConfig[0].accounts[this.deviceIndex].language = document.querySelector('#language').value;
|
|
113
83
|
|
|
114
84
|
const accountConfigured = pluginConfig[0].accounts[i].name && pluginConfig[0].accounts[i].user && pluginConfig[0].accounts[i].passwd && pluginConfig[0].accounts[i].language;
|
|
115
|
-
const
|
|
85
|
+
const setButtonMode = accountConfigured ? document.getElementById('logIn').removeAttribute('disabled') : document.getElementById('logIn').setAttribute('disabled');
|
|
116
86
|
|
|
117
87
|
await homebridge.updatePluginConfig(pluginConfig);
|
|
118
88
|
await homebridge.savePluginConfig(pluginConfig);
|
|
@@ -136,63 +106,60 @@
|
|
|
136
106
|
const user = pluginConfig[0].accounts[this.deviceIndex].user;
|
|
137
107
|
const passwd = pluginConfig[0].accounts[this.deviceIndex].passwd;
|
|
138
108
|
const language = pluginConfig[0].accounts[this.deviceIndex].language;
|
|
109
|
+
const enableDebugMode = pluginConfig[0].accounts[this.deviceIndex].enableDebugMode;
|
|
110
|
+
const refreshInterval = pluginConfig[0].accounts[this.deviceIndex].refreshInterval;
|
|
139
111
|
|
|
140
112
|
const payload = {
|
|
141
113
|
accountName: accountName,
|
|
142
114
|
user: user,
|
|
143
115
|
passwd: passwd,
|
|
144
|
-
language: language
|
|
116
|
+
language: language,
|
|
117
|
+
enableDebugMode: enableDebugMode,
|
|
118
|
+
refreshInterval: refreshInterval
|
|
145
119
|
};
|
|
146
120
|
const response = await homebridge.request('/connect', payload);
|
|
147
|
-
const info = response.info
|
|
121
|
+
const info = response.info;
|
|
148
122
|
const status = response.status;
|
|
149
123
|
const devices = response.data ?? [];
|
|
150
|
-
const newDevices = [];
|
|
151
124
|
|
|
152
125
|
switch (status) {
|
|
153
126
|
case 0:
|
|
127
|
+
|
|
154
128
|
//get device info fom devices
|
|
155
|
-
|
|
156
|
-
const deviceType = deviceInfo.Type;
|
|
129
|
+
for (const deviceInfo of devices) {
|
|
157
130
|
const deviceId = deviceInfo.DeviceID;
|
|
158
131
|
const deviceName = deviceInfo.DeviceName;
|
|
132
|
+
};
|
|
159
133
|
|
|
160
|
-
|
|
161
|
-
const ataDevices = accountKeys.includes('ataDevices') ? pluginConfig[0].accounts[this.deviceIndex].ataDevices : pluginConfig[0].accounts[this.deviceIndex].ataDevices = [];
|
|
162
|
-
const atwDevices = accountKeys.includes('atwDevices') ? pluginConfig[0].accounts[this.deviceIndex].atwDevices : pluginConfig[0].accounts[this.deviceIndex].atwDevices = [];
|
|
163
|
-
const ervDevices = accountKeys.includes('ervDevices') ? pluginConfig[0].accounts[this.deviceIndex].ervDevices : pluginConfig[0].accounts[this.deviceIndex].ervDevices = [];
|
|
164
|
-
|
|
165
|
-
const ataDeviceIdExist = ataDevices.some(device => device.id === deviceId)
|
|
166
|
-
const atwDeviceIdExist = atwDevices.some(device => device.id === deviceId)
|
|
167
|
-
const ervDeviceIdExist = ervDevices.some(device => device.id === deviceId)
|
|
168
|
-
const pushNewDevice = ataDeviceIdExist || atwDeviceIdExist || ervDeviceIdExist ? false : newDevices.push(deviceId);
|
|
169
|
-
|
|
170
|
-
const device = { name: deviceName, id: deviceId, type: deviceType, displayMode: 0 };
|
|
171
|
-
const pushTypeAta = deviceType === 0 && !ataDeviceIdExist ? ataDevices.push(device) : false;
|
|
172
|
-
const pushTypeAtw = deviceType === 1 && !atwDeviceIdExist ? atwDevices.push(device) : false;
|
|
173
|
-
const pushTypeErv = deviceType === 3 && !ervDeviceIdExist ? ervDevices.push(device) : false;
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
const devicesCount = newDevices.length;
|
|
177
|
-
document.getElementById('info').innerHTML = `Success, found ${devicesCount} ${devicesCount !== 1 ? 'new devices' : 'new device'}. Now You can start to configure it.`;
|
|
134
|
+
document.getElementById('info').innerHTML = `${info} Found: ${devices.length} devices. Now You can start to configure it.`;
|
|
178
135
|
document.getElementById('info').style.color = 'green';
|
|
179
|
-
|
|
180
136
|
await homebridge.updatePluginConfig(pluginConfig);
|
|
181
137
|
await homebridge.savePluginConfig(pluginConfig);
|
|
182
138
|
break;
|
|
183
139
|
case 1:
|
|
184
140
|
document.getElementById('info').innerHTML = info;
|
|
185
|
-
document.getElementById('info').style.color = '
|
|
141
|
+
document.getElementById('info').style.color = 'green';
|
|
186
142
|
break;
|
|
187
|
-
|
|
188
|
-
document.getElementById('info').innerHTML =
|
|
143
|
+
case 2:
|
|
144
|
+
document.getElementById('info').innerHTML = info;
|
|
145
|
+
document.getElementById('info').style.color = 'white';
|
|
146
|
+
break;
|
|
147
|
+
case 3:
|
|
148
|
+
document.getElementById('info').innerHTML = info;
|
|
149
|
+
document.getElementById('info').style.color = 'gray';
|
|
150
|
+
break;
|
|
151
|
+
case 4:
|
|
152
|
+
document.getElementById('info').innerHTML = info;
|
|
189
153
|
document.getElementById('info').style.color = 'yellow';
|
|
190
154
|
break;
|
|
155
|
+
case 5:
|
|
156
|
+
document.getElementById('info').innerHTML = info;
|
|
157
|
+
document.getElementById('info').style.color = 'red';
|
|
158
|
+
break;
|
|
191
159
|
};
|
|
192
160
|
|
|
193
161
|
homebridge.hideSpinner();
|
|
194
162
|
} catch (e) {
|
|
195
|
-
document.getElementById('info').innerHTML = 'Please try again.';
|
|
196
163
|
homebridge.toast.error(`Data error: ${e.message}`);
|
|
197
164
|
} finally {
|
|
198
165
|
homebridge.hideSpinner();
|
package/homebridge-ui/server.js
CHANGED
|
@@ -19,24 +19,56 @@ class PluginUiServer extends HomebridgePluginUiServer {
|
|
|
19
19
|
const user = payload.user;
|
|
20
20
|
const passwd = payload.passwd;
|
|
21
21
|
const language = payload.language;
|
|
22
|
+
const enableDebugMode = payload.enableDebugMode;
|
|
23
|
+
const refreshInterval = payload.refreshInterval;
|
|
22
24
|
const accountInfoFile = `${this.homebridgeStoragePath}/melcloud/${accountName}_Account`;
|
|
23
25
|
const deviceInfoFile = `${this.homebridgeStoragePath}/melcloud/${accountName}_Device_`;
|
|
24
26
|
const buildingsFile = `${this.homebridgeStoragePath}/melcloud/${accountName}_Buildings`;
|
|
27
|
+
let data = {};
|
|
25
28
|
|
|
26
29
|
try {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
30
|
+
const melCloud = new MelCloud(user, passwd, language, accountInfoFile, deviceInfoFile, buildingsFile, enableDebugMode, refreshInterval, false);
|
|
31
|
+
melCloud.on('devicesList', (devices) => {
|
|
32
|
+
return data = {
|
|
33
|
+
info: 'Check devices list complete.',
|
|
34
|
+
status: 0,
|
|
35
|
+
data: devices
|
|
36
|
+
};
|
|
37
|
+
})
|
|
38
|
+
.on('success', (message) => {
|
|
39
|
+
return data = {
|
|
40
|
+
info: message,
|
|
41
|
+
status: 1
|
|
42
|
+
};
|
|
43
|
+
})
|
|
44
|
+
.on('message', (message) => {
|
|
45
|
+
return data = {
|
|
46
|
+
info: message,
|
|
47
|
+
status: 2
|
|
48
|
+
};
|
|
49
|
+
})
|
|
50
|
+
.on('debug', (debug) => {
|
|
51
|
+
return data = {
|
|
52
|
+
info: debug,
|
|
53
|
+
status: 3
|
|
54
|
+
};
|
|
55
|
+
})
|
|
56
|
+
.on('warn', (warn) => {
|
|
57
|
+
return data = {
|
|
58
|
+
info: warn,
|
|
59
|
+
status: 4
|
|
60
|
+
};
|
|
61
|
+
})
|
|
62
|
+
.on('error', async (error) => {
|
|
63
|
+
return data = {
|
|
64
|
+
info: error,
|
|
65
|
+
status: 5
|
|
66
|
+
};
|
|
67
|
+
});
|
|
36
68
|
} catch (error) {
|
|
37
69
|
return data = {
|
|
38
70
|
info: error,
|
|
39
|
-
status:
|
|
71
|
+
status: 5
|
|
40
72
|
};
|
|
41
73
|
};
|
|
42
74
|
};
|
package/index.js
CHANGED
|
@@ -78,7 +78,7 @@ class MelCloudPlatform {
|
|
|
78
78
|
const deviceRefreshInterval = account.deviceRefreshInterval * 1000 || 5000;
|
|
79
79
|
|
|
80
80
|
//melcloud account
|
|
81
|
-
const melCloud = new MelCloud(user, passwd, language, accountInfoFile, buildingsFile, deviceInfoFile, enableDebugMode, refreshInterval,
|
|
81
|
+
const melCloud = new MelCloud(user, passwd, language, accountInfoFile, buildingsFile, deviceInfoFile, enableDebugMode, refreshInterval, true);
|
|
82
82
|
melCloud.on('checkDevicesListComplete', (accountInfo, contextKey, deviceInfo) => {
|
|
83
83
|
const deviceId = deviceInfo.DeviceID.toString();
|
|
84
84
|
const deviceType = deviceInfo.Type;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"displayName": "MELCloud Control",
|
|
3
3
|
"name": "homebridge-melcloud-control",
|
|
4
|
-
"version": "2.5.0-beta.
|
|
4
|
+
"version": "2.5.0-beta.5",
|
|
5
5
|
"description": "Homebridge plugin to control Mitsubishi Air Conditioner, Heat Pump and Energy Recovery Ventilation.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "grzegorz914",
|
package/src/melcloud.js
CHANGED
|
@@ -8,15 +8,14 @@ const ImpulseGenerator = require('./impulsegenerator.js');
|
|
|
8
8
|
const CONSTANTS = require('./constants.json');
|
|
9
9
|
|
|
10
10
|
class MelCloud extends EventEmitter {
|
|
11
|
-
constructor(user, passwd, language, accountInfoFile, deviceInfoFile, buildingsFile, enableDebugMode, refreshInterval,
|
|
11
|
+
constructor(user, passwd, language, accountInfoFile, deviceInfoFile, buildingsFile, enableDebugMode, refreshInterval, startImpulseGenerator) {
|
|
12
12
|
super();
|
|
13
|
+
this.enableDebugMode = enableDebugMode;
|
|
13
14
|
this.accountInfoFile = accountInfoFile;
|
|
14
15
|
this.buildingsFile = buildingsFile;
|
|
15
16
|
this.deviceInfoFile = deviceInfoFile;
|
|
16
|
-
this.enableDebugMode = enableDebugMode;
|
|
17
17
|
this.refreshInterval = refreshInterval;
|
|
18
|
-
this.
|
|
19
|
-
this.contextKey = '';
|
|
18
|
+
this.startImpulseGenerator = startImpulseGenerator;
|
|
20
19
|
this.devicesId = [];
|
|
21
20
|
|
|
22
21
|
this.options = {
|
|
@@ -31,18 +30,16 @@ class MelCloud extends EventEmitter {
|
|
|
31
30
|
}
|
|
32
31
|
};
|
|
33
32
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
this.connect();
|
|
45
|
-
};
|
|
33
|
+
this.impulseGenerator = new ImpulseGenerator();
|
|
34
|
+
this.impulseGenerator.on('checkDevicesList', async () => {
|
|
35
|
+
try {
|
|
36
|
+
await this.chackDevicesList();
|
|
37
|
+
} catch (error) {
|
|
38
|
+
this.emit('error', `Check devices list: ${error}.`);
|
|
39
|
+
};
|
|
40
|
+
}).on('state', (state) => { });
|
|
41
|
+
|
|
42
|
+
this.connect();
|
|
46
43
|
};
|
|
47
44
|
|
|
48
45
|
async connect() {
|
|
@@ -82,26 +79,57 @@ class MelCloud extends EventEmitter {
|
|
|
82
79
|
this.emit('warn', `Context key: ${contextKey}, missing.`)
|
|
83
80
|
return;
|
|
84
81
|
};
|
|
82
|
+
|
|
83
|
+
//create axios instance get
|
|
84
|
+
this.axiosInstanceGet = axios.create({
|
|
85
|
+
method: 'GET',
|
|
86
|
+
baseURL: CONSTANTS.ApiUrls.BaseURL,
|
|
87
|
+
timeout: 5000,
|
|
88
|
+
headers: {
|
|
89
|
+
'X-MitsContextKey': contextKey
|
|
90
|
+
},
|
|
91
|
+
maxContentLength: 100000000,
|
|
92
|
+
maxBodyLength: 1000000000,
|
|
93
|
+
withCredentials: true,
|
|
94
|
+
httpsAgent: new https.Agent({
|
|
95
|
+
keepAlive: false,
|
|
96
|
+
rejectUnauthorized: false
|
|
97
|
+
})
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
//create axios instance post
|
|
101
|
+
this.axiosInstancePost = axios.create({
|
|
102
|
+
method: 'POST',
|
|
103
|
+
baseURL: CONSTANTS.ApiUrls.BaseURL,
|
|
104
|
+
timeout: 5000,
|
|
105
|
+
headers: {
|
|
106
|
+
'X-MitsContextKey': contextKey,
|
|
107
|
+
'content-type': 'application/json'
|
|
108
|
+
},
|
|
109
|
+
maxContentLength: 100000000,
|
|
110
|
+
maxBodyLength: 1000000000,
|
|
111
|
+
withCredentials: true,
|
|
112
|
+
httpsAgent: new https.Agent({
|
|
113
|
+
keepAlive: false,
|
|
114
|
+
rejectUnauthorized: false
|
|
115
|
+
})
|
|
116
|
+
});
|
|
117
|
+
|
|
85
118
|
this.accountInfo = accountInfo;
|
|
86
119
|
this.contextKey = contextKey;
|
|
87
120
|
|
|
88
|
-
//return if connect for config
|
|
89
|
-
if (this.connectForConfig) {
|
|
90
|
-
return contextKey;
|
|
91
|
-
};
|
|
92
|
-
|
|
93
121
|
//save melcloud info to the file
|
|
94
122
|
await this.saveData(this.accountInfoFile, accountInfo);
|
|
95
123
|
|
|
96
124
|
//check devices list
|
|
97
|
-
await this.chackDevicesList(
|
|
125
|
+
await this.chackDevicesList();
|
|
98
126
|
|
|
99
127
|
//emit connect success
|
|
100
128
|
this.emit('success', `Connect to MELCloud Success.`)
|
|
101
129
|
|
|
102
130
|
//start impulse generator
|
|
103
131
|
const timers = [{ name: 'checkDevicesList', sampling: this.refreshInterval }];
|
|
104
|
-
this.impulseGenerator.start(timers);
|
|
132
|
+
const startImpulseGenerator = this.startImpulseGenerator ? this.impulseGenerator.start(timers) : false;
|
|
105
133
|
|
|
106
134
|
return true;
|
|
107
135
|
} catch (error) {
|
|
@@ -109,27 +137,10 @@ class MelCloud extends EventEmitter {
|
|
|
109
137
|
};
|
|
110
138
|
}
|
|
111
139
|
|
|
112
|
-
async chackDevicesList(
|
|
140
|
+
async chackDevicesList() {
|
|
113
141
|
try {
|
|
114
|
-
//create axios instance get
|
|
115
|
-
const axiosInstanceGet = axios.create({
|
|
116
|
-
method: 'GET',
|
|
117
|
-
baseURL: CONSTANTS.ApiUrls.BaseURL,
|
|
118
|
-
timeout: 5000,
|
|
119
|
-
headers: {
|
|
120
|
-
'X-MitsContextKey': contextKey
|
|
121
|
-
},
|
|
122
|
-
maxContentLength: 100000000,
|
|
123
|
-
maxBodyLength: 1000000000,
|
|
124
|
-
withCredentials: true,
|
|
125
|
-
httpsAgent: new https.Agent({
|
|
126
|
-
keepAlive: false,
|
|
127
|
-
rejectUnauthorized: false
|
|
128
|
-
})
|
|
129
|
-
});
|
|
130
|
-
|
|
131
142
|
const debug = this.enableDebugMode ? this.emit('debug', `Scanning for devices.`) : false;
|
|
132
|
-
const listDevicesData = await axiosInstanceGet(CONSTANTS.ApiUrls.ListDevices);
|
|
143
|
+
const listDevicesData = await this.axiosInstanceGet(CONSTANTS.ApiUrls.ListDevices);
|
|
133
144
|
const buildingsList = listDevicesData.data;
|
|
134
145
|
const debug1 = this.enableDebugMode ? this.emit('debug', `Buildings: ${JSON.stringify(buildingsList, null, 2)}`) : false;
|
|
135
146
|
|
|
@@ -165,11 +176,6 @@ class MelCloud extends EventEmitter {
|
|
|
165
176
|
}
|
|
166
177
|
const debug3 = this.enableDebugMode ? this.emit('debug', `Found: ${devicesCount} devices.`) : false;
|
|
167
178
|
|
|
168
|
-
//return devices list for config
|
|
169
|
-
if (this.connectForConfig) {
|
|
170
|
-
return devices;
|
|
171
|
-
};
|
|
172
|
-
|
|
173
179
|
//get device info fom devices
|
|
174
180
|
for (const deviceInfo of devices) {
|
|
175
181
|
const deviceId = deviceInfo.DeviceID
|
|
@@ -183,13 +189,16 @@ class MelCloud extends EventEmitter {
|
|
|
183
189
|
//prepare device if not in devices array
|
|
184
190
|
if (!this.devicesId.includes(deviceId)) {
|
|
185
191
|
this.devicesId.push(deviceId);
|
|
186
|
-
this.emit('checkDevicesListComplete', this.accountInfo, contextKey, deviceInfo);
|
|
192
|
+
this.emit('checkDevicesListComplete', this.accountInfo, this.contextKey, deviceInfo);
|
|
187
193
|
}
|
|
188
194
|
};
|
|
189
195
|
|
|
196
|
+
//emit devices list
|
|
197
|
+
this.emit('devicesList', devices);
|
|
198
|
+
|
|
190
199
|
return true;
|
|
191
200
|
} catch (error) {
|
|
192
|
-
|
|
201
|
+
this.impulseGenerator.stop();
|
|
193
202
|
throw new Error(`Scanning for devices error: ${error.message ?? error}.`);
|
|
194
203
|
};
|
|
195
204
|
}
|
|
@@ -206,29 +215,11 @@ class MelCloud extends EventEmitter {
|
|
|
206
215
|
|
|
207
216
|
async send(accountInfo) {
|
|
208
217
|
try {
|
|
209
|
-
//create axios instance post
|
|
210
|
-
const axiosInstancePost = axios.create({
|
|
211
|
-
method: 'POST',
|
|
212
|
-
baseURL: CONSTANTS.ApiUrls.BaseURL,
|
|
213
|
-
timeout: 5000,
|
|
214
|
-
headers: {
|
|
215
|
-
'X-MitsContextKey': this.contextKey,
|
|
216
|
-
'content-type': 'application/json'
|
|
217
|
-
},
|
|
218
|
-
maxContentLength: 100000000,
|
|
219
|
-
maxBodyLength: 1000000000,
|
|
220
|
-
withCredentials: true,
|
|
221
|
-
httpsAgent: new https.Agent({
|
|
222
|
-
keepAlive: false,
|
|
223
|
-
rejectUnauthorized: false
|
|
224
|
-
})
|
|
225
|
-
});
|
|
226
|
-
|
|
227
218
|
const options = {
|
|
228
219
|
data: accountInfo
|
|
229
220
|
};
|
|
230
221
|
|
|
231
|
-
await axiosInstancePost(CONSTANTS.ApiUrls.UpdateApplicationOptions, options);
|
|
222
|
+
await this.axiosInstancePost(CONSTANTS.ApiUrls.UpdateApplicationOptions, options);
|
|
232
223
|
await this.saveData(this.accountInfoFile, accountInfo);
|
|
233
224
|
return true;
|
|
234
225
|
} catch (error) {
|