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. 微信小程序-蓝牙连接

    最近的项目需要使用小程序的蓝牙功能与硬件设备进行连接相互传送数据指令,联调过程中发现一些问题,于是想着记录下来,方便以后查看! 1.0一般使用蓝牙功能肯定是想连接某一个蓝牙设备,所以需要知道这个蓝牙设 ...

  2. MYSQL—第一部分(简介和windows版本的安装)

    一.概述 1.什么是数据库 ? 答:数据的仓库,如:在自己编写的程序中我们创建了一个 db 目录,称其为数据库 2.什么是 MySQL.Oracle.SQLite.Access.MS SQLServe ...

  3. 制作MySQL的Windows服务+创建用户及授权

         在上一篇随笔中详述了MySQL的Windows 64位版本的安装,以及初始化操作.启动服务端.客户端连接.一些基本的文件操作等.然而在进行这些操作的时候,需要我们去输入一长串的路径和命令才能 ...

  4. SSH客户端工具连接Linux(有的也可以连接Windows、mac、iOS等多系统平台)

    要远程操作Linux的话还是得靠SSH工具,一般来说,Linux是打开了默认22端口的SSH的服务端,如果我们要远程它的话,就需要一个SSH客户. 我对一款好用的工具主要需要满足以下几点. (1)连接 ...

  5. 史上最全Windows版本搭建安装React Native环境配置

    史上最全Windows版本搭建安装React Native环境配置 配置过React Native 环境的都知道,在Windows React Native环境配置有很多坑要跳,为了帮助新手快速无误的 ...

  6. 用Advanced Installer制作DotNetBar for Windows Forms 12.0.0.1_冰河之刃重打包版详解

    关于 DotNetBar for Windows Forms 12.0.0.1_冰河之刃重打包版 --------------------11.8.0.8_冰河之刃重打包版-------------- ...

  7. 使用windows远程桌面连接Windows Azure中的Ubuntu虚拟机

    1.创建ubuntu虚拟机,这里同样不再赘述,创建过程和创建Windows虚拟机基本一样,只是登录可以选择密钥注入或者用户名密码(为了方便我选择了用户名密码认证),创建完成后,查看虚拟机详情中的端口信 ...

  8. Redis进阶实践之六Redis Desktop Manager连接Windows和Linux系统上的Redis服务

    一.引言 今天本来没有打算写这篇文章,当初我感觉使用这个工具应该很简单,下载的过程也不复杂,也没有打算记录下来.但是在使用的过程中还是出现了一些问题,为了给第一次使用Redis Desktop Man ...

  9. hiredis的各种windows版本

    hiredis的各种windows版本(金庆的专栏 2016.12)hiredis 是内存数据库 redis 的客户端C库, 不支持Windows.hiredis的Windows移植版本有许多:des ...

  10. JRockit Mission Control建立到Tomcat的连接(windows)

    http://www.360doc.com/content/10/0928/16/203871_57086538.shtml  蓝海豹 JRockit Mission Control建立到Tomcat ...

随机推荐

  1. CentOS搭建Jellyfin影音服务器

    一. 安装Jellyfin 之前介绍过Docker安装jellyfin,但Docker安装方式存在一些限制,于是一起学习一下用RPM包在CentOS 7下安装方法. 先安装需要的依赖: yum ins ...

  2. golang 怎么获取kubernetes deployments的状态?

    如果我们需要把k8s的信息展示为一个友好的web页面.那么deployment 的信息基本上是非常重要的(大部分的服务都是使用deployment部署). 从yaml 中我们能获取到很多关于deplo ...

  3. 记一次Idea无法打开记录(idea升级)

    记一次Idea无法打开记录 前言,本来今天是打算升级Idea,然后体验一波的,结果升级完之后,发现无法打开idea(双击之后并没有任何打开的反应). 原因排查,打开idea所在目录,找到idea.ba ...

  4. H.265码流解析

    这一篇内容旨在对H.265码流中的一些概念做简单了解,部分概念与H.264相同,本篇中将不再重复. 1.NALU H.265(HEVC)码流的NALU结构和AVC有一些不同,属于增强版,HEVC NA ...

  5. 微信小程序预约视频号直播

    一.概述 微信小程序提供了可以唤起预约视频号直播弹窗的接口 reserveChannelsLive,该接口接收一个参数 noticeId,通过 getChannelsLiveNoticeInfo 接口 ...

  6. 智影AI故事转视频创作神器!快速开启AI绘画小说推文之旅

    1.前言 1.1 生成内容形式 生成内容形式主要包含三种,PGC(Professionally Generated Content).UGC(User Generated Content).AIGC( ...

  7. 莫烦tensorflow学习记录 (4)Classification 分类学习

    MNIST 数据 首先准备数据(MNIST库) from tensorflow.examples.tutorials.mnist import input_data mnist = input_dat ...

  8. NumPy 通用函数(ufunc):高性能数组运算的利器

    NumPy 通用函数(ufunc) 简介 NumPy 通用函数(ufunc),代表"通用函数",是一类用于对 ndarray 对象进行逐元素运算的高性能函数.ufunc 使 Num ...

  9. 使用edge浏览器时,怎么让alt+tab不切换他的子标签页而只在程序间切换?

    使用搜索按钮(WIN+Q),搜索"多任务设置",在弹出的窗口中看到"alt+tab"相关设置.选择"仅打开的窗口",ok搞定.

  10. Python数据类型(数字,字符串,[列表],(元组),{字典:字典值},{列表,列表2})

    Python数据类型(数字,字符串,[列表],(元组),{字典:字典值},{列表,列表2}) # 1. # Python3 数字(Number) # Python 数字数据类型用于存储数值. # 数据 ...