homebridge-melcloud-control 4.3.5-beta.9 → 4.3.5

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/CHANGELOG.md CHANGED
@@ -22,11 +22,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
22
22
 
23
23
  - Do not use Homebridge UI > v5.5.0 because of break config.json
24
24
 
25
+ # [4.3.5] - (24.11.2025)
26
+
27
+ ## Changes
28
+
29
+ - removed device refresh time settings
30
+ - stability and performance improvements
31
+ - redme updated
32
+ - cleanup
33
+
25
34
  # [4.3.4] - (23.11.2025)
26
35
 
27
36
  ## Changes
28
37
 
29
- - fix acount monitoring start
38
+ - fix account monitoring start
30
39
  - stability improvements
31
40
  - cleanup
32
41
 
package/README.md CHANGED
@@ -264,7 +264,6 @@ Homebridge plugin for Air Conditioner, Heat Pump and Energy Recovery Ventilation
264
264
  | `ataDevices[].frostProtectionSupport` | This enable extra `Frost Protection` control and sensors to use with automations in HomeKit app. |
265
265
  | `ataDevices[].overheatProtectionSupport` | This enable extra `Overheat Protection` control and sensors to use with automations in HomeKit app. |
266
266
  | `ataDevices[].holidayModeSupport` | This enable extra `Holiday Mode` control and sensors to use with automations in HomeKit app. |
267
- | `ataDevices[].refreshInterval` | Here set the background devices state refresh time in (sec), default `5s`. |
268
267
  | `ataDevices[].presets[]` | Array of ATA device `Presets` created automatically after login to MELCloud from plugin config UI. |
269
268
  | `ataDevices[].presets[].id` | Read only data, do not change it. |
270
269
  | `ataDevices[].presets[].name` | Here You can change the `Preset Name` which is exposed to the `Homebridge/HomeKit`. |
@@ -301,7 +300,6 @@ Homebridge plugin for Air Conditioner, Heat Pump and Energy Recovery Ventilation
301
300
  | `atwDevices[].connectSensor` | This enable `Connect State` sensor to use with automations in HomeKit app. |
302
301
  | `atwDevices[].errorSensor` | This enable `Error` sensors to use with automations in HomeKit app. |
303
302
  | `atwDevices[].holidayModeSupport` | This enable extra `Holiday Mode` control and sensors to use with automations in HomeKit app. |
304
- | `atwDevices[].refreshInterval` | Here set the background devices state refresh time in (sec), default `5s`. |
305
303
  | `atwDevices[].presets[]` | Array of ATW device `Presets` created automatically after login to MELCloud from plugin config UI. |
306
304
  | `atwDevices[].presets[].id` | Read only data, do not change it. |
307
305
  | `atwDevices[].presets[].name` | Here You can change the `Preset Name` which is exposed to the `Homebridge/HomeKit`. |
@@ -331,7 +329,6 @@ Homebridge plugin for Air Conditioner, Heat Pump and Energy Recovery Ventilation
331
329
  | `ervDevices[].connectSensor` | This enable `Connect State` sensor to use with automations in HomeKit app. |
332
330
  | `ervDevices[].errorSensor` | This enable `Error` sensors to use with automations in HomeKit app. |
333
331
  | `ervDevices[].holidayModeSupport` | This enable extra `Holiday Mode` control and sensors to use with automations in HomeKit app. |
334
- | `ervDevices[].refreshInterval` | Here set the background devices state refresh time in (sec), default `5s`. |
335
332
  | `ervDevices[].presets[]` | Array of ERV device `Presets` created automatically after login to MELCloud from plugin config UI. |
336
333
  | `ervDevices[].presets[].id` | Read only data, do not change it. |
337
334
  | `ervDevices[].presets[].name` | Here You can change the `Preset Name` which is exposed to the `Homebridge/HomeKit`. |
@@ -440,14 +440,6 @@
440
440
  "functionBody": "return model.accounts[arrayIndices[0]].type === 'melcloudhome';"
441
441
  }
442
442
  },
443
- "refreshInterval": {
444
- "title": "Refresh Interval",
445
- "type": "integer",
446
- "default": 5,
447
- "minimum": 1,
448
- "maximum": 60,
449
- "description": "Set the background device state refresh time in seconds."
450
- },
451
443
  "presets": {
452
444
  "title": "Presets",
453
445
  "type": "array",
@@ -1296,14 +1288,6 @@
1296
1288
  "functionBody": "return model.accounts[arrayIndices[0]].type === 'melcloudhome';"
1297
1289
  }
1298
1290
  },
1299
- "refreshInterval": {
1300
- "title": "Refresh Interval",
1301
- "type": "integer",
1302
- "default": 5,
1303
- "minimum": 1,
1304
- "maximum": 60,
1305
- "description": "Set the background device state refresh time in seconds."
1306
- },
1307
1291
  "presets": {
1308
1292
  "title": "Presets",
1309
1293
  "type": "array",
@@ -1921,14 +1905,6 @@
1921
1905
  "functionBody": "return model.accounts[arrayIndices[0]].type === 'melcloudhome';"
1922
1906
  }
1923
1907
  },
1924
- "refreshInterval": {
1925
- "title": "Refresh Interval",
1926
- "type": "integer",
1927
- "default": 5,
1928
- "minimum": 1,
1929
- "maximum": 60,
1930
- "description": "Set the background device state refresh time in seconds."
1931
- },
1932
1908
  "presets": {
1933
1909
  "title": "Presets",
1934
1910
  "type": "array",
@@ -2606,8 +2582,7 @@
2606
2582
  "accounts[].ataDevices[].autoDryFanMode",
2607
2583
  "accounts[].ataDevices[].frostProtectionSupport",
2608
2584
  "accounts[].ataDevices[].overheatProtectionSupport",
2609
- "accounts[].ataDevices[].holidayModeSupport",
2610
- "accounts[].ataDevices[].refreshInterval"
2585
+ "accounts[].ataDevices[].holidayModeSupport"
2611
2586
  ],
