蓝牙系列文章目录
第一章 获取本地蓝牙并扫描周围蓝牙信息并输出
文章目录
- 前言
- 头文件
- 一、获取本地蓝牙的句柄和信息
- 1.1 wstring转string
- 1.2 获取MAC地址
- 1.3 扫描附近设备并输出
- 1.4 主函数
- 二、全部代码
- 三、输出结果
- 编译并运行查看结果 MAC地址我就打个码=v= ![在这里插入图片描述](https://img-blog.csdnimg.cn/0f02290828fe4aa1953d65d52aeb410b.png)
- 总结
前言
最近写蓝牙,本来打算用Qt5自带的蓝牙,但是项目本身是Qt4,不支持升级到Qt5,只好用Windows自带的原生api来进行连接访问。记录一下过程,以供大家学习。客户端用的winsock进行通信的。
头文件
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <iomanip>
#include <windows.h>
#include <stdlib.h>
#include<bluetoothapis.h>
#include <winsock.h>
#include <ws2bth.h>
#pragma comment(lib, "wsock32.lib")
#pragma comment(lib, "bthprops.lib")
#pragma comment(lib,"ws2_32.lib")
using namespace std;
一、获取本地蓝牙的句柄和信息
1.1 wstring转string
以下是windows中对蓝牙设备信息的结构体信息,因为BLUETOOTH_DEVICE_INFO中的sName是WCHAR类型的数组,我们在cout的时候会牵扯到宽字符转string的操作,所以在输出搜索蓝牙设备名的时候需要从wstring转string
typedef struct _BLUETOOTH_DEVICE_INFO {
_Field_range_(==, sizeof(BLUETOOTH_DEVICE_INFO_STRUCT))
DWORD dwSize; // size, in bytes, of this structure - must be the sizeof(BLUETOOTH_DEVICE_INFO)
BLUETOOTH_ADDRESS Address; // Bluetooth address
ULONG ulClassofDevice; // Bluetooth "Class of Device"
BOOL fConnected; // Device connected/in use
BOOL fRemembered; // Device remembered
BOOL fAuthenticated; // Device authenticated/paired/bonded
SYSTEMTIME stLastSeen; // Last time the device was seen
SYSTEMTIME stLastUsed; // Last time the device was used for other than RNR, inquiry, or SDP
WCHAR szName[ BLUETOOTH_MAX_NAME_SIZE ]; // Name of the device
} BLUETOOTH_DEVICE_INFO_STRUCT;
具体的wstring转string操作
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;
}
1.2 获取MAC地址
以下是windows中对蓝牙地址息的结构体信息,包含ulonglong类型的ullLong和char类型的rgBytes数组,输出mac地址需要对address进行格式化操作。
typedef struct _BLUETOOTH_ADDRESS {
union {
BTH_ADDR ullLong; // easier to compare again BLUETOOTH_NULL_ADDRESS
BYTE rgBytes[ 6 ]; // easier to format when broken out
};
} BLUETOOTH_ADDRESS_STRUCT;
大写并且用冒号隔开,原本的BLUETOOTH_ADDRESS变为十六进制大写的MAC地址。
string getMAC(BLUETOOTH_ADDRESS Daddress)
{
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();
}
1.3 扫描附近设备并输出
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); //蓝牙收发器的名字
cout << "[Local Device Address]: " << getMAC(bri.address) << 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;
while (bfind)
{
cout << "[Name]:" << wstring2string(btdi.szName); //远程蓝牙设备的名字
cout << ",[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;
}
1.4 主函数
void main() {
vector<BLUETOOTH_DEVICE_INFO> devices = scanDevices();
return;
}
二、全部代码
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <iomanip>
#include <windows.h>
#include <stdlib.h>
#include<bluetoothapis.h>
#include <winsock.h>
#include <ws2bth.h>
#pragma comment(lib, "wsock32.lib")
#pragma comment(lib, "bthprops.lib")
#pragma comment(lib,"ws2_32.lib")
using namespace std;
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); //蓝牙收发器的名字
cout << "[Local Device Address]: " << getMAC(bri.address) << 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;
while (bfind)
{
cout << "[Name]:" << wstring2string(btdi.szName); //远程蓝牙设备的名字
cout << ",[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 main() {
vector<BLUETOOTH_DEVICE_INFO> devices = scanDevices();
return;
}
三、输出结果
编译并运行查看结果
MAC地址我就打个码=v=
总结
觉得有用的话务必给我点赞评论支持一下=v=