@switchbot/homebridge-switchbot 3.5.0-beta.28 → 3.5.0-beta.29

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.
Files changed (132) hide show
  1. package/CHANGELOG.md +1 -0
  2. package/config.schema.json +67 -1
  3. package/dist/device/blindtilt.d.ts.map +1 -1
  4. package/dist/device/blindtilt.js +8 -3
  5. package/dist/device/blindtilt.js.map +1 -1
  6. package/dist/device/bot.d.ts.map +1 -1
  7. package/dist/device/bot.js +8 -3
  8. package/dist/device/bot.js.map +1 -1
  9. package/dist/device/ceilinglight.d.ts.map +1 -1
  10. package/dist/device/ceilinglight.js +31 -5
  11. package/dist/device/ceilinglight.js.map +1 -1
  12. package/dist/device/colorbulb.d.ts.map +1 -1
  13. package/dist/device/colorbulb.js +23 -4
  14. package/dist/device/colorbulb.js.map +1 -1
  15. package/dist/device/contact.d.ts.map +1 -1
  16. package/dist/device/contact.js +7 -2
  17. package/dist/device/contact.js.map +1 -1
  18. package/dist/device/curtain.d.ts.map +1 -1
  19. package/dist/device/curtain.js +7 -2
  20. package/dist/device/curtain.js.map +1 -1
  21. package/dist/device/device.d.ts.map +1 -1
  22. package/dist/device/device.js +13 -3
  23. package/dist/device/device.js.map +1 -1
  24. package/dist/device/fan.d.ts +51 -0
  25. package/dist/device/fan.d.ts.map +1 -0
  26. package/dist/device/fan.js +499 -0
  27. package/dist/device/fan.js.map +1 -0
  28. package/dist/device/hub.d.ts.map +1 -1
  29. package/dist/device/hub.js +32 -24
  30. package/dist/device/hub.js.map +1 -1
  31. package/dist/device/humidifier.d.ts.map +1 -1
  32. package/dist/device/humidifier.js +7 -2
  33. package/dist/device/humidifier.js.map +1 -1
  34. package/dist/device/iosensor.d.ts.map +1 -1
  35. package/dist/device/iosensor.js +25 -17
  36. package/dist/device/iosensor.js.map +1 -1
  37. package/dist/device/lightstrip.d.ts.map +1 -1
  38. package/dist/device/lightstrip.js +41 -4
  39. package/dist/device/lightstrip.js.map +1 -1
  40. package/dist/device/lock.d.ts.map +1 -1
  41. package/dist/device/lock.js +7 -2
  42. package/dist/device/lock.js.map +1 -1
  43. package/dist/device/meter.d.ts.map +1 -1
  44. package/dist/device/meter.js +25 -17
  45. package/dist/device/meter.js.map +1 -1
  46. package/dist/device/meterplus.d.ts.map +1 -1
  47. package/dist/device/meterplus.js +7 -2
  48. package/dist/device/meterplus.js.map +1 -1
  49. package/dist/device/motion.d.ts.map +1 -1
  50. package/dist/device/motion.js +7 -2
  51. package/dist/device/motion.js.map +1 -1
  52. package/dist/device/plug.d.ts.map +1 -1
  53. package/dist/device/plug.js +7 -2
  54. package/dist/device/plug.js.map +1 -1
  55. package/dist/device/robotvacuumcleaner.d.ts.map +1 -1
  56. package/dist/device/robotvacuumcleaner.js +8 -3
  57. package/dist/device/robotvacuumcleaner.js.map +1 -1
  58. package/dist/device/waterdetector.d.ts.map +1 -1
  59. package/dist/device/waterdetector.js +14 -7
  60. package/dist/device/waterdetector.js.map +1 -1
  61. package/dist/irdevice/airconditioner.d.ts.map +1 -1
  62. package/dist/irdevice/airconditioner.js +2 -1
  63. package/dist/irdevice/airconditioner.js.map +1 -1
  64. package/dist/irdevice/airpurifier.d.ts.map +1 -1
  65. package/dist/irdevice/airpurifier.js +2 -1
  66. package/dist/irdevice/airpurifier.js.map +1 -1
  67. package/dist/irdevice/camera.d.ts.map +1 -1
  68. package/dist/irdevice/camera.js +2 -1
  69. package/dist/irdevice/camera.js.map +1 -1
  70. package/dist/irdevice/fan.d.ts +1 -1
  71. package/dist/irdevice/fan.d.ts.map +1 -1
  72. package/dist/irdevice/fan.js +3 -2
  73. package/dist/irdevice/fan.js.map +1 -1
  74. package/dist/irdevice/irdevice.js.map +1 -1
  75. package/dist/irdevice/light.d.ts.map +1 -1
  76. package/dist/irdevice/light.js +2 -1
  77. package/dist/irdevice/light.js.map +1 -1
  78. package/dist/irdevice/other.d.ts.map +1 -1
  79. package/dist/irdevice/other.js +2 -1
  80. package/dist/irdevice/other.js.map +1 -1
  81. package/dist/irdevice/tv.d.ts.map +1 -1
  82. package/dist/irdevice/tv.js +2 -1
  83. package/dist/irdevice/tv.js.map +1 -1
  84. package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
  85. package/dist/irdevice/vacuumcleaner.js +2 -1
  86. package/dist/irdevice/vacuumcleaner.js.map +1 -1
  87. package/dist/irdevice/waterheater.d.ts.map +1 -1
  88. package/dist/irdevice/waterheater.js +2 -1
  89. package/dist/irdevice/waterheater.js.map +1 -1
  90. package/dist/platform.d.ts +2 -1
  91. package/dist/platform.d.ts.map +1 -1
  92. package/dist/platform.js +68 -5
  93. package/dist/platform.js.map +1 -1
  94. package/dist/settings.d.ts +22 -4
  95. package/dist/settings.d.ts.map +1 -1
  96. package/dist/utils.d.ts +10 -5
  97. package/dist/utils.d.ts.map +1 -1
  98. package/dist/utils.js +23 -9
  99. package/dist/utils.js.map +1 -1
  100. package/package.json +3 -3
  101. package/src/device/blindtilt.ts +8 -3
  102. package/src/device/bot.ts +8 -3
  103. package/src/device/ceilinglight.ts +31 -5
  104. package/src/device/colorbulb.ts +25 -6
  105. package/src/device/contact.ts +9 -4
  106. package/src/device/curtain.ts +21 -16
  107. package/src/device/device.ts +13 -3
  108. package/src/device/fan.ts +548 -0
  109. package/src/device/hub.ts +30 -22
  110. package/src/device/humidifier.ts +8 -3
  111. package/src/device/iosensor.ts +27 -19
  112. package/src/device/lightstrip.ts +40 -6
  113. package/src/device/lock.ts +12 -7
  114. package/src/device/meter.ts +29 -21
  115. package/src/device/meterplus.ts +11 -6
  116. package/src/device/motion.ts +8 -3
  117. package/src/device/plug.ts +8 -3
  118. package/src/device/robotvacuumcleaner.ts +13 -8
  119. package/src/device/waterdetector.ts +14 -7
  120. package/src/irdevice/airconditioner.ts +4 -3
  121. package/src/irdevice/airpurifier.ts +4 -3
  122. package/src/irdevice/camera.ts +3 -2
  123. package/src/irdevice/fan.ts +3 -2
  124. package/src/irdevice/irdevice.ts +1 -1
  125. package/src/irdevice/light.ts +2 -1
  126. package/src/irdevice/other.ts +46 -45
  127. package/src/irdevice/tv.ts +2 -1
  128. package/src/irdevice/vacuumcleaner.ts +2 -1
  129. package/src/irdevice/waterheater.ts +2 -1
  130. package/src/platform.ts +71 -5
  131. package/src/settings.ts +34 -9
  132. package/src/utils.ts +24 -9
