btleplug
btleplug copied to clipboard
prevent re-use of dropped peripheral
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(())
}
Besides, I will give a look on how we can prevent this from happening and I will you about it.
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.
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