import logging import time import cc1101 _ADDRESS_LENGTH_BITS = 26 _COMMAND_LENGTH_BITS = 2 _BUTTON_INDEX_LENGTH_BITS = 4 _MESSAGE_LENGTH_BITS = ( _ADDRESS_LENGTH_BITS + _COMMAND_LENGTH_BITS + _BUTTON_INDEX_LENGTH_BITS ) _LOGGER = logging.getLogger(__name__) def _cc1101_transmit(payload: bytes, repeats: int = 3) -> None: with cc1101.CC1101(lock_spi_device=True) as transceiver: transceiver.set_base_frequency_hertz(433.93e6) transceiver.set_symbol_rate_baud(3942) transceiver.set_sync_mode(cc1101.SyncMode.NO_PREAMBLE_AND_SYNC_WORD) transceiver.set_packet_length_mode(cc1101.PacketLengthMode.FIXED) transceiver.set_packet_length_bytes(len(payload)) transceiver.disable_checksum() transceiver.set_output_power((0, 0xC6)) # OOK _LOGGER.info("%s", transceiver) for _ in range(repeats): transceiver.transmit(payload) time.sleep(0.08) def _encode_message(message: int) -> bytes: signal = [0b00000100, 0] assert 0 <= message < 2 ** _MESSAGE_LENGTH_BITS, message for bit_index in reversed(range(_MESSAGE_LENGTH_BITS)): if message & (0b1 << bit_index): signal.append(0b10000010) else: signal.append(0b10100000) signal.append(0b10000000) return bytes(signal) class RemoteControl: def __init__(self, address: int) -> None: if not isinstance(address, int): raise ValueError( "expected {}-bit unsigned integer as address, got {!r}".format( _ADDRESS_LENGTH_BITS, address ) ) if address < 0: raise ValueError("address must not be negative (got {!r})".format(address)) if address >= 2 ** _ADDRESS_LENGTH_BITS: raise ValueError( "address must not exceed {} ({}-bit unsigned integer), got {!r}".format( 2 ** _ADDRESS_LENGTH_BITS, _ADDRESS_LENGTH_BITS, address ) ) self._address = address def _send_command(self, command: int, button_index: int) -> None: assert 0 <= command < 2 ** _COMMAND_LENGTH_BITS assert 0 <= button_index < 2 ** _BUTTON_INDEX_LENGTH_BITS _cc1101_transmit( _encode_message( (self._address << _COMMAND_LENGTH_BITS | command) << _BUTTON_INDEX_LENGTH_BITS | button_index ) ) def turn_on(self, button_index: int) -> None: self._send_command(command=0b01, button_index=button_index) def turn_off(self, button_index: int) -> None: self._send_command(command=0b00, button_index=button_index)