Closed kswann-imb closed 3 years ago
Hmm. I will look into this after the 0.8.0 release. I agree that an example regarding this would be a good idea.
@kswann-imb Hi, I took a look at your code, I am relatively new to asyncio code so I might be wrong.
loop.stop()
from inside the same loop.await client.stop_notify(...)
will be call in case of exception, and since you do call task.cancel() I don't know exactly how this is handled but I guess it make you skip this line (why start a new co-routine if a cancel was requested ?) and get back in stay_connected
and from there you quit without stopping the notification.I rewrote your code but did not try it since I don't have your device. Try it. I hope it will help you.
import asyncio
import signal
from bleak import BleakClient
HEART_RATE_CHARACTERISTIC_UUID = "00002a37-0000-1000-8000-00805f9b34fb" # UUID of heart rate characteristic
ADDRESS = "YOUR BLE ADDRESS"
exit_flag = False
def heart_rate_data_handler(sender, data):
print(str(data)) # Do stuff
class DisconnectionException(Exception):
"""Raised when the device has disconnected."""
class ShutdownException(Exception):
"""Raised when the program should shutdown."""
def ask_exit():
global exit_flag
print("Shutdown Request Received")
exit_flag = True
async def stay_connected(device_address: str, timeout: float = 4.0):
global exit_flag
exit_flag = False
print("Starting Loop")
client = BleakClient(address=device_address, timeout=timeout)
try:
print("Connecting to device.")
await client.connect()
await notify_and_record(client)
except DisconnectionException as e:
print(e)
except ShutdownException as e:
print(e)
except Exception as e:
print(e)
pass
print("Shutting down notification.")
await client.stop_notify(HEART_RATE_CHARACTERISTIC_UUID)
print("Done shutting down notification.")
print("Disconnecting to device.")
await client.disconnect()
print("End of Loop Iteration")
async def notify_and_record(client):
global exit_flag
def disconnect_callback(client, future):
raise DisconnectionException("Client with address {} got disconnected!".format(client.address))
client.set_disconnected_callback(disconnect_callback)
print("Connected: {0}".format(await client.is_connected()))
print("Starting notification.")
await client.start_notify(HEART_RATE_CHARACTERISTIC_UUID, heart_rate_data_handler)
while not exit_flag:
await asyncio.sleep(1)
print("Shutting Down.")
raise ShutdownException
async def run():
print("Attempting to connect to device and start recording.")
await stay_connected(device_address=ADDRESS)
def main():
loop = asyncio.get_event_loop()
for sig in (signal.SIGINT, signal.SIGTERM):
loop.add_signal_handler(sig, ask_exit)
loop.run_until_complete(run())
# I had to manually remove the handlers to
# avoid an exception on BaseEventLoop.__del__
for sig in (signal.SIGINT, signal.SIGTERM):
loop.remove_signal_handler(sig)
loop.stop()
loop.close()
print("Done.")
if __name__ == "__main__":
main()
@GilShoshan94 thanks for taking the time to edit and make those suggestions. I'll give it a try and let you know how it goes!
Have a quick update on this one. I didn't use this solution exactly, but I did use a few of the suggestions including global variables, and not stopping the loop in the routine as described.
There was a couple complications that I thought would be useful to share.
For BLE heart rate monitors, they turn on automatically when they touch the skin, and also turn off automatically after a period of no contact with the skin.
What was happening to me was, the sensor would lose contact with the skin, and after a period of time it would shut off. At that point, it was not possible to shut down notification, because the connection was already closed. This is why I was getting a hang. Similarly, when shutting down with Ctrl+C if the device was already shut off, you also can't disconnect from the client because it's already disconnected. So I had to check these conditions before making those calls in conjunction with the advice above in order to get the desired behaviour.
In hindsight both of these things seem incredibly obvious 🤷
Thanks again for the help!
Will try to incorporate more complex examples when working on #266. Will close this issue in the meantime.
Thanks @hbldh. Overall though great package. I searched for a long time before finding something that worked well for BLE.
@kswann-imb I am having similar issues with my heart rate sensor (Polar H10), would you kindly share your solution with us please?
bluetoothctl -v
) in case of Linux: 5.50Description
I'm trying to write a bleak script that will do the following:
Ctrl+C
What I Did
I can connect to the device without issue and turn on notification, but I'm getting stuck at the shutdown on
Ctrl+C
and the reconnection. In both cases, the program seems to hang when attempting to shutdown notification.I suspect this isn't as much an issue as operator error, but any help would be appreciated. I think this would be a really useful example to add to the examples directory, as many use cases would involve turning on notification and leaving it running and needing reconnects.
Thanks!