@switchbot/homebridge-switchbot 3.5.0 → 3.5.1-beta.1

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 (137) hide show
  1. package/.github/npm-version-script.cjs +81 -0
  2. package/config.schema.json +4 -4
  3. package/dist/device/blindtilt.d.ts.map +1 -1
  4. package/dist/device/blindtilt.js +64 -189
  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 +34 -68
  8. package/dist/device/bot.js.map +1 -1
  9. package/dist/device/ceilinglight.d.ts +1 -1
  10. package/dist/device/ceilinglight.d.ts.map +1 -1
  11. package/dist/device/ceilinglight.js +65 -158
  12. package/dist/device/ceilinglight.js.map +1 -1
  13. package/dist/device/colorbulb.d.ts +1 -1
  14. package/dist/device/colorbulb.d.ts.map +1 -1
  15. package/dist/device/colorbulb.js +47 -159
  16. package/dist/device/colorbulb.js.map +1 -1
  17. package/dist/device/contact.d.ts.map +1 -1
  18. package/dist/device/contact.js +42 -105
  19. package/dist/device/contact.js.map +1 -1
  20. package/dist/device/curtain.d.ts +1 -0
  21. package/dist/device/curtain.d.ts.map +1 -1
  22. package/dist/device/curtain.js +61 -182
  23. package/dist/device/curtain.js.map +1 -1
  24. package/dist/device/device.d.ts +41 -2
  25. package/dist/device/device.d.ts.map +1 -1
  26. package/dist/device/device.js +182 -5
  27. package/dist/device/device.js.map +1 -1
  28. package/dist/device/fan.d.ts.map +1 -1
  29. package/dist/device/fan.js +76 -145
  30. package/dist/device/fan.js.map +1 -1
  31. package/dist/device/hub.d.ts +7 -1
  32. package/dist/device/hub.d.ts.map +1 -1
  33. package/dist/device/hub.js +54 -17
  34. package/dist/device/hub.js.map +1 -1
  35. package/dist/device/humidifier.d.ts.map +1 -1
  36. package/dist/device/humidifier.js +55 -104
  37. package/dist/device/humidifier.js.map +1 -1
  38. package/dist/device/iosensor.d.ts.map +1 -1
  39. package/dist/device/iosensor.js +27 -46
  40. package/dist/device/iosensor.js.map +1 -1
  41. package/dist/device/lightstrip.d.ts +1 -1
  42. package/dist/device/lightstrip.d.ts.map +1 -1
  43. package/dist/device/lightstrip.js +56 -120
  44. package/dist/device/lightstrip.js.map +1 -1
  45. package/dist/device/lock.d.ts +1 -1
  46. package/dist/device/lock.d.ts.map +1 -1
  47. package/dist/device/lock.js +36 -66
  48. package/dist/device/lock.js.map +1 -1
  49. package/dist/device/meter.d.ts.map +1 -1
  50. package/dist/device/meter.js +27 -46
  51. package/dist/device/meter.js.map +1 -1
  52. package/dist/device/meterplus.d.ts.map +1 -1
  53. package/dist/device/meterplus.js +26 -45
  54. package/dist/device/meterplus.js.map +1 -1
  55. package/dist/device/motion.d.ts.map +1 -1
  56. package/dist/device/motion.js +24 -43
  57. package/dist/device/motion.js.map +1 -1
  58. package/dist/device/plug.d.ts.map +1 -1
  59. package/dist/device/plug.js +32 -66
  60. package/dist/device/plug.js.map +1 -1
  61. package/dist/device/robotvacuumcleaner.d.ts +1 -1
  62. package/dist/device/robotvacuumcleaner.d.ts.map +1 -1
  63. package/dist/device/robotvacuumcleaner.js +43 -88
  64. package/dist/device/robotvacuumcleaner.js.map +1 -1
  65. package/dist/device/waterdetector.d.ts.map +1 -1
  66. package/dist/device/waterdetector.js +23 -43
  67. package/dist/device/waterdetector.js.map +1 -1
  68. package/dist/irdevice/airconditioner.d.ts.map +1 -1
  69. package/dist/irdevice/airconditioner.js +10 -28
  70. package/dist/irdevice/airconditioner.js.map +1 -1
  71. package/dist/irdevice/airpurifier.d.ts.map +1 -1
  72. package/dist/irdevice/airpurifier.js +8 -20
  73. package/dist/irdevice/airpurifier.js.map +1 -1
  74. package/dist/irdevice/camera.d.ts.map +1 -1
  75. package/dist/irdevice/camera.js +8 -20
  76. package/dist/irdevice/camera.js.map +1 -1
  77. package/dist/irdevice/fan.d.ts.map +1 -1
  78. package/dist/irdevice/fan.js +8 -20
  79. package/dist/irdevice/fan.js.map +1 -1
  80. package/dist/irdevice/irdevice.d.ts +7 -0
  81. package/dist/irdevice/irdevice.d.ts.map +1 -1
  82. package/dist/irdevice/irdevice.js +28 -0
  83. package/dist/irdevice/irdevice.js.map +1 -1
  84. package/dist/irdevice/light.d.ts.map +1 -1
  85. package/dist/irdevice/light.js +8 -20
  86. package/dist/irdevice/light.js.map +1 -1
  87. package/dist/irdevice/other.d.ts.map +1 -1
  88. package/dist/irdevice/other.js +8 -20
  89. package/dist/irdevice/other.js.map +1 -1
  90. package/dist/irdevice/tv.d.ts.map +1 -1
  91. package/dist/irdevice/tv.js +8 -20
  92. package/dist/irdevice/tv.js.map +1 -1
  93. package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
  94. package/dist/irdevice/vacuumcleaner.js +8 -20
  95. package/dist/irdevice/vacuumcleaner.js.map +1 -1
  96. package/dist/irdevice/waterheater.d.ts.map +1 -1
  97. package/dist/irdevice/waterheater.js +8 -20
  98. package/dist/irdevice/waterheater.js.map +1 -1
  99. package/dist/settings.d.ts +4 -2
  100. package/dist/settings.d.ts.map +1 -1
  101. package/dist/settings.js.map +1 -1
  102. package/dist/utils.d.ts +19 -1
  103. package/dist/utils.d.ts.map +1 -1
  104. package/dist/utils.js +20 -1
  105. package/dist/utils.js.map +1 -1
  106. package/package.json +8 -8
  107. package/src/device/blindtilt.ts +71 -186
  108. package/src/device/bot.ts +32 -68
  109. package/src/device/ceilinglight.ts +67 -153
  110. package/src/device/colorbulb.ts +51 -155
  111. package/src/device/contact.ts +49 -104
  112. package/src/device/curtain.ts +70 -177
  113. package/src/device/device.ts +207 -8
  114. package/src/device/fan.ts +75 -147
  115. package/src/device/hub.ts +55 -19
  116. package/src/device/humidifier.ts +52 -104
  117. package/src/device/iosensor.ts +25 -46
  118. package/src/device/lightstrip.ts +54 -121
  119. package/src/device/lock.ts +35 -67
  120. package/src/device/meter.ts +25 -46
  121. package/src/device/meterplus.ts +24 -45
  122. package/src/device/motion.ts +22 -43
  123. package/src/device/plug.ts +30 -66
  124. package/src/device/robotvacuumcleaner.ts +40 -89
  125. package/src/device/waterdetector.ts +22 -43
  126. package/src/irdevice/airconditioner.ts +10 -26
  127. package/src/irdevice/airpurifier.ts +8 -20
  128. package/src/irdevice/camera.ts +8 -20
  129. package/src/irdevice/fan.ts +8 -20
  130. package/src/irdevice/irdevice.ts +29 -0
  131. package/src/irdevice/light.ts +8 -20
  132. package/src/irdevice/other.ts +8 -20
  133. package/src/irdevice/tv.ts +8 -20
  134. package/src/irdevice/vacuumcleaner.ts +8 -20
  135. package/src/irdevice/waterheater.ts +8 -20
  136. package/src/settings.ts +4 -2
  137. package/src/utils.ts +20 -1
