homebridge-melcloud-control 2.5.0-beta.29 → 2.5.0-beta.3

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.
@@ -205,62 +205,6 @@
205
205
  "description": "Here select the language used in MELCloud account.",
206
206
  "required": true
207
207
  },
208
- "devices": {
209
- "title": "Devices",
210
- "type": "array",
211
- "items": {
212
- "type": "object",
213
- "properties": {
214
- "name": {
215
- "title": "Name",
216
- "type": "string",
217
- "required": true
218
- },
219
- "id": {
220
- "title": "Mode",
221
- "type": "integer",
222
- "description": "Device ID.",
223
- "required": true
224
- },
225
- "type": {
226
- "title": "Type",
227
- "type": "integer",
228
- "description": "Device Type.",
229
- "required": true
230
- },
231
- "displayMode": {
232
- "title": "Control",
233
- "type": "integer",
234
- "minimum": 0,
235
- "maximum": 2,
236
- "default": 0,
237
- "oneOf": [
238
- {
239
- "title": "None/Disabled",
240
- "enum": [
241
- 0
242
- ]
243
- },
244
- {
245
- "title": "Heater/Cooler",
246
- "enum": [
247
- 0
248
- ]
249
- },
250
- {
251
- "title": "Thermostat",
252
- "enum": [
253
- 1
254
- ]
255
- }
256
- ],
257
- "description": "Select device control mode displayed in HomeKit app.",
258
- "required": true
259
- }
260
- }
261
- },
262
- "required": false
263
- },
264
208
  "ataDisplayMode": {
265
209
  "title": "Control",
266
210
  "type": "integer",
@@ -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 Name</label>
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="password" class="form-control"><br>
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
- <select id="language" name="language" class="form-control"><br>
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">Connect to MELCloud</button>
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>
@@ -90,8 +63,7 @@
90
63
  document.getElementById('language').value = pluginConfig[0].accounts[i].language || '';
91
64
 
92
65
  const accountConfigured = pluginConfig[0].accounts[i].name && pluginConfig[0].accounts[i].user && pluginConfig[0].accounts[i].passwd && pluginConfig[0].accounts[i].language;
93
- const setButtonState = accountConfigured ? document.getElementById('logIn').removeAttribute('disabled') : document.getElementById('logIn').setAttribute('disabled');
94
- document.getElementById('configButton').setAttribute('disabled');
66
+ const setButtonName = accountConfigured ? document.getElementById('logIn').removeAttribute('disabled') : document.getElementById('logIn').setAttribute('disabled');
95
67
  await homebridge.updatePluginConfig(pluginConfig);
96
68
  this.deviceIndex = i;
97
69
  });
@@ -110,7 +82,7 @@
110
82
  pluginConfig[0].accounts[this.deviceIndex].language = document.querySelector('#language').value;
111
83
 
112
84
  const accountConfigured = pluginConfig[0].accounts[i].name && pluginConfig[0].accounts[i].user && pluginConfig[0].accounts[i].passwd && pluginConfig[0].accounts[i].language;
113
- const setButtonState = accountConfigured ? document.getElementById('logIn').removeAttribute('disabled') : document.getElementById('logIn').setAttribute('disabled');
85
+ const setButtonMode = accountConfigured ? document.getElementById('logIn').removeAttribute('disabled') : document.getElementById('logIn').setAttribute('disabled');
114
86
 
115
87
  await homebridge.updatePluginConfig(pluginConfig);
116
88
  await homebridge.savePluginConfig(pluginConfig);
@@ -128,57 +100,73 @@
128
100
 
