deviceplug / btleplug

Rust Cross-Platform Host-Side Bluetooth LE Access Library

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Missing Values For Device Address and TX Power

ztroop opened this issue · comments

Describe the bug
I'm writing a program that uses this library to scan devices. I'm able to scan and detect devices, but I'm getting 00:00:00:00:00:00 for address and None for tx_power_level consistently across 15+ devices.

...
    let manager = Manager::new().await?;
    let adapters = manager.adapters().await?;
    let central = adapters.into_iter().next().ok_or("No adapters found")?;

    central.start_scan(ScanFilter::default()).await?;
    let mut events = central.events().await?;

    let mut devices_info = Vec::new();

    while let Some(event) = events.next().await {
        if let CentralEvent::DeviceDiscovered(id) = event {
            if let Ok(device) = central.peripheral(&id).await {
                let properties = device
                    .properties()
                    .await?
                    .unwrap_or(PeripheralProperties::default());
                let name = properties
                    .local_name
                    .unwrap_or_else(|| "Unknown".to_string());
                let tx_power = properties
                    .tx_power_level
                    .map_or_else(|| "N/A".to_string(), |tx| tx.to_string());
                let address = properties.address.to_string();
                let rssi = properties
                    .rssi
                    .map_or_else(|| "N/A".to_string(), |rssi| rssi.to_string());
...

Expected behavior
Expecting data to be provided by properties.address and properties.tx_power_level.

Actual behavior
Consistent lack of data.

Additional context
Using version 0.11.5.

Is this on Mac OS? Some platforms don't provide this information, in which case there's not much we can do.

Yes, this is a Mac Air (M2). Is there a matrix of what platforms are supported and offer what type of functionality?

Perhaps this is the case for tx_power_level but address should show something other than 00:00:00:00:00:00, as other BTLE libraries are able to retrieve this information. I suspect there might be going on there.

commented

It can't show anything, because CoreBluetooth does not allow access to device addresses.

So I've been experimenting with different versions originally thinking it was a bug. When I downgrade to 0.8, I see the address without issue:

Screenshot 2024-03-03 at 11 08 39 PM

Is this because we're using a different method in the older version to get the address?

So I've been experimenting with different versions originally thinking it was a bug. When I downgrade to 0.8, I see the address without issue:

Screenshot 2024-03-03 at 11 08 39 PM Is this because we're using a different method in the older version to get the `address`?

It appears the address calculation in v0.8 differs from the current method. In v0.8, BDAddr is solely derived from the uuid or PeripheralId, which doesn't correspond to the actual address.

pub(crate) fn uuid_to_bdaddr(uuid: &str) -> BDAddr {
let b: [u8; 6] = uuid.as_bytes()[0..6].try_into().unwrap();
BDAddr::try_from(b).unwrap()
}

I think that's expected though.

The CoreBluetooth APIs in iOS do not give you any direct access to a peripheral's real MAC address; instead, each new peripheral seen is assigned a 128-bit UUID and used to reference that peripheral object permanently. See Reference

Given the lack of a consistent method to retrieve the actual MAC address, is it still possible to access the uuid as in previous versions? After reviewing the code, it remains unclear to me whether this information is still accessible.

I believe for my purposes the uuid would be a satisfactory substitution - even if that would appear different from another scanning device.

In corebluetooth/peripheral.rs:

pub struct Peripheral {
    shared: Arc<Shared>,
}

struct Shared {
    notifications_channel: broadcast::Sender<ValueNotification>,
    manager: Weak<AdapterManager<Peripheral>>,
    uuid: Uuid,
    ...

I think the uuid mentioned in my previous post is found in Shared. However, it's private and not accessible.

PeripheralId is implemented with Display traits on all platforms, and will encase the platform specific identifier for the device, be it BTAddr or UUID. You can use that across platforms for identification.

I'm good with this. Closing.