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


浙公网安备 33010602011771号