homebridge-melcloud-control 4.8.2 → 4.8.3

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,16 @@ 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.8.3] - (17.03.2026)
28
+
29
+ ## Changes
30
+
31
+ - fix fan mode control and display
32
+ - fix account disable
33
+ - bump dependencies
34
+ - redme update
35
+ - cleanup
36
+
27
37
  # [4.8.0] - (23.02.2026)
28
38
 
29
39
  ## Changes
package/README.md CHANGED
@@ -55,7 +55,7 @@
55
55
  * Power `ON/OFF`.
56
56
  * Operating mode `AUTO/HEAT/COOL/POWER OFF`.
57
57
  * Temperature `HEATING/COOLING/AUTO`.
58
- * Fan speed `OFF/1/2/3/4/5/AUTO`.
58
+ * Fan speed `AUTO/1/2/3/4/5`.
59
59
  * Swing mode `AUTO/SWING`.
60
60
  * Physical lock controls `LOCK/UNLOCK`.
61
61
  * Temperature display unit `°F/°C`.
@@ -162,7 +162,7 @@
162
162
  * Heater Cooler:
163
163
  * Power `ON/OFF`.
164
164
  * Operating mode `AUTO/HEAT/COOL/POWER OFF` - `AUTO, LOSSNAY, BYPASS, POWER OFF`.
165
- * Fan speed `OFF/1/2/3/4/AUTO`.
165
+ * Fan speed `AUTO/1/2/3/4`.
166
166
  * Temperature display unit `°F/°C`.
167
167
  * Thermostat:
168
168
  * Power `ON/OFF`.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "displayName": "MELCloud Control",
3
3
  "name": "homebridge-melcloud-control",
4
- "version": "4.8.2",
4
+ "version": "4.8.3",
5
5
  "description": "Homebridge plugin to control Mitsubishi Air Conditioner, Heat Pump and Energy Recovery Ventilation.",
6
6
  "license": "MIT",
7
7
  "author": "grzegorz914",
@@ -39,7 +39,7 @@
39
39
  "mqtt": "^5.15.0",
40
40
  "axios": "^1.13.6",
41
41
  "express": "^5.2.1",
42
- "puppeteer": "^24.38.0",
42
+ "puppeteer": "^24.39.1",
43
43
  "ws": "^8.19.0"
44
44
  },
