Windows原生蓝牙编程 第二章 选取设备输入配对码并配对【C++】

蓝牙系列文章目录
第一章 获取本地蓝牙并扫描周围蓝牙信息并输出
第二章 选取设备输入配对码并配对


文章目录

  • 前言
  • 头文件
  • 一、选择想要配对的设备并设置配对码
    • 1.1 设置配对码
    • 1.2 选择设备并配对
  • 二、全部代码
  • 三、测试结果
  • 总结


前言

接着第一章,我们已经把扫描到的蓝牙信息存在了vector数组res中了,接下来我们就要输入配对码进行配对了,为了好理解一点我把res改成devices了=v=


头文件

#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable : 4995)

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include
#include 
#include 
#pragma comment(lib, "wsock32.lib")
#pragma comment(lib, "bthprops.lib")
#pragma comment(lib,"ws2_32.lib")
using namespace std;
string PassKey;
HANDLE btdi;
vector<BLUETOOTH_DEVICE_INFO> devices;
BLUETOOTH_DEVICE_INFO device;

一、选择想要配对的设备并设置配对码

这里我在第一章的基础上加了个序号,以方便我们选择想要连接的设备,其实也可以通过输入设备名或设备MAC地址来进行连接,做一次匹配找到设备。
这里我偷个懒选择序号来直接访问vector数组=v=,我顺便还把vector数组vector devices变成全局数组了,也是偷懒,真正用的时候直接封装到class里的就行了。我还加了个全局变量HANDLE btdi用于保存本地蓝牙句柄信息和BLUETOOTH_DEVICE_INFO device来保存设备。

int i = 0;

while (bfind)
{
	cout << ++i << "\t" << "[Name]:" << wstring2string(btdi.szName);  //远程蓝牙设备的名字
	cout << "\t[Address]:" << getMAC(btdi.Address) << endl;
	res.push_back(btdi);
	bfind = BluetoothFindNextDevice(hbdf, &btdi);//通过BluetoothFindFirstDevice得到的HBLUETOOTH_DEVICE_FIND句柄来枚举搜索下一个远程蓝牙设备,并将远程蓝牙设备的信息储存在btdi中
}
BluetoothFindDeviceClose(hbdf);//使用完后记得关闭HBLUETOOTH_DEVICE_FIND句柄hbdf。

选择好设备后,我们从键盘中输入配对码,设置一个全局string变量PassKey来进行保存配对码。
但注意,如果你使用的单片机这种可以手动设置配对码的设备进行双方通信的话,这个方法是有效的。
但如果你使用其他设备如手机和PC进行连接,那么这个方法是无效的,因为每次PC和手机的配对码都是随机且需要双方同时确认。那么针对PC和手机就需要手动进行连接,连接之后系统会自动保存双方配对码,完成配对,那么就可以可以通过device.fAuthenticated来进行读取当前设备是否已经配对,就不需要设置配对码了。

这里还有个小点是,windowsAPI里配对码是PWSTR类型,我们也需要把输入的string类型的配对码转成PWSTR

1.1 设置配对码

void setPassKey() {
	cout << "请输入配对码:(如果不知道请输入默认0000)";
	cin >> PassKey;
	cout << "您输入的配对码为: " << PassKey << endl;
}

1.2 选择设备并配对

