首页 > 系统相关 >关于使用c++制作蓝牙连接,Windows版本

关于使用c++制作蓝牙连接,Windows版本

时间:2024-01-25 22:45:26浏览次数:27  
标签:NULL string Windows Daddress 蓝牙 c++ BLUETOOTH include

  1 #define _CRT_SECURE_NO_WARNINGS
  2  #pragma warning(disable : 4995) 
  3  #include <iostream> 
  4  #include <string> 
  5  #include <vector> 
  6  #include <sstream> 
  7  #include <iomanip> 
  8  #include <windows.h>
  9  #include <stdlib.h> 
 10  #include<bluetoothapis.h> 
 11  #include <winsock.h>
 12  #include <ws2bth.h> 
 13  #include<Stringapiset.h>
 14  #pragma comment(lib, "wsock32.lib")
 15  #pragma comment(lib, "bthprops.lib")
 16  #pragma comment(lib,"ws2_32.lib")
 17  using namespace std; string PassKey; 
 18  HANDLE btdi; 
 19  vector<BLUETOOTH_DEVICE_INFO> devices; 
 20  BLUETOOTH_DEVICE_INFO device; 
 21  SOCKET sockClient; 
 22  WSADATA wsaData; 
 23  string wstring2string(const wstring& ws) 
 24  { 
 25      string curLocale = setlocale(LC_ALL, NULL); 
 26      setlocale(LC_ALL, "chs");
 27      const wchar_t* _Source = ws.c_str();
 28      size_t _Dsize = 2 * ws.size() + 1;
 29      char* _Dest = new char[_Dsize]; 
 30      memset(_Dest, 0, _Dsize); 
 31      wcstombs(_Dest, _Source, _Dsize); 
 32      string result = _Dest; delete[]_Dest;
 33      setlocale(LC_ALL, curLocale.c_str()); 
 34      return result; 
 35  } 
 36  string String_To_UTF8(const std::string& str) 
 37  { 
 38      int nwLen = ::MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, NULL, 0); 
 39      wchar_t* pwBuf = new wchar_t[nwLen + 1];//一定要加1,不然会出现尾巴 
 40      ZeroMemory(pwBuf, nwLen * 2 + 2); 
 41      ::MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.length(), pwBuf, nwLen); 
 42      int nLen = ::WideCharToMultiByte(CP_UTF8, 0, pwBuf, -1, NULL, NULL, NULL, NULL); char* pBuf = new char[nLen + 1]; 
 43      ZeroMemory(pBuf, nLen + 1); 
 44      ::WideCharToMultiByte(CP_UTF8, 0, pwBuf, nwLen, pBuf, nLen, NULL, NULL); 
 45      std::string retStr(pBuf); delete[]pwBuf; delete[]pBuf; 
 46      pwBuf = NULL; pBuf = NULL; return retStr; 
 47  }
 48  string getMAC(BLUETOOTH_ADDRESS Daddress)
 49  {
 50      /*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]); 
 51      return addr;*/ 
 52      ostringstream oss; oss << hex << setfill('0') << uppercase; 
 53      for (int i = 5; i >= 0; --i) { 
 54      oss << setw(2) << static_cast<int>(Daddress.rgBytes[i]); if (i > 0) { oss << ":"; } }
 55      return oss.str(); 
 56  } 
 57  vector<BLUETOOTH_DEVICE_INFO> scanDevices() 
 58  {
 59      HBLUETOOTH_RADIO_FIND hbf = NULL; 
 60      HANDLE hbr = NULL; HBLUETOOTH_DEVICE_FIND hbdf = NULL;
 61      BLUETOOTH_FIND_RADIO_PARAMS btfrp = { sizeof(BLUETOOTH_FIND_RADIO_PARAMS) }; //调用BluetoothFindFirstDevice搜索本机蓝牙收发器所需要的搜索参数对象 
 62      BLUETOOTH_RADIO_INFO bri = { sizeof(BLUETOOTH_RADIO_INFO) }; //初始化一个储存蓝牙收发器信息(BLUETOOTH_RADIO_INFO)的对象bri 
 63      BLUETOOTH_DEVICE_SEARCH_PARAMS btsp = { sizeof(BLUETOOTH_DEVICE_SEARCH_PARAMS) };//调用BluetoothFindFirstDevice搜索本所需要的搜索参数对象 
 64      BLUETOOTH_DEVICE_INFO btdi = { sizeof(BLUETOOTH_DEVICE_INFO) }; //初始化一个远程蓝牙设备信息(BLUETOOTH_DEVICE_INFO)对象btdi,以储存搜索到的蓝牙设备信息 
 65      hbf = BluetoothFindFirstRadio(&btfrp, &hbr); //得到第一个被枚举的蓝牙收发器的句柄hbf可用于BluetoothFindNextRadio,hbr可用于BluetoothFindFirstDevice。若没有找到本机的蓝牙收发器,则得到的句柄hbf=NULL 
 66      vector<BLUETOOTH_DEVICE_INFO> res; bool brfind = hbf != NULL;
 67      while (brfind) { if (BluetoothGetRadioInfo(hbr, &bri) == ERROR_SUCCESS)//获取蓝牙收发器的信息,储存在bri中 
 68      {
 69          cout << "[Local Device Name]:" << wstring2string(bri.szName) << "\t"; //蓝牙收发器的名字 
 70          cout << "[Local Device Address]: " << getMAC(bri.address) << endl;
 71          cout << "------------------------蓝牙扫描结果如下----------------------------" << endl; 
 72          btsp.hRadio = hbr; //设置执行搜索设备所在的句柄,应设为执行BluetoothFindFirstRadio函数所得到的句柄 
 73          btsp.fReturnAuthenticated = TRUE;//是否搜索已配对的设备 btsp.fReturnConnected = FALSE;//是否搜索已连接的设备 
 74          btsp.fReturnRemembered = TRUE;//是否搜索已记忆的设备 
 75          btsp.fReturnUnknown = TRUE;//是否搜索未知设备 
 76          btsp.fIssueInquiry = TRUE;//是否重新搜索,True的时候会执行新的搜索,时间较长,FALSE的时候会直接返回上次的搜索结果。 
 77          btsp.cTimeoutMultiplier = 30;//指示查询超时的值,以1.28秒为增量。 例如,12.8秒的查询的cTimeoutMultiplier值为10.此成员的最大值为48.当使用大于48的值时,调用函数立即失败并返回 
 78          hbdf = BluetoothFindFirstDevice(&btsp, &btdi);//通过找到第一个设备得到的HBLUETOOTH_DEVICE_FIND句柄hbdf来枚举远程蓝牙设备,搜到的第一个远程蓝牙设备的信息储存在btdi对象中。若没有远程蓝牙设备,hdbf=NULL。 
 79          bool bfind = hbdf != NULL;
 80          int i = 0;
 81          while (bfind) { 
 82          cout << ++i << " " << "[Name]:" << wstring2string(btdi.szName); //远程蓝牙设备的名字 
 83          cout << "\t[Address]:" << getMAC(btdi.Address) << endl; 
 84          res.push_back(btdi); bfind = BluetoothFindNextDevice(hbdf, &btdi);//通过BluetoothFindFirstDevice得到的HBLUETOOTH_DEVICE_FIND句柄来枚举搜索下一个远程蓝牙设备,并将远程蓝牙设备的信息储存在btdi中 } 
 85          BluetoothFindDeviceClose(hbdf);//使用完后记得关闭HBLUETOOTH_DEVICE_FIND句柄hbdf。 } 
 86          CloseHandle(hbr); 
 87          brfind = BluetoothFindNextRadio(hbf, &hbr);//通过BluetoothFindFirstRadio得到的HBLUETOOTH_RADIO_FIND句柄hbf来枚举搜索下一个本地蓝牙收发器,得到可用于BluetoothFindFirstDevice的句柄hbr。 } 
 88          return res; 
 89  } 
 90  void setPassKey() { cout << "请输入配对码:(如果不知道请输入默认0000):"; cin >> PassKey; cout << "您输入的配对码为: " << PassKey << endl; } 
 91  bool pairDevice() 
 92  { 
 93   cout << "输入你想要配对的设备的序号:";
 94   int index; cin >> index; //获取设备信息 device = devices[index - 1]; //输入配对码 
 95   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; 
 96  if (!device.fAuthenticated) { 
 97  result = BluetoothAuthenticateDevice(NULL, btdi, &device, AUTHENTICATION_PASSKEY, (ULONG)wcslen(AUTHENTICATION_PASSKEY)); //配对函数,AUTHENTICATION_PASSKEY是我的蓝牙配对码
 98  if (result != ERROR_SUCCESS) { 
 99     switch (result) { case ERROR_CANCELLED:
100     cout << "用户取消了身份验证或配对操作" << endl; break; case ERROR_INVALID_PARAMETER: cout << "传递给函数的参数无效" << endl; break; 
101     case ERROR_NO_MORE_ITEMS: cout << "没有更多的设备可以配对" << endl; break; case ERROR_NOT_SUPPORTED: cout << "不支持请求的操作" << endl; break;
102     case ERROR_GEN_FAILURE: cout << "通用失败错误" << endl; break; 
103     case ERROR_BUSY: cout << "蓝牙堆栈忙" << endl; break;
104     case ERROR_TIMEOUT: cout << "操作超时" << endl; break; case ERROR_DEVICE_NOT_CONNECTED: cout << "蓝牙设备未连接" << endl; break;
105     case ERROR_DEVICE_NOT_AVAILABLE: cout << "设备不可用" << endl; break; 
106     default: cout << "校验码出错,请手动进行设备连接" << endl; break; } return false; } 
107     } 
108     cout << "身份验证成功,蓝牙设备已成功配对" << endl;; BluetoothUpdateDeviceRecord(&device); return true; 
109     } 
110 bool sendMessage(SOCKET sockClient, string message, int& iCount) {
111     int sum = 0; while (iCount < message.size()) 
112     { 
113     string utf8message = String_To_UTF8(message); iCount = send(sockClient, utf8message.data() + sum, utf8message.size() - sum, 0); 
114     if (iCount == SOCKET_ERROR) { cout << "发送失败" << endl; return false; } sum += iCount; } }
115 bool buildConnect(BLUETOOTH_DEVICE_INFO device, SOCKET& sockClient) {
116     if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
117         cout << "Winsock库初始化失败" << endl;
118         return FALSE;
119     }
120     SOCKET client_socket = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM); 
121     if (client_socket == INVALID_SOCKET) 
122     {     
123         cout << "套接字创建失败" << endl; WSACleanup(); return FALSE; } 
124         sockClient = client_socket; SOCKADDR_BTH serverAddress; memset(&serverAddress, 0, sizeof(serverAddress)); 
125         serverAddress.addressFamily = AF_BTH; BTH_ADDR deviceAddress = device.Address.ullLong; serverAddress.btAddr = deviceAddress; serverAddress.port = 0;
126         serverAddress.serviceClassId = SerialPortServiceClass_UUID;
127         int err = ::connect(client_socket, (SOCKADDR*)&serverAddress, sizeof(serverAddress)); if (0 == err) { } else { cout << "connect连接失败" << endl; 
128         closesocket(client_socket); WSACleanup(); return FALSE; } while (true) { cout << "选择您的操作:1.发送信息 2.退出" << endl; int choice; cin >> choice; 
129         if (choice == 1) { cout << "请输入您想要发送的信息:"; string message; cin >> message; int iCount = 0; 
130         if (sendMessage(client_socket, message, iCount)) { 
131         cout << "信息传输成功,发送字符数:" << iCount << endl;
132         } else {
133             cout << "send失败" << endl; return false; } } 
134         else if (choice == 2) { break; } else {
135             cout << "输入错误,请重新输入" << endl; 
136             } 
137             } 
138         closesocket(client_socket); WSACleanup();
139         BluetoothUpdateDeviceRecord(&device); 
140     return TRUE; } 
141 void main() { 
142 devices = scanDevices();
143  if (pairDevice()) { 
144  buildConnect(device, sockClient); 
145  }
146  return;
147  }

 

标签:NULL,string,Windows,Daddress,蓝牙,c++,BLUETOOTH,include
From: https://www.cnblogs.com/yang131/p/17988354

相关文章

  • C++教程——初识C++(运算符)
    前一节我们初步认识出c++是一门面向对象的程序设计语言,并且我们初步认识了变量,数据类型,常量,输入输出以及合法的标识符命名规则,接下来我们要学习的是运算符。在c++中有逻辑运算符,赋值运算符,算数运算符,位运算符,关系运算符和杂项运算符。先从简单的算数运算符开始讲起,算数运算符简单来......
  • [原创]Windows安装配置PostgreSql_15.5.1数据库
    [原创]Windows安装配置PostgreSql_15.5.1数据库   PostgreSql数据库有多种安装方式,windows上常用的是installer方式、binary手动安装方式,本文采用手动安装的方式处理。总体过程比较简单,有mysql配置经验的分分钟的事儿。    一、下载并解压文件到具体安装目录。 ......
  • windows程序设计---使用c语言开发windows桌面应用程序
     消息机制--队列消息(常规消息鼠标,键盘等等,经过消息循环)GetMessage()得到消息--从消息队列中检索,DispatchMessage()分发消息消息机制----非对列消息-----调用特定windows程序函数触发的消息如:CreateWindow()函数被调用则发送WM_PAINT消息   windows窗口,非客户区是无......
  • VMware下Windows 7安装VMware Tools报错处理
    症状首先安装时它会弹窗选择始终安装最终安装中还是会弹窗提示...驱动安装失败,需要手动安装处理办法由于微软更新了驱动程序签名算法,2019年开始弃用SHA1,改用SHA2。猜测VMwareTools驱动程序使用SHA2,而Windows7只支持SHA1,需要下载安装补丁kb4474419来支持SHA2算法。......
  • 一种windows11连接蓝牙耳机后没有声音的特殊情况
    Windows11连接蓝牙耳机后,显示连接正常,且输出设备也已经切换至蓝牙耳机,可怎么都播放不出声音。最后,在设备管理器中禁用了”适用于蓝牙音频的英特尔智音技术“后,成功解决问题。供遇到类似情况的小伙伴们参考。......
  • 一些C++相关的网站
     https://cppinsights.io/ cppinsights.io是一个在线C++代码查看工具,它可以帮助你深入了解C++代码在编译器层面的实际情况。该工具的主要功能是展示C++代码的编译器输出,即展示编译器对代码进行优化、展开模板、内联函数等操作后的实际代码。 https://zh.cpprefere......
  • C++-类和对象(2)默认成员函数
    在上一篇博客中,和大家分享了C++中类和对象的定义,类的大小的计算等知识,那么如果C++中一个自定义类中不定义任何的成员变量和成员函数,那么这个类中就是一个什么都没有的空类了吗?实际上,如果在一个类中,如果类中什么成员都不定义,编译器会自动生成6个默认成员函数。接下来借助一个自定义M......
  • KY196 复数集合C++
    这题难点就是什么是复数的模了吧。然后C++写个优先队列(大根堆)+操作符重载就行了。#include<iostream>#include<string>#include<queue>#include<math.h>usingnamespacestd;structnode{inta;intb;};typedefstructnodeelement;intchange(strings,......
  • C转C++速成浅入浅出系列——STL之map
    本系列为应付考研复试用,知识浅入浅出,很多地方不深究细节原理;如有谬误,欢迎大家指出。map【map:地图、图谱】理解为地图(我感觉跟python的字典【dictionary】一样)。一个map中包含了多个键值对,一个键值对可以理解为一个特殊的结构体。键值对:即包含关键字(即key)和值(即value或data)的......
  • C语言和C++中的空指针区别
    C语言中,空指针是NULL,是一个宏在C++中NULL似乎也可以用,但是C++中的NULL其实是有问题的。C++大佬在设计的时候可能没有考虑全面在C++98中,字面常量0既可以是一个整形数字,也可以是无类型的指针(void*)常量但是编译器默认情况下将其看成是一个整形常量,如果要将其按照指针方式来使......