homebridge-melcloud-control 2.5.0-beta.2 → 2.5.0-beta.20

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.
@@ -6,7 +6,7 @@
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 Name</label><br>
9
+ <label id="accountName" style="font-size: 23px">Account</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">
@@ -20,8 +20,7 @@
20
20
  <input id="language" type="text" class="form-control"><br>
21
21
  </div>
22
22
  <div class="text-center">
23
- <button id="logIn" type="button" class="btn btn-primary">Log In</button>
24
- <button id="getDevices" type="button" class="btn btn-primary">Get Devices</button>
23
+ <button id="logIn" type="button" class="btn btn-primary">Connect to MELCloud</button>
25
24
  <button id="configButton" type="button" class="btn btn-primary"><i class="fas fa-gear"></i></button>
26
25
  </div>
27
26
  </form>
@@ -64,7 +63,7 @@
64
63
  document.getElementById('language').value = pluginConfig[0].accounts[i].language || '';
65
64
 
66
65
  const accountConfigured = pluginConfig[0].accounts[i].name && pluginConfig[0].accounts[i].user && pluginConfig[0].accounts[i].passwd && pluginConfig[0].accounts[i].language;
67
- const setButtonName = accountConfigured ? document.getElementById('logIn').removeAttribute('disabled') : document.getElementById('logIn').setAttribute('disabled');
66
+ const setButtonState = accountConfigured ? document.getElementById('logIn').removeAttribute('disabled') : document.getElementById('logIn').setAttribute('disabled');
68
67
  await homebridge.updatePluginConfig(pluginConfig);
69
68
  this.deviceIndex = i;
70
69
  });
@@ -83,7 +82,7 @@
83
82
  pluginConfig[0].accounts[this.deviceIndex].language = document.querySelector('#language').value;
84
83
 
85
84
  const accountConfigured = pluginConfig[0].accounts[i].name && pluginConfig[0].accounts[i].user && pluginConfig[0].accounts[i].passwd && pluginConfig[0].accounts[i].language;
86
- const setButtonMode = accountConfigured ? document.getElementById('logIn').removeAttribute('disabled') : document.getElementById('logIn').setAttribute('disabled');
85
+ const setButtonState = accountConfigured ? document.getElementById('logIn').removeAttribute('disabled') : document.getElementById('logIn').setAttribute('disabled');
87
86
 
88
87
  await homebridge.updatePluginConfig(pluginConfig);
89
88
  await homebridge.savePluginConfig(pluginConfig);
@@ -101,7 +100,7 @@
101
100
 