@@ -13,7 +13,7 @@ import { CharacteristicValue, PlatformAccessory, Service } from 'homebridge';
13
13
  * An instance of this class is created for each accessory your platform registers
14
14
  * Each accessory may expose multiple services of different service types.
15
15
  */
16
- export class Fan extends irdeviceBase {
16
+ export class IRFan extends irdeviceBase {
17
17
  // Services
18
18
  private Fan: {
19
19
  Service: Service;
@@ -233,7 +233,8 @@ export class Fan extends irdeviceBase {
233
233
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
234
234
  this.debugSuccessLog(`${this.device.remoteType}: ${this.accessory.displayName} `
235
235
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
236
- this.successLog(`${this.device.remoteType}: ${this.accessory.displayName} request to SwitchBot API, body: ${bodyChange} sent successfully`);
236
+ this.successLog(`${this.device.remoteType}: ${this.accessory.displayName}`
237
+ + ` request to SwitchBot API, body: ${JSON.stringify(bodyChange)} sent successfully`);
237
238
  this.updateHomeKitCharacteristics();
238
239
  } else {
239
240
  this.statusCode(statusCode);
@@ -455,7 +455,7 @@ export abstract class irdeviceBase {
455
455
  break;
456
456
  default:
457
457
  this.infoLog(`${this.device.remoteType}: ${this.accessory.displayName} Unknown statusCode: `
458
- + `${statusCode}, Submit Bugs Here: ' + 'https://tinyurl.com/SwitchBotBug`);
458
+ + `${statusCode}, Submit Bugs Here: ' + 'https://tinyurl.com/SwitchBotBug`);
459
459
  }
460
460
  }
461
461
 
@@ -225,7 +225,8 @@ export class Light extends irdeviceBase {
225
225
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
226
226
  this.debugSuccessLog(`${this.device.remoteType}: ${this.accessory.displayName} `
227
227
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
228
- this.successLog(`${this.device.remoteType}: ${this.accessory.displayName} request to SwitchBot API, body: ${bodyChange} sent successfully`);
228
+ this.successLog(`${this.device.remoteType}: ${this.accessory.displayName}`
229
+ + ` request to SwitchBot API, body: ${JSON.stringify(bodyChange)} sent successfully`);
229
230
  this.accessory.context.On = this.On;
230
231
  this.updateHomeKitCharacteristics();
231
232
  } else {
@@ -440,7 +440,7 @@ export class Others extends irdeviceBase {
440
440
  */
441
441
  async pushOnChanges(On: boolean): Promise<void> {
442
442
  this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} pushOnChanges On: ${On},`
443
- +` disablePushOn: ${this.disablePushOn}, customize: ${this.device.customize}, customOn: ${this.device.customOn}`);
443
+ + ` disablePushOn: ${this.disablePushOn}, customize: ${this.device.customize}, customOn: ${this.device.customOn}`);
444
444
  if (this.device.customize) {
445
445
  if (On === true && !this.disablePushOn) {
446
446
  const commandType: string = await this.commandType();
@@ -493,7 +493,8 @@ export class Others extends irdeviceBase {
493
493
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
494
494
  this.debugSuccessLog(`${this.device.remoteType}: ${this.accessory.displayName} `
495
495
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
496
- this.successLog(`${this.device.remoteType}: ${this.accessory.displayName} request to SwitchBot API, body: ${bodyChange} sent successfully`);
496
+ this.successLog(`${this.device.remoteType}: ${this.accessory.displayName}`
497
+ + ` request to SwitchBot API, body: ${JSON.stringify(bodyChange)} sent successfully`);
497
498
  this.updateHomeKitCharacteristics();
498
499
  } else {
499
500
  this.statusCode(statusCode);
@@ -502,11 +503,11 @@ export class Others extends irdeviceBase {
502
503
  } catch (e: any) {
503
504
  this.apiError(e);
504
505
  this.errorLog(`${this.device.remoteType}: ${this.accessory.displayName} failed pushChanges with ${this.device.connectionType}`
505
- + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
506
+ + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
506
507
  }
507
508
  } else {
508
509
  this.warnLog(`${this.device.remoteType}: ${this.accessory.displayName}`
509
- + ` Connection Type: ${this.device.connectionType}, commands will not be sent to OpenAPI`);
510
+ + ` Connection Type: ${this.device.connectionType}, commands will not be sent to OpenAPI`);
510
511
  }
511
512
  }
512
513
 
@@ -519,12 +520,12 @@ export class Others extends irdeviceBase {
519
520
  this.GarageDoor!.Service.updateCharacteristic(this.hap.Characteristic.TargetDoorState, this.hap.Characteristic.TargetDoorState.OPEN);
520
521
  this.GarageDoor!.Service.updateCharacteristic(this.hap.Characteristic.CurrentDoorState, this.hap.Characteristic.CurrentDoorState.OPEN);
521
522
  this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} updateCharacteristic`
522
- + ` TargetDoorState: Open, CurrentDoorState: Open (${this.GarageDoor!.On})`);
523
+ + ` TargetDoorState: Open, CurrentDoorState: Open (${this.GarageDoor!.On})`);
523
524
  } else {
524
525
  this.GarageDoor!.Service.updateCharacteristic(this.hap.Characteristic.TargetDoorState, this.hap.Characteristic.TargetDoorState.CLOSED);
525
526
  this.GarageDoor!.Service.updateCharacteristic(this.hap.Characteristic.CurrentDoorState, this.hap.Characteristic.CurrentDoorState.CLOSED);
526
527
  this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} updateCharacteristic`
527
- + ` TargetDoorState: Closed, CurrentDoorState: Closed (${this.GarageDoor!.On})`);
528
+ + ` TargetDoorState: Closed, CurrentDoorState: Closed (${this.GarageDoor!.On})`);
528
529
  }
529
530
  }
530
531
  this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} Garage Door On: ${this.GarageDoor!.On}`);
@@ -537,13 +538,13 @@ export class Others extends irdeviceBase {
537
538
  this.Door!.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 100);
538
539
  this.Door!.Service.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
539
540
  this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} updateCharacteristic`
540
- + ` TargetPosition: 100, CurrentPosition: 100 (${this.Door!.On})`);
541
+ + ` TargetPosition: 100, CurrentPosition: 100 (${this.Door!.On})`);
541
542
  } else {
542
543
  this.Door!.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, 0);
543
544
  this.Door!.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 0);
544
545
  this.Door!.Service.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
545
546
  this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} updateCharacteristic`
546
- + ` TargetPosition: 0, CurrentPosition: 0 (${this.Door!.On})`);
547
+ + ` TargetPosition: 0, CurrentPosition: 0 (${this.Door!.On})`);
547
548
  }
