homebridge-melcloud-control 4.2.2-beta.1 → 4.2.2-beta.10

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
@@ -22,6 +22,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
22
22
 
23
23
  - Do not use Homebridge UI > v5.5.0 because of break config.json
24
24
 
25
+ ## [4.2.2] - (xx.11.2025)
26
+
27
+ ## Changes
28
+
29
+ - added in standby mode sensor
30
+ - added connect sensor
31
+ - config schema updated
32
+ - readme updated
33
+ - cleanup
34
+
25
35
  ## [4.2.1] - (13.11.2025)
26
36
 
27
37
  ## Changes
package/README.md CHANGED
@@ -245,6 +245,8 @@ Homebridge plugin for Air Conditioner, Heat Pump and Energy Recovery Ventilation
245
245
  | `ataDevices[].autoDryFanMode` | Here select the operatiing mode for `Auto`, if this mode is not supported, it will be disabled.. |
246
246
  | `ataDevices[].temperatureSensor` | This enable extra `Room` temperature sensor to use with automations in HomeKit app. |
247
247
  | `ataDevices[].temperatureOutdoorSensor` | This enable extra `Outdoor` temperature sensor to use with automations in HomeKit app. |
248
+ | `ataDevices[].inStandbySensor` | This enable `In Standby` sensor to use with automations in HomeKit app. |
249
+ | `ataDevices[].connectSensor` | This enable `Connect` sensor to use with automations in HomeKit app. |
248
250
  | `ataDevices[].errorSensor` | This enable `Error` sensor to use with automations in HomeKit app. |
249
251
  | `ataDevices[].frostProtectionSupport` | This enable extra `Frost Protectio` control and sensors to use with automations in HomeKit app. |
250
252
  | `ataDevices[].overheatProtectionSupport` | This enable extra `Overheat Protection` control and sensors to use with automations in HomeKit app. |
@@ -279,6 +281,8 @@ Homebridge plugin for Air Conditioner, Heat Pump and Energy Recovery Ventilation
279
281
  | `atwDevices[].temperatureReturnWaterTankSensor` | This enable extra `Return Water Tank` temperature sensor to use with automations in HomeKit app. |
280
282
  | `atwDevices[].temperatureFlowZone2Sensor` | This enable extra `Flow Zone 2` temperature sensor to use with automations in HomeKit app. |
281
283
  | `atwDevices[].temperatureReturnZone2Sensor` | This enable extra `Return Zone 2` temperature sensor to use with automations in HomeKit app. |
284
+ | `atwDevices[].inStandbySensor` | This enable `In Standby` sensor to use with automations in HomeKit app. |
285
+ | `atwDevices[].connectSensor` | This enable `Connect` sensor to use with automations in HomeKit app. |
282
286
  | `atwDevices[].errorSensor` | This enable `Error` sensors to use with automations in HomeKit app. |
283
287
  | `atwDevices[].holidayModeSupport` | This enable extra `Holiday Mode` control and sensors to use with automations in HomeKit app. |
284
288
  | `atwDevices[].refreshInterval` | Here set the background devices state refresh time in (sec), default `5s`. |
@@ -304,6 +308,8 @@ Homebridge plugin for Air Conditioner, Heat Pump and Energy Recovery Ventilation
304
308
  | `ervDevices[].temperatureSensor` | This enable extra `Room` temperature sensor to use with automations in HomeKit app. |
305
309
  | `ervDevices[].temperatureOutdoorSensor` | This enable extra `Outdoor` temperature sensor to use with automations in HomeKit app. |
306
310
  | `ervDevices[].temperatureSupplySensor` | This enable extra `Supply` temperature sensor to use with automations in HomeKit app. |
311
+ | `atwDevices[].inStandbySensor` | This enable `In Standby` sensor to use with automations in HomeKit app. |
312
+ | `ervDevices[].connectSensor` | This enable `Connect` sensor to use with automations in HomeKit app. |
307
313
  | `ervDevices[].errorSensor` | This enable `Error` sensors to use with automations in HomeKit app. |
