Windows 10蓝牙低功耗连接c#

本文关键字:连接 低功耗 Windows | 更新日期: 2023-09-27 18:15:27

对于一个项目,我需要使用c#从windows 10上的蓝牙设备获得一些数据。我不太熟悉蓝牙API,不知道为什么以下内容不工作:

使用BluetoothLEAdvertisementWatcher I搜索广告,效果很好。我确实收到了来自设备的广告(本地名称适合)以及ServiceUuids。接下来,我尝试使用与广告一起收到的BluetoothAddress连接到设备:

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

但是,这样做会导致一个异常:

元素未找到。(Exception from HRESULT: 0x80070490).

这是从设备读取数据的正确方法吗?是否有其他选项可用于从服务读取数据?在windows中手动配对设备并不是一个真正的选择,而且似乎也会失败。

/Edit 1:我检查设备的本地名称,以确保我只尝试连接到正确的设备。所以我猜连接到这个特定的设备有问题,我仍然不知道如何解决这个问题。在iOS上已经成功读取了服务数据,所以应该是可以的。

Windows 10蓝牙低功耗连接c#

在MS修复此问题之前,我发现连接到BLE设备的唯一可靠解决方案是要求注册表提供配对BLE设备列表,并将广告中的蓝牙地址与配对设备的注册表进行比较。我的经验是,当FromBluetoothAddressAsync在未配对的设备上被调用时,Windows抛出异常并杀死监视线程。我有一些c++代码,我很高兴分享,读取注册表并创建配对BLE设备列表。

希望微软能像苹果一样,花点时间全面支持BLE。

这是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)的参考。似乎使用这个蓝牙设备。从bluetoothaddressasync我们必须处理异常时,设备是广告,尚未配对

当我直接使用BluetoothLEAdvertisementWatcher时,我也遇到了同样的问题。

然后我测试了观察者列出的不同地址。我发现它与蓝牙设备有关。

按如下方式添加滤波器后,我可以成功连接GATT设备(TI Sensor Tag)。

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();
    }
}

只是猜测,但也许你需要这个:

watcher.ScanningMode = BluetoothLEScanningMode.Active;

和OnAdvertisementReceived事件

if (e.AdvertisementType == BluetoothLEAdvertisementType.ScanResponse)
{
  BluetoothLEDevice blDevice = await BluetoothLEDevice.FromBluetoothAddressAsync(e.BluetoothAddress);
}

如果这是一个UWP项目,请确保您启用了蓝牙功能。

在Visual Studio解决方案资源管理器中双击*。appxmanifest,选择"Capabilities"选项卡,并确保选中了"Bluetooth"。

它将添加一些类似于下面的xml;

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

这个问题已经超过3年了,但是因为它有超过13000的点击量,所以我将回答。没有找到Element的原因是Windows。设备不知道广告ble设备,直到它们配对或连接。相反,在OnAdvertisementReceived中使用:

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

我也有一个非常简单的uwp的例子在github上,它没有控制,以保持它尽可能简单。所有结果都显示在调试输出窗口中。最有用的信息在mainpage . example .cs

查看:https://github.com/GrooverFromHolland/SimpleBleExample_by_Devicename