Windows 10 Bluetooth Low Energy Connection c#

6

For a project I need to get some data from a Bluetooth device on windows 10 using C#. I'm not too familiar with the Bluetooth API and can't figure out why the following is not working:

Using the BluetoothLEAdvertisementWatcher I search for advertisements, which works fine. I do receive the advertisement from the device (local name fits) as well as it's ServiceUuids. Next I try to connect to the device using the BluetoothAddress received together with the advertisement:

private async void OnAdvertisementReceived(BluetoothLEAdvertisementWatcher watcher, 
                    BluetoothLEAdvertisementReceivedEventArgs eventArgs)
{
    ulong blAdress = eventArgs.BluetoothAddress;
    BluetoothLEDevice blDevice = await 
         Windows.Devices.Bluetooth.BluetoothLEDevice.FromBluetoothAddressAsync(blAdress);
}

However, doing so results in an exception:

Element not found. (Exception from HRESULT: 0x80070490).

Is this the correct way to read data from the device? Are other options available to read the data from the services? Manually pairing the device in windows is not really an option and also seems to fail.

/Edit 1: I check for the local name of the device to make sure I only try to connect to the right one. So I guess there is a problem with connecting to this specific device, still I have no idea how to work around that. The service data was succesfully read on iOS, so it should be possible.

c#
windows
bluetooth
bluetooth-lowenergy
windows-10
asked on Stack Overflow Oct 1, 2015 by Stoffel • edited Oct 2, 2015 by Stoffel

6 Answers

3

Until MS fixes this problem the only reliable solution to this I have found to connect to a BLE device is to ask the registry for a list of paired BLE devices and compare the bluetooth address in the advert with with registry list of paired able devices. My experience is that when FromBluetoothAddressAsync is called on an unpaired device Windows throws an exception and kills the watcher thread. I have some C++ code that I am happy to share that reads the registry and creates a list of paired BLE devices.

Hopefully MS will take the time to fully support BLE in the same manner Apple does.

answered on Stack Overflow Nov 3, 2015 by oregonduckman
2