548
549
  }
549
550
  this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} Door On: ${this.Door!.On}`);
@@ -556,13 +557,13 @@ export class Others extends irdeviceBase {
556
557
  this.Window!.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 100);
557
558
  this.Window!.Service.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
558
559
  this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} updateCharacteristic`
559
- + ` TargetPosition: 100, CurrentPosition: 100 (${this.Window!.On})`);
560
+ + ` TargetPosition: 100, CurrentPosition: 100 (${this.Window!.On})`);
560
561
  } else {
561
562
  this.Window!.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, 0);
562
563
  this.Window!.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 0);
563
564
  this.Window!.Service.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
564
565
  this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} updateCharacteristic`
565
- + ` TargetPosition: 0, CurrentPosition: 0 (${this.Window!.On})`);
566
+ + ` TargetPosition: 0, CurrentPosition: 0 (${this.Window!.On})`);
566
567
  }
567
568
  }
568
569
  this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} Window On: ${this.Window!.On}`);
@@ -575,13 +576,13 @@ export class Others extends irdeviceBase {
575
576
  this.WindowCovering!.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 100);
576
577
  this.WindowCovering!.Service.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
577
578
  this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} updateCharacteristic`
578
- + ` TargetPosition: 100, CurrentPosition: 100 (${this.WindowCovering!.On})`);
579
+ + ` TargetPosition: 100, CurrentPosition: 100 (${this.WindowCovering!.On})`);
579
580
  } else {
580
581
  this.WindowCovering!.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, 0);
581
582
  this.WindowCovering!.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 0);
582
583
  this.WindowCovering!.Service.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
583
584
  this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} updateCharacteristic`
584
- + ` TargetPosition: 0, CurrentPosition: 0 (${this.WindowCovering!.On})`);
585
+ + ` TargetPosition: 0, CurrentPosition: 0 (${this.WindowCovering!.On})`);
585
586
  }
586
587
  }
587
588
  this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} Window Covering On: ${this.WindowCovering!.On}`);
@@ -593,7 +594,7 @@ export class Others extends irdeviceBase {
593
594
  this.Lock!.Service.updateCharacteristic(this.hap.Characteristic.LockTargetState, this.hap.Characteristic.LockTargetState.UNSECURED);
594
595
  this.Lock!.Service.updateCharacteristic(this.hap.Characteristic.LockCurrentState, this.hap.Characteristic.LockCurrentState.UNSECURED);
595
596
  this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} updateCharacteristic`
