Home > Mobile >  How do I safely terminate the external PY program and free temporary resources?
How do I safely terminate the external PY program and free temporary resources?

Time:04-04

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:

Can't shutdown Ble program

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:
            ...
  • Related