C# & .Net8.0使用Window api(Windows.Devices.Bluetooth)实现低功耗蓝牙BLE通信

1. 先实现Window API

在.Net8.0环境下直接引用Windows.Devices.Bluetooth会报错
using Windows.Devices.Bluetooth;
using Windows.Devices.Bluetooth.Advertisement;
using Windows.Devices.Bluetooth.GenericAttributeProfile;
using Windows.Foundation;
using Windows.Security.Cryptography;
安装Windows.Devices.Bluetooth过程如下:
  (1)Nuget安装InTheHand.BluetoothLE这个包
  (2)安装完毕,然后卸载
  (3)然后刷新下项目,
Windows.Devices.Bluetooth即可使用

2.实现Ble类(参考晚上前辈与大佬们的实现,感谢各位,代码没有精简,大家可以自己发挥)
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices.JavaScript;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using Windows.Devices.Bluetooth;
using Windows.Devices.Bluetooth.Advertisement;
using Windows.Devices.Bluetooth.GenericAttributeProfile;
using Windows.Foundation;
using Windows.Security.Cryptography;

namespace WpfApp2
{

    public class CBle :IDisposable
    {
        /// <summary>
        /// 写特征对象
        /// </summary>
        public GattCharacteristic CurrentWriteCharacteristic { get; set; }

        /// <summary>
        /// 通知特征对象
        /// </summary>
        public GattCharacteristic CurrentNotifyCharacteristic { get; set; }

        /// <summary>
        /// 设备搜索监测
        /// </summary>
        public BluetoothLEAdvertisementWatcher bleWatcher{ get; set; }


        private ulong BleAddress {  get; set; }
        /// <summary>
        /// 当前连接的蓝牙设备
        /// </summary>
        public BluetoothLEDevice CurrentDevice { get; set; }
        /// <summary>
        /// 定义搜索蓝牙设备委托
        /// </summary>
        public delegate void DeviceWatcherChangedEvent(BluetoothLEDevice bluetoothLEDevice);

        /// <summary>
        /// 搜索蓝牙事件
        /// </summary>
        public event DeviceWatcherChangedEvent DeviceWatcherChanged;

        public event EventHandler<List<byte>> DataRecHandler;

        //特性通知类型通知启用
        private const GattClientCharacteristicConfigurationDescriptorValue CHARACTERISTIC_NOTIFICATION_TYPE = GattClientCharacteristicConfigurationDescriptorValue.Notify;

        public CBle()
        {

        }
        #region Scan


        public void StartScanNearbyDevices()
        {
            bleWatcher = new BluetoothLEAdvertisementWatcher
            {
                ScanningMode = BluetoothLEScanningMode.Active,
            };
            // only activate the watcher when we're recieving values >= -80
            bleWatcher.SignalStrengthFilter.InRangeThresholdInDBm = -80;

            // stop watching if the value drops below -90 (user walked away)
            bleWatcher.SignalStrengthFilter.OutOfRangeThresholdInDBm = -90;

            // wait 5 seconds to make sure the device is really out of range
            bleWatcher.SignalStrengthFilter.OutOfRangeTimeout = TimeSpan.FromMilliseconds(5000);
            bleWatcher.SignalStrengthFilter.SamplingInterval = TimeSpan.FromMilliseconds(2000);
            bleWatcher.Received -= OnAdvertisementReceived;
            bleWatcher.Received += OnAdvertisementReceived;

            bleWatcher.Start();
            Debug.WriteLine("StartScanNearbyDevices");
        }

        public void StopScanNearbyDevices()
        {
            
            if (bleWatcher != null)
            {
                bleWatcher.Received -= OnAdvertisementReceived;
                bleWatcher.Stop();
            }
            Debug.WriteLine("StopScanNearbyDevices");

        }
        private void OnAdvertisementReceived(BluetoothLEAdvertisementWatcher watcher, BluetoothLEAdvertisementReceivedEventArgs eventArgs)
        {
            BluetoothLEDevice.FromBluetoothAddressAsync(eventArgs.BluetoothAddress).Completed = (asyncInfo, asyncStatus) =>
            {
                if (asyncStatus == AsyncStatus.Completed)
                {
                    if (asyncInfo.GetResults() != null)
                    {
                        BluetoothLEDevice currentDevice = asyncInfo.GetResults();
                        DeviceWatcherChanged?.Invoke(currentDevice);
                    }
                }
            };
        }
        #endregion