2612
2587
  "condition": {
2613
2588
  "functionBody": "return model.accounts[arrayIndices[0]].ataDevices[arrayIndices[1]].displayType > 0;"
@@ -2779,8 +2754,7 @@
2779
2754
  "accounts[].atwDevices[].hideZone",
2780
2755
  "accounts[].atwDevices[].name",
2781
2756
  "accounts[].atwDevices[].frostProtectionSupport",
2782
- "accounts[].atwDevices[].holidayModeSupport",
2783
- "accounts[].atwDevices[].refreshInterval"
2757
+ "accounts[].atwDevices[].holidayModeSupport"
2784
2758
  ],
2785
2759
  "condition": {
2786
2760
  "functionBody": "return model.accounts[arrayIndices[0]].atwDevices[arrayIndices[1]].displayType > 0;"
@@ -2957,8 +2931,7 @@
2957
2931
  "expanded": false,
2958
2932
  "items": [
2959
2933
  "accounts[].ervDevices[].name",
2960
- "accounts[].ervDevices[].holidayModeSupport",
2961
- "accounts[].ervDevices[].refreshInterval"
2934
+ "accounts[].ervDevices[].holidayModeSupport"
2962
2935
  ],
2963
2936
  "condition": {
2964
2937
  "functionBody": "return model.accounts[arrayIndices[0]].ervDevices[arrayIndices[1]].displayType > 0;"
@@ -17,8 +17,7 @@ class PluginUiServer extends HomebridgePluginUiServer {
17
17
  const accountName = account.name;
18
18
  const accountFile = `${this.homebridgeStoragePath}/melcloud/${accountName}_Account`;
19
19
  const buildingsFile = `${this.homebridgeStoragePath}/melcloud/${accountName}_Buildings`;
20
- const devicesFile = `${this.homebridgeStoragePath}/melcloud/${accountName}_Devices`;
21
- const melCloud = account.type === 'melcloud' ? new MelCloud(account, accountFile, buildingsFile, devicesFile) : new MelCloudHome(account, accountFile, buildingsFile, devicesFile);
20
+ const melCloud = account.type === 'melcloud' ? new MelCloud(account, accountFile, buildingsFile) : new MelCloudHome(account, accountFile, buildingsFile);
22
21
 
23
22
  try {
24
23
  const accountInfo = await melCloud.connect();
package/index.js CHANGED
@@ -74,10 +74,9 @@ class MelCloudPlatform {
74
74
  //define directory and file paths
75
75
  const accountFile = `${prefDir}/${accountName}_Account`;
76
76
  const buildingsFile = `${prefDir}/${accountName}_Buildings`;
77
- const devicesFile = `${prefDir}/${accountName}_Devices`;
78
77
 
79
78
  //set account refresh interval
80
- const refreshInterval = (account.refreshInterval ?? 120) * 1000
79
+ const accountRefreshInterval = (account.refreshInterval ?? 120) * 1000
81
80
 
82
81
  try {
83
82
  //create impulse generator
@@ -89,12 +88,12 @@ class MelCloudPlatform {
89
88
  let timmers = []
90
89
  switch (account.type) {
91
90
  case 'melcloud':
92
- timmers = [{ name: 'checkDevicesList', sampling: refreshInterval }];
93
- melcloud = new MelCloud(account, accountFile, buildingsFile, devicesFile, true);
91
+ timmers = [{ name: 'checkDevicesList', sampling: accountRefreshInterval }];
92
+ melcloud = new MelCloud(account, accountFile, buildingsFile, true);
94
93
  break;
95
94
  case 'melcloudhome':
96
95
  timmers = [{ name: 'connect', sampling: 3300000 }, { name: 'checkDevicesList', sampling: 3000 }];
97
- melcloud = new MelCloudHome(account, accountFile, buildingsFile, devicesFile, true);
96
+ melcloud = new MelCloudHome(account, accountFile, buildingsFile, true);
98
97
  break;
99
98
  default:
100
99
  if (logLevel.warn) log.warn(`Unknown account type: ${account.type}.`);
@@ -118,21 +117,22 @@ class MelCloudPlatform {
118
117
  if (logLevel.error) log.error(`${accountName}, Connect error: ${error.message ?? error}`);
119
118
  return;
120
119
  }
121
- if (logLevel.success) log.success(accountInfo.Info);
120
+ if (logLevel.success) log.success(`${accountName}, ${accountInfo.Info}`);
122
121
 
123
122
  //check devices list
124
- let devicesList;
123
+ let melcloudDevicesList;
125
124
  try {
126
- devicesList = await melcloud.checkDevicesList();
127
- if (!devicesList.State) {
128
- if (logLevel.warn) log.warn(`${accountName}, ${devicesList.Info}`);
125
+ melcloudDevicesList = await melcloud.checkDevicesList();
126
+ if (!melcloudDevicesList.State) {
127
+ if (logLevel.warn) log.warn(`${accountName}, ${melcloudDevicesList.Info}`);
129
128
  return;
130
129
  }
131
130
  } catch (error) {
132
131
  if (logLevel.error) log.error(`${accountName}, Check devices list error: ${error.message ?? error}`);
133
132
  return;
134
133
  }
135
- if (logLevel.debug) log.info(devicesList.Info);
134
+ if (logLevel.debug) log.info(melcloudDevicesList.Info);
135
+ await new Promise(r => setTimeout(r, 1000));
136
136
 
137
137
  //configured devices
138
138
  const ataDevices = (account.ataDevices || []).filter(device => device.id != null && String(device.id) !== '0');
@@ -144,14 +144,13 @@ class MelCloudPlatform {
144
144
  for (const [index, device] of devices.entries()) {
145
145
  //chack device from config exist on melcloud
146
146
  const displayType = device.displayType > 0;
147
- const deviceExistInMelCloud = devicesList.Devices.some(dev => dev.DeviceID === device.id);
147
+ const deviceExistInMelCloud = melcloudDevicesList.Devices.some(dev => dev.DeviceID === device.id);
148
148
  if (!deviceExistInMelCloud || !displayType) continue;
149
149
 
150
150
  device.id = String(device.id);
151
151
  const deviceName = device.name;
152
152
  const deviceType = device.type;
153
153
  const deviceTypeString = device.typeString;
154
- const deviceRefreshInterval = (device.refreshInterval ?? 5) * 1000;
155
154
  const defaultTempsFile = `${prefDir}/${accountName}_${device.id}_Temps`;
156
155
 
157
156
  // set rest ful port
@@ -179,15 +178,15 @@ class MelCloudPlatform {
179
178
  let configuredDevice;
180
179
  switch (deviceType) {
181
180
  case 0: //ATA
182
- configuredDevice = new DeviceAta(api, account, device, devicesFile, defaultTempsFile, accountInfo, accountFile, melcloud);
181
+ configuredDevice = new DeviceAta(api, account, device, defaultTempsFile, accountInfo, accountFile, melcloud, melcloudDevicesList);
183
182
  break;
184
183
  case 1: //ATW
185
- configuredDevice = new DeviceAtw(api, account, device, devicesFile, defaultTempsFile, accountInfo, accountFile, melcloud);
184
+ configuredDevice = new DeviceAtw(api, account, device, defaultTempsFile, accountInfo, accountFile, melcloud, melcloudDevicesList);
186
185
  break;
187
186
  case 2:
188
187
  break;
189
188
  case 3: //ERV
190
- configuredDevice = new DeviceErv(api, account, device, devicesFile, defaultTempsFile, accountInfo, accountFile, melcloud);
189
+ configuredDevice = new DeviceErv(api, account, device, defaultTempsFile, accountInfo, accountFile, melcloud, melcloudDevicesList);
191
190
  break;
192
191
  default:
193
192
  if (logLevel.warn) log.warn(`${accountName}, ${deviceTypeString}, ${deviceName}, unknown device: ${deviceType}.`);
@@ -208,11 +207,11 @@ class MelCloudPlatform {
208
207
  }
209
208
  }
210
209
 
211
- //start account impulse generator
212
- await melcloud.impulseGenerator.state(true, timmers, false);
213
-
214
210
  //stop start impulse generator
215
211
  await impulseGenerator.state(false);
212
+
213
+ //start account impulse generator
214
+ await melcloud.impulseGenerator.state(true, timmers, false);
216
215
  } catch (error) {
217
216
  if (logLevel.error) log.error(`${accountName}, Start impulse generator error, ${error.message ?? error}, trying again.`);
218
217
  }
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.5-beta.9",
4
+ "version": "4.3.5",
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/deviceata.js CHANGED
@@ -7,7 +7,7 @@ import { TemperatureDisplayUnits, AirConditioner } from './constants.js';
7
7
  let Accessory, Characteristic, Service, Categories, AccessoryUUID;
8
8
 
9
9
  class DeviceAta extends EventEmitter {
10
- constructor(api, account, device, devicesFile, defaultTempsFile, accountInfo, accountFile, melcloud) {
10
+ constructor(api, account, device, defaultTempsFile, accountInfo, accountFile, melcloud, melcloudDevicesList) {
11
11
  super();
12
12
 
13
13
  Accessory = api.platformAccessory;
@@ -18,6 +18,7 @@ class DeviceAta extends EventEmitter {
18
18
 
19
19
  //account config
20
20
  this.melcloud = melcloud;
21
+ this.melcloudDevicesList = melcloudDevicesList;
21
22
  this.account = account;
22
23
  this.accountType = account.type;
23
24
  this.accountName = account.name;
@@ -49,7 +50,6 @@ class DeviceAta extends EventEmitter {
49
50
  this.buttons = (device.buttonsSensors || []).filter(button => (button.displayType ?? 0) > 0);
50
51
 
51
52
  //files
52
- this.devicesFile = devicesFile;
53
53
  this.defaultTempsFile = defaultTempsFile;
54
54
  this.accountInfo = accountInfo;
55
55
  this.accountFile = accountFile;
@@ -1321,7 +1321,7 @@ class DeviceAta extends EventEmitter {
1321
1321
  async start() {
1322
1322
  try {
1323
1323
  //melcloud device
1324
- this.melCloudAta = new MelCloudAta(this.account, this.device, this.devicesFile, this.defaultTempsFile, this.accountFile, this.melcloud)
1324
+ this.melCloudAta = new MelCloudAta(this.account, this.device, this.defaultTempsFile, this.accountFile, this.melcloud)
1325
1325
  .on('deviceInfo', (modelIndoor, modelOutdoor, serialNumber, firmwareAppVersion) => {
1326
1326
  if (this.logDeviceInfo && this.displayDeviceInfo) {
1327
1327
  this.emit('devInfo', `---- ${this.deviceTypeString}: ${this.deviceName} ----`);
@@ -1878,9 +1878,10 @@ class DeviceAta extends EventEmitter {
1878
1878
  if (this.restFul.enable || this.mqtt.enable) await this.externalIntegrations();
1879
1879
 
1880
1880
  //check state
1881
- await this.melCloudAta.updateState();
1881
+ await this.melCloudAta.checkState(this.melcloudDevicesList);
1882
1882
 
1883
1883
  //prepare accessory
1884
+ await new Promise(r => setTimeout(r, 5000));
1884
1885
  const accessory = await this.prepareAccessory();
1885
1886
  return accessory;
1886
1887
  } catch (error) {
package/src/deviceatw.js CHANGED
@@ -7,7 +7,7 @@ import { TemperatureDisplayUnits, HeatPump } from './constants.js';
7
7
  let Accessory, Characteristic, Service, Categories, AccessoryUUID;
8
8
 
9
9
  class DeviceAtw extends EventEmitter {
10
- constructor(api, account, device, devicesFile, defaultTempsFile, accountInfo, accountFile, melcloud) {
10
+ constructor(api, account, device, defaultTempsFile, accountInfo, accountFile, melcloud, melcloudDevicesList) {
11
11
  super();
12
12
 
13
13
  Accessory = api.platformAccessory;
@@ -18,6 +18,7 @@ class DeviceAtw extends EventEmitter {
18
18
 
19
19
  //account config
20
20
  this.melcloud = melcloud;
21
+ this.melcloudDevicesList = melcloudDevicesList;
21
22
  this.account = account;
22
23
  this.accountType = account.type;
23
24
  this.accountName = account.name;
@@ -53,7 +54,6 @@ class DeviceAtw extends EventEmitter {
53
54
  this.buttons = (device.buttonsSensors || []).filter(button => (button.displayType ?? 0) > 0);
54
55
 
55
56
  //files
56
- this.devicesFile = devicesFile;
57
57
  this.defaultTempsFile = defaultTempsFile;
58
58
  this.accountInfo = accountInfo;
59
59
  this.accountFile = accountFile;
@@ -1567,7 +1567,7 @@ class DeviceAtw extends EventEmitter {
1567
1567
  async start() {
1568
1568
  try {
1569
1569
  //melcloud device
1570
- this.melCloudAtw = new MelCloudAtw(this.account, this.device, this.devicesFile, this.defaultTempsFile, this.accountFile, this.melcloud)
1570
+ this.melCloudAtw = new MelCloudAtw(this.account, this.device, this.defaultTempsFile, this.accountFile, this.melcloud)
1571
1571
  .on('deviceInfo', (modelIndoor, modelOutdoor, serialNumber, firmwareAppVersion, supportsHotWaterTank, supportsZone2) => {
1572
1572
  if (this.logDeviceInfo && this.displayDeviceInfo) {
1573
1573
  this.emit('devInfo', `---- ${this.deviceTypeString}: ${this.deviceName} ----`);
@@ -2307,9 +2307,10 @@ class DeviceAtw extends EventEmitter {
2307
2307
  if (this.restFul.enable || this.mqtt.enable) await this.externalIntegrations();
2308
2308
 
2309
2309
  //check state
2310
- await this.melCloudAtw.updateState();
2310
+ await this.melCloudAta.checkState(this.melcloudDevicesList);
2311
2311
 
2312
2312
  //prepare accessory
2313
+ await new Promise(r => setTimeout(r, 1000));
2313
2314
  const accessory = await this.prepareAccessory();
2314
2315
  return accessory;
2315
2316
  } catch (error) {
package/src/deviceerv.js CHANGED
@@ -7,7 +7,7 @@ import { TemperatureDisplayUnits, Ventilation } from './constants.js';
7
7
  let Accessory, Characteristic, Service, Categories, AccessoryUUID;
8
8
 
9
9
  class DeviceErv extends EventEmitter {
10
- constructor(api, account, device, devicesFile, defaultTempsFile, accountInfo, accountFile, melcloud) {
10
+ constructor(api, account, device, defaultTempsFile, accountInfo, accountFile, melcloud, melcloudDevicesList) {
11
11
  super();
12
12
 
13
13
  Accessory = api.platformAccessory;
@@ -18,6 +18,7 @@ class DeviceErv extends EventEmitter {
18
18
 
19
19
  //account config
20
20
  this.melcloud = melcloud;
21
+ this.melcloudDevicesList = melcloudDevicesList;
21
22
  this.account = account;
22
23
  this.accountType = account.type;
23
24
  this.accountName = account.name;
@@ -45,7 +46,6 @@ class DeviceErv extends EventEmitter {
45
46
  this.buttons = (device.buttonsSensors || []).filter(button => (button.displayType ?? 0) > 0);
46
47
 
47
48
  //files
48
- this.devicesFile = devicesFile;
49
49
  this.defaultTempsFile = defaultTempsFile;
50
50
  this.accountInfo = accountInfo;
51
51
  this.accountFile = accountFile;
@@ -1121,7 +1121,7 @@ class DeviceErv extends EventEmitter {
1121
1121
  async start() {
1122
1122
  try {
1123
1123
  //melcloud device
1124
- this.melCloudErv = new MelCloudErv(this.account, this.device, this.devicesFile, this.defaultTempsFile, this.accountFile, this.melcloud)
1124
+ this.melCloudErv = new MelCloudErv(this.account, this.device, this.defaultTempsFile, this.accountFile, this.melcloud)
1125
1125
  .on('deviceInfo', (modelIndoor, modelOutdoor, serialNumber, firmwareAppVersion) => {
1126
1126
  if (this.logDeviceInfo && this.displayDeviceInfo) {
1127
1127
  this.emit('devInfo', `---- ${this.deviceTypeString}: ${this.deviceName} ----`);
@@ -1581,9 +1581,10 @@ class DeviceErv extends EventEmitter {
1581
1581
  if (this.restFul.enable || this.mqtt.enable) await this.externalIntegrations();
1582
1582
 
1583
1583
  //check state
1584
- await this.melCloudErv.updateState();
1584
+ await this.melCloudAta.checkState(this.melcloudDevicesList);
1585
1585
 
1586
1586
  //prepare accessory
1587
+ await new Promise(r => setTimeout(r, 1000));
1587
1588
  const accessory = await this.prepareAccessory();
1588
1589
  return accessory;
1589
1590
  } catch (error) {
package/src/melcloud.js CHANGED
@@ -5,7 +5,7 @@ import Functions from './functions.js';
5
5
  import { ApiUrls } from './constants.js';
6
6
 
7
7
  class MelCloud extends EventEmitter {
8
- constructor(account, accountFile, buildingsFile, devicesFile, pluginStart = false) {
8
+ constructor(account, accountFile, buildingsFile, pluginStart = false) {
9
9
  super();
10
10
  this.accountType = account.type;
11
11
  this.user = account.user;
@@ -14,9 +14,9 @@ class MelCloud extends EventEmitter {
14
14
  this.logWarn = account.log?.warn;
15
15
  this.logError = account.log?.error;
16
16
  this.logDebug = account.log?.debug;
17
+
17
18
  this.accountFile = accountFile;
18
19
  this.buildingsFile = buildingsFile;
19
- this.devicesFile = devicesFile;
20
20
  this.headers = {};
21
21
 
22
22
  this.functions = new Functions(this.logWarn, this.logError, this.logDebug)
@@ -112,9 +112,6 @@ class MelCloud extends EventEmitter {
112
112
  devicesList.Headers = this.headers;
113
113
  this.emit('devicesList', devicesList);
114
114
 
115
- await this.functions.saveData(this.devicesFile, devicesList);
116
- if (this.logDebug) this.emit('debug', `${devicesCount} devices saved`);
117
-
118
115
  return devicesList;
119
116
  } catch (error) {
120
117
  throw new Error(`Check devices list error: ${error.message}`);
@@ -174,7 +171,7 @@ class MelCloud extends EventEmitter {
174
171
  });
175
172
 
176
173
  accountInfo.State = true;
177
- accountInfo.Info = 'Connect to MELCloud Success';
174
+ accountInfo.Info = 'Connect Success';
178
175
  accountInfo.UseFahrenheit = loginData.UseFahrenheit;
179
176
  accountInfo.Account = account;
180
177
  await this.functions.saveData(this.accountFile, accountInfo);
@@ -4,7 +4,7 @@ import Functions from './functions.js';
4
4
  import { ApiUrls, ApiUrlsHome, AirConditioner } from './constants.js';
5
5
 
6
6
  class MelCloudAta extends EventEmitter {
7
- constructor(account, device, devicesFile, defaultTempsFile, accountFile, melcloud) {
7
+ constructor(account, device, defaultTempsFile, accountFile, melcloud) {
8
8
  super();
9
9
  this.accountType = account.type;
10
10
  this.logSuccess = account.log?.success;
@@ -14,9 +14,9 @@ class MelCloudAta extends EventEmitter {
14
14
  this.restFulEnabled = account.restFul?.enable;
15
15
  this.mqttEnabled = account.mqtt?.enable;
16
16
  this.deviceId = device.id;
17
- this.devicesFile = devicesFile;
18
17
  this.defaultTempsFile = defaultTempsFile;
19
18
  this.accountFile = accountFile;
19
+
20
20
  this.functions = new Functions(this.logWarn, this.logError, this.logDebug)
21
21
  .on('warn', warn => this.emit('warn', warn))
22
22
  .on('error', error => this.emit('error', error))
@@ -24,7 +24,7 @@ class MelCloudAta extends EventEmitter {
24
24
 
25
25
  //set default values
26
26
  this.deviceData = {};
27
- this.headers = {};
27
+ this.headers = {}
28
28
 
29
29
  let deviceData = null;
30
30
  melcloud.on('devicesList', async (devicesData) => {
@@ -35,73 +35,63 @@ class MelCloudAta extends EventEmitter {
35
35
 
36
36
  //update state
37
37
  await this.updateState(deviceData);
38
- });
39
-
40
- //web cocket message
41
- if (this.accountType === 'melcloudhome') {
38
+ }).on('webSocket', async (parsedMessage) => {
42
39
  try {
43
- melcloud.webSocket.on('message', async (message) => {
44
- const parsedMessage = JSON.parse(message);
45
- const stringifyMessage = JSON.stringify(parsedMessage, null, 2);
46
- if (parsedMessage.message === 'Forbidden') return;
47
-
48
- const messageData = parsedMessage?.[0]?.Data;
49
- if (!messageData || !deviceData) return;
50
-
51
- let updateState = false;
52
- const unitId = messageData?.id;
53
- switch (unitId) {
54
- case this.deviceId:
55
- if (!this.logDebug) this.emit('debug', `Incoming message: ${stringifyMessage}`);
56
- const messageType = parsedMessage[0].messageType;
57
- const settings = this.functions.parseArrayNameValue(messageData.settings);
58
- switch (messageType) {
59
- case 'unitStateChanged':
60
-
61
- //update values
62
- for (const [key, value] of Object.entries(settings)) {
63
- if (!this.functions.isValidValue(value)) continue;
64
-
65
- //update holiday mode
66
- if (key === 'HolidayMode') {
67
- deviceData.HolidayMode.Enabled = value;
68
- continue;
69
- }
70
-
71
- //update device settings
72
- if (key in deviceData.Device) {
73
- deviceData.Device[key] = value;
74
- }
40
+ const messageData = parsedMessage?.[0]?.Data;
41
+ if (!messageData || !deviceData) return;
42
+
43
+ let updateState = false;
44
+ const unitId = messageData?.id;
45
+ switch (unitId) {
46
+ case this.deviceId:
47
+ const messageType = parsedMessage[0].messageType;
48
+ const settings = this.functions.parseArrayNameValue(messageData.settings);
49
+ switch (messageType) {
50
+ case 'unitStateChanged':
51
+
52
+ //update values
53
+ for (const [key, value] of Object.entries(settings)) {
54
+ if (!this.functions.isValidValue(value)) continue;
55
+
56
+ //update holiday mode
57
+ if (key === 'HolidayMode') {
58
+ deviceData.HolidayMode.Enabled = value;
59
+ continue;
75
60
  }
76
- updateState = true;
77
- break;
78
- case 'unitHolidayModeTriggered':
79
- deviceData.Device.Power = settings.Power;
80
- deviceData.HolidayMode.Enabled = settings.HolidayMode;
81
- deviceData.HolidayMode.Active = messageData.active;
82
- updateState = true;
83
- break;
84
- case 'unitWifiSignalChanged':
85
- deviceData.Rssi = messageData.rssi;
86
- updateState = true;
87
- break;
88
- default:
89
- if (this.logDebug) this.emit('debug', `Unit ${unitId}, received unknown message type: ${stringifyMessage}`);
90
- return;
91
- }
92
- break;
93
- default:
94
- if (this.logDebug) this.emit('debug', `Incoming unknown unit id: ${stringifyMessage}`);
95
- return;
96
- }
97
61
 
98
- //update state
99
- if (updateState) await this.updateState(deviceData);
100
- });
62
+ //update device settings
63
+ if (key in deviceData.Device) {
64
+ deviceData.Device[key] = value;
65
+ }
66
+ }
67
+ updateState = true;
68
+ break;
69
+ case 'unitHolidayModeTriggered':
70
+ deviceData.Device.Power = settings.Power;
71
+ deviceData.HolidayMode.Enabled = settings.HolidayMode;
72
+ deviceData.HolidayMode.Active = messageData.active;
73
+ updateState = true;
74
+ break;
75
+ case 'unitWifiSignalChanged':
76
+ deviceData.Rssi = messageData.rssi;
77
+ updateState = true;
78
+ break;
79
+ default:
80
+ if (this.logDebug) this.emit('debug', `Unit ${unitId}, received unknown message type: ${stringifyMessage}`);
81
+ return;
82
+ }
83
+ break;
84
+ default:
85
+ if (this.logDebug) this.emit('debug', `Incoming unknown unit id: ${stringifyMessage}`);
86
+ return;
87
+ }
88
+
89
+ //update state
90
+ if (updateState) await this.updateState(deviceData);
101
91
  } catch (error) {
102
- if (this.logError) this.emit('error', `Socket connection failed: ${error}`);
92
+ if (this.logError) this.emit('error', `Web socket process message error: ${error}`);
103
93
  }
104
- }
94
+ });
105
95
  }
106
96
 
107
97
  async updateState(deviceData) {
@@ -177,6 +167,19 @@ class MelCloudAta extends EventEmitter {
177
167
  };
178
168
  };
179
169
 
170
+ async checkState(devicesData) {
171
+ try {
172
+ this.headers = devicesData.Headers;
173
+ const deviceData = devicesData.Devices.find(device => device.DeviceID === this.deviceId);
174
+ deviceData.Scenes = devicesData.Scenes ?? [];
175
+ await this.updateState(deviceData);
176
+
177
+ return true;
178
+ } catch (error) {
179
+ throw new Error(`Chaeck state error: ${error.message}`);
180
+ };
181
+ }
182
+
180
183
  async send(accountType, displayType, deviceData, flag, flagData) {
181
184
  try {
182
185
  let method = null
@@ -229,6 +232,7 @@ class MelCloudAta extends EventEmitter {
229
232
  data: payload
230
233
  });
231
234
 
235
+ this.emit('deviceState', deviceData);
232
236
  return true;
233
237
  case "melcloudhome":
234
238
  switch (flag) {
@@ -4,7 +4,7 @@ import Functions from './functions.js';
4
4
  import { ApiUrls, ApiUrlsHome, HeatPump } from './constants.js';
5
5
 
6
6
  class MelCloudAtw extends EventEmitter {
7
- constructor(account, device, devicesFile, defaultTempsFile, accountFile, melcloud) {
7
+ constructor(account, device, defaultTempsFile, accountFile, melcloud) {
8
8
  super();
9
9
  this.accountType = account.type;
10
10
  this.logSuccess = account.log?.success;
@@ -14,9 +14,9 @@ class MelCloudAtw extends EventEmitter {
14
14
  this.restFulEnabled = account.restFul?.enable;
15
15
  this.mqttEnabled = account.mqtt?.enable;
16
16
  this.deviceId = device.id;
17
- this.devicesFile = devicesFile;
18
17
  this.defaultTempsFile = defaultTempsFile;
19
18
  this.accountFile = accountFile;
19
+
20
20
  this.functions = new Functions(this.logWarn, this.logError, this.logDebug)
21
21
  .on('warn', warn => this.emit('warn', warn))
22
22
  .on('error', error => this.emit('error', error))
@@ -35,58 +35,59 @@ class MelCloudAtw extends EventEmitter {
35
35
 
36
36
  //update state
37
37
  await this.updateState(deviceData);
38
- });
39
-
40
- ///web cocket message
41
- if (this.accountType === 'melcloudhome') {
38
+ }).on('message', async (message) => {
42
39
  try {
43
- melcloud.webSocket.on('message', async (message) => {
44
- const parsedMessage = JSON.parse(message);
45
- const stringifyMessage = JSON.stringify(parsedMessage, null, 2);
46
- if (this.logDebug) this.emit('debug', `Incoming message: ${stringifyMessage}`);
47
- if (parsedMessage.message === 'Forbidden') return;
40
+ const parsedMessage = JSON.parse(message);
41
+ const stringifyMessage = JSON.stringify(parsedMessage, null, 2);
42
+ if (this.logDebug) this.emit('debug', `Incoming message: ${stringifyMessage}`);
43
+ if (parsedMessage.message === 'Forbidden') return;
48
44
 
49
- const messageData = parsedMessage?.[0]?.Data;
50
- if (!messageData || !deviceData) return;
45
+ const messageData = parsedMessage?.[0]?.Data;
46
+ if (!messageData || !deviceData) return;
51
47
 
52
- let updateState = false;
53
- const unitId = messageData?.id;
54
- switch (unitId) {
55
- case this.deviceId:
56
- const messageType = parsedMessage[0].messageType;
57
- switch (messageType) {
58
- case 'unitStateChanged':
59
- const settings = Object.fromEntries(
60
- messageData.settings.map(({ name, value }) => {
61
- let parsedValue = this.functions.convertValue(value);
62
- return [name, parsedValue];
63
- })
64
- );
65
- Object.assign(deviceData.Device, settings);
66
- updateState = true;
67
- break;
68
- case 'unitWifiSignalChanged':
69
- deviceData.Rssi = messageData.rssi;
70
- updateState = true;
71
- break;
72
- default:
73
- if (this.logDebug) this.emit('debug', `Unit ${unitId}, received unknown message type: ${stringifyMessage}`);
74
- return;
75
- }
76
- break;
77
- default:
78
- if (this.logDebug) this.emit('debug', `Incoming unknown unit id: ${stringifyMessage}`);
79
- return;
80
- }
48
+ let updateState = false;
49
+ const unitId = messageData?.id;
50
+ switch (unitId) {
51
+ case this.deviceId:
52
+ const messageType = parsedMessage[0].messageType;
53
+ switch (messageType) {
54
+ case 'unitStateChanged':
55
+ const settings = Object.fromEntries(
56
+ messageData.settings.map(({ name, value }) => {
57
+ let parsedValue = this.functions.convertValue(value);
58
+ return [name, parsedValue];
59
+ })
60
+ );
61
+ Object.assign(deviceData.Device, settings);
62
+ updateState = true;
63
+ break;
64
+ case 'unitHolidayModeTriggered':
65
+ deviceData.Device.Power = settings.Power;
66
+ deviceData.HolidayMode.Enabled = settings.HolidayMode;
67
+ deviceData.HolidayMode.Active = messageData.active;
68
+ updateState = true;
69
+ break;
70
+ case 'unitWifiSignalChanged':
71
+ deviceData.Rssi = messageData.rssi;
72
+ updateState = true;
73
+ break;
74
+ default:
75
+ if (this.logDebug) this.emit('debug', `Unit ${unitId}, received unknown message type: ${stringifyMessage}`);
76
+ return;
77
+ }
78
+ break;
79
+ default:
80
+ if (this.logDebug) this.emit('debug', `Incoming unknown unit id: ${stringifyMessage}`);
81
+ return;
82
+ }
81
83
 
82
- //update state
83
- if (updateState) await this.updateState(deviceData);
84
- });
84
+ //update state
85
+ if (updateState) await this.updateState(deviceData);
85
86
  } catch (error) {
86
- if (this.logError) this.emit('error', `Socket connection failed: ${error}`);
87
- this.cleanupSocket();
87
+ if (this.logError) this.emit('error', `Web socket process message error: ${error}`);
88
88
  }
89
- }
89
+ });
90
+
90
91
  }
91
92
 
92
93
  async updateState(deviceData) {
@@ -156,6 +157,19 @@ class MelCloudAtw extends EventEmitter {
156
157
  };
157
158
  };
158
159
 
160
+ async checkState(devicesData) {
161
+ try {
162
+ this.headers = devicesData.Headers;
163
+ const deviceData = devicesData.Devices.find(device => device.DeviceID === this.deviceId);
164
+ deviceData.Scenes = devicesData.Scenes ?? [];
165
+ await this.updateState(deviceData);
166
+
167
+ return true;
168
+ } catch (error) {
169
+ throw new Error(`Chaeck state error: ${error.message}`);
170
+ };
171
+ }
172
+
159
173
  async send(accountType, displayType, deviceData, flag, flagData) {
160
174
  try {
161
175
 
@@ -223,6 +237,7 @@ class MelCloudAtw extends EventEmitter {
223
237
  data: payload
224
238
  });
225
239
 
240
+ this.emit('deviceState', deviceData);
226
241
  return true;
227
242
  case "melcloudhome":
228
243
  switch (flag) {
@@ -4,7 +4,7 @@ import Functions from './functions.js';
4
4
  import { ApiUrls, ApiUrlsHome, Ventilation } from './constants.js';
5
5
 
6
6
  class MelCloudErv extends EventEmitter {
7
- constructor(account, device, devicesFile, defaultTempsFile, accountFile, melcloud) {
7
+ constructor(account, device, defaultTempsFile, accountFile, melcloud) {
8
8
  super();
9
9
  this.accountType = account.type;
10
10
  this.logSuccess = account.log?.success;
@@ -14,9 +14,9 @@ class MelCloudErv extends EventEmitter {
14
14
  this.restFulEnabled = account.restFul?.enable;
15
15
  this.mqttEnabled = account.mqtt?.enable;
16
16
  this.deviceId = device.id;
17
- this.devicesFile = devicesFile;
18
17
  this.defaultTempsFile = defaultTempsFile;
19
18
  this.accountFile = accountFile;
19
+
20
20
  this.functions = new Functions(this.logWarn, this.logError, this.logDebug)
21
21
  .on('warn', warn => this.emit('warn', warn))
22
22
  .on('error', error => this.emit('error', error))
@@ -35,14 +35,68 @@ class MelCloudErv extends EventEmitter {
35
35
 
36
36
  //update state
37
37
  await this.updateState(deviceData);
38
- }); this.firstRun = true;
38
+ }).on('webSocket', async (parsedMessage) => {
39
+ try {
40
+ const messageData = parsedMessage?.[0]?.Data;
41
+ if (!messageData || !deviceData) return;
42
+
43
+ let updateState = false;
44
+ const unitId = messageData?.id;
45
+ switch (unitId) {
46
+ case this.deviceId:
47
+ const messageType = parsedMessage[0].messageType;
48
+ const settings = this.functions.parseArrayNameValue(messageData.settings);
49
+ switch (messageType) {
50
+ case 'unitStateChanged':
51
+
52
+ //update values
53
+ for (const [key, value] of Object.entries(settings)) {
54
+ if (!this.functions.isValidValue(value)) continue;
55
+
56
+ //update holiday mode
57
+ if (key === 'HolidayMode') {
58
+ deviceData.HolidayMode.Enabled = value;
59
+ continue;
60
+ }
61
+
62
+ //update device settings
63
+ if (key in deviceData.Device) {
64
+ deviceData.Device[key] = value;
65
+ }
66
+ }
67
+ updateState = true;
68
+ break;
69
+ case 'unitHolidayModeTriggered':
70
+ deviceData.Device.Power = settings.Power;
71
+ deviceData.HolidayMode.Enabled = settings.HolidayMode;
72
+ deviceData.HolidayMode.Active = messageData.active;
73
+ updateState = true;
74
+ break;
75
+ case 'unitWifiSignalChanged':
76
+ deviceData.Rssi = messageData.rssi;
77
+ updateState = true;
78
+ break;
79
+ default:
80
+ if (this.logDebug) this.emit('debug', `Unit ${unitId}, received unknown message type: ${stringifyMessage}`);
81
+ return;
82
+ }
83
+ break;
84
+ default:
85
+ if (this.logDebug) this.emit('debug', `Incoming unknown unit id: ${stringifyMessage}`);
86
+ return;
87
+ }
88
+
89
+ //update state
90
+ if (updateState) await this.updateState(deviceData);
91
+ } catch (error) {
92
+ if (this.logError) this.emit('error', `Web socket process message error: ${error}`);
93
+ }
94
+ });
39
95
  }
40
96
 
41
97
  async updateState(deviceData) {
42
98
  try {
43
99
  if (this.accountType === 'melcloudhome') {
44
- deviceData.Scenes = devicesData.Scenes ?? [];
45
-
46
100
  //read default temps
47
101
  const temps = await this.functions.readData(this.defaultTempsFile, true);
48
102
  deviceData.Device.DefaultHeatingSetTemperature = temps?.defaultHeatingSetTemperature ?? 20;
@@ -106,6 +160,19 @@ class MelCloudErv extends EventEmitter {
106
160
  };
107
161
  };
108
162
 
163
+ async checkState(devicesData) {
164
+ try {
165
+ this.headers = devicesData.Headers;
166
+ const deviceData = devicesData.Devices.find(device => device.DeviceID === this.deviceId);
167
+ deviceData.Scenes = devicesData.Scenes ?? [];
168
+ await this.updateState(deviceData);
169
+
170
+ return true;
171
+ } catch (error) {
172
+ throw new Error(`Chaeck state error: ${error.message}`);
173
+ };
174
+ }
175
+
109
176
  async send(accountType, displayType, deviceData, flag, flagData) {
110
177
  try {
111
178
  let method = null
@@ -174,6 +241,7 @@ class MelCloudErv extends EventEmitter {
174
241
  data: payload
175
242
  });
176
243
 
244
+ this.emit('deviceState', deviceData);
177
245
  return true;
178
246
  case "melcloudhome":
179
247
  switch (flag) {
@@ -11,7 +11,7 @@ import { ApiUrlsHome, LanguageLocaleMap } from './constants.js';
11
11
  const execPromise = promisify(exec);
12
12
 
13
13
  class MelCloudHome extends EventEmitter {
14
- constructor(account, accountFile, buildingsFile, devicesFile, pluginStart = false) {
14
+ constructor(account, accountFile, buildingsFile, pluginStart = false) {
15
15
  super();
16
16
  this.accountType = account.type;
17
17
  this.user = account.user;
@@ -23,7 +23,7 @@ class MelCloudHome extends EventEmitter {
23
23
  this.logDebug = account.log?.debug;
24
24
  this.accountFile = accountFile;
25
25
  this.buildingsFile = buildingsFile;
26
- this.devicesFile = devicesFile;
26
+
27
27
  this.headers = {};
28
28
  this.webSocketOptions = {};
29
29
  this.socket = null;
@@ -252,8 +252,10 @@ class MelCloudHome extends EventEmitter {
252
252
  })
253
253
  .on('message', (message) => {
254
254
  const parsedMessage = JSON.parse(message);
255
- const stringifyMessage = JSON.stringify(parsedMessage, null, 2);
256
- if (this.logDebug) this.emit('debug', `Incoming message: ${stringifyMessage}`);
255
+ if (this.logDebug) this.emit('debug', `Incoming message: ${JSON.stringify(parsedMessage, null, 2)}`);
256
+ if (parsedMessage.message === 'Forbidden') return;
257
+
258
+ this.emit('webSocket', parsedMessage);
257
259
  });
258
260
  } catch (error) {
259
261
  if (this.logError) this.emit('error', `Socket connection failed: ${error}`);
@@ -266,12 +268,8 @@ class MelCloudHome extends EventEmitter {
266
268
  devicesList.Devices = devices;
267
269
  devicesList.Scenes = scenes;
268
270
  devicesList.Headers = this.headers;
269
- devicesList.WebSocket = this.socket;
270
271
  this.emit('devicesList', devicesList);
271
272
 
272
- await this.functions.saveData(this.devicesFile, devicesList);
273
- if (this.logDebug) this.emit('debug', `${devicesCount} devices saved`);
274
-
275
273
  return devicesList;
276
274
  } catch (error) {
277
275
  throw new Error(`Check devices list error: ${error.message}`);
@@ -442,7 +440,7 @@ class MelCloudHome extends EventEmitter {
442
440
  };
443
441
 
444
442
  accountInfo.State = true;
445
- accountInfo.Info = 'Connect to MELCloud Home Success';
443
+ accountInfo.Info = 'Connect Success';
446
444
  await this.functions.saveData(this.accountFile, accountInfo);
447
445
 
448
446
  return accountInfo;