102
101
  try {
103
102
  await homebridge.updatePluginConfig(pluginConfig)
104
- document.getElementById('info').innerHTML = '';
103
+ document.getElementById('info').innerHTML = 'Connecting...';
105
104
 
106
105
  const accountName = pluginConfig[0].accounts[this.deviceIndex].name;
107
106
  const user = pluginConfig[0].accounts[this.deviceIndex].user;
@@ -111,7 +110,6 @@
111
110
  const refreshInterval = pluginConfig[0].accounts[this.deviceIndex].refreshInterval;
112
111
 
113
112
  const payload = {
114
- mode: 'connect',
115
113
  accountName: accountName,
116
114
  user: user,
117
115
  passwd: passwd,
@@ -120,77 +118,41 @@
120
118
  refreshInterval: refreshInterval
121
119
  };
122
120
  const response = await homebridge.request('/connect', payload);
123
- const info = response.info;
121
+ const info = response.info ?? '';
124
122
  const status = response.status;
125
- const data = response.data;
126
- const error = response.error;
123
+ const devices = response.data ?? [];
127
124
 
128
125
  switch (status) {
129
126
  case 0:
130
- document.getElementById('info').innerHTML = info;
131
- document.getElementById('getDevices').removeAttribute('disabled');
132
- break;
133
- case 2:
134
- document.getElementById('getDevices').setAttribute('disabled');
135
- document.getElementById('info').innerHTML = `MELCloud error: ${JSON.stringify(error, null, 2)}`;
136
- document.getElementById('info').style.color = 'red';
137
- break;
138
- };
139
-
140
- homebridge.hideSpinner();
141
- } catch (e) {
142
- homebridge.toast.error(`Data error: ${e.message}`);
143
- } finally {
144
- homebridge.hideSpinner();
145
- };
146
- });
147
-
148
- //get devices
149
- document.getElementById('getDevices').addEventListener('click', async () => {
150
- homebridge.showSpinner();
151
- try {
152
- const devicesId = [];
153
-
154
- const payload = {
155
- mode: 'getdevices'
156
- };
157
- const response = await homebridge.request('/getDevices', payload);
158
-
159
- const info = response.info;
160
- const status = response.status;
161
- const devices = response.data;
162
- const error = response.error;
163
-
164
- switch (status) {
165
- case 1:
166
127
  //get device info fom devices
167
128
  for (const deviceInfo of devices) {
168
129
  const deviceId = deviceInfo.DeviceID;
169
130
  const deviceName = deviceInfo.DeviceName;
170
-
171
- //prepare device if not in devices array
172
- if (!devicesId.includes(deviceId)) {
173
- devicesId.push(deviceId);
174
- }
175
131
  };
176
132
 
177
- document.getElementById('info').innerHTML = `${info} Found: ${devicesId.length} devices. Now You can start configure it.`;
133
+ const devicesCount = devices.length;
134
+ document.getElementById('info').innerHTML = `${info}, found ${devicesCount} ${devicesCount !== 1 ? 'devices' : 'device'}. Now You can start to configure it.`;
135
+ document.getElementById('info').style.color = 'green';
178
136
  await homebridge.updatePluginConfig(pluginConfig);
179
137
  await homebridge.savePluginConfig(pluginConfig);
180
138
  break;
181
- case 2:
182
- document.getElementById('info').innerHTML = `MELCloud error: ${JSON.stringify(error, null, 2)}`;
139
+ case 1:
140
+ document.getElementById('info').innerHTML = info;
183
141
  document.getElementById('info').style.color = 'red';
184
142
  break;
143
+ default:
144
+ document.getElementById('info').innerHTML = `Received unknown status: ${status}, please try again.`;
145
+ document.getElementById('info').style.color = 'yellow';
146
+ break;
185
147
  };
186
148
 
187
149
  homebridge.hideSpinner();
188
150
  } catch (e) {
189
- homebridge.toast.error(`Get devices error: ${e.message}`);
151
+ document.getElementById('info').innerHTML = 'Please try again.';
152
+ homebridge.toast.error(`Data error: ${e.message}`);
190
153
  } finally {
191
154
  homebridge.hideSpinner();
192
- }
155
+ };
193
156
  });
194
-
195
157
  })();
196
158
  </script>
