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