如何将 Android 应用程序正确连接到支持蓝牙的 Arduino 微控制器上的 RFCOMM 插座?

Posted

技术标签:

【中文标题】如何将 Android 应用程序正确连接到支持蓝牙的 Arduino 微控制器上的 RFCOMM 插座?【英文标题】:How can I properly connect an Android application to an RFCOMM socket on a Bluetooth enabled Arduino microcontroller? 【发布时间】:2011-11-02 19:52:38 【问题描述】:

我正在与我大学的一些学生一起开发一个简单的蓝牙 android 应用程序,该应用程序将用于与连接有蓝牙模块的 Arduino 微控制器进行串行通信 (RFCOMM)。

据我所知,我为RFCOMM/SPP 00001101-0000-1000-8000-00805F9B34FB 使用了正确的蓝牙地址和UUID。我的应用程序启动了一个尝试使用BluetoothDevice.createRfcommSocketToServiceRecord(UUID) 连接到设备的线程。但出于某种原因,我们没有看到成功的连接。对来自上述调用的结果 BluetoothSocket 调用 connect() 时,该操作总是失败。

在我的HTC Evo 上运行 HTC 的Gingerbread 变体进行测试时,connect() 调用通常会失败并显示异常消息“无法启动服务发现”。我做了一些阅读,发现有人说 HTC 在蓝牙堆栈中对 RFCOMM 的实现有问题,所以我们决定在另一个学生的Samsung Galaxy S 上尝试一下。代码第一次运行时,一切正常。 Arduino 微控制器连接到一个小型电动机,该电动机开始按预期工作。我没有排除问题是否出在微控制器方面。

随后在三星设备上使用该应用程序失败,现在显示“服务发现失败”消息。对我来说,似乎设备端的蓝牙模块认为RFCOMM服务仍在使用中。但是我们重新启动了微控制器,仍然看到了相同的结果。

我刚刚列出了线程代码,因为它是真正相关的所有内容。我读到有一个非常常见的解决方法(hack)使用反射来解决这些问题。我的尝试也失败了,但在那里并被注释掉了。希望有人可以在这里引导我朝着正确的方向前进。另请注意,我确实在清单中启用了必要的权限,并且在这两种情况下,设备都已使用 Android 的用户界面成功与 Arduino 配对。

private class ClientThread extends Thread 

    private String _btAddress;

    /**
     * A handle to the local device's Bluetooth adapter hardware.
     */
    private BluetoothAdapter _btAdapter = BluetoothAdapter.getDefaultAdapter();

    /**
     * A handle to the remote device Bluetooth context.
     */
    private BluetoothDevice _btRemoteDevice;

    /**
     * A handle to the Bluetooth serial socket.
     */
    private BluetoothSocket _btSocket;

    /**
     * Constructor.
     * @param btAddress The BluetoothHardware address.
     */
    public ClientThread(String btAddress)
    
        _btAddress = btAddress;
    

    public void run()
    
        // Retrieves the device identified by the _btAddress property.
        _btRemoteDevice = retrieveDevice();
        if ( _btRemoteDevice == null )
            sendUIMessage( CONNECTION_BT_DEVICE_NOT_BONDED );
        else
            sendBeacon();
    

    /**
     * Retrieves the device associated with this client thread.
     * @return
     */
    private BluetoothDevice retrieveDevice()
    
        Set<BluetoothDevice> btDevices = _btAdapter.getBondedDevices();
        for (BluetoothDevice btd : btDevices)
        
            String addr = btd.getAddress();
            String name = btd.getName();
            if ( addr.equalsIgnoreCase(_btAddress) )
                return btd;
        
        return null;
    

    /**
     * Sends the beacon to the Bluetooth device.
     */
    private void sendBeacon()
    
        // Holds the output stream of the BluetoothDevice.
        OutputStream os = null;

        try
        
            _btSocket = _btRemoteDevice.createRfcommSocketToServiceRecord( UUID.fromString( "00001101-0000-1000-8000-00805F9B34FB" ) );

            //Method m = _btRemoteDevice.getClass().getMethod("createInsecureRfcommSocket", new Class[] int.class);
            //_btSocket = (BluetoothSocket) m.invoke(_btRemoteDevice, 1);
            _btSocket.connect();
            os = _btSocket.getOutputStream();
            os.write('L');
        
        catch (IOException e)
        
            String message = e.getMessage();
            e.printStackTrace();
            sendUIMessage(CONNECTION_FAILURE_IO);
        
        catch (Exception e)
        
            e.printStackTrace();
            sendUIMessage(CONNECTION_FAILURE_UNKNOWN);
        
        finally
        
            try
            
                if (_btSocket != null)
                    _btSocket.close();
            
            catch (IOException e)
            
                System.out.println("Failed closing Bluetooth output stream.");
                e.printStackTrace();
            
        
    

