Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

prevent re-use of dropped peripheral #378

Open
jcaude opened this issue Mar 28, 2024 · 3 comments
Open

prevent re-use of dropped peripheral #378

jcaude opened this issue Mar 28, 2024 · 3 comments
Labels
bug Something isn't working corebluetooth (macos/ios) Issues related to the MacOS/iOS CoreBluetooth impl

Comments

@jcaude
Copy link
Contributor

jcaude commented Mar 28, 2024

Hello,

I hesitate filling a feature request or a bug. But since it happens with erroneous code I prefer to see it as a FR.

On macOS (not tested on other platforms), the following sequence goes in an infinite waiting loop:

  • 1/ scan
  • 2/ connect to a peripheral
  • 3/ disconnect the peripheral
  • 4/ as if the peripheral is connected <== stuck in an await.

I am fully aware that step 4 is wrong, still it should not await indefinitely (at least panic)

The feature request is:

"could we add a timeout() on the connect(), disconnect() and is_connected() functions or use reference counting at some point."

I hope I make a clear statement.

jC

ps/ as code usually says more:

use std::error::Error;
use std::time::Duration;

use btleplug::api::{Central, Manager as _, Peripheral as _, ScanFilter};
use btleplug::platform::{Adapter, Manager, Peripheral};
use log::info;
use tokio::io::AsyncWriteExt as _;
use tokio::{io, time};

pub async fn bug_is_connected(adapter: &Adapter) -> Result<(), Box<dyn Error>> {
    info!("IS-CONNECTED TEST");
    let mut device: Option<Peripheral> = None;
    // scan
    info!(" 1) Scan");
    adapter
        .start_scan(ScanFilter::default())
        .await
        .expect("Can't scan BLE adapter for connected devices...");
    time::sleep(Duration::from_secs(10)).await;
    // list peripherals
    let peripherals = adapter.peripherals().await?;
    if peripherals.is_empty() {
        eprintln!("->>> BLE peripheral devices were not found, sorry. Exiting...");
    } else {
        // All peripheral devices in range
        for peripheral in peripherals.iter() {
            let properties = peripheral.properties().await?;
            let is_connected = peripheral.is_connected().await?;
            let local_name = properties
                .unwrap()
                .local_name
                .unwrap_or(String::from("(peripheral name unknown)"));
            println!(
                "Peripheral {:?} {:?} is connected: {:?}",
                local_name,
                peripheral.id(),
                is_connected
            );
            io::stdout().flush().await?;
            if local_name.contains("iPhone") {
                device = Some(peripheral.clone());
                break;
            }
        }
    } 
      // connect
    info!(" 2) Connect device");
    if let Some(iphone) = &device {
        iphone.connect().await?;
        let is_connected = iphone.is_connected().await?;
        println!("iPhone is connected: {:?}", is_connected);
    }
    //
    info!(" 3) Disconnect device");
    if let Some(iphone) = &device {
        iphone.disconnect().await?;
    }
    info!(" 4) Check connection status");
    if let Some(iphone) = &device {
        let is_connected = iphone.is_connected().await?; // infinite await here..
        println!("iPhone is connected: {:?}", is_connected);
    } 
    // eop
    Ok(())
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    env_logger::init();
    info!("BtLEPlug Test Code");
    // init.
    let manager = Manager::new().await?;
    let adapter_list = manager.adapters().await?;
    if adapter_list.is_empty() {
        eprintln!("No Bluetooth adapters found");
    }
    let adapter = adapter_list.first().unwrap(); // we have at least one ..

    // TEST 1
    bug_is_connected(&adapter).await?;

    // eop
    Ok(())
}
@jcaude
Copy link
Contributor Author

jcaude commented Mar 28, 2024

Besides, I will give a look on how we can prevent this from happening and I will you about it.

@qdot
Copy link
Contributor

qdot commented Mar 28, 2024

This is definitely a bug. is_connected() should return pretty much immediately, so there's something in our background executor that's having a problem.

@qdot qdot added bug Something isn't working corebluetooth (macos/ios) Issues related to the MacOS/iOS CoreBluetooth impl labels Mar 28, 2024
@jcaude
Copy link
Contributor Author

jcaude commented Mar 28, 2024

I agree on the bug thing.. here some feedback on the possible issue:

INFO  btleplug_hunting]  3) Disconnect device
TRACE btleplug::corebluetooth::internal] Adapter message!
TRACE btleplug::corebluetooth::internal] Trying to disconnect peripheral!
TRACE btleplug::corebluetooth::internal] Disconnecting peripheral!
TRACE btleplug::corebluetooth::central_delegate::CentralDelegate] delegate_centralmanager_diddisconnectperipheral_error CBPeripheral(iPhone, XXXXX)
TRACE btleplug::corebluetooth::internal] Got disconnect event!
INFO  btleplug::corebluetooth::peripheral] Event receiver died, breaking out of corebluetooth device loop.
TRACE btleplug::common::adapter_manager] Lost central event, while nothing subscribed: SendError(DeviceDisconnected(PeripheralId(XXXXX)))
TRACE btleplug::common::adapter_manager] Lost central event, while nothing subscribed: SendError(DeviceDisconnected(PeripheralId(XXXXX)))
TRACE btleplug::corebluetooth::peripheral] Device disconnected!
INFO  btleplug_hunting]  4) Check connection status

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working corebluetooth (macos/ios) Issues related to the MacOS/iOS CoreBluetooth impl
Projects
None yet
Development

No branches or pull requests

2 participants