void pairDevice() {
	cout << "输入你想要配对的设备的序号:";
	int index;
	cin >> index;
	//获取设备信息
	BLUETOOTH_DEVICE_INFO device = devices[index - 1];
	//输入配对码
	setPassKey();
	//string转PWSTR
	wstringstream wss;
	for (char c : PassKey) {
		wss << wchar_t(c);
	}
	wstring wstr = wss.str();
	const wchar_t* wcharPtr = wstr.c_str();
	PWSTR AUTHENTICATION_PASSKEY = const_cast<PWSTR>(wcharPtr);
	//开始配对
	wstring ws = device.szName;
	HBLUETOOTH_AUTHENTICATION_REGISTRATION hCallbackHandle = 0;
	DWORD result = -1;
	if (!device.fAuthenticated) {
		result = BluetoothAuthenticateDevice(NULL, btdi, &device, AUTHENTICATION_PASSKEY, (ULONG)wcslen(AUTHENTICATION_PASSKEY));  //配对函数,AUTHENTICATION_PASSKEY是我的蓝牙配对码
		if (result != ERROR_SUCCESS) {
			switch (result)
			{
			case ERROR_CANCELLED:
				cout << "用户取消了身份验证或配对操作" << endl;
				break;
			case ERROR_INVALID_PARAMETER:
				cout << "传递给函数的参数无效" << endl;
				break;
			case ERROR_NO_MORE_ITEMS:
				cout << "没有更多的设备可以配对" << endl;
				break;
			case ERROR_NOT_SUPPORTED:
				cout << "不支持请求的操作" << endl;
				break;
			case ERROR_GEN_FAILURE:
				cout << "通用失败错误" << endl;
				break;
			case ERROR_BUSY:
				cout << "蓝牙堆栈忙" << endl;
				break;
			case ERROR_TIMEOUT:
				cout << "操作超时" << endl;
				break;
			case ERROR_DEVICE_NOT_CONNECTED:
				cout << "蓝牙设备未连接" << endl;
				break;
			case ERROR_DEVICE_NOT_AVAILABLE:
				cout << "设备不可用" << endl;
				break;
			default:
				cout << "校验码出错,请手动进行设备连接" << endl;
				break;
			}
			return;
		}
	}
	cout << "身份验证成功,蓝牙设备已成功配对" << endl;;
	BluetoothUpdateDeviceRecord(&device);
}

还有一个小点:result = BluetoothAuthenticateDevice(NULL, btdi, &device, AUTHENTICATION_PASSKEY, (ULONG)wcslen(AUTHENTICATION_PASSKEY));中,BluetoothAuthenticateDevice已经不支持使用,被标记为deprecated了,因为我这是老版本上要使用的只能用这个,需要加上#pragma warning(disable : 4995)。

二、全部代码

#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable : 4995)

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include
#include 
#include 
#pragma comment(lib, "wsock32.lib")
#pragma comment(lib, "bthprops.lib")
#pragma comment(lib,"ws2_32.lib")
using namespace std;
string PassKey;
HANDLE btdi;
vector<BLUETOOTH_DEVICE_INFO> devices;
BLUETOOTH_DEVICE_INFO device;

string wstring2string(const wstring& ws)
{
	string curLocale = setlocale(LC_ALL, NULL);
	setlocale(LC_ALL, "chs");
	const wchar_t* _Source = ws.c_str();
	size_t _Dsize = 2 * ws.size() + 1;
	char* _Dest = new char[_Dsize];
	memset(_Dest, 0, _Dsize);
	wcstombs(_Dest, _Source, _Dsize);
	string result = _Dest;
	delete[]_Dest;
	setlocale(LC_ALL, curLocale.c_str());
	return result;
}

string getMAC(BLUETOOTH_ADDRESS Daddress)
{
	/*string addr;
	addr = addr.sprintf("%02x:%02x:%02x:%02x:%02x:%02x", Daddress.rgBytes[5], Daddress.rgBytes[4], Daddress.rgBytes[3], Daddress.rgBytes[2], Daddress.rgBytes[1], Daddress.rgBytes[0]);
	return addr;*/
	ostringstream oss;
	oss << hex << setfill('0') << uppercase;
	for (int i = 5; i >= 0; --i) {
		oss << setw(2) << static_cast<int>(Daddress.rgBytes[i]);
		if (i > 0) {
			oss << ":";
		}
	}
	return oss.str();
}