596
- + ` LockTargetState: UNSECURED, LockCurrentState: UNSECURE (${this.Lock!.On})`);
597
+ + ` LockTargetState: UNSECURED, LockCurrentState: UNSECURE (${this.Lock!.On})`);
597
598
  } else {
598
599
  this.Lock!.Service.updateCharacteristic(this.hap.Characteristic.LockTargetState, this.hap.Characteristic.LockTargetState.SECURED);
599
600
  this.Lock!.Service.updateCharacteristic(this.hap.Characteristic.LockCurrentState, this.hap.Characteristic.LockCurrentState.SECURED);
@@ -637,13 +638,13 @@ export class Others extends irdeviceBase {
637
638
  this.hap.Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS);
638
639
  this.StatefulProgrammableSwitch!.Service.updateCharacteristic(this.hap.Characteristic.ProgrammableSwitchOutputState, 1);
639
640
  this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} updateCharacteristic`
640
- + ` ProgrammableSwitchEvent: SINGLE, ProgrammableSwitchOutputState: 1 (${this.StatefulProgrammableSwitch!.On})`);
641
+ + ` ProgrammableSwitchEvent: SINGLE, ProgrammableSwitchOutputState: 1 (${this.StatefulProgrammableSwitch!.On})`);
641
642
  } else {
642
643
  this.StatefulProgrammableSwitch!.Service.updateCharacteristic(this.hap.Characteristic.ProgrammableSwitchEvent,
643
644
  this.hap.Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS);
644
645
  this.StatefulProgrammableSwitch!.Service.updateCharacteristic(this.hap.Characteristic.ProgrammableSwitchOutputState, 0);
645
646
  this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} updateCharacteristic`
646
- + ` ProgrammableSwitchEvent: SINGLE, ProgrammableSwitchOutputState: 0 (${this.StatefulProgrammableSwitch!.On})`);
647
+ + ` ProgrammableSwitchEvent: SINGLE, ProgrammableSwitchOutputState: 0 (${this.StatefulProgrammableSwitch!.On})`);
647
648
  }
648
649
  }
