关于使用c++制作蓝牙连接,Windows版本
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 }
关于使用c++制作蓝牙连接,Windows版本的更多相关文章
- 微信小程序-蓝牙连接
最近的项目需要使用小程序的蓝牙功能与硬件设备进行连接相互传送数据指令,联调过程中发现一些问题,于是想着记录下来,方便以后查看! 1.0一般使用蓝牙功能肯定是想连接某一个蓝牙设备,所以需要知道这个蓝牙设 ...
- MYSQL—第一部分(简介和windows版本的安装)
一.概述 1.什么是数据库 ? 答:数据的仓库,如:在自己编写的程序中我们创建了一个 db 目录,称其为数据库 2.什么是 MySQL.Oracle.SQLite.Access.MS SQLServe ...
- 制作MySQL的Windows服务+创建用户及授权
在上一篇随笔中详述了MySQL的Windows 64位版本的安装,以及初始化操作.启动服务端.客户端连接.一些基本的文件操作等.然而在进行这些操作的时候,需要我们去输入一长串的路径和命令才能 ...
- SSH客户端工具连接Linux(有的也可以连接Windows、mac、iOS等多系统平台)
要远程操作Linux的话还是得靠SSH工具,一般来说,Linux是打开了默认22端口的SSH的服务端,如果我们要远程它的话,就需要一个SSH客户. 我对一款好用的工具主要需要满足以下几点. (1)连接 ...
- 史上最全Windows版本搭建安装React Native环境配置
史上最全Windows版本搭建安装React Native环境配置 配置过React Native 环境的都知道,在Windows React Native环境配置有很多坑要跳,为了帮助新手快速无误的 ...
- 用Advanced Installer制作DotNetBar for Windows Forms 12.0.0.1_冰河之刃重打包版详解
关于 DotNetBar for Windows Forms 12.0.0.1_冰河之刃重打包版 --------------------11.8.0.8_冰河之刃重打包版-------------- ...
- 使用windows远程桌面连接Windows Azure中的Ubuntu虚拟机
1.创建ubuntu虚拟机,这里同样不再赘述,创建过程和创建Windows虚拟机基本一样,只是登录可以选择密钥注入或者用户名密码(为了方便我选择了用户名密码认证),创建完成后,查看虚拟机详情中的端口信 ...
- Redis进阶实践之六Redis Desktop Manager连接Windows和Linux系统上的Redis服务
一.引言 今天本来没有打算写这篇文章,当初我感觉使用这个工具应该很简单,下载的过程也不复杂,也没有打算记录下来.但是在使用的过程中还是出现了一些问题,为了给第一次使用Redis Desktop Man ...
- hiredis的各种windows版本
hiredis的各种windows版本(金庆的专栏 2016.12)hiredis 是内存数据库 redis 的客户端C库, 不支持Windows.hiredis的Windows移植版本有许多:des ...
- JRockit Mission Control建立到Tomcat的连接(windows)
http://www.360doc.com/content/10/0928/16/203871_57086538.shtml 蓝海豹 JRockit Mission Control建立到Tomcat ...
随机推荐
- 用tkinter编写一个简单的登录注册界面
代码: from tkinter import * window = Tk() window.geometry('400x300+500+150') window.title('xxx系统') Can ...
- NET框架下如何使用PaddleOCRSharp
打开VSIDE,新建Windows窗体应用(.NET Framework)类型的项目,选择一个.NET框架,如.NET Framework 4.0,右键点击项目,选择属性>生成,目标平台设置成X ...
- 7.30考试总结(NOIP模拟28)[遗忘之祭仪·客星璀璨之夜·割海成路之日]
一个人有表里两面,你能看到的,仅仅是其中一面而已. 前言 看着这套题非常不可做,但是经历的所有的模拟赛中,这次还是第一次切题(惭愧) 本来 T1 我 1h 就码完了,交了一遍 TLE90 然后后来两个 ...
- Pyinstaller打包exe的反编译——LitCTF 2024(公开赛道)ezpython!!!!!
这个工具折磨了我很久,搭配题目记录一下... 题目 Die 打包工具: PyInstaller 建议下载GitHub的:GitHub - extremecoders-re/pyinstxtractor ...
- 小程序视图组件 scroll-view
视图容器组件 3.2.1.swiper 滑块视图容器. https://developers.weixin.qq.com/miniprogram/dev/component/swiper.html 3 ...
- kettle从入门到精通 第十九课 kettle 资源仓库
1.kettle 里面的资源仓库的意思就是存放转换(.ktr)或者job(.kjb)文件的地方.通过spoon客户端右上角可以进行设置资源仓库. 2.kettle的资源仓库有三种方式 1)本地文件存储 ...
- json null (空值)不序列化
json null (空值)不序列化 JsonSerializerSettings jsetting = new JsonSerializerSettings(); jsetting.DefaultV ...
- 如何发现及处理 MySQL 主从延迟问题
在 Percona MySQL 支持团队中,我们经常看到客户抱怨复制延迟的问题.当然,这对 MySQL 用户来说并不是什么新鲜事,多年来我们在 MySQL 性能博客上发表过一些关于这个主题的文章(过去 ...
- 妙用OSGraph:发掘GitHub知识图谱上的开源故事
1. 何为OSGraph? OSGraph (Open Source Graph) 是一个开源图谱关系洞察工具,基于GitHub开源数据全域图谱,实现开发者行为.项目社区生态的分析洞察.可以为开发者. ...
- 交通规划四阶段法:基于 Python 的交通分布预测算法复现 - 附完整代码链接
目录 交通规划四阶段法:基于 Python 的交通分布预测算法复现 - 附完整代码链接 我只是想使用这些代码 下载代码文件 代码的使用方法 合作 部分代码内容的展示 交通规划四阶段法:基于 Pytho ...