homebridge-melcloud-control 4.4.0-beta.8 → 4.4.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.8",
4
+ "version": "4.4.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
@@ -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}`);
@@ -2189,7 +2193,7 @@ class DeviceAtw extends EventEmitter {
2189
2193
  if (this.frostProtectionSupport && frostProtection.Enabled !== null) {
2190
2194
  this.frostProtectionControlService?.updateCharacteristic(Characteristic.Active, frostProtection.Enabled);
2191
2195
  this.frostProtectionControlService?.updateCharacteristic(Characteristic.CurrentHeaterCoolerState, frostProtection.Active ? 2 : 1);
2192
- this.frostProtectionControlService?.updateCharacteristic(Characteristic.TargetHeaterCoolerState, frostProtection.Active ? 2 : 1);
2196
+ this.frostProtectionControlService?.updateCharacteristic(Characteristic.TargetHeaterCoolerState, 0);
2193
2197
  this.frostProtectionControlService?.updateCharacteristic(Characteristic.CurrentTemperature, roomTemperature);
2194
2198
  this.frostProtectionControlService?.updateCharacteristic(Characteristic.CoolingThresholdTemperature, frostProtection.Max);
2195
2199
  this.frostProtectionControlService?.updateCharacteristic(Characteristic.HeatingThresholdTemperature, frostProtection.Min);
package/src/functions.js CHANGED
@@ -237,38 +237,45 @@ class Functions extends EventEmitter {
237
237
  })
238
238
  );
239
239
  }
240
+
240
241
  async adjustTempProtection(oldMin, oldMax, newValue, type, minRangeMin, maxRangeMin, minRangeMax, maxRangeMax) {
241
242
  let min = oldMin;
242
243
  let max = oldMax;
243
244
 
244
245
  if (type === "min") {
245
- // clamp MIN
246
246
  min = Math.min(Math.max(newValue, minRangeMin), maxRangeMin);
247
247
 
248
- // ensure difference raise max if needed
249
- if (max - min < 2) {
248
+ if (min > oldMin && max - min < 2) {
250
249
  max = Math.min(min + 2, maxRangeMax);
251
- }
252
250
 
253
- // if still too small differencelower min
254
- if (max - min < 2) {
255
- min = Math.max(max - 2, minRangeMin);
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 };
256
257
  }
258
+
259
+ // min maleje → zwracamy tylko min
260
+ return { min, max };
257
261
  }
258
262
 
259
263
  if (type === "max") {
260
- // clamp MAX
261
264
  max = Math.min(Math.max(newValue, minRangeMax), maxRangeMax);
262
265
 
263
- // ensure difference lower min if needed
264
- if (max - min < 2) {
266
+ if (max < oldMax && max - min < 2) {
265
267
  min = Math.max(max - 2, minRangeMin);
266
- }
267
268
 
268
- // if still too small differenceraise max
269
- if (max - min < 2) {
270
- max = Math.min(min + 2, maxRangeMax);
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 };
271
275
  }
276
+
277
+ // max rośnie → zwracamy tylko max
278
+ return { min, max };
272
279
  }
273
280
 
274
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;