winform 程序調用Windows.Devices.Bluetoot API 實現windows下BLE藍牙設備自動鏈接,收發數據功能。不須要使用win10的UWP開發。web
先貼圖,回頭來完善代碼windows
源碼以下:數組
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Windows.Devices.Bluetooth; using Windows.Devices.Bluetooth.GenericAttributeProfile; using Windows.Devices.Enumeration; using Windows.Foundation; using Windows.Security.Cryptography; namespace BLECode { public class BluetoothLECode { //存儲檢測的設備MAC。 public string CurrentDeviceMAC { get; set; } //存儲檢測到的設備。 public BluetoothLEDevice CurrentDevice { get; set; } //存儲檢測到的主服務。 public GattDeviceService CurrentService { get; set; } //存儲檢測到的寫特徵對象。 public GattCharacteristic CurrentWriteCharacteristic { get; set; } //存儲檢測到的通知特徵對象。 public GattCharacteristic CurrentNotifyCharacteristic { get; set; } public string ServiceGuid { get; set; } public string WriteCharacteristicGuid { get; set; } public string NotifyCharacteristicGuid { get; set; } private const int CHARACTERISTIC_INDEX = 0; //特性通知類型通知啓用 private const GattClientCharacteristicConfigurationDescriptorValue CHARACTERISTIC_NOTIFICATION_TYPE = GattClientCharacteristicConfigurationDescriptorValue.Notify; private Boolean asyncLock = false; private DeviceWatcher deviceWatcher; //定義一個委託 public delegate void eventRun(MsgType type, string str,byte[] data=null); //定義一個事件 public event eventRun ValueChanged; public BluetoothLECode(string serviceGuid, string writeCharacteristicGuid, string notifyCharacteristicGuid) { ServiceGuid = serviceGuid; WriteCharacteristicGuid = writeCharacteristicGuid; NotifyCharacteristicGuid = notifyCharacteristicGuid; } public void StartBleDeviceWatcher() { string[] requestedProperties = { "System.Devices.Aep.DeviceAddress", "System.Devices.Aep.IsConnected", "System.Devices.Aep.Bluetooth.Le.IsConnectable" }; string aqsAllBluetoothLEDevices = "(System.Devices.Aep.ProtocolId:=\"{bb7bb05e-5972-42b5-94fc-76eaa7084d49}\")"; deviceWatcher = DeviceInformation.CreateWatcher( aqsAllBluetoothLEDevices, requestedProperties, DeviceInformationKind.AssociationEndpoint); // Register event handlers before starting the watcher. deviceWatcher.Added += DeviceWatcher_Added; deviceWatcher.Stopped += DeviceWatcher_Stopped; deviceWatcher.Start(); string msg = "自動發現設備中.."; ValueChanged(MsgType.NotifyTxt, msg); } private void DeviceWatcher_Stopped(DeviceWatcher sender, object args) { string msg = "自動發現設備中止"; ValueChanged(MsgType.NotifyTxt, msg); } private void DeviceWatcher_Added(DeviceWatcher sender, DeviceInformation args) { ValueChanged(MsgType.NotifyTxt, "發現設備:" + args.Id); if (args.Id.EndsWith(CurrentDeviceMAC)) { Matching(args.Id); } } /// <summary> /// 按MAC地址查找系統中配對設備 /// </summary> /// <param name="MAC"></param> public async Task SelectDevice(string MAC) { CurrentDeviceMAC = MAC; CurrentDevice = null; DeviceInformation.FindAllAsync(BluetoothLEDevice.GetDeviceSelector()).Completed = async (asyncInfo, asyncStatus) => { if (asyncStatus == AsyncStatus.Completed) { DeviceInformationCollection deviceInformation = asyncInfo.GetResults(); foreach (DeviceInformation di in deviceInformation) { await Matching(di.Id); } if (CurrentDevice == null) { string msg = "沒有發現設備"; ValueChanged(MsgType.NotifyTxt, msg); StartBleDeviceWatcher(); } } }; } /// <summary> /// 按MAC地址直接組裝設備ID查找設備 /// </summary> /// <param name="MAC"></param> /// <returns></returns> public async Task SelectDeviceFromIdAsync(string MAC) { CurrentDeviceMAC = MAC; CurrentDevice = null; BluetoothAdapter.GetDefaultAsync().Completed = async (asyncInfo, asyncStatus) => { if (asyncStatus == AsyncStatus.Completed) { BluetoothAdapter mBluetoothAdapter = asyncInfo.GetResults(); byte[] _Bytes1 = BitConverter.GetBytes(mBluetoothAdapter.BluetoothAddress);//ulong轉換爲byte數組 Array.Reverse(_Bytes1); string macAddress = BitConverter.ToString(_Bytes1, 2, 6).Replace('-', ':').ToLower(); string Id = "BluetoothLE#BluetoothLE" + macAddress + "-" + MAC; await Matching(Id); } }; } private async Task Matching(string Id) { try { BluetoothLEDevice.FromIdAsync(Id).Completed = async (asyncInfo, asyncStatus) => { if (asyncStatus == AsyncStatus.Completed) { BluetoothLEDevice bleDevice = asyncInfo.GetResults(); //在當前設備變量中保存檢測到的設備。 CurrentDevice = bleDevice; await Connect(); } }; } catch (Exception e) { string msg = "沒有發現設備" + e.ToString(); ValueChanged(MsgType.NotifyTxt, msg); StartBleDeviceWatcher(); } } private async Task Connect() { string msg = "正在鏈接設備<" + CurrentDeviceMAC + ">.."; ValueChanged(MsgType.NotifyTxt, msg); CurrentDevice.ConnectionStatusChanged += CurrentDevice_ConnectionStatusChanged; await SelectDeviceService(); } /// <summary> /// 主動斷開鏈接 /// </summary> /// <returns></returns> public void Dispose() { CurrentDeviceMAC = null; CurrentService?.Dispose(); CurrentDevice?.Dispose(); CurrentDevice = null; CurrentService = null; CurrentWriteCharacteristic = null; CurrentNotifyCharacteristic = null; ValueChanged(MsgType.NotifyTxt, "主動斷開鏈接"); } private void CurrentDevice_ConnectionStatusChanged(BluetoothLEDevice sender, object args) { if (sender.ConnectionStatus == BluetoothConnectionStatus.Disconnected && CurrentDeviceMAC != null) { string msg = "設備已斷開,自動重連"; ValueChanged(MsgType.NotifyTxt, msg); if (!asyncLock) { asyncLock = true; CurrentDevice.Dispose(); CurrentDevice = null; CurrentService = null; CurrentWriteCharacteristic = null; CurrentNotifyCharacteristic = null; SelectDeviceFromIdAsync(CurrentDeviceMAC); } } else { string msg = "設備已鏈接"; ValueChanged(MsgType.NotifyTxt, msg); } } /// <summary> /// 按GUID 查找主服務 /// </summary> /// <param name="characteristic">GUID 字符串</param> /// <returns></returns> public async Task SelectDeviceService() { Guid guid = new Guid(ServiceGuid); CurrentDevice.GetGattServicesForUuidAsync(guid).Completed = (asyncInfo, asyncStatus) => { if (asyncStatus == AsyncStatus.Completed) { try { GattDeviceServicesResult result = asyncInfo.GetResults(); string msg = "主服務=" + CurrentDevice.ConnectionStatus; ValueChanged(MsgType.NotifyTxt, msg); if (result.Services.Count > 0) { CurrentService = result.Services[CHARACTERISTIC_INDEX]; if (CurrentService != null) { asyncLock = true; GetCurrentWriteCharacteristic(); GetCurrentNotifyCharacteristic(); } } else { msg = "沒有發現服務,自動重試中"; ValueChanged(MsgType.NotifyTxt, msg); SelectDeviceService(); } } catch (Exception e) { ValueChanged(MsgType.NotifyTxt, "沒有發現服務,自動重試中"); SelectDeviceService(); } } }; } /// <summary> /// 設置寫特徵對象。 /// </summary> /// <returns></returns> public async Task GetCurrentWriteCharacteristic() { string msg = ""; Guid guid = new Guid(WriteCharacteristicGuid); CurrentService.GetCharacteristicsForUuidAsync(guid).Completed = async (asyncInfo, asyncStatus) => { if (asyncStatus == AsyncStatus.Completed) { GattCharacteristicsResult result = asyncInfo.GetResults(); msg = "特徵對象=" + CurrentDevice.ConnectionStatus; ValueChanged(MsgType.NotifyTxt, msg); if (result.Characteristics.Count > 0) { CurrentWriteCharacteristic = result.Characteristics[CHARACTERISTIC_INDEX]; } else { msg = "沒有發現特徵對象,自動重試中"; ValueChanged(MsgType.NotifyTxt, msg); await GetCurrentWriteCharacteristic(); } } }; } /// <summary> /// 發送數據接口 /// </summary> /// <param name="characteristic"></param> /// <param name="data"></param> /// <returns></returns> public async Task Write(byte[] data) { if (CurrentWriteCharacteristic != null) { CurrentWriteCharacteristic.WriteValueAsync(CryptographicBuffer.CreateFromByteArray(data), GattWriteOption.WriteWithResponse); } } /// <summary> /// 設置通知特徵對象。 /// </summary> /// <returns></returns> public async Task GetCurrentNotifyCharacteristic() { string msg = ""; Guid guid = new Guid(NotifyCharacteristicGuid); CurrentService.GetCharacteristicsForUuidAsync(guid).Completed = async (asyncInfo, asyncStatus) => { if (asyncStatus == AsyncStatus.Completed) { GattCharacteristicsResult result = asyncInfo.GetResults(); msg = "特徵對象=" + CurrentDevice.ConnectionStatus; ValueChanged(MsgType.NotifyTxt, msg); if (result.Characteristics.Count > 0) { CurrentNotifyCharacteristic = result.Characteristics[CHARACTERISTIC_INDEX]; CurrentNotifyCharacteristic.ProtectionLevel = GattProtectionLevel.Plain; CurrentNotifyCharacteristic.ValueChanged += Characteristic_ValueChanged; await EnableNotifications(CurrentNotifyCharacteristic); } else { msg = "沒有發現特徵對象,自動重試中"; ValueChanged(MsgType.NotifyTxt, msg); await GetCurrentNotifyCharacteristic(); } } }; } /// <summary> /// 設置特徵對象爲接收通知對象 /// </summary> /// <param name="characteristic"></param> /// <returns></returns> public async Task EnableNotifications(GattCharacteristic characteristic) { string msg = "收通知對象=" + CurrentDevice.ConnectionStatus; ValueChanged(MsgType.NotifyTxt, msg); characteristic.WriteClientCharacteristicConfigurationDescriptorAsync(CHARACTERISTIC_NOTIFICATION_TYPE).Completed = async (asyncInfo, asyncStatus) => { if (asyncStatus == AsyncStatus.Completed) { GattCommunicationStatus status = asyncInfo.GetResults(); if (status == GattCommunicationStatus.Unreachable) { msg = "設備不可用"; ValueChanged(MsgType.NotifyTxt, msg); if (CurrentNotifyCharacteristic != null && !asyncLock) { await EnableNotifications(CurrentNotifyCharacteristic); } } asyncLock = false; msg = "設備鏈接狀態" + status; ValueChanged(MsgType.NotifyTxt, msg); } }; } private void Characteristic_ValueChanged(GattCharacteristic sender, GattValueChangedEventArgs args) { byte[] data; CryptographicBuffer.CopyToByteArray(args.CharacteristicValue, out data); string str = BitConverter.ToString(data); ValueChanged(MsgType.BLEData,str, data); } } public enum MsgType { NotifyTxt, BLEData } }
調用方式:async
bluetooth = new BluetoothLECode(_serviceGuid, _writeCharacteristicGuid, _notifyCharacteristicGuid); bluetooth.ValueChanged += Bluetooth_ValueChanged;
若是你沒法編譯上面的類庫,請直接使用我生成的DLL文件ui
https://files.cnblogs.com/files/webtojs/BLECode.rarspa