@@ -2,8 +2,6 @@
2
2
  *
3
3
  * blindtilt.ts: @switchbot/homebridge-switchbot.
4
4
  */
5
- import { request } from 'undici';
6
- import { Devices } from '../settings.js';
7
5
  import { interval, Subject } from 'rxjs';
8
6
  import { deviceBase } from './device.js';
9
7
  import { BlindTiltMappingMode } from '../utils.js';
@@ -267,14 +265,13 @@ export class BlindTilt extends deviceBase {
267
265
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.WindowCovering.CurrentPosition},`
268
266
  + ` TargetPosition: ${this.WindowCovering.TargetPosition}, PositionState: ${this.WindowCovering.PositionState},`);
269
267
 
270
- if (!this.device.blindTilt?.hide_lightsensor) {
271
- const set_minLux = this.device.blindTilt?.set_minLux ?? 1;
272
- const set_maxLux = this.device.blindTilt?.set_maxLux ?? 6001;
273
- const spaceBetweenLevels = 9;
274
-
268
+ if (!this.device.blindTilt?.hide_lightsensor && this.LightSensor?.Service) {
275
269
  if (this.LightSensor?.CurrentAmbientLightLevel === 0) {
276
270
  this.LightSensor!.CurrentAmbientLightLevel = 0.0001;
277
271
  }
272
+ const set_minLux = this.device.blindTilt?.set_minLux ?? 1;
273
+ const set_maxLux = this.device.blindTilt?.set_maxLux ?? 6001;
274
+ const spaceBetweenLevels = 9;
278
275
 
279
276
  // Brightness
280
277
  switch (serviceData.lightLevel) {
@@ -462,63 +459,43 @@ export class BlindTilt extends deviceBase {
462
459
 
463
460
  async BLERefreshStatus(): Promise<void> {
464
461
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLERefreshStatus`);
465
- const switchbot = await this.platform.connectBLE();
466
- // Convert to BLE Address
467
- this.device.bleMac = this.device
468
- .deviceId!.match(/.{1,2}/g)!
469
- .join(':')
470
- .toLowerCase();
471
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
472
- this.getCustomBLEAddress(switchbot);
473
- // Start to monitor advertisement packets
474
- (async () => {
462
+ const switchbot = await this.switchbotBLE();
463
+
464
+ if (switchbot === undefined) {
465
+ await this.BLERefreshConnection(switchbot);
466
+ } else {
475
467
  // Start to monitor advertisement packets
476
- await switchbot.startScan({ model: this.device.bleModel, id: this.device.bleMac });
477
- // Set an event handler
478
- switchbot.onadvertisement = (ad: any) => {
479
- if (this.device.bleMac === ad.address && ad.model === this.device.bleModel) {
480
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ${JSON.stringify(ad, null, ' ')}`);
481
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} address: ${ad.address}, model: ${ad.model}`);
482
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
468
+ (async () => {
469
+ // Start to monitor advertisement packets
470
+ const serviceData: serviceData = await this.monitorAdvertisementPackets(switchbot);
471
+ // Update HomeKit
472
+ if (serviceData.model !== '' && serviceData.modelName !== '') {
473
+ await this.BLEparseStatus(serviceData);
474
+ await this.updateHomeKitCharacteristics();
483
475
  } else {
484
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
476
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed to get serviceData, serviceData: ${serviceData}`);
477
+ await this.BLERefreshConnection(switchbot);
485
478
  }
486
- };
487
- // Wait 10 seconds
488
- await switchbot.wait(this.scanDuration * 1000);
489
- // Stop to monitor
490
- await switchbot.stopScan();
491
- // Update HomeKit
492
- await this.BLEparseStatus(switchbot.onadvertisement.serviceData);
493
- await this.updateHomeKitCharacteristics();
494
- })();
495
- if (switchbot === undefined) {
496
- await this.BLERefreshConnection(switchbot);
479
+ })();
497
480
  }
498
481
  }
499
482
 
500
483
  async openAPIRefreshStatus(): Promise<void> {
501
484
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
502
485
  try {
503
- const { body, statusCode } = await this.platform.retryRequest(this.deviceMaxRetries, this.deviceDelayBetweenRetries,
504
- `${Devices}/${this.device.deviceId}/status`, { headers: this.platform.generateHeaders() });
505
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
486
+ const { body, statusCode } = await this.deviceRefreshStatus();
506
487
  const deviceStatus: any = await body.json();
507
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
508
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
488
+ await this.refreshStatusCodes(statusCode, deviceStatus);;
509
489
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
510
- this.debugSuccessLog(`${this.device.deviceType}: ${this.accessory.displayName} `
511
- + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
512
- this.openAPIparseStatus(deviceStatus);
513
- this.updateHomeKitCharacteristics();
490
+ await this.successfulRefreshStatus(statusCode, deviceStatus);
491
+ await this.openAPIparseStatus(deviceStatus);
492
+ await this.updateHomeKitCharacteristics();
514
493
  } else {
515
- this.statusCode(statusCode);
516
- this.statusCode(deviceStatus.statusCode);
494
+ await this.statusCodes(statusCode, deviceStatus);
517
495
  }
518
496
  } catch (e: any) {
519
- this.apiError(e);
520
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}`
521
- + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
497
+ await this.apiError(e);
498
+ await this.openAPIRefreshError(e);
522
499
  }
523
500
  }
524
501
 
@@ -539,7 +516,7 @@ export class BlindTilt extends deviceBase {
539
516
  if (!device.blindTilt?.hide_lightsensor) {
540
517
  this.LightSensor!.CurrentAmbientLightLevel = lightLevel;
541
518
  }
542
- this.updateHomeKitCharacteristics();
519
+ await this.updateHomeKitCharacteristics();
543
520
  } catch (e: any) {
544
521
  this.errorLog(`${device.deviceType}: ${accessory.displayName} failed to handle webhook. Received: ${JSON.stringify(context)} Error: ${e}`);
545
522
  }
@@ -558,8 +535,7 @@ export class BlindTilt extends deviceBase {
558
535
  await this.openAPIpushChanges();
559
536
  } else {
560
537
  await this.offlineOff();
561
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
562
- + ` ${this.device.connectionType}, pushChanges will not happen.`);
538
+ await this.pushChangeDisabled();
563
539
  }
564
540
  // Refresh the status from the API
565
541
  interval(15000)
@@ -575,16 +551,12 @@ export class BlindTilt extends deviceBase {
575
551
  if (this.WindowCovering.TargetPosition !== this.WindowCovering.CurrentPosition) {
576
552
  const switchbot = await this.platform.connectBLE();
577
553
  // Convert to BLE Address
578
- this.device.bleMac = this.device
579
- .deviceId!.match(/.{1,2}/g)!
580
- .join(':')
581
- .toLowerCase();
582
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
554
+ await this.convertBLEAddress();
583
555
  const { setPositionMode, Mode }: { setPositionMode: number; Mode: string; } = await this.setPerformance();
584
556
  this.debugLog(`${this.accessory.displayName} Mode: ${Mode}`);
585
557
  if (switchbot !== false) {
586
558
  switchbot
587
- .discover({ model: 'c', quick: true, id: this.device.bleMac })
559
+ .discover({ model: this.device.bleModel, quick: true, id: this.device.bleMac })
588
560
  .then(async (device_list: any) => {
589
561
  this.infoLog(`${this.accessory.displayName} Target Position: ${this.WindowCovering.TargetPosition}`);
590
562
  return await this.retryBLE({
@@ -600,13 +572,12 @@ export class BlindTilt extends deviceBase {
600
572
  + `Target Position: ${this.WindowCovering.TargetPosition} sent over BLE, sent successfully`);
601
573
  })
602
574
  .catch(async (e: any) => {
603
- this.apiError(e);
604
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLEpushChanges with ${this.device.connectionType}`
605
- + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
575
+ await this.apiError(e);
576
+ await this.failedBLEChanges(e);
606
577
  await this.BLEPushConnection();
607
578
  });
608
579
  } else {
609
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} wasn't able to establish BLE Connection`);
580
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} wasn't able to establish BLE Connection,`);
610
581
  await this.BLEPushConnection();
611
582
  }
612
583
  } else {
@@ -650,24 +621,15 @@ export class BlindTilt extends deviceBase {
650
621
  }
651
622
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API, body: ${bodyChange},`);
652
623
  try {
653
- const { body, statusCode } = await request(`${Devices}/${this.device.deviceId}/commands`, {
654
- body: bodyChange,
655
- method: 'POST',
656
- headers: this.platform.generateHeaders(),
657
- });
658
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
624
+ const { body, statusCode } = await this.pushChangeRequest(bodyChange);
659
625
  const deviceStatus: any = await body.json();
660
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
661
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus body: ${JSON.stringify(deviceStatus.body)}`);
662
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
626
+ await this.pushStatusCodes(statusCode, deviceStatus);
663
627
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
664
- this.debugSuccessLog(`${this.device.deviceType}: ${this.accessory.displayName} `
665
- + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
666
- this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
667
- + `request to SwitchBot API, body: ${JSON.stringify(JSON.parse(bodyChange))} sent successfully`);
628
+ await this.successfulPushChange(statusCode, deviceStatus, bodyChange);
629
+ await this.updateHomeKitCharacteristics();
668
630
  } else {
669
- this.statusCode(statusCode);
670
- this.statusCode(deviceStatus.statusCode);
631
+ await this.statusCode(statusCode);
632
+ await this.statusCode(deviceStatus.statusCode);
671
633
  }
672
634
  } catch (e: any) {
673
635
  this.apiError(e);
@@ -686,36 +648,31 @@ export class BlindTilt extends deviceBase {
686
648
  * Handle requests to set the value of the "Target Horizontal Tilt" characteristic
687
649
  */
688
650
  async TargetHorizontalTiltAngleSet(value: CharacteristicValue): Promise<void> {
689
- if (this.WindowCovering.TargetHorizontalTiltAngle === this.accessory.context.TargetHorizontalTiltAngle) {
690
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No Changes, Set TargetHorizontalTiltAngle: ${value}`);
651
+ if (this.WindowCovering.TargetHorizontalTiltAngle !== this.accessory.context.TargetHorizontalTiltAngle) {
652
+ await this.changeSet(value, 'TargetHorizontalTiltAngle');
691
653
  } else {
692
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set TargetHorizontalTiltAngle: ${value}`);
654
+ await this.noChangeSet(value, 'TargetHorizontalTiltAngle');
693
655
  }
694
656
 
695
657
  //value = value < 0 ? -90 : 90;
696
658
  this.WindowCovering.TargetHorizontalTiltAngle = value;
697
- if (this.device.mqttURL) {
698
- this.mqttPublish('TargetHorizontalTiltAngle', this.WindowCovering.TargetHorizontalTiltAngle.toString());
699
- }
700
-
701
- this.startUpdatingBlindTiltIfNeeded();
659
+ await this.mqtt('TargetHorizontalTiltAngle', this.WindowCovering.TargetHorizontalTiltAngle);
660
+ await this.startUpdatingBlindTiltIfNeeded();
702
661
  }
703
662
 
704
663
  /**
705
664
  * Handle requests to set the value of the "Target Position" characteristic
706
665
  */
707
666
  async TargetPositionSet(value: CharacteristicValue): Promise<void> {
708
- if (this.WindowCovering.TargetPosition === this.accessory.context.TargetPosition) {
709
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No Changes, Set TargetPosition: ${value}`);
667
+ if (this.WindowCovering.TargetPosition !== this.accessory.context.TargetPosition) {
668
+ await this.changeSet(value, 'TargetPosition');
710
669
  } else {
711
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set TargetPosition: ${value}`);
670
+ await this.noChangeSet(value, 'TargetPosition');
712
671
  }
713
672
 
714
673
  this.WindowCovering.TargetPosition = value;
715
- if (this.device.mqttURL) {
716
- this.mqttPublish('TargetPosition', this.WindowCovering.TargetPosition.toString());
717
- }
718
- this.startUpdatingBlindTiltIfNeeded();
674
+ await this.mqtt('TargetPosition', this.WindowCovering.TargetPosition);
675
+ await this.startUpdatingBlindTiltIfNeeded();
719
676
  }
720
677
 
721
678
  async startUpdatingBlindTiltIfNeeded(): Promise<void> {
@@ -760,106 +717,33 @@ export class BlindTilt extends deviceBase {
760
717
  await this.setMinMax();
761
718
  // CurrentHorizontalTiltAngle
762
719
  if (this.mappingMode === BlindTiltMappingMode.UseTiltForDirection) {
763
- if (this.WindowCovering.CurrentHorizontalTiltAngle === undefined || Number.isNaN(this.WindowCovering.CurrentHorizontalTiltAngle)) {
764
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
765
- + ` CurrentHorizontalTiltAngle: ${this.WindowCovering.CurrentHorizontalTiltAngle}`);
766
- } else {
767
- if (this.device.mqttURL) {
768
- this.mqttPublish('CurrentHorizontalTiltAngle', this.WindowCovering.CurrentHorizontalTiltAngle.toString());
769
- }
770
- this.accessory.context.CurrentHorizontalTiltAngle = this.WindowCovering.CurrentHorizontalTiltAngle;
771
- this.WindowCovering.Service.updateCharacteristic(
772
- this.hap.Characteristic.CurrentHorizontalTiltAngle,
773
- Number(this.WindowCovering.CurrentHorizontalTiltAngle));
774
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}
775
- updateCharacteristic CurrentHorizontalTiltAngle: ${this.WindowCovering.CurrentHorizontalTiltAngle}`);
776
- }
720
+ await this.updateCharacteristic(this.WindowCovering.Service, this.hap.Characteristic.CurrentHorizontalTiltAngle,
721
+ this.WindowCovering.CurrentHorizontalTiltAngle, 'CurrentHorizontalTiltAngle');
777
722
  }
778
723
  // CurrentPosition
779
- if (this.WindowCovering.CurrentPosition === undefined || Number.isNaN(this.WindowCovering.CurrentPosition)) {
780
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
781
- } else {
782
- if (this.device.mqttURL) {
783
- this.mqttPublish('CurrentPosition', this.WindowCovering.CurrentPosition.toString());
784
- }
785
- this.accessory.context.CurrentPosition = this.WindowCovering.CurrentPosition;
786
- this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, Number(this.WindowCovering.CurrentPosition));
787
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
788
- + ` updateCharacteristic CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
789
- }
724
+ await this.updateCharacteristic(this.WindowCovering.Service, this.hap.Characteristic.CurrentPosition,
725
+ this.WindowCovering.CurrentPosition, 'CurrentPosition');
790
726
  // PositionState
791
- if (this.WindowCovering.PositionState === undefined) {
792
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} PositionState: ${this.WindowCovering.PositionState}`);
793
- } else {
794
- if (this.device.mqttURL) {
795
- this.mqttPublish('PositionState', this.WindowCovering.PositionState.toString());
796
- }
797
- this.accessory.context.PositionState = this.WindowCovering.PositionState;
798
- this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.PositionState, Number(this.WindowCovering.PositionState));
799
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
800
- + ` PositionState: ${this.WindowCovering.PositionState}`);
801
- }
727
+ await this.updateCharacteristic(this.WindowCovering.Service, this.hap.Characteristic.PositionState,
728
+ this.WindowCovering.PositionState, 'PositionState');
802
729
  // TargetPosition
803
- if (this.WindowCovering.TargetPosition === undefined || Number.isNaN(this.WindowCovering.TargetPosition)) {
804
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} TargetPosition: ${this.WindowCovering.TargetPosition}`);
805
- } else {
806
- if (this.device.mqttURL) {
807
- this.mqttPublish('TargetPosition', this.WindowCovering.TargetPosition.toString());
808
- }
809
- this.accessory.context.TargetPosition = this.WindowCovering.TargetPosition;
810
- this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, Number(this.WindowCovering.TargetPosition));
811
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
812
- + ` TargetPosition: ${this.WindowCovering.TargetPosition}`);
813
- }
730
+ await this.updateCharacteristic(this.WindowCovering.Service, this.hap.Characteristic.TargetPosition,
731
+ this.WindowCovering.TargetPosition, 'TargetPosition');
814
732
  // CurrentAmbientLightLevel
815
- if (!this.device.blindTilt?.hide_lightsensor) {
816
- if (this.LightSensor!.CurrentAmbientLightLevel === undefined || Number.isNaN(this.LightSensor!.CurrentAmbientLightLevel)) {
817
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
818
- + ` CurrentAmbientLightLevel: ${this.LightSensor!.CurrentAmbientLightLevel}`);
819
- } else {
820
- if (this.device.mqttURL) {
821
- this.mqttPublish('CurrentAmbientLightLevel', this.LightSensor!.CurrentAmbientLightLevel.toString());
822
- }
823
- this.accessory.context.CurrentAmbientLightLevel = this.LightSensor!.CurrentAmbientLightLevel;
824
- this.LightSensor!.Service.updateCharacteristic(this.hap.Characteristic.CurrentAmbientLightLevel, this.LightSensor!.CurrentAmbientLightLevel);
825
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
826
- + ` updateCharacteristic CurrentAmbientLightLevel: ${this.LightSensor!.CurrentAmbientLightLevel}`);
827
- }
733
+ if (!this.device.blindTilt?.hide_lightsensor && this.LightSensor?.Service) {
734
+ const history = { time: Math.round(new Date().valueOf() / 1000), lux: this.LightSensor.CurrentAmbientLightLevel };
735
+ await this.updateCharacteristic(this.LightSensor?.Service, this.hap.Characteristic.CurrentAmbientLightLevel,
736
+ this.LightSensor?.CurrentAmbientLightLevel, 'CurrentAmbientLightLevel', history);
828
737
  }
829
738
  // BatteryLevel
830
- if (this.Battery.BatteryLevel === undefined) {
831
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel}`);
832
- } else {
833
- if (this.device.mqttURL) {
834
- this.mqttPublish('BatteryLevel', this.Battery.BatteryLevel.toString());
835
- }
836
- this.accessory.context.BatteryLevel = this.Battery.BatteryLevel;
837
- this.Battery?.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, this.Battery.BatteryLevel);
838
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.Battery.BatteryLevel}`);
839
- }
739
+ await this.updateCharacteristic(this.Battery.Service, this.hap.Characteristic.BatteryLevel,
740
+ this.Battery.BatteryLevel, 'BatteryLevel');
840
741
  // StatusLowBattery
841
- if (this.Battery.StatusLowBattery === undefined) {
842
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} StatusLowBattery: ${this.Battery.StatusLowBattery}`);
843
- } else {
844
- if (this.device.mqttURL) {
845
- this.mqttPublish('StatusLowBattery', this.Battery.StatusLowBattery.toString());
846
- }
847
- this.accessory.context.StatusLowBattery = this.Battery.StatusLowBattery;
848
- this.Battery?.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, this.Battery.StatusLowBattery);
849
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
850
- + ` StatusLowBattery: ${this.Battery.StatusLowBattery}`);
851
- }
852
- if (this.Battery.ChargingState === undefined) {
853
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ChargingState: ${this.Battery.ChargingState}`);
854
- } else {
855
- if (this.device.mqttURL) {
856
- this.mqttPublish('ChargingState', this.Battery.ChargingState.toString());
857
- }
858
- this.accessory.context.ChargingState = this.Battery.ChargingState;
859
- this.Battery.Service.updateCharacteristic(this.hap.Characteristic.ChargingState, this.Battery.ChargingState);
860
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
861
- + ` ChargingState: ${this.Battery.ChargingState}`);
862
- }
742
+ await this.updateCharacteristic(this.Battery.Service, this.hap.Characteristic.StatusLowBattery,
743
+ this.Battery.StatusLowBattery, 'StatusLowBattery');
744
+ // ChargingState
745
+ await this.updateCharacteristic(this.Battery.Service, this.hap.Characteristic.ChargingState,
746
+ this.Battery.ChargingState, 'ChargingState');
863
747
  }
