[转]windows BLE编程 net winform 连接蓝牙4.0
本文转自:https://www.cnblogs.com/webtojs/p/9675956.html
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 = 0;
//特性通知类型通知启用
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, 2, 6).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 > 0)
{
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 > 0)
{
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 > 0)
{
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
winform 程序调用Windows.Devices.Bluetoot API 实现windows下BLE蓝牙设备自动连接,收发数据功能.不需要使用win10的UWP开发. 先贴图,回头来完善代码 ...
- 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 ...
随机推荐
- android-音量管理
推荐简书夕月风: 前两个主要设计音频建设置流程. 一.https://www.jianshu.com/p/a48fc2c830da 二.https://www.jianshu.com/p/892761 ...
- Android逆向之smali学习
Smali是Android虚拟机Dalvik反汇编的结果. Dalvik指令集 指令格式为:[op]-[type](可选)/[位宽,默认4位] [目标寄存器],[源寄存器](可选) 赋值:move* ...
- jquery.ocupload上传文件到指定目录
首先引入两个js <script type="text/javascript" src="${pageContext.request.contextPath }/r ...
- 背水一战 Windows 10 (116) - 后台任务: 前台程序激活后台任务
[源码下载] 背水一战 Windows 10 (116) - 后台任务: 前台程序激活后台任务 作者:webabcd 介绍背水一战 Windows 10 之 后台任务 前台程序激活后台任务 示例演示后 ...
- Jenkins的初级应用(1)-Publish Over SSH
作为Jenkins最基本的应用也是重要的一环就是可以把文件传到服务器上面,或者在服务器上面远程执行命令.一个可在在远程分发了文件之后就控制远程服务器的操作.另外一个就是分发了文件之后,结合自动化工具在 ...
- 弹性盒子模型属性之flex-grow
在学习弹性盒子模型的时候,有几个属性常常让同学们感觉头痛, 不知到最后得到的效果数值到底是怎样计算得来的,那么不要慌,稳住,我们能赢 !!!今天就让我们先来看看flex-grow这个属性 flex-g ...
- 1.TabActivity、视图树、动画
整个页面为TabActivity, 其中对TabWidget进行了一些改变,当切换页签时页签后面红色背景会以Translate动画形式移动到相对应的页签后. 布局 )); lastPosition = ...
- Android APK安装过程学习笔记
1.什么是APK APK,即Android Package,Android安装包.不同平台的安装文件格式都不同,类似于Windows的安装包是二进制的exe格式,Mac的安装包是dmg格式.APK可以 ...
- WPF中TreeView控件的使用案例
WPF总体来说还是比较方便的,其中变化最大的主要是Listview和Treeview控件,而且TreeView似乎在WPF是一个备受指责的控件,很多人说他不好用.我这个demo主要是在wpf中使用Tr ...
- JS创建对象,数组,函数的三种方式
害怕自己忘记,简单总结一下 创建对象的3种方法 ①:创建一个空对象 var obj = {}; ②:对象字面量 var obj = { name: "Tom", age: 27 ...