308
314
  | `ervDevices[].holidayModeSupport` | This enable extra `Holiday Mode` control and sensors to use with automations in HomeKit app. |
309
315
  | `ervDevices[].refreshInterval` | Here set the background devices state refresh time in (sec), default `5s`. |
@@ -395,6 +395,18 @@
395
395
  "default": false,
396
396
  "description": "This enable extra outdoor temperature sensor to use with automations in HomeKit app."
397
397
  },
398
+ "inStandbySensor": {
399
+ "title": "In Standby",
400
+ "type": "boolean",
401
+ "default": false,
402
+ "description": "This enable in standby mode sensor to use with automations in HomeKit app."
403
+ },
404
+ "connectSensor": {
405
+ "title": "Connect",
406
+ "type": "boolean",
407
+ "default": false,
408
+ "description": "This enable connect sensor to use with automations in HomeKit app."
409
+ },
398
410
  "errorSensor": {
399
411
  "title": "Error",
400
412
  "type": "boolean",
@@ -1107,6 +1119,18 @@
1107
1119
  "default": false,
1108
1120
  "description": "This enable extra Return Zone 2 temperature sensor to use with automations in HomeKit app."
1109
1121
  },
1122
+ "inStandbySensor": {
1123
+ "title": "In Standby",
1124
+ "type": "boolean",
1125
+ "default": false,
1126
+ "description": "This enable in standby mode sensor to use with automations in HomeKit app."
1127
+ },
1128
+ "connectSensor": {
1129
+ "title": "Connect",
1130
+ "type": "boolean",
1131
+ "default": false,
1132
+ "description": "This enable connect sensor to use with automations in HomeKit app."
1133
+ },
1110
1134
  "errorSensor": {
1111
1135
  "title": "Error",
1112
1136
  "type": "boolean",
@@ -1579,6 +1603,18 @@
1579
1603
  "default": false,
1580
1604
  "description": "This enable extra supply temperature sensor to use with automations in HomeKit app."
1581
1605
  },