129
101
  try {
130
102
  await homebridge.updatePluginConfig(pluginConfig)
131
- document.getElementById('info').innerHTML = 'Connecting...';
103
+ document.getElementById('info').innerHTML = '';
132
104
 
133
105
  const accountName = pluginConfig[0].accounts[this.deviceIndex].name;
134
106
  const user = pluginConfig[0].accounts[this.deviceIndex].user;
135
107
  const passwd = pluginConfig[0].accounts[this.deviceIndex].passwd;
136
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;
137
111
 
138
112
  const payload = {
139
113
  accountName: accountName,
140
114
  user: user,
141
115
  passwd: passwd,
142
- language: language
116
+ language: language,
117
+ enableDebugMode: enableDebugMode,
118
+ refreshInterval: refreshInterval
143
119
  };
144
120
  const response = await homebridge.request('/connect', payload);
145
- const info = response.info ?? '';
121
+ const info = response.info;
146
122
  const status = response.status;
147
- const devices = response.data ?? [];
123
+ const data = response.data;
124
+ const error = response.error;
148
125
 
149
126
  switch (status) {
150
127
  case 0:
151
- const devicesCount = devices.length;
152
- document.getElementById('info').innerHTML = `Success, found ${devicesCount} ${devicesCount !== 1 ? 'devices' : 'device'}. Now You can start to configure it.`;
153
- document.getElementById('info').style.color = 'green';
128
+ const devicesId = [];
154
129
 
155
130
  //get device info fom devices
156
- devices.forEach((deviceInfo, index) => {
157
- const deviceType = deviceInfo.Type;
131
+ for (const deviceInfo of devices) {
158
132
  const deviceId = deviceInfo.DeviceID;
159
133
  const deviceName = deviceInfo.DeviceName;
160
134
 
161
- const displayMode = pluginConfig[0].accounts[this.deviceIndex].devices[index].displayMode ?? 0;
162
- const device = { name: deviceName, id: deviceId, type: deviceType, displayMode: displayMode };
163
- const language = pluginConfig[0].accounts[this.deviceIndex].devices.push(device);
164
- });
135
+ //prepare device if not in devices array
136
+ if (!devicesId.includes(deviceId)) {
137
+ devicesId.push(deviceId);
138
+ }
139
+ };
165
140
 
141
+ document.getElementById('info').innerHTML = `${info} Found: ${devicesId.length} devices. Now You can start configure it.`;
142
+ document.getElementById('info').style.color = 'green';
166
143
  await homebridge.updatePluginConfig(pluginConfig);
167
144
  await homebridge.savePluginConfig(pluginConfig);
168
145
  break;
169
146
  case 1:
170
147
  document.getElementById('info').innerHTML = info;
171
- document.getElementById('info').style.color = 'red';
148
+ document.getElementById('info').style.color = 'green';
149
+ break;
150
+ case 2:
151
+ document.getElementById('info').innerHTML = info;
152
+ document.getElementById('info').style.color = 'white';
172
153
  break;
173
- default:
174
- document.getElementById('info').innerHTML = `Received unknown status: ${status}, please try again.`;
154
+ case 3:
155
+ document.getElementById('info').innerHTML = info;
156
+ document.getElementById('info').style.color = 'gray';
157
+ break;
158
+ case 4:
159
+ document.getElementById('info').innerHTML = info;
175
160
  document.getElementById('info').style.color = 'yellow';
176
161
  break;
162
+ case 5:
163
+ document.getElementById('info').innerHTML = `MELCloud error: ${JSON.stringify(error, null, 2)}`;
164
+ document.getElementById('info').style.color = 'red';
165
+ break;
177
166
  };
178
167
 
179
168
  homebridge.hideSpinner();
180
169
  } catch (e) {
181
- document.getElementById('info').innerHTML = 'Please try again.';
182
170
  homebridge.toast.error(`Data error: ${e.message}`);
183
171
  } finally {
184
172
  homebridge.hideSpinner();
@@ -19,24 +19,58 @@ 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
- let data = {};
28
- const melCloud = new MelCloud(user, passwd, language, accountInfoFile, deviceInfoFile, buildingsFile, false, 0, true);
29
- const contextKey = await melCloud.connect();
30
- const devices = await melCloud.chackDevicesList(contextKey);
31
- return data = {
32
- info: '',
33
- status: 0,
34
- data: devices
35
- };
30
+ const melCloud = new MelCloud(user, passwd, language, accountInfoFile, deviceInfoFile, buildingsFile, enableDebugMode, refreshInterval, false);
31
+ melCloud.on('connect', (devices) => {
32
+ return data = {
33
+ info: 'Connect to MELCloud success, now pres the button Get Devices.',
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: 'Connect error:',
65
+ status: 5,
66
+ data: error
67
+ };
68
+ });
36
69
  } catch (error) {
37
70
  return data = {
38
- info: error,
39
- status: 1
71
+ info: 'MELCloud error.',
72
+ status: 5,
73
+ error: error
40
74
  };
41
75
  };
42
76
  };
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, false);
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.29",
4
+ "version": "2.5.0-beta.3",
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, connectForConfig) {
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.connectForConfig = connectForConfig;
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
- if (!connectForConfig) {
35
- this.impulseGenerator = new ImpulseGenerator();
36
- this.impulseGenerator.on('checkDevicesList', async () => {
37
- try {
38
- await this.chackDevicesList(this.contextKey);
39
- } catch (error) {
40
- this.emit('error', `Check devices list: ${error}.`);
41
- };
42
- }).on('state', (state) => { });
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(contextKey);
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(contextKey) {
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
- const stop = connectForConfig ? false : this.impulseGenerator.stop();
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) {