649
650
  this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} StatefulProgrammableSwitch On: ${this.StatefulProgrammableSwitch!.On}`);
@@ -701,90 +702,90 @@ export class Others extends irdeviceBase {
701
702
  async removeOutletService(accessory: PlatformAccessory): Promise<void> {
702
703
  // If Outlet.Service still present, then remove first
703
704
  if (this.Outlet?.Service) {
704
- this.Outlet!.Service = this.accessory.getService(this.hap.Service.Outlet) as Service;
705
- this.warnLog(`${this.device.remoteType}: ${accessory.displayName} Removing Leftover Outlet Service`);
706
- accessory.removeService(this.Outlet!.Service);
705
+ this.Outlet!.Service = this.accessory.getService(this.hap.Service.Outlet) as Service;
706
+ this.warnLog(`${this.device.remoteType}: ${accessory.displayName} Removing Leftover Outlet Service`);
707
+ accessory.removeService(this.Outlet!.Service);
707
708
  }
708
709
  }
709
710
 
710
711
  async removeGarageDoorService(accessory: PlatformAccessory): Promise<void> {
711
712
  // If GarageDoor.Service still present, then remove first
712
713
  if (this.GarageDoor?.Service) {
713
- this.GarageDoor!.Service = this.accessory.getService(this.hap.Service.GarageDoorOpener) as Service;
714
- this.warnLog(`${this.device.remoteType}: ${accessory.displayName} Removing Leftover Garage Door Service`);
715
- accessory.removeService(this.GarageDoor!.Service);
714
+ this.GarageDoor!.Service = this.accessory.getService(this.hap.Service.GarageDoorOpener) as Service;
715
+ this.warnLog(`${this.device.remoteType}: ${accessory.displayName} Removing Leftover Garage Door Service`);
716
+ accessory.removeService(this.GarageDoor!.Service);
716
717
  }
717
718
  }
718
719
 
719
720
  async removeDoorService(accessory: PlatformAccessory): Promise<void> {
720
721
  // If Door.Service still present, then remove first
721
722
  if (this.Door?.Service) {
722
- this.Door!.Service = this.accessory.getService(this.hap.Service.Door) as Service;
723
- this.warnLog(`${this.device.remoteType}: ${accessory.displayName} Removing Leftover Door Service`);
724
- accessory.removeService(this.Door!.Service);
723
+ this.Door!.Service = this.accessory.getService(this.hap.Service.Door) as Service;
724
+ this.warnLog(`${this.device.remoteType}: ${accessory.displayName} Removing Leftover Door Service`);
725
+ accessory.removeService(this.Door!.Service);
725
726
  }
726
727
  }
727
728
 
728
729
  async removeLockService(accessory: PlatformAccessory): Promise<void> {
729
730
  // If Lock.Service still present, then remove first
730
731
  if (this.Lock?.Service) {
731
- this.Lock!.Service = this.accessory.getService(this.hap.Service.LockMechanism) as Service;
732
- this.warnLog(`${this.device.remoteType}: ${accessory.displayName} Removing Leftover Lock Service`);
733
- accessory.removeService(this.Lock!.Service);
732
+ this.Lock!.Service = this.accessory.getService(this.hap.Service.LockMechanism) as Service;
733
+ this.warnLog(`${this.device.remoteType}: ${accessory.displayName} Removing Leftover Lock Service`);
734
+ accessory.removeService(this.Lock!.Service);
734
735
  }
735
736
  }
736
737
 
737
738
  async removeFaucetService(accessory: PlatformAccessory): Promise<void> {
738
739
  // If Faucet.Service still present, then remove first
739
740
  if (this.Faucet?.Service) {
740
- this.Faucet!.Service = this.accessory.getService(this.hap.Service.Faucet) as Service;
741
- this.warnLog(`${this.device.remoteType}: ${accessory.displayName} Removing Leftover Faucet Service`);
742
- accessory.removeService(this.Faucet!.Service);
741
+ this.Faucet!.Service = this.accessory.getService(this.hap.Service.Faucet) as Service;
742
+ this.warnLog(`${this.device.remoteType}: ${accessory.displayName} Removing Leftover Faucet Service`);
743
+ accessory.removeService(this.Faucet!.Service);
743
744
  }
744
745
  }
745
746
 
746
747
  async removeFanService(accessory: PlatformAccessory): Promise<void> {
747
748
  // If Fan Service still present, then remove first
748
749
  if (this.Fan?.Service) {
749
- this.Fan!.Service = this.accessory.getService(this.hap.Service.Fan) as Service;
750
- this.warnLog(`${this.device.remoteType}: ${accessory.displayName} Removing Leftover Fan Service`);
751
- accessory.removeService(this.Fan!.Service);
750
+ this.Fan!.Service = this.accessory.getService(this.hap.Service.Fan) as Service;
751
+ this.warnLog(`${this.device.remoteType}: ${accessory.displayName} Removing Leftover Fan Service`);
752
+ accessory.removeService(this.Fan!.Service);
752
753
  }
753
754
  }
754
755
 
755
756
  async removeWindowService(accessory: PlatformAccessory): Promise<void> {
756
757
  // If Window.Service still present, then remove first
757
758
  if (this.Window?.Service) {
758
- this.Window!.Service = this.accessory.getService(this.hap.Service.Window) as Service;
759
- this.warnLog(`${this.device.remoteType}: ${accessory.displayName} Removing Leftover Window Service`);
760
- accessory.removeService(this.Window!.Service);
759
+ this.Window!.Service = this.accessory.getService(this.hap.Service.Window) as Service;
760
+ this.warnLog(`${this.device.remoteType}: ${accessory.displayName} Removing Leftover Window Service`);
761
+ accessory.removeService(this.Window!.Service);
761
762
  }
762
763
  }
763
764
 
764
765
  async removeWindowCoveringService(accessory: PlatformAccessory): Promise<void> {
765
766
  // If WindowCovering.Service still present, then remove first
766
767
  if (this.WindowCovering?.Service) {
767
- this.WindowCovering!.Service = this.accessory.getService(this.hap.Service.WindowCovering) as Service;
768
- this.warnLog(`${this.device.remoteType}: ${accessory.displayName} Removing Leftover Window Covering Service`);
769
- accessory.removeService(this.WindowCovering!.Service);
768
+ this.WindowCovering!.Service = this.accessory.getService(this.hap.Service.WindowCovering) as Service;
769
+ this.warnLog(`${this.device.remoteType}: ${accessory.displayName} Removing Leftover Window Covering Service`);
770
+ accessory.removeService(this.WindowCovering!.Service);
770
771
  }
771
772
  }
772
773
 
773
774
  async removeStatefulProgrammableSwitchService(accessory: PlatformAccessory): Promise<void> {
774
775
  // If StatefulProgrammableSwitch.Service still present, then remove first
775
776
  if (this.StatefulProgrammableSwitch?.Service) {
776
- this.StatefulProgrammableSwitch!.Service = this.accessory.getService(this.hap.Service.StatefulProgrammableSwitch) as Service;
777
- this.warnLog(`${this.device.remoteType}: ${accessory.displayName} Removing Leftover Stateful Programmable Switch Service`);
778
- accessory.removeService(this.StatefulProgrammableSwitch!.Service);
777
+ this.StatefulProgrammableSwitch!.Service = this.accessory.getService(this.hap.Service.StatefulProgrammableSwitch) as Service;
778
+ this.warnLog(`${this.device.remoteType}: ${accessory.displayName} Removing Leftover Stateful Programmable Switch Service`);
779
+ accessory.removeService(this.StatefulProgrammableSwitch!.Service);
779
780
  }
780
781
  }
781
782
 
782
783
  async removeSwitchService(accessory: PlatformAccessory): Promise<void> {
783
784
  // If Switch.Service still present, then remove first
784
785
  if (this.Switch?.Service) {
785
- this.Switch!.Service = this.accessory.getService(this.hap.Service.Switch) as Service;
786
- this.warnLog(`${this.device.remoteType}: ${accessory.displayName} Removing Leftover Switch Service`);
787
- accessory.removeService(this.Switch!.Service);
786
+ this.Switch!.Service = this.accessory.getService(this.hap.Service.Switch) as Service;
787
+ this.warnLog(`${this.device.remoteType}: ${accessory.displayName} Removing Leftover Switch Service`);
788
+ accessory.removeService(this.Switch!.Service);
788
789
  }
789
790
  }
790
791
 
@@ -390,7 +390,8 @@ export class TV extends irdeviceBase {
390
390
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
391
391
  this.debugSuccessLog(`${this.device.remoteType}: ${this.accessory.displayName} `
392
392
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
393
- this.successLog(`${this.device.remoteType}: ${this.accessory.displayName} request to SwitchBot API, body: ${bodyChange} sent successfully`);
393
+ this.successLog(`${this.device.remoteType}: ${this.accessory.displayName}`
394
+ + ` request to SwitchBot API, body: ${JSON.stringify(bodyChange)} sent successfully`);
394
395
  this.updateHomeKitCharacteristics();
395
396
  } else {
396
397
  this.statusCode(statusCode);
@@ -109,7 +109,8 @@ export class VacuumCleaner extends irdeviceBase {
109
109
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
110
110
  this.debugSuccessLog(`${this.device.remoteType}: ${this.accessory.displayName} `
111
111
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
112
- this.successLog(`${this.device.remoteType}: ${this.accessory.displayName} request to SwitchBot API, body: ${bodyChange} sent successfully`);
112
+ this.successLog(`${this.device.remoteType}: ${this.accessory.displayName}`
113
+ + ` request to SwitchBot API, body: ${JSON.stringify(bodyChange)} sent successfully`);
113
114
  this.updateHomeKitCharacteristics();
114
115
  } else {
115
116
  this.statusCode(statusCode);
@@ -114,7 +114,8 @@ export class WaterHeater extends irdeviceBase {
114
114
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
115
115
  this.debugSuccessLog(`${this.device.remoteType}: ${this.accessory.displayName} `
116
116
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
117
- this.successLog(`${this.device.remoteType}: ${this.accessory.displayName} request to SwitchBot API, body: ${bodyChange} sent successfully`);
117
+ this.successLog(`${this.device.remoteType}: ${this.accessory.displayName}`
118
+ + ` request to SwitchBot API, body: ${JSON.stringify(bodyChange)} sent successfully`);
118
119
  this.updateHomeKitCharacteristics();
119
120
  } else {
120
121
  this.statusCode(statusCode);
package/src/platform.ts CHANGED
@@ -20,8 +20,9 @@ import { CeilingLight } from './device/ceilinglight.js';
20
20
  import { StripLight } from './device/lightstrip.js';
21
21
  import { Humidifier } from './device/humidifier.js';
22
22
  import { RobotVacuumCleaner } from './device/robotvacuumcleaner.js';
23
+ import { Fan } from './device/fan.js';
23
24
  import { TV } from './irdevice/tv.js';
24
- import { Fan } from './irdevice/fan.js';
25
+ import { IRFan } from './irdevice/fan.js';
25
26
  import { Light } from './irdevice/light.js';
26
27
  import { Others } from './irdevice/other.js';
27
28
  import { Camera } from './irdevice/camera.js';
@@ -727,6 +728,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
727
728
  case 'WoSweeperMini':
728
729
  case 'Robot Vacuum Cleaner S1':
729
730
  case 'Robot Vacuum Cleaner S1 Plus':
731
+ case 'Robot Vacuum Cleaner S10':
730
732
  this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}`);
