You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

741 lines
27 KiB
C#

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