864
748
 
865
749
  async BLEPushConnection() {
@@ -963,7 +847,8 @@ export class BlindTilt extends deviceBase {
963
847
 
964
848
  // homekit position 0 => closed
965
849
  // homekit position 100 => open
966
- deviceDirection;
850
+ const direction = deviceDirection === 'up' ? 'up' : 'down';
851
+ this.debugLog(`Mapping device values to homekit values, devicePostion: ${devicePosition}, deviceDirection: ${direction}`);
967
852
  switch (this.mappingMode) {
968
853
  case BlindTiltMappingMode.OnlyUp:
969
854
  // we only close upwards, so we see anything that is tilted downwards(<50) as open
package/src/device/bot.ts CHANGED
@@ -2,10 +2,8 @@
2
2
  *
3
3
  * bot.ts: @switchbot/homebridge-switchbot.
4
4
  */
5
- import { request } from 'undici';
6
5
  import { deviceBase } from './device.js';
7
6
  import { interval, Subject } from 'rxjs';
8
- import { Devices } from '../settings.js';
9
7
  import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
10
8
 
11
9
  import type { SwitchBotPlatform } from '../platform.js';
@@ -599,63 +597,43 @@ export class Bot extends deviceBase {
599
597
 
600
598
  async BLERefreshStatus(): Promise<void> {
601
599
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLERefreshStatus`);
602
- const switchbot = await this.platform.connectBLE();
603
- // Convert to BLE Address
604
- this.device.bleMac = this.device
605
- .deviceId!.match(/.{1,2}/g)!
606
- .join(':')
607
- .toLowerCase();
608
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
609
- this.getCustomBLEAddress(switchbot);
600
+ const switchbot = await this.switchbotBLE();
601
+
602
+ if (switchbot === undefined) {
603
+ await this.BLERefreshConnection(switchbot);
604
+ } else {
610
605
  // Start to monitor advertisement packets
611
- (async () => {
606
+ (async () => {
612
607
  // Start to monitor advertisement packets
613
- await switchbot.startScan({ model: this.device.bleModel, id: this.device.bleMac });
614
- // Set an event handler
615
- switchbot.onadvertisement = (ad: any) => {
616
- if (this.device.bleMac === ad.address && ad.model === this.device.bleModel) {
617
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ${JSON.stringify(ad, null, ' ')}`);
618
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} address: ${ad.address}, model: ${ad.model}`);
619
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
608
+ const serviceData: serviceData = await this.monitorAdvertisementPackets(switchbot);
609
+ // Update HomeKit
610
+ if (serviceData.model !== '' && serviceData.modelName !== '') {
611
+ await this.BLEparseStatus(serviceData);
612
+ await this.updateHomeKitCharacteristics();
620
613
  } else {
621
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
614
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed to get serviceData, serviceData: ${serviceData}`);
615
+ await this.BLERefreshConnection(switchbot);
622
616
  }
623
- };
624
- // Wait 10 seconds
625
- await switchbot.wait(this.scanDuration * 1000);
626
- // Stop to monitor
627
- await switchbot.stopScan();
628
- // Update HomeKit
629
- await this.BLEparseStatus(switchbot.onadvertisement.serviceData);
630
- await this.updateHomeKitCharacteristics();
631
- })();
632
- if (switchbot === undefined) {
633
- await this.BLERefreshConnection(switchbot);
617
+ })();
634
618
  }
