可直接复制编译,只要环境没问题,应该能编译通过
#pragma once
#include <iostream>
#include <iomanip>
#include <sstream>
// 蓝牙API需要的头文件
#include <afxtempl.h>
#include <BluetoothAPIs.h>
#include <bthdef.h>
#include <bthsdpdef.h>
#include <ws2bth.h>
#include <WinSock2.h>
#include <string>
#include <string.h>
#include <winspool.h> // 获取串口列表所需
#pragma comment(lib,"Irprops.lib")
#define NAME_LEN 100
using namespace std;
int getLocalBluetooth(HANDLE p_local_bluetooth);
string int2hexstring(int a);
string wideChar2string(WCHAR* pWCString);
int scanRemoteBluetooth(HANDLE p_local_bluetooth, string bluetooths[], int length);
int clearAttributeBluetooth(HANDLE p_local_bluetooth, string bluetooths[], int size);
int scanComServer(string comlist[]);
string compareComList(string oldComList[100], string newComList[100]);
void Split(const string& src, const string& separator, string input[]);
// 创建数组,用来存放bdi 全局
CArray < BLUETOOTH_DEVICE_INFO, BLUETOOTH_DEVICE_INFO&> remote_bluetooth; // 周边蓝牙设备
int main(int argc, char* argv[])
{
string bluetooths[100]; // 蓝牙名字列表
int size = 0; // bluetooths 的有效长度
// 外部输入蓝牙名字
char** input_temp = argv;
input_temp++; // 不要0位置的参数
while (*input_temp != NULL) {
cout << *input_temp << endl;
bluetooths[size] = *input_temp;
size++;
++input_temp;
}
cout << "有效长度size = " << size<<endl;
// 1、获取本地蓝牙句柄
HANDLE hRadio = NULL;
int res = getLocalBluetooth(hRadio);
if (res == -1) {
// 获取本地蓝牙句柄失败
cout << "return:" << res << endl;
return -1;
}
// 2、清空 remote_bluetooth 列表,清空已经配对的蓝牙
remote_bluetooth.RemoveAll();
clearAttributeBluetooth(hRadio, bluetooths, size);
// 3、扫描目标蓝牙
int res2 = scanRemoteBluetooth(hRadio, bluetooths, size);
if (res2 == -1) {
// 未能扫描到目标蓝牙设备
cout << "return:" << -2 << endl;
}
// 4、根据remote_bluetooth的数量,创建串口服务
string oldCom[100] = {};
string newCom[100] = {};
for (int i = 0; i < remote_bluetooth.GetCount(); i++) {
// 扫一次当前PC的串口
scanComServer(oldCom);
// 申请串口服务
const BLUETOOTH_DEVICE_INFO *bdi = NULL;
bdi = &remote_bluetooth[i];
const GUID *guid = NULL;
guid = &SerialPortServiceClass_UUID;
BluetoothSetServiceState(hRadio, bdi, guid, BLUETOOTH_SERVICE_ENABLE);
// 再扫描一次当前串口
scanComServer(newCom);
// 对比两个串口列表
string myCom = compareComList(oldCom, newCom);
cout << "#蓝牙:";
wcout << bdi->szName;
cout << "--" << myCom << endl;
}
return 0;
}
struct bluetooth2com
{
string bluetoothName; // 蓝牙名称
string comName; // 串口名称
};
// 获取本地蓝牙
int getLocalBluetooth(HANDLE p_local_bluetooth)
{
BLUETOOTH_FIND_RADIO_PARAMS bfrp; // 本地蓝牙结构体
bfrp.dwSize = sizeof(bfrp);
// 获取本地蓝牙操作句柄,
HANDLE local_bluetooth = p_local_bluetooth; // 本地蓝牙句柄 本地蓝牙在windows API中被称为 radio
HBLUETOOTH_RADIO_FIND hFind = BluetoothFindFirstRadio(&bfrp, &local_bluetooth);
// 获取本地蓝牙详细信息;调用 BluetoothGetRadioInfo 函数
BLUETOOTH_RADIO_INFO local_bluetooth_message = { sizeof(local_bluetooth_message) }; // 蓝牙信息结构体
PBLUETOOTH_RADIO_INFO p_local_bluetooth_message = &local_bluetooth_message;
DWORD result = BluetoothGetRadioInfo(local_bluetooth, p_local_bluetooth_message);
if (result == ERROR_SUCCESS) {
cout << "搜索到本地蓝牙,获取其信息..." << endl;
}
else {
return -1;
}
// 解析本地蓝牙信息,并展示
// 蓝牙名称
cout << "名称:";
wcout << local_bluetooth_message.szName << endl;
// 蓝牙地址, 从 reBytes中获取,地址是逆序的,长度是6
cout << "地址:";
for (int i = 5; i >= 0; i--) {
cout << int2hexstring((int)local_bluetooth_message.address.rgBytes[i]);
if (i != 0) {
cout << ":";
}
}
cout << endl;
return 0;
}
// 扫描周边的蓝牙
int scanRemoteBluetooth(HANDLE p_local_bluetooth, string bluetooths[],int length)
{
/*
p_local_bluetooth 本地蓝牙句柄
bluetooths 蓝牙名称 string 列表
length 蓝牙名称列表的有效长度
*/
// 蓝牙搜索条件结构体
BLUETOOTH_DEVICE_SEARCH_PARAMS bdsp = { sizeof(bdsp) };
bdsp.fReturnAuthenticated = 1; // 返回经过身份验证的蓝牙设备
bdsp.fReturnRemembered = 1; // 返回记住的蓝牙设备
bdsp.fReturnUnknown = 1; // 返回未知的蓝牙设备
bdsp.fReturnConnected = 1; // 返回已连接的蓝牙设备
bdsp.fIssueInquiry = 1; // 发出新一轮的查询
bdsp.cTimeoutMultiplier = 30; // 1.28s的增量,1.28 * 20
bdsp.hRadio = p_local_bluetooth; // 有效的本地蓝牙句柄,如果是NULL,在所有本地蓝牙无线电上进行查询
// 蓝牙设备结构体
BLUETOOTH_DEVICE_INFO bdi[20];
for (int i = 0; i < 20; i++) {
bdi[i].dwSize = sizeof(bdi[i]);
}
// 搜索周边第一个蓝牙设备
HBLUETOOTH_DEVICE_FIND hdf = BluetoothFindFirstDevice(&bdsp, &bdi[0]); // 返回的hdf 句柄留给 BluetoothFindNextDevice使用
if (hdf == NULL) {
cout << "获取句柄失败" << endl;
return -1;
}
int count = 0;
do {
// 如果扫到了第一个蓝牙设备
string bluetooth_name = wideChar2string(bdi[count].szName);
for (int i = 0; i < length; i++) {
if (bluetooth_name == bluetooths[i]) {
remote_bluetooth.Add(bdi[count]);
}
}
count++;
} while (BluetoothFindNextDevice(hdf, &bdi[count]));
// 对比 remote_bluetooth 和 bluetooths 的长度,搜索到所有目标蓝牙
if (remote_bluetooth.GetCount() == length) {
cout << "匹配完成" << endl;
for (int i = 0; i < remote_bluetooth.GetCount(); i++) {
wcout << remote_bluetooth[i].szName << endl;
}
return 0;
}
// 没有所有到所有目标蓝牙,将没有搜索到的打印出来
else {
// 第一层循环:遍历所有目标蓝牙的名字
for (int i = 0; i < length; i++) {
string temp_name = bluetooths[i];
int sign = 0; // 匹配到是1,没匹配到是0
// 第二层循环:遍历匹配到的蓝牙数组
for (int j = 0; j < remote_bluetooth.GetCount(); j++) {
string t = wideChar2string(remote_bluetooth[j].szName);
if (t == temp_name) {
sign = 1;
}
}
if (sign == 0) {
cout << "未能匹配到:" << temp_name << endl;
}
if (sign == 1) {
cout << "匹配到:" << temp_name << endl;
}
}
return -1;
}
return -1;
};
// 清除已配对的蓝牙 应该只清楚要配对的蓝牙
int clearAttributeBluetooth(HANDLE p_local_bluetooth, string bluetooths[], int size)
{
/*
p_local_bluetooth 本地蓝牙操作句柄
bluetooths 要配对蓝牙的名称列表
size bluetooths数组长度
*/
// 蓝牙搜索条件结构体
BLUETOOTH_DEVICE_SEARCH_PARAMS bdsp = { sizeof(bdsp) };
bdsp.fReturnAuthenticated = 1; // 返回经过身份验证的蓝牙设备
bdsp.fReturnRemembered = 1; // 返回记住的蓝牙设备
bdsp.fReturnUnknown = 0; // 返回未知的蓝牙设备
bdsp.fReturnConnected = 0; // 返回已连接的蓝牙设备
bdsp.fIssueInquiry = 0; // 发出新一轮的查询
bdsp.cTimeoutMultiplier = 0; // 1.28s的增量,1.28 * 20
bdsp.hRadio = p_local_bluetooth; // 有效的本地蓝牙句柄,如果是NULL,在所有本地蓝牙无线电上进行查询
// 蓝牙设备结构体
BLUETOOTH_DEVICE_INFO bdi[20];
for (int i = 0; i < 20; i++) {
bdi[i].dwSize = sizeof(bdi[i]);
}
// 搜索周边第一个蓝牙设备
HBLUETOOTH_DEVICE_FIND hdf = BluetoothFindFirstDevice(&bdsp, &bdi[0]); // 返回的hdf 句柄留给 BluetoothFindNextDevice使用
if (hdf == NULL) {
return -1;
}
int count = 0;
do {
// 搜索到的蓝牙名称
string temp_name = wideChar2string(bdi[count].szName);
const BLUETOOTH_ADDRESS *pAddres = NULL;
// 遍历bluetooths
for (int i = 0; i < size; i++) {
// 如果当前搜索到的蓝牙名称在bluetooths中,删去该蓝牙的串口服务
if (temp_name == bluetooths[i]) {
pAddres = &bdi[count].Address;
BluetoothRemoveDevice(pAddres); // 移除改蓝牙
cout << "移除所有服务:" << temp_name << endl;
}
}
count++;
} while (BluetoothFindNextDevice(hdf, &bdi[count]));
return 0;
};
// 建立串口服务
int setComServer(HANDLE p_local_bluetooth, BLUETOOTH_DEVICE_INFO bdi,GUID guidService, DWORD flag)
{
// 1.扫描当前存在串口
string comList[256]; // 串口名数组
// 2.一个蓝牙新建一个串口服务
// 3.再扫描当前存在串口
// 4.对比两次扫描的串口结果,多出来的那个串口就是改蓝牙申请的串口服务
return 0;
};
// 获取windows所有串口列表
int scanComServer(string comlist[]) {
HKEY hKey;
LPCTSTR data_Set = _T("HARDWARE\\DEVICEMAP\\SERIALCOMM\\");
LONG ret0 = RegOpenKeyEx(HKEY_LOCAL_MACHINE, data_Set, 0, KEY_READ, &hKey);
if (ret0 != ERROR_SUCCESS)
{
wcout << (L"错误:无法打开有关的hKEY");
return -1;
}
DWORD dwIndex = 0;
int count = 0;
while (1)
{
LONG Status;
CHAR Name[256] = { 0 };
UCHAR szPortName[80] = { 0 };
DWORD dwName;
DWORD dwSizeofPortName;
DWORD Type;
dwName = sizeof(Name);
dwSizeofPortName = sizeof(szPortName);
Status = RegEnumValue(hKey, dwIndex++, (LPWSTR)Name, &dwName, NULL, &Type,
szPortName, &dwSizeofPortName);
if ((Status == ERROR_SUCCESS) || (Status == ERROR_MORE_DATA))
{
CString str;
str.Format(L"%s", szPortName);
comlist[count] = CT2A(str.GetBuffer());
count++;
//TRACE("\n-------%s", str);COM_SERIAL_PORT_LIST.AddString(str);
/*cout << comlist[count];*/
}
else
{
break;
}
}
RegCloseKey(hKey);
return 0;
};
// 将 int 转成 16进制的 string
string int2hexstring(int a) {
stringstream ioss;
string s_temp;
string zero = "0";
ioss << setiosflags(ios::uppercase) << hex << a;
ioss >> s_temp;
int strlength = s_temp.length();
if (strlength == 1) {
s_temp = zero + s_temp;
}
return s_temp;
}
// 将双字节的字符串转成string
string wideChar2string(WCHAR* pWCString)
{
// 获取传入的pWCString长度,用于开辟控件
int pSize = WideCharToMultiByte(CP_OEMCP, 0, pWCString, wcslen(pWCString), NULL, 0, NULL, NULL);
char* pCString = new char[pSize + 1]; // 新建 char数组
// 调用双字节字符串装成单字节字符串
WideCharToMultiByte(CP_OEMCP, 0, pWCString, wcslen(pWCString), pCString, pSize, NULL, NULL);
pCString[pSize] = '\0';
// 赋值给string
string pString = pCString;
// 释放 new 申请的空间
delete pCString;
return pString;
};
// 对比两个串口列表,输出新增加的那个串口
string compareComList(string oldComList[100], string newComList[100])
{
string defaultCom = "COM1";
// 获取两个字符串数组的长度
int old = 100;
int newc = 100;
// 第一层循环:遍历 newComList 列表
for (int i = 0; i < newc; i++) {
string temp_newc = newComList[i];
int sign = 1; // 0 旧串口 1 新增串口
// 第二层循环:遍历 oldComList 列表
for (int j = 0; j < old; j++) {
string temp_old = oldComList[j];
if (temp_newc == temp_old) {
// 不是新增的串口
sign = 0;
}
}
if (sign == 1) {
// 找到了新增的串口
return temp_newc;
}
}
return defaultCom;
};
// 分割字符串
void Split(const string& src, const string& separator, string input[]) //字符串分割到数组
{
//参数1:要分割的字符串;参数2:作为分隔符的字符;参数3:存放分割后的字符串的vector向量
string str = src;
string substring;
string::size_type start = 0, index;
index = str.find_first_of(separator, start);
int count = 0;
do
{
if (index != string::npos)
{
substring = str.substr(start, index - start);
input[count] = substring;
count++;
start = index + separator.size();
index = str.find(separator, start);
if (start == string::npos) break;
}
} while (index != string::npos);
//the last part
substring = str.substr(start);
input[count] = substring;
}