编辑: 蓝牙模块是 MDFLY RF-BT0417CB。我知道在 arduino 上运行的代码并不多,只是使用 Serial.available() 和 Serial.read() 与 BT 模块通信。但是,我有一条可能更有用的新信息。当我的应用程序安装在三星设备上时,它只运行了一次,并且在随后的试验中失败了。不久前,与我一起工作的另一位学生使用 Android App Inventor(一种拖放式 GUI 工具,也可以创建逻辑工作工件)创建一个简单的应用程序,该应用程序连接了相同的 BT 模块/arduino 板,该应用程序有效。他说,当我的应用程序安装时,另一个应用程序无法连接到 BT 模块,这让我相信系统一直认为资源已分配给我的应用程序。在他卸载我的应用程序后,另一个能够连接。他没有其他应用程序的源代码,但我将自己尝试 App Inventor,看看它生成的源代码是否有任何不同。据我所知,我遵守了 Android 文档中定义的大多数标准做法,因此 BT 模块可能有些奇怪,或者 arduino 代码不一定以编程方式控制 BT 模块。

另一个编辑: 我不是蓝牙专家,但我们能够找到解决办法。正如一些人所知道的,有一堆公共的 BluetoothDevice API,在编译时隐藏,但在运行时使用反射合法地公开。其中之一是 createRfCommSocket(int)。这个 API 没有在官方文档中,因为它是隐藏的,但是你可以阅读它here。我还没有尝试使用文档支持的 API,但问题似乎是手机和串行板之间的并发问题。手机发送了一条消息,这当然是一个阻塞呼叫,当它从那里返回时,关闭了连接。串行板上的屏蔽也会关闭连接,因此数据对 arduino 应用程序不可用。我们在 android 端在调试模式下见证成功通信时意识到这一点,但在发布模式下失败。在 android 端,在 BluetoothSocket 的传输和关闭之间添加半秒延迟修复了该问题。我不能说这个问题是否是由 arduino 代码引起的,因为我对架构不是很熟悉,但我们作为学生缺乏经验,所以这不会让我感到惊讶。

【问题讨论】:

Arduino 设备上运行的是哪个蓝牙模块和软件?您能否发布对您正在使用的设备的引用。此外,如果您可以在 Android 端发布完整的日志,它会有所帮助。 丹尼斯,感谢您的回复,请接受我的歉意,因为您花了这么长时间才回复您,考试和其他义务一直拖累我。我正在研究 arduino 的型号和软件版本,但我发布了一些关于 BT 设备的信息和一些关于该问题的新信息。 您好,我遇到了类似的问题...我正在尝试将 LG 手机连接到 TI PAN1315 Dev。板,我得到了具有相同 UUID 的套接字,但 connect() 总是抛出一个 IOException。在调试嵌入式 PAN1315 时,我将一些日志打印到控制台,试图弄清楚我是否在原始应用程序设计中搞砸了,我发现 hci/acl 断开连接请求来自电话,而不是来自嵌入式设备,在将链接密钥从嵌入式设备发送到手机之后......你能同意吗? 嗨 TacB0sS,请参阅我上面的评论。 android 蓝牙 API 对于串行板连接显然有些参差不齐,因此使用了许多解决方法。我在这里提到的是一个相当常见的问题,但除此之外,我们还遇到了主板和手机之间的一些并发问题。这可能是也可能不是您想要调查的内容。关于连接关闭和链接密钥交换,我确信任一设备都可以请求连接或关闭,并且链接密钥存储在设备上,以便它们中的任何一个稍后可以相互连接。祝你好运 虽然我承认我完全不知道如何提供帮助,但您可能想尝试electronics.stackexchange.com。 :) 【参考方案1】:

Communication Between Android And Arduino With Bluetooth(1)

我认为这会对您有所帮助。 你能提供一些细节吗?我看过一个链接,你也可以看到这个。让我知道这是否有帮助? How to create Insecure RFCOMM Socket in Android?

【讨论】:

你运气好吗?请告诉我。【参考方案2】:

Amarino Toolkit 专为促进 Android 设备和带有蓝牙的 Arduino 之间的串行蓝牙通信而构建。

【讨论】:

以上是关于如何将 Android 应用程序正确连接到支持蓝牙的 Arduino 微控制器上的 RFCOMM 插座?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 iOS 中使用 iphone 5 连接到支持蓝牙 2.1 的设备

Android 手机从蓝牙更改为 BLE 后无法连接到树莓派

Android 蓝牙 API 连接到多个设备

通过蓝牙将 Android 应用程序连接到 Mac OS X 上的 Python 脚本

使用蓝牙无法同时将超过 4 个从机连接到 master-android

Android:可以将蓝牙连接到自己吗?