在Windows 10下使用C#完成低功耗蓝牙通信(BLE)

13 篇文章 0 订阅

1.VS2017新建C#【控制台应用】项目,项目名为ConsoleApp2

2.编辑项目文件ConsoleApp2.csproj,添加如下代码并保存,这样才能添加下一步的引用。

注意:如果在项目中添加了文件导致项目文件被覆盖,可能需要重新添加此代码。

<TargetPlatformVersion>10.0</TargetPlatformVersion>

3.添加Universal Windows下的5个引用

4.添加windows.windmd引用(位于C:\Program Files (x86)\Windows Kits\10\UnionMetadata\10.0.17763.0\Facade\windows.winmd)

如果不添加windows.windmd将报以下错误

5.添加BleCore类

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.Foundation;
using Windows.Security.Cryptography;

namespace ConsoleApp2
{
    class BleCore
    {
        private bool asyncLock = false;

        /// <summary>
        /// 当前连接的服务
        /// </summary>
        public GattDeviceService CurrentService { get; private set; }

        /// <summary>
        /// 当前连接的蓝牙设备
        /// </summary>
        public BluetoothLEDevice CurrentDevice { get; private set; }

        /// <summary>
        /// 写特征对象
        /// </summary>
        public GattCharacteristic CurrentWriteCharacteristic { get; private set; }

        /// <summary>
        /// 通知特征对象
        /// </summary>
        public GattCharacteristic CurrentNotifyCharacteristic { get; private set; }

        /// <summary>
        /// 存储检测到的设备
        /// </summary>
        public List<BluetoothLEDevice> DeviceList { get; private set; }

        /// <summary>
        /// 特性通知类型通知启用
        /// </summary>
        private const GattClientCharacteristicConfigurationDescriptorValue CHARACTERISTIC_NOTIFICATION_TYPE = GattClientCharacteristicConfigurationDescriptorValue.Notify;

        /// <summary>
        /// 定义搜索蓝牙设备委托
        /// </summary>
        public delegate void DeviceWatcherChangedEvent(BluetoothLEDevice bluetoothLEDevice);

        /// <summary>
        /// 搜索蓝牙事件
        /// </summary>
        public event DeviceWatcherChangedEvent DeviceWatcherChanged;

        /// <summary>
        /// 获取服务委托
        /// </summary>
        public delegate void CharacteristicFinishEvent(int size);

        /// <summary>
        /// 获取服务事件
        /// </summary>
        public event CharacteristicFinishEvent CharacteristicFinish;

        /// <summary>
        /// 获取特征委托
        /// </summary>
        public delegate void CharacteristicAddedEvent(GattCharacteristic gattCharacteristic);

        /// <summary>
        /// 获取特征事件
        /// </summary>
        public event CharacteristicAddedEvent CharacteristicAdded;

        /// <summary>
        /// 接受数据委托
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="data"></param>
        public delegate void RecDataEvent(GattCharacteristic sender, byte[] data);

        /// <summary>
        /// 接受数据事件
        /// </summary>
        public event RecDataEvent Recdate;

        /// <summary>
        /// 当前连接的蓝牙Mac
        /// </summary>
        private string CurrentDeviceMAC { get; set; }

        private BluetoothLEAdvertisementWatcher Watcher = null;

        public BleCore()
        {
            DeviceList = new List<BluetoothLEDevice>();
        }

        /// <summary>
        /// 搜索蓝牙设备
        /// </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;

            // 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();

            Console.WriteLine("搜索设备中..");
        }

        /// <summary>
        /// 停止搜索蓝牙
        /// </summary>
        public void StopBleDeviceWatcher()
        {
            if (Watcher != null)
                this.Watcher.Stop();
        }

        /// <summary>
        /// 主动断开连接
        /// </summary>
        /// <returns></returns>
        public void Dispose()
        {
            CurrentDeviceMAC = null;
            CurrentService?.Dispose();
            CurrentDevice?.Dispose();
            CurrentDevice = null;
            CurrentService = null;
            CurrentWriteCharacteristic = null;
            CurrentNotifyCharacteristic = null;
            Console.WriteLine("主动断开连接");
        }

