question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

client.set_disconnected_callback - callback does not appear to fire on disconnect

See original GitHub issue
  • bleak version: 0.8.0
  • Python version: 3.8.5
  • Operating System: Windows 10 2004, build 19041.508

Description

After connecting to a device, I am trying to set up a callback so that I am alerted if/when the device disappears (for instance if it wanders out of range, or waiting for confirmation of disconnect after await client.disconnect().

However, while the device definitely disconnects (be it through range, or being turned off, or await client.disconnect()) the callback never runs and no errors are produced either.

I’m not entirely sure if I’m doing this right!

What I Did

For the purpose of testing, I put these two methods together in the class I’m implementing for BLE stuff; __callback_test() is fed the target MAC address and then connects to the device, sets a disconnected_callback, pokes the GATT, then disconnects.

    def __disconnect_callback(self):
        # fires when a device is disconnected
        print("Disconnect callback...")

    async def __callback_test(self, mac):
        print("Connecting to mac: {0}".format(mac), flush=True)
        client = BleakClient(mac)
        await client.connect()
        # try to set a callback
        client.set_disconnected_callback(self.__disconnect_callback)
        # do something with the connection, blah blah 
        print("Poking services...".format(mac), flush=True)
        await client.get_services()
        # now disconnect        
        print("Trying disconnect...".format(mac), flush=True)
        await client.disconnect()

Elsewhere in the class is the code to initiate the test:

                mac = "[MAC address here]"
                loop = asyncio.get_event_loop()
                loop.run_until_complete(self.__callback_test(mac))

The console output is as below; the device shows a connection formed, then a few seconds later, disconnected, but the callback doesn’t appear to run from the console output. As stated before there is no error and the program is still running after this:

Connecting to mac: [MAC address here]
Poking services...
Trying disconnect...

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:6 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
NbrTDBcommented, Sep 25, 2020

Thanks for all the advice, I really appreciate it!

I’ve found a way around the need for await asyncio.sleep(); in short I just don’t understand asyncio enough yet; the loop in my BLE handler that was listening for stdin was blocking…

I’ve changed things around such that the class has a singular event loop:

def start(self):
        self.loop = asyncio.get_event_loop()
        self.loop.run_until_complete(self.__loop()) 

This makes the message handler (which is now async) much cleaner:

    async def __stdin_msg_handler(self, inp):
        # read the input command and respond accordingly
        print("Received:", inp, flush=True)
        if(len(inp) > 0):
            # convert from JSON
            msg = json.loads(inp[0])
            if(msg["cmd"] == "a"):
                self.__hello()
            if(msg["cmd"] == "b"):
                await self.__find_devices()
            if(msg["cmd"] == "c"):
                mac = msg["mac"]
                await self.__connect_device(mac)         
            if(msg["cmd"] == "d"):
                mac = msg["mac"]
                await self.__disconnect_device(mac)         
           ...etc

And as for getting input from stdin:

line = await self.loop.run_in_executor(None, sys.stdin.readline)

With these tweaks I don’t need asyncio.sleep() and the disconnect callback fires as expected.

0reactions
hbldhcommented, Sep 25, 2020

Very good!

No, unbinding is not possible in Windows right now, due to several reasons. You should discard the client between uses and set up a new one each time to avoid it.

Read more comments on GitHub >

github_iconTop Results From Across the Web

connectedCallback/disconnectedCallback not firing on 2nd ...
For first case (Standard Action Override (new)), where just disconnected callback run on second redirect to that target, fix was easy.
Read more >
[idea] childConnectedCallback and childDisconnectedCallback
This has the side-effect that by the time connectedCallback is fired that the custom element may already have had children added to it, ......
Read more >
Using custom elements - Web Components | MDN
isConnected to make sure. disconnectedCallback : Invoked each time the custom element is disconnected from the document's DOM. adoptedCallback : ...
Read more >
socket.io client - emit callback does not fire if no connection or ...
I am trying to add some verifications client side, to be sure the message was correctly sent to the server. If the server...
Read more >
Run Code When a Component Is Inserted or Removed from ...
The disconnectedCallback() lifecycle hook fires when a component is removed from the DOM. Both hooks flow from parent to child. You can't access...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found