I am having a strange problem when changing BLE devices that provide the same functionality.
My BLE device pairs and connects fine, and gets data no problem. If I unpair it, I can then discover it, pair, connect and get the data once again.
However, if I unpair it then pair another of the same device - i.e. with the same services & characteristics, etc. then, first of all a call to DeviceInformation.FindAllAsync()
(to return devices with my service) returns no results, and a call to BluetoothLEDevice.GetGattServicesAsync()
hangs and never returns.
The only way I can get it going again, is to go into the TaskManager and kill the process running the "Bluetooth Support Service" (bthserv
). This then restarts automatically and I can then proceed to pair & connect and once again start downloading data.
Here is my code:
int retryCount = 5;
DeviceInformation deviceInfo = null;
// Sometimes Windows loses track of the services! We may need to refresh them - can sometimes take a few retries.
while (deviceInfo == null && retryCount-- > 0)
{
// after switching devices this call usually returns an empty set even though I have successfully paired the second device with the same service.
var allDeviceInfos = await DeviceInformation.FindAllAsync(GattDeviceService.GetDeviceSelectorFromUuid(MyServiceId));
deviceInfo = allDeviceInfos.FirstOrDefault(d => d.Name == device.DeviceInformation.Name);
if (deviceInfo == null)
{
_logger.LogDebug("Device not found! Retrying...");
await RefreshServices();
Thread.Sleep(1000);
}
}
....
private async Task RefreshServices()
{
_logger.LogDebug("Refreshing the device's service list.");
var devices = await DeviceInformation.FindAllAsync(BluetoothLEDevice.GetDeviceSelector());
var myDevices = new List<DeviceInformation>();
foreach (var device in devices.Where(d => d.Name.StartsWith("MyDeviceName_")))
{
var bleDevice = await BluetoothLEDevice.FromIdAsync(device.Id);
// after switching devices, the application hangs on the following line and never returns a value.
var services = await bleDevice.GetGattServicesAsync();
_logger.LogDebug($"Service list from {wristOx.Name}: Status: {services.Status}, count: {services.Services?.Count}");
}
}
You may ask why I'm calling the RefreshServices()
method. This is because I have seen in the past that when I get no results from the intial FindAllAsync()
doing this seems to rectify the situation though sometimes requires several retries. (I'm thinking it's refreshing some sort of cache) If there is a better way of doing this, then that would be great to hear about too!
Notes
GetGattServicesAsync(BluetoothMode.Uncached)
but get the same result.GetGattServicesAsync()
out of its torpor! This is really odd - killing a process "fixes" it, but restarting the computer doesn't!DeviceInformation.FindAllAsync(GattDeviceService.GetDeviceSelectorFromUuid(MyServiceId))
returns 0 devices, the subsequent call to DeviceInformation.FindAllAsync(BluetoothLEDevice.GetDeviceSelector())
returns some devices, including my one!Edit
As requested I've attempted to get the bluetooth logs using WPR and the link provided by Junjie Zhu - MSFT, and I'm taking my time now to go through the 'Generic Events' graph which is the only one with any information in it. However I'm not really sure on how to match up the hang with the events in this graph and there is far too much information to paste it in here.
e.g. I've found this 'Bluetooth' section but narrowing down the right events to look at and interpreting the results is the hard part.
Interestingly though, WPA crashes every time I try to view the RadioDiagnosticTlvVerbose
events... It's an ArgumentOutOfRangeException
Another edit
As requested, here are the logs from WPR. (21MB each)
Failure - this one shows when it fails - i.e. I get 0 devices from DeviceInformation.FindAllAsync(GattDeviceService.GetDeviceSelectorFromUuid(MyServiceId))
then GetGattServicesAsync()
hangs forever.
Success - after killing the "Bluetooth Support Service" (it auto-restarts), in this log, I still got 0 devices from DeviceInformation.FindAllAsync(GattDeviceService.GetDeviceSelectorFromUuid(MyServiceId))
. However, GetGattServicesAsync()
returned a list of services for the device, and after two times through this loop, DeviceInformation.FindAllAsync(GattDeviceService.GetDeviceSelectorFromUuid(MyServiceId))
then finally returns my device and I can connect to it.
Device and new information
BluetoothLEDevice.FromIdAsync(deviceId)
or FromBluetoothAddressAsync
and check the GattServices
property, it lists 1 service. (It's generic service 0x1801). After that GetGattServicesAsync
hangs as previously described. However, when I kill the bthserv
service, and make the same check, it lists 0 services - after that I can call GetGattServicesAsync
and it correctly returns all services on the device without hanging.