731
733
  this.createRobotVacuumCleaner(device);
732
734
  break;
@@ -747,6 +749,10 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
747
749
  case 'remote with screen+':
748
750
  this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId} is Not Supported.`);
749
751
  break;
752
+ case 'Battery Circulator Fan':
753
+ this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}`);
754
+ this.createFan(device);
755
+ break;
750
756
  default:
751
757
  this.warnLog(`Device: ${device.deviceName} with Device Type: ${device.deviceType}, is currently not supported.`);
752
758
  // eslint-disable-next-line max-len
@@ -782,7 +788,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
782
788
  case 'Fan':
783
789
  case 'DIY Fan':
784
790
  this.debugLog(`Discovered ${device.remoteType}: ${device.deviceId}`);
785
- this.createFan(device);
791
+ this.createIRFan(device);
786
792
  break;
787
793
  case 'Air Conditioner':
788
794
  case 'DIY Air Conditioner':
@@ -1814,6 +1820,66 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1814
1820
  }
1815
1821
  }
1816
1822
 
1823
+ private async createFan(device: device & devicesConfig) {
1824
+ const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
1825
+
1826
+ // see if an accessory with the same uuid has already been registered and restored from
1827
+ // the cached devices we stored in the `configureAccessory` method above
1828
+ const existingAccessory = this.accessories.find((accessory) => accessory.UUID === uuid);
1829
+
1830
+ if (existingAccessory) {
1831
+ // the accessory already exists
1832
+ if (await this.registerDevice(device)) {
1833
+ // if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
1834
+ existingAccessory.context.model = device.deviceType;
1835
+ existingAccessory.context.deviceID = device.deviceId;
1836
+ existingAccessory.displayName = device.configDeviceName || device.deviceName;
1837
+ if (device.firmware) {
1838
+ existingAccessory.context.FirmwareRevision = device.firmware;
1839
+ }
1840
+ existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1841
+ this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
1842
+ existingAccessory.context.connectionType = await this.connectionType(device);
1843
+ this.api.updatePlatformAccessories([existingAccessory]);
1844
+ // create the accessory handler for the restored accessory
1845
+ // this is imported from `platformAccessory.ts`
1846
+ new Fan(this, existingAccessory, device);
1847
+ this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${existingAccessory.UUID})`);
1848
+ } else {
1849
+ this.unregisterPlatformAccessories(existingAccessory);
1850
+ }
1851
+ } else if (await this.registerDevice(device)) {
1852
+ // the accessory does not yet exist, so we need to create it
1853
+ if (!device.external) {
1854
+ this.infoLog(`Adding new accessory: ${device.deviceName} ${device.deviceType} DeviceID: ${device.deviceId}`);
1855
+ }
1856
+
1857
+ // create a new accessory
1858
+ const accessory = new this.api.platformAccessory(device.deviceName, uuid);
1859
+
1860
+ // store a copy of the device object in the `accessory.context`
1861
+ // the `context` property can be used to store any data about the accessory you may need
1862
+ accessory.context.device = device;
1863
+ accessory.context.model = device.deviceType;
1864
+ accessory.context.deviceID = device.deviceId;
1865
+ if (device.firmware) {
1866
+ accessory.context.FirmwareRevision = device.firmware;
1867
+ }
1868
+ accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1869
+ accessory.context.connectionType = await this.connectionType(device);
1870
+ // create the accessory handler for the newly create accessory
1871
+ // this is imported from `platformAccessory.ts`
1872
+ new Fan(this, accessory, device);
1873
+ this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${accessory.UUID})`);
1874
+
1875
+ // publish device externally or link the accessory to your platform
1876
+ this.externalOrPlatform(device, accessory);
1877
+ this.accessories.push(accessory);
1878
+ } else {
1879
+ this.debugLog(`Device not registered: ${device.deviceName} ${device.deviceType} DeviceID: ${device.deviceId}`);
1880
+ }
1881
+ }
1882
+
1817
1883
  private async createRobotVacuumCleaner(device: device & devicesConfig) {
1818
1884
  const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
1819
1885
 
@@ -1926,7 +1992,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1926
1992
  }
