def run()

in src/ble/ble_uart_peripheral.py [0:0]


    def run(self):
        # Note: Bluepy is not thread safe so can't run Rx loop in a seperate thread. Need to Rx and Tx sequentially.
        # Also can't safely poll connection state during read / write operations
        # Have set Rx timeout low (0.1 secs) to avoid long delays.

        # Initilie the BLE Peripheral connection. 
        log.info('Rx/Tx thread started for BLE Device: {}, initilising connection.....'.format(self.ble_mac))
        self._ble_init_connect()

        while self.thread_running:

            try:

                #############################################
                ## Transmit BLE messages
                while not self._tx_queue.empty() and self.thread_running:

                    # Parse and send messages in queue
                    tx_object = self._tx_queue.get_nowait()
                    with_ble_response = tx_object['with_ble_response']
                    message_object = tx_object['message_object']

                    log.info('Publishing To BLE MAC: {} - tx_object: {}'.format(self.ble_mac, tx_object))
                    json_message = json.dumps(message_object) + '\n'
                    payload_bytes = bytes(json_message.encode('utf-8'))
                    self._uart_rx.write(payload_bytes, with_ble_response)

                #############################################
                ## Receive BLE messages - handled by BleUartDelegate (callbacks)
                if self.thread_running:
                    self._ble_peripheral.waitForNotifications(0.1)

            #############################################
            ## Catch Rx/Tx exceptions, mostly expected due to lost BLE connection.
            except Exception as err:
                # If thread still running, attempt to re-initilise the BLE device connection
                if (self.thread_running):
                    log.error('BLE Mac {} error: {} - attempting to reconnect.'.format(self.ble_mac, err))
                    
                    # Give time for the BLE device to disconnect and start re-advertsing beacon 
                    # also prevents fast exceptions loops when device is not reachable.
                    self._disconect_ble()
                    time.sleep(5)

                    # Attempt to reconnect.
                    self._ble_init_connect()

        # Clear the BLE connection if leaving the running thread.
        self._disconect_ble()
        log.info('Exiting the BLE Peripheral Rx/Tx process loop for BLE Mac: {}'.format(self.ble_mac))