vector<BLUETOOTH_DEVICE_INFO> scanDevices()
{
	HBLUETOOTH_RADIO_FIND hbf = NULL;
	HANDLE hbr = NULL;
	HBLUETOOTH_DEVICE_FIND hbdf = NULL;
	BLUETOOTH_FIND_RADIO_PARAMS btfrp = { sizeof(BLUETOOTH_FIND_RADIO_PARAMS) }; //调用BluetoothFindFirstDevice搜索本机蓝牙收发器所需要的搜索参数对象
	BLUETOOTH_RADIO_INFO bri = { sizeof(BLUETOOTH_RADIO_INFO) }; //初始化一个储存蓝牙收发器信息(BLUETOOTH_RADIO_INFO)的对象bri
	BLUETOOTH_DEVICE_SEARCH_PARAMS btsp = { sizeof(BLUETOOTH_DEVICE_SEARCH_PARAMS) };//调用BluetoothFindFirstDevice搜索本所需要的搜索参数对象
	BLUETOOTH_DEVICE_INFO btdi = { sizeof(BLUETOOTH_DEVICE_INFO) };  //初始化一个远程蓝牙设备信息(BLUETOOTH_DEVICE_INFO)对象btdi,以储存搜索到的蓝牙设备信息
	hbf = BluetoothFindFirstRadio(&btfrp, &hbr); //得到第一个被枚举的蓝牙收发器的句柄hbf可用于BluetoothFindNextRadio,hbr可用于BluetoothFindFirstDevice。若没有找到本机的蓝牙收发器,则得到的句柄hbf=NULL

	vector<BLUETOOTH_DEVICE_INFO> res;

	bool brfind = hbf != NULL;
	while (brfind)
	{
		if (BluetoothGetRadioInfo(hbr, &bri) == ERROR_SUCCESS)//获取蓝牙收发器的信息,储存在bri中
		{
			cout << "[Local Device Name]:" << wstring2string(bri.szName) << "\t";   //蓝牙收发器的名字
			cout << "[Local Device Address]: " << getMAC(bri.address) << endl;
			cout << "------------------------蓝牙扫描结果如下----------------------------" << endl;

			btsp.hRadio = hbr;  //设置执行搜索设备所在的句柄,应设为执行BluetoothFindFirstRadio函数所得到的句柄
			btsp.fReturnAuthenticated = TRUE;//是否搜索已配对的设备
			btsp.fReturnConnected = FALSE;//是否搜索已连接的设备
			btsp.fReturnRemembered = TRUE;//是否搜索已记忆的设备
			btsp.fReturnUnknown = TRUE;//是否搜索未知设备
			btsp.fIssueInquiry = TRUE;//是否重新搜索,True的时候会执行新的搜索,时间较长,FALSE的时候会直接返回上次的搜索结果。
			btsp.cTimeoutMultiplier = 30;//指示查询超时的值,以1.28秒为增量。 例如,12.8秒的查询的cTimeoutMultiplier值为10.此成员的最大值为48.当使用大于48的值时,调用函数立即失败并返回
			hbdf = BluetoothFindFirstDevice(&btsp, &btdi);//通过找到第一个设备得到的HBLUETOOTH_DEVICE_FIND句柄hbdf来枚举远程蓝牙设备,搜到的第一个远程蓝牙设备的信息储存在btdi对象中。若没有远程蓝牙设备,hdbf=NULL。
			bool bfind = hbdf != NULL;
			int i = 0;

			while (bfind)
			{
				cout << ++i << " " << "[Name]:" << wstring2string(btdi.szName);  //远程蓝牙设备的名字
				cout << "\t[Address]:" << getMAC(btdi.Address) << endl;
				res.push_back(btdi);
				bfind = BluetoothFindNextDevice(hbdf, &btdi);//通过BluetoothFindFirstDevice得到的HBLUETOOTH_DEVICE_FIND句柄来枚举搜索下一个远程蓝牙设备,并将远程蓝牙设备的信息储存在btdi中
			}
			BluetoothFindDeviceClose(hbdf);//使用完后记得关闭HBLUETOOTH_DEVICE_FIND句柄hbdf。
		}
		CloseHandle(hbr);
		brfind = BluetoothFindNextRadio(hbf, &hbr);//通过BluetoothFindFirstRadio得到的HBLUETOOTH_RADIO_FIND句柄hbf来枚举搜索下一个本地蓝牙收发器,得到可用于BluetoothFindFirstDevice的句柄hbr。
	}
	return res;
}

void setPassKey() {
	cout << "请输入配对码:(如果不知道请输入默认0000):";
	cin >> PassKey;
	cout << "您输入的配对码为: " << PassKey << endl;
}

void pairDevice() {
	cout << "输入你想要配对的设备的序号:";
	int index;
	cin >> index;
	//获取设备信息
	device = devices[index - 1];
	//输入配对码
	setPassKey();
	//string转PWSTR
	wstringstream wss;
	for (char c : PassKey) {
		wss << wchar_t(c);
	}
	wstring wstr = wss.str();
	const wchar_t* wcharPtr = wstr.c_str();
	PWSTR AUTHENTICATION_PASSKEY = const_cast<PWSTR>(wcharPtr);
	//开始配对
	wstring ws = device.szName;
	HBLUETOOTH_AUTHENTICATION_REGISTRATION hCallbackHandle = 0;
	DWORD result = -1;
	if (!device.fAuthenticated) {
		result = BluetoothAuthenticateDevice(NULL, btdi, &device, AUTHENTICATION_PASSKEY, (ULONG)wcslen(AUTHENTICATION_PASSKEY));  //配对函数,AUTHENTICATION_PASSKEY是我的蓝牙配对码
		if (result != ERROR_SUCCESS) {
			switch (result)
			{
			case ERROR_CANCELLED:
				cout << "用户取消了身份验证或配对操作" << endl;
				break;
			case ERROR_INVALID_PARAMETER:
				cout << "传递给函数的参数无效" << endl;
				break;
			case ERROR_NO_MORE_ITEMS:
				cout << "没有更多的设备可以配对" << endl;
				break;
			case ERROR_NOT_SUPPORTED:
				cout << "不支持请求的操作" << endl;
				break;
			case ERROR_GEN_FAILURE:
				cout << "通用失败错误" << endl;
				break;
			case ERROR_BUSY:
				cout << "蓝牙堆栈忙" << endl;
				break;
			case ERROR_TIMEOUT:
				cout << "操作超时" << endl;
				break;
			case ERROR_DEVICE_NOT_CONNECTED:
				cout << "蓝牙设备未连接" << endl;
				break;
			case ERROR_DEVICE_NOT_AVAILABLE:
				cout << "设备不可用" << endl;
				break;
			default:
				cout << "校验码出错,请手动进行设备连接" << endl;
				break;
			}
			return;
		}
	}
	cout << "身份验证成功,蓝牙设备已成功配对" << endl;;
	BluetoothUpdateDeviceRecord(&device);
}

void main() {
	devices = scanDevices();
	pairDevice();
	return;
}

三、测试结果

我的手机和电脑已经提前配对好了,原因我已经在本文的第一点里已经说过了。
在这里插入图片描述
编译运行一下,老规矩MAC地址打码=v=
Windows原生蓝牙编程 第二章 选取设备输入配对码并配对【C++】_第1张图片
输入我要连接我的手机,输入序号5
输入配对码,已经我已经和电脑配对过了,但我也不知道配对码是多少没输入0000
结果如下
Windows原生蓝牙编程 第二章 选取设备输入配对码并配对【C++】_第2张图片
用系统保存过的信息配对,完美配对。

总结

如果您觉得有用请点赞评论收藏一波,下一章我们开始通信!=v=

你可能感兴趣的:(windows蓝牙编程,蓝牙,蓝牙通信,windowsAPI,qt4蓝牙通信,windows,蓝牙编程)