        /// <summary>
        /// 匹配
        /// </summary>
        /// <param name="Device"></param>
        public void StartMatching(BluetoothLEDevice Device)
        {
            this.CurrentDevice = Device;
        }

        /// <summary>
        /// 发送数据接口
        /// </summary>
        /// <returns></returns>
        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);
                    }
                };
            }

        }

        /// 获取蓝牙服务
        /// </summary>
        public void FindService()
        {
            this.CurrentDevice.GetGattServicesAsync(BluetoothCacheMode.Uncached).Completed = (asyncInfo, asyncStatus) =>
            {
                if (asyncStatus == AsyncStatus.Completed)
                {
                    var services = asyncInfo.GetResults().Services;

                    int i = 1;
                    foreach (GattDeviceService ser in services)
                    {
                        Console.WriteLine(string.Format("\n-----{0}--------Service:{1}-------------", i++, ser.Uuid));
                        FindCharacteristic(ser);
                    }
                    CharacteristicFinish?.Invoke(services.Count);
                }
            };

        }

        /// <summary>
        /// 按MAC地址直接组装设备ID查找设备
        /// </summary>
        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);//ulong转换为byte数组
                    Array.Reverse(_Bytes1);
                    string macAddress = BitConverter.ToString(_Bytes1, 2, 6).Replace('-', ':').ToLower();
                    string Id = "BluetoothLE#BluetoothLE" + macAddress + "-" + MAC;
                    Matching(Id);
                }
            };
        }

        /// <summary>
        /// 获取操作
        /// </summary>
        /// <returns></returns>
        public void SetOpteron(GattCharacteristic gattCharacteristic)
        {
            byte[] _Bytes1 = BitConverter.GetBytes(this.CurrentDevice.BluetoothAddress);
            Array.Reverse(_Bytes1);
            this.CurrentDeviceMAC = BitConverter.ToString(_Bytes1, 2, 6).Replace('-', ':').ToLower();

            if (gattCharacteristic.CharacteristicProperties.HasFlag(GattCharacteristicProperties.Read))
            {
                // This characteristic supports reading from it.
            }
            if (gattCharacteristic.CharacteristicProperties.HasFlag(GattCharacteristicProperties.Write))
            {
                this.CurrentWriteCharacteristic = gattCharacteristic;
            }

            if (gattCharacteristic.CharacteristicProperties.HasFlag(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)
                    {
                        //Console.WriteLine("没有得到结果集");
                    }
                    else
                    {
                        BluetoothLEDevice currentDevice = asyncInfo.GetResults();

                        if (DeviceList.FindIndex((x) => { return x.Name.Equals(currentDevice.Name); }) < 0)
                        {
                            this.DeviceList.Add(currentDevice);
                            DeviceWatcherChanged?.Invoke(currentDevice);
                        }

                    }

                }
            };
        }

        /// <summary>
        /// 获取特性
        /// </summary>
        private void FindCharacteristic(GattDeviceService gattDeviceService)
        {
            this.CurrentService = gattDeviceService;

            this.CurrentService.GetCharacteristicsAsync(BluetoothCacheMode.Uncached).Completed = (asyncInfo, asyncStatus) =>
            {
                if (asyncStatus == AsyncStatus.Completed)
                {
                    var Chas = asyncInfo.GetResults().Characteristics;
                    foreach (var c in Chas)
                    {
                        this.CharacteristicAdded?.Invoke(c);
                    }

                }
            };
        }

        /// <summary>
        /// 搜索到的蓝牙设备
        /// </summary>
        /// <returns></returns>
        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 == Windows.Foundation.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("设备已断开");
                    //this.CurrentDevice?.Dispose();
                    //this.CurrentDevice = null;
                    //CurrentService = null;
                    //CurrentWriteCharacteristic = null;
                    //CurrentNotifyCharacteristic = null;
                    //SelectDeviceFromIdAsync(CurrentDeviceMAC);
                }
            }
            else
            {
                if (!asyncLock)
                {
                    asyncLock = true;
                    Console.WriteLine("设备已连接");
                }
            }
        }

        /// <summary>
        /// 设置特征对象为接收通知对象
        /// </summary>
        /// <param name="characteristic"></param>
        /// <returns></returns>
        private void EnableNotifications(GattCharacteristic characteristic)
        {
            Console.WriteLine("     开启Notify:" + 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);
                }
            };
        }

        /// <summary>
        /// 接受到蓝牙数据
        /// </summary>
        private void Characteristic_ValueChanged(GattCharacteristic sender, GattValueChangedEventArgs args)
        {
            byte[] data;
            CryptographicBuffer.CopyToByteArray(args.CharacteristicValue, out data);
            Recdate?.Invoke(sender, data);
        }

    }
}