635
619
  }
636
620
 
637
621
  async openAPIRefreshStatus(): Promise<void> {
638
622
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
639
623
  try {
640
- const { body, statusCode } = await this.platform.retryRequest(this.deviceMaxRetries, this.deviceDelayBetweenRetries,
641
- `${Devices}/${this.device.deviceId}/status`, { headers: this.platform.generateHeaders() });
642
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
624
+ const { body, statusCode } = await this.deviceRefreshStatus();
643
625
  const deviceStatus: any = await body.json();
644
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
645
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
626
+ await this.refreshStatusCodes(statusCode, deviceStatus);;
646
627
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
647
- this.debugSuccessLog(`${this.device.deviceType}: ${this.accessory.displayName} `
648
- + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
649
- this.openAPIparseStatus(deviceStatus);
650
- this.updateHomeKitCharacteristics();
628
+ await this.successfulRefreshStatus(statusCode, deviceStatus);
629
+ await this.openAPIparseStatus(deviceStatus);
630
+ await this.updateHomeKitCharacteristics();
651
631
  } else {
652
- this.statusCode(statusCode);
653
- this.statusCode(deviceStatus.statusCode);
632
+ await this.statusCodes(statusCode, deviceStatus);
654
633
  }
655
634
  } catch (e: any) {
656
- this.apiError(e);
657
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}`
658
- + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
635
+ await this.apiError(e);
636
+ await this.openAPIRefreshError(e);
659
637
  }
660
638
  }
661
639
 
@@ -696,12 +674,11 @@ export class Bot extends deviceBase {
696
674
  this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} pushChanges enableCloudService: ${this.device.enableCloudService}`);
