__init__.py 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. import logging
  2. import time
  3. import cc1101
  4. _ADDRESS_LENGTH_BITS = 26
  5. _COMMAND_LENGTH_BITS = 2
  6. _BUTTON_INDEX_LENGTH_BITS = 4
  7. _MESSAGE_LENGTH_BITS = (
  8. _ADDRESS_LENGTH_BITS + _COMMAND_LENGTH_BITS + _BUTTON_INDEX_LENGTH_BITS
  9. )
  10. _LOGGER = logging.getLogger(__name__)
  11. def _cc1101_transmit(payload: bytes, repeats: int = 3) -> None:
  12. with cc1101.CC1101(lock_spi_device=True) as transceiver:
  13. transceiver.set_base_frequency_hertz(433.93e6)
  14. transceiver.set_symbol_rate_baud(3942)
  15. transceiver.set_sync_mode(cc1101.SyncMode.NO_PREAMBLE_AND_SYNC_WORD)
  16. transceiver.set_packet_length_mode(cc1101.PacketLengthMode.FIXED)
  17. transceiver.set_packet_length_bytes(len(payload))
  18. transceiver.disable_checksum()
  19. transceiver.set_output_power((0, 0xC6)) # OOK
  20. _LOGGER.info("%s", transceiver)
  21. for _ in range(repeats):
  22. transceiver.transmit(payload)
  23. time.sleep(0.08)
  24. def _encode_message(message: int) -> bytes:
  25. signal = [0b00000100, 0]
  26. assert 0 <= message < 2 ** _MESSAGE_LENGTH_BITS, message
  27. for bit_index in reversed(range(_MESSAGE_LENGTH_BITS)):
  28. if message & (0b1 << bit_index):
  29. signal.append(0b10000010)
  30. else:
  31. signal.append(0b10100000)
  32. signal.append(0b10000000)
  33. return bytes(signal)
  34. class RemoteControl:
  35. def __init__(self, address: int) -> None:
  36. if not isinstance(address, int):
  37. raise ValueError(
  38. "expected {}-bit unsigned integer as address, got {!r}".format(
  39. _ADDRESS_LENGTH_BITS, address
  40. )
  41. )
  42. if address < 0:
  43. raise ValueError("address must not be negative (got {!r})".format(address))
  44. if address >= 2 ** _ADDRESS_LENGTH_BITS:
  45. raise ValueError(
  46. "address must not exceed {} ({}-bit unsigned integer), got {!r}".format(
  47. 2 ** _ADDRESS_LENGTH_BITS, _ADDRESS_LENGTH_BITS, address
  48. )
  49. )
  50. self._address = address
  51. def _send_command(self, command: int, button_index: int) -> None:
  52. assert 0 <= command < 2 ** _COMMAND_LENGTH_BITS
  53. assert 0 <= button_index < 2 ** _BUTTON_INDEX_LENGTH_BITS
  54. _cc1101_transmit(
  55. _encode_message(
  56. (self._address << _COMMAND_LENGTH_BITS | command)
  57. << _BUTTON_INDEX_LENGTH_BITS
  58. | button_index
  59. )
  60. )
  61. def turn_on(self, button_index: int) -> None:
  62. self._send_command(command=0b01, button_index=button_index)
  63. def turn_off(self, button_index: int) -> None:
  64. self._send_command(command=0b00, button_index=button_index)