有没有办法在Windows编程中以编程方式配对蓝牙设备?

3
有一个问题: 有没有办法在Windows上以编程方式配对蓝牙设备?(c ++,c#)
感谢回复。

你应该使用WinRT Windows.Devices.Enumeration配对API。这里有一个示例:https://learn.microsoft.com/en-us/samples/microsoft/windows-universal-samples/deviceenumerationandpairing/ - sam msft
5个回答

3

我能在商业项目中使用32feet.NET吗? - Taras
@Division_Bell: 许可证在这里(http://32feet.codeplex.com/license)。看起来商业使用是可以的,只要你给予适当的信用,但是需要在需要可靠法律建议时与律师联系。 - Ben Voigt
Windows蓝牙堆栈在过去的10年中没有对win32 API进行投资。本示例介绍了如何使用WinRT配对API来进行C++(推荐:CppWinrt)和C#等编程语言的开发。请访问以下链接获取更多信息:https://learn.microsoft.com/en-us/samples/microsoft/windows-universal-samples/deviceenumerationandpairing/ - sam msft

3
Python是一个诱人且总体易于解决的方案,但PyBlueZ在此处未公开Windows蓝牙身份验证API:https://msdn.microsoft.com/en-us/library/windows/desktop/cc766819(v=vs.85).aspx 解决方法之一是创建一个命令行工具并通过Python使用它。要为Windows创建命令行工具,请使用Visual Studio并将必要的库添加到项目链接器属性中:Bthprops.lib和ws2_32.lib。
下面是一个项目的代码,用于制作具有1个参数(MAC地址)的命令行工具,该工具使用“Just Works”配对来配对指定的设备。请参见使用密码配对的注释代码。
#include "stdafx.h"
#include <initguid.h>
#include <winsock2.h>
#include <BluetoothAPIs.h>
#include <ws2bth.h>

BOOL WINAPI BluetoothAuthCallback(LPVOID pvParam, PBLUETOOTH_AUTHENTICATION_CALLBACK_PARAMS pAuthCallbackParams);

int _tmain(int argc, _TCHAR* argv[])
{
    SOCKADDR_BTH sa = { 0 };
    int sa_len = sizeof(sa);
    DWORD dwRet;
    BLUETOOTH_DEVICE_INFO  btdi = { 0 };
    HBLUETOOTH_AUTHENTICATION_REGISTRATION hRegHandle = 0;

    // initialize windows sockets
    WORD wVersionRequested;
    WSADATA wsaData;
    wVersionRequested = MAKEWORD(2, 0);
    if (WSAStartup(wVersionRequested, &wsaData) != 0) {
        ExitProcess(2);
    }

    // parse the specified Bluetooth address
    if (argc < 2) {
        fprintf(stderr, "usage: csbtpair <addr>\n"
            "\n  addr must be in the form (XX:XX:XX:XX:XX:XX)");
        ExitProcess(2);
    }
    if (SOCKET_ERROR == WSAStringToAddress(argv[1], AF_BTH,
        NULL, (LPSOCKADDR)&sa, &sa_len)) {
        ExitProcess(2);
    }

    // setup device info
    btdi.dwSize = sizeof(BLUETOOTH_DEVICE_INFO);
    btdi.Address.ullLong = sa.btAddr;
    btdi.ulClassofDevice = 0;
    btdi.fConnected = false;
    btdi.fRemembered = false;
    btdi.fAuthenticated = false;

    // register authentication callback. this prevents UI from showing up.
    dwRet = BluetoothRegisterForAuthenticationEx(&btdi, &hRegHandle, &BluetoothAuthCallback, NULL);
    if (dwRet != ERROR_SUCCESS)
    {
        fprintf(stderr, "BluetoothRegisterForAuthenticationEx ret %d\n", dwRet);
        ExitProcess(2);
    }

    // authenticate device (will call authentication callback)
    AUTHENTICATION_REQUIREMENTS authreqs = MITMProtectionNotRequired;
    fprintf(stderr, "BluetoothAuthReqs = %d\n", authreqs);
    dwRet = BluetoothAuthenticateDeviceEx(NULL, NULL, &btdi, NULL, authreqs);
    if (dwRet != ERROR_SUCCESS)
    {
        fprintf(stderr, "BluetoothAuthenticateDevice ret %d\n", dwRet);
        if (dwRet == ERROR_CANCELLED)
        {
            fprintf(stderr, "Cancelled");
        }
        else if (dwRet == ERROR_INVALID_PARAMETER)
        {
            fprintf(stderr, "Invalid Parameter");
        }
        else if (dwRet == ERROR_NO_MORE_ITEMS)
        {
            fprintf(stderr, "Already paired!");
        }
    }

    fprintf(stderr, "pairing finish\n");
    ExitProcess(0);
    return 0;
}

// Authentication callback
BOOL WINAPI BluetoothAuthCallback(LPVOID pvParam, PBLUETOOTH_AUTHENTICATION_CALLBACK_PARAMS pAuthCallbackParams)
{
    DWORD dwRet;

    fprintf(stderr, "BluetoothAuthCallback 0x%x\n", pAuthCallbackParams->deviceInfo.Address.ullLong);
    BLUETOOTH_AUTHENTICATE_RESPONSE AuthRes;
    AuthRes.authMethod = pAuthCallbackParams->authenticationMethod;
    fprintf(stderr, "Authmethod %d\n", AuthRes.authMethod);
    // Check to make sure we are using numeric comparison (Just Works)
    if (AuthRes.authMethod == BLUETOOTH_AUTHENTICATION_METHOD_NUMERIC_COMPARISON) 
    {
        fprintf(stderr, "Numeric Comparison supported\n");
    }
    AuthRes.bthAddressRemote = pAuthCallbackParams->deviceInfo.Address;
    AuthRes.negativeResponse = FALSE;

    // Commented out code is used for pairing using the BLUETOOTH_AUTHENTICATION_METHOD_PASSKEY method
    //memcpy_s(AuthRes.pinInfo.pin, sizeof(AuthRes.pinInfo.pin), L"1234", 0);
    //AuthRes.pinInfo.pinLength = 0;
    // Respond with numerical value for Just Works pairing
    AuthRes.numericCompInfo.NumericValue = 1;

    // Send authentication response to authenticate device
    dwRet = BluetoothSendAuthenticationResponseEx(NULL, &AuthRes);
    if (dwRet != ERROR_SUCCESS)
    {
        fprintf(stderr, "BluetoothSendAuthenticationResponseEx ret %d\n", dwRet);
        if (dwRet == ERROR_CANCELLED)
        {
            fprintf(stderr, "Bluetooth device denied passkey response or communicatino problem.\n");
        }
        else if (dwRet == E_FAIL)
        {
            fprintf(stderr, "Device returned a failure code during authentication.\n");
        }
        else if (dwRet == 1244)
        {
            fprintf(stderr, "Not authenticated\n");
        }
    }
    else
    {
        fprintf(stderr, "BluetoothAuthCallback finish\n");
    }

    return 1; // This value is ignored
}

如果您不想自己创建,可以尝试使用预制解决方案: http://bluetoothinstaller.com/bluetooth-command-line-tools/ 但这并未适用于我的特定解决方案。

接下来,您需要以管理员身份从Python运行下载或自定义的命令行工具。为了可靠地执行此操作,我建议查看stackoverflow问题: 如何在Windows上以提升的权限运行Python脚本


2

这是最正确的答案。设备枚举和配对示例展示了如何最好地完成此操作。WinRT API和内置系统UX配对最终确实使用了相同的流程和内部API,但它们有些不同。要理解其中的原因,WinRT API需要一个代理,即设备关联代理(DAB),以便能够为低完整性级别的应用容器进程配对设备。实际上,Windows shell也在低完整性级别下运行许多UI,并且也使用代理来进行配对等操作,但一旦代码到达代理层,WinRT API和shell UX非常相似。 - sam msft

1

我遇到了同样的问题,但我已经解决了它。也许你可以试一下:

  1. make a windows tool named pairtool.exe, it help you to pairing with command line. the key api is BluetoothAuthenticateDevice, please refering the functions document

    dwRet = BluetoothAuthenticateDevice(NULL, NULL, &btdi, L"1234", 4);
    if(dwRet != ERROR_SUCCESS)
    {
        fprintf(stderr, "BluetoothAuthenticateDevice ret %d\n", dwRet);
        ExitProcess(2);
    }
    
  2. python code:

    def connect2Btdev(devName):
    #found the device addr
    addr = inquiry(devName)
    if addr == None:
       return None
    
    #pairing with pairtool.exe
    cmd=r'%s %s' % ('pairtool.exe',addr)
    ret = os.system(cmd)
    
    if ret <> 0:
        return None
    

这里是pairtool.exe的全部代码:

#include "stdafx.h"
#include <initguid.h>
#include <winsock2.h>
#include <BluetoothAPIs.h>
#include <ws2bth.h>

bool BluetoothAuthCallback(LPVOID pvParam, PBLUETOOTH_AUTHENTICATION_CALLBACK_PARAMS pAuthCallbackParams)
{
    DWORD dwRet;

    fprintf(stderr, "BluetoothAuthCallback 0x%x\n", pAuthCallbackParams->deviceInfo.Address.ullLong);

    dwRet = BluetoothSendAuthenticationResponse(NULL, &(pAuthCallbackParams->deviceInfo), L"1234");
    if(dwRet != ERROR_SUCCESS)
    {
        fprintf(stderr, "BluetoothSendAuthenticationResponse ret %d\n", dwRet);
        ExitProcess(2);
        return 1;
    }
    fprintf(stderr, "BluetoothAuthCallback finish\n");
    ExitProcess(0);
    return 1;
}

int _tmain(int argc, _TCHAR* argv[])
{
    SOCKADDR_BTH sa = { 0 };
    int sa_len = sizeof(sa);
    DWORD dwRet;
    BLUETOOTH_DEVICE_INFO  btdi = {0};
    HBLUETOOTH_AUTHENTICATION_REGISTRATION hRegHandle = 0;

    // initialize windows sockets
    WORD wVersionRequested;
    WSADATA wsaData;
    wVersionRequested = MAKEWORD( 2, 0 );
    if( WSAStartup( wVersionRequested, &wsaData ) != 0 ) {
        ExitProcess(2);
    }

    // parse the specified Bluetooth address
    if( argc < 2 ) {
        fprintf(stderr, "usage: rfcomm-client <addr>\n"
                "\n  addr must be in the form (XX:XX:XX:XX:XX:XX)");
        ExitProcess(2);
    }
    if( SOCKET_ERROR == WSAStringToAddress( argv[1], AF_BTH,
                NULL, (LPSOCKADDR) &sa, &sa_len ) ) {
        ExitProcess(2);
    }

    //注册回调函数
    btdi.dwSize = sizeof(BLUETOOTH_DEVICE_INFO);
    btdi.Address.ullLong = sa.btAddr;
    btdi.ulClassofDevice = 0;
    btdi.fConnected = false;
    btdi.fRemembered = false;
    btdi.fAuthenticated = false;

    dwRet = BluetoothRegisterForAuthenticationEx(&btdi, &hRegHandle, &BluetoothAuthCallback, NULL);
    if(dwRet != ERROR_SUCCESS)
    {
        fprintf(stderr, "BluetoothRegisterForAuthenticationEx ret %d\n", dwRet);
        ExitProcess(2);
    }

    dwRet = BluetoothAuthenticateDevice(NULL, NULL, &btdi, L"1234", 4);
    if(dwRet != ERROR_SUCCESS)
    {
        fprintf(stderr, "BluetoothAuthenticateDevice ret %d\n", dwRet);
        ExitProcess(2);
    }

    Sleep(1000);
      fprintf(stderr, "pairing finish\n");
    ExitProcess(0);

    return 0;
}

在最近的Windows版本中,有一个内置的pairtool.exe工具。它位于c:\windows\system32\pairtool.exe。以下是其功能: C:>pairtool Microsoft设备配对工具pairtool [/enum-endpoints <...> | /enum-services <...> | /enum-containers <...> | /enum-protocols <...> | /associate <...> | /associate-oob <...> | /disassociate <...> | /challenge <...> | /?] - sam msft

-1
您可以通过使用MSDN 蓝牙函数文档记录下的函数来实现。这些函数可编程地实现搜索和配对蓝牙设备的功能。

不,你应该使用WinRT Windows.Devices.Enumeration配对API。 这里有一个示例:https://learn.microsoft.com/en-us/samples/microsoft/windows-universal-samples/deviceenumerationandpairing/ - sam msft
我不相信这个API在2012年就可用了。这个问题相当久远了。 - Turbo J
有道理。在Win8/8.1时期,配对功能并不完善。你可能只能使用功能发现。我在TH1或TH2时期编写了WinRT配对API...这是Windows 10最初版本的代号。目前来看,只要SKU支持蓝牙,几乎所有支持的Windows版本都会有WinRT版本的配对API。 - sam msft

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接