0

I have a small Python application that uses a ttkbootstrap GUI and connects to a BLE service via Bleak. Since the ttkbootstrap GUI runs in an endless loop, I have separated the operation into it's own thread. I am attempting to disconnect the Bluetooth connection upon closing the window - the connection is successfully broken, however the program hangs for ~2min until I receive the following timeout error message:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Python310\lib\site-packages\bleak\backends\winrt\client.py", line 498, in disconnect
    await event.wait()
  File "C:\Python310\lib\asyncio\locks.py", line 213, in wait
    await fut
  File "C:\Python310\lib\asyncio\futures.py", line 284, in __await__
    yield self  # This tells Task to wait for completion.
  File "C:\Python310\lib\asyncio\tasks.py", line 304, in __wakeup
    future.result()
  File "C:\Python310\lib\asyncio\futures.py", line 196, in result
    raise exc
asyncio.exceptions.CancelledError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Python310\lib\tkinter\__init__.py", line 1921, in __call__
    return self.func(*args)
  File "C:\Users\coope\Desktop\scorem8\client\test.py", line 17, in <lambda>
    root.protocol("WM_DELETE_WINDOW", lambda: on_closing(root))
  File "C:\Users\coope\Desktop\scorem8\client\test.py", line 9, in on_closing
    bluetooth_connection.disconnect()
  File "C:\Users\coope\Desktop\scorem8\client\blue.py", line 16, in disconnect
    asyncio.run(disconnect(self.client))
  File "C:\Python310\lib\site-packages\nest_asyncio.py", line 31, in run
    return loop.run_until_complete(task)
  File "C:\Python310\lib\site-packages\nest_asyncio.py", line 99, in run_until_complete
    return f.result()
  File "C:\Python310\lib\asyncio\futures.py", line 201, in result
    raise self._exception
  File "C:\Python310\lib\asyncio\tasks.py", line 234, in __step
    result = coro.throw(exc)
  File "C:\Users\coope\Desktop\scorem8\client\blue.py", line 19, in disconnect
    await client.disconnect()
  File "C:\Python310\lib\site-packages\bleak\__init__.py", line 540, in disconnect
    return await self._backend.disconnect()
  File "C:\Python310\lib\site-packages\bleak\backends\winrt\client.py", line 497, in disconnect
    async with async_timeout(120):
  File "C:\Python310\lib\site-packages\async_timeout\__init__.py", line 129, in __aexit__
    self._do_exit(exc_type)
  File "C:\Python310\lib\site-packages\async_timeout\__init__.py", line 212, in _do_exit
    raise asyncio.TimeoutError
asyncio.exceptions.TimeoutError

How can I prevent this error from occurring?

main.py

import blue
import ttkbootstrap as ttk
from ttkbootstrap.constants import *
from threading import Thread

def on_closing(root): # add bluetooth disconnect
    root.destroy()
    if "bluetooth_connection" in globals():
        bluetooth_connection.disconnect()

def setBluetoothConnection(value):
    global bluetooth_connection
    bluetooth_connection = value

def window():
    root = ttk.Window(themename="superhero", size=(1000,500))
    root.protocol("WM_DELETE_WINDOW", lambda: on_closing(root))
    root.mainloop()

def setup_bluetooth():
    while True:
        try:
            setBluetoothConnection(blue.Connection())
            break
        except:
            continue

if __name__ == '__main__':
    thread_gui = Thread(target=window)
    thread_gui.start()
    setup_bluetooth()

blue.py

import asyncio
from bleak import BleakScanner, BleakClient
import nest_asyncio
nest_asyncio.apply()

characteristic_uuid = "UUID"

class Connection():
    def __init__(self):
        self.client = asyncio.run(run())
    
    def send(self, command):
        asyncio.run(send(self.client, command))
    
    def disconnect(self):
        asyncio.run(disconnect(self.client))

async def disconnect(client):
    await client.disconnect()

async def getAddress():
    devices = await BleakScanner.discover()
    for d in devices:
        if d.name and "Scoreboard" in d.name:
            return d.address

async def connect_to_device(address):
    client = BleakClient(address)
    await client.connect()
    return client

async def send(client, command):
    data_to_send = command.encode()
    await client.write_gatt_char(characteristic_uuid, data_to_send, response=False)

async def run():
    address = await getAddress()
    if address:
        client = await connect_to_device(address)
        return client
CoopDaddio
  • 577
  • 1
  • 5
  • 20

0 Answers0