homebridge-melcloud-control 3.1.2-beta.9 → 3.1.3-beta.0

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
@@ -12,15 +12,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
12
12
  - v1 After update to v1 and above from v0 the devices need to be added to the Home app again and the old unresponsive remove!!! This devices will be removed from all automations and scenes!!!
13
13
  - v2 After update to v2 from v1 only RESTFull and MQTT config settings need to be updated in config.
14
14
  - v2.4 and above require upcomming homebridge v2
15
- - v3 After update to v3 from previous versions the plugin need to be configured using Config UI X.
15
+ - v3 After update to v3 the plugin need to be configured using Config UI X.
16
16
  - do not configure it manually, always using Config UI X
17
+ - required Homebridge v2.0.0 and above
18
+
19
+ ## [3.1.2] - (31.08.2024)
20
+
21
+ ## Changes
22
+
23
+ - fix presets configured array
17
24
 
18
25
  ## [3.1.0] - (31.08.2024)
19
26
 
20
27
  ## Changes
21
28
 
22
29
  - improvements in plugin config UI
23
- - added possibility indyvidual presets control
30
+ - added presets config indyvidually
24
31
  - config schema update
25
32
  - bump dependencies
26
33
  - cleanup
@@ -39,7 +46,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
39
46
 
40
47
  - added homebridge UI server
41
48
  - whole new concept get all devices from melcloud usin config UI X
42
- - added individual configuration of every device
49
+ - added device config indyvidually
43
50
  - config schema updated
44
51
  - cleanup
45
52
 
package/README.md CHANGED
@@ -21,8 +21,8 @@ Homebridge plugin for Air Conditioner, Heat Pump and Energy Recovery Ventilation
21
21
 
22
22
  | Package | Installation | Role | Required |
23
23
  | --- | --- | --- | --- |
