homebridge-melcloud-control 4.3.0-beta.0 → 4.3.0-beta.10

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.0-beta.0",
4
+ "version": "4.3.0-beta.10",
5
5
  "description": "Homebridge plugin to control Mitsubishi Air Conditioner, Heat Pump and Energy Recovery Ventilation.",
6
6
  "license": "MIT",
7
7
  "author": "grzegorz914",
@@ -26,6 +26,7 @@ class MelCloudAta extends EventEmitter {
26
26
  //set default values
27
27
  this.deviceData = {};
28
28
  this.headers = {};
29
+ this.hash = null;
29
30
  this.start = true;
30
31
 
31
32
  //lock flag
@@ -60,6 +61,7 @@ class MelCloudAta extends EventEmitter {
60
61
  if (!devicesData) return;
61
62
 
62
63
  this.headers = devicesData.Headers;
64
+ this.hash = devicesData.Hash;
63
65
  const deviceData = devicesData.Devices.find(device => device.DeviceID === this.deviceId);
64
66
  if (this.accountType === 'melcloudhome') {
65
67
  deviceData.Scenes = devicesData.Scenes ?? [];
@@ -73,35 +75,45 @@ class MelCloudAta extends EventEmitter {
73
75
  const temps = await this.functions.readData(this.defaultTempsFile, true);
74
76
  deviceData.Device.DefaultHeatingSetTemperature = temps?.defaultHeatingSetTemperature ?? 20;
75
77
  deviceData.Device.DefaultCoolingSetTemperature = temps?.defaultCoolingSetTemperature ?? 24;
76
- }
77
- if (this.logDebug) this.emit('debug', `Device Data: ${JSON.stringify(deviceData, null, 2)}`);
78
-
79
- if (this.start) {
80
- const hash = '2db32d6f-c19c-4b1f-a0dd-1915420a5152';
81
78
 
82
- const ws = new WebSocket(`wss://ws.melcloudhome.com/?hash=${hash}`, {
83
- headers: {
84
- 'Origin': 'https://melcloudhome.com',
85
- 'User-Agent': this.headers['User-Agent'],
86
- 'Pragma': 'no-cache',
87
- 'Cache-Control': 'no-cache'
88
- }
89
- });
90
- ws.on('open', () => {
91
- if (!this.logDebug) this.emit('warn', `Connected to MelCloudHome WebSocket`);
92
- this.start = false;
93
- })
94
- .on('message', (data) => {
95
- if (!this.logDebug) this.emit('warn', `Incoming message:', data.toString()`);
96
- })
97
- .on('close', () => {
98
- if (!this.logDebug) this.emit('warn', `Connection closed`);
99
- })
100
- .on('error', (error) => {
101
- if (!this.logDebug) this.emit('warn', `Connected error: ${error}`);
79
+ if (this.start) {
80
+ const ws = new WebSocket(`wss://ws.melcloudhome.com/?hash=${devicesData.Hash}`, {
81
+ headers: {
82
+ 'Origin': 'https://melcloudhome.com',
83
+ 'Pragma': 'no-cache',
84
+ 'Cache-Control': 'no-cache'
85
+ }
102
86
  });
103
- }
87
+ ws.on('open', () => {
88
+ if (!this.logDebug) this.emit('warn', `Connected to MelCloudHome WebSocket`);
89
+ this.start = false;
90
+ })
91
+ .on('close', () => {
92
+ if (!this.logDebug) this.emit('warn', `Connection closed`);
93
+ })
94
+ .on('error', (error) => {
95
+ if (!this.logDebug) this.emit('warn', `Connected error: ${error}`);
96
+ })
97
+ .on('message', (message) => {
98
+ if (!this.logDebug) this.emit('warn', `Incoming message:', ${JSON.stringify(message.toString(), null, 2)}`);
99
+
100
+ const messageType = message[0].messageType;
101
+ const messageData = message[0].Data;
102
+ switch (messageType) {
103
+ case 'unitStateChanged':
104
+ const unitId = messageData.id;
105
+ const unitType = messageData.unitType;
106
+ const settings = messageData.settings[0];
107
+ const name = settings.name;
108
+ const value = settings.value;
109
+ if (this.deviceId === unitId) deviceData.Device[name] = value;
110
+ break;
111
+ }
112
+ });
113
+ }
104
114
 
115
+ }
116
+ if (this.logDebug) this.emit('debug', `Device Data: ${JSON.stringify(deviceData, null, 2)}`);
105
117
 
106
118
  //device
107
119
  const serialNumber = deviceData.SerialNumber || '4.0.0';
@@ -23,6 +23,7 @@ class MelCloudHome extends EventEmitter {
23
23
  this.buildingsFile = buildingsFile;
24
24
  this.devicesFile = devicesFile;
25
25
  this.headers = {};
26
+ this.hash = null;
26
27
 
27
28
  this.functions = new Functions(this.logWarn, this.logError, this.logDebug)
28
29
  .on('warn', warn => this.emit('warn', warn))
@@ -208,6 +209,7 @@ class MelCloudHome extends EventEmitter {
208
209
  devicesList.Devices = devices;
209
210
  devicesList.Scenes = scenes;
210
211
  devicesList.Headers = this.headers;
212
+ devicesList.Hash = this.hash;
211
213
 
212
214
  await this.functions.saveData(this.devicesFile, devicesList);
213
215
  if (this.logDebug) this.emit('debug', `${devicesCount} devices saved`);
@@ -276,6 +278,21 @@ class MelCloudHome extends EventEmitter {
276
278
  page.setDefaultTimeout(GLOBAL_TIMEOUT);
277
279
  page.setDefaultNavigationTimeout(GLOBAL_TIMEOUT);
278
280
 
281
+ // === CDP session (modern API) ===
282
+ const client = await page.createCDPSession();
283
+ await client.send('Network.enable')
284
+ client.on('Network.webSocketCreated', ({ url }) => {
285
+ try {
286
+ if (url.startsWith('wss://ws.melcloudhome.com/?hash=')) {
287
+ const params = new URL(url).searchParams;
288
+ this.hash = params.get('hash');
289
+ if (this.logDebug) this.emit('debug', `MelCloudHome WS hash detected: ${melcloudHash}`);
290
+ }
291
+ } catch (err) {
292
+ this.emit('error', `CDP WebSocketCreated handler error: ${err.message}`);
293
+ }
294
+ });
295
+
279
296
  try {
280
297
  await page.goto(ApiUrlsHome.BaseURL, { waitUntil: ['domcontentloaded', 'networkidle2'], timeout: GLOBAL_TIMEOUT });
281
298
  } catch (error) {