繁体   English   中英

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

[英]How can I properly connect an Android application to an RFCOMM socket on a Bluetooth enabled Arduino microcontroller?

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

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

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

随后在Samsung设备上使用该应用程序失败,现在显示“Service Discovery Failed”消息。 对我来说,似乎设备端的蓝牙模块可能认为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不在官方文档中,因为它是隐藏的,但您可以在此处阅读。 我还没有尝试使用文档支持的API,但问题似乎是手机和串行板之间的并发问题。 手机发送了一条消息,这当然是一个阻塞呼叫,当它从那里返回时,关闭了连接。 然后,串行板上的屏蔽也将关闭连接,因此arduino应用程序无法获得数据。 我们在android端调试模式下见证成功通信时意识到这一点,但在发布模式下失败了。 在android端添加半秒延迟,在BluetoothSocket的传输和关闭之间修复了这个问题。 我不能说这个问题是否归因于arduino代码,因为我对这个架构不是很熟悉,但是我们学生们缺乏经验所以不会让我感到惊讶。

Android和Arduino之间的通信与蓝牙(1)

我想这会对你有所帮助。 你能提供一些细节吗。我看过一个链接,你也可以看到这个。 让我知道这是有帮助还是没有? 如何在Android中创建不安全的RFCOMM套接字?

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM