windows BLE编程 net winform 连接蓝牙4.0
winform 程序调用Windows.Devices.Bluetoot API 实现windows下BLE蓝牙设备自动连接,收发数据功能。不需要使用win10的UWP开发。
先贴图,回头来完善代码


源码如下:
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 = ;
//特性通知类型通知启用
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, , ).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 > )
{
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 > )
{
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 > )
{
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
}
}
调用方式:
bluetooth = new BluetoothLECode(_serviceGuid, _writeCharacteristicGuid, _notifyCharacteristicGuid);
bluetooth.ValueChanged += Bluetooth_ValueChanged;
如果你无法编译上面的类库,请直接使用我生成的DLL文件
https://files.cnblogs.com/files/webtojs/BLECode.rar
windows BLE编程 net winform 连接蓝牙4.0的更多相关文章
- [转]windows BLE编程 net winform 连接蓝牙4.0
本文转自:https://www.cnblogs.com/webtojs/p/9675956.html winform 程序调用Windows.Devices.Bluetoot API 实现windo ...
- Windows 10下怎么远程连接 Ubuntu 16.0.4(方案二)
使用TeamViewer实现远程桌面连接 背景: 有些朋友反映,借助Ubuntu自带的桌面共享工具desktop sharing会有不再同一网端下出现连接不稳定或者掉线的问题,那么现在我们就可以借助第 ...
- Windows 10下怎么远程连接 Ubuntu 16.0.4(小白级教程)
前言: 公司因为用Ruby做开发,所有适用了Ubuntu系统,但是自己笔记本是W10,又不想装双系统,搭建开发环境,便想到倒不如自己远程操控公司电脑,这样在家的时候也可以处理一些问题.故此便有了下面的 ...
- 蓝牙4.0(包含BLE)简介
1. BLE (低功耗蓝牙)简介 国际蓝牙联盟( BT-SIG,TI 是 企业成员之一)通过的一个标准蓝牙无线协议. 主要的新特性是在蓝牙标准版本上添加了4.0 蓝牙规范 (2010 年6 月 ...
- iOS蓝牙BLE4.0通信功能
概述 iOS蓝牙BLE4.0通信功能,最近刚学的苹果,为了实现蓝牙门锁的项目,找了一天学习了下蓝牙的原理,亲手测试了一次蓝牙的通信功能,结果成功了,那么就把我学习的东西分享一下. 详细 代码下载:ht ...
- 基于蓝牙4.0(Bluetooth Low Energy)胎压监测方案设计
基于一种新的蓝牙技术——蓝牙4.0(Bluetooth Low Energy)新型的胎压监测系统(TPMS)的设计方案.鉴于蓝牙4.0(Bluetooth Low Energy)的低成本.低功耗.高稳 ...
- Android项目实战(三十四):蓝牙4.0 BLE 多设备连接
最近项目有个需求,手机设备连接多个蓝牙4.0 设备 并获取这些设备的数据. 查询了很多资料终于实现,现进行总结. ------------------------------------------- ...
- android4.3 蓝牙BLE编程
一.蓝牙4.0简介 蓝牙4.0标准包含两个蓝牙标准,准确的说,是一个双模的标准,它包含传统蓝牙部分(也有称之为经典蓝牙Classic Bluetooth)和低功耗蓝牙部分(Bluetooth Low ...
- Android5.0(Lollipop) BLE蓝牙4.0+浅析demo连接(三)
作者:Bgwan链接:https://zhuanlan.zhihu.com/p/23363591来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. Android5.0(L ...
随机推荐
- var
在函数中,使用var声明的变量,为局部变量,只能在函数内部访问. 不使用var声明的变量,为全局变量,在函数外边也能访问. 没有var的情况 <script type="text/ja ...
- 决策树模型组合之随机森林与GBDT(转)
版权声明: 本文由LeftNotEasy发布于http://leftnoteasy.cnblogs.com, 本文可以被全部的转载或者部分使用,但请注明出处,如果有问题,请联系wheeleast@gm ...
- Python开发——7.迭代器、生成器和装饰器
一.迭代器 1.迭代器协议 (1)迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么引起一个StopIteration移除异常以中止迭代. (2)可迭代对象:实现了迭 ...
- DSP builder安装指南(以9.1为例) 转自http://www.cnblogs.com/sleepy/archive/2011/06/28/2092362.html
DSP Builder在算法友好的开发环境中帮助设计人员生成DSP设计硬件表征,从而缩短了DSP设计周期.已有的MATLAB函数和Simulink模块可以和Altera DSP Builder模块以及 ...
- 使用netstat命令查看端口的使用情况
Windows如何查看端口占用情况操作步骤如下: 开始--运行--cmd 进入命令提示符,输入netstat -ano 即可看到所有连接的PID 之后在任务管理器中找到这个PID所对应的程序如果任务管 ...
- React-Native 问题随记2: com.android.builder.testing.api.DeviceException
错误详细: Execution failed for task ':app:installDebug'.> com.android.builder.testing.api.DeviceExcep ...
- Typescript 学习笔记七:泛型
中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...
- css 如何“画”一个抽奖转盘
主要描述的是如何运用 css 绘制一个抽奖转盘,并运用原生 js 实现转盘抽奖效果. 先来张效果图: 布局 一般来说,转盘一般有四个部分组成:外层闪烁的灯.内层旋转的圆盘.圆盘上的中奖结果.指针. 所 ...
- 撰写一篇博客要求讲述四则运算2的设计思想,源程序代码、运行结果截图、编程总结分析,并按照PSP0级的要求记录开发过程中的时间记录日志。
一.撰写一篇博客要求讲述四则运算2的设计思想,源程序代码.运行结果截图.编程总结分析,并按照PSP0级的要求记录开发过程中的时间记录日志. 1.设计思想: ①创建test.jsp建立第一个前端界面,提 ...
- c++中的.hpp文件
http://blog.chinaunix.net/uid-24118190-id-75239.html hpp,其实质就是将.cpp的实现代码混入.h头文件当中,定义与实现都包含在同一文件,则该类的 ...