目录

前言

一、添加引用

二、使用步骤

1.蓝牙通讯类

2.测试界面

3.界面截图

三、注意事项


前言

因为项目需要上位机软件与下位机的蓝牙模块进行通讯,所以上网查阅了很多关于蓝牙通讯的资料。刚开始以为使用现成的库就可以了,像InTheHand,发现无法搜索到蓝牙设备。后来查询资料知道,由于我们的下位机使用的是低功耗蓝牙,很多蓝牙通讯的库不适用低功耗蓝牙。再后来发现,我们的上位机软件是使用WinForm开发的,网上关于WinForm开发低功耗蓝牙的资料很少。整个开发过程挺不容易的,也踩了很多坑,终于可以正常与蓝牙模块进行通讯了。


一、添加引用

需要引用Windows.winmd,不过我发现按照网上说的路径添加引用,程序编译不通过,所以我把Windows.winmd文件和源代码一块打包,在Debug目录下,代码地址见文末。

二、使用步骤

1.蓝牙通讯类

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.Networking;
using Windows.Networking.Proximity;
using Windows.Networking.Sockets;
using Windows.Security.Cryptography;
using Windows.Storage.Streams;namespace Test
{public class BleCore{public enum MsgType{NotifyTxt,BleData,BleDevice}private Boolean asyncLock = false;/// <summary>/// 搜索蓝牙设备对象/// </summary>private Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementWatcher 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 CurrentNotifyCharacteristic { get; set; }/// <summary>/// 特性通知类型通知启用/// </summary>private const GattClientCharacteristicConfigurationDescriptorValue CHARACTERISTIC_NOTIFICATION_TYPE = GattClientCharacteristicConfigurationDescriptorValue.Notify;/// <summary>/// 存储检测到的设备/// </summary>private List<BluetoothLEDevice> DeviceList = new List<BluetoothLEDevice>();/// <summary>/// 定义搜索蓝牙设备委托/// </summary>public delegate void DeviceWatcherChangedEvent(MsgType type, BluetoothLEDevice bluetoothLEDevice);/// <summary>/// 搜索蓝牙事件/// </summary>public event DeviceWatcherChangedEvent DeviceWatcherChanged;/// <summary>/// 获取服务委托/// </summary>public delegate void GattDeviceServiceAddedEvent(GattDeviceService gattDeviceService);/// <summary>/// 获取服务事件/// </summary>public event GattDeviceServiceAddedEvent GattDeviceServiceAdded;/// <summary>/// 获取特征委托/// </summary>public delegate void CharacteristicAddedEvent(GattCharacteristic gattCharacteristic);/// <summary>/// 获取特征事件/// </summary>public event CharacteristicAddedEvent CharacteristicAdded;/// <summary>/// 提示信息委托/// </summary>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>/// 搜索蓝牙设备/// </summary>public void StartBleDeviceWatcher(){this.deviceWatcher = new Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementWatcher();this.deviceWatcher.ScanningMode = Windows.Devices.Bluetooth.Advertisement.BluetoothLEScanningMode.Active;this.deviceWatcher.SignalStrengthFilter.InRangeThresholdInDBm = -80;this.deviceWatcher.SignalStrengthFilter.OutOfRangeThresholdInDBm = -90;this.deviceWatcher.SignalStrengthFilter.OutOfRangeTimeout = TimeSpan.FromMilliseconds(5000);this.deviceWatcher.SignalStrengthFilter.SamplingInterval = TimeSpan.FromMilliseconds(2000);this.deviceWatcher.Received += DeviceWatcher_Received;this.deviceWatcher.Start();}private void DeviceWatcher_Received(Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementWatcher sender, Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementReceivedEventArgs args){BluetoothLEDevice.FromBluetoothAddressAsync(args.BluetoothAddress).Completed = async (asyncInfo, asyncStatus) =>{if (asyncStatus == AsyncStatus.Completed){if (asyncInfo.GetResults() != null){BluetoothLEDevice currentDevice = asyncInfo.GetResults();Boolean contain = false;foreach (BluetoothLEDevice device in DeviceList)//过滤重复的设备{if (device.DeviceId == currentDevice.DeviceId){contain = true;}}if (!contain){this.DeviceList.Add(currentDevice);this.DeviceWatcherChanged(MsgType.BleDevice, currentDevice);}}}};}/// <summary>/// 停止搜索蓝牙/// </summary>public void StopBleDeviceWatcher(){this.deviceWatcher.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);}/// <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){this.CurrentDevice = Device;}/// <summary>/// 获取蓝牙服务/// </summary>public async void FindService(){this.CurrentDevice.GetGattServicesAsync().Completed = async (asyncInfo, asyncStatus) =>{if (asyncStatus == AsyncStatus.Completed){var services = asyncInfo.GetResults().Services;foreach (GattDeviceService ser in services){this.GattDeviceServiceAdded(ser);}}};}/// <summary>/// 获取特性/// </summary>public async void FindCharacteristic(GattDeviceService gattDeviceService){this.CurrentService = gattDeviceService;this.CurrentService.GetCharacteristicsAsync().Completed = async (asyncInfo, asyncStatus) =>{if (asyncStatus == AsyncStatus.Completed){var characteristics = asyncInfo.GetResults().Characteristics;foreach (GattCharacteristic characteristic in characteristics){this.CharacteristicAdded(characteristic);}}};}/// <summary>/// 获取操作/// </summary>/// <returns></returns>public async Task SetOpteron(GattCharacteristic gattCharacteristic){if (gattCharacteristic.CharacteristicProperties == (GattCharacteristicProperties.Write | GattCharacteristicProperties.WriteWithoutResponse)){this.CurrentWriteCharacteristic = gattCharacteristic;}if (gattCharacteristic.CharacteristicProperties == GattCharacteristicProperties.Notify){this.CurrentNotifyCharacteristic = gattCharacteristic;}if ((uint)gattCharacteristic.CharacteristicProperties == 26){ }if (gattCharacteristic.CharacteristicProperties == (GattCharacteristicProperties.Notify | GattCharacteristicProperties.Read | GattCharacteristicProperties.Write)){this.CurrentWriteCharacteristic = gattCharacteristic;this.CurrentNotifyCharacteristic = gattCharacteristic;this.CurrentNotifyCharacteristic.ProtectionLevel = GattProtectionLevel.Plain;this.CurrentNotifyCharacteristic.ValueChanged += Characteristic_ValueChanged;await this.EnableNotifications(CurrentNotifyCharacteristic);}this.Connect();}/// <summary>/// 连接蓝牙/// </summary>/// <returns></returns>private async Task Connect(){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 += this.CurrentDevice_ConnectionStatusChanged;}/// <summary>/// 搜索到的蓝牙设备/// </summary>/// <returns></returns>private async Task Matching(string Id){try{BluetoothLEDevice.FromIdAsync(Id).Completed = async (asyncInfo, asyncStatus) =>{if (asyncStatus == AsyncStatus.Completed){BluetoothLEDevice bleDevice = asyncInfo.GetResults();this.DeviceList.Add(bleDevice);this.DeviceWatcherChanged(MsgType.BleDevice, bleDevice);}};}catch (Exception e){string msg = "没有发现设备" + e.ToString();this.MessAgeChanged(MsgType.NotifyTxt, msg);this.StartBleDeviceWatcher();}}/// <summary>/// 主动断开连接/// </summary>/// <returns></returns>public void Dispose(){CurrentDeviceMAC = null;CurrentService?.Dispose();CurrentDevice?.Dispose();CurrentDevice = null;CurrentService = null;CurrentWriteCharacteristic = null;CurrentNotifyCharacteristic = null;MessAgeChanged(MsgType.NotifyTxt, "主动断开连接");}private void CurrentDevice_ConnectionStatusChanged(BluetoothLEDevice sender, object args){if (sender.ConnectionStatus == BluetoothConnectionStatus.Disconnected && CurrentDeviceMAC != null){string msg = "设备已断开,自动重连";MessAgeChanged(MsgType.NotifyTxt, msg);if (!asyncLock){asyncLock = true;this.CurrentDevice.Dispose();this.CurrentDevice = null;CurrentService = null;CurrentWriteCharacteristic = null;CurrentNotifyCharacteristic = null;SelectDeviceFromIdAsync(CurrentDeviceMAC);}}else{string msg = "设备已连接";MessAgeChanged(MsgType.NotifyTxt, msg);}}/// <summary>/// 按MAC地址直接组装设备ID查找设备/// </summary>public async Task SelectDeviceFromIdAsync(string MAC){CurrentDeviceMAC = MAC;CurrentDevice = null;BluetoothAdapter.GetDefaultAsync().Completed = async (asyncInfo, asyncStatus) =>{if (asyncStatus == AsyncStatus.Completed){BluetoothAdapter mBluetoothAdapter = asyncInfo.GetResults();if (mBluetoothAdapter != null){await Matching(MAC);}else{string msg = "查找连接蓝牙设备异常.";}}};}/// <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(CHARACTERISTIC_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.BleData, 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.BleData, str, data);}}}
}

2.测试界面

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;namespace Test
{public partial class FormTest : Form{BleCore bleCore = new BleCore();/// <summary>/// 存储检测到的设备/// </summary>List<Windows.Devices.Bluetooth.BluetoothLEDevice> DeviceList = new List<Windows.Devices.Bluetooth.BluetoothLEDevice>();/// <summary>/// 当前蓝牙服务列表/// </summary>List<Windows.Devices.Bluetooth.GenericAttributeProfile.GattDeviceService> GattDeviceServices = new List<Windows.Devices.Bluetooth.GenericAttributeProfile.GattDeviceService>();/// <summary>/// 当前蓝牙服务特征列表/// </summary>List<Windows.Devices.Bluetooth.GenericAttributeProfile.GattCharacteristic> GattCharacteristics = new List<Windows.Devices.Bluetooth.GenericAttributeProfile.GattCharacteristic>();public FormTest(){InitializeComponent();CheckForIllegalCrossThreadCalls = false;}private void FormTest_Load(object sender, EventArgs e){this.bleCore.MessAgeChanged += BleCore_MessAgeChanged;this.bleCore.DeviceWatcherChanged += BleCore_DeviceWatcherChanged;this.bleCore.GattDeviceServiceAdded += BleCore_GattDeviceServiceAdded;this.bleCore.CharacteristicAdded += BleCore_CharacteristicAdded;this.Init();}private void Init(){this.btnConnect.Enabled = false;this.btnServer.Enabled = false;this.btnFeatures.Enabled = false;this.btnOpteron.Enabled = false;this.btnReader.Enabled = false;this.btnSend.Enabled = false;}// 异步线程public static void RunAsync(Action action){((Action)(delegate (){action.Invoke();})).BeginInvoke(null, null);}/// <summary>/// 提示消息/// </summary>private void BleCore_MessAgeChanged(BleCore.MsgType type, string message, byte[] data){RunAsync(() =>{this.listboxMessage.Items.Add(message);});}/// <summary>/// 搜索蓝牙设备列表/// </summary>private void BleCore_DeviceWatcherChanged(BleCore.MsgType type, Windows.Devices.Bluetooth.BluetoothLEDevice bluetoothLEDevice){RunAsync(() =>{this.listboxBleDevice.Items.Add(bluetoothLEDevice.Name);this.DeviceList.Add(bluetoothLEDevice);this.btnConnect.Enabled = true;});}/// <summary>/// 获取蓝牙服务列表/// </summary>private void BleCore_GattDeviceServiceAdded(Windows.Devices.Bluetooth.GenericAttributeProfile.GattDeviceService gattDeviceService){RunAsync(() =>{this.cmbServer.Items.Add(gattDeviceService.Uuid.ToString());this.GattDeviceServices.Add(gattDeviceService);this.btnFeatures.Enabled = true;});}/// <summary>/// 获取特征列表/// </summary>private void BleCore_CharacteristicAdded(Windows.Devices.Bluetooth.GenericAttributeProfile.GattCharacteristic gattCharacteristic){RunAsync(() =>{this.cmbFeatures.Items.Add(gattCharacteristic.Uuid);this.GattCharacteristics.Add(gattCharacteristic);this.btnOpteron.Enabled = true;});}private void buttonSearch_Click(object sender, EventArgs e){if (this.btnSearch.Text == "搜索"){this.listboxMessage.Items.Clear();this.listboxBleDevice.Items.Clear();this.bleCore.StartBleDeviceWatcher();this.btnSearch.Text = "停止";}else{this.bleCore.StopBleDeviceWatcher();this.btnSearch.Text = "搜索";}}private void btnConnect_Click(object sender, EventArgs e){if (this.listboxBleDevice.SelectedItem != null){string DeviceName = this.listboxBleDevice.SelectedItem.ToString();Windows.Devices.Bluetooth.BluetoothLEDevice bluetoothLEDevice = this.DeviceList.Where(u => u.Name == DeviceName).FirstOrDefault();if (bluetoothLEDevice != null){bleCore.StartMatching(bluetoothLEDevice);this.btnServer.Enabled = true;}else{MessageBox.Show("没有发现此蓝牙,请重新搜索.");this.btnServer.Enabled = false;}}else{MessageBox.Show("请选择连接的蓝牙.");this.btnServer.Enabled = false;}}private void btnServer_Click(object sender, EventArgs e){this.cmbServer.Items.Clear();this.bleCore.FindService();}private void btnFeatures_Click(object sender, EventArgs e){this.cmbFeatures.Items.Clear();if (this.cmbServer.SelectedItem != null){var item = this.GattDeviceServices.Where(u => u.Uuid == new Guid(this.cmbServer.SelectedItem.ToString())).FirstOrDefault();this.bleCore.FindCharacteristic(item);}else{MessageBox.Show("选择蓝牙服务.");}}private void btnOpteron_Click(object sender, EventArgs e){if (this.cmbFeatures.SelectedItem != null){var item = this.GattCharacteristics.Where(u => u.Uuid == new Guid(this.cmbFeatures.SelectedItem.ToString())).FirstOrDefault();this.bleCore.SetOpteron(item);if (item.CharacteristicProperties == (Windows.Devices.Bluetooth.GenericAttributeProfile.GattCharacteristicProperties.Write | Windows.Devices.Bluetooth.GenericAttributeProfile.GattCharacteristicProperties.WriteWithoutResponse)){this.btnReader.Enabled = true;this.btnSend.Enabled = true;}}else{MessageBox.Show("选择蓝牙服务.");}}private void btnReader_Click(object sender, EventArgs e){}private void btnSend_Click(object sender, EventArgs e){byte[] dataBytes = new byte[8];dataBytes[0] = 0xAB;dataBytes[1] = 0x00;dataBytes[2] = 0x01;dataBytes[3] = 0xA2;dataBytes[4] = 0x02;dataBytes[5] = 0x0D;dataBytes[6] = 0xAC;dataBytes[7] = 0xBA;this.bleCore.Write(dataBytes);}private void FormTest_FormClosed(object sender, FormClosedEventArgs e){this.bleCore.Dispose();}}
}

3.界面截图

操作步骤:搜索》选择列表框中的某个蓝牙》匹配》获取服务》获取特征》获取操作》发送

三、注意事项

在获取操作的时候,需要根据使用的蓝牙设备的特征修改BleCore类的SetOpteron()方法,单步调试程序来查看gattCharacteristic.CharacteristicProperties属性的值,修改成匹配的GattCharacteristicProperties的组合。否则,写特征CurrentWriteCharacteristic为空,无法发送数据。同时,需要修改“获取操作”按钮的响应函数btnOpteron_Click()。


代码地址:(14条消息) 低功耗蓝牙通讯C#WinForm-C#文档类资源-CSDN文库

低功耗蓝牙通讯 C# WinForm相关推荐

  1. 在uniAPP中使用使用低功耗蓝牙通讯

    在uniAPP中使用使用低功耗蓝牙通讯 1.初始化蓝牙监听器 onLoad(){//蓝牙是否在扫描设备uni.onBluetoothAdapterStateChange((res)=>{cons ...

  2. windows+python+bleak+BLE低功耗蓝牙通讯连接

    前言 1.为什么选bleak   参考这篇知乎:https://zhuanlan.zhihu.com/p/577687336   windows端使用python连接常规的BLE设备(蓝牙4.0),仅 ...

  3. Android 低功耗蓝牙开发简述

    低功耗蓝牙简述 一.什么是低功耗蓝牙? 二.怎么做低功耗蓝牙应用? ① 之前有没有接触Android蓝牙开发? ② 蓝牙设备固件是公司自己的吗? ③ 有没有蓝牙固件和蓝牙应用的文档和Demo? ④ 具 ...

  4. android 连接蓝牙电子秤_电子秤蓝牙双模通讯Android低功耗蓝牙(蓝牙4.0)BLE开发(上)...

    电子秤蓝牙双模通讯Android低功耗蓝牙(蓝牙4.0)BLE开发(上) 前段时间,公司项目用到了手机APP和蓝牙设备的通讯开发,这里也正好对低功耗蓝牙(蓝牙4.0及以后标准)的开发,做一个总结. 蓝 ...

  5. Android BLE低功耗蓝牙开发(下) BLE客户端(中央设备)与GATT服务的通讯

    之前的文章简单实现了使用传统蓝牙进行通讯的DEMO,说是最简单其实只是夸张的写法~毕竟标题党横行,我们也得学学点~至少没有UC震惊部那么夸张. 然后,本来是要写Android开发之BlueTooth- ...

  6. Android BLE 低功耗蓝牙技术使用解析

    什么是BLE BLE 全称为 Bluetooth low energy,意思是低功耗蓝牙. Android 4.3 (API 18)之后引入Ble. 最常用的Ble蓝牙技术是设备之间传输数据. And ...

  7. 怎么查看蓝牙uuid_多设备低功耗蓝牙 Swarm BLE in Android and iOS

    Camellia Café 在这里讲述同时与多个低功耗蓝牙设备的连接及通迅,在Android和iOS中的开发,敬请点击观看视频: 多设备低功耗蓝牙Android和iOShttps://www.zhih ...

  8. 经典蓝牙和低功耗蓝牙(BLE)有什么区别?

    蓝牙模块Bluetooth module)是指集成蓝牙功能的芯片基本电路集合,用于短距离2.4G的无线通讯模块.对于最终用户来说,蓝牙模块是半成品,通过在模块的基础上功能再开发.封装外壳等工序,实现能 ...

  9. microbit编程_使用图形化编程实现主控板与手机蓝牙通讯(2019.3.25)

    本文转自:DFRobot创客社区 原文链接: [Mind+]使用图形化编程实现主控板与手机蓝牙通讯-Mind+论坛-DF创客社区​mc.dfrobot.com.cn 本帖最后由 Forgotten 于 ...

最新文章

  1. 频率分布直方图组距如何确定_QC七大手法之直方图法,快快转发、收藏!
  2. SQL 2005 中的数据约束
  3. Python-OpenCV 杂项(三): 程序性能的检测和优化
  4. 通过live555实现H264 RTSP直播(Windows版)
  5. iar 看时序_IAR 硬件仿真查看运行时间
  6. centos7 nginx+php5.6+mysql安装与配置
  7. xgboost算法_XGBoost算法可能会长期占据你的视野!
  8. ubuntu16.04下在TensorFlow中实现快速风格迁移
  9. 1-junos基本操作
  10. 用牛顿法求算术平方根python
  11. 定义一个鸭子的类java_2019-02-11——Java 鸭子模型
  12. 看日漫学日语:日漫里常看到的日语100句(建议收藏)
  13. C#中indexof和substring函数用法 (截取字符串)
  14. NTFS Change Journal(USN Journal)详解
  15. CTF竞赛实战 中国菜刀与一句话木马
  16. Shader Graph学习(一)
  17. GPT模型介绍并且使用pytorch实现一个小型GPT中文闲聊系统
  18. 如何进行矢量格式转换和坐标变换
  19. pytest—pytest.mark.parametrize的使用
  20. 命令行查看笔记本电脑电池使用状态

热门文章

  1. 【153天】尚学堂高淇Java300集视频精华笔记(122-123)
  2. 深度学习:GAN优化方法-DCGAN案例
  3. aurora(极光) vpn查看代理ip和端口
  4. 【软件工程】药品存销信息管理系统
  5. 6-RabbitMQ实战
  6. 如何搜索下载到自己要的东西,避免病毒(捆绑广告)
  7. vue admin template开启顶部导航
  8. 麒麟AI首席科学家现世
  9. postman Error: connect ECONNREFUSED 127.0.0.1:9001
  10. 机械臂——六轴机械臂操作空间运动分析