Here is a reference from MS (https://social.msdn.microsoft.com/Forums/vstudio/en-US/e321cb3c-462a-4b16-b7e4-febdb3d0c7d6/windows-10-pairing-a-ble-device-from-code?forum=wdk). It seems that to use this BluetoothLEDevice.FromBluetoothAddressAsync we have to handle the exception when the device is advertising and not yet paired.

answered on Stack Overflow Nov 3, 2015 by oregonduckman
1

I got the same issue when I using the BluetoothLEAdvertisementWatcher directly.

Then I tested the different addresses listed by the watcher. I found it is related to the Bluetooth devices.

After adding the filter as following, I can connect to GATT device (TI Sensor Tag) successfully.

public sealed partial class MainPage : Page
{
    private BluetoothLEAdvertisementWatcher watcher;

    public MainPage()
    {
        this.InitializeComponent();

        // Create and initialize a new watcher instance.
        watcher = new BluetoothLEAdvertisementWatcher();

        // Part 1B: Configuring the signal strength filter for proximity scenarios

        // Configure the signal strength filter to only propagate events when in-range
        // Please adjust these values if you cannot receive any advertisement 
        // Set the in-range threshold to -70dBm. This means advertisements with RSSI >= -70dBm 
        // will start to be considered "in-range".
        watcher.SignalStrengthFilter.InRangeThresholdInDBm = -70;

        // Set the out-of-range threshold to -75dBm (give some buffer). Used in conjunction with OutOfRangeTimeout
        // to determine when an advertisement is no longer considered "in-range"
        watcher.SignalStrengthFilter.OutOfRangeThresholdInDBm = -75;

        // Set the out-of-range timeout to be 2 seconds. Used in conjunction with OutOfRangeThresholdInDBm
        // to determine when an advertisement is no longer considered "in-range"
        watcher.SignalStrengthFilter.OutOfRangeTimeout = TimeSpan.FromMilliseconds(2000);

        // By default, the sampling interval is set to zero, which means there is no sampling and all
        // the advertisement received is returned in the Received event

        // End of watcher configuration. There is no need to comment out any code beyond this point.
    }


    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        watcher.Received += OnAdvertisementReceived;

        watcher.Stopped += OnAdvertisementWatcherStopped;

        App.Current.Suspending += App_Suspending;

        App.Current.Resuming += App_Resuming;
    }


    protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
    {
        App.Current.Suspending -= App_Suspending;
        App.Current.Resuming -= App_Resuming;

        watcher.Stop();

        watcher.Received -= OnAdvertisementReceived;
        watcher.Stopped -= OnAdvertisementWatcherStopped;

        base.OnNavigatingFrom(e);
    }


    private void App_Suspending(object sender, Windows.ApplicationModel.SuspendingEventArgs e)
    {
        // Make sure to stop the watcher on suspend.
        watcher.Stop();
        // Always unregister the handlers to release the resources to prevent leaks.
        watcher.Received -= OnAdvertisementReceived;
        watcher.Stopped -= OnAdvertisementWatcherStopped;

    }

    private void App_Resuming(object sender, object e)
    {
        watcher.Received += OnAdvertisementReceived;
        watcher.Stopped += OnAdvertisementWatcherStopped;
    }

    private async void OnAdvertisementReceived(BluetoothLEAdvertisementWatcher watcher, BluetoothLEAdvertisementReceivedEventArgs eventArgs)
    {
        var address = eventArgs.BluetoothAddress;

        BluetoothLEDevice device = await BluetoothLEDevice.FromBluetoothAddressAsync(address);

        var cnt =device.GattServices.Count;

        watcher.Stop();
    }

    /// <summary>
    /// Invoked as an event handler when the watcher is stopped or aborted.
    /// </summary>
    /// <param name="watcher">Instance of watcher that triggered the event.</param>
    /// <param name="eventArgs">Event data containing information about why the watcher stopped or aborted.</param>
    private void OnAdvertisementWatcherStopped(BluetoothLEAdvertisementWatcher watcher, BluetoothLEAdvertisementWatcherStoppedEventArgs eventArgs)
    {

    }

    private void start_Click(object sender, RoutedEventArgs e)
    {
        watcher.Start();
    }
}
answered on Stack Overflow Oct 2, 2015 by Jeffrey Chen
0

Just a guess, but maybe you need this:

watcher.ScanningMode = BluetoothLEScanningMode.Active;

and in the OnAdvertisementReceived event

if (e.AdvertisementType == BluetoothLEAdvertisementType.ScanResponse)
{
  BluetoothLEDevice blDevice = await BluetoothLEDevice.FromBluetoothAddressAsync(e.BluetoothAddress);
}
answered on Stack Overflow Jul 30, 2016 by LanderV
0

If this is a UWP project, ensure you enable Bluetooth capabilities.

To do so in Visual Studio solution explorer double click the *.appxmanifest, choose the 'Capabilities' tab and ensure that 'Bluetooth' is checked.

It will add some xml not unlike the following;

<Capabilities>
    <Capability Name="internetClientServer" />
    <DeviceCapability Name="bluetooth" />
</Capabilities>

answered on Stack Overflow Feb 1, 2019 by 1point8zero61
0

This Question is over 3 years old, but because it has over 13000 views, I will answer. The reason for Element not found is that Windows.Devices is not aware of advertising Ble-devices until they are paired or connected. Instead in the OnAdvertisementReceived just use:

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

I also have a very simple uwp example on github, it has no controls to keep it as simple as possible. All the results are shown in the debug output window. The most usefull info is in MainPage.xaml.cs

check it out: https://github.com/GrooverFromHolland/SimpleBleExample_by_Devicename

answered on Stack Overflow Feb 1, 2019 by GrooverFromHolland

User contributions licensed under CC BY-SA 3.0