homebridge-melcloud-control 4.10.9-beta.3 → 4.10.9

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
@@ -451,8 +451,11 @@
451
451
  if (removedScenesCount) removedParts.push(`Scenes: ${removedScenesCount}`);
452
452
  if (removedParts.length) updateInfo('info1', `Removed old: ${removedParts.join('; ')}`, 'orange');
453
453
 
454
+ homebridge.hideSpinner();
455
+ $('logIn').disabled = false;
456
+
454
457
  await homebridge.updatePluginConfig(pluginConfig);
455
- await homebridge.savePluginConfig(pluginConfig);
458
+ await homebridge.savePluginConfig();
456
459
  } catch (error) {
457
460
  const msg = error?.message || error?.error || String(error);
458
461
  updateInfo('info', 'Connection failed', 'red');
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.3",
4
+ "version": "4.10.9",
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
  };
@@ -382,10 +385,10 @@ class DeviceAta extends EventEmitter {
382
385
  .setProps({
383
386
  minValue: this.accessory.fanSpeedSetPropsMinValue,
384
387
  maxValue: this.accessory.fanSpeedSetPropsMaxValue,
385
- minStep: 1
388
+ minStep: this.accessory.fanSpeedSetPropsMinStep
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) => {
@@ -393,11 +396,12 @@ class DeviceAta extends EventEmitter {
393
396
  const payload = {};
394
397
  const fanKeySet = accountTypeMelCloud ? 'fanSpeed' : 'setFanSpeed';
395
398
  const max = numberOfFanSpeeds;
396
- const minValue = supportsAutomaticFanSpeed ? 0 : 1;
397
- const clampedValue = Math.min(Math.max(value, minValue), max);
399
+ const minFanSpeed = supportsAutomaticFanSpeed ? 0 : 1;
400
+ // Reverse-map from 0-100 HomeKit scale to raw fan speed level
401
+ const rawFanSpeed = value === 0 ? 0 : Math.max(minFanSpeed, Math.min(max, Math.round((value / 100) * max)));
398
402
 
399
- payload[fanKeySet] = clampedValue;
400
- if (this.logInfo) this.emit('info', `Set fan speed mode: ${AirConditioner.FanSpeedMapEnumToString[clampedValue]}`);
403
+ payload[fanKeySet] = rawFanSpeed;
404
+ if (this.logInfo) this.emit('info', `Set fan speed mode: ${AirConditioner.FanSpeedMapEnumToString[rawFanSpeed]}`);
401
405
  await this.melCloudAta.send(this.accountType, this.displayType, deviceData, payload, AirConditioner.EffectiveFlags.SetFanSpeed);
402
406
  } catch (error) {
403
407
  if (this.logWarn) this.emit('warn', `Set fan speed mode error: ${error}`);
@@ -1643,17 +1647,15 @@ class DeviceAta extends EventEmitter {
1643
1647
  //fan speed mode
1644
1648
  if (supportsFanSpeed) {
1645
1649
  const max = numberOfFanSpeeds;
1646
-
1647
- // ograniczamy wartość do zakresu API
1648
- const minValue = supportsAutomaticFanSpeed ? 0 : 1;
1649
- const maxValue = max;
1650
-
1651
- // zabezpieczenie przed out-of-bounds
1652
- const clampedValue = Math.min(Math.max(setFanSpeed, minValue), maxValue);
1653
-
1654
- obj.currentFanSpeed = clampedValue;
1655
- obj.fanSpeedSetPropsMinValue = minValue;
1656
- obj.fanSpeedSetPropsMaxValue = maxValue;
1650
+ const minRaw = supportsAutomaticFanSpeed ? 0 : 1;
1651
+ const rawFanSpeed = Math.min(Math.max(setFanSpeed, minRaw), max);
1652
+ // Scale raw fan speed to 0-100 HomeKit range
1653
+ const scaledFanSpeed = rawFanSpeed === 0 ? 0 : Math.round((rawFanSpeed / max) * 100);
1654
+
1655
+ obj.currentFanSpeed = scaledFanSpeed;
1656
+ obj.fanSpeedSetPropsMinValue = 0;
1657
+ obj.fanSpeedSetPropsMaxValue = 100;
1658
+ obj.fanSpeedSetPropsMinStep = Math.round(100 / max);
1657
1659
  }
1658
1660
 
1659
1661
  //create characteristics
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