24
- | [Homebridge](https://github.com/homebridge/homebridge) | [Homebridge Wiki](https://github.com/homebridge/homebridge/wiki) | HomeKit Bridge | Required |
25
- | [Config UI X](https://github.com/homebridge/homebridge-config-ui-x) | [Config UI X Wiki](https://github.com/homebridge/homebridge-config-ui-x/wiki) | Homebridge Web User Interface | Recommended |
24
+ | [Homebridge v2.0](https://github.com/homebridge/homebridge) | [Homebridge Wiki](https://github.com/homebridge/homebridge/wiki) | HomeKit Bridge | Required ab v3.0.0 |
25
+ | [Config UI X](https://github.com/homebridge/homebridge-config-ui-x) | [Config UI X Wiki](https://github.com/homebridge/homebridge-config-ui-x/wiki) | Homebridge Web User Interface | Required ab v3.0.0|
26
26
  | [MELCloud](https://github.com/grzegorz914/homebridge-melcloud-control) | [Plug-In Wiki](https://github.com/grzegorz914/homebridge-melcloud-control/wiki) | Homebridge Plug-In | Required |
27
27
 
28
28
  ### About The Plugin
@@ -161,7 +161,7 @@ Homebridge plugin for Air Conditioner, Heat Pump and Energy Recovery Ventilation
161
161
  ### Configuration
162
162
 
163
163
  * Run this plugin as a [Child Bridge](https://github.com/homebridge/homebridge/wiki/Child-Bridges) (Highly Recommended), this prevent crash Homebridge if plugin crashes.
164
- * Install and use [Homebridge Config UI X](https://github.com/homebridge/homebridge-config-ui-x/wiki) to configure this plugin (Highly Recommended).
164
+ * Install and use [Homebridge Config UI X](https://github.com/homebridge/homebridge-config-ui-x/wiki) to configure this plugin, required for version v3 and above.
165
165
  * The `sample-config.json` can be edited and used as an alternative.
166
166
 
167
167
  <p align="center">
@@ -1719,7 +1719,7 @@
1719
1719
  {
1720
1720
  "key": "accounts[].ataDevices[].presets",
1721
1721
  "type": "tabarray",
1722
- "title": "{{ value.name || ''}}",
1722
+ "title": "{{ value.name }}",
1723
1723
  "items": [
1724
1724
  {
1725
1725
  "key": "accounts[].ataDevices[].presets[].id",
@@ -187,7 +187,7 @@
187
187
  };
188
188
 
189
189
  //get device info fom devices ata
190
- devicesByType.ata.forEach((device, index) => {
190
+ devicesByType.ata.forEach(async (device, index) => {
191
191
  const deviceId = device.DeviceID;
192
192
  const deviceType = device.Type;
193
193
  const deviceTypeText = "Air Conditioner";
@@ -212,6 +212,7 @@
212
212
 
213
213
  const ataDevicesExist = pluginConfig[0].accounts[this.deviceIndex].ataDevices ?? false;
214
214
  const ataDevices = ataDevicesExist ? pluginConfig[0].accounts[this.deviceIndex].ataDevices : pluginConfig[0].accounts[this.deviceIndex].ataDevices = [];
215
+
215
216
  const ataDeviceIdExist = ataDevices.some(device => device.id === deviceId);
216
217
  const pushTypeAta = ataDeviceIdExist ? false : ataDevices.push(deviceAta);
217
218
  const pushNewDevice = ataDeviceIdExist ? false : newDevices.ata.push(device);
@@ -236,10 +237,15 @@
236
237
  const presetsCount = newDevices.ataPresets.length;
237
238
  textAtaPresets = `ATA Presets: ${presetsCount}`
238
239
  };
240
+
241
+ //compare presets
242
+ const presetsOnMelCloud = devicePresets;
243
+ const presetsAtaInConfig = pluginConfig[0].accounts[this.deviceIndex].ataDevices[index].presets;
244
+ presetsAtaInConfig = syncArrays(presetsOnMelCloud, presetsAtaInConfig);
239
245
  });
240
246
 
241
247
  //get device info fom devices atw
242
- devicesByType.atw.forEach((device, index) => {
248
+ devicesByType.atw.forEach(async (device, index) => {
243
249
  const deviceId = device.DeviceID;
244
250
  const deviceType = device.Type;
245
251
  const deviceTypeText = "Heat Pump";
@@ -293,10 +299,14 @@
293
299
  const presetsCount = newDevices.atwPresets.length;
294
300
  textAtwPresets = `ATW Presets: ${presetsCount}`
295
301
  };
302
+
303
+ const presetsOnMelCloud = devicePresets;
304
+ const presetsAtwInConfig = pluginConfig[0].accounts[this.deviceIndex].atwDevices[index].presets;
305
+ presetsAtwInConfig = syncArrays(presetsOnMelCloud, presetsAtwInConfig);
296
306
  });
297
307
 
298
308
  //get device info fom devices erv
299
- devicesByType.erv.forEach((device, index) => {
309
+ devicesByType.erv.forEach(async (device, index) => {
300
310
  const deviceId = device.DeviceID;
301
311
  const deviceType = device.Type;
302
312
  const deviceTypeText = "Energy Recovery Ventilation";
@@ -344,8 +354,23 @@
344
354
  const presetsCount = newDevices.ervPresets.length;
345
355
  textErvPresets = `ERV Presets: ${presetsCount}`
346
356
  };
357
+
358
+ const presetsOnMelCloud = devicePresets;
359
+ const presetsErvInConfig = pluginConfig[0].accounts[this.deviceIndex].ervDevices[index].presets;
360
+ presetsErvInConfig = await syncArrays(presetsOnMelCloud, presetsErvInConfig);
347
361
  });
348
362
 
363
+ //compare arrays and update array in config
364
+ const devicesOnMelCloud = devices;
365
+ const devicesAtaInConfig = pluginConfig[0].accounts[this.deviceIndex].ataDevices;
366
+ devicesAtaInConfig = await syncArrays(devicesOnMelCloud, devicesAtaInConfig);
367
+
368
+ const devicesAtwInConfig = pluginConfig[0].accounts[this.deviceIndex].atwDevices;
369
+ devicesAtwInConfig = await syncArrays(devicesOnMelCloud, devicesAtwInConfig);
370
+
371
+ const devicesErvInConfig = pluginConfig[0].accounts[this.deviceIndex].ervDevices;
372
+ devicesErvInConfig = await syncArrays(devicesOnMelCloud, devicesErvInConfig);
373
+
349
374
  const newDevicesCount = newDevices.ata.length + newDevices.atw.length + newDevices.erv.length ?? 0;
350
375
  const newPresetsCount = newDevices.ataPresets.length + newDevices.atwPresets.length + newDevices.ervPresets.length ?? 0;
351
376
  if (newDevicesCount === 0 && newPresetsCount === 0) {
@@ -389,6 +414,23 @@
389
414
  break;
390
415
  };
391
416
 
417
+ async function syncArrays(devicesOnMelCloud, devicesInConfig) {
418
+ // Create a Set of IDs from devicesOnMelCloud for quick lookup
419
+ const devicesOnMelCloudId = new Set(devicesOnMelCloud.map(device => device.DeviceID));
420
+
421
+ // Filter devicesInConfig to keep only objects that exist in devicesOnMelCloud
422
+ devicesInConfig = devicesInConfig.filter(device => devicesOnMelCloudId.has(device.DeviceID));
423
+
424
+ // Add objects from devicesOnMelCloud to devicesInConfig that do not exist in devicesInConfig
425
+ devicesOnMelCloud.forEach(device => {
426
+ if (!devicesInConfig.some(item => item.id === device.id)) {
427
+ devicesInConfig.push(device);
428
+ }
429
+ });
430
+
431
+ return devicesInConfig;
432
+ }
433
+
392
434
  homebridge.hideSpinner();
393
435
  } catch (e) {
394
436
  document.getElementById('info').innerHTML = 'Please try again.';
package/index.js CHANGED
@@ -105,7 +105,9 @@ class MelCloudPlatform {
105
105
 
106
106
  //Air Conditioner
107
107
  for (const device of account.ataDevices) {
108
- if (!device.id || device.displayMode === 0) {
108
+ //chack device from config exist on melcloud
109
+ const deviceExistInMelCloud = devices.some(dev => dev.DeviceID === device.id);
110
+ if (!deviceExistInMelCloud || device.displayMode === 0) {
109
111
  continue;
110
112
  };
111
113
 
@@ -142,7 +144,9 @@ class MelCloudPlatform {
142
144
 
143
145
  //Heat Pump
144
146
  for (const device of account.atwDevices) {
145
- if (!device.id || device.displayMode === 0) {
147
+ //chack device from config exist on melcloud
148
+ const deviceExistInMelCloud = devices.some(dev => dev.DeviceID === device.id);
149
+ if (!deviceExistInMelCloud || device.displayMode === 0) {
146
150
  continue;
147
151
  };
148
152
 
@@ -180,7 +184,9 @@ class MelCloudPlatform {
180
184
 
181
185
  //Energy Recovery Ventilation
182
186
  for (const device of account.ervDevices) {
183
- if (!device.id || device.displayMode === 0) {
187
+ //chack device from config exist on melcloud
188
+ const deviceExistInMelCloud = devices.some(dev => dev.DeviceID === device.id);
189
+ if (!deviceExistInMelCloud || device.displayMode === 0) {
184
190
  continue;
185
191
  };
186
192
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "displayName": "MELCloud Control",
3
3
  "name": "homebridge-melcloud-control",
4
- "version": "3.1.2-beta.9",
4
+ "version": "3.1.3-beta.0",
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
@@ -20,7 +20,6 @@ class DeviceAta extends EventEmitter {
20
20
  this.displayMode = device.displayMode;
21
21
  this.temperatureSensor = device.temperatureSensor || false;
22
22
  this.temperatureSensorOutdoor = device.temperatureSensorOutdoor || false;
23
- this.presetsEnabled = device.presets || false;
24
23
  this.heatDryFanMode = device.heatDryFanMode || 1; //NONE, HEAT, DRY, FAN
25
24
  this.coolDryFanMode = device.coolDryFanMode || 1; //NONE, COOL, DRY, FAN
26
25
  this.autoDryFanMode = device.autoDryFanMode || 1; //NONE, AUTO, DRY, FAN
@@ -46,13 +45,13 @@ class DeviceAta extends EventEmitter {
46
45
  const presetDisplayType = preset.displayType ?? 0;
47
46
  const presetNamePrefix = preset.namePrefix ?? false;
48
47
  if (presetName && presetDisplayType > 0) {
49
- const buttonServiceType = ['', Service.Outlet, Service.Switch, Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][presetDisplayType];
50
- const buttonCharacteristicType = ['', Characteristic.On, Characteristic.On, Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][presetDisplayType];
48
+ const presetyServiceType = ['', Service.Outlet, Service.Switch, Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][presetDisplayType];
49
+ const presetCharacteristicType = ['', Characteristic.On, Characteristic.On, Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][presetDisplayType];
51
50
  preset.namePrefix = presetNamePrefix;
52
- preset.serviceType = buttonServiceType;
53
- preset.characteristicType = buttonCharacteristicType;
51
+ preset.serviceType = presetyServiceType;
52
+ preset.characteristicType = presetCharacteristicType;
54
53
  preset.state = false;
55
- this.buttonsConfigured.push(preset);
54
+ this.presetsConfigured.push(preset);
56
55
  } else {
57
56
  const log = presetDisplayType === 0 ? false : this.emit('message', `Preset Name: ${preset ? preset : 'Missing'}.`);
58
57
  };
package/src/deviceatw.js CHANGED
@@ -42,25 +42,25 @@ class DeviceAtw extends EventEmitter {
42
42
  //function
43
43
  this.melCloud = melCloud; //function
44
44
 
45
- //presets configured
46
- this.presetsConfigured = [];
47
- for (const preset of this.presets) {
48
- const presetName = preset.name ?? false;
49
- const presetDisplayType = preset.displayType ?? 0;
50
- const presetNamePrefix = preset.namePrefix ?? false;
51
- if (presetName && presetDisplayType > 0) {
52
- const buttonServiceType = ['', Service.Outlet, Service.Switch, Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][presetDisplayType];
53
- const buttonCharacteristicType = ['', Characteristic.On, Characteristic.On, Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][presetDisplayType];
54
- preset.namePrefix = presetNamePrefix;
55
- preset.serviceType = buttonServiceType;
56
- preset.characteristicType = buttonCharacteristicType;
57
- preset.state = false;
58
- this.buttonsConfigured.push(preset);
59
- } else {
60
- const log = presetDisplayType === 0 ? false : this.emit('message', `Preset Name: ${preset ? preset : 'Missing'}.`);
61
- };
62
- }
63
- this.presetsConfiguredCount = this.presetsConfigured.length || 0;
45
+ //presets configured
46
+ this.presetsConfigured = [];
47
+ for (const preset of this.presets) {
48
+ const presetName = preset.name ?? false;
49
+ const presetDisplayType = preset.displayType ?? 0;
50
+ const presetNamePrefix = preset.namePrefix ?? false;
51
+ if (presetName && presetDisplayType > 0) {
52
+ const presetyServiceType = ['', Service.Outlet, Service.Switch, Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][presetDisplayType];
53
+ const presetCharacteristicType = ['', Characteristic.On, Characteristic.On, Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][presetDisplayType];
54
+ preset.namePrefix = presetNamePrefix;
55
+ preset.serviceType = presetyServiceType;
56
+ preset.characteristicType = presetCharacteristicType;
57
+ preset.state = false;
58
+ this.presetsConfigured.push(preset);
59
+ } else {
60
+ const log = presetDisplayType === 0 ? false : this.emit('message', `Preset Name: ${preset ? preset : 'Missing'}.`);
61
+ };
62
+ }
63
+ this.presetsConfiguredCount = this.presetsConfigured.length || 0;
64
64
 
65
65
  //buttons configured
66
66
  this.buttonsConfigured = [];
package/src/deviceerv.js CHANGED
@@ -43,13 +43,13 @@ class DeviceErv extends EventEmitter {
43
43
  const presetDisplayType = preset.displayType ?? 0;
44
44
  const presetNamePrefix = preset.namePrefix ?? false;
45
45
  if (presetName && presetDisplayType > 0) {
46
- const buttonServiceType = ['', Service.Outlet, Service.Switch, Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][presetDisplayType];
47
- const buttonCharacteristicType = ['', Characteristic.On, Characteristic.On, Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][presetDisplayType];
46
+ const presetyServiceType = ['', Service.Outlet, Service.Switch, Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][presetDisplayType];
47
+ const presetCharacteristicType = ['', Characteristic.On, Characteristic.On, Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][presetDisplayType];
48
48
  preset.namePrefix = presetNamePrefix;
49
- preset.serviceType = buttonServiceType;
50
- preset.characteristicType = buttonCharacteristicType;
49
+ preset.serviceType = presetyServiceType;
50
+ preset.characteristicType = presetCharacteristicType;
51
51
  preset.state = false;
52
- this.buttonsConfigured.push(preset);
52
+ this.presetsConfigured.push(preset);
53
53
  } else {
54
54
  const log = presetDisplayType === 0 ? false : this.emit('message', `Preset Name: ${preset ? preset : 'Missing'}.`);
55
55
  };