I wrote a BLE program based on the Bleak third-party library and read bluetooth values in an interface. I failed to terminate the BLE program after I shut down the interface. What is the reason?
I uploaded an animated GIF to illustrate the problem:
The program includes the following: create the UI interface, that the UI interface reads value into the BLE program in the external PY file, and terminate the BLE program smoothly when closing the UI interface.
BLE.py Code:
import numpy as np
import sys
import time
import asyncio
import logging
from bleak import BleakClient
logger = logging.getLogger()
async def run_ble_client(address: str, char_uuid: str, queue: asyncio.Queue):
async def callback_handler(sender, data):
await queue.put((time.time(), data))
async with BleakClient(address) as client:
logger.info(f"Connected: {client.is_connected}")
await client.start_notify(char_uuid, callback_handler)
while True:
await asyncio.sleep(3600.0)
# await client.stop_notify(char_uuid)
# Send an "exit command to the consumer"
await queue.put((time.time(), None))
async def run_queue_consumer(queue: asyncio.Queue):
while True:
# Use await asyncio.wait_for(queue.get(), timeout=1.0) if you want a timeout for getting data.
epoch, data = await queue.get()
if data is None:
logger.info(
"Got message from client about disconnection. Exiting consumer loop..."
)
break
else:
EMG = str(data, "utf-8").split(',')
print(EMG)
print(queue.full())
async def main(address: str, char_uuid: str):
queue = asyncio.Queue()
client_task = run_ble_client(address, char_uuid, queue)
consumer_task = run_queue_consumer(queue)
await asyncio.gather(client_task, consumer_task)
logger.info("Main method done.")
Main Code:
import ble
from PyQt5 import QtCore, QtWidgets
import threading
import EMG_NUM
class UIForm(): # PE8: `CamelNames` for classes
def setupUI(self, form, **kwargs):
form.resize(820, 454)
form.setObjectName("Form")
self.gridLayoutWidget = QtWidgets.QWidget(form)
self.gridLayoutWidget.setGeometry(QtCore.QRect(550, 270, 261, 121))
self.gridLayoutWidget.setObjectName("gridLayoutWidget")
self.gridLayout = QtWidgets.QGridLayout(self.gridLayoutWidget)
self.gridLayout.setContentsMargins(0, 0, 0, 0)
self.gridLayout.setObjectName("gridLayout")
self.retranslateUi(form)
def retranslateUi(self, form):
_translate = QtCore.QCoreApplication.translate
form.setWindowTitle(_translate("Form", "xxxx"))
def main():
app = QtWidgets.QApplication([])
form = QtWidgets.QWidget() # PE8: `lower_case_names` for variables
ui = UIForm()
ui.setupUI(form)
form.show()
app.exec()
if __name__ == "__main__":
# better start before GUI to create all needed variables and values
thread_ble = threading.Thread(target=ble.ble)
thread_ble.start()
# input() # keep running program when GUI runs in thread
main()
thread_ble.join()
I used the thread and could not successfully terminate the thread. Can you tell me how to terminate the thread?
CodePudding user response:
furas Sorry, recently, I have been studying how to improve the throughput of BLE. I didn't notice your comment.
The solution above is to modify the BLE code.
Add a judgment to BLE's main function, as Furas says: Use global running = True
.
Look at the BLE message to check whether it is connected. If it is disconnected, it will jump out. In this way, bluetooth can be safely turned off.
It took a few days to get familiar with the use of the Bleak third-party library to change to the following code. (It's thousands of lines of code, and I'm not going to put it on here. I put a simple example)
Main.py
...
if __name__ == "__main__":
thread_ble = threading.Thread(target=ble.ble)
thread_ble.start()
# input() # keep running program when GUI runs in thread
main()
EMG_NUM.Kill=True
thread_ble.join()
EMG_NUM.py
Kill=False
Connect=False
BLE.py
...
async def main(address: str, char_uuid: str):
async with BleakClient(address) as client:
EMG_NUM.Connect=client.is_connected
...
await client.start_notify(char_uuid, callback_handler)
while EMG_NUM.Connect:
if client.is_connected:
pass1`
else:
EMG_NUM.Connect=False
...
break
if EMG_NUM.Kill:
break
else:
await asyncio.sleep(1.0)
def ble():
while EMG_NUM.Kill == False:
try:
...