1927
1993
  }
1928
1994
 
1929
- private async createFan(device: irdevice & devicesConfig) {
1995
+ private async createIRFan(device: irdevice & devicesConfig) {
1930
1996
  const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`);
1931
1997
 
1932
1998
  // see if an accessory with the same uuid has already been registered and restored from
@@ -1949,7 +2015,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1949
2015
  this.api.updatePlatformAccessories([existingAccessory]);
1950
2016
  // create the accessory handler for the restored accessory
1951
2017
  // this is imported from `platformAccessory.ts`
1952
- new Fan(this, existingAccessory, device);
2018
+ new IRFan(this, existingAccessory, device);
1953
2019
  this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${existingAccessory.UUID})`);
1954
2020
  } else {
1955
2021
  this.unregisterPlatformAccessories(existingAccessory);
@@ -1975,7 +2041,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1975
2041
  accessory.context.connectionType = device.connectionType;
1976
2042
  // create the accessory handler for the newly create accessory
1977
2043
  // this is imported from `platformAccessory.ts`
1978
- new Fan(this, accessory, device);
2044
+ new IRFan(this, accessory, device);
1979
2045
  this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`);
1980
2046
 
1981
2047
  // publish device externally or link the accessory to your platform
package/src/settings.ts CHANGED
@@ -48,6 +48,9 @@ export type options = {
48
48
  };
49
49
 
50
50
  export interface devicesConfig extends device {
51
+ bleMac?: string;
52
+ model?: string;
53
+ bleModel?: string;
51
54
  configDeviceType: string;
52
55
  configDeviceName?: string;
53
56
  deviceId: string;
@@ -89,11 +92,13 @@ export interface devicesConfig extends device {
89
92
 
90
93
  export type meter = {
91
94
  hide_temperature?: boolean;
95
+ convertUnitTo?: string;
92
96
  hide_humidity?: boolean;
93
97
  };
94
98
 
95
99
  export type iosensor = {
96
100
  hide_temperature?: boolean;
101
+ convertUnitTo?: string;
97
102
  hide_humidity?: boolean;
98
103
  };
99
104
 
@@ -174,6 +179,7 @@ export type lock = {
174
179
 
175
180
  export type hub = {
176
181
  hide_temperature?: boolean;
182
+ convertUnitTo?: string;
177
183
  hide_humidity?: boolean;
178
184
  hide_lightsensor?: boolean;
179
185
  };
@@ -271,14 +277,28 @@ export type device = {
271
277
  slidePosition?: string;
272
278
  //the version of the device
273
279
  version?: number;
274
- //BLE Mac Address
275
- bleMac?: string;
276
- //Device Model
277
- model?: string;
278
- //Device BLE Model
279
- bleModel?: string;
280
+ // Fan Mode: direct mode: direct; natural mode: "natural"; sleep mode: "sleep"; ultra quiet mode: "baby"
281
+ mode: string;
282
+ //the current battery level
283
+ battery: number;
284
+ //ON/OFF state
285
+ power: string;
286
+ //set nightlight status. turn off: off; mode 1: 1; mode 2: 2
287
+ nightStatus: number;
288
+ //set horizontal oscillation. turn on: on; turn off: off
289
+ oscillation: string;
290
+ //set vertical oscillation. turn on: on; turn off: off
291
+ verticalOscillation: string;
292
+ //battery charge status. charging or uncharged
293
+ chargingStatus: string;
294
+ //fan speed. 1~100
295
+ fanSpeed: number;
280
296
  };
281
297
 
298
+ // values defined but not displayed by API
299
+ export interface deviceInfo extends device {
300
+ }
301
+
282
302
  //a list of virtual infrared remote devices.
283
303
  export type infraredRemoteList = {
284
304
  device: Array<irdevice>;
@@ -300,7 +320,7 @@ export type deviceStatus = {
300
320
 
301
321
  export type deviceStatusBody = {
302
322
  //v1.1 of API
303
- deviceId: string; //device ID. (Used by the following deviceTypes: Bot, Curtain, Meter, Meter Plus, Lock, Keypad, Keypad Touch, Motion Sensor, Contact Sensor, Ceiling Light, Ceiling Light Pro, Plug Mini (US), Plug Mini (JP), Strip Light, Color Bulb, Robot Vacuum Cleaner S1, Robot Vacuum Cleaner S1 Plus, Humidifier, Blind Tilt)
323
+ deviceId: string; //device ID. (Used by the following deviceTypes: Bot, Curtain, Meter, Meter Plus, Lock, Keypad, Keypad Touch, Motion Sensor, Contact Sensor, Ceiling Light, Ceiling Light Pro, Plug Mini (US), Plug Mini (JP), Strip Light, Color Bulb, Robot Vacuum Cleaner S1, Robot Vacuum Cleaner S1 Plus, Humidifier, Blind Tilt, Battery Circulator Fan)
304
324
  deviceType: string; //device type. (Used by the following deviceTypes: Bot, Curtain, Meter, Meter Plus, Lock, Keypad, Keypad Touch, Motion Sensor, Contact Sensor, Ceiling Light, Ceiling Light Pro, Plug Mini (US), Plug Mini (JP), Strip Light, Color Bulb, Robot Vacuum Cleaner S1, Robot Vacuum Cleaner S1 Plus, Humidifier, Blind Tilt)
305
325
  hubDeviceId: string; //device's parent Hub ID. 000000000000 when the device itself is a Hub or it is connected through Wi-Fi. (Used by the following deviceTypes: Bot, Curtain, Meter, Meter Plus, Lock, Keypad, Keypad Touch, Motion Sensor, Contact Sensor, Ceiling Light, Ceiling Light Pro, Plug Mini (JP), Strip Light, Color Bulb, Robot Vacuum Cleaner S1, Robot Vacuum Cleaner S1 Plus, Humidifier, Blind Tilt)
306
326
  power?: string; //ON/OFF state. (Used by the following deviceTypes: Bot, Ceiling Light, Ceiling Light Pro, PLug, Plug Mini (US), Plug Mini (JP), Strip Light, Color Bulb, Humidifier)
@@ -330,16 +350,21 @@ export type deviceStatusBody = {
330
350
  childLock?: boolean; //determines if a Humidifier's safety lock is on or not. (Used by the following deviceTypes: Humidifier)
331
351
  sound?: boolean; //determines if a Humidifier is muted or not. (Used by the following deviceTypes: Humidifier)
332
352
  lackWater?: boolean; //determines if the water tank is empty or not. (Used by the following deviceTypes: Humidifier)
333
- version?: number; //the version of the device. (Used by the following deviceTypes: Blind Tilt, Meter, MeterPlus, IOSensor)
353
+ version?: number; //the version of the device.
334
354
  direction?: string; //the opening direction of a Blind Tilt device. (Used by the following deviceTypes: Blind Tilt)
335
355
  runStatus?: string; //'static' when not moving. (Used by the following deviceTypes: Blind Tilt)
336
- mode?: number; //available for devices. the fan mode. (Used by the following deviceTypes: Smart Fan)
356
+ mode?: number | string; //available for devices. the fan mode. (Used by the following deviceTypes: Smart Fan, Battery Circulator Fan):(direct mode: direct; natural mode: "natural"; sleep mode: "sleep"; ultra quiet mode: "baby")
337
357
  speed?: number; //the fan speed. (Used by the following deviceTypes: Smart Fan)
338
358
  shaking?: boolean; //determines if the fan is swinging or not. (Used by the following deviceTypes: Smart Fan)
339
359
  shakeCenter?: string; //the fan's swing direction. (Used by the following deviceTypes: Smart Fan)
340
360
  shakeRange?: string; //the fan's swing range, 0~120°. (Used by the following deviceTypes: Smart Fan)
341
361
  status?: number //the leak status. 0 for no leak, 1 for leak. (Used by the following deviceTypes: Water Detector)
342
362
  lightLevel?: number; //the light level. (Used by the following deviceTypes: Hub)
363
+ nightStatus: number // set nightlight status. turn off: off; mode 1: 1; mode 2: 2
364
+ oscillation: string // set horizontal oscillation. turn on: on; turn off: off
365
+ verticalOscillation: string // set vertical oscillation. turn on: on; turn off: off
366
+ chargingStatus: string // battery charge status. charging or uncharged
367
+ fanSpeed: number // fan speed. 1~100
343
368
  };
344
369
 
345
370
  export type ad = {
package/src/utils.ts CHANGED
@@ -19,8 +19,8 @@ export enum SwitchBotModel {
19
19
  ContactSensor = 'W1201500',
20
20
  ColorBulb = 'W1401400',
21
21
  StripLight = 'W1701100',
22
- PlugMiniUS = 'W1901400',
23
- PlugMiniJP = 'W2001400',
22
+ PlugMiniUS = 'W1901400/W1901401',
23
+ PlugMiniJP = 'W2001400/W2001401',
24
24
  Lock = 'W1601700',
25
25
  LockPro = 'W3500000',
26
26
  Keypad = 'W2500010',
@@ -30,16 +30,17 @@ export enum SwitchBotModel {
30
30
  WoSweeperMini = 'WoSweeperMini',
31
31
  RobotVacuumCleanerS1 = 'W3011000', // Currently only available in Japan.
32
32
  RobotVacuumCleanerS1Plus = 'W3011010', // Currently only available in Japan.
33
+ RobotVacuumCleanerS10 = 'W3211800',
33
34
  Remote = 'Remote',
34
35
  UniversalRemote = 'UniversalRemote',
35
- CeilingLight = 'W2612230', // Currently only available in Japan.
36
- CeilingLightPro = 'W2612210', // Currently only available in Japan.
36
+ CeilingLight = 'W2612230/W2612240', // Currently only available in Japan.
37
+ CeilingLightPro = 'W2612210/W2612220', // Currently only available in Japan.
37
38
  IndoorCam = 'W1301200',
38
39
  PanTiltCam = 'W1801200',
39
40
  PanTiltCam2K = 'W3101100',
40
41
  BlindTilt = 'W2701600',
41
42
  BatteryCirculatorFan = 'W3800510',
42
- WaterDetector = 'WoWaterDetector',
43
+ WaterDetector = 'W4402000',
43
44
  Unknown = 'Unknown',
44
45
  }
45
46
 
@@ -77,11 +78,25 @@ export function sleep(ms: number): Promise<void> {
77
78
  return new Promise((resolve) => setTimeout(resolve, ms));
78
79
  }
79
80
 
81
+ /**
82
+ * Converts the value to celsius if the temperature units are in Fahrenheit
83
+ **/
84
+ export function convertUnits(value: number, unit: string, convert?: string): number {
85
+ if (unit === 'CELSIUS' && convert === 'CELSIUS') {
86
+ return Math.round((value * 9) / 5 + 32);
87
+ } else if (unit === 'FAHRENHEIT' && convert === 'FAHRENHEIT') {
88
+ // celsius should be to the nearest 0.5 degree
89
+ return Math.round((5 / 9) * (value - 32) * 2) / 2;
90
+ }
91
+ return value;
92
+ }
93
+
94
+
80
95
  export function rgb2hs(r: any, g: any, b: any) {
81
- /*
82
- Credit:
83
- https://github.com/WickyNilliams/pure-color
84
- */
96
+ /**
97
+ * Credit:
98
+ * https://github.com/WickyNilliams/pure-color
99
+ **/
85
100
  r = parseInt(r);
86
101
  g = parseInt(g);
87
102
  b = parseInt(b);