using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Windows.Devices.Bluetooth; using Windows.Devices.Bluetooth.Advertisement; using Windows.Devices.Bluetooth.GenericAttributeProfile; using Windows.Devices.Enumeration; using Windows.Foundation; using Windows.Security.Cryptography; namespace Bluetoolth { public enum BlueStatus { DisConnected, //未连接 Connecting, //正在连接 Connected //已连接 }; public enum MsgType { NotifyTxt, BleDevice, BleSendData, BleRecData, } public class BleCore { private bool asyncLock = false; /// <summary> /// 搜索蓝牙设备对象 /// </summary> private DeviceWatcher deviceWatcher; /// <summary> /// 当前连接的服务 /// </summary> public GattDeviceService CurrentService { get; set; } /// <summary> /// 当前连接的蓝牙设备 /// </summary> public BluetoothLEDevice CurrentDevice { get; set; } /// <summary> /// 写特征对象 /// </summary> public GattCharacteristic CurrentWriteCharacteristic { get; set; } /// <summary> /// 写名称特征对象 /// </summary> public GattCharacteristic CurrentNameCharacteristic { get; set; } /// <summary> /// 通知特征对象 /// </summary> public GattCharacteristic CurrentNotifyCharacteristic { get; set; } /// <summary> /// 特性通知类型通知启用 /// </summary> private const GattClientCharacteristicConfigurationDescriptorValue CHARACTERSITIC_NOTIFICATION_TYPE = GattClientCharacteristicConfigurationDescriptorValue.Notify; /// <summary> /// 存储检测到的设备 /// </summary> private List<string> DevicesList = new List<string>(); /// <summary> /// 定义搜索蓝牙设备委托 /// </summary> /// <param name="type"></param> /// <param name="bluetoothLEDevice"></param> public delegate void DevicewatcherChangedEvent(MsgType type, BluetoothLEDevice bluetoothLEDevice); /// <summary> /// 搜索蓝牙事件 /// </summary> public event DevicewatcherChangedEvent DevicewatcherChanged; /// <summary> /// 获取服务委托 /// </summary> /// <param name="gattDeviceService"></param> public delegate void GattDeviceServiceAddedEvent(GattDeviceService gattDeviceService); /// <summary> /// 获取服务事件 /// </summary> public event GattDeviceServiceAddedEvent GattDeviceServiceAdded; /// <summary> /// 获取特征委托 /// </summary> /// <param name="gattCharacteristic"></param> public delegate void CharacteristicAddedEvent(GattCharacteristic gattCharacteristic); /// <summary> /// 获取特征事件 /// </summary> public event CharacteristicAddedEvent CharacteristicAdded; /// <summary> /// 提示信息委托 /// </summary> /// <param name="type"></param> /// <param name="message"></param> /// <param name="data"></param> public delegate void MessageChangedEvent(MsgType type, string message, byte[] data = null); /// <summary> /// 提示信息事件 /// </summary> public event MessageChangedEvent MessageChanged; /// <summary> /// 当前连接蓝牙的Mac /// </summary> private string CurrentDeviceMAC { get; set; } public BleCore() { } /// <summary> /// 搜索蓝牙设备 方法1 /// </summary> public void StartBleDevicewatcher_1() { string[] requestedProperties = { "System.Devices.Aep.DeviceAddress", "System.Devices.Aep.IsConnected", "System.Devices.Aep.Bluetooth.Le.IsConnectable" , "System.Devices.Aep.SignalStrength", "System.Devices.Aep.IsPresent" }; string aqsAllBluetoothLEDevices = "(System.Devices.Aep.ProtocolId:=\"{bb7bb05e-5972-42b5-94fc-76eaa7084d49}\")"; string Selector = "System.Devices.Aep.ProtocolId:=\"{bb7bb05e-5972-42b5-94fc-76eaa7084d49}\""; string selector = "(" + Selector + ")" + " AND (System.Devices.Aep.CanPair:=System.StructuredQueryType.Boolean#True OR System.Devices.Aep.IsPaired:=System.StructuredQueryType.Boolean#True)"; this.deviceWatcher = DeviceInformation.CreateWatcher( // aqsAllBluetoothLEDevices, // BluetoothLEDevice.GetDeviceSelectorFromPairingState(false), selector, requestedProperties, DeviceInformationKind.AssociationEndpoint); //在监控之前注册事件 this.deviceWatcher.Added += DeviceWatcher_Added; this.deviceWatcher.Stopped += DeviceWatcher_Stopped; this.deviceWatcher.Updated += DeviceWatcher_Updated; ; this.deviceWatcher.Start(); string msg = "自动发现设备中.."; this.MessageChanged(MsgType.NotifyTxt, msg); } BluetoothLEAdvertisementWatcher watcher; /// <summary> /// 搜索蓝牙设备 方法2 /// </summary> public void StartBleDevicewatcher() { watcher = new BluetoothLEAdvertisementWatcher(); watcher.ScanningMode = BluetoothLEScanningMode.Active; // only activate the watcher when we're recieving values >= -80 watcher.SignalStrengthFilter.InRangeThresholdInDBm = -80; // stop watching if the value drops below -90 (user walked away) watcher.SignalStrengthFilter.OutOfRangeThresholdInDBm = -90; // register callback for when we see an advertisements watcher.Received += OnAdvertisementReceived; watcher.Stopped += Watcher_Stopped; // wait 5 seconds to make sure the device is really out of range watcher.SignalStrengthFilter.OutOfRangeTimeout = TimeSpan.FromMilliseconds(5000); watcher.SignalStrengthFilter.SamplingInterval = TimeSpan.FromMilliseconds(2000); // starting watching for advertisements watcher.Start(); string msg = "自动发现设备中.."; // this.MessageChanged(MsgType.NotifyTxt, msg); } private void Watcher_Stopped(BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementWatcherStoppedEventArgs args) { DevicesList.Clear(); string msg = "自动发现设备停止"; this.MessageChanged(MsgType.NotifyTxt, msg); } private void OnAdvertisementReceived(BluetoothLEAdvertisementWatcher watcher, BluetoothLEAdvertisementReceivedEventArgs eventArgs) { BluetoothLEDevice.FromBluetoothAddressAsync(eventArgs.BluetoothAddress).Completed = async (asyncInfo, asyncStatus) => { if (asyncStatus == AsyncStatus.Completed) { if (asyncInfo.GetResults() == null) { //this.MessAgeChanged(MsgType.NotifyTxt, "没有得到结果集"); } else { BluetoothLEDevice currentDevice = asyncInfo.GetResults(); if (currentDevice.Name.StartsWith("Bluetooth")) { return; } Boolean contain = false; foreach (string deviceId in DevicesList)//过滤重复的设备 { if (deviceId == currentDevice.DeviceId) { contain = true; break; } } string tmpMAC = ""; byte[] _Bytes1 = BitConverter.GetBytes(currentDevice.BluetoothAddress); Array.Reverse(_Bytes1); tmpMAC = BitConverter.ToString(_Bytes1, 2, 6).Replace('-', ':').ToLower(); if (!contain) { this.DevicesList.Add(currentDevice.DeviceId); this.MessageChanged(MsgType.NotifyTxt, "发现设备:" + currentDevice.Name + " address:" + tmpMAC); this.DevicewatcherChanged(MsgType.BleDevice, currentDevice); // currentDevice = null; } /* if (CurrentDevice == null && CurrentDeviceMAC == tmpMAC) {//自动重连 CurrentDevice = currentDevice; //获取服务 this.CurrentDevice.GetGattServicesAsync().Completed = (asynServe, asyncStatu) => { if (asyncStatu == AsyncStatus.Completed) { var sevices = asynServe.GetResults().Services; foreach (GattDeviceService ser in sevices) { if (ser.Uuid.ToString() == Utility.UUID_SERVER) { this.CurrentService = ser; break; } } } else { this.CurrentDevice = null; } }; if (this.CurrentService != null) { //获取特征值 this.CurrentService.GetCharacteristicsAsync().Completed = (asynChara, asyncStatu) => { if (asyncStatu == AsyncStatus.Completed) { var chara = asynChara.GetResults().Characteristics; foreach (GattCharacteristic c in chara) { if (c.Uuid.ToString() == Utility.UUID_Name) { this.CurrentNameCharacteristic = c; break; } } } }; } else {//删除设备 this.CurrentDevice = null; this.CurrentService = null; return; } if (this.CurrentNameCharacteristic != null) { string msg = "已重连设备连接设备<" + this.CurrentDeviceMAC + "> .."; this.MessageChanged(MsgType.NotifyTxt, msg); } } */ } } }; } /// <summary> /// 停止搜索 /// </summary> public void StopBleDeviceWatcher() { if (deviceWatcher != null) this.deviceWatcher.Stop(); if (watcher != null && watcher.Status == BluetoothLEAdvertisementWatcherStatus.Started) watcher.Stop(); } /// <summary> /// 获取发现的蓝牙设备 /// </summary> /// <param name="sender"></param> /// <param name="args"></param> private void DeviceWatcher_Added(DeviceWatcher sender, DeviceInformation args) { this.MessageChanged(MsgType.NotifyTxt, "发现设备:" + args.Id); this.Matching(args.Id, args); } private void DeviceWatcher_Updated(DeviceWatcher sender, DeviceInformationUpdate args) { } /// <summary> /// 停止搜索蓝牙设备 /// </summary> /// <param name="sender"></param> /// <param name="args"></param> private void DeviceWatcher_Stopped(DeviceWatcher sender, object args) { string msg = "自动发现设备停止"; this.MessageChanged(MsgType.NotifyTxt, msg); } /// <summary> /// 匹配 /// </summary> /// <param name="device"></param> public void StartMatching(BluetoothLEDevice device) { // Dispose(false); this.CurrentDevice = device; } /// <summary> /// 获取蓝牙服务 /// </summary> public async void FindService() { /*var gattServices = this.CurrentDevice.GattServices; foreach(GattDeviceService ser in gattServices) { this.GattDeviceServiceAdded(ser); }*/ this.CurrentDevice.GetGattServicesAsync().Completed = async (asyncInfo, asyncStatu) => { if (asyncStatu == AsyncStatus.Completed) { var sevices = asyncInfo.GetResults().Services; foreach (GattDeviceService ser in sevices) { this.GattDeviceServiceAdded(ser); // FindCharacteristic(ser); } } }; } public async void FindCharacteristic(GattDeviceService gattDeviceService) { /* this.CurrentService = gattDeviceService; foreach(var c in gattDeviceService.GetAllCharacteristics()) { this.CharacteristicAdded(c); }*/ gattDeviceService.GetCharacteristicsAsync().Completed = async (asyncInfo, asyncStatu) => { if (asyncStatu == AsyncStatus.Completed) { var chara = asyncInfo.GetResults().Characteristics; foreach (GattCharacteristic c in chara) { this.CharacteristicAdded(c); } } }; } /// <summary> /// 获取操作 /// </summary> /// <param name="gattCharacteristic"></param> /// <returns></returns> public async Task SetOpteron(GattCharacteristic gattCharacteristic) { if (gattCharacteristic.CharacteristicProperties == GattCharacteristicProperties.WriteWithoutResponse) { this.CurrentWriteCharacteristic = gattCharacteristic; } if (gattCharacteristic.CharacteristicProperties == GattCharacteristicProperties.Notify) { this.CurrentNotifyCharacteristic = gattCharacteristic; this.CurrentNotifyCharacteristic.ProtectionLevel = GattProtectionLevel.Plain; this.CurrentNotifyCharacteristic.ValueChanged += Characteristic_ValueChanged; await this.EnableNotifications(CurrentNotifyCharacteristic); } if (gattCharacteristic.CharacteristicProperties == (GattCharacteristicProperties.Read | GattCharacteristicProperties.Write)) { this.CurrentNameCharacteristic = gattCharacteristic; } if (!IsConnect) this.Connect(); } bool IsConnect = false; private async Task Connect() { IsConnect = true; byte[] _Bytes1 = BitConverter.GetBytes(this.CurrentDevice.BluetoothAddress); Array.Reverse(_Bytes1); this.CurrentDeviceMAC = BitConverter.ToString(_Bytes1, 2, 6).Replace('-', ':').ToLower(); string msg = "正在连接设备<" + this.CurrentDeviceMAC + "> .."; this.MessageChanged(MsgType.NotifyTxt, msg); this.CurrentDevice.ConnectionStatusChanged += CurrentDevice_ConnectionStatusChanged; } private void CurrentDevice_ConnectionStatusChanged(BluetoothLEDevice sender, object args) { if (sender.ConnectionStatus == BluetoothConnectionStatus.Disconnected && CurrentDeviceMAC != null) { this.DevicesList.Remove(sender.DeviceId); string msg = "设备已断开"; MessageChanged(MsgType.NotifyTxt, msg); // if(!asyncLock) { asyncLock = true; this.CurrentDevice?.Dispose(); this.CurrentDevice = null; this.CurrentNotifyCharacteristic = null; this.CurrentWriteCharacteristic = null; this.CurrentNameCharacteristic = null; // SelectDeviceFromIdAsync(CurrentDeviceMAC); } } else { string msg = "设备已连接"; MessageChanged(MsgType.NotifyTxt, msg); } } /// <summary> /// 搜索到的蓝牙设备 /// </summary> /// <param name="id"></param> /// <returns></returns> private async Task Matching(string id, DeviceInformation args = null) { try { BluetoothLEDevice.FromIdAsync(id).Completed = async (asyncInfo, asyncStatus) => { if (asyncStatus == AsyncStatus.Completed) { BluetoothLEDevice bleDevice = asyncInfo.GetResults(); if (bleDevice.Name.StartsWith("Bluetooth")) { return; } if (CurrentDeviceMAC != null) {//自动重连 CurrentDevice = bleDevice; //获取服务 this.CurrentDevice.GetGattServicesAsync().Completed = async (asynServe, asyncStatu) => { if (asyncStatu == AsyncStatus.Completed) { var sevices = asynServe.GetResults().Services; foreach (GattDeviceService ser in sevices) { if (ser.Uuid.ToString() == Utility.UUID_SERVER) { this.CurrentService = ser; break; } } } }; if (this.CurrentService != null) { //获取特征值 this.CurrentService.GetCharacteristicsAsync().Completed = async (asynChara, asyncStatu) => { if (asyncStatu == AsyncStatus.Completed) { var chara = asynChara.GetResults().Characteristics; foreach (GattCharacteristic c in chara) { if (c.Uuid.ToString() == Utility.UUID_Name) { this.CurrentNameCharacteristic = c; break; } } } }; } if (this.CurrentNameCharacteristic != null) { string msg = "已重连设备连接设备<" + this.CurrentDeviceMAC + "> .."; this.MessageChanged(MsgType.NotifyTxt, msg); } } string tmp = this.DevicesList.Where(p => p == bleDevice.DeviceId).FirstOrDefault(); if (tmp == null) {//没有添加过 this.DevicesList.Add(bleDevice.DeviceId); this.DevicewatcherChanged(MsgType.BleDevice, bleDevice); bleDevice = null; } } }; } catch (Exception e) { string msg = "没有发现设备" + e.ToString(); this.MessageChanged(MsgType.NotifyTxt, msg); this.StopBleDeviceWatcher(); } } public void DisConnect() { /* GattSession.FromDeviceIdAsync(CurrentDevice.BluetoothDeviceId).Completed = async (asyncInfo, asyncStatus) => { if (asyncStatus == AsyncStatus.Completed) { GattSession session = asyncInfo.GetResults(); if(session != null) { session.Dispose(); this.MessageChanged(MsgType.NotifyTxt, "主动断开session"); Dispose(); } } };*/ Dispose(); } /// <summary> /// 主动断开连接 /// </summary> public void Dispose(bool IsTip = true) { IsConnect = false; CurrentDeviceMAC = null; CurrentService?.Dispose(); if (CurrentDevice != null) CurrentDevice.ConnectionStatusChanged -= CurrentDevice_ConnectionStatusChanged; CurrentDevice?.Dispose(); CurrentDevice = null; CurrentService = null; CurrentNameCharacteristic = null; CurrentWriteCharacteristic = null; CurrentNotifyCharacteristic = null; // if(IsTip) this.MessageChanged(MsgType.NotifyTxt, "主动断开连接"); // else {//清除蓝牙列表 this.DevicesList.Clear(); } } /// <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 bluetoothAdapter = asyncInfo.GetResults(); // ulong 转为byte数组 byte[] _Bytes1 = BitConverter.GetBytes(bluetoothAdapter.BluetoothAddress); Array.Reverse(_Bytes1); string macAddress = BitConverter.ToString(_Bytes1, 2, 6).Replace('-', ':').ToLower(); string Id = "BluetoothLe#BluetoothLe" + macAddress + "-" + MAC; await Matching(Id); } }; } /// <summary> /// 设置特征对象为接收通知对象 /// </summary> /// <param name="characteristic"></param> /// <returns></returns> public async Task EnableNotifications(GattCharacteristic characteristic) { string msg = "收通知对象=" + CurrentDevice.ConnectionStatus; this.MessageChanged(MsgType.NotifyTxt, msg); characteristic.WriteClientCharacteristicConfigurationDescriptorAsync(CHARACTERSITIC_NOTIFICATION_TYPE).Completed = async (asyncInfo, asyncStatus) => { if (asyncStatus == AsyncStatus.Completed) { GattCommunicationStatus status = asyncInfo.GetResults(); if (status == GattCommunicationStatus.Unreachable) { msg = "设备不可用"; this.MessageChanged(MsgType.NotifyTxt, msg); if (CurrentNotifyCharacteristic != null && !asyncLock) { await this.EnableNotifications(CurrentNotifyCharacteristic); } } asyncLock = false; msg = "设备连接状态" + status; this.MessageChanged(MsgType.NotifyTxt, msg); } }; } /// <summary> /// 接受到蓝牙数据 /// </summary> private void Characteristic_ValueChanged(GattCharacteristic sender, GattValueChangedEventArgs args) { byte[] data; CryptographicBuffer.CopyToByteArray(args.CharacteristicValue, out data); string str = BitConverter.ToString(data); this.MessageChanged(MsgType.BleRecData, str, data); } /// <summary> /// 发送数据接口 /// </summary> /// <returns></returns> public async Task Write(byte[] data) { if (CurrentWriteCharacteristic != null) { CurrentWriteCharacteristic.WriteValueAsync(CryptographicBuffer.CreateFromByteArray(data), GattWriteOption.WriteWithResponse); string str = "发送数据:" + BitConverter.ToString(data); this.MessageChanged(MsgType.BleSendData, str, data); } } /// <summary> /// 发送数据接口 /// </summary> /// <returns></returns> public async Task WriteName(byte[] data) { if (CurrentNameCharacteristic != null) { CurrentNameCharacteristic.WriteValueAsync(CryptographicBuffer.CreateFromByteArray(data), GattWriteOption.WriteWithResponse); string str = "发送数据:" + BitConverter.ToString(data); this.MessageChanged(MsgType.BleSendData, str, data); } } } }