美文网首页
winform、wpf蓝牙扫描的三种方式

winform、wpf蓝牙扫描的三种方式

作者: Camellia666 | 来源:发表于2020-08-27 18:19 被阅读0次

    1,先说结论

    本文介绍如何在winform、wpf中实现经典蓝牙扫描(同步方式和异步方式),以及实现基于win10的ble扫描。

    接下来是一波废话:

    由于公司业务需求,需要在windows桌面软件中实现蓝牙设备搜索功能。

    一番摆渡后发现基本上用的都是Inthehand的,这个库只能搜索到bt3经典蓝牙,可以实现同步搜索和异步搜索。要想实现ble搜索需要基于win10 SDK进行开发,微软官方demo是基于uwp的,那么可以实现在winform/wpf中使用吗?经过一番操作,实现了在wpf中调动win10 SDK进行ble搜索,但是必须要在win10环境下运行。

    2,Inthehand同步搜索

    所谓同步搜索就是固定扫描一段时间(大概10s钟的样子),然后返回扫描到的所有蓝牙设备。

    1,添加依赖

    32feet.PNG

    2,撸码

    public partial class Bt3SyncScan : Window
    {
        private BluetoothClient blueClient;
    
        public Bt3SyncScan()
        {
            InitializeComponent();
    
            BluetoothRadio BuleRadio = BluetoothRadio.PrimaryRadio;
            BuleRadio.Mode = RadioMode.Discoverable;
            blueClient = new BluetoothClient();
        }
    
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            // 异步扫描
            new Thread(() =>
            {
                IReadOnlyCollection<BluetoothDeviceInfo> Devices = blueClient.DiscoverDevices();
                foreach (BluetoothDeviceInfo device in Devices)
                {
                    //地址做一下美化
                    String addr = CommonUtil.btAddrFormat(device.DeviceAddress.ToString());
                    this.btnSearch.Dispatcher.Invoke(() =>
                    {
                        listBox.Items.Add(addr);
                    });
                }
            }).Start();
        }
    }
    

    3,效果

    1.gif

    缺点比较明显,需要等几秒钟才展示结果。

    3,Inthehand异步搜索

    异步搜索和同步搜索使用的是相同的库。

    1,撸码

    public partial class Bt3AsyncScan : Window
    {
        private BluetoothClient bluetoothClient;
    
        public Bt3AsyncScan()
        {
            InitializeComponent();
            
            bluetoothClient = new BluetoothClient();
            BluetoothRadio bluetoothRadio = BluetoothRadio.PrimaryRadio;
            bluetoothRadio.Mode = RadioMode.Connectable;
        }
    
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            BluetoothComponent bluetoothComponent = new BluetoothComponent(bluetoothClient);
            // 开始异步扫描
            bluetoothComponent.DiscoverDevicesAsync(10, false, false, false, true, bluetoothComponent);
            // 扫描结果回调
            bluetoothComponent.DiscoverDevicesProgress += BluetoothComponent_DiscoverDevicesProgress;
        }
    
        private void BluetoothComponent_DiscoverDevicesProgress(object sender, DiscoverDevicesEventArgs e)
        {
            string addr = e.Devices[0].DeviceAddress.ToString();
            listBox.Items.Add(CommonUtil.btAddrFormat(addr));
        }
    }
    

    2,效果

    2.gif

    可以看出每扫描到一个设备就展示出来,速度非常快。

    4,基于winSDK的ble扫描

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

    1,准备

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

    2,添加win10 SDK依赖

    在你的wpf项目中添加如下引用

    win10refer.PNG

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

    这三个依赖的参考位置如下:

    C:\Windows Kits\10\UnionMetadata\10.0.17763.0\Windows.winmd
    C:\Windows Kits\10\References\10.0.17763.0\Windows.Foundation.FoundationContract\3.0.0.0\Windows.Foundation.FoundationContract.winmd
    C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7.2\WindowsBase.dll
    

    3,撸码

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

    4,效果

    3.gif

    相关文章

      网友评论

          本文标题:winform、wpf蓝牙扫描的三种方式

          本文链接:https://www.haomeiwen.com/subject/rukhsktx.html