homebridge-tasmota-control 1.6.15-beta.1 → 1.6.15-beta.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.
@@ -686,23 +686,29 @@
686
686
  ]
687
687
  },
688
688
  {
689
- "title": "AIR DIRECTION EVEN",
689
+ "title": "AIR DIRECTION INDIRECT",
690
690
  "enum": [
691
691
  40
692
692
  ]
693
693
  },
694
694
  {
695
- "title": "AIR DIRECTION INDIRECT",
695
+ "title": "AIR DIRECTION DIRECT",
696
696
  "enum": [
697
697
  41
698
698
  ]
699
699
  },
700
700
  {
701
- "title": "AIR DIRECTION DIRECT",
701
+ "title": "AIR DIRECTION EVEN",
702
702
  "enum": [
703
703
  42
704
704
  ]
705
705
  },
706
+ {
707
+ "title": "AIR DIRECTION OFF",
708
+ "enum": [
709
+ 43
710
+ ]
711
+ },
706
712
  {
707
713
  "title": "LOCK CONTROL All (only as sensor now)",
708
714
  "enum": [
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "displayName": "Tasmota Control",
3
3
  "name": "homebridge-tasmota-control",
4
- "version": "1.6.15-beta.1",
4
+ "version": "1.6.15-beta.3",
5
5
  "description": "Homebridge plugin to control Tasmota flashed devices.",
6
6
  "license": "MIT",
7
7
  "author": "grzegorz914",
package/src/constants.js CHANGED
@@ -62,9 +62,6 @@ export const MiElHVAC = {
62
62
  "right": "HVACSetSwingH%20right",
63
63
  "split": "HVACSetSwingH%20split",
64
64
  "swing": "HVACSetSwingH%20swing",
65
- "even": "HVACSetSwingH%20even",
66
- "indirect": "HVACSetSwingH%20indirect",
67
- "direct": "HVACSetSwingH%20direct",
68
65
  },
69
66
  "SetAirDirection": {
70
67
  "even": "HVACSetSwingH%20even",
package/src/mielhvac.js CHANGED
@@ -200,9 +200,6 @@ class MiElHvac extends EventEmitter {
200
200
  const statusSnsSupported = sensorStatusKeys.includes('StatusSNS');
201
201
  const statusSns = statusSnsSupported ? sensorStatus.StatusSNS : {};
202
202
 
203
- //power
204
- const power1 = powerStatus.POWER == 'ON' ? 1 : 0;
205
-
206
203
  //status SNS
207
204
  const time = statusSns.Time ?? '';
208
205
  const temperatureUnit = statusSns.TempUnit === 'C' ? '°C' : 'F';
@@ -285,7 +282,7 @@ class MiElHvac extends EventEmitter {
285
282
  hideVaneControls: hideVaneControls
286
283
  };
287
284
 
288
- //operation mode
285
+ // Map stages to index safely, fallback to 0 if not found
289
286
  const operationModeStageMap = {
290
287
  'manual': 0,
291
288
  'heat': 2,
@@ -300,37 +297,39 @@ class MiElHvac extends EventEmitter {
300
297
  'auto_cool': 3,
301
298
  'auto_leader': 4
302
299
  };
300
+
301
+ const stageIndex = operationModeStageMap[operationModeStage] ?? 0;
303
302
  switch (operationMode) {
304
303
  case 'heat':
305
- obj.currentOperationMode = [2, 1, 2, 3, 0][operationModeStageMap[operationModeStage]]; //INACTIVE, IDLE, HEATING, COOLING
306
- obj.targetOperationMode = 1; //AUTO, HEAT, COOL
304
+ obj.currentOperationMode = [2, 1, 2, 3, 0][stageIndex]; // INACTIVE, IDLE, HEATING, COOLING
305
+ obj.targetOperationMode = 1; // AUTO, HEAT, COOL
307
306
  break;
308
307
  case 'dry':
309
- obj.currentOperationMode = [1, 1, 2, 3, 0][operationModeStageMap[operationModeStage]];
308
+ obj.currentOperationMode = [1, 1, 2, 3, 0][stageIndex];
310
309
  obj.targetOperationMode = this.autoDryFanMode === 2 ? 0 : this.heatDryFanMode === 2 ? 1 : this.coolDryFanMode === 2 ? 2 : obj.targetOperationMode;
311
310
  break;
312
311
  case 'cool':
313
- obj.currentOperationMode = [3, 1, 2, 3, 0][operationModeStageMap[operationModeStage]];
312
+ obj.currentOperationMode = [3, 1, 2, 3, 0][stageIndex];
314
313
  obj.targetOperationMode = 2;
315
314
  break;
316
315
  case 'fan':
317
- obj.currentOperationMode = [1, 1, 2, 3, 0][operationModeStageMap[operationModeStage]];
316
+ obj.currentOperationMode = [1, 1, 2, 3, 0][stageIndex];
318
317
  obj.targetOperationMode = this.autoDryFanMode === 3 ? 0 : this.heatDryFanMode === 3 ? 1 : this.coolDryFanMode === 3 ? 2 : obj.targetOperationMode;
319
318
  break;
320
319
  case 'auto':
321
- obj.currentOperationMode = [2, 1, 2, 3, 0][operationModeStageMap[operationModeStage]];
320
+ obj.currentOperationMode = [2, 1, 2, 3, 0][stageIndex];
322
321
  obj.targetOperationMode = 0;
323
322
  break;
324
323
  case 'heat_isee':
325
- obj.currentOperationMode = [2, 1, 2, 3, 0][operationModeStageMap[operationModeStage]];
324
+ obj.currentOperationMode = [2, 1, 2, 3, 0][stageIndex];
326
325
  obj.targetOperationMode = 1;
327
326
  break;
328
327
  case 'dry_isee':
329
- obj.currentOperationMode = [1, 1, 2, 3, 0][operationModeStageMap[operationModeStage]];
328
+ obj.currentOperationMode = [1, 1, 2, 3, 0][stageIndex];
330
329
  obj.targetOperationMode = this.autoDryFanMode === 2 ? 0 : this.heatDryFanMode === 2 ? 1 : this.coolDryFanMode === 2 ? 2 : obj.targetOperationMode;
331
330
  break;
332
331
  case 'cool_isee':
333
- obj.currentOperationMode = [3, 1, 2, 3, 0][operationModeStageMap[operationModeStage]];
332
+ obj.currentOperationMode = [3, 1, 2, 3, 0][stageIndex];
334
333
  obj.targetOperationMode = 2;
335
334
  break;
336
335
  default:
@@ -338,392 +337,312 @@ class MiElHvac extends EventEmitter {
338
337
  return;
339
338
  }
340
339
 
340
+ // If power is off, force currentOperationMode to 0 (inactive)
341
341
  obj.currentOperationMode = !power ? 0 : obj.currentOperationMode;
342
+
343
+ // Set min/max/valid values for operation mode controls
342
344
  obj.operationModeSetPropsMinValue = modelSupportsAuto && modelSupportsHeat ? 0 : !modelSupportsAuto && modelSupportsHeat ? 1 : modelSupportsAuto && !modelSupportsHeat ? 0 : 2;
343
- obj.operationModeSetPropsMaxValue = 2
345
+ obj.operationModeSetPropsMaxValue = 2;
344
346
  obj.operationModeSetPropsValidValues = modelSupportsAuto && modelSupportsHeat ? [0, 1, 2] : !modelSupportsAuto && modelSupportsHeat ? [1, 2] : modelSupportsAuto && !modelSupportsHeat ? [0, 2] : [2];
345
347
 
348
+
346
349
  if (modelSupportsFanSpeed) {
347
- //fan speed mode
350
+ // Map fan speed string to index
348
351
  const fanSpeedMap = {
349
352
  'auto': 0,
350
353
  'quiet': 1,
351
354
  '1': 2,
352
355
  '2': 3,
353
356
  '3': 4,
354
- '4': 5
357
+ '4': 5,
358
+ };
359
+
360
+ // Get mapped index, fallback to 0 if not found
361
+ const fanSpeedIndex = fanSpeedMap[fanSpeed] ?? 0;
362
+
363
+ // Function to generate speed arrays dynamically
364
+ const generateSpeedArray = (count, hasAuto) => {
365
+ // if hasAuto, first element is count+1 (offset), else 0
366
+ // Then numbers 1 .. count-1 (except 0 and auto)
367
+ // your original arrays always have [hasAuto ? count+1 : 0, 1, 2, ..., count-1]
368
+ // So let's build that:
369
+ const arr = [];
370
+ if (hasAuto) {
371
+ arr.push(count + 1); // e.g. 3+1=4 for 3 speeds
372
+ } else {
373
+ arr.push(0);
374
+ }
375
+ for (let i = 1; i < count; i++) {
376
+ arr.push(i);
377
+ }
378
+ return arr;
355
379
  };
356
380
 
357
381
  switch (numberOfFanSpeeds) {
358
- case 2: //Fan speed mode 2
359
- obj.fanSpeed = hasAutomaticFanSpeed ? [3, 1, 2][fanSpeedMap[fanSpeed]] : [0, 1, 2][fanSpeedMap[fanSpeed]];
382
+ case 2:
383
+ obj.fanSpeed = generateSpeedArray(3, hasAutomaticFanSpeed)[fanSpeedIndex];
360
384
  obj.fanSpeedSetPropsMaxValue = hasAutomaticFanSpeed ? 3 : 2;
361
385
  break;
362
- case 3: //Fan speed mode 3
363
- obj.fanSpeed = hasAutomaticFanSpeed ? [4, 1, 2, 3][fanSpeedMap[fanSpeed]] : [0, 1, 2, 3][fanSpeedMap[fanSpeed]];
386
+ case 3:
387
+ obj.fanSpeed = generateSpeedArray(4, hasAutomaticFanSpeed)[fanSpeedIndex];
364
388
  obj.fanSpeedSetPropsMaxValue = hasAutomaticFanSpeed ? 4 : 3;
365
389
  break;
366
- case 4: //Fan speed mode 4
367
- obj.fanSpeed = hasAutomaticFanSpeed ? [5, 1, 2, 3, 4][fanSpeedMap[fanSpeed]] : [0, 1, 2, 3, 4][fanSpeedMap[fanSpeed]];
390
+ case 4:
391
+ obj.fanSpeed = generateSpeedArray(5, hasAutomaticFanSpeed)[fanSpeedIndex];
368
392
  obj.fanSpeedSetPropsMaxValue = hasAutomaticFanSpeed ? 5 : 4;
369
393
  break;
370
- case 5: //Fan speed mode 5
371
- obj.fanSpeed = hasAutomaticFanSpeed ? [6, 1, 2, 3, 4, 5][fanSpeedMap[fanSpeed]] : [0, 1, 2, 3, 4, 5][fanSpeedMap[fanSpeed]];
394
+ case 5:
395
+ obj.fanSpeed = generateSpeedArray(6, hasAutomaticFanSpeed)[fanSpeedIndex];
372
396
  obj.fanSpeedSetPropsMaxValue = hasAutomaticFanSpeed ? 6 : 5;
373
397
  break;
398
+ default:
399
+ // Fallback for unexpected fan speed count
400
+ obj.fanSpeed = 0;
401
+ obj.fanSpeedSetPropsMaxValue = 0;
402
+ break;
374
403
  }
375
404
  }
405
+
376
406
  this.mielHvac = obj;
377
407
 
378
408
  //update characteristics
379
409
  if (this.miElHvacService) {
380
- this.miElHvacService
381
- .updateCharacteristic(Characteristic.Active, power)
410
+ const svc = this.miElHvacService;
411
+
412
+ svc.updateCharacteristic(Characteristic.Active, power)
382
413
  .updateCharacteristic(Characteristic.CurrentHeaterCoolerState, obj.currentOperationMode)
383
414
  .updateCharacteristic(Characteristic.TargetHeaterCoolerState, obj.targetOperationMode)
384
415
  .updateCharacteristic(Characteristic.CurrentTemperature, roomTemperature)
385
416
  .updateCharacteristic(Characteristic.LockPhysicalControls, lockPhysicalControl)
386
417
  .updateCharacteristic(Characteristic.TemperatureDisplayUnits, useFahrenheit)
387
418
  .updateCharacteristic(Characteristic.SwingMode, swingMode);
388
- const updateDefCool = obj.targetOperationMode === 0 || obj.targetOperationMode === 2 ? this.miElHvacService.updateCharacteristic(Characteristic.CoolingThresholdTemperature, obj.targetOperationMode === 0 ? defaultCoolingSetTemperature : setTemperature) : false;
389
- const updateDefHeat = obj.targetOperationMode === 0 || obj.targetOperationMode === 1 ? this.miElHvacService.updateCharacteristic(Characteristic.HeatingThresholdTemperature, obj.targetOperationMode === 0 ? defaultHeatingSetTemperature : setTemperature) : false;
390
- const updateRS = modelSupportsFanSpeed ? this.miElHvacService.updateCharacteristic(Characteristic.RotationSpeed, obj.fanSpeed) : false;
419
+
420
+ if (obj.targetOperationMode === 0 || obj.targetOperationMode === 2) {
421
+ svc.updateCharacteristic(
422
+ Characteristic.CoolingThresholdTemperature,
423
+ obj.targetOperationMode === 0 ? defaultCoolingSetTemperature : setTemperature
424
+ );
425
+ }
426
+
427
+ if (obj.targetOperationMode === 0 || obj.targetOperationMode === 1) {
428
+ svc.updateCharacteristic(
429
+ Characteristic.HeatingThresholdTemperature,
430
+ obj.targetOperationMode === 0 ? defaultHeatingSetTemperature : setTemperature
431
+ );
432
+ }
433
+
434
+ if (modelSupportsFanSpeed) {
435
+ svc.updateCharacteristic(Characteristic.RotationSpeed, obj.fanSpeed);
436
+ }
391
437
 
392
438
  if (this.frostProtectEnable) {
393
439
  if (roomTemperature <= this.frostProtectLowTemp && !power) {
394
- this.miElHvacService
395
- .setCharacteristic(Characteristic.Active, true)
440
+ svc.setCharacteristic(Characteristic.Active, true)
396
441
  .setCharacteristic(Characteristic.TargetHeaterCoolerState, 1)
397
442
  .setCharacteristic(Characteristic.HeatingThresholdTemperature, this.frostProtectHighTemp);
398
443
  this.frostProtectActive = true;
399
-
400
444
  }
401
445
 
402
446
  if (roomTemperature >= this.frostProtectHighTemp && this.frostProtectActive) {
403
- this.miElHvacService.setCharacteristic(Characteristic.Active, false);
447
+ svc.setCharacteristic(Characteristic.Active, false);
404
448
  this.frostProtectActive = false;
405
449
  }
406
450
  }
407
451
  }
408
452
 
409
- //update presets state
453
+ // Update presets state
410
454
  if (this.presetsConfiguredCount > 0) {
411
455
  this.presetsConfigured.forEach((preset, index) => {
412
-
413
456
  let iseeMode = operationMode;
414
- iseeMode = (operationMode === 'heat' || operationMode === 'heat_isee') ? 'heat' : iseeMode;
415
- iseeMode = (operationMode === 'dry' || operationMode === 'dry_isee') ? 'dry' : iseeMode;
416
- iseeMode = (operationMode === 'cool' || operationMode === 'cool_isee') ? 'cool' : iseeMode;
457
+ if (iseeMode === 'heat_isee') iseeMode = 'heat';
458
+ else if (iseeMode === 'dry_isee') iseeMode = 'dry';
459
+ else if (iseeMode === 'cool_isee') iseeMode = 'cool';
417
460
 
418
- preset.state = power ? (preset.mode === iseeMode
419
- && (preset.setTemp).toFixed(1) === parseFloat(setTemperature).toFixed(1)
420
- && preset.fanSpeed === fanSpeed
421
- && preset.swingV === vaneVerticalDirection
422
- && preset.swingH === vaneHorizontalDirection) : false;
461
+ const sameTemp = Number(preset.setTemp).toFixed(1) === Number(setTemperature).toFixed(1);
462
+ const sameFan = preset.fanSpeed === fanSpeed;
463
+ const sameSwingV = preset.swingV === vaneVerticalDirection;
464
+ const sameSwingH = preset.swingH === vaneHorizontalDirection;
465
+ const sameMode = preset.mode === iseeMode;
466
+
467
+ preset.state = power ? (sameMode && sameTemp && sameFan && sameSwingV && sameSwingH) : false;
423
468
 
424
469
  if (this.presetsServices) {
425
- const characteristicType = preset.characteristicType;
426
470
  this.presetsServices[index]
427
- .updateCharacteristic(characteristicType, preset.state);
471
+ .updateCharacteristic(preset.characteristicType, preset.state);
428
472
  }
429
473
  });
430
474
  }
431
475
 
432
- //update buttons state
433
476
  if (this.buttonsConfiguredCount > 0) {
477
+ const modeMap = {
478
+ 0: () => power === 1,
479
+ 1: () => power && ['heat', 'heat_isee'].includes(operationMode),
480
+ 2: () => power && ['dry', 'dry_isee'].includes(operationMode),
481
+ 3: () => power && ['cool', 'cool_isee'].includes(operationMode),
482
+ 4: () => power && operationMode === 'fan',
483
+ 5: () => power && operationMode === 'auto',
484
+ 6: () => power && operationMode === 'purify',
485
+ };
486
+
487
+ const vaneHMap = {
488
+ 11: 'left',
489
+ 12: 'left_middle',
490
+ 13: 'center',
491
+ 14: 'right_middle',
492
+ 15: 'right',
493
+ 16: 'split',
494
+ 17: 'swing',
495
+ };
496
+
497
+ const vaneVMap = {
498
+ 20: 'auto',
499
+ 21: 'up',
500
+ 22: 'up_middle',
501
+ 23: 'center',
502
+ 24: 'down_middle',
503
+ 25: 'down',
504
+ 26: 'swing',
505
+ };
506
+
507
+ const fanSpeedMap = {
508
+ 30: 'auto',
509
+ 31: 'quiet',
510
+ 32: '1',
511
+ 33: '2',
512
+ 34: '3',
513
+ 35: '4',
514
+ };
515
+
516
+ const airDirMap = {
517
+ 40: () => power && airDirection === 'indirect',
518
+ 41: () => power && airDirection === 'direct',
519
+ 42: () => power && airDirection === 'even',
520
+ 43: () => power && !['indirect', 'direct', 'even'].includes(airDirection),
521
+ };
522
+
523
+ const prohibitMap = {
524
+ 50: 'all',
525
+ 51: 'power',
526
+ 52: 'mode',
527
+ 53: 'temp',
528
+ };
529
+
434
530
  this.buttonsConfigured.forEach((button, index) => {
435
531
  const mode = button.mode;
436
- switch (mode) {
437
- case 0: //POWER ON,OFF
438
- button.state = power === 1;
439
- break;
440
- case 1: //OPERATING MODE HEAT
441
- button.state = power ? (operationMode === 'heat' || operationMode === 'heat_isee') : false;
442
- break;
443
- case 2: //OPERATING MODE DRY
444
- button.state = power ? (operationMode === 'dry' || operationMode === 'dry_isee') : false;
445
- break
446
- case 3: //OPERATING MODE COOL
447
- button.state = power ? (operationMode === 'cool' || operationMode === 'cool_isee') : false;
448
- break;
449
- case 4: //OPERATING MODE FAN
450
- button.state = power ? (operationMode === 'fan') : false;
451
- break;
452
- case 5: //OPERATING MODE AUTO
453
- button.state = power ? (operationMode === 'auto') : false;
454
- break;
455
- case 6: //OPERATING MODE PURIFY
456
- button.state = power ? (operationMode === 'purify') : false;
457
- break;
458
- case 11: //VANE H LEFT
459
- button.state = power ? (vaneHorizontalDirection === 'left') : false;
460
- break;
461
- case 12: //VANE H LEFT MIDDLE
462
- button.state = power ? (vaneHorizontalDirection === 'left_middle') : false;
463
- break;
464
- case 13: //VANE H CENTER
465
- button.state = power ? (vaneHorizontalDirection === 'center') : false;
466
- break;
467
- case 14: //VANE H RIGHT MIDDLE
468
- button.state = power ? (vaneHorizontalDirection === 'right_middle') : false;
469
- break;
470
- case 15: //VANE H RIGHT
471
- button.state = power ? (vaneHorizontalDirection === 'right') : false;
472
- break;
473
- case 16: //VANE H SPLIT
474
- button.state = power ? (vaneHorizontalDirection === 'split') : false;
475
- break;
476
- case 17: //VANE H SWING
477
- button.state = power ? (vaneHorizontalDirection === 'swing') : false;
478
- break;
479
- case 20: //VANE V AUTO
480
- button.state = power ? (vaneVerticalDirection === 'auto') : false;
481
- break;
482
- case 21: //VANE V UP
483
- button.state = power ? (vaneVerticalDirection === 'up') : false;
484
- break;
485
- case 22: //VANE V UP MIDDLE
486
- button.state = power ? (vaneVerticalDirection === 'up_middle') : false;
487
- break;
488
- case 23: //VANE V CENTER
489
- button.state = power ? (vaneVerticalDirection === 'center') : false;
490
- break;
491
- case 24: //VANE V DOWN MIDDLE
492
- button.state = power ? (vaneVerticalDirection === 'down_middle') : false;
493
- break;
494
- case 25: //VANE V DOWN
495
- button.state = power ? (vaneVerticalDirection === 'down') : false;
496
- break;
497
- case 26: //VANE V SWING
498
- button.state = power ? (vaneVerticalDirection === 'swing') : false;
499
- break;
500
- case 30: //FAN SPEED MODE AUTO
501
- button.state = power ? (fanSpeed === 'auto') : false;
502
- break;
503
- case 31: //FAN SPEED MODE 1
504
- button.state = power ? (fanSpeed === 'quiet') : false;
505
- break;
506
- case 32: //FAN SPEED MODE 2
507
- button.state = power ? (fanSpeed === '1') : false;
508
- break;
509
- case 33: //FAN SPEED MODE 3
510
- button.state = power ? (fanSpeed === '2') : false;
511
- break;
512
- case 34: //FAN SPEED MODE 4
513
- button.state = power ? (fanSpeed === '3') : false;
514
- break;
515
- case 35: //FAN SPEED MODE 5
516
- button.state = power ? (fanSpeed === '4') : false;
517
- break;
518
- case 40: //AIR DIRECTION EVEN
519
- button.state = power ? (airDirection === 'even') : false;
520
- break;
521
- case 41: //AIR DIRECTION INDIRECT
522
- button.state = power ? (airDirection === 'indirect') : false;
523
- break;
524
- case 42: //AIR DIRECTION DIRECT
525
- button.state = power ? (airDirection === 'direct') : false;
526
- break;
527
- case 50: //PHYSICAL LOCK CONTROLS ALL
528
- button.state = prohibit === 'all';
529
- break;
530
- case 51: //PHYSICAL LOCK CONTROLS POWER
531
- button.state = prohibit === 'power';
532
- break;
533
- case 52: //PHYSICAL LOCK CONTROLS MODE
534
- button.state = prohibit === 'mode';
535
- break;
536
- case 53: //PHYSICAL LOCK CONTROLS TEMP
537
- button.state = prohibit === 'temp';
538
- break;
539
- default: //Unknown button
540
- this.emit('warn', `Unknown button mode: ${mode} detected`);
541
- break;
532
+ let state = false;
533
+
534
+ if (modeMap[mode] !== undefined) {
535
+ state = modeMap[mode]();
536
+ } else if (vaneHMap[mode]) {
537
+ state = power && vaneHorizontalDirection === vaneHMap[mode];
538
+ } else if (vaneVMap[mode]) {
539
+ state = power && vaneVerticalDirection === vaneVMap[mode];
540
+ } else if (fanSpeedMap[mode]) {
541
+ state = power && fanSpeed === fanSpeedMap[mode];
542
+ } else if (airDirMap[mode]) {
543
+ state = airDirMap[mode]();
544
+ } else if (prohibitMap[mode] !== undefined) {
545
+ state = prohibit === prohibitMap[mode];
546
+ } else {
547
+ this.emit('warn', `Unknown button mode: ${mode} detected`);
542
548
  }
543
549
 
544
- //update services
550
+ button.state = state;
551
+
545
552
  if (this.buttonsServices) {
546
553
  const characteristicType = button.characteristicType;
547
554
  this.buttonsServices[index]
548
- .updateCharacteristic(characteristicType, button.state);
555
+ .updateCharacteristic(characteristicType, state);
549
556
  }
550
557
  });
551
558
  }
552
559
 
553
- //update sensors state
554
560
  if (this.sensorsConfiguredCount > 0) {
561
+ const powerOn = power === 1;
562
+
563
+ // Helper: match by value with power check
564
+ const is = (val, match) => powerOn && val === match;
565
+ const isOneOf = (val, matches) => powerOn && matches.includes(val);
566
+
555
567
  this.sensorsConfigured.forEach((sensor, index) => {
556
568
  const mode = sensor.mode;
557
- switch (mode) {
558
- case 0: //POWER ON,OFF
559
- sensor.state = power === 1;
560
- break;
561
- case 1: //OPERATING MODE HEAT
562
- sensor.state = power ? (operationMode === 'heat' || operationMode === 'heat_isee') : false;
563
- break;
564
- case 2: //OPERATING MODE DRY
565
- sensor.state = power ? (operationMode === 'dry' || operationMode === 'dry_isee') : false;
566
- break
567
- case 3: //OPERATING MODE COOL
568
- sensor.state = power ? (operationMode === 'cool' || operationMode === 'cool_isee') : false;
569
- break;
570
- case 4: //OPERATING MODE FAN
571
- sensor.state = power ? (operationMode === 'fan') : false;
572
- break;
573
- case 5: //OPERATING MODE AUTO
574
- sensor.state = power ? (operationMode === 'auto') : false;
575
- break;
576
- case 6: //OPERATING MODE PURIFY
577
- sensor.state = power ? (operationMode === 'purify') : false;
578
- break;
579
- case 10: //VANE H AUTO
580
- sensor.state = power ? (vaneHorizontalDirection === 'auto') : false;
581
- break;
582
- case 11: //VANE H LEFT
583
- sensor.state = power ? (vaneHorizontalDirection === 'left') : false;
584
- break;
585
- case 12: //VANE H LEFT MIDDLE
586
- sensor.state = power ? (vaneHorizontalDirection === 'left_middle') : false;
587
- break;
588
- case 13: //VANE H CENTER
589
- sensor.state = power ? (vaneHorizontalDirection === 'center') : false;
590
- break;
591
- case 14: //VANE H RIGHT MIDDLE
592
- sensor.state = power ? (vaneHorizontalDirection === 'right_middle') : false;
593
- break;
594
- case 15: //VANE H RIGHT
595
- sensor.state = power ? (vaneHorizontalDirection === 'right') : false;
596
- break;
597
- case 16: //VANE H SPLIT
598
- sensor.state = power ? (vaneHorizontalDirection === 'split') : false;
599
- break;
600
- case 17: //VANE H SWING
601
- sensor.state = power ? (vaneHorizontalDirection === 'swing') : false;
602
- break;
603
- case 20: //VANE V AUTO
604
- sensor.state = power ? (vaneVerticalDirection === 'auto') : false;
605
- break;
606
- case 21: //VANE V UP
607
- sensor.state = power ? (vaneVerticalDirection === 'up') : false;
608
- break;
609
- case 22: //VANE V UP MIDDLE
610
- sensor.state = power ? (vaneVerticalDirection === 'up_middle') : false;
611
- break;
612
- case 23: //VANE V CENTER
613
- sensor.state = power ? (vaneVerticalDirection === 'center') : false;
614
- break;
615
- case 24: //VANE V DOWN MIDDLE
616
- sensor.state = power ? (vaneVerticalDirection === 'down_middle') : false;
617
- break;
618
- case 25: //VANE V DOWN
619
- sensor.state = power ? (vaneVerticalDirection === 'down') : false;
620
- break;
621
- case 26: //VANE V SWING
622
- sensor.state = power ? (vaneVerticalDirection === 'swing') : false;
623
- break;
624
- case 27: //VANE H/V CONTROLS HIDE
625
- sensor.state = power ? (hideVaneControls === true) : false;
626
- break;
627
- case 30: //FAN SPEED MODE AUTO
628
- sensor.state = power ? (fanSpeed === 'auto') : false;
629
- break;
630
- case 31: //FAN SPEED MODE 1
631
- sensor.state = power ? (fanSpeed === 'quiet') : false;
632
- break;
633
- case 32: //FAN SPEED MODE 2
634
- sensor.state = power ? (fanSpeed === '1') : false;
635
- break;
636
- case 33: //FAN SPEED MODE 3
637
- sensor.state = power ? (fanSpeed === '2') : false;
638
- break;
639
- case 34: //FAN SPEED MODE 4
640
- sensor.state = power ? (fanSpeed === '3') : false;
641
- break;
642
- case 35: //FAN SPEED MODE 5
643
- sensor.state = power ? (fanSpeed === '4') : false;
644
- break;
645
- case 40: //AIR DIRECTION EVEN
646
- sensor.state = power ? (airDirection === 'even') : false;
647
- break;
648
- case 41: //AIR DIRECTION INDIRECT
649
- sensor.state = power ? (airDirection === 'indirect') : false;
650
- break;
651
- case 42: //AIR DIRECTION DIRECT
652
- sensor.state = power ? (airDirection === 'direct') : false;
653
- break;
654
- case 50: //PHYSICAL LOCK CONTROLS ALL
655
- sensor.state = prohibit === 'all';
656
- break;
657
- case 51: //PHYSICAL LOCK CONTROLS POWER
658
- sensor.state = prohibit === 'power';
659
- break;
660
- case 52: //PHYSICAL LOCK CONTROLS MODE
661
- sensor.state = prohibit === 'mode';
662
- break;
663
- case 53: //PHYSICAL LOCK CONTROLS TEMP
664
- sensor.state = prohibit === 'temp';
665
- break;
666
- case 60: //REMOTE TEMPERATURE STATE
667
- sensor.state = remoteTemperatureSensorState;
668
- break;
669
- case 70: //OPERATION STAGE NORMAL
670
- sensor.state = operationStage === 'normal';
671
- break;
672
- case 71: //OPERATION STAGE DEFROST
673
- sensor.state = operationStage === 'defrost';
674
- break;
675
- case 72: //OPERATION STAGE PREHEAT
676
- sensor.state = operationStage === 'preheat';
677
- break;
678
- case 73: //OPERATION STAGE STANDBY
679
- sensor.state = operationStage === 'standby';
680
- break;
681
- case 80: //FAN STAGE OFF
682
- sensor.state = fanSpeedStage === 'off';
683
- break;
684
- case 81: //FAN STAGE QUIET
685
- sensor.state = fanSpeedStage === 'quiet';;
686
- break;
687
- case 82: //FAN STAGE 1
688
- sensor.state = fanSpeedStage === '1';;
689
- break;
690
- case 83: //FAN STAGE 2
691
- sensor.state = fanSpeedStage === '2';;
692
- break;
693
- case 84: //FAN STAGE 3
694
- sensor.state = fanSpeedStage === '3';;
695
- break;
696
- case 85: //FAN STAGE 4
697
- sensor.state = fanSpeedStage === '4';;
698
- break;
699
- case 86: //FAN STAGE 5
700
- sensor.state = fanSpeedStage === '5';;
701
- break;
702
- case 90: //MODE STAGE AUTO OFF
703
- sensor.state = operationMode !== 'auto';
704
- break;
705
- case 91: //MODE STAGE AUTO FAN
706
- sensor.state = operationModeStage === 'auto_fan';
707
- break;
708
- case 92: //MODE STAGE AUTO HEAT
709
- sensor.state = operationModeStage === 'auto_heat';
710
- break;
711
- case 93: //MODE STAGE AUTO COOL
712
- sensor.state = operationModeStage === 'auto_cool';;
713
- break;
714
- case 94: //MODE STAGE AUTO LEADER
715
- sensor.state = operationModeStage === 'auto_leader';;
716
- break;
717
- default: //Unknown sensor
718
- this.emit('warn', `Unknown sensor mode: ${mode} detected`);
719
- break;
569
+
570
+ const sensorStates = {
571
+ 0: powerOn,
572
+ 1: isOneOf(operationMode, ['heat', 'heat_isee']),
573
+ 2: isOneOf(operationMode, ['dry', 'dry_isee']),
574
+ 3: isOneOf(operationMode, ['cool', 'cool_isee']),
575
+ 4: is(operationMode, 'fan'),
576
+ 5: is(operationMode, 'auto'),
577
+ 6: is(operationMode, 'purify'),
578
+
579
+ 11: is(vaneHorizontalDirection, 'left'),
580
+ 12: is(vaneHorizontalDirection, 'left_middle'),
581
+ 13: is(vaneHorizontalDirection, 'center'),
582
+ 14: is(vaneHorizontalDirection, 'right_middle'),
583
+ 15: is(vaneHorizontalDirection, 'right'),
584
+ 16: is(vaneHorizontalDirection, 'split'),
585
+ 17: is(vaneHorizontalDirection, 'swing'),
586
+
587
+ 20: is(vaneVerticalDirection, 'auto'),
588
+ 21: is(vaneVerticalDirection, 'up'),
589
+ 22: is(vaneVerticalDirection, 'up_middle'),
590
+ 23: is(vaneVerticalDirection, 'center'),
591
+ 24: is(vaneVerticalDirection, 'down_middle'),
592
+ 25: is(vaneVerticalDirection, 'down'),
593
+ 26: is(vaneVerticalDirection, 'swing'),
594
+
595
+ 27: is(hideVaneControls, true),
596
+
597
+ 30: is(fanSpeed, 'auto'),
598
+ 31: is(fanSpeed, 'quiet'),
599
+ 32: is(fanSpeed, '1'),
600
+ 33: is(fanSpeed, '2'),
601
+ 34: is(fanSpeed, '3'),
602
+ 35: is(fanSpeed, '4'),
603
+
604
+ 40: is(airDirection, 'indirect'),
605
+ 41: is(airDirection, 'direct'),
606
+ 42: is(airDirection, 'even'),
607
+ 43: powerOn && !['indirect', 'direct', 'even'].includes(airDirection),
608
+
609
+ 50: prohibit === 'all',
610
+ 51: prohibit === 'power',
611
+ 52: prohibit === 'mode',
612
+ 53: prohibit === 'temp',
613
+
614
+ 60: remoteTemperatureSensorState,
615
+
616
+ 70: operationStage === 'normal',
617
+ 71: operationStage === 'defrost',
618
+ 72: operationStage === 'preheat',
619
+ 73: operationStage === 'standby',
620
+
621
+ 80: fanSpeedStage === 'off',
622
+ 81: fanSpeedStage === 'quiet',
623
+ 82: fanSpeedStage === '1',
624
+ 83: fanSpeedStage === '2',
625
+ 84: fanSpeedStage === '3',
626
+ 85: fanSpeedStage === '4',
627
+ 86: fanSpeedStage === '5',
628
+
629
+ 90: operationMode !== 'auto',
630
+ 91: operationModeStage === 'auto_fan',
631
+ 92: operationModeStage === 'auto_heat',
632
+ 93: operationModeStage === 'auto_cool',
633
+ 94: operationModeStage === 'auto_leader',
634
+ };
635
+
636
+ if (mode in sensorStates) {
637
+ sensor.state = sensorStates[mode];
638
+ } else {
639
+ this.emit('warn', `Unknown sensor mode: ${mode} detected`);
720
640
  }
721
641
 
722
- //update services
642
+ // Update characteristic
723
643
  if (this.sensorsServices) {
724
644
  const characteristicType = sensor.characteristicType;
725
- this.sensorsServices[index]
726
- .updateCharacteristic(characteristicType, sensor.state);
645
+ this.sensorsServices[index]?.updateCharacteristic(characteristicType, sensor.state);
727
646
  }
728
647
  });
729
648
  }
@@ -1066,242 +985,175 @@ class MiElHvac extends EventEmitter {
1066
985
 
1067
986
  //presets services
1068
987
  if (this.presetsConfiguredCount > 0) {
1069
- const debug = this.enableDebugMode ? this.emit('debug', `Prepare presets services`) : false;
988
+ if (this.enableDebugMode) this.emit('debug', 'Prepare presets services');
1070
989
  this.presetsServices = [];
1071
990
 
1072
991
  this.presetsConfigured.forEach((preset, index) => {
1073
- //get preset name
1074
- const presetName = preset.name;
992
+ const { name: presetName, namePrefix, serviceType, characteristicType, mode, setTemp, fanSpeed, swingV, swingH } = preset;
993
+ const serviceName = namePrefix ? `${accessoryName} ${presetName}` : presetName;
1075
994
 
1076
- //get preset name prefix
1077
- const presetNamePrefix = preset.namePrefix;
1078
-
1079
- const serviceName = presetNamePrefix ? `${accessoryName} ${presetName}` : presetName;
1080
- const serviceType = preset.serviceType;
1081
- const characteristicType = preset.characteristicType;
1082
995
  const presetService = new serviceType(serviceName, `Preset ${index}`);
1083
996
  presetService.addOptionalCharacteristic(Characteristic.ConfiguredName);
1084
997
  presetService.setCharacteristic(Characteristic.ConfiguredName, serviceName);
998
+
1085
999
  presetService.getCharacteristic(characteristicType)
1086
- .onGet(async () => {
1087
- const state = preset.state;
1088
- return state;
1089
- })
1000
+ .onGet(async () => preset.state)
1090
1001
  .onSet(async (state) => {
1091
1002
  try {
1092
- let data = '';
1093
- switch (state) {
1094
- case true:
1095
- const setPower = !this.mielHvac.power ? await this.axiosInstance(MiElHVAC.PowerOn) : false;
1096
- data = MiElHVAC.SetMode[preset.mode];
1097
- await this.axiosInstance(data);
1098
- data = `${MiElHVAC.SetTemp}${preset.setTemp}`;
1099
- await this.axiosInstance(data);
1100
- data = MiElHVAC.SetFanSpeed[preset.fanSpeed];
1101
- await this.axiosInstance(data);
1102
- data = MiElHVAC.SetSwingV[preset.swingV];
1103
- await this.axiosInstance(data);
1104
- data = MiElHVAC.SetSwingH[preset.swingH];
1105
- await this.axiosInstance(data);
1106
- break;
1107
- case false:
1108
- break;
1003
+ if (state) {
1004
+ // Power on if needed
1005
+ if (!this.mielHvac.power) {
1006
+ await this.axiosInstance(MiElHVAC.PowerOn);
1007
+ }
1008
+
1009
+ // Apply preset commands in sequence
1010
+ const commands = [
1011
+ MiElHVAC.SetMode[mode],
1012
+ `${MiElHVAC.SetTemp}${setTemp}`,
1013
+ MiElHVAC.SetFanSpeed[fanSpeed],
1014
+ MiElHVAC.SetSwingV[swingV],
1015
+ MiElHVAC.SetSwingH[swingH]
1016
+ ];
1017
+
1018
+ for (const cmd of commands) {
1019
+ await this.axiosInstance(cmd);
1020
+ }
1021
+
1022
+ if (!this.disableLogInfo) {
1023
+ this.emit('info', `Set: ${presetName}`);
1024
+ }
1025
+
1026
+ await new Promise(resolve => setTimeout(resolve, 250));
1109
1027
  }
1110
-
1111
- const info = this.disableLogInfo || !state ? false : this.emit('info', `Set: ${presetName}`);
1112
- await new Promise(resolve => setTimeout(resolve, 250));
1113
1028
  } catch (error) {
1114
1029
  this.emit('warn', `Set preset error: ${error}`);
1115
1030
  }
1116
1031
  });
1032
+
1117
1033
  this.presetsServices.push(presetService);
1118
1034
  accessory.addService(presetService);
1119
1035
  });
1120
1036
  }
1121
1037
 
1122
- //buttons services
1038
+
1123
1039
  if (this.buttonsConfiguredCount > 0) {
1124
- const debug = this.enableDebugMode ? this.emit('debug', `Prepare buttons services`) : false;
1040
+ if (this.enableDebugMode) this.emit('debug', 'Prepare buttons services');
1125
1041
  this.buttonsServices = [];
1126
1042
 
1127
1043
  this.buttonsConfigured.forEach((button, index) => {
1128
- //get button mode
1129
- const mode = button.mode;
1130
-
1131
- //get button name
1132
- const buttonName = button.name;
1133
-
1134
- //get button name prefix
1135
- const buttonNamePrefix = button.namePrefix;
1044
+ const { mode, name: buttonName, namePrefix, serviceType, characteristicType } = button;
1045
+ const serviceName = namePrefix ? `${accessoryName} ${buttonName}` : buttonName;
1136
1046
 
1137
- const serviceName = buttonNamePrefix ? `${accessoryName} ${buttonName}` : buttonName;
1138
- const serviceType = button.serviceType;
1139
- const characteristicType = button.characteristicType;
1140
1047
  const buttonService = new serviceType(serviceName, `Button ${index}`);
1141
1048
  buttonService.addOptionalCharacteristic(Characteristic.ConfiguredName);
1142
1049
  buttonService.setCharacteristic(Characteristic.ConfiguredName, serviceName);
1050
+
1143
1051
  buttonService.getCharacteristic(characteristicType)
1144
- .onGet(async () => {
1145
- const state = button.state;
1146
- return state;
1147
- })
1052
+ .onGet(async () => button.state)
1148
1053
  .onSet(async (state) => {
1149
1054
  try {
1150
- let data = '';
1151
- switch (mode) {
1152
- case 0: //POWER ON,OFF
1153
- data = state ? MiElHVAC.PowerOn : MiElHVAC.PowerOff;
1154
- break;
1155
- case 1: //OPERATING MODE HEAT
1156
- button.previousValue = state ? MiElHVAC.SetMode[this.mielHvac.operationMode] : button.previousValue;
1157
- data = state ? MiElHVAC.SetMode.heat : button.previousValue;
1158
- break;
1159
- case 2: //OPERATING MODE DRY
1160
- button.previousValue = state ? MiElHVAC.SetMode[this.mielHvac.operationMode] : button.previousValue;
1161
- data = state ? MiElHVAC.SetMode.dry : button.previousValue;
1162
- break
1163
- case 3: //OPERATING MODE COOL
1164
- button.previousValue = state ? MiElHVAC.SetMode[this.mielHvac.operationMode] : button.previousValue;
1165
- data = state ? MiElHVAC.SetMode.cool : button.previousValue;
1166
- break;
1167
- case 4: //OPERATING MODE FAN
1168
- button.previousValue = state ? MiElHVAC.SetMode[this.mielHvac.operationMode] : button.previousValue;
1169
- data = state ? MiElHVAC.SetMode.fan : button.previousValue;
1170
- break;
1171
- case 5: //OPERATING MODE AUTO
1172
- button.previousValue = state ? MiElHVAC.SetMode[this.mielHvac.operationMode] : button.previousValue;
1173
- data = state ? MiElHVAC.SetMode.auto : button.previousValue;
1174
- break;
1175
- case 6: //OPERATING MODE PURIFY
1176
- button.previousValue = state ? MiElHVAC.SetMode[this.mielHvac.operationMode] : button.previousValue;
1177
- data = state ? MiElHVAC.SetMode.purify : button.previousValue;
1178
- break;
1179
- case 11: //VANE H LEFT
1180
- button.previousValue = state ? MiElHVAC.SetSwingH[this.mielHvac.vaneHorizontalDirection] : button.previousValue;
1181
- data = state ? MiElHVAC.SetSwingH.left : button.previousValue;
1182
- break;
1183
- case 12: //VANE H LEFT MIDDLE
1184
- button.previousValue = state ? MiElHVAC.SetSwingH[this.mielHvac.vaneHorizontalDirection] : button.previousValue;
1185
- data = state ? MiElHVAC.SetSwingH.left_middle : button.previousValue;
1186
- break;
1187
- case 13: //VANE H CENTER
1188
- button.previousValue = state ? MiElHVAC.SetSwingH[this.mielHvac.vaneHorizontalDirection] : button.previousValue;
1189
- data = state ? MiElHVAC.SetSwingH.center : button.previousValue;
1190
- break;
1191
- case 14: //VANE H RIGHT MIDDLE
1192
- button.previousValue = state ? MiElHVAC.SetSwingH[this.mielHvac.vaneHorizontalDirection] : button.previousValue;
1193
- data = state ? MiElHVAC.SetSwingH.right_middle : button.previousValue;
1194
- break;
1195
- case 15: //VANE H RIGHT
1196
- button.previousValue = state ? MiElHVAC.SetSwingH[this.mielHvac.vaneHorizontalDirection] : button.previousValue;
1197
- data = state ? MiElHVAC.SetSwingH.right : button.previousValue;
1198
- break;
1199
- case 16: //VANE H SPLIT
1200
- button.previousValue = state ? MiElHVAC.SetSwingH[this.mielHvac.vaneHorizontalDirection] : button.previousValue;
1201
- data = state ? MiElHVAC.SetSwingH.split : button.previousValue;
1202
- break;
1203
- case 17: //VANE H SWING
1204
- button.previousValue = state ? MiElHVAC.SetSwingH[this.mielHvac.vaneHorizontalDirection] : button.previousValue;
1205
- data = state ? MiElHVAC.SetSwingH.swing : button.previousValue;
1206
- break;
1207
- case 20: //VANE V AUTO
1208
- button.previousValue = state ? MiElHVAC.SetSwingV[this.mielHvac.vaneVerticalDirection] : button.previousValue;
1209
- data = state ? MiElHVAC.SetSwingV.auto : button.previousValue;
1210
- break;
1211
- case 21: //VANE V UP
1212
- button.previousValue = state ? MiElHVAC.SetSwingV[this.mielHvac.vaneVerticalDirection] : button.previousValue;
1213
- data = state ? MiElHVAC.SetSwingV.up : button.previousValue;
1214
- break;
1215
- case 22: //VANE V UP MIDDLE
1216
- button.previousValue = state ? MiElHVAC.SetSwingV[this.mielHvac.vaneVerticalDirection] : button.previousValue;
1217
- data = state ? MiElHVAC.SetSwingV.up_middle : button.previousValue;
1218
- break;
1219
- case 23: //VANE V CENTER
1220
- button.previousValue = state ? MiElHVAC.SetSwingV[this.mielHvac.vaneVerticalDirection] : button.previousValue;
1221
- data = state ? MiElHVAC.SetSwingV.center : button.previousValue;
1222
- break;
1223
- case 24: //VANE V DOWN MIDDLE
1224
- button.previousValue = state ? MiElHVAC.SetSwingV[this.mielHvac.vaneVerticalDirection] : button.previousValue;
1225
- data = state ? MiElHVAC.SetSwingV.down_middle : button.previousValue;
1226
- break;
1227
- case 25: //VANE V DOWN
1228
- button.previousValue = state ? MiElHVAC.SetSwingV[this.mielHvac.vaneVerticalDirection] : button.previousValue;
1229
- data = state ? MiElHVAC.SetSwingV.down : button.previousValue;
1230
- break;
1231
- case 26: //VANE V SWING
1232
- button.previousValue = state ? MiElHVAC.SetSwingV[this.mielHvac.vaneVerticalDirection] : button.previousValue;
1233
- data = state ? MiElHVAC.SetSwingV.swing : button.previousValue;
1234
- break;
1235
- case 30: //FAN SPEED AUTO
1236
- button.previousValue = state ? MiElHVAC.SetFanSpeed[this.mielHvac.fanSpeed] : button.previousValue;
1237
- data = state ? MiElHVAC.SetFanSpeed.auto : button.previousValue;
1238
- break;
1239
- case 31: //FAN SPEED QUIET
1240
- button.previousValue = state ? MiElHVAC.SetFanSpeed[this.mielHvac.fanSpeed] : button.previousValue;
1241
- data = state ? MiElHVAC.SetFanSpeed.quiet : button.previousValue;
1242
- break;
1243
- case 32: //FAN SPEED 1
1244
- button.previousValue = state ? MiElHVAC.SetFanSpeed[this.mielHvac.fanSpeed] : button.previousValue;
1245
- data = state ? MiElHVAC.SetFanSpeed['1'] : button.previousValue;
1246
- break;
1247
- case 33: //FAN SPEED 2
1248
- button.previousValue = state ? MiElHVAC.SetFanSpeed[this.mielHvac.fanSpeed] : button.previousValue;
1249
- data = state ? MiElHVAC.SetFanSpeed['2'] : button.previousValue;
1250
- break;
1251
- case 34: //FAN 3
1252
- button.previousValue = state ? MiElHVAC.SetFanSpeed[this.mielHvac.fanSpeed] : button.previousValue;
1253
- data = state ? MiElHVAC.SetFanSpeed['3'] : button.previousValue;
1254
- break;
1255
- case 35: //FAN SPEED 4
1256
- button.previousValue = state ? MiElHVAC.SetFanSpeed[this.mielHvac.fanSpeed] : button.previousValue;
1257
- data = state ? MiElHVAC.SetFanSpeed['4'] : button.previousValue;
1258
- break;
1259
- case 40: //AIR DIRECTION EVEN
1260
- button.previousValue = state ? MiElHVAC.SetAirDirection[this.mielHvac.airDirection] : button.previousValue;
1261
- data = state ? MiElHVAC.SetAirDirection.even : button.previousValue;
1262
- break;
1263
- case 41: //AIR DIRECTION INDIRECT
1264
- button.previousValue = state ? MiElHVAC.SetAirDirection[this.mielHvac.airDirection] : button.previousValue;
1265
- data = state ? MiElHVAC.SetAirDirection.indirect : button.previousValue;
1266
- break;
1267
- case 42: //AIR DIRECTION DIRECT
1268
- button.previousValue = state ? MiElHVAC.SetAirDirection[this.mielHvac.airDirection] : button.previousValue;
1269
- data = state ? MiElHVAC.SetAirDirection.direct : button.previousValue;
1270
- break;
1271
- case 50: //PHYSICAL LOCK CONTROLS
1272
- button.previousValue = state ? MiElHVAC.SetProhibit[this.mielHvac.prohibit] : button.previousValue;
1273
- data = state ? MiElHVAC.SetProhibit.all : button.previousValue;
1274
- break;
1275
- case 51: //PHYSICAL LOCK CONTROLS POWER
1276
- button.previousValue = state ? MiElHVAC.SetProhibit[this.mielHvac.prohibit] : button.previousValue;
1277
- data = state ? MiElHVAC.SetProhibit.power : button.previousValue;
1278
- break;
1279
- case 52: //PHYSICAL LOCK CONTROLS MODE
1280
- button.previousValue = state ? MiElHVAC.SetProhibit[this.mielHvac.prohibit] : button.previousValue;
1281
- data = state ? MiElHVAC.SetProhibit.mode : button.previousValue;
1282
- break;
1283
- case 53: //PHYSICAL LOCK CONTROLS TEMP
1284
- button.previousValue = state ? MiElHVAC.SetProhibit[this.mielHvac.prohibit] : button.previousValue;
1285
- data = state ? MiElHVAC.SetProhibit.temp : button.previousValue;
1286
- break;
1287
- default:
1288
- this.emit('warn', `Unknown button mode: ${mode}`);
1289
- return;
1055
+ let data;
1056
+ const mappings = {
1057
+ 0: () => state ? MiElHVAC.PowerOn : MiElHVAC.PowerOff,
1058
+
1059
+ // Modes
1060
+ 1: () => getModeCommand('heat'),
1061
+ 2: () => getModeCommand('dry'),
1062
+ 3: () => getModeCommand('cool'),
1063
+ 4: () => getModeCommand('fan'),
1064
+ 5: () => getModeCommand('auto'),
1065
+ 6: () => getModeCommand('purify'),
1066
+
1067
+ // Horizontal Swing
1068
+ 11: () => getSwingCommand('SetSwingH', 'left'),
1069
+ 12: () => getSwingCommand('SetSwingH', 'left_middle'),
1070
+ 13: () => getSwingCommand('SetSwingH', 'center'),
1071
+ 14: () => getSwingCommand('SetSwingH', 'right_middle'),
1072
+ 15: () => getSwingCommand('SetSwingH', 'right'),
1073
+ 16: () => getSwingCommand('SetSwingH', 'split'),
1074
+ 17: () => getSwingCommand('SetSwingH', 'swing'),
1075
+
1076
+ // Vertical Swing
1077
+ 20: () => getSwingCommand('SetSwingV', 'auto'),
1078
+ 21: () => getSwingCommand('SetSwingV', 'up'),
1079
+ 22: () => getSwingCommand('SetSwingV', 'up_middle'),
1080
+ 23: () => getSwingCommand('SetSwingV', 'center'),
1081
+ 24: () => getSwingCommand('SetSwingV', 'down_middle'),
1082
+ 25: () => getSwingCommand('SetSwingV', 'down'),
1083
+ 26: () => getSwingCommand('SetSwingV', 'swing'),
1084
+
1085
+ // Fan Speeds
1086
+ 30: () => getSwingCommand('SetFanSpeed', 'auto'),
1087
+ 31: () => getSwingCommand('SetFanSpeed', 'quiet'),
1088
+ 32: () => getSwingCommand('SetFanSpeed', '1'),
1089
+ 33: () => getSwingCommand('SetFanSpeed', '2'),
1090
+ 34: () => getSwingCommand('SetFanSpeed', '3'),
1091
+ 35: () => getSwingCommand('SetFanSpeed', '4'),
1092
+
1093
+ // Air Direction
1094
+ 40: () => getSwingCommand('SetAirDirection', 'indirect'),
1095
+ 41: () => getSwingCommand('SetAirDirection', 'direct'),
1096
+ 42: () => getSwingCommand('SetAirDirection', 'even'),
1097
+ 43: () => getSwingCommand('SetAirDirection', 'off'),
1098
+
1099
+ // Prohibit
1100
+ 50: () => getSwingCommand('SetProhibit', 'all'),
1101
+ 51: () => getSwingCommand('SetProhibit', 'power'),
1102
+ 52: () => getSwingCommand('SetProhibit', 'mode'),
1103
+ 53: () => getSwingCommand('SetProhibit', 'temp')
1104
+ };
1105
+
1106
+ const getModeCommand = (target) => {
1107
+ button.previousValue = state ? MiElHVAC.SetMode[this.mielHvac.operationMode] : button.previousValue;
1108
+ return state ? MiElHVAC.SetMode[target] : button.previousValue;
1109
+ };
1110
+
1111
+ const getSwingCommand = (type, target) => {
1112
+ const current = this.mielHvac[getCurrentKey(type)];
1113
+ button.previousValue = state ? MiElHVAC[type][current] : button.previousValue;
1114
+ return state ? MiElHVAC[type][target] : button.previousValue;
1115
+ };
1116
+
1117
+ const getCurrentKey = (type) => {
1118
+ switch (type) {
1119
+ case 'SetSwingH': return 'vaneHorizontalDirection';
1120
+ case 'SetSwingV': return 'vaneVerticalDirection';
1121
+ case 'SetFanSpeed': return 'fanSpeed';
1122
+ case 'SetAirDirection': return 'airDirection';
1123
+ case 'SetProhibit': return 'prohibit';
1124
+ default: return '';
1125
+ }
1126
+ };
1127
+
1128
+ if (!mappings.hasOwnProperty(mode)) {
1129
+ this.emit('warn', `Unknown button mode: ${mode}`);
1130
+ return;
1131
+ }
1132
+
1133
+ data = mappings[mode]();
1134
+ if (!this.mielHvac.power && state && mode > 0 && mode < 50) {
1135
+ await this.axiosInstance(MiElHVAC.PowerOn);
1290
1136
  }
1291
1137
 
1292
- const setPower = !this.mielHvac.power && state && (mode > 0 && mode < 50) ? await this.axiosInstance(MiElHVAC.PowerOn) : false;
1293
1138
  await this.axiosInstance(data);
1294
- const info = this.disableLogInfo ? false : mode > 0 ? this.emit('info', `${state ? `Set: ${buttonName}` : `Unset: ${buttonName}, Set: ${button.previousValue}`}`) : `Set: ${buttonName}`;
1139
+
1140
+ if (!this.disableLogInfo) {
1141
+ const action = state ? `Set: ${buttonName}` : `Unset: ${buttonName}, Set: ${button.previousValue}`;
1142
+ if (mode > 0) this.emit('info', action);
1143
+ }
1144
+
1295
1145
  await new Promise(resolve => setTimeout(resolve, 250));
1296
1146
  } catch (error) {
1297
1147
  this.emit('warn', `Set button error: ${error}`);
1298
1148
  }
1299
1149
  });
1150
+
1300
1151
  this.buttonsServices.push(buttonService);
1301
1152
  accessory.addService(buttonService);
1302
1153
  });
1303
1154
  }
1304
1155
 
1156
+
1305
1157
  //sensors services
1306
1158
  if (this.sensorsConfiguredCount > 0) {
1307
1159
  const debug = this.enableDebugMode ? this.emit('debug', `Prepare sensors services`) : false;