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

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/melcloudata.js +63 -91
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.33",
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,6 +27,7 @@ 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;
31
32
 
32
33
  //lock flag
@@ -74,76 +75,12 @@ class MelCloudAta extends EventEmitter {
74
75
  if (this.logDebug) this.emit('debug', `Reconnect in ${delay}ms`);
75
76
 
76
77
  setTimeout(() => {
77
- this.reconnectDelay *= 2; // exponential backoff
78
+ this.reconnectDelay *= 2;
78
79
  this.reconnectDelay = Math.max(1000, this.reconnectDelay);
79
80
  this.connectSocket(deviceData);
80
81
  }, delay);
81
82
  };
82
83
 
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
84
  async checkState() {
148
85
  try {
149
86
 
@@ -166,7 +103,67 @@ class MelCloudAta extends EventEmitter {
166
103
  deviceData.Device.DefaultHeatingSetTemperature = temps?.defaultHeatingSetTemperature ?? 20;
167
104
  deviceData.Device.DefaultCoolingSetTemperature = temps?.defaultCoolingSetTemperature ?? 24;
168
105
 
169
- await this.connectSocket(deviceData, devicesData.WsHeaders);
106
+ if (!this.connecting && !this.socketConnected) {
107
+
108
+ this.connecting = true;
109
+ const url = `${ApiUrlsHome.WebSocketURL}${devicesData.wsHeaders.hash}`;
110
+ try {
111
+ const socket = new WebSocket(url, { headers: devicesData.wsHeaders.headers })
112
+ .on('error', (error) => {
113
+ if (this.logError) this.emit('error', `Socket error: ${error}`);
114
+ })
115
+ .on('close', () => {
116
+ if (this.logDebug) this.emit('debug', `Socket closed`);
117
+ this.reconnect();
118
+ })
119
+ .on('open', () => {
120
+ this.socket = socket;
121
+ this.socketConnected = true;
122
+ this.connecting = false;
123
+ this.reconnectDelay = 1000;
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';