使用WPF C# 实现BLE扫描设备

996 阅读1分钟

基于winSDK的ble扫描

ble扫描可以扫描到ble设备,可以添加过滤条件,只搜索特定的设备,并且可以获取其信号强度。微软官方demo是基于uwp的,迁移到 wpf下,还是有点麻烦的。主要过程如下:

1,准备

需要你在win10环境下,并且vs安装了win10 SDK。

2,添加win10 SDK依赖

image.png

如果你的项目中默认没有添加WindowsBase的话也要手动引入。

这三个依赖的参考位置如下: 1) C:\Windows Kits\10\UnionMetadata\10.0.17763.0\Windows.winmd 2) C:\Windows Kits\10\References\10.0.17763.0\Windows.Foundation.FoundationContract\3.0.0.0\Windows.Foundation.FoundationContract.winmd

3) C:\Program Files\Reference Assemblies\Microsoft\Framework.NETFramework\v4.7.2\WindowsBase.dll

  1. 代码实现

public partial class BleScan : Window { private BluetoothLEAdvertisementWatcher watcher;

private BluetoothLEManufacturerData manufacturerData;

public BleScan()
{
    InitializeComponent();

    initBluetooth();
}

private void initBluetooth()
{
    watcher = new BluetoothLEAdvertisementWatcher();

    var manufacturerData = new BluetoothLEManufacturerData();

    manufacturerData.CompanyId = 0x014C;

    var writer = new DataWriter();
    writer.WriteUInt16(0x0719);

    manufacturerData.Data = writer.DetachBuffer();

    // 过滤条件:companyId = 0x014C 且值为:0x0719的广播。可自行修改或删除
    watcher.AdvertisementFilter.Advertisement.ManufacturerData.Add(manufacturerData);
    // 根据信号强度过滤
    watcher.SignalStrengthFilter.InRangeThresholdInDBm = -50;
    watcher.SignalStrengthFilter.OutOfRangeThresholdInDBm = -55;
    watcher.SignalStrengthFilter.OutOfRangeTimeout = TimeSpan.FromMilliseconds(2000);
    watcher.Received += OnAdvertisementReceived;
    watcher.Stopped += OnAdvertisementWatcherStopped;
}

private void Button_Click(object sender, RoutedEventArgs e)
{
    watcher.Start();
}

private async void OnAdvertisementReceived(BluetoothLEAdvertisementWatcher watcher, BluetoothLEAdvertisementReceivedEventArgs eventArgs)
{
    // 信号强度
    Int16 rssi = eventArgs.RawSignalStrengthInDBm;
	// 蓝牙地址
    string addr = CommonUtil.btAddrFormat2(eventArgs.BluetoothAddress.ToString("x8"));

    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 = BitConverter.ToString(data);
    }

    // Serialize UI update to the main UI thread
    this.btnScan.Dispatcher.Invoke(() =>
    {
        listBox.Items.Add(String.Format("address:{0}, rssi:{1}, manufacturer:{2}", addr, rssi, manufacturerDataString));
    });
}

private async void OnAdvertisementWatcherStopped(BluetoothLEAdvertisementWatcher watcher, BluetoothLEAdvertisementWatcherStoppedEventArgs eventArgs)
{
    this.btnScan.Dispatcher.Invoke(() =>
    {
    });
}

private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
    watcher.Received -= OnAdvertisementReceived;
    watcher.Stopped -= OnAdvertisementWatcherStopped;
    watcher.Stop();
}

}