1606
+ "inStandbySensor": {
1607
+ "title": "In Standby",
1608
+ "type": "boolean",
1609
+ "default": false,
1610
+ "description": "This enable in standby mode sensor to use with automations in HomeKit app."
1611
+ },
1612
+ "connectSensor": {
1613
+ "title": "Connect",
1614
+ "type": "boolean",
1615
+ "default": false,
1616
+ "description": "This enable connect sensor to use with automations in HomeKit app."
1617
+ },
1582
1618
  "errorSensor": {
1583
1619
  "title": "Error",
1584
1620
  "type": "boolean",
@@ -2221,6 +2257,8 @@
2221
2257
  {
2222
2258
  "title": "System",
2223
2259
  "items": [
2260
+ "accounts[].ataDevices[].inStandbySensor",
2261
+ "accounts[].ataDevices[].connectSensor",
2224
2262
  "accounts[].ataDevices[].errorSensor"
2225
2263
  ]
2226
2264
  },
@@ -2372,6 +2410,8 @@
2372
2410
  {
2373
2411
  "title": "System",
2374
2412
  "items": [
2413
+ "accounts[].atwDevices[].inStandbySensor",
2414
+ "accounts[].atwDevices[].connectSensor",
2375
2415
  "accounts[].atwDevices[].errorSensor"
2376
2416
  ]
2377
2417
  },
@@ -2516,6 +2556,8 @@
2516
2556
  {
2517
2557
  "title": "System",
2518
2558
  "items": [
2559
+ "accounts[].ervDevices[].inStandbySensor",
2560
+ "accounts[].ervDevices[].connectSensor",
2519
2561
  "accounts[].ervDevices[].errorSensor"
2520
2562
  ]
2521
2563
  },
package/index.js CHANGED
@@ -203,7 +203,7 @@ class MelCloudPlatform {
203
203
  //start impulse generators\
204
204
  const timmers = accountType === 'melcloudhome' ? [{ name: 'connect', sampling: 1800000 }, { name: 'checkDevicesList', sampling: deviceRefreshInterval }] : [{ name: 'checkDevicesList', sampling: refreshInterval }];
205
205
  await melCloud.impulseGenerator.state(true, timmers, false);
206
- await configuredDevice.startStopImpulseGenerator(true, [{ name: 'checkState', sampling: deviceRefreshInterval }]);
206
+ await configuredDevice.startStopImpulseGenerator(true, [{ name: 'checkState', sampling: deviceRefreshInterval + 500 }]);
207
207
 
208
208
  //stop impulse generator
209
209
  await impulseGenerator.state(false);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "displayName": "MELCloud Control",
3
3
  "name": "homebridge-melcloud-control",
4
- "version": "4.2.2-beta.1",
4
+ "version": "4.2.2-beta.10",
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
@@ -35,6 +35,8 @@ class DeviceAta extends EventEmitter {
35
35
  this.autoDryFanMode = device.autoDryFanMode || 1; //NONE, AUTO, DRY, FAN
36
36
  this.temperatureSensor = device.temperatureSensor || false;
37
37
  this.temperatureOutdoorSensor = device.temperatureOutdoorSensor || false;
38
+ this.inStandbySensor = device.inStandbySensor || false;
39
+ this.connectSensor = device.connectSensor || false;
38
40
  this.errorSensor = device.errorSensor || false;
39
41
  this.frostProtectionSupport = device.frostProtectionSupport || false;
40
42
  this.overheatProtectionSupport = device.overheatProtectionSupport || false;
@@ -655,10 +657,38 @@ class DeviceAta extends EventEmitter {
655
657
  accessory.addService(this.outdoorTemperatureSensorService);
656
658
  };
657
659
 
660
+ //connect sensor
661
+ if (this.inStandbySensor && this.accessory.inStandbyMode !== null) {
662
+ if (this.logDebug) this.emit('debug', `Prepare in standby mode service`);
663
+ this.inStandbyService = new Service.ContactSensor(`${serviceName} In Standby`, `inStandbyService${deviceId}`);
664
+ this.inStandbyService.addOptionalCharacteristic(Characteristic.ConfiguredName);
665
+ this.inStandbyService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} In Standby`);
666
+ this.inStandbyService.getCharacteristic(Characteristic.ContactSensorState)
667
+ .onGet(async () => {
668
+ const state = this.accessory.isConnected;
669
+ return state;
670
+ })
671
+ accessory.addService(this.inStandbyService);
672
+ }
673
+
674
+ //connect sensor
675
+ if (this.connectSensor && this.accessory.isConnected !== null) {
676
+ if (this.logDebug) this.emit('debug', `Prepare connect service`);
677
+ this.connectService = new Service.ContactSensor(`${serviceName} Connected`, `connectService${deviceId}`);
678
+ this.connectService.addOptionalCharacteristic(Characteristic.ConfiguredName);
679
+ this.connectService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Connected`);
680
+ this.connectService.getCharacteristic(Characteristic.ContactSensorState)
681
+ .onGet(async () => {
682
+ const state = this.accessory.isConnected;
683
+ return state;
684
+ })
685
+ accessory.addService(this.connectService);
686
+ }
687
+
658
688
  //error sensor
659
689
  if (this.errorSensor && this.accessory.isInError !== null) {
660
690
  if (this.logDebug) this.emit('debug', `Prepare error service`);
661
- this.errorService = new Service.ContactSensor(`${serviceName} Error`, `Error Sensor ${deviceId}`);
691
+ this.errorService = new Service.ContactSensor(`${serviceName} Error`, `errorService${deviceId}`);
662
692
  this.errorService.addOptionalCharacteristic(Characteristic.ConfiguredName);
663
693
  this.errorService.setCharacteristic(Characteristic.ConfiguredName, `${accessoryName} Error`);
664
694
  this.errorService.getCharacteristic(Characteristic.ContactSensorState)
@@ -1206,16 +1236,19 @@ class DeviceAta extends EventEmitter {
1206
1236
  this.deviceData = deviceData;
1207
1237
 
1208
1238
  //keys
1209
- const fanKey = this.accountType === 'melcloud' ? 'FanSpeed' : 'SetFanSpeed';
1210
- const tempStepKey = this.accountType === 'melcloud' ? 'TemperatureIncrement' : 'HasHalfDegreeIncrements';
1211
- const errorKey = this.accountType === 'melcloud' ? 'HasError' : 'IsInError';
1212
- const supportAirDirectionKey = this.accountType === 'melcloud' ? 'AirDirectionFunction' : 'HasAirDirectionFunction';
1213
- const supportSwingKey = this.accountType === 'melcloud' ? 'SwingFunction' : 'HasSwing';
1214
- const supportVideWaneKey = this.accountType === 'melcloud' ? 'ModelSupportsWideVane' : 'SupportsWideVane';
1215
- const supportAutoKey = this.accountType === 'melcloud' ? 'ModelSupportsAuto' : 'HasAutoOperationMode';
1216
- const supportHeatKey = this.accountType === 'melcloud' ? 'ModelSupportsHeat' : 'HasHeatOperationMode';
1217
- const supportDryKey = this.accountType === 'melcloud' ? 'ModelSupportsDry' : 'HasDryOperationMode';
1218
- const supportCoolKey = this.accountType === 'melcloud' ? 'ModelSupportsCool' : 'HasCoolOperationMode';
1239
+ const accountTypeMelcloud = this.accountType === 'melcloud';
1240
+ const fanKey = accountTypeMelcloud ? 'FanSpeed' : 'SetFanSpeed';
1241
+ const tempStepKey = accountTypeMelcloud ? 'TemperatureIncrement' : 'HasHalfDegreeIncrements';
1242
+ const connectKey = accountTypeMelcloud ? 'Offline' : 'IsConnected';
1243
+ const errorKey = accountTypeMelcloud ? 'HasError' : 'IsInError';
1244
+ const supportAirDirectionKey = accountTypeMelcloud ? 'AirDirectionFunction' : 'HasAirDirectionFunction';
1245
+ const supportSwingKey = accountTypeMelcloud ? 'SwingFunction' : 'HasSwing';
1246
+ const supportVideWaneKey = accountTypeMelcloud ? 'ModelSupportsWideVane' : 'SupportsWideVane';
1247
+ const supportAutoKey = accountTypeMelcloud ? 'ModelSupportsAuto' : 'HasAutoOperationMode';
1248
+ const supportHeatKey = accountTypeMelcloud ? 'ModelSupportsHeat' : 'HasHeatOperationMode';
1249
+ const supportDryKey = accountTypeMelcloud ? 'ModelSupportsDry' : 'HasDryOperationMode';
1250
+ const supportCoolKey = accountTypeMelcloud ? 'ModelSupportsCool' : 'HasCoolOperationMode';
1251
+ const supportStandbyKey = accountTypeMelcloud ? 'ModelSupportsStandbyMode' : 'HasStandby';
1219
1252
 
1220
1253
  //presets schedules
1221
1254
  const scheduleEnabled = deviceData.ScheduleEnabled;
@@ -1235,12 +1268,11 @@ class DeviceAta extends EventEmitter {
1235
1268
  const hideDryModeControl = deviceData.HideDryModeControl ?? false;
1236
1269
 
1237
1270
  //device info
1238
- const accountTypeMelcloud = this.accountType === 'melcloud';
1239
1271
  const supportsAutomaticFanSpeed = deviceData.Device.HasAutomaticFanSpeed ?? false;
1240
1272
  const supportsAirDirectionFunction = deviceData.Device[supportAirDirectionKey];
1241
1273
  const supportsSwingFunction = deviceData.Device[supportSwingKey];
1242
1274
  const supportsWideVane = deviceData.Device[supportVideWaneKey];
1243
- const supportsOutdoorTemperature = deviceData.Device.HasOutdoorTemperature ?? false;
1275
+ const supportsOutdoorTemperature = deviceData.Device.HasOutdoorTemperature;
1244
1276
  const supportsFanSpeed = accountTypeMelcloud ? deviceData.Device.ModelSupportsFanSpeed : deviceData.Device.NumberOfFanSpeeds > 0;
1245
1277
  const supportsAuto1 = deviceData.Device[supportAutoKey];
1246
1278
  const supportsAuto = this.autoDryFanMode >= 1 && supportsAuto1
@@ -1250,6 +1282,7 @@ class DeviceAta extends EventEmitter {
1250
1282
  const supportsCool1 = deviceData.Device[supportCoolKey];
1251
1283
  const supportsCool = this.coolDryFanMode >= 1 && supportsCool1;
1252
1284
  const numberOfFanSpeeds = supportsFanSpeed ? deviceData.Device.NumberOfFanSpeeds : 0;
1285
+ const supportsStanbyMode = deviceData.Device[supportStandbyKey];
1253
1286
  const minTempHeat = 10;
1254
1287
  const maxTempHeat = 31;
1255
1288
  const minTempCoolDryAuto = 16;
@@ -1257,7 +1290,7 @@ class DeviceAta extends EventEmitter {
1257
1290
 
1258
1291
  //device state
1259
1292
  const power = deviceData.Device.Power ?? false;
1260
- const inStandbyMode = deviceData.Device.InStandbyMode ?? false;
1293
+ const inStandbyMode = deviceData.Device.InStandbyMode;
1261
1294
  const roomTemperature = deviceData.Device.RoomTemperature;
1262
1295
  const setTemperature = deviceData.Device.SetTemperature;
1263
1296
  const defaultHeatingSetTemperature = deviceData.Device.DefaultHeatingSetTemperature;
@@ -1275,6 +1308,7 @@ class DeviceAta extends EventEmitter {
1275
1308
  const prohibitPower = deviceData.Device.ProhibitPower ?? false;
1276
1309
  const temperatureStep = deviceData.Device[tempStepKey] ? 0.5 : 1;
1277
1310
  const outdoorTemperature = deviceData.Device.OutdoorTemperature;
1311
+ const isConnected = accountTypeMelcloud ? !deviceData.Device[connectKey] : deviceData.Device[connectKey];
1278
1312
  const isInError = deviceData.Device[errorKey];
1279
1313
 
1280
1314
  //accessory
@@ -1292,6 +1326,7 @@ class DeviceAta extends EventEmitter {
1292
1326
  supportsHeat: supportsHeat,
1293
1327
  supportsDry: supportsDry,
1294
1328
  supportsCool: supportsCool,
1329
+ supportsStanbyMode: supportsStanbyMode,
1295
1330
  minTempHeat: minTempHeat,
1296
1331
  maxTempHeat: maxTempHeat,
1297
1332
  minTempCoolDryAuto: minTempCoolDryAuto,
@@ -1315,6 +1350,7 @@ class DeviceAta extends EventEmitter {
1315
1350
  temperatureStep: temperatureStep,
1316
1351
  useFahrenheit: this.useFahrenheit,
1317
1352
  temperatureUnit: TemperatureDisplayUnits[this.useFahrenheit],
1353
+ isConnected: isConnected,
1318
1354
  isInError: isInError,
1319
1355
  frostProtectionEnabled: frostProtectionEnabled,
1320
1356
  frostProtectionActive: frostProtectionActive,
@@ -1328,70 +1364,67 @@ class DeviceAta extends EventEmitter {
1328
1364
  //operating mode 0, HEAT, DRY, COOL, 4, 5, 6, FAN, AUTO, ISEE HEAT, ISEE DRY, ISEE COOL
1329
1365
  switch (this.displayType) {
1330
1366
  case 1: //Heater Cooler
1367
+ // Helper to map fan mode (2 or 3) into operation target
1368
+ const resolveTargetOperation = (modeValue, obj) => {
1369
+ return this.autoDryFanMode === modeValue ? 0 : this.heatDryFanMode === modeValue ? 1 : this.coolDryFanMode === modeValue ? 2 : (obj.targetOperationMode ?? 0);
1370
+ };
1371
+
1331
1372
  switch (operationMode) {
1332
- case 1: //HEAT
1333
- obj.currentOperationMode = roomTemperature > setTemperature ? 1 : 2; //INACTIVE, IDLE, HEATING, COOLING
1334
- obj.targetOperationMode = 1; //AUTO, HEAT, COOL
1373
+ case 1: // HEAT
1374
+ obj.currentOperationMode = roomTemperature > setTemperature ? 1 : 2;
1375
+ obj.targetOperationMode = 1;
1335
1376
  break;
1336
- case 2: //DRY
1377
+ case 2: // DRY
1337
1378
  obj.currentOperationMode = 1;
1338
- obj.targetOperationMode = this.autoDryFanMode === 2 ? 0 : this.heatDryFanMode === 2 ? 1 : this.coolDryFanMode === 2 ? 2 : obj.targetOperationMode ?? 0;
1379
+ obj.targetOperationMode = resolveTargetOperation(2, obj);
1339
1380
  break;
1340
- case 3: //COOL
1381
+ case 3: // COOL
1341
1382
  obj.currentOperationMode = roomTemperature < setTemperature ? 1 : 3;
1342
1383
  obj.targetOperationMode = 2;
1343
1384
  break;
1344
- case 7: //FAN
1385
+ case 7: // FAN
1345
1386
  obj.currentOperationMode = 1;
1346
- obj.targetOperationMode = this.autoDryFanMode === 3 ? 0 : this.heatDryFanMode === 3 ? 1 : this.coolDryFanMode === 3 ? 2 : obj.targetOperationMode ?? 0;
1387
+ obj.targetOperationMode = resolveTargetOperation(3, obj);
1347
1388
  break;
1348
- case 8: //AUTO
1389
+ case 8: // AUTO
1349
1390
  obj.currentOperationMode = roomTemperature > setTemperature ? 3 : roomTemperature < setTemperature ? 2 : 1;
1350
1391
  obj.targetOperationMode = 0;
1351
1392
  break;
1352
- case 9: //ISEE HEAT
1353
- obj.currentOperationMode = roomTemperature > setTemperature ? 1 : 2
1393
+ case 9: // ISEE HEAT
1394
+ obj.currentOperationMode = roomTemperature > setTemperature ? 1 : 2;
1354
1395
  obj.targetOperationMode = 1;
1355
1396
  break;
1356
- case 10: //ISEE DRY
1397
+ case 10: // ISEE DRY
1357
1398
  obj.currentOperationMode = 1;
1358
- obj.targetOperationMode = this.autoDryFanMode === 2 ? 0 : this.heatDryFanMode === 2 ? 1 : this.coolDryFanMode === 2 ? 2 : obj.targetOperationMode ?? 0;
1399
+ obj.targetOperationMode = resolveTargetOperation(2, obj);
1359
1400
  break;
1360
- case 11: //ISEE COOL;
1401
+ case 11: // ISEE COOL
1361
1402
  obj.currentOperationMode = roomTemperature < setTemperature ? 1 : 3;
1362
1403
  obj.targetOperationMode = 2;
1363
1404
  break;
1364
1405
  default:
1365
1406
  if (this.logWarn) this.emit('warn', `Unknown operating mode: ${operationMode}`);
1366
- return
1367
- };
1407
+ }
1408
+
1368
1409
 
1369
- obj.currentOperationMode = !power ? 0 : inStandbyMode ? 1 : obj.currentOperationMode;
1410
+ obj.currentOperationMode = !power ? 0 : (inStandbyMode ? 1 : obj.currentOperationMode);
1370
1411
  obj.operationModeSetPropsMinValue = supportsAuto && supportsHeat ? 0 : !supportsAuto && supportsHeat ? 1 : supportsAuto && !supportsHeat ? 0 : 2;
1371
1412
  obj.operationModeSetPropsMaxValue = 2
1372
1413
  obj.operationModeSetPropsValidValues = supportsAuto && supportsHeat ? [0, 1, 2] : !supportsAuto && supportsHeat ? [1, 2] : supportsAuto && !supportsHeat ? [0, 2] : [2];
1373
1414
 
1374
1415
  //fan speed mode
1375
1416
  if (supportsFanSpeed) {
1376
- switch (numberOfFanSpeeds) {
1377
- case 2: //Fan speed mode 2
1378
- obj.currentFanSpeed = supportsAutomaticFanSpeed ? [3, 1, 2][setFanSpeed] : [0, 1, 2][setFanSpeed];
1379
- obj.fanSpeedSetPropsMaxValue = supportsAutomaticFanSpeed ? 3 : 2;
1380
- break;
1381
- case 3: //Fan speed mode 3
1382
- obj.currentFanSpeed = supportsAutomaticFanSpeed ? [4, 1, 2, 3][setFanSpeed] : [0, 1, 2, 3][setFanSpeed];
1383
- obj.fanSpeedSetPropsMaxValue = supportsAutomaticFanSpeed ? 4 : 3;
1384
- break;
1385
- case 4: //Fan speed mode 4
1386
- obj.currentFanSpeed = supportsAutomaticFanSpeed ? [5, 1, 2, 3, 4][setFanSpeed] : [0, 1, 2, 3, 4][setFanSpeed];
1387
- obj.fanSpeedSetPropsMaxValue = supportsAutomaticFanSpeed ? 5 : 4;
1388
- break;
1389
- case 5: //Fan speed mode 5
1390
- obj.currentFanSpeed = supportsAutomaticFanSpeed ? [6, 1, 2, 3, 4, 5][setFanSpeed] : [0, 1, 2, 3, 4, 5][setFanSpeed];
1391
- obj.fanSpeedSetPropsMaxValue = supportsAutomaticFanSpeed ? 6 : 5;
1392
- break;
1393
- };
1394
- };
1417
+ const max = numberOfFanSpeeds;
1418
+ const autoIndex = supportsAutomaticFanSpeed ? max + 1 : 0;
1419
+ const speeds = [autoIndex];
1420
+
1421
+ for (let i = 1; i <= max; i++) {
1422
+ speeds.push(i);
1423
+ }
1424
+
1425
+ obj.currentFanSpeed = speeds[setFanSpeed];
1426
+ obj.fanSpeedSetPropsMaxValue = supportsAutomaticFanSpeed ? max + 1 : max;
1427
+ }
1395
1428
 
1396
1429
  //update characteristics
1397
1430
  this.melCloudService
@@ -1407,43 +1440,57 @@ class DeviceAta extends EventEmitter {
1407
1440
  if (supportsSwingFunction) this.melCloudService?.updateCharacteristic(Characteristic.SwingMode, obj.currentSwingMode);
1408
1441
  break;
1409
1442
  case 2: //Thermostat
1443
+ // Helper for mapping target operation in DRY / FAN modes
1444
+ const resolveTargetOperation1 = (modeValue, obj) => {
1445
+ return this.autoDryFanMode === modeValue ? 3 : this.heatDryFanMode === modeValue ? 1 : this.coolDryFanMode === modeValue ? 2 : (obj.targetOperationMode ?? 0);
1446
+ };
1447
+
1410
1448
  switch (operationMode) {
1411
- case 1: //HEAT
1412
- obj.currentOperationMode = roomTemperature > setTemperature ? 0 : 1; //OFF, HEATING, COOLING
1413
- obj.targetOperationMode = 1; //OFF, HEAT, COOL, AUTO
1449
+ case 1: // HEAT
1450
+ obj.currentOperationMode = roomTemperature > setTemperature ? 0 : 1;
1451
+ obj.targetOperationMode = 1;
1414
1452
  break;
1415
- case 2: //DRY
1453
+
1454
+ case 2: // DRY
1416
1455
  obj.currentOperationMode = 0;
1417
- obj.targetOperationMode = this.autoDryFanMode === 2 ? 3 : this.heatDryFanMode === 2 ? 1 : this.coolDryFanMode === 2 ? 2 : obj.targetOperationMode ?? 0;
1456
+ obj.targetOperationMode = resolveTargetOperation1(2, obj);
1418
1457
  break;
1419
- case 3: //COOL
1458
+
1459
+ case 3: // COOL
1420
1460
  obj.currentOperationMode = roomTemperature < setTemperature ? 0 : 2;
1421
1461
  obj.targetOperationMode = 2;
1422
1462
  break;
1423
- case 7: //FAN
1463
+
1464
+ case 7: // FAN
1424
1465
  obj.currentOperationMode = 0;
1425
- obj.targetOperationMode = this.autoDryFanMode === 3 ? 3 : this.heatDryFanMode === 3 ? 1 : this.coolDryFanMode === 3 ? 2 : obj.targetOperationMode ?? 0;
1466
+ obj.targetOperationMode = resolveTargetOperation1(3, obj);
1426
1467
  break;
1427
- case 8: //AUTO
1468
+
1469
+ case 8: // AUTO
1428
1470
  obj.currentOperationMode = roomTemperature < setTemperature ? 1 : roomTemperature > setTemperature ? 2 : 0;
1429
1471
  obj.targetOperationMode = 3;
1430
1472
  break;
1431
- case 9: //ISEE HEAT
1473
+
1474
+ case 9: // ISEE HEAT
1432
1475
  obj.currentOperationMode = roomTemperature > setTemperature ? 0 : 1;
1433
1476
  obj.targetOperationMode = 1;
1434
1477
  break;
1435
- case 10: //ISEE DRY
1478
+
1479
+ case 10: // ISEE DRY
1436
1480
  obj.currentOperationMode = 0;
1437
- obj.targetOperationMode = this.autoDryFanMode === 2 ? 3 : this.heatDryFanMode === 2 ? 1 : this.coolDryFanMode === 2 ? 2 : obj.targetOperationMode ?? 0;
1481
+ obj.targetOperationMode = resolveTargetOperation1(2, obj);
1438
1482
  break;
1439
- case 11: //ISEE COOL;
1483
+
1484
+ case 11: // ISEE COOL
1440
1485
  obj.currentOperationMode = roomTemperature < setTemperature ? 0 : 2;
1441
1486
  obj.targetOperationMode = 2;
1442
1487
  break;
1488
+
1443
1489
  default:
1444
1490
  if (this.logWarn) this.emit('warn', `Unknown operating mode: ${operationMode}`);
1445
1491
  break;
1446
- };
1492
+ }
1493
+
1447
1494
 
1448
1495
  obj.currentOperationMode = !power ? 0 : obj.currentOperationMode;
1449
1496
  obj.targetOperationMode = !power ? 0 : obj.targetOperationMode;
@@ -1462,9 +1509,11 @@ class DeviceAta extends EventEmitter {
1462
1509
  };
1463
1510
  this.accessory = obj;
1464
1511
 
1465
- //senors
1512
+ //other sensors
1466
1513
  this.roomTemperatureSensorService?.updateCharacteristic(Characteristic.CurrentTemperature, roomTemperature);
1467
1514
  this.outdoorTemperatureSensorService?.updateCharacteristic(Characteristic.CurrentTemperature, outdoorTemperature);
1515
+ this.inStandbyService?.updateCharacteristic(Characteristic.ContactSensorState, inStandbyMode);
1516
+ this.connectService?.updateCharacteristic(Characteristic.ContactSensorState, isConnected);
1468
1517
  this.errorService?.updateCharacteristic(Characteristic.ContactSensorState, isInError);
1469
1518
 
1470
1519
  //frost protection