__init__.py 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. """Library to handle connection with Switchbot"""
  2. import time
  3. import binascii
  4. import logging
  5. import bluepy
  6. DEFAULT_RETRY_COUNT = 3
  7. DEFAULT_RETRY_TIMEOUT = .2
  8. UUID = "cba20d00-224d-11e6-9fb8-0002a5d5c51b"
  9. HANDLE = "cba20002-224d-11e6-9fb8-0002a5d5c51b"
  10. PRESS_KEY = "570100"
  11. ON_KEY = "570101"
  12. OFF_KEY = "570102"
  13. _LOGGER = logging.getLogger(__name__)
  14. class Switchbot:
  15. """Representation of a Switchbot."""
  16. def __init__(self, mac, retry_count=DEFAULT_RETRY_COUNT) -> None:
  17. self._mac = mac
  18. self._device = None
  19. self._retry_count = retry_count
  20. def _connect(self) -> None:
  21. if self._device is not None:
  22. return
  23. try:
  24. _LOGGER.debug("Connecting to Switchbot...")
  25. self._device = bluepy.btle.Peripheral(self._mac,
  26. bluepy.btle.ADDR_TYPE_RANDOM)
  27. _LOGGER.debug("Connected to Switchbot.")
  28. except bluepy.btle.BTLEException:
  29. _LOGGER.debug("Failed connecting to Switchbot.", exc_info=True)
  30. self._device = None
  31. raise
  32. def _disconnect(self) -> None:
  33. if self._device is None:
  34. return
  35. _LOGGER.debug("Disconnecting")
  36. try:
  37. self._device.disconnect()
  38. except bluepy.btle.BTLEException:
  39. _LOGGER.warning("Error disconnecting from Switchbot.", exc_info=True)
  40. finally:
  41. self._device = None
  42. def _writekey(self, key) -> bool:
  43. _LOGGER.debug("Prepare to send")
  44. hand_service = self._device.getServiceByUUID(UUID)
  45. hand = hand_service.getCharacteristics(HANDLE)[0]
  46. _LOGGER.debug("Sending command, %s", key)
  47. write_result = hand.write(binascii.a2b_hex(key), withResponse=True)
  48. if not write_result:
  49. _LOGGER.error("Sent command but didn't get a response from Switchbot confirming command was sent. "
  50. "Please check the Switchbot.")
  51. else:
  52. _LOGGER.info("Successfully sent command to Switchbot (MAC: %s).", self._mac)
  53. return write_result
  54. def _sendcommand(self, key, retry) -> bool:
  55. send_success = False
  56. try:
  57. self._connect()
  58. send_success = self._writekey(key)
  59. except bluepy.btle.BTLEException:
  60. _LOGGER.warning("Error talking to Switchbot.", exc_info=True)
  61. finally:
  62. self._disconnect()
  63. if send_success:
  64. return send_success
  65. if retry < 1:
  66. _LOGGER.error("Switchbot communication failed. Stopping trying.", exc_info=True)
  67. return False
  68. _LOGGER.warning("Cannot connect to Switchbot. Retrying (remaining: %d)...", retry)
  69. time.sleep(DEFAULT_RETRY_TIMEOUT)
  70. return self._sendcommand(key, retry - 1)
  71. def turn_on(self) -> bool:
  72. """Turn device on."""
  73. return self._sendcommand(ON_KEY, self._retry_count)
  74. def turn_off(self) -> bool:
  75. """Turn device off."""
  76. return self._sendcommand(OFF_KEY, self._retry_count)
  77. def press(self) -> bool:
  78. """Press command to device."""
  79. return self._sendcommand(PRESS_KEY, self._retry_count)