5.编写Program.cs

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;

namespace ConsoleApp2
{
    class Program
    {
        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(
                "   Characteristic:[{0}]  UUID:[{1}]",
                gatt.CharacteristicProperties.ToString(),
                gatt.Uuid);
            characteristics.Add(gatt);

            bleCore.SetOpteron(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 + ">");

            //指定一个对象,使用下面方法去连接设备
            if (currentDevice.Name == "train_gun")
            {
                Console.WriteLine("连接:<" + currentDevice.Name + ">  address:<" + address + ">");

                ConnectDevice(currentDevice);
            }

        }

        private static void ConnectDevice(BluetoothLEDevice Device)
        {
            characteristics.Clear();
            bleCore.StopBleDeviceWatcher();
            bleCore.StartMatching(Device);
            bleCore.FindService();
        }
    }
}

编译运行,结果如下

以下是使用C#实现低功耗蓝牙BLE数据读写功能的示例代码: ```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.GenericAttributeProfile; using Windows.Devices.Enumeration; namespace BleCommunication { class Program { static void Main(string[] args) { var task = MainAsync(args); task.Wait(); } static async Task MainAsync(string[] args) { // 查询所有蓝牙设备 string selector = BluetoothLEDevice.GetDeviceSelector(); var devices = await DeviceInformation.FindAllAsync(selector); // 过滤出指定名称的设备 var device = devices.FirstOrDefault(d => d.Name == "My BLE Device"); if (device != null) { // 连接设备 var bleDevice = await BluetoothLEDevice.FromIdAsync(device.Id); // 查询服务 var serviceUuid = Guid.Parse("0000fff0-0000-1000-8000-00805f9b34fb"); var serviceResult = await bleDevice.GetGattServicesForUuidAsync(serviceUuid); var service = serviceResult.Services.FirstOrDefault(); if (service != null) { // 查询特征值 var characteristicUuid = Guid.Parse("0000fff1-0000-1000-8000-00805f9b34fb"); var characteristicResult = await service.GetCharacteristicsForUuidAsync(characteristicUuid); var characteristic = characteristicResult.Characteristics.FirstOrDefault(); if (characteristic != null) { // 订阅特征值通知 var status = await characteristic.WriteClientCharacteristicConfigurationDescriptorAsync(GattClientCharacteristicConfigurationDescriptorValue.Notify); if (status == GattCommunicationStatus.Success) { characteristic.ValueChanged += (sender, args) => { // 处理接收到的数据 var data = args.CharacteristicValue.ToArray(); Console.WriteLine("Received data: {0}", BitConverter.ToString(data)); }; // 发送数据 var dataToSend = new byte[] { 0x01, 0x02, 0x03 }; var writeStatus = await characteristic.WriteValueAsync(dataToSend.AsBuffer()); if (writeStatus == GattCommunicationStatus.Success) { Console.WriteLine("Data sent successfully."); } else { Console.WriteLine("Failed to send data."); } } else { Console.WriteLine("Failed to subscribe to notifications."); } } else { Console.WriteLine("Characteristic not found."); } } else { Console.WriteLine("Service not found."); } } else { Console.WriteLine("Device not found."); } Console.ReadLine(); } } } ``` 请注意,此示例仅用于演示BLE通信的基本过程。在实际应用中,您需要根据设备的具体规格和特性来编写更复杂的代码。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值