def __init__(self, config: Config, request_transmitter: 'Queue[Request]'): threading.Thread.__init__(self) self._config = config if not config.rfcomm_enabled: self._logger.fatal('RFCC is disabled but is trying to create') raise Exception('RFCC is disabled but is trying to create') self._count_connected = 0 self._request_transmitter = request_transmitter self._protocol_parser = ProtocolParser(self)
def __init__(self, config: Config, request_transmitter: 'Queue[Request]'): threading.Thread.__init__(self) self._config = config if not config.mqtt_enabled: self._logger.fatal('Mqtt is disabled but is trying to create') raise Exception('Mqtt is disabled but is trying to create') self._request_transmitter = request_transmitter self._mqtt_address = config.mqtt_address self._is_mqtt_connected = False self._protocol_parser = ProtocolParser(self)
def test_serialize_with_empty_payload(self): # Given command = CommandType.GetSettings payload = None expected_bytes = bytes(b'\xfd\xba\xdc\x01\x50\xb4\x11\xff\x04\x00\x00\xab') parser = ProtocolParser(MagicMock()) # When package = ProtocolParser.create_package(command, payload) ser_package = parser.serialize_package(package) # Then assert expected_bytes == ser_package
def test_serialize(self): # Given command = CommandType.GetGestures payload = bytes(b'\xba\x05') expected_bytes = bytes(b'\xfd\xba\xdc\x01\x50\xb4\x11\xff\x06\x02\x00\xba\x05\xb1') parser = ProtocolParser(MagicMock()) # When package = ProtocolParser.create_package(command, payload) ser_package = parser.serialize_package(package) # Then assert expected_bytes == ser_package
def test_create_package_with_empty_payload(self): # Given command = CommandType.GetGestures # When package = ProtocolParser.create_package(command, None) # Then assert command == package.command_type assert package.payload is None assert 0 == package.payload_size
def test_create_package(self): # Given command = CommandType.GetGestures payload = bytes(b'\xba\x05') # When package = ProtocolParser.create_package(command, payload) # Then assert command == package.command_type assert payload == package.payload assert len(payload) == package.payload_size
def test_receive_sequence_package(self): # Given parser = ProtocolParser(MagicMock()) package1_received = bytes(b'\xfd\xba\xdc\x01\x50\xb4\x11\xff\x09\x05\x00\xff\xff\xff\xff\xff\xb6') package2_received = bytes(b'\xfd\xba\xdc\x01\x50\xb4\x11\xff\x05\x02\x00\xab\xcd\x8a') # When & Then parser.update(package1_received) assert parser.state == ProtocolState.SFD assert parser.current_request.payload_size == 5 assert parser.current_request.payload == bytes(b'\xff\xff\xff\xff\xff') assert parser.current_request.command_type == CommandType.PerformGestureId assert parser.current_request.received_crc8 == b'\xb6' assert parser.current_request.real_crc8 == b'\xc6' parser.update(package2_received) assert parser.state == ProtocolState.SFD assert parser.current_request.payload_size == 2 assert parser.current_request.payload == bytes(b'\xab\xcd') assert parser.current_request.command_type == CommandType.SetSettings assert parser.current_request.received_crc8 == b'\x8a' assert parser.current_request.real_crc8 == b'\x23'
def test_receive_incorrect_sfd(self): # Given parser = ProtocolParser(MagicMock()) first_received = bytes(b'\x03\x5B\xD5\xD4') second_received = bytes(b'\xff\xfa\xb4') third_received = bytes(b'\x01\x50\xb4\x11\xff') # When parser.update(first_received) parser.update(second_received) parser.update(third_received) # Then assert parser.state == ProtocolState.SFD
def test_receive_type(self): # Given parser = ProtocolParser(MagicMock()) sfd_received = bytes(b'\xfd\xba\xdc\x01\x50\xb4\x11\xff') type_received = bytes(b'\x09') # When parser.update(sfd_received) parser.update(type_received) # Then assert parser.state == ProtocolState.SIZE assert parser.current_request.command_type == CommandType.PerformGestureId
def test_receive_package(self): # Given receiver_mock = MagicMock() parser = ProtocolParser(receiver_mock) sfd_part1_received = bytes(b'\xfd\xba\xdc') sfd_part2_third_received = bytes(b'\x01\x50\xb4\x11\xff') type_info_payload_crc8_received = bytes(b'\x09\x05\x00\xff\xff\xff\xff\xff\xb6') # When parser.update(sfd_part1_received) parser.update(sfd_part2_third_received) parser.update(type_info_payload_crc8_received) # Then assert parser.state == ProtocolState.SFD assert parser.current_request.payload_size == 5 assert parser.current_request.payload == bytes(b'\xff\xff\xff\xff\xff') assert parser.current_request.command_type == CommandType.PerformGestureId assert parser.current_request.received_crc8 == b'\xb6' assert parser.current_request.real_crc8 == b'\xc6' assert receiver_mock.receive_package.call_count == 1
def test_receive_size(self): # Given parser = ProtocolParser(MagicMock()) sfd_received = bytes(b'\xfd\xba\xdc\x01\x50\xb4\x11\xff') type_received = bytes(b'\x09') size_received = bytes(b'\x3b\x01') # When parser.update(sfd_received) parser.update(type_received) parser.update(size_received) # Then assert parser.state == ProtocolState.PAYLOAD assert parser.current_request.payload_size == 315
def test_sfd_receive_correct(self): # Given self._package_receiver_mock = MagicMock() parser = ProtocolParser(self._package_receiver_mock) incorrect_received = bytes(b'\x03\x5B\xD5\xD4') sfd_part1_received = bytes(b'\xfd\xba\xdc') sfd_part2_received = bytes(b'\x01\x50\xb4\x11\xff') # When parser.update(incorrect_received) parser.update(sfd_part1_received) parser.update(sfd_part2_received) # Then assert parser.state == ProtocolState.TYPE
def test_timeout(self): # Given receiver_mock = MagicMock() parser = ProtocolParser(receiver_mock) sfd_received = bytes(b'\xfd\xba\xdc\x01\x50\xb4\x11\xff') before_timeout_received = bytes(b'\x09\x05\x00\xff') package_after_timeout_received = bytes(b'\xfd\xba\xdc\x01\x50\xb4\x11\xff\x09\x05\x00\xff\xff\xff\xff\xff\xb6') # When & Then parser.update(sfd_received) parser.update(before_timeout_received) assert parser.state == ProtocolState.PAYLOAD time.sleep(6) parser.update(package_after_timeout_received) assert parser.state == ProtocolState.SFD assert parser.current_request.payload_size == 5 assert parser.current_request.payload == bytes(b'\xff\xff\xff\xff\xff') assert parser.current_request.command_type == CommandType.PerformGestureId assert parser.current_request.received_crc8 == b'\xb6' assert parser.current_request.real_crc8 == b'\xc6'
class MqttConnector(threading.Thread, IResponseWriter, IPackageReceiver): _logger = logging.getLogger('Main') _mqtt_address: str _is_mqtt_connected: bool _bluetooth_client: BluetoothClient = None _response_mutex = threading.Lock() def __init__(self, config: Config, request_transmitter: 'Queue[Request]'): threading.Thread.__init__(self) self._config = config if not config.mqtt_enabled: self._logger.fatal('Mqtt is disabled but is trying to create') raise Exception('Mqtt is disabled but is trying to create') self._request_transmitter = request_transmitter self._mqtt_address = config.mqtt_address self._is_mqtt_connected = False self._protocol_parser = ProtocolParser(self) @property def connected(self) -> bool: if self._bluetooth_client is not None: return self._bluetooth_client.connected else: return False def run(self): self._logger.info('Mqtt running start') self._bluetooth_client = BluetoothClient(server=self._mqtt_address, data_received_callback=self.data_received_handler, auto_connect=False, power_up_device=True, encoding=None) self._logger.info('Mqtt client created') while True: self._logger.info('Mqtt client try to connect') try: self._bluetooth_client.connect() except OSError as e: self._logger.info(f'Mqtt client connection error: {e}') time.sleep(30) continue except Exception as e: self._logger.exception(e) raise e self._is_mqtt_connected = True self._logger.info('Mqtt client connected') while True: if not self._bluetooth_client.connected: self._logger.info('Mqtt client disconnected') self._is_mqtt_connected = False break self._is_mqtt_connected = False time.sleep(10) def data_received_handler(self, data): self._logger.debug(f'MQTT receive {len(data)} bytes') self._protocol_parser.update(data) def write_response(self, response: Response): self._response_mutex.acquire() payload_length = 0 if response.payload is not None: payload_length = {len(response.payload)} if response.command_type is not CommandType.Telemetry: self._logger.info( f'MQTT try to send response with type {response.command_type} and payload length {payload_length}') package = self._protocol_parser.create_package(response.command_type, response.payload) self.send(self._protocol_parser.serialize_package(package)) self._response_mutex.release() def receive_package(self, package: PackageDto): self._logger.info(f'MQTT receive new package {package.command_type} with size {package.payload_size} bytes') new_request = Request(package.command_type, package.payload, self) self._request_transmitter.put(new_request) def send(self, payload: bytes): if self._bluetooth_client is None: self._logger.critical('MQTT not running, but send invoke') raise ConnectionError('MQTT not running, but send invoke') self._bluetooth_client.send(payload)
class RFCCConnector(threading.Thread, IResponseWriter, IPackageReceiver): _logger = logging.getLogger('Main') _bluetooth_server: BluetoothServer = None _response_mutex = threading.Lock() _count_connected: int def __init__(self, config: Config, request_transmitter: 'Queue[Request]'): threading.Thread.__init__(self) self._config = config if not config.rfcomm_enabled: self._logger.fatal('RFCC is disabled but is trying to create') raise Exception('RFCC is disabled but is trying to create') self._count_connected = 0 self._request_transmitter = request_transmitter self._protocol_parser = ProtocolParser(self) @property def connected(self) -> bool: if self._bluetooth_server is not None: return self._count_connected > 0 else: return False def run(self): self._logger.info('RFCC running start') self._bluetooth_server = BluetoothServer( data_received_callback=self._data_received_handler, auto_start=False, power_up_device=True, encoding=None, when_client_connects=self._client_connect_handler, when_client_disconnects=self._client_disconnect_handler) self._logger.info('RFCC server created') while True: self._logger.info('RFCC server try to start') try: self._bluetooth_server.start() except OSError as e: self._logger.info(f'RFCC server start error: {e}') time.sleep(30) continue except Exception as e: self._logger.exception(e) raise e self._logger.info('RFCC started') break def _client_connect_handler(self): self._logger.info('New device connected') self._count_connected = self._count_connected + 1 def _client_disconnect_handler(self): self._logger.info('Device disconnected') self._count_connected = self._count_connected - 1 if self._count_connected < 0: self._count_connected = 0 def _data_received_handler(self, data): self._logger.debug(f'RFCC receive {len(data)} bytes') self._protocol_parser.update(data) def write_response(self, response: Response): self._response_mutex.acquire() payload_length = 0 if response.payload is not None: payload_length = {len(response.payload)} if response.command_type is not CommandType.Telemetry: self._logger.info( f'RFCC try to send response with type {response.command_type} and payload length {payload_length}' ) package = self._protocol_parser.create_package(response.command_type, response.payload) self.send(self._protocol_parser.serialize_package(package)) self._response_mutex.release() def receive_package(self, package: PackageDto): self._logger.info( f'RFCC receive new package {package.command_type} with size {package.payload_size} bytes' ) new_request = Request(package.command_type, package.payload, self) self._request_transmitter.put(new_request) def send(self, payload: bytes): if self._bluetooth_server is None: self._logger.critical('RFCC not running, but send invoke') raise ConnectionError('RFCC not running, but send invoke') self._bluetooth_server.send(payload)