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