1、有一个蓝牙设备,是一个蓝牙模块,非手机或者其他主机。使用SPP协议。
2、使用主机连接这个蓝牙设备,主机是win10系统。在系统中的蓝牙设置中,对这个设备的蓝牙连接,会出现两个虚拟端口。如下图,设备DX2003,会有COM3,COM4两个端口。如果进行数据传输,只能使用COM4端口。
3、开始的时候,使用串口控制来实现对蓝牙设备的数据传输,这种方式比较简单。就是先遍历串口设备,然后选择一个COM口,打开,就可以进行数据传输了。但是有一些缺点,无法通过程序端获取到是哪个端口可用,也无法获取到类似于window系统这样的可以显示出不同端口的名称,再根据名称的后缀来判断。同时,一旦设备断开,对于串口的程序端判断,也不是很及时。在不同电脑上,同一个设备的COM口也会不同,还需要人工去判断,选择。操作模式不够好。
4、基于上述原因,走了另外一条道路。就是使用socket来实现。可通过网络查询,很多都说SPP协议是点对点经典蓝牙模式,没有服务器/客户端的协议。一度放弃,只是可以实现通过设备名称可以找到蓝牙地址的功能。一次偶然的机会,进行测试的时候,突发奇想试试socket能不能连上设备。最后竟然连接上了。设备端是服务器,电脑端是客户端。除了一些设置不同,其他的使用方式和网络没有什么区别。唉,我也不知道为什么。
5、查找蓝牙设备的代码,此代码可以实现对已配对电脑设备的遍历查找。但是无法实现查找未配对设备。
#include <stdlib.h>
#include <stdio.h>
// Link to ws2_32.lib
#include <Winsock2.h>
#include <Ws2bth.h>
// Link to Bthprops.lib
#include <BluetoothAPIs.h>
int main(int argc, char **argv)
{
HANDLE hRadio, hDeviceFind;
BLUETOOTH_DEVICE_INFO_STRUCT deviceInfo;
BLUETOOTH_DEVICE_SEARCH_PARAMS deviceSearchParams;
BLUETOOTH_RADIO_INFO radioInfo;
GUID guidServices[10];
DWORD numServices, result;
int i = 1;
BLUETOOTH_FIND_RADIO_PARAMS btfrp = { sizeof(BLUETOOTH_FIND_RADIO_PARAMS) };
HBLUETOOTH_RADIO_FIND hFind = BluetoothFindFirstRadio(&btfrp, &hRadio);
if (hFind != NULL)
{
printf("BluetoothFindFirstRadio() is working!\n");
do
{
// Do something with the radio handle...
radioInfo.dwSize = sizeof(radioInfo);
if (BluetoothGetRadioInfo(hRadio, &radioInfo) == ERROR_SUCCESS)
{
printf("BluetoothGetRadioInfo() is OK!\n");
printf(" Radio found: %S\n", radioInfo.szName);
}
else
printf("BluetoothGetRadioInfo() failed with error code %d\n", GetLastError());
deviceInfo.dwSize = sizeof(deviceInfo);
memset(&deviceSearchParams, 0, sizeof(deviceSearchParams));
deviceSearchParams.dwSize = sizeof(deviceSearchParams);
// deviceSearchParams.fReturnAuthenticated = TRUE;
deviceSearchParams.fReturnRemembered = TRUE;
//deviceSearchParams.fReturnUnknown = TRUE;
//deviceSearchParams.fReturnConnected = TRUE;
deviceSearchParams.hRadio = hRadio;
hDeviceFind = BluetoothFindFirstDevice(&deviceSearchParams, &deviceInfo);
if (hDeviceFind != NULL)
{
printf("BluetoothFindFirstDevice() is OK!\n");
do
{
printf(" Device found - Name: %S\n", deviceInfo.szName);
printf(" Device found - Address: %X\n", deviceInfo.Address);
printf(" Device found - Device Class: %ul\n", deviceInfo.ulClassofDevice);
numServices = sizeof(guidServices);
// guidServices should contains a complete list of enabled service GUIDs.
result = BluetoothEnumerateInstalledServices(hRadio, &deviceInfo, &numServices, guidServices);
if (result == ERROR_SUCCESS)
{
printf("BluetoothEnumerateInstalledServices() should be fine!\n");
printf(" ...GUID services\n");
}
else
printf("BluetoothEnumerateInstalledServices() failed with error code %d\n", result);
}
while(BluetoothFindNextDevice(hDeviceFind, &deviceInfo));
BluetoothFindDeviceClose(hDeviceFind);
}
// Need to re-allocate, else BluetoothGetDeviceInfo() will fail
memset(&deviceInfo, 0, sizeof(deviceInfo));
deviceInfo.dwSize = sizeof(deviceInfo);
if (BluetoothGetDeviceInfo(hRadio, &deviceInfo))
{
printf("BluetoothGetDeviceInfo() is OK!\n");
printf(" ...More operations...\n");
// BluetoothUpdateDeviceRecord() - change name, BluetoothRemoveDevice() etc.
}
else
printf("BluetoothGetDeviceInfo() failed with error code %d\n", GetLastError());
CloseHandle(hRadio);
} while( BluetoothFindNextRadio(hFind, &hRadio));
BluetoothFindRadioClose(hFind);
}
return 0;
}
6、socket相关设置代码,可以连接蓝牙设备。有过网络通信编程经验的同学,看到这已经可以自主往下进行了。连接成功后,后面使用socket就可以进行数据通讯了。
btSocket = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
memset(&sockAddr, 0, sizeof(sockAddr));
sockAddr.addressFamily = AF_BTH;
sockAddr.serviceClassId = RFCOMM_PROTOCOL_UUID;
sockAddr.port = BT_PORT_ANY;
sockAddr.btAddr = deviceInfo.Address.ullLong;
error = connect(btSocket, (SOCKADDR*)&sockAddr, sizeof(sockAddr));
if (error== SOCKET_ERROR)
{
printf("=CRITICAL= | connect() call failed. WSAGetLastError=[%d]\n", WSAGetLastError());
}
else
{
nLinkState = 1;
printf("--------- Link Sucess!!!------- \n");
break;
}
7、现在可以实现电脑PC端对另一个蓝牙设备模块的数据通讯。电脑是win10,蓝牙是SPP协议。电脑端已经对蓝牙设备进行了配对。然后电脑端写程序使用Socket就可以实现与蓝牙设备的数据传输。虽然已经实现,但还是有很多问题没有想明白。时间有效,暂时先做到这一步,后续有机会,再进行。