class BleCore
{
private bool asyncLock = false;
public GattDeviceService CurrentService { get; private set; }
public BluetoothLEDevice CurrentDevice { get; private set; }
public GattCharacteristic CurrentWriteCharacteristic { get; private set; }
public GattCharacteristic CurrentNotifyCharacteristic { get; private set; }
public List<BluetoothLEDevice> DeviceList { get; private set; }
private const GattClientCharacteristicConfigurationDescriptorValue CHARACTERISTIC_NOTIFICATION_TYPE = GattClientCharacteristicConfigurationDescriptorValue.Notify;
public delegate void DeviceWatcherChangedEvent(BluetoothLEDevice bluetoothLEDevice);
public event DeviceWatcherChangedEvent DeviceWatcherChanged;
public delegate void CharacteristicFinishEvent(int size);
public event CharacteristicFinishEvent CharacteristicFinish;
public delegate void CharacteristicAddedEvent(GattCharacteristic gattCharacteristic);
public event CharacteristicAddedEvent CharacteristicAdded;
public delegate void RecDataEvent(GattCharacteristic sender, byte[] data);
public event RecDataEvent Recdate;
private string CurrentDeviceMAC { get; set; }
private BluetoothLEAdvertisementWatcher Watcher = null;
public BleCore()
{
DeviceList = new List<BluetoothLEDevice>();
}
public void StartBleDeviceWatcher()
{
Watcher = new BluetoothLEAdvertisementWatcher();
Watcher.ScanningMode = BluetoothLEScanningMode.Active;
Watcher.SignalStrengthFilter.InRangeThresholdInDBm = -80;
Watcher.SignalStrengthFilter.OutOfRangeThresholdInDBm = -90;
Watcher.Received += OnAdvertisementReceived;
Watcher.SignalStrengthFilter.OutOfRangeTimeout = TimeSpan.FromMilliseconds(5000);
Watcher.SignalStrengthFilter.SamplingInterval = TimeSpan.FromMilliseconds(2000);
Watcher.Start();
Console.WriteLine("自动发现设备中..");
}
public void StopBleDeviceWatcher()
{
if (Watcher != null)
this.Watcher.Stop();
}
public void Dispose()
{
CurrentDeviceMAC = null;
CurrentService?.Dispose();
CurrentDevice?.Dispose();
CurrentDevice = null;
CurrentService = null;
CurrentWriteCharacteristic = null;
CurrentNotifyCharacteristic = null;
Console.WriteLine("主动断开连接");
}
public void StartMatching(BluetoothLEDevice Device)
{
this.CurrentDevice = Device;
}
public void Write(byte[] data)
{
if (CurrentWriteCharacteristic != null)
{
CurrentWriteCharacteristic.WriteValueAsync(CryptographicBuffer.CreateFromByteArray(data), GattWriteOption.WriteWithResponse).Completed = (asyncInfo, asyncStatus) =>
{
if (asyncStatus == AsyncStatus.Completed)
{
GattCommunicationStatus a = asyncInfo.GetResults();
Console.WriteLine("发送数据:" + BitConverter.ToString(data) + " State : " + a);
}
};
}
}
public void FindService()
{
this.CurrentDevice.GetGattServicesAsync().Completed = (asyncInfo, asyncStatus) =>
{
if (asyncStatus == AsyncStatus.Completed)
{
var services = asyncInfo.GetResults().Services;
Console.WriteLine("GattServices size=" + services.Count);
foreach (GattDeviceService ser in services)
{
FindCharacteristic(ser);
}
CharacteristicFinish?.Invoke(services.Count);
}
};
}
public void SelectDeviceFromIdAsync(string MAC)
{
CurrentDeviceMAC = MAC;
CurrentDevice = null;
BluetoothAdapter.GetDefaultAsync().Completed = (asyncInfo, asyncStatus) =>
{
if (asyncStatus == AsyncStatus.Completed)
{
BluetoothAdapter mBluetoothAdapter = asyncInfo.GetResults();
byte[] _Bytes1 = BitConverter.GetBytes(mBluetoothAdapter.BluetoothAddress);
Array.Reverse(_Bytes1);
string macAddress = BitConverter.ToString(_Bytes1, 2, 6).Replace('-', ':').ToLower();
string Id = "BluetoothLE#BluetoothLE" + macAddress + "-" + MAC;
Matching(Id);
}
};
}
public void SetOpteron(GattCharacteristic gattCharacteristic)
{
byte[] _Bytes1 = BitConverter.GetBytes(this.CurrentDevice.BluetoothAddress);
Array.Reverse(_Bytes1);
this.CurrentDeviceMAC = BitConverter.ToString(_Bytes1, 2, 6).Replace('-', ':').ToLower();
string msg = "正在连接设备<" + this.CurrentDeviceMAC + ">..";
Console.WriteLine(msg);
if (gattCharacteristic.CharacteristicProperties == GattCharacteristicProperties.Write)
{
this.CurrentWriteCharacteristic = gattCharacteristic;
}
if (gattCharacteristic.CharacteristicProperties == GattCharacteristicProperties.Notify)
{
this.CurrentNotifyCharacteristic = gattCharacteristic;
}
if ((uint)gattCharacteristic.CharacteristicProperties == 26)
{
}
if (gattCharacteristic.CharacteristicProperties == (GattCharacteristicProperties.Write | GattCharacteristicProperties.Notify))
{
this.CurrentWriteCharacteristic = gattCharacteristic;
this.CurrentNotifyCharacteristic = gattCharacteristic;
this.CurrentNotifyCharacteristic.ProtectionLevel = GattProtectionLevel.Plain;
this.CurrentNotifyCharacteristic.ValueChanged += Characteristic_ValueChanged;
this.CurrentDevice.ConnectionStatusChanged += this.CurrentDevice_ConnectionStatusChanged;
this.EnableNotifications(CurrentNotifyCharacteristic);
}
}
private void OnAdvertisementReceived(BluetoothLEAdvertisementWatcher watcher, BluetoothLEAdvertisementReceivedEventArgs eventArgs)
{
BluetoothLEDevice.FromBluetoothAddressAsync(eventArgs.BluetoothAddress).Completed = (asyncInfo, asyncStatus) =>
{
if (asyncStatus == AsyncStatus.Completed)
{
if (asyncInfo.GetResults() == null)
{
}
else
{
BluetoothLEDevice currentDevice = asyncInfo.GetResults();
if (DeviceList.FindIndex((x) => { return x.Name.Equals(currentDevice.Name); }) < 0)
{
this.DeviceList.Add(currentDevice);
DeviceWatcherChanged?.Invoke(currentDevice);
}
}
}
};
}
private void FindCharacteristic(GattDeviceService gattDeviceService)
{
this.CurrentService = gattDeviceService;
this.CurrentService.GetCharacteristicsAsync().Completed = (asyncInfo, asyncStatus) =>
{
if (asyncStatus == AsyncStatus.Completed)
{
var services = asyncInfo.GetResults().Characteristics;
foreach (var c in services)
{
this.CharacteristicAdded?.Invoke(c);
}
}
};
}
private void Matching(string Id)
{
try
{
BluetoothLEDevice.FromIdAsync(Id).Completed = (asyncInfo, asyncStatus) =>
{
if (asyncStatus == AsyncStatus.Completed)
{
BluetoothLEDevice bleDevice = asyncInfo.GetResults();
this.DeviceList.Add(bleDevice);
Console.WriteLine(bleDevice);
}
if (asyncStatus == AsyncStatus.Started)
{
Console.WriteLine(asyncStatus.ToString());
}
if (asyncStatus == AsyncStatus.Canceled)
{
Console.WriteLine(asyncStatus.ToString());
}
if (asyncStatus == AsyncStatus.Error)
{
Console.WriteLine(asyncStatus.ToString());
}
};
}
catch (Exception e)
{
string msg = "没有发现设备" + e.ToString();
Console.WriteLine(msg);
this.StartBleDeviceWatcher();
}
}
private void CurrentDevice_ConnectionStatusChanged(BluetoothLEDevice sender, object args)
{
if (sender.ConnectionStatus == BluetoothConnectionStatus.Disconnected && CurrentDeviceMAC != null)
{
if (!asyncLock)
{
asyncLock = true;
Console.WriteLine("设备已断开");
}
}
else
{
if (!asyncLock)
{
asyncLock = true;
Console.WriteLine("设备已连接");
}
}
}
private void EnableNotifications(GattCharacteristic characteristic)
{
Console.WriteLine("收通知对象=" + CurrentDevice.Name + ":" + CurrentDevice.ConnectionStatus);
characteristic.WriteClientCharacteristicConfigurationDescriptorAsync(CHARACTERISTIC_NOTIFICATION_TYPE).Completed = (asyncInfo, asyncStatus) =>
{
if (asyncStatus == AsyncStatus.Completed)
{
GattCommunicationStatus status = asyncInfo.GetResults();
if (status == GattCommunicationStatus.Unreachable)
{
Console.WriteLine("设备不可用");
if (CurrentNotifyCharacteristic != null && !asyncLock)
{
this.EnableNotifications(CurrentNotifyCharacteristic);
}
return;
}
asyncLock = false;
Console.WriteLine("设备连接状态" + status);
}
};
}
private void Characteristic_ValueChanged(GattCharacteristic sender, GattValueChangedEventArgs args)
{
byte[] data;
CryptographicBuffer.CopyToByteArray(args.CharacteristicValue, out data);
Recdate?.Invoke(sender, data);
}
}
class Progame
{
private static BleCore bleCore = null;
private static List<GattCharacteristic> characteristics = new List<GattCharacteristic>();
public static void Main(string[] args)
{
bleCore = new BleCore();
bleCore.DeviceWatcherChanged += DeviceWatcherChanged;
bleCore.CharacteristicAdded += CharacteristicAdded;
bleCore.CharacteristicFinish += CharacteristicFinish;
bleCore.Recdate += Recdata;
bleCore.StartBleDeviceWatcher();
Console.ReadKey(true);
bleCore.Dispose();
bleCore = null;
}
private static void CharacteristicFinish(int size)
{
if (size <= 0)
{
Console.WriteLine("设备未连上");
return;
}
}
private static void Recdata(GattCharacteristic sender, byte[] data)
{
string str = BitConverter.ToString(data);
Console.WriteLine(sender.Uuid + " " + str);
}
private static void CharacteristicAdded(GattCharacteristic gatt)
{
Console.WriteLine(
"handle:[0x{0}] char properties:[{1}] UUID:[{2}]",
gatt.AttributeHandle.ToString("X4"),
gatt.CharacteristicProperties.ToString(),
gatt.Uuid);
characteristics.Add(gatt);
}
private static void DeviceWatcherChanged(BluetoothLEDevice currentDevice)
{
byte[] _Bytes1 = BitConverter.GetBytes(currentDevice.BluetoothAddress);
Array.Reverse(_Bytes1);
string address = BitConverter.ToString(_Bytes1, 2, 6).Replace('-', ':').ToLower();
Console.WriteLine("发现设备:<" + currentDevice.Name + "> address:<" + address + ">");
}
private static void ConnectDevice(BluetoothLEDevice Device)
{
characteristics.Clear();
bleCore.StopBleDeviceWatcher();
bleCore.StartMatching(Device);
bleCore.FindService();
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix