使用32feet .NET蓝牙库将蓝牙设备与计算机配对

33

如果想知道如何使用32feet.NET库与蓝牙设备通信,请阅读解决方案。


我目前正在尝试在计算机和自制的.NET Gadgeteer原型之间通过蓝牙进行通信。

Gadgeteer原型由主板、电源和蓝牙模块组成。该模块处于可发现模式。

在计算机上运行基于32feet .NET蓝牙的自定义蓝牙程序。该程序检测到范围内的所有蓝牙设备并尝试与它们配对。然而,目前还不能自动完成这个过程,我必须为设备输入配对代码。

如何在不输入配对代码的情况下配对设备?

设备被发现了,问题在于配对部分。我做了很多实验,但没有找到解决办法...

foreach (BluetoothDeviceInfo device in this.deviceList)
{
    try
    {
        //BluetoothClient client = new BluetoothClient(this.CreateNewEndpoint(localAddress));
        //BluetoothEndPoint ep = this.CreateNewEndpoint(device.DeviceAddress);

        EventHandler<BluetoothWin32AuthenticationEventArgs> handler = new EventHandler<BluetoothWin32AuthenticationEventArgs>(HandleRequests);
        BluetoothWin32Authentication auth = new BluetoothWin32Authentication(handler);

        BluetoothSecurity.PairRequest(device.DeviceAddress, null);
    }
}

这个代码块启动了配对,它可以正常工作,但是Windows要求我为设备输入配对代码。我读了关于BluetoothWin32Authentication的内容,以防止出现这种情况,但我做不对。

private void HandleRequests(object that, BluetoothWin32AuthenticationEventArgs e)
{
    e.Confirm = true;
}

这是事件处理程序的代码(http://32feet.codeplex.com/wikipage?title=BluetoothWin32Authentication

如果你只想在 SSP 设备连接时允许配对,则处理回调并设置 e.Confirm=True 就足够了——但这有点不安全...


我有点困惑。目标是应用程序和微型工具模块可以在两个方向上发送数据而不需要任何用户干预。

是否无法在没有用户交互的情况下自动配对设备?

如果两个设备已经配对,它们是否可以在没有用户干预的情况下交换数据?


1
在Windows 10中,这个方法不起作用。操作系统提示我“点击设置设备”,使用上面的代码,我从未收到“HandleRequests”事件处理程序回调。有什么办法可以绕过这个提示? - TheJeff
是的,正如TheJeff所说,在Windows 10中配对不起作用,设备已经配对但在“播放设备”中不可见,有什么解决办法吗? - sebastso
系统要求中没有列出Windows 10,只有Windows 8。也许目前还不可能。 - xmashallax
我在Windows 8.1上也收到了“点击设置设备”的弹出通知。我想知道这是否与蓝牙设置中的“有新的蓝牙设备要连接时提醒我”选项有关。 - Aron Curzon
你能解决这个问题吗?我也遇到了同样的问题,当我点击设置toast通知时,它会正确配对。 - sebastso
1个回答

53

我找到了解决我的问题的方法,现在我对蓝牙连接的知识更加深入了一点。如果其他人遇到问题,我可以提供我的解决方案。下面的代码示例展示了使用32feet蓝牙库实现蓝牙控制器的C#实现。

扫描

这意味着检测到了范围内的设备。我的代码:

// mac is mac address of local bluetooth device
BluetoothEndPoint localEndpoint = new BluetoothEndPoint(mac, BluetoothService.SerialPort);
// client is used to manage connections
BluetoothClient localClient = new BluetoothClient(localEndpoint);
// component is used to manage device discovery
BluetoothComponent localComponent = new BluetoothComponent(localClient);
// async methods, can be done synchronously too
localComponent.DiscoverDevicesAsync(255, true, true, true, true, null);
localComponent.DiscoverDevicesProgress += new EventHandler<DiscoverDevicesEventArgs>(component_DiscoverDevicesProgress);
localComponent.DiscoverDevicesComplete += new EventHandler<DiscoverDevicesEventArgs>(component_DiscoverDevicesComplete);

private void component_DiscoverDevicesProgress(object sender, DiscoverDevicesEventArgs e)
{
    // log and save all found devices
    for (int i = 0; i < e.Devices.Length; i++)
    {           
        if (e.Devices[i].Remembered)
        {
            Print(e.Devices[i].DeviceName + " (" + e.Devices[i].DeviceAddress + "): Device is known");
        }
        else
        {
            Print(e.Devices[i].DeviceName + " (" + e.Devices[i].DeviceAddress + "): Device is unknown");
        }
        this.deviceList.Add(e.Devices[i]);         
    }
}

private void component_DiscoverDevicesComplete(object sender, DiscoverDevicesEventArgs e)
{
    // log some stuff
}

配对

这意味着设备与本地蓝牙设备进行了配对。需要通过输入双方的代码进行一次操作。可以通过代码完成此操作,以便用户甚至无需注意到添加了设备。我用于此目的的代码:

// get a list of all paired devices
BluetoothDeviceInfo[] paired = localClient.DiscoverDevices(255, false, true, false, false);
// check every discovered device if it is already paired 
foreach (BluetoothDeviceInfo device in this.deviceList)
{
    bool isPaired = false;
    for (int i = 0; i < paired.Length; i++)
    {
        if (device.Equals(paired[i]))
        {
            isPaired = true;
            break;
        }
    }

    // if the device is not paired, pair it!
    if (!isPaired)
    {
        // replace DEVICE_PIN here, synchronous method, but fast
        isPaired = BluetoothSecurity.PairRequest(device.DeviceAddress, DEVICE_PIN);
        if (isPaired)
        {
            // now it is paired
        }
        else
        {
            // pairing failed
        }
    }
}

连接

这意味着建立连接并交换数据。以下是一些代码:

// check if device is paired
if (device.Authenticated)
{
    // set pin of device to connect with
    localClient.SetPin(DEVICE_PIN);
    // async connection method
    localClient.BeginConnect(device.DeviceAddress, BluetoothService.SerialPort, new AsyncCallback(Connect), device);
}

// callback
private void Connect(IAsyncResult result)
{
    if (result.IsCompleted)
    {
        // client is connected now :)
    }
}

如果您保持扫描、配对、连接的顺序,一切都应该正常工作。要发送或接收数据,请使用BluetoothClientGetStream()方法。它提供一个可以操作的网络流。

接收连接

如果您希望另一个设备与您的设备连接,您需要监听传入的连接请求。这仅在设备之前已经配对时才有效。我的代码:

BluetoothListener l = new BluetoothListener(LOCAL_MAC, BluetoothService.SerialPort);
l.Start(10);
l.BeginAcceptBluetoothClient(new AsyncCallback(AcceptConnection), l);

void AcceptConnection(IAsyncResult result){
    if (result.IsCompleted){
        BluetoothClient remoteDevice = ((BluetoothListener)result.AsyncState).EndAcceptBluetoothClient(result);    
    }    
}

请用有效的 BluetoothAddress 替换 LOCAL_MAC(例如通过使用 BluetoothAddress.Parse();)。设备连接后,它们可以通过底层流交换消息。如果连接不起作用,则可能存在身份验证问题,请尝试在监听器中设置本地设备 PIN (l.SetPin(LOCAL_MAC, MY_PASSWORD);)。


2
@xmarshallax Socket 无法通过 BeginConnect 方法连接。Socket.connected 状态为 false,因此 Getstream() 方法将无法用于发送或接收数据。 - Harsh
2
在调用DiscoverDevicesAsync方法之前,难道不应该先注册ProgressComplete事件处理程序吗? - Edgar
一般而言是的,但异步方法需要一些时间(几秒钟),因此通常在处理程序注册之前设备不会被发现。 - xmashallax
3
寻找如何找到蓝牙Mac地址“mac”的方法:https://dev59.com/qUrSa4cB1Zd3GeqPXZLe - CodyF
有人知道如何在没有 PIN 的情况下连接到蓝牙设备吗? - noone392
显示剩余12条评论

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