Winsock 2 发现蓝牙设备只显示以前配对的设备
Winsock 2 discovering Bluetooth devices only showing previously paired devices
我目前正在尝试使用 WINSOCK 2 API 以发现附近可用的蓝牙设备。我使用的代码基于可以在 here.
中找到的 Microsoft 示例
我主要使用 WSALookupServiceNext 遍历可用设备。问题是我只得到以前配对的蓝牙设备的列表,而我没有看到任何其他设备。我添加了一些代码以打印设备信息:
*********************
Winsock search started!
*********************
Device #:1
Device name:MagicBox II
Device connected: 0
Device remembered: 1
Device authenticated: 1
Remote Bluetooth device is 0x00025b3dc371, server channel = 0
Local Bluetooth device is 0x84ef18b8460a, server channel = 0
Device #:2
Device name:Mpow Flame
Device connected: 0
Device remembered: 1
Device authenticated: 1
Remote Bluetooth device is 0x501801101c68, server channel = 0
Local Bluetooth device is 0x84ef18b8460a, server channel = 0
Device #:3
Device name:WH-1000XM2
Device connected: 0
Device remembered: 1
Device authenticated: 1
Remote Bluetooth device is 0x702605aba41d, server channel = 0
Local Bluetooth device is 0x84ef18b8460a, server channel = 0
Device #:4
Device name:Magicbuds
Device connected: 0
Device remembered: 1
Device authenticated: 1
Remote Bluetooth device is 0x5017032a701b, server channel = 0
Local Bluetooth device is 0x84ef18b8460a, server channel = 0
这是相应的代码部分,(我事先调用了 WSAStartup):
void WSALookupAvailableDevices(void)
{
WSAQUERYSET wsaQuery{};
LPWSAQUERYSET pwsaResults{};
HANDLE hLookup{};
CSADDR_INFO *pAddrInfo{};
SOCKADDR_BTH *pBtSockRemote{},
*pBtSockLocal{};
char buffer[4096] = {};
int nDevicesFound = 1;
DWORD swSize = sizeof(buffer);
DWORD flags = LUP_RETURN_ADDR | LUP_RETURN_NAME | LUP_RES_SERVICE | LUP_CONTAINERS | LUP_RETURN_BLOB | LUP_RETURN_TYPE;
/*Preparing the query set*/
wsaQuery.dwNameSpace = NS_BTH;
wsaQuery.dwSize = sizeof(WSAQUERYSET);
if (WSALookupServiceBegin(&wsaQuery, flags, &hLookup) == SOCKET_ERROR)
{
wprintf(L"Shit something went wrong! error: %d!\n", WSAGetLastError());
return;
}
wprintf(L"*********************\n");
wprintf(L"Winsock search started!\n");
wprintf(L"*********************\n\n");
/*Preparing the queryset return buffer*/
pwsaResults = (LPWSAQUERYSET)buffer;
pwsaResults->dwNameSpace = NS_BTH;
pwsaResults->dwSize = sizeof(WSAQUERYSET);
while (WSALookupServiceNext(hLookup, flags, &swSize, pwsaResults) == NO_ERROR)
{
pAddrInfo = (CSADDR_INFO*)pwsaResults->lpcsaBuffer;
pBtSockRemote = (SOCKADDR_BTH*)(pwsaResults->lpcsaBuffer->RemoteAddr.lpSockaddr);
pBtSockLocal = (SOCKADDR_BTH*)(pwsaResults->lpcsaBuffer->LocalAddr.lpSockaddr);
wprintf(L"Device #:%d\n", nDevicesFound);
wprintf(L"Device name:%s\n", pwsaResults->lpszServiceInstanceName);
wprintf(L"Device connected: %d\n", (pwsaResults->dwOutputFlags & BTHNS_RESULT_DEVICE_CONNECTED));
wprintf(L"Device remembered: %d\n", (pwsaResults->dwOutputFlags & BTHNS_RESULT_DEVICE_REMEMBERED)>0);
wprintf(L"Device authenticated: %d\n", (pwsaResults->dwOutputFlags & BTHNS_RESULT_DEVICE_AUTHENTICATED)>0);
wprintf(L"Remote Bluetooth device is 0x%04x%08x, server channel = %d\n",
GET_NAP(pBtSockRemote->btAddr), GET_SAP(pBtSockRemote->btAddr), pBtSockRemote->port);
wprintf(L"Local Bluetooth device is 0x%04x%08x, server channel = %d\n",
GET_NAP(pBtSockLocal->btAddr), GET_SAP(pBtSockLocal->btAddr), pBtSockLocal->port);
nDevicesFound++;
}
WSALookupServiceEnd(hLookup);
wprintf(L"\n");
}
提前感谢您的帮助!
LUP_FLUSHCACHE 就是您所需要的。是的,它总是 return 配对设备(除了发现)。我的意思是如果设备配对 WSALookup return 它在列表中,即使它不可用(关闭或超出范围)。
DWORD flags = LUP_RETURN_ADDR | LUP_RETURN_NAME | LUP_RES_SERVICE | LUP_CONTAINERS | LUP_RETURN_BLOB | LUP_RETURN_TYPE | LUP_FLUSHCACHE;
但发现设备的最佳方法是使用此标志集。
DWORD flags = LUP_RETURN_ADDR | LUP_CONTAINERS | LUP_FLUSHCACHE;
此外,最好提供额外的信息 (BTH_QUERY_DEVICE),以便您可以设置发现超时和其他参数
BTH_QUERY_DEVICE qDev;
qDev.LAP = 0;
qDev.length = bTimeout; // Timeout in seconds
BLOB Blb;
Blb.cbSize = sizeof(BTH_QUERY_DEVICE);
Blb.pBlobData = (PBYTE)&qDev;
QuerySet.lpBlob = &Blb;
https://docs.microsoft.com/th-th/windows/desktop/api/ws2bth/ns-ws2bth-_bth_query_device
发现完成后(请注意 WSALookupServiceBegin 需要时间(块)直到发现完成)您可以使用 BluetoothGetDeviceInfo 获取扩展信息,例如设备名称和其他信息。
您应该知道,由于某些蓝牙限制,名称解析只能在发现完成后才能执行。而且这个操作可能需要时间。因此,如果您在发现完成后立即调用 BluetoothGetDeviceInfo,您仍然可以获得新发现设备(之前未发现的设备)的空设备名称。
除了切换到 WinRT API 或等待一段时间再读取设备名称外,没有其他简单的方法可以解决此问题。您还可以使用 WM_DEVICECHANGE 消息来获取有关设备名称解析的通知
https://docs.microsoft.com/en-us/windows/desktop/bluetooth/bluetooth-and-wm-devicechange-messages
还有一个问题:MS 堆栈总是 return在发现过程中 sd 配对设备,即使它们不可用。
我目前正在尝试使用 WINSOCK 2 API 以发现附近可用的蓝牙设备。我使用的代码基于可以在 here.
中找到的 Microsoft 示例我主要使用 WSALookupServiceNext 遍历可用设备。问题是我只得到以前配对的蓝牙设备的列表,而我没有看到任何其他设备。我添加了一些代码以打印设备信息:
*********************
Winsock search started!
*********************
Device #:1
Device name:MagicBox II
Device connected: 0
Device remembered: 1
Device authenticated: 1
Remote Bluetooth device is 0x00025b3dc371, server channel = 0
Local Bluetooth device is 0x84ef18b8460a, server channel = 0
Device #:2
Device name:Mpow Flame
Device connected: 0
Device remembered: 1
Device authenticated: 1
Remote Bluetooth device is 0x501801101c68, server channel = 0
Local Bluetooth device is 0x84ef18b8460a, server channel = 0
Device #:3
Device name:WH-1000XM2
Device connected: 0
Device remembered: 1
Device authenticated: 1
Remote Bluetooth device is 0x702605aba41d, server channel = 0
Local Bluetooth device is 0x84ef18b8460a, server channel = 0
Device #:4
Device name:Magicbuds
Device connected: 0
Device remembered: 1
Device authenticated: 1
Remote Bluetooth device is 0x5017032a701b, server channel = 0
Local Bluetooth device is 0x84ef18b8460a, server channel = 0
这是相应的代码部分,(我事先调用了 WSAStartup):
void WSALookupAvailableDevices(void)
{
WSAQUERYSET wsaQuery{};
LPWSAQUERYSET pwsaResults{};
HANDLE hLookup{};
CSADDR_INFO *pAddrInfo{};
SOCKADDR_BTH *pBtSockRemote{},
*pBtSockLocal{};
char buffer[4096] = {};
int nDevicesFound = 1;
DWORD swSize = sizeof(buffer);
DWORD flags = LUP_RETURN_ADDR | LUP_RETURN_NAME | LUP_RES_SERVICE | LUP_CONTAINERS | LUP_RETURN_BLOB | LUP_RETURN_TYPE;
/*Preparing the query set*/
wsaQuery.dwNameSpace = NS_BTH;
wsaQuery.dwSize = sizeof(WSAQUERYSET);
if (WSALookupServiceBegin(&wsaQuery, flags, &hLookup) == SOCKET_ERROR)
{
wprintf(L"Shit something went wrong! error: %d!\n", WSAGetLastError());
return;
}
wprintf(L"*********************\n");
wprintf(L"Winsock search started!\n");
wprintf(L"*********************\n\n");
/*Preparing the queryset return buffer*/
pwsaResults = (LPWSAQUERYSET)buffer;
pwsaResults->dwNameSpace = NS_BTH;
pwsaResults->dwSize = sizeof(WSAQUERYSET);
while (WSALookupServiceNext(hLookup, flags, &swSize, pwsaResults) == NO_ERROR)
{
pAddrInfo = (CSADDR_INFO*)pwsaResults->lpcsaBuffer;
pBtSockRemote = (SOCKADDR_BTH*)(pwsaResults->lpcsaBuffer->RemoteAddr.lpSockaddr);
pBtSockLocal = (SOCKADDR_BTH*)(pwsaResults->lpcsaBuffer->LocalAddr.lpSockaddr);
wprintf(L"Device #:%d\n", nDevicesFound);
wprintf(L"Device name:%s\n", pwsaResults->lpszServiceInstanceName);
wprintf(L"Device connected: %d\n", (pwsaResults->dwOutputFlags & BTHNS_RESULT_DEVICE_CONNECTED));
wprintf(L"Device remembered: %d\n", (pwsaResults->dwOutputFlags & BTHNS_RESULT_DEVICE_REMEMBERED)>0);
wprintf(L"Device authenticated: %d\n", (pwsaResults->dwOutputFlags & BTHNS_RESULT_DEVICE_AUTHENTICATED)>0);
wprintf(L"Remote Bluetooth device is 0x%04x%08x, server channel = %d\n",
GET_NAP(pBtSockRemote->btAddr), GET_SAP(pBtSockRemote->btAddr), pBtSockRemote->port);
wprintf(L"Local Bluetooth device is 0x%04x%08x, server channel = %d\n",
GET_NAP(pBtSockLocal->btAddr), GET_SAP(pBtSockLocal->btAddr), pBtSockLocal->port);
nDevicesFound++;
}
WSALookupServiceEnd(hLookup);
wprintf(L"\n");
}
提前感谢您的帮助!
LUP_FLUSHCACHE 就是您所需要的。是的,它总是 return 配对设备(除了发现)。我的意思是如果设备配对 WSALookup return 它在列表中,即使它不可用(关闭或超出范围)。
DWORD flags = LUP_RETURN_ADDR | LUP_RETURN_NAME | LUP_RES_SERVICE | LUP_CONTAINERS | LUP_RETURN_BLOB | LUP_RETURN_TYPE | LUP_FLUSHCACHE;
但发现设备的最佳方法是使用此标志集。
DWORD flags = LUP_RETURN_ADDR | LUP_CONTAINERS | LUP_FLUSHCACHE;
此外,最好提供额外的信息 (BTH_QUERY_DEVICE),以便您可以设置发现超时和其他参数
BTH_QUERY_DEVICE qDev;
qDev.LAP = 0;
qDev.length = bTimeout; // Timeout in seconds
BLOB Blb;
Blb.cbSize = sizeof(BTH_QUERY_DEVICE);
Blb.pBlobData = (PBYTE)&qDev;
QuerySet.lpBlob = &Blb;
https://docs.microsoft.com/th-th/windows/desktop/api/ws2bth/ns-ws2bth-_bth_query_device
发现完成后(请注意 WSALookupServiceBegin 需要时间(块)直到发现完成)您可以使用 BluetoothGetDeviceInfo 获取扩展信息,例如设备名称和其他信息。
您应该知道,由于某些蓝牙限制,名称解析只能在发现完成后才能执行。而且这个操作可能需要时间。因此,如果您在发现完成后立即调用 BluetoothGetDeviceInfo,您仍然可以获得新发现设备(之前未发现的设备)的空设备名称。
除了切换到 WinRT API 或等待一段时间再读取设备名称外,没有其他简单的方法可以解决此问题。您还可以使用 WM_DEVICECHANGE 消息来获取有关设备名称解析的通知
https://docs.microsoft.com/en-us/windows/desktop/bluetooth/bluetooth-and-wm-devicechange-messages
还有一个问题:MS 堆栈总是 return在发现过程中 sd 配对设备,即使它们不可用。