@@ -7,9 +7,6 @@ class PluginUiServer extends HomebridgePluginUiServer {
7
7
  constructor() {
8
8
  super();
9
9
 
10
- //get devices
11
- this.onRequest('/getdevices', this.start.bind(this));
12
-
13
10
  //connect
14
11
  this.onRequest('/connect', this.start.bind(this));
15
12
 
@@ -18,8 +15,6 @@ class PluginUiServer extends HomebridgePluginUiServer {
18
15
  };
19
16
 
20
17
  async start(payload) {
21
-
22
- const mode = payload.mode;
23
18
  const accountName = payload.accountName;
24
19
  const user = payload.user;
25
20
  const passwd = payload.passwd;
@@ -29,40 +24,22 @@ class PluginUiServer extends HomebridgePluginUiServer {
29
24
  const accountInfoFile = `${this.homebridgeStoragePath}/melcloud/${accountName}_Account`;
30
25
  const deviceInfoFile = `${this.homebridgeStoragePath}/melcloud/${accountName}_Device_`;
31
26
  const buildingsFile = `${this.homebridgeStoragePath}/melcloud/${accountName}_Buildings`;
32
- const melCloud = new MelCloud(user, passwd, language, accountInfoFile, deviceInfoFile, buildingsFile, enableDebugMode, refreshInterval);
33
27
 
34
- let data = {};
35
- switch (mode) {
36
- case 'connect':
37
- try {
38
- const response = await melCloud.connect();
39
- return data = {
40
- info: 'Connect to MELCloud success, now pres the button Get Devices.',
41
- status: 1,
42
- data: response
43
- };
44
- } catch (error) {
45
- return data = {
46
- info: 'Connect error:',
47
- status: 2,
48
- data: error
49
- };
50
- };
51
- case 'getdevices':
52
- try {
53
- const response = await melCloud.chackDevicesList();
54
- return data = {
55
- info: 'Get devices success.',
56
- status: 0,
57
- data: response
58
- };
59
- } catch (error) {
60
- return data = {
61
- info: 'Get devices error:',
62
- status: 2,
63
- data: error
64
- };
65
- };
28
+ try {
29
+ let data = {};
30
+ const melCloud = new MelCloud(user, passwd, language, accountInfoFile, deviceInfoFile, buildingsFile, enableDebugMode, refreshInterval, true);
31
+ const contextKey = await melCloud.connect();
32
+ const devices = await melCloud.chackDevicesList(contextKey);
33
+ return data = {
34
+ info: 'Success!',
35
+ status: 0,
36
+ data: devices
37
+ };
38
+ } catch (error) {
39
+ return data = {
40
+ info: error,
41
+ status: 1
42
+ };
66
43
  };
67
44
  };
68
45
  };
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, false);
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.2",
4
+ "version": "2.5.0-beta.20",
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,13 +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, connectForConfig) {
12
12
  super();
13
13
  this.enableDebugMode = enableDebugMode;
14
14
  this.accountInfoFile = accountInfoFile;
15
15
  this.buildingsFile = buildingsFile;
16
16
  this.deviceInfoFile = deviceInfoFile;
17
17
  this.refreshInterval = refreshInterval;
18
+ this.connectForConfig = connectForConfig;
18
19
  this.devicesId = [];
19
20
 
20
21
  this.options = {
@@ -38,7 +39,9 @@ class MelCloud extends EventEmitter {
38
39
  };
39
40
  }).on('state', (state) => { });
40
41
 
41
- this.connect();
42
+ if (!connectForConfig) {
43
+ this.connect();
44
+ };
42
45
  };
43
46
 
44
47
  async connect() {
@@ -79,56 +82,26 @@ class MelCloud extends EventEmitter {
79
82
  return;
80
83
  };
81
84
 
82
- //create axios instance get
83
- this.axiosInstanceGet = axios.create({
84
- method: 'GET',
85
- baseURL: CONSTANTS.ApiUrls.BaseURL,
86
- timeout: 5000,
87
- headers: {
88
- 'X-MitsContextKey': contextKey
89
- },
90
- maxContentLength: 100000000,
91
- maxBodyLength: 1000000000,
92
- withCredentials: true,
93
- httpsAgent: new https.Agent({
94
- keepAlive: false,
95
- rejectUnauthorized: false
96
- })
97
- });
98
-
99
- //create axios instance post
100
- this.axiosInstancePost = axios.create({
101
- method: 'POST',
102
- baseURL: CONSTANTS.ApiUrls.BaseURL,
103
- timeout: 5000,
104
- headers: {
105
- 'X-MitsContextKey': contextKey,
106
- 'content-type': 'application/json'
107
- },
108
- maxContentLength: 100000000,
109
- maxBodyLength: 1000000000,
110
- withCredentials: true,
111
- httpsAgent: new https.Agent({
112
- keepAlive: false,
113
- rejectUnauthorized: false
114
- })
115
- });
116
-
117
85
  this.accountInfo = accountInfo;
118
86
  this.contextKey = contextKey;
119
87
 
120
88
  //save melcloud info to the file
121
89
  await this.saveData(this.accountInfoFile, accountInfo);
122
90
 
91
+ //return if connect for config
92
+ if (this.connectForConfig) {
93
+ return contextKey;
94
+ };
95
+
123
96
  //check devices list
124
- await this.chackDevicesList();
97
+ await this.chackDevicesList(contextKey);
125
98
 
126
99
  //emit connect success
127
100
  this.emit('success', `Connect to MELCloud Success.`)
128
101
 
129
102
  //start impulse generator
130
103
  const timers = [{ name: 'checkDevicesList', sampling: this.refreshInterval }];
131
- this.impulseGenerator.start(timers)
104
+ this.impulseGenerator.start(timers);
132
105
 
133
106
  return true;
134
107
  } catch (error) {
@@ -136,10 +109,29 @@ class MelCloud extends EventEmitter {
136
109
  };
137
110
  }
