homebridge-melcloud-control 4.10.18 → 4.10.19-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
@@ -24,6 +24,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
24
24
  - For plugin < v4.6.0 use Homebridge UI <= v5.5.0
25
25
  - For plugin >= v4.6.0 use Homebridge UI >= v5.13.0
26
26
 
27
+ ## [4.10.19] - (13.09.2026)
28
+
29
+ ### Changes
30
+
31
+ - fix: MQTT client had `protocolVersion: 5` hardcoded, so brokers that only support MQTT 3.1.1 (e.g. the ioBroker MQTT adapter) accepted the TCP connection, failed the handshake, and got disconnected every second forever, with nothing published and no error logged; added a `Protocol Version` option (5.0 / 3.1.1) in the MQTT section, and a one-time warning if no successful connection is established within 30 seconds
32
+ - bump dependencies
33
+
27
34
  ## [4.10.18] - (17.06.2026)
28
35
 
29
36
  ### Changes
@@ -2412,6 +2412,25 @@
2412
2412
  "functionBody": "return model.devices[arrayIndices].mqtt.enable === true;"
2413
2413
  }
2414
2414
  },
2415
+ "protocolVersion": {
2416
+ "title": "Protocol Version",
2417
+ "type": "integer",
2418
+ "default": 5,
2419
+ "oneOf": [
2420
+ {
2421
+ "title": "5.0",
2422
+ "enum": [5]
2423
+ },
2424
+ {
2425
+ "title": "3.1.1",
2426
+ "enum": [4]
2427
+ }
2428
+ ],
2429
+ "description": "MQTT protocol version used to connect to the broker. Some brokers (e.g. the ioBroker MQTT adapter) only support 3.1.1 and will silently reject 5.0 connections.",
2430
+ "condition": {
2431
+ "functionBody": "return model.devices[arrayIndices].mqtt.enable === true;"
2432
+ }
2433
+ },
2415
2434
  "auth": {
2416
2435
  "title": "Authorization",
2417
2436
  "type": "object",
package/index.js CHANGED
@@ -294,6 +294,7 @@ class MelCloudPlatform {
294
294
  port: mqtt.port || 1883,
295
295
  clientId: mqtt.clientId ? `melcloud_${mqtt.clientId}_${Math.random().toString(16).slice(3)}` : `melcloud_${Math.random().toString(16).slice(3)}`,
296
296
  prefix: mqtt.prefix ? `melcloud/${mqtt.prefix}/${deviceTypeString}/${deviceName}` : `melcloud/${deviceTypeString}/${deviceName}`,
297
+ protocolVersion: mqtt.protocolVersion,
297
298
  user: mqtt.auth?.user,
298
299
  passwd: mqtt.auth?.passwd,
299
300
  logWarn: logLevel.warn,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "displayName": "MELCloud Control",
3
3
  "name": "homebridge-melcloud-control",
4
- "version": "4.10.18",
4
+ "version": "4.10.19-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",
@@ -35,13 +35,13 @@
35
35
  "node": "^20 || ^22 || ^24 || ^25 || ^26"
36
36
  },
37
37
  "dependencies": {
38
- "@homebridge/plugin-ui-utils": "^2.2.5",
38
+ "@homebridge/plugin-ui-utils": "^2.2.6",
39
39
  "mqtt": "^5.15.2",
40
- "axios": "^1.18.1",
40
+ "axios": "^1.20.0",
41
41
  "axios-cookiejar-support": "^7.0.0",
42
42
  "tough-cookie": "^6.0.2",
43
43
  "express": "^5.2.1",
44
- "ws": "^8.21.1"
44
+ "ws": "^8.21.3"
45
45
  },
46
46
  "keywords": [
47
47
  "homebridge",
package/src/mqtt.js CHANGED
@@ -8,35 +8,47 @@ class Mqtt extends EventEmitter {
8
8
 
9
9
  const url = `mqtt://${config.host}:${config.port}`;
10
10
  const subscribeTopic = `${config.prefix}/Set`;
11
+ const protocolVersion = config.protocolVersion === 4 ? 4 : 5;
12
+ const isV5 = protocolVersion === 5;
13
+ this.isV5 = isV5;
11
14
 
12
15
  const options = {
13
16
  clientId: config.clientId,
14
17
  username: config.user,
15
18
  password: config.passwd,
16
- protocolVersion: 5,
17
- clean: false,
18
- properties: {
19
- sessionExpiryInterval: 60 * 60,
20
- userProperties: {
21
- source: 'node-client'
19
+ protocolVersion,
20
+ clean: !isV5,
21
+ ...(isV5 ? {
22
+ properties: {
23
+ sessionExpiryInterval: 60 * 60,
24
+ userProperties: {
25
+ source: 'node-client'
26
+ }
22
27
  }
23
- }
28
+ } : {})
24
29
  };
25
30
 
31
+ const startTime = Date.now();
32
+ let hasConnected = false;
33
+ let warnedStalled = false;
34
+
26
35
  this.mqttClient = connect(url, options)
27
36
  .on('connect', async () => {
28
- this.emit('connected', 'MQTT v5 connected.');
37
+ hasConnected = true;
38
+ this.emit('connected', `MQTT v${protocolVersion} connected.`);
29
39
 
30
40
  try {
31
41
  await new Promise((resolve, reject) => {
32
42
  this.mqttClient.subscribe(subscribeTopic,
33
43
  {
34
44
  qos: 1,
35
- properties: {
36
- userProperties: {
37
- type: 'subscription'
45
+ ...(isV5 ? {
46
+ properties: {
47
+ userProperties: {
48
+ type: 'subscription'
49
+ }
38
50
  }
39
- }
51
+ } : {})
40
52
  },
41
53
  (error) => {
42
54
  if (error) return reject(error);
@@ -69,6 +81,10 @@ class Mqtt extends EventEmitter {
69
81
  if (config.logDebug) this.emit('debug', 'MQTT Reconnecting...');
70
82
  })
71
83
  .on('close', () => {
84
+ if (!hasConnected && !warnedStalled && Date.now() - startTime > 30000) {
85
+ warnedStalled = true;
86
+ 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.`);
87
+ }
72
88
  if (config.logDebug) this.emit('debug', 'MQTT Connection closed.');
73
89
  });
74
90
  }
@@ -81,13 +97,15 @@ class Mqtt extends EventEmitter {
81
97
  this.mqttClient.publish(fullTopic, publishMessage,
82
98
  {
83
99
  qos: 1,
84
- properties: {
85
- contentType: 'application/json',
86
- userProperties: {
87
- source: 'node',
88
- action: 'set'
100
+ ...(this.isV5 ? {
101
+ properties: {
102
+ contentType: 'application/json',
103
+ userProperties: {
104
+ source: 'node',
105
+ action: 'set'
106
+ }
89
107
  }
90
- }
108
+ } : {})
91
109
  },
92
110
  (error) => {
93
111
  if (error) {