I am communicating with the Nordic nRF52840DK device using the Bleak code example uart_service and the Nordic code example Nordic UART Service (NUS). I modified the bleak uart_service code a bit: integrated PyQt6 to create a GUI for displaying sensor data from the nRF52840DK, and also changed the code from nordic.
What I Did
Initially, I developed a functional version of the code that worked fine. However, when I encapsulated the code in a class, the code behaved strangely. The class code successfully establishes a connection with the Nordic nRF52840DK, but it disconnects after some seconds. On the Nordic nRF52840DK side I get an error BLE errror 19 (hex 0x13), which means that the remote device has forced a disconnection. This means that Bleak has cut the connection.
On The python console I get this error:
Can someone explain me why is happening? Thanks
Below is the python code:
import sys
import asyncio
from threading import Thread, Event
from bleak import BleakClient, BleakScanner
from bleak.backends.characteristic import BleakGATTCharacteristic
from bleak.backends.device import BLEDevice
from bleak.backends.scanner import AdvertisementData
from PyQt6.QtWidgets import QApplication, QGridLayout, QLabel, QPushButton, QWidget
import pyqtgraph as pg # type: ignore
from pglive.sources.data_connector import DataConnector
from pglive.sources.live_plot import LiveLinePlot
from pglive.sources.live_plot_widget import LivePlotWidget
UART_SERVICE_UUID = "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"
UART_TX_CHAR_UUID = "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
UART_RX_CHAR_UUID = "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
async def uart_terminal(connector_x, connector_y, connector_z, label, event_start, event_stop):
loop_continue = True
def match_nus_uuid(device: BLEDevice, adv: AdvertisementData):
if UART_SERVICE_UUID.lower() in adv.service_uuids:
return True
return False
device = await BleakScanner.find_device_by_filter(match_nus_uuid)
if device is None:
print("no matching device found, you may need to edit match_nus_uuid().")
sys.exit(1)
def handle_disconnect(_: BleakClient):
print("Device was disconnected, goodbye.")
# cancelling all tasks effectively ends the program
loop_continue = False
label.setText("BLE: Disconnected")
for task in asyncio.all_tasks():
task.cancel()
def handle_rx(_: BleakGATTCharacteristic, data_l: bytearray):
rtext = data_l.decode('utf-8') # receive data here
values = [float(i) for i in rtext.split(',')]
connector_x.cb_append_data_point(values[1], values[0] / 1000)
connector_y.cb_append_data_point(values[2], values[0] / 1000)
connector_z.cb_append_data_point(values[3], values[0] / 1000)
async with BleakClient(device, disconnected_callback=handle_disconnect) as client:
await client.start_notify(UART_TX_CHAR_UUID, handle_rx)
label.setText("BLE: Connected")
nus = client.services.get_service(UART_SERVICE_UUID)
rx_char = nus.get_characteristic(UART_RX_CHAR_UUID)
await asyncio.sleep(0.5)
await client.write_gatt_char(rx_char, "1", response=False)
while loop_continue:
if event_stop.is_set():
await client.write_gatt_char(rx_char, b"0\r\n")
print("stop")
connector_x.clear()
connector_y.clear()
connector_z.clear()
event_stop.clear()
elif event_start.is_set():
await client.write_gatt_char(rx_char, b"1\r\n")
print("start")
event_start.clear()
await asyncio.sleep(0.5)
label.setText("BLE: not connected")
await asyncio.sleep(2)
def bleak_process(connector_x, connector_y, connector_z, event_start, event_stop, label):
try:
asyncio.run(uart_terminal(connector_x, connector_y,
connector_z, label,
event_start, event_stop))
except asyncio.CancelledError:
# task is cancelled on disconnect, so we ignore this error
pass
class qt_app:
def __init__(self):
self.event_start = Event()
self.event_stop = Event()
self.app = QApplication(sys.argv)
# Create parent widget
self.parent_widget = QWidget()
parent_layout = QGridLayout()
self.parent_widget.setLayout(parent_layout)
plot_widget = LivePlotWidget(title="Line Plot ")
plot_curve_x = LiveLinePlot(pen="red")
plot_curve_y = LiveLinePlot(pen="green")
plot_curve_z = LiveLinePlot(pen="blue")
plot_widget.addItem(plot_curve_x)
plot_widget.addItem(plot_curve_y)
plot_widget.addItem(plot_curve_z)
self.ch_status_value = QLabel("BLE: not connected")
connect_button = QPushButton("connect")
start_button = QPushButton("start")
stop_button = QPushButton("stop")
parent_layout.addWidget(plot_widget, 0, 0, 1, 2)
parent_layout.addWidget(connect_button, 1, 0)
parent_layout.addWidget(self.ch_status_value, 1, 1)
parent_layout.addWidget(start_button, 2, 0)
parent_layout.addWidget(stop_button, 2, 1)
# Connect signals with respective methods
connect_button.clicked.connect(self.start_thread)
start_button.clicked.connect(self.start)
stop_button.clicked.connect(self.stop)
TIME_IN_S = 180
SAMPLE_RATE = 200
POINTS_SIZE = TIME_IN_S * SAMPLE_RATE
self.data_connector_x = DataConnector(plot_curve_x, max_points=POINTS_SIZE, update_rate=200)
self.data_connector_y = DataConnector(plot_curve_y, max_points=POINTS_SIZE, update_rate=200)
self.data_connector_z = DataConnector(plot_curve_z, max_points=POINTS_SIZE, update_rate=200)
def stop(self):
self.event_stop.set()
def start(self):
self.event_start.set()
def start_thread(self):
self.ch_status_value.setText("BLE: Connecting.")
Thread(target=bleak_process,
args=(self.data_connector_x, self.data_connector_y, self.data_connector_z, self.event_start,
self.event_stop, self.ch_status_value)).start()
def run(self):
self.parent_widget.show()
self.app.exec()
if __name__ == "__main__":
gui = qt_app()
gui.run()
Description
I am communicating with the Nordic nRF52840DK device using the Bleak code example uart_service and the Nordic code example Nordic UART Service (NUS). I modified the bleak uart_service code a bit: integrated PyQt6 to create a GUI for displaying sensor data from the nRF52840DK, and also changed the code from nordic.
What I Did
Initially, I developed a functional version of the code that worked fine. However, when I encapsulated the code in a class, the code behaved strangely. The class code successfully establishes a connection with the Nordic nRF52840DK, but it disconnects after some seconds. On the Nordic nRF52840DK side I get an error BLE errror 19 (hex 0x13), which means that the remote device has forced a disconnection. This means that Bleak has cut the connection.
On The python console I get this error:
Can someone explain me why is happening? Thanks
Below is the python code: