homebridge-melcloud-control 4.10.9-beta.4 → 4.10.10-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.9] - (28.05.2026)
28
+
29
+ ### Changes
30
+
31
+ - fix ATA HeaterCooler Active.onSet now includes current OperationMode (EffectiveFlags: PowerOperationMode) when powering on, preventing MELCloud from resetting the operation mode to Auto when iOS sends a spurious Active=1 alongside a fan speed change
32
+ - fix ATA and ERV RotationSpeed characteristic scaled to 0-100 HomeKit range instead of raw 0-N; GET scales raw fan speed to percentage (level 1 of 5 → 20%), SET reverse-maps percentage back to raw level, setProps maxValue set to 100 with minStep = 100/numberOfFanSpeeds so the slider snaps to clean positions
33
+
27
34
  ## [4.10.8] - (24.05.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.10.9-beta.4",
4
+ "version": "4.10.10-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
@@ -330,8 +330,11 @@ class DeviceAta extends EventEmitter {
330
330
  .onSet(async (state) => {
331
331
  try {
332
332
  const payload = { power: state ? true : false };
333
+ const operationMode = deviceData.Device.OperationMode;
334
+ const includeMode = state && operationMode != null;
335
+ if (includeMode) payload.operationMode = operationMode;
333
336
  if (this.logInfo) this.emit('info', `Set power: ${state ? 'On' : 'Off'}`);
334
- await this.melCloudAta.send(this.accountType, this.displayType, deviceData, payload);
337
+ await this.melCloudAta.send(this.accountType, this.displayType, deviceData, payload, includeMode ? AirConditioner.EffectiveFlags.OperationMode : null);
335
338
  } catch (error) {
336
339
  if (this.logWarn) this.emit('warn', `Set power error: ${error}`);
337
340
  };
@@ -385,7 +388,7 @@ class DeviceAta extends EventEmitter {
385
388
  minStep: 1
386
389
  })
387
390
  .onGet(async () => {
388
- const value = this.accessory.currentFanSpeed; //AUTO, 1, 2, 3, 4, 5, 6, OFF
391
+ const value = this.accessory.currentFanSpeed;
389
392
  return value;
390
393
  })
391
394
  .onSet(async (value) => {
@@ -1642,8 +1645,6 @@ class DeviceAta extends EventEmitter {
1642
1645
 
1643
1646
  //fan speed mode
1644
1647
  if (supportsFanSpeed) {
1645
- const max = numberOfFanSpeeds;
1646
-
1647
1648
  // ograniczamy wartość do zakresu API
1648
1649
  const minValue = supportsAutomaticFanSpeed ? 0 : 1;
1649
1650
  const maxValue = max;
package/src/deviceerv.js CHANGED
@@ -348,21 +348,22 @@ class DeviceErv extends EventEmitter {
348
348
  .setProps({
349
349
  minValue: this.accessory.fanSpeedSetPropsMinValue,
350
350
  maxValue: this.accessory.fanSpeedSetPropsMaxValue,
351
- minStep: 1
351
+ minStep: this.accessory.fanSpeedSetPropsMinStep
352
352
  })
353
353
  .onGet(async () => {
354
- const value = this.accessory.fanSpeed; //STOP, 1, 2, 3, 4, OFF
354
+ const value = this.accessory.fanSpeed;
355
355
  return value;
356
356
  })
357
357
  .onSet(async (value) => {
358
358
  try {
359
359
  const payload = {};
360
360
  const max = numberOfFanSpeeds;
361
- const minValue = supportsAutomaticFanSpeed ? 0 : 1;
362
- const clampedValue = Math.min(Math.max(value, minValue), max);
361
+ const minFanSpeed = supportsAutomaticFanSpeed ? 0 : 1;
362
+ // Reverse-map from 0-100 HomeKit scale to raw fan speed level
363
+ const rawFanSpeed = value === 0 ? 0 : Math.max(minFanSpeed, Math.min(max, Math.round((value / 100) * max)));
363
364
 
364
- payload.setFanSpeed = clampedValue;
365
- if (this.logInfo) this.emit('info', `Set fan speed mode: ${Ventilation.FanSpeedMapEnumToString[clampedValue]}`);
365
+ payload.setFanSpeed = rawFanSpeed;
366
+ if (this.logInfo) this.emit('info', `Set fan speed mode: ${Ventilation.FanSpeedMapEnumToString[rawFanSpeed]}`);
366
367
  await this.melCloudErv.send(this.accountType, this.displayType, deviceData, payload, Ventilation.EffectiveFlags.SetFanSpeed);
367
368
  } catch (error) {
368
369
  if (this.logWarn) this.emit('warn', `Set fan speed mode error: ${error}`);
@@ -1274,17 +1275,15 @@ class DeviceErv extends EventEmitter {
1274
1275
  //fan speed mode
1275
1276
  if (supportsFanSpeed) {
1276
1277
  const max = numberOfFanSpeeds;
1277
-
1278
- // ograniczamy wartość do zakresu API
1279
- const minValue = supportsAutomaticFanSpeed ? 0 : 1;
1280
- const maxValue = max;
1281
-
1282
- // zabezpieczenie przed out-of-bounds
1283
- const clampedValue = Math.min(Math.max(setFanSpeed, minValue), maxValue);
1284
-
1285
- obj.fanSpeed = clampedValue;
1286
- obj.fanSpeedSetPropsMinValue = minValue;
1287
- obj.fanSpeedSetPropsMaxValue = maxValue;
1278
+ const minRaw = supportsAutomaticFanSpeed ? 0 : 1;
1279
+ const rawFanSpeed = Math.min(Math.max(setFanSpeed, minRaw), max);
1280
+ // Scale raw fan speed to 0-100 HomeKit range
1281
+ const scaledFanSpeed = rawFanSpeed === 0 ? 0 : Math.round((rawFanSpeed / max) * 100);
1282
+
1283
+ obj.fanSpeed = scaledFanSpeed;
1284
+ obj.fanSpeedSetPropsMinValue = 0;
1285
+ obj.fanSpeedSetPropsMaxValue = 100;
1286
+ obj.fanSpeedSetPropsMinStep = Math.round(100 / max);
1288
1287
  }
1289
1288
 
1290
1289
  //create characteristics