697
675
  } else if (this.BLE) {
698
676
  await this.BLEpushChanges();
699
- } else if (this.OpenAPI) {
677
+ } else if (this.OpenAPI && this.platform.config.credentials?.token) {
700
678
  await this.openAPIpushChanges();
701
679
  } else {
702
680
  await this.offlineOff();
703
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
704
- + ` ${this.device.connectionType}, pushChanges will not happen.`);
681
+ await this.pushChangeDisabled();
705
682
  }
706
683
  // Refresh the status from the API
707
684
  interval(15000)
@@ -719,11 +696,7 @@ export class Bot extends deviceBase {
719
696
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges On: ${On} OnCached: ${this.accessory.context.On}`);
720
697
  const switchbot = await this.platform.connectBLE();
721
698
  // Convert to BLE Address
722
- this.device.bleMac = this.device
723
- .deviceId!.match(/.{1,2}/g)!
724
- .join(':')
725
- .toLowerCase();
726
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
699
+ await this.convertBLEAddress();
727
700
  //if (switchbot !== false) {
728
701
  if (this.botMode === 'press') {
729
702
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Bot Mode: ${this.botMode}`);
@@ -756,7 +729,7 @@ export class Bot extends deviceBase {
756
729
  } else if (this.botMode === 'switch') {
757
730
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Press Mode: ${this.botMode}`);
758
731
  switchbot
759
- .discover({ model: 'H', quick: true, id: this.device.bleMac })
732
+ .discover({ model: this.device.bleModel, quick: true, id: this.device.bleMac })
760
733
  .then(async (device_list: any) => {
761
734
  this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${On}`);
