deviceplug / btleplug

Rust Cross-Platform Host-Side Bluetooth LE Access Library

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

DeviceConnected doesn't always fire on linux

ratmice opened this issue · comments

Describe the bug
On Linux/bluez sometimes the CentralEvent::DeviceConnected never fires,
It seems like there are cases where it doesn't fire, In additional context i've added the changes I made to event_driven_discovery example.

when handling the DeviceDiscovered event, if is_connected returns true DeviceConnected is never received.

Expected behavior
I would expect that DeviceConnected should be delivered for devices where is_connected returns true

Actual behavior
DeviceConnected is delivered only when is_connected before the call to connect() on the next line

Additional context
I tested this with the below change to examples/event_driven_discovery.rs

            CentralEvent::DeviceDiscovered(id) => {
                println!("DeviceDiscovered: {:?}", id);
                let periph = central.peripheral(&id).await?;
                let connected = periph.is_connected().await?;
                let foo = periph.connect().await?;
                println!("{} {:?} {:?}", connected, foo, periph);
            }

Ran the example twice after remove <device> in bluetoothctl,
The first time the DeviceConnected event fires, and the second time it never arrives.

Tried it on the dev branch.

Thanks for the bug report.

I'm afraid I'm struggling to follow what exactly the issue is. Could you paste the output from your modified event_driven_discovery example, in the case where it works as expected and in the case where you're missing the event?

Sure, here is a shell transcript,

$ bluetoothctl remove A0:CD:B0:6D:40:9B
[CHG] Device A0:CD:B0:6D:40:9B ServicesResolved: no
Device has been removed

$ cargo run --example event_driven_discovery
DeviceDiscovered: PeripheralId(A0:CD:B0:6D:40:9B)
false () Peripheral { session: BluetoothSession, device: DeviceId { object_path: Path("/org/bluez/hci0/dev_A0_CD_B0_6D_40_9B\u{0}") }, mac_address: A0:CD:B0:6D:40:9B, services: Mutex { data: {}, poisoned: false, .. } }
DeviceConnected: PeripheralId(A0:CD:B0:6D:40:9B)

$ cargo run --example event_driven_discovery
DeviceDiscovered: PeripheralId(A0:CD:B0:6D:40:9B)
true () Peripheral { session: BluetoothSession, device: DeviceId { object_path: Path("/org/bluez/hci0/dev_A0_CD_B0_6D_40_9B\u{0}") }, mac_address: A0:CD:B0:6D:40:9B, services: Mutex { data: {}, poisoned: false, .. } }

So, if the device is already connected to bluez before the example is run, you never receive the DeviceConnected event,

Thanks, okay. So you would expect btleplug to generate a DeviceConnected event on startup for every peripheral which is already connected to the adapter?

We already do this for DeviceDiscovered events, so I guess there is some logic to it.

Yeah, I believe that is the least surprising behavior, because e.g. as it is you can receive DeviceDisconnected without having received DeviceConnected etc.

Okay, see if #237 does what you expect.

Indeed it does, thank you.