        /// <summary>
        /// 主动断开连接
        /// </summary>
        /// <returns></returns>
        public void DisConnect()
        {
            Dispose();
        }

        #region Match
        /// <summary>
        /// 通过MAC地址获取实际设备信息
        /// </summary>
        /// <param name="bluetoothAddress"></param>
        /// <returns></returns>
        public async Task<BluetoothLEDevice> GetBleByAddressAsync(ulong bluetoothAddress)
        {
            BleAddress = bluetoothAddress;
            BluetoothLEDevice device = await BluetoothLEDevice.FromBluetoothAddressAsync(BleAddress);
            return device;
        }


        /// <summary>
        /// 获取蓝牙服务
        /// </summary>
        public async Task<List<GattDeviceService>> StartFindServiceAsync(BluetoothLEDevice device)
        {
            List<GattDeviceService> gattDeviceServices = new List<GattDeviceService>();
            this.CurrentDevice = device;
            BleAddress = device.BluetoothAddress;
            if (this.CurrentDevice == null)
                return gattDeviceServices;
            GattDeviceServicesResult gatts = await this.CurrentDevice.GetGattServicesAsync();
            if (gatts.Services == null || gatts.Services.Count == 0)
                return gattDeviceServices;
            foreach (GattDeviceService gattDeviceService in gatts.Services)
            {
                gattDeviceServices.Add(gattDeviceService);
            }
            return gattDeviceServices;
        }



        /// <summary>
        /// 设置写特征对象。
        /// </summary>
        /// <returns></returns>
        public async Task<bool> Connect(GattDeviceService gattDeviceService)
        {

            Debug.WriteLine($"Connect:{gattDeviceService.Uuid}");
            GattCharacteristicsResult gattCharacteristicsResult = await gattDeviceService.GetCharacteristicsAsync();

            if (gattCharacteristicsResult == null)
            {
                Debug.WriteLine($"GattCharacteristicsResult is null");
                return false;
            }
            else
            {
                this.CurrentWriteCharacteristic = gattCharacteristicsResult.Characteristics.FirstOrDefault(c => c.CharacteristicProperties == GattCharacteristicProperties.WriteWithoutResponse);
                Debug.WriteLine($"gattCharacteristicsResult.Characteristics WriteWithoutResponse :{CurrentWriteCharacteristic?.Uuid}");
this.CurrentNotifyCharacteristic = gattCharacteristicsResult.Characteristics.FirstOrDefault(c => c.CharacteristicProperties == GattCharacteristicProperties.Notify); Debug.WriteLine($"gattCharacteristicsResult.Characteristics Notify :{CurrentNotifyCharacteristic?.Uuid}"); if (this.CurrentNotifyCharacteristic != null && this.CurrentWriteCharacteristic != null) { this.CurrentNotifyCharacteristic.ProtectionLevel = GattProtectionLevel.Plain; this.CurrentNotifyCharacteristic.ValueChanged += Characteristic_ValueChanged; GattCommunicationStatus communicationStatus = await CurrentNotifyCharacteristic.WriteClientCharacteristicConfigurationDescriptorAsync(GattClientCharacteristicConfigurationDescriptorValue.Notify); return communicationStatus == GattCommunicationStatus.Success; } return false; } } public void Dispose() { CurrentDevice?.Dispose(); CurrentDevice = null; CurrentWriteCharacteristic = null; CurrentNotifyCharacteristic = null; } #endregion #region RW /// <summary> /// 发送数据接口 /// </summary> /// <param name="characteristic"></param> /// <param name="data"></param> /// <returns></returns> public async Task<bool> Write(byte[] data) { if (CurrentWriteCharacteristic != null) { //GattCommunicationStatus status = await CurrentWriteCharacteristic.WriteValueAsync(CryptographicBuffer.CreateFromByteArray(data), GattWriteOption.WriteWithoutResponse); GattWriteResult result = await CurrentWriteCharacteristic.WriteValueWithResultAsync(CryptographicBuffer.CreateFromByteArray(data), GattWriteOption.WriteWithoutResponse); return result.Status == GattCommunicationStatus.Success; } return false; } private void Characteristic_ValueChanged(GattCharacteristic sender, GattValueChangedEventArgs args) { CryptographicBuffer.CopyToByteArray(args.CharacteristicValue, out byte[] data); //string str = BitConverter.ToString(data); //Debug.WriteLine(str); DataRecHandler?.Invoke(sender, data.ToList()); } #endregion } }

  


3.调用下(也没有精简,只是提供下方法)

我连接的目标设备是 2025021909这个设备,搜索到就直接调用了,uuid用的是fff0 / ff03 / ff02
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Xml;
using Windows.Devices.Bluetooth;
using Windows.Devices.Bluetooth.Advertisement;
using Windows.Devices.Bluetooth.GenericAttributeProfile;
using Windows.Devices.HumanInterfaceDevice;

namespace WpfApp2
{

