homebridge-melcloud-control 4.3.0-beta.32 → 4.3.0-beta.34

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/index.js CHANGED
@@ -194,7 +194,7 @@ class MelCloudPlatform {
194
194
 
195
195
  //start impulse generators\
196
196
  await configuredDevice.startStopImpulseGenerator(true, [{ name: 'checkState', sampling: deviceRefreshInterval }]);
197
- const timmers = accountType === 'melcloudhome' ? [] : [{ name: 'checkDevicesList', sampling: refreshInterval }];
197
+ const timmers = accountType === 'melcloudhome' ? [{ name: 'connect', sampling: 3600000 }, { name: 'checkDevicesList', sampling: 3000 }] : [{ name: 'checkDevicesList', sampling: refreshInterval }];
198
198
  await melCloud.impulseGenerator.state(true, timmers, false);
199
199
 
200
200
  //stop impulse generator
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.0-beta.32",
4
+ "version": "4.3.0-beta.34",
5
5
  "description": "Homebridge plugin to control Mitsubishi Air Conditioner, Heat Pump and Energy Recovery Ventilation.",
6
6
  "license": "MIT",
7
7
  "author": "grzegorz914",
@@ -27,7 +27,9 @@ class MelCloudAta extends EventEmitter {
27
27
  this.deviceData = {};
28
28
  this.headers = {};
29
29
  this.socket = null;
30
+ this.connecting = false;
30
31
  this.socketConnected = false;
32
+ this.reconnectDelay = 1000;
31
33
 
32
34
  //lock flag
33
35
  this.locks = false;
@@ -74,76 +76,12 @@ class MelCloudAta extends EventEmitter {
74
76
  if (this.logDebug) this.emit('debug', `Reconnect in ${delay}ms`);
75
77
 
76
78
  setTimeout(() => {
77
- this.reconnectDelay *= 2; // exponential backoff
79
+ this.reconnectDelay *= 2;
78
80
  this.reconnectDelay = Math.max(1000, this.reconnectDelay);
79
81
  this.connectSocket(deviceData);
80
82
  }, delay);
81
83
  };
82
84
 
83
- async connectSocket(deviceData, wsHeaders) {
84
- if (this.connecting || this.socketConnected) return;
85
-
86
- this.connecting = true;
87
- const url = `${ApiUrlsHome.WebSocketURL}${wsHeaders.hash}`;
88
- try {
89
- const socket = new WebSocket(url, { headers: wsHeaders.headers })
90
- .on('error', (error) => {
91
- if (this.logError) this.emit('error', `Socket error: ${error}`);
92
- })
93
- .on('close', () => {
94
- if (this.logDebug) this.emit('debug', `Socket closed`);
95
- this.reconnect();
96
- })
97
- .on('open', () => {
98
- this.socket = socket;
99
- this.socketConnected = true;
100
- this.connecting = false;
101
- this.reconnectDelay = 1000;
102
- this.emit('success', `Socket Connect Success`);
103
-
104
- // heartbeat
105
- this.heartbeat = setInterval(() => {
106
- if (socket.readyState === socket.OPEN) {
107
- if (!this.logDebug) this.emit('warn', `Socket send heartbeat`);
108
- socket.ping();
109
- }
110
- }, 30000);
111
- })
112
- .on('pong', () => {
113
- if (!this.logDebug) this.emit('warn', `Socket received heartbeat`);
114
- })
115
- .on('message', (message) => {
116
- const parsedMessage = JSON.parse(message);
117
- if (!this.logDebug) this.emit('warn', `Incoming message: ${JSON.stringify(parsedMessage, null, 2)}`);
118
-
119
- const messageData = parsedMessage?.[0]?.Data;
120
- const unitId = messageData?.id;
121
-
122
- switch (unitId) {
123
- case this.deviceId:
124
- const messageType = parsedMessage[0].messageType;
125
- switch (messageType) {
126
- case 'unitStateChanged':
127
- const settings = Object.fromEntries(messageData.settings.map(s => [s.name, s.value]));
128
- Object.assign(deviceData.Device, settings);
129
- this.emit('deviceState', deviceData);
130
- break;
131
- case 'unitWiFiChanged':
132
- const state = Object.fromEntries(messageData.settings.map(s => [s.name, s.value]));
133
- Object.assign(deviceData.Device, state);
134
- this.emit('deviceState', deviceData);
135
- break;
136
- }
137
- break;
138
- }
139
- });
140
-
141
- } catch (error) {
142
- if (this.logError) this.emit('error', `Socket connection failed: ${error}`);
143
- this.reconnect();
144
- }
145
- }
146
-
147
85
  async checkState() {
148
86
  try {
149
87
 
@@ -166,7 +104,66 @@ class MelCloudAta extends EventEmitter {
166
104
  deviceData.Device.DefaultHeatingSetTemperature = temps?.defaultHeatingSetTemperature ?? 20;
167
105
  deviceData.Device.DefaultCoolingSetTemperature = temps?.defaultCoolingSetTemperature ?? 24;
168
106
 
169
- await this.connectSocket(deviceData, devicesData.WsHeaders);
107
+ if (!this.connecting && !this.socketConnected) {
108
+ this.connecting = true;
109
+
110
+ const url = `${ApiUrlsHome.WebSocketURL}${devicesData.wsHeaders.hash}`;
111
+ try {
112
+ const socket = new WebSocket(url, { headers: devicesData.wsHeaders.headers })
113
+ .on('error', (error) => {
114
+ if (this.logError) this.emit('error', `Socket error: ${error}`);
115
+ })
116
+ .on('close', () => {
117
+ if (this.logDebug) this.emit('debug', `Socket closed`);
118
+ this.reconnect();
119
+ })
120
+ .on('open', () => {
121
+ this.socket = socket;
122
+ this.socketConnected = true;
123
+ this.connecting = false;
124
+ this.emit('success', `Socket Connect Success`);
125
+
126
+ // heartbeat
127
+ this.heartbeat = setInterval(() => {
128
+ if (socket.readyState === socket.OPEN) {
129
+ if (!this.logDebug) this.emit('warn', `Socket send heartbeat`);
130
+ socket.ping();
131
+ }
132
+ }, 30000);
133
+ })
134
+ .on('pong', () => {
135
+ if (!this.logDebug) this.emit('warn', `Socket received heartbeat`);
136
+ })
137
+ .on('message', (message) => {
138
+ const parsedMessage = JSON.parse(message);
139
+ if (!this.logDebug) this.emit('warn', `Incoming message: ${JSON.stringify(parsedMessage, null, 2)}`);
140
+
141
+ const messageData = parsedMessage?.[0]?.Data;
142
+ const unitId = messageData?.id;
143
+
144
+ switch (unitId) {
145
+ case this.deviceId:
146
+ const messageType = parsedMessage[0].messageType;
147
+ switch (messageType) {
148
+ case 'unitStateChanged':
149
+ const settings = Object.fromEntries(messageData.settings.map(s => [s.name, s.value]));
150
+ Object.assign(deviceData.Device, settings);
151
+ this.emit('deviceState', deviceData);
152
+ break;
153
+ case 'unitWiFiChanged':
154
+ const state = Object.fromEntries(messageData.settings.map(s => [s.name, s.value]));
155
+ Object.assign(deviceData.Device, state);
156
+ this.emit('deviceState', deviceData);
157
+ break;
158
+ }
159
+ break;
160
+ }
161
+ });
162
+ } catch (error) {
163
+ if (this.logError) this.emit('error', `Socket connection failed: ${error}`);
164
+ this.reconnect();
165
+ }
166
+ }
170
167
  }
171
168
  if (this.logDebug) this.emit('debug', `Device Data: ${JSON.stringify(deviceData, null, 2)}`);
172
169
 
@@ -324,11 +321,6 @@ class MelCloudAta extends EventEmitter {
324
321
  this.headers.Referer = ApiUrlsHome.Referers.GetPutScenes;
325
322
  break;
326
323
  default:
327
- if (!this.socket || this.socket.readyState !== this.socket.OPEN) {
328
- if (this.logDebug) this.emit('debug', `Socket not open, cannot send`);
329
- return false;
330
- }
331
-
332
324
  if (displayType === 1 && deviceData.Device.OperationMode === 8) {
333
325
  deviceData.Device.SetTemperature = (deviceData.Device.DefaultCoolingSetTemperature + deviceData.Device.DefaultHeatingSetTemperature) / 2;
334
326
 
@@ -354,26 +346,6 @@ class MelCloudAta extends EventEmitter {
354
346
  method = 'PUT';
355
347
  path = ApiUrlsHome.PutAta.replace('deviceid', deviceData.DeviceID);
356
348
  this.headers.Referer = ApiUrlsHome.Referers.PutDeviceSettings;
357
-
358
- const payload1 = {
359
- Data: {
360
- id: deviceData.DeviceID,
361
- unitType: 'ata',
362
- settings: [
363
- {
364
- name: 'Power',
365
- value: deviceData.Device.Power
366
- }
367
- ]
368
- }
369
- };
370
- try {
371
- this.socket.send(JSON.stringify(payload1));
372
- return true;
373
- } catch (err) {
374
- if (this.logDebug) this.emit('debug', `Socket send error: ${err}`);
375
- return false;
376
- }
377
349
  }
378
350
 
379
351
  this.headers['Content-Type'] = 'application/json; charset=utf-8';