homebridge-melcloud-control 4.7.3 → 4.7.5-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.7.4] - (29.01.2026)
28
+
29
+ ## Changes
30
+
31
+ - fix ATW Zone 2
32
+ - cleanup
33
+
27
34
  # [4.7.3] - (29.01.2026)
28
35
 
29
36
  ## Changes
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "displayName": "MELCloud Control",
3
3
  "name": "homebridge-melcloud-control",
4
- "version": "4.7.3",
4
+ "version": "4.7.5-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/deviceatw.js CHANGED
@@ -1792,11 +1792,11 @@ class DeviceAtw extends EventEmitter {
1792
1792
  const holidayMode = deviceData.HolidayMode ?? {};
1793
1793
 
1794
1794
  //device info
1795
- const supportsStanbyMode = deviceData.Device[supportStandbyKey];
1795
+ const supportsStandbyMode = deviceData.Device[supportStandbyKey];
1796
1796
  const supportsHeatPump = ![1, 2, 3, 4, 5, 6, 7, 15].includes(this.hideZone);
1797
1797
  const supportsZone1 = ![2, 3, 4, 8, 9, 10, 11, 15].includes(this.hideZone);
1798
1798
  const supportsHotWaterTank = ![3, 5, 6, 9, 10, 12, 13, 15].includes(this.hideZone) && deviceData.Device[supportHotWaterKey];
1799
- const supportsZone2 = ![4, 6, 7, 10, 11, 13, 14, 15].includes(this.hideZone) && deviceData.Device.HasZone2 !== false && deviceData.Device.HasZone2 !== null;
1799
+ const supportsZone2 = ![4, 6, 7, 10, 11, 13, 14, 15].includes(this.hideZone) && deviceData.Device.HasZone2 === true;
1800
1800
  const supportsHeat = deviceData.Device[supportHeatKey] ?? true;
1801
1801
  const supportsCool = deviceData.Device[supportCoolKey] ?? false;
1802
1802
  const supportsOutdoorTemperature = deviceData.Device.HasOutdoorTemperature;
@@ -1895,7 +1895,7 @@ class DeviceAtw extends EventEmitter {
1895
1895
  supportsHotWaterTank: supportsHotWaterTank,
1896
1896
  supportsZone2: supportsZone2,
1897
1897
  heatCoolModes: heatCoolModes,
1898
- supportsStanbyMode: supportsStanbyMode,
1898
+ supportsStandbyMode: supportsStandbyMode,
1899
1899
  supportsOutdoorTemperature: supportsOutdoorTemperature,
1900
1900
  caseHeatPump: caseHeatPump,
1901
1901
  caseZone1: caseZone1,
@@ -1998,7 +1998,7 @@ class DeviceAtw extends EventEmitter {
1998
1998
  };
1999
1999
  break;
2000
2000
  default:
2001
- if (this.logWarn) this.emit('warn', `${name}, Received unknoen operation mode: ${operationModeZone1}`);
2001
+ if (this.logWarn) this.emit('warn', `${name}, Received unknown operation mode: ${operationModeZone1}`);
2002
2002
  return;
2003
2003
  }
2004
2004
 
@@ -2028,18 +2028,28 @@ class DeviceAtw extends EventEmitter {
2028
2028
  currentOperationMode = !power ? 0 : (idleZone2 ? 1 : [2, 2, 2, 3, 3, 2][operationModeZone2]); //INACTIVE, IDLE, HEATING, COOLING
2029
2029
  targetOperationMode = [1, 2, 0, 1, 2, 1][operationModeZone2]; //AUTO, HEAT, COOL
2030
2030
 
2031
- switch (operationModeZone2) {
2032
- case 1: //HEAT FLOW
2033
- setTemperature = setHeatFlowTemperatureZone2;
2034
- roomTemperature = flowTemperatureZone2;
2035
- temperatureSetPropsMinValue = minSetHeatFlowTemperature;
2036
- temperatureSetPropsMaxValue = maxSetHeatFlowTemperature;
2037
- break;
2038
- case 4: //COOL FLOW
2039
- setTemperature = setCoolFlowTemperatureZone2;
2040
- roomTemperature = flowTemperatureZone2;
2041
- temperatureSetPropsMinValue = minSetCoolFlowTemperature;
2042
- temperatureSetPropsMaxValue = maxSetHeatCoolRoomTemperature;
2031
+ switch (accountTypeMelcloud) {
2032
+ case true: //Melcloud
2033
+ switch (operationModeZone2) {
2034
+ case 1: //HEAT FLOW
2035
+ setTemperature = setHeatFlowTemperatureZone2;
2036
+ roomTemperature = flowTemperatureZone2;
2037
+ temperatureSetPropsMinValue = minSetHeatFlowTemperature;
2038
+ temperatureSetPropsMaxValue = maxSetHeatFlowTemperature;
2039
+ break;
2040
+ case 4: //COOL FLOW
2041
+ setTemperature = setCoolFlowTemperatureZone2;
2042
+ roomTemperature = flowTemperatureZone2;
2043
+ temperatureSetPropsMinValue = minSetCoolFlowTemperature;
2044
+ temperatureSetPropsMaxValue = maxSetCoolFlowTemperature;
2045
+ break;
2046
+ default:
2047
+ setTemperature = setTemperatureZone2;
2048
+ roomTemperature = roomTemperatureZone2;
2049
+ temperatureSetPropsMinValue = minSetHeatRoomTemperature;
2050
+ temperatureSetPropsMaxValue = maxSetHeatCoolRoomTemperature;
2051
+ break
2052
+ };
2043
2053
  break;
2044
2054
  case false: //Melcloud Home
2045
2055
  switch (operationModeZone2) {
@@ -2175,30 +2185,40 @@ class DeviceAtw extends EventEmitter {
2175
2185
  currentOperationMode = !power ? 0 : (idleZone2 ? 0 : [1, 1, 1, 2, 2, 1][operationModeZone2]); //OFF, HEAT, COOL
2176
2186
  targetOperationMode = [1, 2, 3, 1, 2, 1][operationModeZone2]; //OFF, HEAT, COOL, AUTO
2177
2187
 
2178
- switch (operationModeZone2) {
2179
- case 1: //HEAT FLOW
2180
- setTemperature = setHeatFlowTemperatureZone2;
2181
- roomTemperature = flowTemperatureZone2;
2182
- temperatureSetPropsMinValue = minSetHeatFlowTemperature;
2183
- temperatureSetPropsMaxValue = maxSetHeatFlowTemperature;
2184
- break;
2185
- case 4: //COOL FLOW
2186
- setTemperature = setCoolFlowTemperatureZone2;
2187
- roomTemperature = flowTemperatureZone2;
2188
- temperatureSetPropsMinValue = minSetCoolFlowTemperature;
2189
- temperatureSetPropsMaxValue = maxSetHeatCoolRoomTemperature;
2188
+ switch (accountTypeMelcloud) {
2189
+ case true: //Melcloud
2190
+ switch (operationModeZone2) {
2191
+ case 1: //HEAT FLOW
2192
+ setTemperature = setHeatFlowTemperatureZone2;
2193
+ roomTemperature = flowTemperatureZone2;
2194
+ temperatureSetPropsMinValue = minSetHeatFlowTemperature;
2195
+ temperatureSetPropsMaxValue = maxSetHeatFlowTemperature;
2196
+ break;
2197
+ case 4: //COOL FLOW
2198
+ setTemperature = setCoolFlowTemperatureZone2;
2199
+ roomTemperature = flowTemperatureZone2;
2200
+ temperatureSetPropsMinValue = minSetCoolFlowTemperature;
2201
+ temperatureSetPropsMaxValue = maxSetCoolFlowTemperature;
2202
+ break;
2203
+ default:
2204
+ setTemperature = setTemperatureZone2;
2205
+ roomTemperature = roomTemperatureZone2;
2206
+ temperatureSetPropsMinValue = minSetHeatRoomTemperature;
2207
+ temperatureSetPropsMaxValue = maxSetHeatCoolRoomTemperature;
2208
+ break
2209
+ };
2190
2210
  break;
2191
2211
  case false: //Melcloud Home
2192
- switch (operationModeZone1) {
2212
+ switch (operationModeZone2) {
2193
2213
  case 3: //COOL THERMOSTAT
2194
- setTemperature = setTemperatureZone1;
2195
- roomTemperature = roomTemperatureZone1;
2214
+ setTemperature = setTemperatureZone2;
2215
+ roomTemperature = roomTemperatureZone2;
2196
2216
  temperatureSetPropsMinValue = minSetCoolRoomTemperature;
2197
2217
  temperatureSetPropsMaxValue = maxSetHeatCoolRoomTemperature;
2198
2218
  break;
2199
2219
  default:
2200
- setTemperature = setTemperatureZone1;
2201
- roomTemperature = roomTemperatureZone1;
2220
+ setTemperature = setTemperatureZone2;
2221
+ roomTemperature = roomTemperatureZone2;
2202
2222
  temperatureSetPropsMinValue = minSetHeatRoomTemperature;
2203
2223
  temperatureSetPropsMaxValue = maxSetHeatCoolRoomTemperature;
2204
2224
  break
@@ -42,85 +42,78 @@ class MelCloudAta extends EventEmitter {
42
42
  } catch (error) {
43
43
  if (this.logError) this.emit('error', `Request process message error: ${error}`);
44
44
  }
45
- }).on('webSocket', async (parsedMessage) => {
45
+ }).on(this.deviceId, async (parsedMessage) => {
46
46
  try {
47
- const messageData = parsedMessage?.[0]?.Data;
48
- if (!messageData || !deviceData) return;
47
+ if (!deviceData) return;
48
+ const messageData = parsedMessage[0].Data;
49
49
 
50
50
  let updateState = false;
51
- const unitId = messageData?.id;
52
- switch (unitId) {
53
- case this.deviceId:
54
- const messageType = parsedMessage[0].messageType;
55
- const settings = this.functions.parseArrayNameValue(messageData.settings);
56
- switch (messageType) {
57
- case 'unitStateChanged':
58
-
59
- //update values
60
- for (const [key, value] of Object.entries(settings)) {
61
- if (!this.functions.isValidValue(value)) continue;
62
-
63
- //update holiday mode
64
- if (key === 'HolidayMode') {
65
- deviceData.HolidayMode.Enabled = value;
66
- continue;
67
- }
68
-
69
- //update device settings
70
- if (key in deviceData.Device) {
71
- deviceData.Device[key] = value;
72
- }
73
- }
51
+ const settings = this.functions.parseArrayNameValue(messageData.settings);
52
+ const messageType = parsedMessage[0].messageType;
53
+ switch (messageType) {
54
+ case 'unitStateChanged':
55
+
56
+ //update values
57
+ for (const [key, value] of Object.entries(settings)) {
58
+ if (!this.functions.isValidValue(value)) continue;
59
+
60
+ //update holiday mode
61
+ if (key === 'HolidayMode') {
62
+ deviceData.HolidayMode.Enabled = value;
63
+ continue;
64
+ }
74
65
 
75
- updateState = true;
76
- break;
77
- case 'ataUnitFrostProtectionTriggered':
78
- deviceData.FrostProtection.Active = messageData.active;
66
+ //update device settings
67
+ if (key in deviceData.Device) {
68
+ deviceData.Device[key] = value;
69
+ }
70
+ }
79
71
 
80
- //update device settings
81
- for (const [key, value] of Object.entries(settings)) {
82
- if (!this.functions.isValidValue(value) || key === 'SetTemperature') continue;
72
+ updateState = true;
73
+ break;
74
+ case 'ataUnitFrostProtectionTriggered':
75
+ deviceData.FrostProtection.Active = messageData.active;
83
76
 
84
- if (key in deviceData.Device) {
85
- deviceData.Device[key] = value;
86
- }
87
- }
77
+ //update device settings
78
+ for (const [key, value] of Object.entries(settings)) {
79
+ if (!this.functions.isValidValue(value) || key === 'SetTemperature') continue;
88
80
 
89
- updateState = true;
90
- break;
91
- case 'ataUnitOverheatProtectionTriggered':
92
- deviceData.OverheatProtection.Active = messageData.active;
81
+ if (key in deviceData.Device) {
82
+ deviceData.Device[key] = value;
83
+ }
84
+ }
93
85
 
94
- //update device settings
95
- for (const [key, value] of Object.entries(settings)) {
96
- if (!this.functions.isValidValue(value) || key === 'SetTemperature') continue;
86
+ updateState = true;
87
+ break;
88
+ case 'ataUnitOverheatProtectionTriggered':
89
+ deviceData.OverheatProtection.Active = messageData.active;
97
90
 
98
- if (key in deviceData.Device) {
99
- deviceData.Device[key] = value;
100
- }
101
- }
91
+ //update device settings
92
+ for (const [key, value] of Object.entries(settings)) {
93
+ if (!this.functions.isValidValue(value) || key === 'SetTemperature') continue;
102
94
 
103
- updateState = true;
104
- break;
105
- case 'unitHolidayModeTriggered':
106
- deviceData.Device.Power = settings.Power;
107
- deviceData.HolidayMode.Enabled = settings.HolidayMode;
108
- deviceData.HolidayMode.Active = messageData.active;
109
- updateState = true;
110
- break;
111
- case 'unitWifiSignalChanged':
112
- deviceData.Rssi = messageData.rssi;
113
- updateState = true;
114
- break;
115
- case 'unitCommunicationRestored':
116
- deviceData.Device.IsConnected = true;
117
- break;
118
- default:
119
- if (this.logDebug) this.emit('debug', `Unit ${unitId}, received unknown message type: ${parsedMessage}`);
120
- return;
95
+ if (key in deviceData.Device) {
96
+ deviceData.Device[key] = value;
97
+ }
121
98
  }
99
+
100
+ updateState = true;
101
+ break;
102
+ case 'unitHolidayModeTriggered':
103
+ deviceData.Device.Power = settings.Power;
104
+ deviceData.HolidayMode.Enabled = settings.HolidayMode;
105
+ deviceData.HolidayMode.Active = messageData.active;
106
+ updateState = true;
107
+ break;
108
+ case 'unitWifiSignalChanged':
109
+ deviceData.Rssi = messageData.rssi;
110
+ updateState = true;
111
+ break;
112
+ case 'unitCommunicationRestored':
113
+ deviceData.Device.IsConnected = true;
122
114
  break;
123
115
  default:
116
+ if (this.logDebug) this.emit('debug', `Unit ${unitId}, received unknown message type: ${parsedMessage}`);
124
117
  return;
125
118
  }
126
119
 
@@ -41,70 +41,63 @@ class MelCloudAtw extends EventEmitter {
41
41
  } catch (error) {
42
42
  if (this.logError) this.emit('error', `Request process message error: ${error}`);
43
43
  }
44
- }).on('webSocket', async (parsedMessage) => {
44
+ }).on(this.deviceId, async (parsedMessage) => {
45
45
  try {
46
- const messageData = parsedMessage?.[0]?.Data;
47
- if (!messageData || !deviceData) return;
46
+ if (!deviceData) return;
47
+ const messageData = parsedMessage[0]?.Data;
48
48
 
49
49
  let updateState = false;
50
- const unitId = messageData?.id;
51
- switch (unitId) {
52
- case this.deviceId:
53
- const messageType = parsedMessage[0].messageType;
54
- const settings = this.functions.parseArrayNameValue(messageData.settings);
55
- switch (messageType) {
56
- case 'unitStateChanged':
50
+ const messageType = parsedMessage[0].messageType;
51
+ const settings = this.functions.parseArrayNameValue(messageData.settings);
52
+ switch (messageType) {
53
+ case 'unitStateChanged':
57
54
 
58
- //update values
59
- for (const [key, value] of Object.entries(settings)) {
60
- if (!this.functions.isValidValue(value)) continue;
55
+ //update values
56
+ for (const [key, value] of Object.entries(settings)) {
57
+ if (!this.functions.isValidValue(value)) continue;
61
58
 
62
- //update holiday mode
63
- if (key === 'HolidayMode') {
64
- deviceData.HolidayMode.Enabled = value;
65
- continue;
66
- }
59
+ //update holiday mode
60
+ if (key === 'HolidayMode') {
61
+ deviceData.HolidayMode.Enabled = value;
62
+ continue;
63
+ }
67
64
 
68
- //update device settings
69
- if (key in deviceData.Device) {
70
- deviceData.Device[key] = value;
71
- }
72
- }
65
+ //update device settings
66
+ if (key in deviceData.Device) {
67
+ deviceData.Device[key] = value;
68
+ }
69
+ }
73
70
 
74
- updateState = true;
75
- break;
76
- case 'atwUnitFrostProtectionTriggered':
77
- deviceData.FrostProtection.Active = messageData.active;
71
+ updateState = true;
72
+ break;
73
+ case 'atwUnitFrostProtectionTriggered':
74
+ deviceData.FrostProtection.Active = messageData.active;
78
75
 
79
- //update device settings
80
- for (const [key, value] of Object.entries(settings)) {
81
- if (!this.functions.isValidValue(value) || key === 'SetTemperature') continue;
76
+ //update device settings
77
+ for (const [key, value] of Object.entries(settings)) {
78
+ if (!this.functions.isValidValue(value) || key === 'SetTemperature') continue;
82
79
 
83
- if (key in deviceData.Device) {
84
- deviceData.Device[key] = value;
85
- }
86
- }
87
- updateState = true;
88
- break;
89
- case 'unitHolidayModeTriggered':
90
- deviceData.Device.Power = settings.Power;
91
- deviceData.HolidayMode.Enabled = settings.HolidayMode;
92
- deviceData.HolidayMode.Active = messageData.active;
93
- updateState = true;
94
- break;
95
- case 'unitWifiSignalChanged':
96
- deviceData.Rssi = messageData.rssi;
97
- updateState = true;
98
- break;
99
- case 'unitCommunicationRestored':
100
- deviceData.Device.IsConnected = true;
101
- break;
102
- default:
103
- if (this.logDebug) this.emit('debug', `Unit ${unitId}, received unknown message type: ${parsedMessage}`);
104
- return;
80
+ if (key in deviceData.Device) {
81
+ deviceData.Device[key] = value;
82
+ }
105
83
  }
84
+ updateState = true;
85
+ break;
86
+ case 'unitHolidayModeTriggered':
87
+ deviceData.Device.Power = settings.Power;
88
+ deviceData.HolidayMode.Enabled = settings.HolidayMode;
89
+ deviceData.HolidayMode.Active = messageData.active;
90
+ updateState = true;
91
+ break;
92
+ case 'unitWifiSignalChanged':
93
+ deviceData.Rssi = messageData.rssi;
94
+ updateState = true;
95
+ break;
96
+ case 'unitCommunicationRestored':
97
+ deviceData.Device.IsConnected = true;
106
98
  break;
107
99
  default:
100
+ if (this.logDebug) this.emit('debug', `Unit ${unitId}, received unknown message type: ${parsedMessage}`);
108
101
  return;
109
102
  }
110
103
 
@@ -43,68 +43,61 @@ class MelCloudErv extends EventEmitter {
43
43
  }
44
44
  }).on('webSocket', async (parsedMessage) => {
45
45
  try {
46
- const messageData = parsedMessage?.[0]?.Data;
47
- if (!messageData || !deviceData) return;
46
+ if (!deviceData) return;
47
+ const messageData = parsedMessage[0]?.Data;
48
48
 
49
49
  let updateState = false;
50
- const unitId = messageData?.id;
51
- switch (unitId) {
52
- case this.deviceId:
53
- const messageType = parsedMessage[0].messageType;
54
- const settings = this.functions.parseArrayNameValue(messageData.settings);
55
- switch (messageType) {
56
- case 'unitStateChanged':
57
-
58
- //update values
59
- for (const [key, value] of Object.entries(settings)) {
60
- if (!this.functions.isValidValue(value)) continue;
61
-
62
- //update holiday mode
63
- if (key === 'HolidayMode') {
64
- deviceData.HolidayMode.Enabled = value;
65
- continue;
66
- }
67
-
68
- //update device settings
69
- if (key in deviceData.Device) {
70
- deviceData.Device[key] = value;
71
- }
72
- }
50
+ const messageType = parsedMessage[0].messageType;
51
+ const settings = this.functions.parseArrayNameValue(messageData.settings);
52
+ switch (messageType) {
53
+ case 'unitStateChanged':
54
+
55
+ //update values
56
+ for (const [key, value] of Object.entries(settings)) {
57
+ if (!this.functions.isValidValue(value)) continue;
58
+
59
+ //update holiday mode
60
+ if (key === 'HolidayMode') {
61
+ deviceData.HolidayMode.Enabled = value;
62
+ continue;
63
+ }
64
+
65
+ //update device settings
66
+ if (key in deviceData.Device) {
67
+ deviceData.Device[key] = value;
68
+ }
69
+ }
73
70
 
74
- updateState = true;
75
- break;
76
- case 'ervUnitFrostProtectionTriggered':
77
- deviceData.FrostProtection.Active = messageData.active;
71
+ updateState = true;
72
+ break;
73
+ case 'ervUnitFrostProtectionTriggered':
74
+ deviceData.FrostProtection.Active = messageData.active;
78
75
 
79
- //update device settings
80
- for (const [key, value] of Object.entries(settings)) {
81
- if (!this.functions.isValidValue(value) || key === 'SetTemperature') continue;
76
+ //update device settings
77
+ for (const [key, value] of Object.entries(settings)) {
78
+ if (!this.functions.isValidValue(value) || key === 'SetTemperature') continue;
82
79
 
83
- if (key in deviceData.Device) {
84
- deviceData.Device[key] = value;
85
- }
86
- }
87
- updateState = true;
88
- break;
89
- case 'unitHolidayModeTriggered':
90
- deviceData.Device.Power = settings.Power;
91
- deviceData.HolidayMode.Enabled = settings.HolidayMode;
92
- deviceData.HolidayMode.Active = messageData.active;
93
- updateState = true;
94
- break;
95
- case 'unitWifiSignalChanged':
96
- deviceData.Rssi = messageData.rssi;
97
- updateState = true;
98
- break;
99
- case 'unitCommunicationRestored':
100
- deviceData.Device.IsConnected = true;
101
- break;
102
- default:
103
- if (this.logDebug) this.emit('debug', `Unit ${unitId}, received unknown message type: ${parsedMessage}`);
104
- return;
80
+ if (key in deviceData.Device) {
81
+ deviceData.Device[key] = value;
82
+ }
105
83
  }
84
+ updateState = true;
85
+ break;
86
+ case 'unitHolidayModeTriggered':
87
+ deviceData.Device.Power = settings.Power;
88
+ deviceData.HolidayMode.Enabled = settings.HolidayMode;
89
+ deviceData.HolidayMode.Active = messageData.active;
90
+ updateState = true;
91
+ break;
92
+ case 'unitWifiSignalChanged':
93
+ deviceData.Rssi = messageData.rssi;
94
+ updateState = true;
95
+ break;
96
+ case 'unitCommunicationRestored':
97
+ deviceData.Device.IsConnected = true;
106
98
  break;
107
99
  default:
100
+ if (this.logDebug) this.emit('debug', `Unit ${unitId}, received unknown message type: ${parsedMessage}`);
108
101
  return;
109
102
  }
110
103
 
@@ -331,9 +331,10 @@ class MelCloudHome extends EventEmitter {
331
331
  .on('message', (message) => {
332
332
  const parsedMessage = JSON.parse(message);
333
333
  if (this.logDebug) this.emit('debug', `Web socket incoming message: ${JSON.stringify(parsedMessage, null, 2)}`);
334
- if (parsedMessage.message === 'Forbidden') return;
334
+ const messageData = parsedMessage?.[0]?.Data;
335
+ if (!messageData || parsedMessage.message === 'Forbidden') return;
335
336
 
336
- this.emit('webSocket', parsedMessage);
337
+ this.emit(messageData.id, parsedMessage);
337
338
  });
338
339
  } catch (error) {
339
340
  if (this.logError) this.emit('error', `Web socket connection failed: ${error}`);