    /// <summary>
    /// Window1.xaml 的交互逻辑
    /// </summary>
    public partial class Window1 : Window
    {
        List<BluetoothLEDevice> Devices = new List<BluetoothLEDevice>();
        CBle bleCore { get; set; } = new CBle();
        private BluetoothLEDevice TDeviceAddr { get; set; }
        public Window1()
        {
            InitializeComponent();

            bleCore.DeviceWatcherChanged -= BleCore_DeviceWatcherChanged;
            bleCore.DeviceWatcherChanged += BleCore_DeviceWatcherChanged;
            bleCore.DataRecHandler += BleCore_DataRecHandler;
            Debug.WriteLine($"Start");
            bleCore.StartScanNearbyDevices();

            Task.Delay(20000).GetAwaiter().GetResult();
            bleCore.StopScanNearbyDevices();
            Debug.WriteLine($"End");

        }


        bool IsStart = false;
        private async void BleCore_DeviceWatcherChanged(BluetoothLEDevice bluetoothLEDevice)
        {

            Debug.WriteLine($"Resp Device >>>>> {bluetoothLEDevice.Name}; Mac:{bluetoothLEDevice.BluetoothDeviceId.Id}");

            if (bluetoothLEDevice.DeviceInformation.Name.Contains("2025021909"))
            {

                if (IsStart)
                    return;
                IsStart = true;

                bleCore.StopScanNearbyDevices();
                //Devices.Add(bluetoothLEDevice);
                //Debug.WriteLine($"ADD Device >>>>> {bluetoothLEDevice.Name}; Mac:{bluetoothLEDevice.BluetoothDeviceId.Id}");
                TDeviceAddr = bluetoothLEDevice;


                List<GattDeviceService> result = await bleCore.StartFindServiceAsync(TDeviceAddr);
                while (result.Count() == 0)
                {
                    Debug.WriteLine($"Get GattDeviceService Failed!  ReStart! " );
                    result = await bleCore.StartFindServiceAsync(TDeviceAddr);
                }
                GattDeviceService gattDeviceService = result.First(gds => gds.Uuid.ToString().Contains("fff0"));

                Debug.WriteLine($"GattDeviceService:{gattDeviceService.Uuid}");

                bool status = await bleCore.Connect(gattDeviceService);
                if (status)
                {
                    Debug.WriteLine($"Connect  status:{status}");

                  
                    for (int i = 0; i < 3; i++)
                    {

                        bool writeStatus = await bleCore.Write(new byte[] { 0x01, 0x22, });
                        Debug.WriteLine($"NO.{i} Write Result:{writeStatus}");
                        await Task.Delay(5000);
                    }

                }

                await Task.Delay(5000);
                bleCore.DisConnect();
                Debug.WriteLine($"DisConnect");
                Debug.WriteLine($"bleCore Status:{bleCore.CurrentDevice != null}");
            }
        }

        private void BleCore_DataRecHandler(object? sender, List<byte> e)
        {
            Debug.WriteLine($"DataRecHandler: {string.Join(" ", e)}");
        }
    }
}

 

 

 


 

posted @ 2025-02-26 16:16  sanmannn  阅读(942)  评论(0)    收藏  举报