Repository navigation
can not find device already connect to computer #259
Description
Activity
My test code
let manager = Manager::new().await.unwrap(); let adapter_list = manager.adapters().await.unwrap(); println!("adapter len === {}", adapter_list.len()); let central = manager .adapters() .await .expect("Unable to fetch adapter list.") .into_iter() .nth(0) .expect("Unable to find adapters."); let mut events = central.events().await.unwrap(); central.start_scan(ScanFilter::default()).await.unwrap(); loop { tokio::time::sleep(Duration::from_secs(2)).await; for p in central.peripherals().await.unwrap() { println!("{:?}",p.properties().await.unwrap().unwrap().local_name); if p.properties() .await .unwrap() .unwrap() .local_name .iter() .any(|name| name.contains("RY KB3 5.0")) { println!("FFFFIIIIINNNNNNNDDDDDDDDD"); } } }Does the keyboard still work as an actual keyboard? Is it bonded to your system? If so, this may be the operating system picking it up in the HID manager before anything else can get to it.
Does the keyboard still work as an actual keyboard? Is it bonded to your system? If so, this may be the operating system picking it up in the HID manager before anything else can get to it.
yes.keyboard work as an actual keyboard. but I can find the device use "Blue Tooth Le Explorer" OR in Chrome use the code below
navigator.bluetooth.requestDevice({
acceptAllDevices: true,
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });I'm also getting this issue on win10. If the device is already paired/connected, enumerating the peripherals on an adapter will only yield BT devices that are available for pairing but not yet connected. It seems silly to have to remove/unpair the device and then put it back in pairing mode and let btleplug do a scan, find the device and connect, instead of just being able to find an existing connection.
It may be, as you say, the OS picking up the HID manager before anything else can get to it but I have a similar C# based set of code that is able to connect to existing BT connections on the same device, and in theory, it should be using the same win dlls that the windows crate dependency is using.
From the btleplug discord channel, recording here just in case a PR doesn't come in:
Ok, I think I got something that will work. If you used a
Windows::Devices::Enumeration::DeviceInformation::CreateWatcherWithKindAqsFilterAndAdditionalProperties()
with the hand written aql selector that fetches all BT LE protocol devices and pass None to the additional properties (since we can't create the necessary collection in rust) and provide the "kind" of AssociationEndpoint, we get a watcher than shows both connected and not connected advertising devices.As I said above, the thing it sends to the handlers is a more generic DeviceInformation type that doesn't have any BT related information, like connections status, bt address, etc.. instead of the BluetoothLEAdvertisementReceivedEventArgs you are currently getting from the advertisement watcher. However, that doesn't matter at all as I now see you weren't getting anything useful from those args except the bluetooth_address and then using that to get a windows::Devices::Bluetooth::BluetoothLEDevice from BluetoothLEDevice.FromBluetoothAddressAsync() that you wrap in the BLEDevice struct. Luckily, one thing the DeviceInformation does have is an ID and BluetoothLEDevice also has a BluetoothLEDevice::FromIdAsync() .
So I think it would only take swapping the watcher, updating the handler types, and changing BLEDevice struct's new() to instead take the deviceId instead of BDaddr, then getting the BluetoothLEDevice from BluetoothLEDevice::FromIdAsync() instead and everything else should work exactly as it did with the other watcher.
The same problem =(
(Mac, Ventura 13.3)I have a similar issue with Windows and Android, but not on Linux. On Linux, it sees the devices that are already connected/paired/bonded.
I wrote a simple C# script and it's able to get the paired devices and connect to them, but for the Rust code based on btleplug if the device is paired to the system it will never see it unless unpaired.
using System; using System.Threading.Tasks; using Windows.Devices.Bluetooth; using Windows.Devices.Bluetooth.GenericAttributeProfile; using Windows.Devices.Enumeration; class Program { static async Task Main(string[] args) { Console.WriteLine("Listing Connected Bluetooth LE Devices:"); try { var bluetoothLeDeviceSelector = BluetoothLEDevice.GetDeviceSelector(); var devices = await DeviceInformation.FindAllAsync(bluetoothLeDeviceSelector); foreach (var device in devices) { try { Console.WriteLine($"Trying to get a Device with Id: {device.Id}"); // Create BluetoothLEDevice instance from device ID var bluetoothDevice = await BluetoothLEDevice.FromIdAsync(device.Id); if (bluetoothDevice != null) { // Check if the device is connected if (bluetoothDevice.ConnectionStatus == BluetoothConnectionStatus.Connected) { Console.WriteLine($"Device Name: {device.Name}"); Console.WriteLine($"Device Id: {device.Id}"); Console.WriteLine($"Device Kind: {device.Kind}"); Console.WriteLine(); } else { Console.WriteLine($"Device with Id {device.Id} is not connected!"); bool isConnected = false; while (!isConnected) { try { // Try to access a service (you'll need to know the service GUID) var serviceResult = await bluetoothDevice.GetGattServicesAsync(BluetoothCacheMode.Uncached); if (serviceResult.Status == GattCommunicationStatus.Success) { Console.WriteLine($"Successfully connected to device {device.Name} by accessing its services."); Console.WriteLine($"Device Name: {device.Name}"); Console.WriteLine($"Device Id: {device.Id}"); Console.WriteLine($"Device Kind: {device.Kind}"); Console.WriteLine(); isConnected = true; // Exit loop } else { Console.WriteLine($"Failed to connect to the device {device.Name}. Retrying in 2 seconds..."); } } catch (Exception ex) { Console.WriteLine($"Exception while trying to connect to {device.Name}: {ex.Message}"); } if (!isConnected) { // Wait for 2 seconds before retrying Thread.Sleep(2000); } } } } else { Console.WriteLine($"Failed to get the device with Id: {device.Id}"); } } catch (Exception ex) { // Handle device-specific exceptions Console.WriteLine($"Error processing device {device.Name}: {ex.Message}"); } } } catch (Exception ex) { Console.WriteLine($"An error occurred: {ex.Message}"); } Console.WriteLine("Press any key to exit..."); Console.ReadKey(); } }
My colleague also wrote a similar test using Java and it works on Android, similar to Windows btleplug only sees the devices when unpaired.
For what it's worth I've had a fork for a while which finds already connected devices on Mac and Windows. I haven't had time to clean it up and make a PR, and the API is therefore pretty awkward to use. Perhaps someone else will be able to take this and make something useful with it, or perhaps I'll have time down the line to do the right thing and get it in a state for everyone to use. https://github.com/challiwill/btleplug
I think with some recent changes corebluetooth is not working anymore, so maybe that will let me revisit this and do some cleanup on it.
Would love to get connected devices working with the library, the systems I use also need that. Just that perpetual issue of never having time to work on this part of the system, heh.
Reacted by Corbin@qdot I started taking a look and turns out my branch hadn't deviated from master as much as I thought. I've started porting it over and opened a draft PR here: #437.
Let me know if this API seems okay. I don't have a Windows computer with me today so I have to wait for next week to tackle that side of things. From this comment it seems Linux works already, but I don't have a machine I can test on. I also don't have an Android phone so I won't be able to build for that right now. How do you feel about implementations across only a subset of OS's?
@qdot okay I have the Windows changes on the PR now as well. Unfortunately I am fairly new to Rust, so I think there are some awkward constructions in it, but I think it gets the job done. I'm very happy to clean anything up if you have suggestions as well.
This was generated by AI during triage.
Closing this issue because connected-device retrieval is now supported through the public retrieval and address-based APIs. Applications should use
retrieve_peripheralsoradd_peripheralrather than expecting a normal scan to rediscover devices that are already connected or known to the operating system.
Describe the bug
I have a keyboard that communicates through GATT. When he is not linked to the computer, it can be searched normally, but when it is linked to the computer, it cannot be found. But I can find the device normally (whether it is already connected to the computer or not) using "Bluetooth LE Explorer".
Expected behavior
device can be find normal
Actual behavior
can not find device when it connect to computer
I test both on Windows 10 and Mac 11.6.4