138
111
 
139
- async chackDevicesList() {
112
+ async chackDevicesList(key) {
140
113
  try {
114
+ const contextKey = this.contextKey ?? key;
115
+
116
+ //create axios instance get
117
+ const axiosInstanceGet = axios.create({
118
+ method: 'GET',
119
+ baseURL: CONSTANTS.ApiUrls.BaseURL,
120
+ timeout: 5000,
121
+ headers: {
122
+ 'X-MitsContextKey': contextKey
123
+ },
124
+ maxContentLength: 100000000,
125
+ maxBodyLength: 1000000000,
126
+ withCredentials: true,
127
+ httpsAgent: new https.Agent({
128
+ keepAlive: false,
129
+ rejectUnauthorized: false
130
+ })
131
+ });
132
+
141
133
  const debug = this.enableDebugMode ? this.emit('debug', `Scanning for devices.`) : false;
142
- const listDevicesData = await this.axiosInstanceGet(CONSTANTS.ApiUrls.ListDevices);
134
+ const listDevicesData = await axiosInstanceGet(CONSTANTS.ApiUrls.ListDevices);
143
135
  const buildingsList = listDevicesData.data;
144
136
  const debug1 = this.enableDebugMode ? this.emit('debug', `Buildings: ${JSON.stringify(buildingsList, null, 2)}`) : false;
145
137
 
@@ -175,6 +167,11 @@ class MelCloud extends EventEmitter {
175
167
  }
176
168
  const debug3 = this.enableDebugMode ? this.emit('debug', `Found: ${devicesCount} devices.`) : false;
177
169
 
170
+ //return devices list for config
171
+ if (this.connectForConfig) {
172
+ return devices;
173
+ };
174
+
178
175
  //get device info fom devices
179
176
  for (const deviceInfo of devices) {
180
177
  const deviceId = deviceInfo.DeviceID
@@ -188,11 +185,11 @@ class MelCloud extends EventEmitter {
188
185
  //prepare device if not in devices array
189
186
  if (!this.devicesId.includes(deviceId)) {
190
187
  this.devicesId.push(deviceId);
191
- this.emit('checkDevicesListComplete', this.accountInfo, this.contextKey, deviceInfo);
188
+ this.emit('checkDevicesListComplete', this.accountInfo, contextKey, deviceInfo);
192
189
  }
193
190
  };
194
191
 
195
- return devices;
192
+ return true;
196
193
  } catch (error) {
197
194
  this.impulseGenerator.stop();
198
195
  throw new Error(`Scanning for devices error: ${error.message ?? error}.`);
@@ -211,11 +208,29 @@ class MelCloud extends EventEmitter {
211
208
 
212
209
  async send(accountInfo) {
213
210
  try {
211
+ //create axios instance post
212
+ const axiosInstancePost = axios.create({
213
+ method: 'POST',
214
+ baseURL: CONSTANTS.ApiUrls.BaseURL,
215
+ timeout: 5000,
216
+ headers: {
217
+ 'X-MitsContextKey': this.contextKey,
218
+ 'content-type': 'application/json'
219
+ },
220
+ maxContentLength: 100000000,
221
+ maxBodyLength: 1000000000,
222
+ withCredentials: true,
223
+ httpsAgent: new https.Agent({
224
+ keepAlive: false,
225
+ rejectUnauthorized: false
226
+ })
227
+ });
228
+
214
229
  const options = {
215
230
  data: accountInfo
216
231
  };
217
232
 
218
- await this.axiosInstancePost(CONSTANTS.ApiUrls.UpdateApplicationOptions, options);
233
+ await axiosInstancePost(CONSTANTS.ApiUrls.UpdateApplicationOptions, options);
219
234
  await this.saveData(this.accountInfoFile, accountInfo);
220
235
  return true;
221
236
  } catch (error) {