homebridge-melcloud-control 4.4.0-beta.9 → 4.4.1-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
@@ -28,13 +28,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
28
28
 
29
29
  - added possibility to set frost protection min/max temperaure (ATA, ATW)
30
30
  - added possibility to set overheat protection min/max temperture (ATA)
31
- - bump dependencies
32
- - cleanup
33
-
34
- # [4.3.16] - (09.12.2025)
35
-
36
- ## Changes
37
-
38
31
  - stability and performance improvements
39
32
  - moved MQTT to v5
40
33
  - bump dependencies
package/index.js CHANGED
@@ -90,7 +90,7 @@ class MelCloudPlatform {
90
90
  melcloud = new MelCloud(account, accountFile, buildingsFile, true);
91
91
  break;
92
92
  case 'melcloudhome':
93
- timmers = [{ name: 'connect', sampling: 3300000 }, { name: 'checkDevicesList', sampling: 3000 }];
93
+ timmers = [{ name: 'connect', sampling: 3300000 }, { name: 'checkDevicesList', sampling: 5000 }];
94
94
  melcloud = new MelCloudHome(account, accountFile, buildingsFile, true);
95
95
  break;
96
96
  default:
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "displayName": "MELCloud Control",
3
3
  "name": "homebridge-melcloud-control",
4
- "version": "4.4.0-beta.9",
4
+ "version": "4.4.1-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
@@ -934,7 +934,7 @@ class DeviceAta extends EventEmitter {
934
934
  }
935
935
 
936
936
  //holiday mode
937
- if (this.holidayModeSupport && this.accessory.holidayModeEnabled !== null) {
937
+ if (this.holidayModeSupport && this.accessory.holidayMode.Enabled !== null) {
938
938
  //control
939
939
  if (this.logDebug) this.emit('debug', `Prepare holiday mode control service`);
940
940
  this.holidayModeControlService = new Service.Switch(`${serviceName} Holiday Mode`, `holidayModeControlService${deviceId}`);
@@ -942,7 +942,7 @@ class DeviceAta extends EventEmitter {
942
942
  this.holidayModeControlService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Holiday Mode`);
943
943
  this.holidayModeControlService.getCharacteristic(Characteristic.On)
944
944
  .onGet(async () => {
945
- const state = this.accessory.holidayModeEnabled;
945
+ const state = this.accessory.holidayMode.Enabled;
946
946
  return state;
947
947
  })
948
948
  .onSet(async (state) => {
@@ -962,7 +962,7 @@ class DeviceAta extends EventEmitter {
962
962
  this.holidayModeControlSensorService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Holiday Mode Control`);
963
963
  this.holidayModeControlSensorService.getCharacteristic(Characteristic.ContactSensorState)
964
964
  .onGet(async () => {
965
- const state = this.accessory.holidayModeEnabled;
965
+ const state = this.accessory.holidayMode.Enabled;
966
966
  return state;
967
967
  })
968
968
  accessory.addService(this.holidayModeControlSensorService);
@@ -974,7 +974,7 @@ class DeviceAta extends EventEmitter {
974
974
  this.holidayModeSensorService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Holiday Mode`);
975
975
  this.holidayModeSensorService.getCharacteristic(Characteristic.ContactSensorState)
976
976
  .onGet(async () => {
977
- const state = this.accessory.holidayModeActive;
977
+ const state = this.accessory.holidayMode.Active;
978
978
  return state;
979
979
  })
980
980
  accessory.addService(this.holidayModeSensorService);
@@ -1506,15 +1506,14 @@ class DeviceAta extends EventEmitter {
1506
1506
 
1507
1507
  //presets schedules
1508
1508
  const presetsOnServer = deviceData.Presets ?? [];
1509
- const scheduleEnabled = deviceData.ScheduleEnabled;
1510
1509
  const schedulesOnServer = deviceData.Schedule ?? [];
1510
+ const scheduleEnabled = deviceData.ScheduleEnabled;
1511
1511
  const scenesOnServer = deviceData.Scenes ?? [];
1512
- const holidayModeEnabled = deviceData.HolidayMode?.Enabled;
1513
- const holidayModeActive = deviceData.HolidayMode?.Active ?? false;
1514
1512
 
1515
1513
  //protection
1516
1514
  const frostProtection = deviceData.FrostProtection ?? {};
1517
1515
  const overheatProtection = deviceData.OverheatProtection ?? {};
1516
+ const holidayMode = deviceData.HolidayMode ?? {};
1518
1517
 
1519
1518
  //device control
1520
1519
  const hideVaneControls = deviceData.HideVaneControls ?? false;
@@ -1569,7 +1568,11 @@ class DeviceAta extends EventEmitter {
1569
1568
  const obj = {
1570
1569
  presets: presetsOnServer,
1571
1570
  schedules: schedulesOnServer,
1571
+ scheduleEnabled: scheduleEnabled,
1572
1572
  scenes: scenesOnServer,
1573
+ frostProtection: frostProtection,
1574
+ overheatProtection: overheatProtection,
1575
+ holidayMode: holidayMode,
1573
1576
  supportsAutomaticFanSpeed: supportsAutomaticFanSpeed,
1574
1577
  supportsAirDirectionFunction: supportsAirDirectionFunction,
1575
1578
  supportsSwingFunction: supportsSwingFunction,
@@ -1606,12 +1609,7 @@ class DeviceAta extends EventEmitter {
1606
1609
  useFahrenheit: this.accountInfo.useFahrenheit ? 1 : 0,
1607
1610
  temperatureUnit: TemperatureDisplayUnits[this.accountInfo.useFahrenheit ? 1 : 0],
1608
1611
  isConnected: isConnected,
1609
- isInError: isInError,
1610
- frostProtection: frostProtection,
1611
- overheatProtection: overheatProtection,
1612
- holidayModeEnabled: holidayModeEnabled,
1613
- holidayModeActive: holidayModeActive,
1614
- scheduleEnabled: scheduleEnabled
1612
+ isInError: isInError
1615
1613
  };
1616
1614
 
1617
1615
  //characteristics array
@@ -1796,10 +1794,10 @@ class DeviceAta extends EventEmitter {
1796
1794
  }
1797
1795
 
1798
1796
  //holiday mode
1799
- if (this.holidayModeSupport && holidayModeEnabled !== null) {
1800
- this.holidayModeControlService?.updateCharacteristic(Characteristic.On, holidayModeEnabled);
1801
- this.holidayModeControlSensorService?.updateCharacteristic(Characteristic.ContactSensorState, holidayModeEnabled);
1802
- this.holidayModeSensorService?.updateCharacteristic(Characteristic.ContactSensorState, holidayModeActive);
1797
+ if (this.holidayModeSupport && holidayMode.Enabled !== null) {
1798
+ this.holidayModeControlService?.updateCharacteristic(Characteristic.On, holidayMode.Enabled);
1799
+ this.holidayModeControlSensorService?.updateCharacteristic(Characteristic.ContactSensorState, holidayMode.Enabled);
1800
+ this.holidayModeSensorService?.updateCharacteristic(Characteristic.ContactSensorState, holidayMode.Active);
1803
1801
  }
1804
1802
 
1805
1803
  //presets
package/src/deviceatw.js CHANGED
@@ -1115,8 +1115,10 @@ class DeviceAtw extends EventEmitter {
1115
1115
  })
1116
1116
  .onSet(async (value) => {
1117
1117
  try {
1118
- deviceData.FrostProtection.Max = value;
1119
- if (this.logInfo) this.emit('info', `Set frost protection max. temperature: ${value}${this.accessory.temperatureUnit}`);
1118
+ let { min, max } = await this.functions.adjustTempProtection(deviceData.FrostProtection.Min, deviceData.FrostProtection.Max, value, 'max', 4, 14, 6, 16);
1119
+ deviceData.FrostProtection.Min = min;
1120
+ deviceData.FrostProtection.Max = max;
1121
+ if (this.logInfo) this.emit('info', `Set frost protection max. temperature: ${max}${this.accessory.temperatureUnit}`);
1120
1122
  await this.melCloudAta.send(this.accountType, this.displayType, deviceData, 'frostprotection');
1121
1123
  } catch (error) {
1122
1124
  if (this.logWarn) this.emit('warn', `Set frost protection max. temperature error: ${error}`);
@@ -1134,8 +1136,10 @@ class DeviceAtw extends EventEmitter {
1134
1136
  })
1135
1137
  .onSet(async (value) => {
1136
1138
  try {
1137
- deviceData.FrostProtection.Min = value;
1138
- if (this.logInfo) this.emit('info', `Set frost protection min. temperature: ${value}${this.accessory.temperatureUnit}`);
1139
+ let { min, max } = await this.functions.adjustTempProtection(deviceData.FrostProtection.Min, deviceData.FrostProtection.Max, value, 'min', 4, 14, 6, 16);
1140
+ deviceData.FrostProtection.Min = min;
1141
+ deviceData.FrostProtection.Max = max;
1142
+ if (this.logInfo) this.emit('info', `Set frost protection min. temperature: ${min}${this.accessory.temperatureUnit}`);
1139
1143
  await this.melCloudAta.send(this.accountType, this.displayType, deviceData, 'frostprotection');
1140
1144
  } catch (error) {
1141
1145
  if (this.logWarn) this.emit('warn', `Set frost protection min. temperature error: ${error}`);
@@ -1169,7 +1173,7 @@ class DeviceAtw extends EventEmitter {
1169
1173
  }
1170
1174
 
1171
1175
  //holiday mode
1172
- if (this.holidayModeSupport && this.accessory.holidayModeEnabled !== null) {
1176
+ if (this.holidayModeSupport && this.accessory.holidayMode.Enabled !== null) {
1173
1177
  //control
1174
1178
  if (this.logDebug) this.emit('debug', `Prepare holiday mode control service`);
1175
1179
  this.holidayModeControlService = new Service.Switch(`${serviceName} Holiday Mode`, `holidayModeControlService${deviceId}`);
@@ -1177,7 +1181,7 @@ class DeviceAtw extends EventEmitter {
1177
1181
  this.holidayModeControlService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Holiday Mode`);
1178
1182
  this.holidayModeControlService.getCharacteristic(Characteristic.On)
1179
1183
  .onGet(async () => {
1180
- const state = this.accessory.holidayModeEnabled;
1184
+ const state = this.accessory.holidayMode.Enabled;
1181
1185
  return state;
1182
1186
  })
1183
1187
  .onSet(async (state) => {
@@ -1197,7 +1201,7 @@ class DeviceAtw extends EventEmitter {
1197
1201
  this.holidayModeControlSensorService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Holiday Mode Control`);
1198
1202
  this.holidayModeControlSensorService.getCharacteristic(Characteristic.ContactSensorState)
1199
1203
  .onGet(async () => {
1200
- const state = this.accessory.holidayModeEnabled;
1204
+ const state = this.accessory.holidayMode.Enabled;
1201
1205
  return state;
1202
1206
  })
1203
1207
  accessory.addService(this.holidayModeControlSensorService);
@@ -1209,7 +1213,7 @@ class DeviceAtw extends EventEmitter {
1209
1213
  this.holidayModeSensorService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Holiday Mode State`);
1210
1214
  this.holidayModeSensorService.getCharacteristic(Characteristic.ContactSensorState)
1211
1215
  .onGet(async () => {
1212
- const state = this.accessory.holidayModeActive;
1216
+ const state = this.accessory.holidayMode.Active;
1213
1217
  return state;
1214
1218
  })
1215
1219
  accessory.addService(this.holidayModeSensorService);
@@ -1672,12 +1676,10 @@ class DeviceAtw extends EventEmitter {
1672
1676
  const scheduleEnabled = deviceData.ScheduleEnabled;
1673
1677
  const schedulesOnServer = deviceData.Schedule ?? [];
1674
1678
  const scenesOnServer = deviceData.Scenes ?? [];
1675
- const holidayMode = deviceData.Device.HolidayMode;
1676
- const holidayModeEnabled = accountTypeMelcloud ? holidayMode : deviceData.HolidayMode?.Enabled;
1677
- const holidayModeActive = deviceData.HolidayMode?.Active ?? false;
1678
1679
 
1679
1680
  //protection
1680
1681
  const frostProtection = deviceData.FrostProtection ?? {};
1682
+ const holidayMode = deviceData.HolidayMode ?? {};
1681
1683
 
1682
1684
  //device info
1683
1685
  const supportsStanbyMode = deviceData.Device[supportStandbyKey];
@@ -1759,7 +1761,10 @@ class DeviceAtw extends EventEmitter {
1759
1761
  const obj = {
1760
1762
  presets: presetsOnServer,
1761
1763
  schedules: schedulesOnServer,
1764
+ scheduleEnabled: scheduleEnabled,
1762
1765
  scenes: scenesOnServer,
1766
+ frostProtection: frostProtection,
1767
+ holidayMode: holidayMode,
1763
1768
  power: power,
1764
1769
  inStandbyMode: inStandbyMode,
1765
1770
  unitStatus: unitStatus,
@@ -1786,11 +1791,6 @@ class DeviceAtw extends EventEmitter {
1786
1791
  temperatureUnit: TemperatureDisplayUnits[this.accountInfo.useFahrenheit ? 1 : 0],
1787
1792
  isConnected: isConnected,
1788
1793
  isInError: isInError,
1789
- frostProtection: frostProtection,
1790
- scheduleEnabled: scheduleEnabled,
1791
- holidayModeEnabled: holidayModeEnabled,
1792
- holidayModeActive: holidayModeActive,
1793
- scheduleEnabled: scheduleEnabled,
1794
1794
  zones: [],
1795
1795
  zonesSensors: []
1796
1796
  };
@@ -2189,7 +2189,7 @@ class DeviceAtw extends EventEmitter {
2189
2189
  if (this.frostProtectionSupport && frostProtection.Enabled !== null) {
2190
2190
  this.frostProtectionControlService?.updateCharacteristic(Characteristic.Active, frostProtection.Enabled);
2191
2191
  this.frostProtectionControlService?.updateCharacteristic(Characteristic.CurrentHeaterCoolerState, frostProtection.Active ? 2 : 1);
2192
- this.frostProtectionControlService?.updateCharacteristic(Characteristic.TargetHeaterCoolerState, frostProtection.Active ? 2 : 1);
2192
+ this.frostProtectionControlService?.updateCharacteristic(Characteristic.TargetHeaterCoolerState, 0);
2193
2193
  this.frostProtectionControlService?.updateCharacteristic(Characteristic.CurrentTemperature, roomTemperature);
2194
2194
  this.frostProtectionControlService?.updateCharacteristic(Characteristic.CoolingThresholdTemperature, frostProtection.Max);
2195
2195
  this.frostProtectionControlService?.updateCharacteristic(Characteristic.HeatingThresholdTemperature, frostProtection.Min);
@@ -2198,10 +2198,10 @@ class DeviceAtw extends EventEmitter {
2198
2198
  }
2199
2199
 
2200
2200
  //holiday mode
2201
- if (this.holidayModeSupport && holidayModeEnabled !== null) {
2202
- this.holidayModeControlService?.updateCharacteristic(Characteristic.On, holidayModeEnabled);
2203
- this.holidayModeControlSensorService?.updateCharacteristic(Characteristic.ContactSensorState, holidayModeEnabled);
2204
- this.holidayModeSensorService?.updateCharacteristic(Characteristic.ContactSensorState, holidayModeActive);
2201
+ if (this.holidayModeSupport && holidayMode.Enabled !== null) {
2202
+ this.holidayModeControlService?.updateCharacteristic(Characteristic.On, holidayMode.Enabled);
2203
+ this.holidayModeControlSensorService?.updateCharacteristic(Characteristic.ContactSensorState, holidayMode.Enabled);
2204
+ this.holidayModeSensorService?.updateCharacteristic(Characteristic.ContactSensorState, holidayMode.Active);
2205
2205
  }
2206
2206
 
2207
2207
  //presets
@@ -2286,7 +2286,7 @@ class DeviceAtw extends EventEmitter {
2286
2286
  button.state = power ? (operationMode === 1) : false;
2287
2287
  break;
2288
2288
  case 53: //HOLIDAY
2289
- button.state = power ? (holidayModeEnabled === true) : false;
2289
+ button.state = power ? (holidayMode.Enabled === true) : false;
2290
2290
  break;
2291
2291
  case 10: //ALL ZONES PHYSICAL LOCK CONTROL
2292
2292
  button.state = power ? (prohibitZone1 === true && prohibitHotWater === true && prohibitZone2 === true) : false;
package/src/functions.js CHANGED
@@ -238,28 +238,44 @@ class Functions extends EventEmitter {
238
238
  );
239
239
  }
240
240
 
241
- async adjustTempProtection(oldMin, oldMax, newValue, type, minRangeMin, maxRangeMin, minRangeMax, maxRangeMax) {
242
- let min = oldMin;
243
- let max = oldMax;
241
+ async adjustTempProtection(currentMin, currentMax, value, type, minRangeMin, maxRangeMin, minRangeMax, maxRangeMax) {
242
+ let min = currentMin;
243
+ let max = currentMax;
244
244
 
245
245
  if (type === "min") {
246
- // użytkownik zmienia MIN
247
- min = Math.min(Math.max(newValue, minRangeMin), maxRangeMin);
246
+ min = Math.min(Math.max(value, minRangeMin), maxRangeMin);
248
247
 
249
- // jeśli różnica jest za mała podnieś MAX
250
- if (max - min < 2) {
248
+ if (min > currentMin && max - min < 2) {
251
249
  max = Math.min(min + 2, maxRangeMax);
250
+
251
+ // jeśli max uderza w górną granicę → obniż min o 2
252
+ if (max === maxRangeMax && max - min < 2) {
253
+ min = Math.max(min - 2, minRangeMin);
254
+ }
255
+
256
+ return { min, max };
252
257
  }
258
+
259
+ // min maleje → zwracamy tylko min
260
+ return { min, max };
253
261
  }
254
262
 
255
263
  if (type === "max") {
256
- // użytkownik zmienia MAX
257
- max = Math.min(Math.max(newValue, minRangeMax), maxRangeMax);
264
+ max = Math.min(Math.max(value, minRangeMax), maxRangeMax);
258
265
 
259
- // jeśli różnica jest za mała obniż MIN
260
- if (max - min < 2) {
266
+ if (max < currentMax && max - min < 2) {
261
267
  min = Math.max(max - 2, minRangeMin);
268
+
269
+ // jeśli min uderza w dolną granicę → podbij max o 2
270
+ if (min === minRangeMin && max - min < 2) {
271
+ max = Math.min(max + 2, maxRangeMax);
272
+ }
273
+
274
+ return { min, max };
262
275
  }
276
+
277
+ // max rośnie → zwracamy tylko max
278
+ return { min, max };
263
279
  }
264
280
 
265
281
  return { min, max };
@@ -24,6 +24,7 @@ class MelCloudAta extends EventEmitter {
24
24
  //set default values
25
25
  this.deviceData = {};
26
26
  this.client = melcloud.client;
27
+ this.lock = false;
27
28
 
28
29
  //handle melcloud events
29
30
  let deviceData = null;
@@ -196,6 +197,7 @@ class MelCloudAta extends EventEmitter {
196
197
  let method = null
197
198
  let payload = {};
198
199
  let path = '';
200
+ let update = false;
199
201
  switch (accountType) {
200
202
  case "melcloud":
201
203
  switch (flag) {
@@ -248,6 +250,7 @@ class MelCloudAta extends EventEmitter {
248
250
  };
249
251
  method = 'POST';
250
252
  path = ApiUrlsHome.PostProtectionFrost;
253
+ update = true;
251
254
  break;
252
255
  case 'overheatprotection':
253
256
  payload = {
@@ -258,6 +261,7 @@ class MelCloudAta extends EventEmitter {
258
261
  };
259
262
  method = 'POST';
260
263
  path = ApiUrlsHome.PostProtectionOverheat;
264
+ update = true;
261
265
  break;
262
266
  case 'holidaymode':
263
267
  payload = {
@@ -273,6 +277,7 @@ class MelCloudAta extends EventEmitter {
273
277
  payload = { enabled: deviceData.ScheduleEnabled };
274
278
  method = 'PUT';
275
279
  path = ApiUrlsHome.PutScheduleEnabled.replace('deviceid', deviceData.DeviceID);
280
+ update = true;
276
281
  break;
277
282
  case 'scene':
278
283
  method = 'PUT';
@@ -309,7 +314,12 @@ class MelCloudAta extends EventEmitter {
309
314
  //send payload
310
315
  if (this.logDebug) this.emit('debug', `Send data: ${JSON.stringify(payload, null, 2)}`);
311
316
  await this.client(path, { method: method, data: payload });
312
- this.update(deviceData);
317
+
318
+ if (update) {
319
+ setTimeout(() => {
320
+ this.emit('deviceState', deviceData);
321
+ }, 500);
322
+ }
313
323
 
314
324
  return true;
315
325
  default:
@@ -319,12 +329,6 @@ class MelCloudAta extends EventEmitter {
319
329
  throw new Error(`Send data error: ${error.message}`);
320
330
  }
321
331
  }
322
-
323
- update(deviceData) {
324
- setTimeout(() => {
325
- this.emit('deviceState', deviceData)
326
- }, 500);
327
- }
328
332
  }
329
333
 
330
334
  export default MelCloudAta;
@@ -197,6 +197,7 @@ class MelCloudAtw extends EventEmitter {
197
197
  let method = null
198
198
  let payload = {};
199
199
  let path = '';
200
+ let update = false;
200
201
  switch (accountType) {
201
202
  case "melcloud":
202
203
  switch (flag) {
@@ -241,6 +242,17 @@ class MelCloudAtw extends EventEmitter {
241
242
  return true;
242
243
  case "melcloudhome":
243
244
  switch (flag) {
245
+ case 'frostprotection':
246
+ payload = {
247
+ enabled: deviceData.FrostProtection.Enabled,
248
+ min: deviceData.FrostProtection.Min,
249
+ max: deviceData.FrostProtection.Max,
250
+ units: { ATA: [deviceData.DeviceID] }
251
+ };
252
+ method = 'POST';
253
+ path = ApiUrlsHome.PostProtectionFrost;
254
+ update = true;
255
+ break;
244
256
  case 'holidaymode':
245
257
  payload = {
246
258
  enabled: deviceData.HolidayMode.Enabled,
@@ -255,6 +267,7 @@ class MelCloudAtw extends EventEmitter {
255
267
  payload = { enabled: deviceData.ScheduleEnabled };
256
268
  method = 'PUT';
257
269
  path = ApiUrlsHome.PutScheduleEnabled.replace('deviceid', deviceData.DeviceID);
270
+ update = true;
258
271
  break;
259
272
  case 'scene':
260
273
  method = 'PUT';
@@ -284,6 +297,12 @@ class MelCloudAtw extends EventEmitter {
284
297
  if (this.logDebug) this.emit('debug', `Send data: ${JSON.stringify(payload, null, 2)}`);
285
298
  await this.client(path, { method: method, data: payload });
286
299
 
300
+ if (update) {
301
+ setTimeout(() => {
302
+ this.emit('deviceState', deviceData);
303
+ }, 500);
304
+ }
305
+
287
306
  return true;
288
307
  default:
289
308
  return;