|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using Windows.Devices.Bluetooth;
|
|
|
|
|
using Windows.Devices.Bluetooth.GenericAttributeProfile;
|
|
|
|
|
using Windows.Devices.Enumeration;
|
|
|
|
|
using Windows.Security.Cryptography;
|
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
|
|
|
|
|
namespace BluetoothLibrary
|
|
|
|
|
{
|
|
|
|
|
public enum BlueStatus
|
|
|
|
|
{
|
|
|
|
|
DisConnected, // 未连接
|
|
|
|
|
Connecting, // 正在连接
|
|
|
|
|
Connected // 已连接
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
public enum MsgType
|
|
|
|
|
{
|
|
|
|
|
NotifyTxt,
|
|
|
|
|
BleDevice,
|
|
|
|
|
BleSendData,
|
|
|
|
|
BleRecData,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class BleCore
|
|
|
|
|
{
|
|
|
|
|
private BluetoothLEDevice _currentDevice;
|
|
|
|
|
private GattDeviceService _currentService;
|
|
|
|
|
private GattCharacteristic _writeCharacteristic;
|
|
|
|
|
private GattCharacteristic _notifyCharacteristic;
|
|
|
|
|
private List<BluetoothLEDevice> _discoveredDevices = new List<BluetoothLEDevice>();
|
|
|
|
|
|
|
|
|
|
public event Action<MsgType, string, byte[]> MessageChanged;
|
|
|
|
|
|
|
|
|
|
public async Task StartDeviceDiscoveryAsync()
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
string selector = BluetoothLEDevice.GetDeviceSelectorFromPairingState(false);
|
|
|
|
|
var devices = await DeviceInformation.FindAllAsync(selector);
|
|
|
|
|
|
|
|
|
|
foreach (var deviceInfo in devices)
|
|
|
|
|
{
|
|
|
|
|
var device = await BluetoothLEDevice.FromIdAsync(deviceInfo.Id);
|
|
|
|
|
if (device != null && !_discoveredDevices.Any(d => d.DeviceId == device.DeviceId))
|
|
|
|
|
{
|
|
|
|
|
_discoveredDevices.Add(device);
|
|
|
|
|
OnMessageChanged(MsgType.BleDevice, $"Discovered device: {device.Name}", null);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
OnMessageChanged(MsgType.NotifyTxt, $"Error during device discovery: {ex.Message}", null);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task ConnectToDeviceAsync(string deviceId)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
_currentDevice = await BluetoothLEDevice.FromIdAsync(deviceId);
|
|
|
|
|
if (_currentDevice != null)
|
|
|
|
|
{
|
|
|
|
|
_currentDevice.ConnectionStatusChanged += OnConnectionStatusChanged;
|
|
|
|
|
OnMessageChanged(MsgType.NotifyTxt, $"Connecting to device: {_currentDevice.Name}", null);
|
|
|
|
|
await DiscoverServicesAsync();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
OnMessageChanged(MsgType.NotifyTxt, "Device not found", null);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
OnMessageChanged(MsgType.NotifyTxt, $"Error connecting to device: {ex.Message}", null);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async Task DiscoverServicesAsync()
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var services = await _currentDevice.GetGattServicesAsync();
|
|
|
|
|
foreach (var service in services.Services)
|
|
|
|
|
{
|
|
|
|
|
if (service.Uuid.ToString() == "your-service-uuid-here") // Replace with your service UUID
|
|
|
|
|
{
|
|
|
|
|
_currentService = service;
|
|
|
|
|
await DiscoverCharacteristicsAsync();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
OnMessageChanged(MsgType.NotifyTxt, $"Error discovering services: {ex.Message}", null);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async Task DiscoverCharacteristicsAsync()
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var characteristics = await _currentService.GetCharacteristicsAsync();
|
|
|
|
|
foreach (var characteristic in characteristics.Characteristics)
|
|
|
|
|
{
|
|
|
|
|
if (characteristic.Uuid.ToString() == "your-write-uuid-here") // Replace with your write UUID
|
|
|
|
|
{
|
|
|
|
|
_writeCharacteristic = characteristic;
|
|
|
|
|
}
|
|
|
|
|
else if (characteristic.Uuid.ToString() == "your-notify-uuid-here") // Replace with your notify UUID
|
|
|
|
|
{
|
|
|
|
|
_notifyCharacteristic = characteristic;
|
|
|
|
|
await EnableNotificationsAsync(characteristic);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
OnMessageChanged(MsgType.NotifyTxt, $"Error discovering characteristics: {ex.Message}", null);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async Task EnableNotificationsAsync(GattCharacteristic characteristic)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
await characteristic.WriteClientCharacteristicConfigurationDescriptorAsync(
|
|
|
|
|
GattClientCharacteristicConfigurationDescriptorValue.Notify);
|
|
|
|
|
characteristic.ValueChanged += OnCharacteristicValueChanged;
|
|
|
|
|
OnMessageChanged(MsgType.NotifyTxt, "Notifications enabled", null);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
OnMessageChanged(MsgType.NotifyTxt, $"Error enabling notifications: {ex.Message}", null);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OnCharacteristicValueChanged(GattCharacteristic sender, GattValueChangedEventArgs args)
|
|
|
|
|
{
|
|
|
|
|
byte[] data;
|
|
|
|
|
CryptographicBuffer.CopyToByteArray(args.CharacteristicValue, out data);
|
|
|
|
|
OnMessageChanged(MsgType.BleRecData, "Data received", data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task WriteDataAsync(byte[] data)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
if (_writeCharacteristic != null)
|
|
|
|
|
{
|
|
|
|
|
await _writeCharacteristic.WriteValueAsync(CryptographicBuffer.CreateFromByteArray(data));
|
|
|
|
|
OnMessageChanged(MsgType.BleSendData, "Data sent", data);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
OnMessageChanged(MsgType.NotifyTxt, "Write characteristic not found", null);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
OnMessageChanged(MsgType.NotifyTxt, $"Error writing data: {ex.Message}", null);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OnConnectionStatusChanged(BluetoothLEDevice sender, object args)
|
|
|
|
|
{
|
|
|
|
|
if (sender.ConnectionStatus == BluetoothConnectionStatus.Disconnected)
|
|
|
|
|
{
|
|
|
|
|
OnMessageChanged(MsgType.NotifyTxt, "Device disconnected", null);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
OnMessageChanged(MsgType.NotifyTxt, "Device connected", null);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OnMessageChanged(MsgType type, string message, byte[] data)
|
|
|
|
|
{
|
|
|
|
|
MessageChanged?.Invoke(type, message, data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Dispose()
|
|
|
|
|
{
|
|
|
|
|
// 不需要调用 Dispose 方法
|
|
|
|
|
_currentDevice?.Dispose(); // 如果 BluetoothLEDevice 实现了 IDisposable,则可以调用 Dispose
|
|
|
|
|
_currentService = null;
|
|
|
|
|
_writeCharacteristic = null;
|
|
|
|
|
_notifyCharacteristic = null;
|
|
|
|
|
_discoveredDevices.Clear();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|