762
735
  return await this.retryBLE({
@@ -819,24 +792,15 @@ export class Bot extends deviceBase {
819
792
  });
820
793
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API, body: ${bodyChange},`);
821
794
  try {
822
- const { body, statusCode } = await request(`${Devices}/${this.device.deviceId}/commands`, {
823
- body: bodyChange,
824
- method: 'POST',
825
- headers: this.platform.generateHeaders(),
826
- });
827
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
795
+ const { body, statusCode } = await this.pushChangeRequest(bodyChange);
828
796
  const deviceStatus: any = await body.json();
829
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
830
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus body: ${JSON.stringify(deviceStatus.body)}`);
831
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
797
+ await this.pushStatusCodes(statusCode, deviceStatus);
832
798
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
833
- this.debugSuccessLog(`${this.device.deviceType}: ${this.accessory.displayName} `
834
- + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
835
- this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
836
- + `request to SwitchBot API, body: ${JSON.stringify(JSON.parse(bodyChange))} sent successfully`);
799
+ await this.successfulPushChange(statusCode, deviceStatus, bodyChange);
800
+ await this.updateHomeKitCharacteristics();
837
801
  } else {
838
- this.statusCode(statusCode);
839
- this.statusCode(deviceStatus.statusCode);
802
+ await this.statusCode(statusCode);
803
+ await this.statusCode(deviceStatus.statusCode);
840
804
  }
841
805
  if (this.device.bot?.mode === 'multipress') {
842
806
  this.multiPressCount--;