45
45
  "keywords": [
package/src/deviceata.js CHANGED
@@ -384,7 +384,7 @@ class DeviceAta extends EventEmitter {
384
384
  if (supportsFanSpeed) {
385
385
  melCloudService.getCharacteristic(Characteristic.RotationSpeed)
386
386
  .setProps({
387
- minValue: 0,
387
+ minValue: this.accessory.fanSpeedSetPropsMinValue,
388
388
  maxValue: this.accessory.fanSpeedSetPropsMaxValue,
389
389
  minStep: 1
390
390
  })
@@ -396,23 +396,12 @@ class DeviceAta extends EventEmitter {
396
396
  try {
397
397
  const payload = {};
398
398
  const fanKeySet = accountTypeMelCloud ? 'fanSpeed' : 'setFanSpeed';
399
- switch (numberOfFanSpeeds) {
400
- case 2: //Fan speed mode 2
401
- value = supportsAutomaticFanSpeed ? [0, 1, 2, 0][value] : [1, 1, 2][value];
402
- break;
403
- case 3: //Fan speed mode 3
404
- value = supportsAutomaticFanSpeed ? [0, 1, 2, 3, 0][value] : [1, 1, 2, 3][value];
405
- break;
406
- case 4: //Fan speed mode 4
407
- value = supportsAutomaticFanSpeed ? [0, 1, 2, 3, 4, 0][value] : [1, 1, 2, 3, 4][value];
408
- break;
409
- case 5: //Fan speed mode 5
410
- value = supportsAutomaticFanSpeed ? [0, 1, 2, 3, 4, 5, 0][value] : [1, 1, 2, 3, 4, 5][value];
411
- break;
412
- };
399
+ const max = numberOfFanSpeeds;
400
+ const minValue = supportsAutomaticFanSpeed ? 0 : 1;
401
+ const clampedValue = Math.min(Math.max(value, minValue), max);
413
402
 
414
- payload[fanKeySet] = value;
415
- if (this.logInfo) this.emit('info', `Set fan speed mode: ${AirConditioner.FanSpeedMapEnumToString[value]}`);
403
+ payload[fanKeySet] = clampedValue;
404
+ if (this.logInfo) this.emit('info', `Set fan speed mode: ${AirConditioner.FanSpeedMapEnumToString[clampedValue]}`);
416
405
  await this.melCloudAta.send(this.accountType, this.displayType, deviceData, payload, AirConditioner.EffectiveFlags.SetFanSpeed);
417
406
  } catch (error) {
418
407
  if (this.logWarn) this.emit('warn', `Set fan speed mode error: ${error}`);
@@ -1652,15 +1641,17 @@ class DeviceAta extends EventEmitter {
1652
1641
  //fan speed mode
1653
1642
  if (supportsFanSpeed) {
1654
1643
  const max = numberOfFanSpeeds;
1655
- const autoIndex = supportsAutomaticFanSpeed ? max + 1 : 0;
1656
- const speeds = [autoIndex];
1657
1644
 
1658
- for (let i = 1; i <= max; i++) {
1659
- speeds.push(i);
1660
- }
1645
+ // ograniczamy wartość do zakresu API
1646
+ const minValue = supportsAutomaticFanSpeed ? 0 : 1;
1647
+ const maxValue = max;
1648
+
1649
+ // zabezpieczenie przed out-of-bounds
1650
+ const clampedValue = Math.min(Math.max(setFanSpeed, minValue), maxValue);
1661
1651
 
1662
- obj.currentFanSpeed = speeds[setFanSpeed];
1663
- obj.fanSpeedSetPropsMaxValue = supportsAutomaticFanSpeed ? max + 1 : max;
1652
+ obj.currentFanSpeed = clampedValue;
1653
+ obj.fanSpeedSetPropsMinValue = minValue;
1654
+ obj.fanSpeedSetPropsMaxValue = maxValue;
1664
1655
  }
1665
1656
 
1666
1657
  //create characteristics
package/src/deviceerv.js CHANGED
@@ -348,7 +348,7 @@ class DeviceErv extends EventEmitter {
348
348
  if (supportsFanSpeed) {
349
349
  melCloudService.getCharacteristic(Characteristic.RotationSpeed)
350
350
  .setProps({
351
- minValue: 0,
351
+ minValue: this.accessory.fanSpeedSetPropsMinValue,
352
352
  maxValue: this.accessory.fanSpeedSetPropsMaxValue,
353
353
  minStep: 1
354
354
  })
@@ -358,23 +358,13 @@ class DeviceErv extends EventEmitter {
358
358
  })
359
359
  .onSet(async (value) => {
360
360
  try {
361
- switch (numberOfFanSpeeds) {
362
- case 2: //Fan speed mode 2
363
- value = supportsAutomaticFanSpeed ? [0, 1, 2, 0][value] : [1, 1, 2][value];
364
- break;
365
- case 3: //Fan speed mode 3
366
- value = supportsAutomaticFanSpeed ? [0, 1, 2, 3, 0][value] : [1, 1, 2, 3][value];
367
- break;
368
- case 4: //Fan speed mode 4
369
- value = supportsAutomaticFanSpeed ? [0, 1, 2, 3, 4, 0][value] : [1, 1, 2, 3, 4][value];
370
- break;
371
- case 5: //Fan speed mode 5
372
- value = supportsAutomaticFanSpeed ? [0, 1, 2, 3, 4, 5, 0][value] : [1, 1, 2, 3, 4, 5][value];
373
- break;;
374
- };
361
+ const payload = {};
362
+ const max = numberOfFanSpeeds;
363
+ const minValue = supportsAutomaticFanSpeed ? 0 : 1;
364
+ const clampedValue = Math.min(Math.max(value, minValue), max);
375
365
 
376
- const payload = { setFanSpeed: value };
377
- if (this.logInfo) this.emit('info', `Set fan speed mode: ${Ventilation.FanSpeedMapEnumToString[value]}`);
366
+ payload.setFanSpeed = clampedValue;
367
+ if (this.logInfo) this.emit('info', `Set fan speed mode: ${Ventilation.FanSpeedMapEnumToString[clampedValue]}`);
378
368
  await this.melCloudErv.send(this.accountType, this.displayType, deviceData, payload, Ventilation.EffectiveFlags.SetFanSpeed);
379
369
  } catch (error) {
380
370
  if (this.logWarn) this.emit('warn', `Set fan speed mode error: ${error}`);
@@ -1281,21 +1271,19 @@ class DeviceErv extends EventEmitter {
1281
1271
  obj.operationModeSetPropsValidValues = operationModevalidValues;
1282
1272
 
1283
1273
  //fan speed mode
1284
- obj.fanSpeedSetPropsMaxValue = 2;
1285
-
1286
- // fan speed mode
1287
1274
  if (supportsFanSpeed) {
1288
1275
  const max = numberOfFanSpeeds;
1289
- const autoIndex = supportsAutomaticFanSpeed ? max + 1 : 0;
1290
1276
 
1291
- // Tworzymy tablicę prędkości: [auto?, 1..N]
1292
- const speeds = [autoIndex];
1293
- for (let i = 1; i <= max; i++) {
1294
- speeds.push(i);
1295
- }
1277
+ // ograniczamy wartość do zakresu API
1278
+ const minValue = supportsAutomaticFanSpeed ? 0 : 1;
1279
+ const maxValue = max;
1280
+
1281
+ // zabezpieczenie przed out-of-bounds
1282
+ const clampedValue = Math.min(Math.max(setFanSpeed, minValue), maxValue);
1296
1283
 
1297
- obj.fanSpeed = speeds[setFanSpeed];
1298
- obj.fanSpeedSetPropsMaxValue = supportsAutomaticFanSpeed ? max + 1 : max;
1284
+ obj.fanSpeed = clampedValue;
1285
+ obj.fanSpeedSetPropsMinValue = minValue;
1286
+ obj.fanSpeedSetPropsMaxValue = maxValue;
1299
1287
  }
1300
1288
 
1301
1289
  //create characteristics
@@ -1304,11 +1292,11 @@ class DeviceErv extends EventEmitter {
1304
1292
  { type: Characteristic.CurrentHeaterCoolerState, value: obj.currentOperationMode },
1305
1293
  { type: Characteristic.TargetHeaterCoolerState, value: obj.targetOperationMode },
1306
1294
  { type: Characteristic.CurrentTemperature, value: roomTemperature },
1307
- { type: Characteristic.RotationSpeed, value: obj.fanSpeed },
1308
1295
  { type: Characteristic.LockPhysicalControls, value: obj.lockPhysicalControl },
1309
1296
  { type: Characteristic.TemperatureDisplayUnits, value: obj.useFahrenheit },
1310
1297
  );
1311
1298
 
1299
+ if (supportsFanSpeed) characteristics.push({ type: Characteristic.RotationSpeed, value: obj.fanSpeed });
1312
1300
  if (supportsCoolOperationMode) characteristics.push({ type: Characteristic.CoolingThresholdTemperature, value: defaultCoolingSetTemperature });
1313
1301
  if (supportsHeatOperationMode) characteristics.push({ type: Characteristic.HeatingThresholdTemperature, value: defaultHeatingSetTemperature });
1314
1302
  break;
@@ -313,7 +313,7 @@ class MelCloudAta extends EventEmitter {
313
313
  }
314
314
 
315
315
  //send payload
316
- if (!this.logDebug) this.emit('debug', `Send data: ${JSON.stringify(payload, null, 2)}`);
316
+ if (this.logDebug) this.emit('debug', `Send data: ${JSON.stringify(payload, null, 2)}`);
317
317
  await this.client(path, { method: method, data: payload });
318
318
  return true;
319
319
  default: