homebridge-melcloud-control 4.13.0 → 4.13.2

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
@@ -25,6 +25,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
25
25
  - For plugin < v4.6.0 use Homebridge UI <= v5.5.0
26
26
  - For plugin >= v4.6.0 use Homebridge UI >= v5.13.0
27
27
 
28
+ ## [4.13.2] - (17.10.2026)
29
+
30
+ ### Changes
31
+
32
+ - fixed: Config UI, the error shown after a failed Login and Sync was an empty object `{}`, now the real error message is shown
33
+
34
+ ## [4.13.1] - (29.09.2026)
35
+
36
+ ### Changes
37
+
38
+ - fixed: MQTT, when the broker was not running yet at the start of Homebridge the device never published over MQTT and the Home Assistant discovery was not set up until a restart. The device now starts publishing and sets up the discovery as soon as the broker comes online
39
+ - fixed: Home Assistant discovery, the config and the state are published again after a restart of the broker, a broker without persistence loses the retained messages
40
+
28
41
  ## [4.13.0] - (24.09.2026)
29
42
 
30
43
  ### Changes
@@ -477,7 +477,7 @@
477
477
  await homebridge.savePluginConfig();
478
478
  } catch (error) {
479
479
  updateInfo('info', `Prepare config error`, "red");
480
- updateInfo('info1', `Error: ${JSON.stringify(error)}`, "red");
480
+ updateInfo('info1', `Error: ${error?.message ?? JSON.stringify(error)}`, "red");
481
481
  } finally {
482
482
  homebridge.hideSpinner();
483
483
  $('logIn').disabled = false;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "displayName": "MELCloud Control",
3
3
  "name": "homebridge-melcloud-control",
4
- "version": "4.13.0",
4
+ "version": "4.13.2",
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
@@ -64,6 +64,8 @@ class DeviceAta extends EventEmitter {
64
64
  this.mqtt = account.mqtt ?? {};
65
65
  this.mqtt1 = mqtt1;
66
66
  this.mqttConnected = mqttConnected;
67
+ // The broker may come online after the start or restart, the device then publishes again
68
+ this.mqtt1?.on('online', () => this.mqttOnline().catch((error) => this.emit('warn', `MQTT online error: ${error}`)));
67
69
 
68
70
  const serviceType = [null, Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor, Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor, null];
69
71
  const characteristicType = [null, Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState, Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState, null];
@@ -1321,7 +1323,15 @@ class DeviceAta extends EventEmitter {
1321
1323
  }
1322
1324
  }
1323
1325
 
1326
+ // MQTT connected, at start when the broker was not running yet or after a restart of the broker
1327
+ async mqttOnline() {
1328
+ this.mqttConnected = true;
1329
+ this.ha?.reset();
1330
+ if (this.haLast) await this.haPublish(...this.haLast);
1331
+ }
1332
+
1324
1333
  async haPublish(capabilities, state) {
1334
+ this.haLast = [capabilities, state];
1325
1335
  if (!this.haReady()) return;
1326
1336
 
1327
1337
  try {
package/src/deviceatw.js CHANGED
@@ -71,6 +71,8 @@ class DeviceAtw extends EventEmitter {
71
71
  this.mqtt = account.mqtt ?? {};
72
72
  this.mqtt1 = mqtt1;
73
73
  this.mqttConnected = mqttConnected;
74
+ // The broker may come online after the start or restart, the device then publishes again
75
+ this.mqtt1?.on('online', () => this.mqttOnline().catch((error) => this.emit('warn', `MQTT online error: ${error}`)));
74
76
 
75
77
  const serviceType = [null, Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor, Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor, null];
76
78
  const characteristicType = [null, Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState, Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState, null];
@@ -1593,7 +1595,15 @@ class DeviceAtw extends EventEmitter {
1593
1595
  }
1594
1596
  }
1595
1597
 
1598
+ // MQTT connected, at start when the broker was not running yet or after a restart of the broker
1599
+ async mqttOnline() {
1600
+ this.mqttConnected = true;
1601
+ this.ha?.reset();
1602
+ if (this.haLast) await this.haPublish(...this.haLast);
1603
+ }
1604
+
1596
1605
  async haPublish(capabilities, power, zones, tank) {
1606
+ this.haLast = [capabilities, power, zones, tank];
1597
1607
  if (!this.haReady()) return;
1598
1608
 
1599
1609
  try {
package/src/deviceerv.js CHANGED
@@ -59,6 +59,8 @@ class DeviceErv extends EventEmitter {
59
59
  this.mqtt = account.mqtt ?? {};
60
60
  this.mqtt1 = mqtt1;
61
61
  this.mqttConnected = mqttConnected;
62
+ // The broker may come online after the start or restart, the device then publishes again
63
+ this.mqtt1?.on('online', () => this.mqttOnline().catch((error) => this.emit('warn', `MQTT online error: ${error}`)));
62
64
 
63
65
  const serviceType = [null, Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor, Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor, null];
64
66
  const characteristicType = [null, Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState, Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState, null];
@@ -995,7 +997,15 @@ class DeviceErv extends EventEmitter {
995
997
  }
996
998
  }
997
999
 
1000
+ // MQTT connected, at start when the broker was not running yet or after a restart of the broker
1001
+ async mqttOnline() {
1002
+ this.mqttConnected = true;
1003
+ this.ha?.reset();
1004
+ if (this.haLast) await this.haPublish(...this.haLast);
1005
+ }
1006
+
998
1007
  async haPublish(capabilities, state) {
1008
+ this.haLast = [capabilities, state];
999
1009
  if (!this.haReady()) return;
1000
1010
 
1001
1011
  try {
@@ -33,6 +33,12 @@ class HaDiscovery {
33
33
  }
34
34
 
35
35
  // Publish (or republish when changed) one retained discovery message
36
+ // The broker may have lost the retained messages (restart without persistence), the next publish sends everything again
37
+ reset() {
38
+ this.lastConfig = {};
39
+ this.lastState = '';
40
+ }
41
+
36
42
  async publishEntity(component, suffix, entity) {
37
43
  const objectId = suffix ? `${this.baseId}_${suffix}` : this.baseId;
38
44
  const topic = `${this.mqtt.haPrefix}/${component}/${objectId}/config`;
package/src/mqtt.js CHANGED
@@ -36,6 +36,7 @@ class Mqtt extends EventEmitter {
36
36
  } : {})
37
37
  };
38
38
 
39
+ this.connected = false;
39
40
  const startTime = Date.now();
40
41
  let hasConnected = false;
41
42
  let warnedStalled = false;
@@ -45,6 +46,9 @@ class Mqtt extends EventEmitter {
45
46
  hasConnected = true;
46
47
  this.emit('connected', `MQTT v${protocolVersion} connected.`);
47
48
  if (this.haDiscovery) this.publishRetained(this.availabilityTopic, 'online').catch(() => { });
49
+ // Every connect, also when the broker was not running at start or restarted, devices publish again
50
+ this.connected = true;
51
+ this.emit('online');
48
52
 
49
53
  try {
50
54
  await new Promise((resolve, reject) => {
@@ -90,6 +94,7 @@ class Mqtt extends EventEmitter {
90
94
  if (config.logDebug) this.emit('debug', 'MQTT Reconnecting...');
91
95
  })
92
96
  .on('close', () => {
97
+ this.connected = false;
93
98
  if (!hasConnected && !warnedStalled && Date.now() - startTime > 30000) {
94
99
  warnedStalled = true;
95
100
  this.emit('warn', `MQTT has not connected after 30s of retries using protocol v${protocolVersion}. Check broker address, credentials, and whether the broker supports this MQTT protocol version.`);