abinop
abinop

Reputation: 3183

device.GattServices returns an empty set for BLE devices on a Windows universal app

I am using the sample from Microsoft. When an advertisement is received I am calling

BluetoothLEDevice device = await BluetoothLEDevice.FromBluetoothAddressAsync(eventArgs.BluetoothAddress);

and then

device.GattServices()

but that always returns an empty list. Why is this happening? I have found no answer whatsoever.

Upvotes: 0

Views: 635

Answers (2)

GrooverFromHolland
GrooverFromHolland

Reputation: 1029

I wanted to put more explanation in my comment, but something went wrong and cannot edit my comment so I will add it as an answer. I had exactly the same problem. for some reason you have to initialize your BLEdevice as null.

private BluetoothLEDevice device = null;

Also to prevent that you advertisementWatcher is setting your device over and over, use an if statement to set it only when the divice is null,

 if (device == null)
 {
    device = await BluetoothLEDevice.FromBluetoothAddressAsync(eventArgs.BluetoothAddress);
 }  

or if you want to set multiple devices than add them to a collection and make sure each device is only added once.

This is my working code :

  private async void OnAdvertisementReceived(BluetoothLEAdvertisementWatcher watcher,
                                            BluetoothLEAdvertisementReceivedEventArgs eventArgs)
  {
     BluetoothLEAdvertisementType advertisementType = eventArgs.AdvertisementType;
     short rssi = eventArgs.RawSignalStrengthInDBm;
     string localName = eventArgs.Advertisement.LocalName;
     string manufacturerDataString = "";
     var manufacturerSections = eventArgs.Advertisement.ManufacturerData;
     if (manufacturerSections.Count > 0)
     {
        // Only print the first one of the list
        var manufacturerData = manufacturerSections[0];
        var data = new byte[manufacturerData.Data.Length];
        using (var reader = DataReader.FromBuffer(manufacturerData.Data))
        {
           reader.ReadBytes(data);
        }
        manufacturerDataString = string.Format("0x{0}: {1}",
        manufacturerData.CompanyId.ToString("X"),
        BitConverter.ToString(data));
     }
     string res = string.Format("type={0}, rssi={1}, name={2}, manufacturerData=[{3}]",
            advertisementType.ToString(),
            rssi.ToString(),
            localName,
            manufacturerDataString);
     await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
     {
        textBoxWatcher.Text = res;
     });
     if (device == null)
     {
        device = await BluetoothLEDevice.FromBluetoothAddressAsync(eventArgs.BluetoothAddress);

        if (device != null)
        {
           var deviceInfo = device.DeviceInformation;
           await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
           {
              if (device.Name != string.Empty)
              {
                 //ResultCollection is a observable observable collection of blueutooth devices
                 // to bind to a listvieuw,it is not needed!
                 ResultCollection.Add(new BleDevice(device));
                 if (deviceInfo.Name == "HMSoft")
                 {
                    if (ResultCollection[0] is BleDevice bleDevice)
                    {
                       BleDeviceId = bleDevice.Id;
                       SelectedBleDeviceName = bleDevice.Name;
                    }                        
                    Connect();
                 }
              }
           });
        }
     }

Upvotes: 0

GrooverFromHolland
GrooverFromHolland

Reputation: 1029

If you want this to work by using advertisement watcher, you need to target the windows 10 creators update(10.0;Build 15063) and use the latest SDK, otherwise you will have to pair the device first. To get the GattServices, first check if the device is not null. Then use:

var serviceResult = await bluetoothLeDevice.GetGattServicesAsync();
if (serviceResult.Status == GattCommunicationStatus.Success)
{
//Do something with servivicResult list
}

But there is a catch; It can be that serviceResult.Status returns success, but not all or no services have been found yet. My solution is to put it in a loop with a short delay and try it a few times until serviceResult count stays the same.

Upvotes: 1

Related Questions