homebridge-melcloud-control 4.3.11-beta.24 → 4.3.11-beta.26

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "displayName": "MELCloud Control",
3
3
  "name": "homebridge-melcloud-control",
4
- "version": "4.3.11-beta.24",
4
+ "version": "4.3.11-beta.26",
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
@@ -17,8 +17,8 @@ class MelCloud extends EventEmitter {
17
17
 
18
18
  this.accountFile = accountFile;
19
19
  this.buildingsFile = buildingsFile;
20
- this.headers = {};
21
20
 
21
+ this.client = null;
22
22
  this.functions = new Functions(this.logWarn, this.logError, this.logDebug)
23
23
  .on('warn', warn => this.emit('warn', warn))
24
24
  .on('error', error => this.emit('error', error))
@@ -56,7 +56,7 @@ class MelCloud extends EventEmitter {
56
56
  try {
57
57
  const devicesList = { State: false, Info: null, Devices: [], Scenes: [] }
58
58
  if (this.logDebug) this.emit('debug', `Scanning for devices...`);
59
- const listDevicesData = await this.axiosInstance(ApiUrls.ListDevices, { method: 'GET', });
59
+ const listDevicesData = await this.client(ApiUrls.ListDevices, { method: 'GET', });
60
60
 
61
61
  if (!listDevicesData || !listDevicesData.data) {
62
62
  devicesList.Info = 'Invalid or empty response from MELCloud API'
@@ -162,14 +162,13 @@ class MelCloud extends EventEmitter {
162
162
  'X-MitsContextKey': contextKey,
163
163
  'Content-Type': 'application/json'
164
164
  };
165
- this.emit('headers', headers);
166
-
167
- this.headers = headers;
168
- this.axiosInstance = axios.create({
165
+
166
+ this.client = axios.create({
169
167
  baseURL: ApiUrls.BaseURL,
170
168
  timeout: 30000,
171
169
  headers: headers
172
170
  });
171
+ this.emit('client', this.client);
173
172
 
174
173
  accountInfo.State = true;
175
174
  accountInfo.Info = 'Connect Success';
@@ -1,4 +1,3 @@
1
- import axios from 'axios';
2
1
  import EventEmitter from 'events';
3
2
  import Functions from './functions.js';
4
3
  import { ApiUrls, ApiUrlsHome, AirConditioner } from './constants.js';
@@ -24,12 +23,12 @@ class MelCloudAta extends EventEmitter {
24
23
 
25
24
  //set default values
26
25
  this.deviceData = {};
27
- this.headers = melcloud.headers;
26
+ this.client = melcloud.client;
28
27
 
29
28
  //handle melcloud events
30
29
  let deviceData = null;
31
- melcloud.on('headers', (headers) => {
32
- this.headers = headers;
30
+ melcloud.on('client', (client) => {
31
+ this.client = client;
33
32
  }).on('devicesList', async (devicesData) => {
34
33
  try {
35
34
  deviceData = devicesData.Devices.find(device => device.DeviceID === this.deviceId);
@@ -197,7 +196,6 @@ class MelCloudAta extends EventEmitter {
197
196
  let method = null
198
197
  let payload = {};
199
198
  let path = '';
200
- let headers = this.headers;
201
199
  switch (accountType) {
202
200
  case "melcloud":
203
201
  switch (flag) {
@@ -235,14 +233,7 @@ class MelCloudAta extends EventEmitter {
235
233
  }
236
234
 
237
235
  if (this.logDebug) this.emit('debug', `Send data: ${JSON.stringify(payload, null, 2)}`);
238
-
239
- await axios(path, {
240
- method: 'POST',
241
- baseURL: ApiUrls.BaseURL,
242
- timeout: 30000,
243
- headers: headers,
244
- data: payload
245
- });
236
+ await this.client(path, { method: 'POST', data: payload });
246
237
 
247
238
  this.emit('deviceState', deviceData);
248
239
  return true;
@@ -257,7 +248,6 @@ class MelCloudAta extends EventEmitter {
257
248
  };
258
249
  method = 'POST';
259
250
  path = ApiUrlsHome.PostProtectionFrost;
260
- headers.Referer = ApiUrlsHome.Referers.PostProtectionFrost.replace('deviceid', deviceData.DeviceID);
261
251
  break;
262
252
  case 'overheatprotection':
263
253
  payload = {
@@ -268,7 +258,6 @@ class MelCloudAta extends EventEmitter {
268
258
  };
269
259
  method = 'POST';
270
260
  path = ApiUrlsHome.PostProtectionOverheat;
271
- headers.Referer = ApiUrlsHome.Referers.PostProtectionOverheat.replace('deviceid', deviceData.DeviceID);
272
261
  break;
273
262
  case 'holidaymode':
274
263
  payload = {
@@ -279,18 +268,15 @@ class MelCloudAta extends EventEmitter {
279
268
  };
280
269
  method = 'POST';
281
270
  path = ApiUrlsHome.PostHolidayMode;
282
- headers.Referer = ApiUrlsHome.Referers.PostHolidayMode.replace('deviceid', deviceData.DeviceID);
283
271
  break;
284
272
  case 'schedule':
285
273
  payload = { enabled: deviceData.ScheduleEnabled };
286
274
  method = 'PUT';
287
275
  path = ApiUrlsHome.PutScheduleEnabled.replace('deviceid', deviceData.DeviceID);
288
- this.headers.Referer = ApiUrlsHome.Referers.PutScheduleEnabled.replace('deviceid', deviceData.DeviceID);
289
276
  break;
290
277
  case 'scene':
291
278
  method = 'PUT';
292
279
  path = ApiUrlsHome.PutScene[flagData.Enabled ? 'Enable' : 'Disable'].replace('sceneid', flagData.Id);
293
- headers.Referer = ApiUrlsHome.Referers.GetPutScenes;
294
280
  break;
295
281
  default:
296
282
  if (displayType === 1 && deviceData.Device.OperationMode === 8) {
@@ -317,22 +303,12 @@ class MelCloudAta extends EventEmitter {
317
303
  };
318
304
  method = 'PUT';
319
305
  path = ApiUrlsHome.PutAta.replace('deviceid', deviceData.DeviceID);
320
- headers.Referer = ApiUrlsHome.Referers.PutDeviceSettings;
321
306
  break;
322
307
  }
323
308
 
324
- //sens payload
325
- headers['Content-Type'] = 'application/json; charset=utf-8';
326
- headers.Origin = ApiUrlsHome.Origin;
309
+ //send payload
327
310
  if (!this.logDebug) this.emit('debug', `Send data: ${JSON.stringify(payload, null, 2)}`);
328
-
329
- await axios(path, {
330
- method: method,
331
- baseURL: ApiUrlsHome.BaseURL,
332
- timeout: 30000,
333
- headers: headers,
334
- data: payload
335
- });
311
+ await this.client(path, { method: method, data: payload });
336
312
 
337
313
  return true;
338
314
  default:
@@ -1,4 +1,3 @@
1
- import axios from 'axios';
2
1
  import EventEmitter from 'events';
3
2
  import Functions from './functions.js';
4
3
  import { ApiUrls, ApiUrlsHome, HeatPump } from './constants.js';
@@ -24,12 +23,12 @@ class MelCloudAtw extends EventEmitter {
24
23
 
25
24
  //set default values
26
25
  this.deviceData = {};
27
- this.headers = melcloud.headers;
26
+ this.client = melcloud.client;
28
27
 
29
28
  //handle melcloud events
30
29
  let deviceData = null;
31
- melcloud.on('headers', (headers) => {
32
- this.headers = headers;
30
+ melcloud.on('client', (client) => {
31
+ this.client = client;
33
32
  }).on('devicesList', async (devicesData) => {
34
33
  try {
35
34
  deviceData = devicesData.Devices.find(device => device.DeviceID === this.deviceId);
@@ -198,7 +197,6 @@ class MelCloudAtw extends EventEmitter {
198
197
  let method = null
199
198
  let payload = {};
200
199
  let path = '';
201
- let headers = this.headers;
202
200
  switch (accountType) {
203
201
  case "melcloud":
204
202
  switch (flag) {
@@ -237,14 +235,7 @@ class MelCloudAtw extends EventEmitter {
237
235
  }
238
236
 
239
237
  if (this.logDebug) this.emit('debug', `Send data: ${JSON.stringify(payload, null, 2)}`);
240
-
241
- await axios(path, {
242
- method: 'POST',
243
- baseURL: ApiUrls.BaseURL,
244
- timeout: 30000,
245
- headers: headers,
246
- data: payload
247
- });
238
+ await this.client(path, { method: 'POST', data: payload });
248
239
 
249
240
  this.emit('deviceState', deviceData);
250
241
  return true;
@@ -259,18 +250,15 @@ class MelCloudAtw extends EventEmitter {
259
250
  };
260
251
  method = 'POST';
261
252
  path = ApiUrlsHome.PostHolidayMode;
262
- headers.Referer = ApiUrlsHome.Referers.PostHolidayMode.replace('deviceid', deviceData.DeviceID);
263
253
  break;
264
254
  case 'schedule':
265
255
  payload = { enabled: deviceData.ScheduleEnabled };
266
256
  method = 'PUT';
267
257
  path = ApiUrlsHome.PutScheduleEnabled.replace('deviceid', deviceData.DeviceID);
268
- headers.Referer = ApiUrlsHome.Referers.PutScheduleEnabled.replace('deviceid', deviceData.DeviceID);
269
258
  break;
270
259
  case 'scene':
271
260
  method = 'PUT';
272
261
  path = ApiUrlsHome.PutScene[flagData.Enabled ? 'Enable' : 'Disable'].replace('sceneid', flagData.Id);
273
- headers.Referer = ApiUrlsHome.Referers.GetPutScenes;
274
262
  break;
275
263
  default:
276
264
  payload = {
@@ -290,21 +278,11 @@ class MelCloudAtw extends EventEmitter {
290
278
  };
291
279
  method = 'PUT';
292
280
  path = ApiUrlsHome.PutAtw.replace('deviceid', deviceData.DeviceID);
293
- headers.Referer = ApiUrlsHome.Referers.PutDeviceSettings;
294
281
  break
295
282
  }
296
283
 
297
- headers['Content-Type'] = 'application/json; charset=utf-8';
298
- headers.Origin = ApiUrlsHome.Origin;
299
284
  if (this.logDebug) this.emit('debug', `Send data: ${JSON.stringify(payload, null, 2)}`);
300
-
301
- await axios(path, {
302
- method: method,
303
- baseURL: ApiUrlsHome.BaseURL,
304
- timeout: 30000,
305
- headers: headers,
306
- data: payload
307
- });
285
+ await this.client(path, { method: method, data: payload });
308
286
 
309
287
  return true;
310
288
  default:
@@ -1,4 +1,3 @@
1
- import axios from 'axios';
2
1
  import EventEmitter from 'events';
3
2
  import Functions from './functions.js';
4
3
  import { ApiUrls, ApiUrlsHome, Ventilation } from './constants.js';
@@ -24,12 +23,12 @@ class MelCloudErv extends EventEmitter {
24
23
 
25
24
  //set default values
26
25
  this.deviceData = {};
27
- this.headers = melcloud.headers;
26
+ this.client = melcloud.client;
28
27
 
29
28
  //handle melcloud events
30
29
  let deviceData = null;
31
- melcloud.on('headers', (headers) => {
32
- this.headers = headers;
30
+ melcloud.on('client', (client) => {
31
+ this.client = client;
33
32
  }).on('devicesList', async (devicesData) => {
34
33
  try {
35
34
  deviceData = devicesData.Devices.find(device => device.DeviceID === this.deviceId);
@@ -183,7 +182,6 @@ class MelCloudErv extends EventEmitter {
183
182
  let method = null
184
183
  let payload = {};
185
184
  let path = '';
186
- let headers = this.headers;
187
185
  switch (accountType) {
188
186
  case "melcloud":
189
187
  switch (flag) {
@@ -237,14 +235,7 @@ class MelCloudErv extends EventEmitter {
237
235
  }
238
236
 
239
237
  if (this.logDebug) this.emit('debug', `Send data: ${JSON.stringify(payload, null, 2)}`);
240
-
241
- await axios(path, {
242
- method: 'POST',
243
- baseURL: ApiUrls.BaseURL,
244
- timeout: 30000,
245
- headers: headers,
246
- data: payload
247
- });
238
+ await this.client(path, { method: 'POST', data: payload });
248
239
 
249
240
  this.emit('deviceState', deviceData);
250
241
  return true;
@@ -259,18 +250,15 @@ class MelCloudErv extends EventEmitter {
259
250
  };
260
251
  method = 'POST';
261
252
  path = ApiUrlsHome.PostHolidayMode;
262
- headers.Referer = ApiUrlsHome.Referers.PostHolidayMode.replace('deviceid', deviceData.DeviceID);
263
253
  break;
264
254
  case 'schedule':
265
255
  payload = { enabled: deviceData.ScheduleEnabled };
266
256
  method = 'PUT';
267
257
  path = ApiUrlsHome.PutScheduleEnabled.replace('deviceid', deviceData.DeviceID);
268
- headers.Referer = ApiUrlsHome.Referers.PutScheduleEnabled.replace('deviceid', deviceData.DeviceID);
269
258
  break;
270
259
  case 'scene':
271
260
  method = 'PUT';
272
261
  path = ApiUrlsHome.PutScene[flagData.Enabled ? 'Enable' : 'Disable'].replace('sceneid', flagData.Id);
273
- headers.Referer = ApiUrlsHome.Referers.GetPutScenes;
274
262
  break;
275
263
  default:
276
264
  if (displayType === 1 && deviceData.Device.VentilationMode === 2) {
@@ -294,21 +282,11 @@ class MelCloudErv extends EventEmitter {
294
282
  };
295
283
  method = 'PUT';
296
284
  path = ApiUrlsHome.PutErv.replace('deviceid', deviceData.DeviceID);
297
- headers.Referer = ApiUrlsHome.Referers.PutDeviceSettings;
298
285
  break
299
286
  }
300
287
 
301
- headers['Content-Type'] = 'application/json; charset=utf-8';
302
- headers.Origin = ApiUrlsHome.Origin;
303
288
  if (this.logDebug) this.emit('debug', `Send data: ${JSON.stringify(payload, null, 2)}`);
304
-
305
- await axios(path, {
306
- method: method,
307
- baseURL: ApiUrlsHome.BaseURL,
308
- timeout: 30000,
309
- headers: headers,
310
- data: payload
311
- });
289
+ await this.client(path, { method: method, data: payload });
312
290
 
313
291
  return true;
314
292
  default:
@@ -24,9 +24,8 @@ class MelCloudHome extends EventEmitter {
24
24
  this.accountFile = accountFile;
25
25
  this.buildingsFile = buildingsFile;
26
26
 
27
- this.headers = {};
28
- this.webSocketOptions = {};
29
- this.socket = null;
27
+ this.client = null;
28
+ this.webSocket = null;
30
29
  this.connecting = false;
31
30
  this.socketConnected = false;
32
31
  this.heartbeat = null;
@@ -74,9 +73,9 @@ class MelCloudHome extends EventEmitter {
74
73
  this.heartbeat = null;
75
74
  }
76
75
 
77
- if (this.socket) {
78
- try { this.socket.close(); } catch { }
79
- this.socket = null;
76
+ if (this.webSocket) {
77
+ try { this.webSocket.close(); } catch { }
78
+ this.webSocket = null;
80
79
  }
81
80
 
82
81
  this.socketConnected = false;
@@ -85,7 +84,7 @@ class MelCloudHome extends EventEmitter {
85
84
  async checkScenesList() {
86
85
  try {
87
86
  if (this.logDebug) this.emit('debug', `Scanning for scenes`);
88
- const listScenesData = await this.axiosInstance(ApiUrlsHome.GetUserScenes, { method: 'GET', });
87
+ const listScenesData = await this.client(ApiUrlsHome.GetUserScenes, { method: 'GET', });
89
88
 
90
89
  const scenesList = listScenesData.data;
91
90
  if (this.logDebug) this.emit('debug', `Scenes: ${JSON.stringify(scenesList, null, 2)}`);
@@ -117,7 +116,7 @@ class MelCloudHome extends EventEmitter {
117
116
  try {
118
117
  const devicesList = { State: false, Info: null, Devices: [], Scenes: [] }
119
118
  if (this.logDebug) this.emit('debug', `Scanning for devices`);
120
- const listDevicesData = await this.axiosInstance(ApiUrlsHome.GetUserContext, { method: 'GET' });
119
+ const listDevicesData = await this.client(ApiUrlsHome.GetUserContext, { method: 'GET' });
121
120
 
122
121
  const userContext = listDevicesData.data;
123
122
  const buildings = userContext.buildings ?? [];
@@ -216,12 +215,10 @@ class MelCloudHome extends EventEmitter {
216
215
  this.connecting = true;
217
216
 
218
217
  try {
219
- const url = `${ApiUrlsHome.WebSocketURL}${this.webSocketOptions.Hash}`;
220
- this.socket = new WebSocket(url, { headers: this.webSocketOptions.Headers })
221
- .on('error', (error) => {
222
- if (this.logError) this.emit('error', `Socket error: ${error}`);
223
- this.socket.close();
224
- })
218
+ this.webSocket.on('error', (error) => {
219
+ if (this.logError) this.emit('error', `Socket error: ${error}`);
220
+ this.socket.close();
221
+ })
225
222
  .on('close', () => {
226
223
  if (this.logDebug) this.emit('debug', `Socket closed`);
227
224
  this.cleanupSocket();
@@ -331,15 +328,22 @@ class MelCloudHome extends EventEmitter {
331
328
  page.setDefaultNavigationTimeout(GLOBAL_TIMEOUT);
332
329
 
333
330
  // === CDP session ===
334
- let hash = null;
335
331
  const client = await page.createCDPSession();
336
332
  await client.send('Network.enable')
337
333
  client.on('Network.webSocketCreated', ({ url }) => {
338
334
  try {
339
335
  if (url.startsWith('wss://ws.melcloudhome.com/?hash=')) {
340
336
  const params = new URL(url).searchParams;
341
- hash = params.get('hash');
337
+ const hash = params.get('hash');
342
338
  if (this.logDebug) this.emit('debug', `MelCloudHome WS hash detected: ${hash}`);
339
+
340
+ const headers = {
341
+ 'Origin': ApiUrlsHome.BaseURL,
342
+ 'Pragma': 'no-cache',
343
+ 'Cache-Control': 'no-cache'
344
+ };
345
+ const url = `${ApiUrlsHome.WebSocketURL}${hash}`;
346
+ this.webSocket = new WebSocket(url, { headers: headers });
343
347
  }
344
348
  } catch (error) {
345
349
  if (this.logError) this.emit('error', `CDP WebSocketCreated handler error: ${error.message}`);
@@ -419,23 +423,13 @@ class MelCloudHome extends EventEmitter {
419
423
  'User-Agent': userAgent,
420
424
  'x-csrf': '1'
421
425
  };
422
- this.emit('headers', headers);
423
426
 
424
- this.headers = headers;
425
- this.axiosInstance = axios.create({
427
+ this.client = axios.create({
426
428
  baseURL: ApiUrlsHome.BaseURL,
427
429
  timeout: 30000,
428
430
  headers: headers
429
431
  })
430
-
431
- this.webSocketOptions = {
432
- Hash: hash,
433
- Headers: {
434
- 'Origin': ApiUrlsHome.BaseURL,
435
- 'Pragma': 'no-cache',
436
- 'Cache-Control': 'no-cache'
437
- }
438
- };
432
+ this.emit('client', this.client);
439
433
 
440
434
  accountInfo.State = true;
441
435
  accountInfo.Info = 'Connect Success';