本文介绍了使用BluetoothChat与ELM327沟通的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目前我正在试图通过在BluetoothChat示例应用程序的ELM327 OBDII蓝牙模块进行通信。我能够连接,因为我已经改变了UUID,但我只能接受她的启动命令,并提示>发送命令,每当我尝试发送,我得到如下的命令

  • CAN OBDII:ELM327 V1.2A>
  • 我:ATRV
  • CAN OBDII:ATRV
  • CAN OBDII:>
  • CAN OBDII:

现在我读了这里追加\ R的命令,但是当我这样做,我得到完全相同的反应。我使用的示例应用程序BluetoothChat

主类...

 公共类BluetoothChat延伸活动{
    // 调试
    私有静态最后字符串变量=BluetoothChat;
    私有静态最终布尔D =真;

    //从BluetoothChatService处理程序中发送的消息类型
    公共静态最终诠释MESSAGE_STATE_CHANGE = 1;
    公共静态最终诠释MESSAGE_READ = 2;
    公共静态最终诠释MESSAGE_WRITE = 3;
    公共静态最终诠释MESSAGE_DEVICE_NAME = 4;
    公共静态最终诠释MESSAGE_TOAST = 5;

    //从BluetoothChatService处理程序接收到的键名
    公共静态最后弦乐DEVICE_NAME =DEVICE_NAME;
    公共静态最后弦乐土司=干杯;

    //意向申请codeS
    私有静态最终诠释REQUEST_CONNECT_DEVICE_SECURE = 1;
    私有静态最终诠释REQUEST_CONNECT_DEVICE_INSECURE = 2;
    私有静态最终诠释REQUEST_ENABLE_BT = 3;

    //布局视图
    私人TextView的mTitle;
    私人的ListView mConversationView;
    私人的EditText mOutEditText;
    私人按钮mSendButton;

    //所连接设备的名称
    私人字符串mConnectedDeviceName = NULL;
    //阵列适配器的对话线程
    私人ArrayAdapter<字符串> mConversationArrayAdapter;
    //字符串缓冲区,用于发送邮件
    私人的StringBuffer mOutStringBuffer;
    //本地蓝牙适配器
    私人BluetoothAdapter mBluetoothAdapter = NULL;
    //为聊天服务会员对象
    私人BluetoothChatService mChatService = NULL;


    @覆盖
    公共无效的onCreate(包savedInstanceState){
        super.onCreate(savedInstanceState);
        如果(D)Log.e(TAG,+++上创建+++);

        //设置窗口布局
        requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
        的setContentView(R.layout.main);
        。getWindow()setFeatureInt(Window.FEATURE_CUSTOM_TITLE,R.layout.custom_title);

        //设置的自定义标题
        mTitle =(TextView中)findViewById(R.id.title_left_text);
        mTitle.setText(R.string.app_name);
        mTitle =(TextView中)findViewById(R.id.title_right_text);

        //获取本地蓝牙适配器
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

        //如果适配器为空,则是不支持蓝牙
        如果(mBluetoothAdapter == NULL){
            Toast.makeText(这一点,蓝牙不可用,Toast.LENGTH_LONG).show();
            完();
            返回;
        }
    }

    @覆盖
    公共无效的OnStart(){
        super.onStart();
        如果(D)Log.e(TAG,++ ON START ++);

        //如果BT不上,要求将其激活。
        // setupChat()将被onActivityResult期间调用
        如果(!mBluetoothAdapter.isEnabled()){
            意图enableIntent =新的意图(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableIntent,REQUEST_ENABLE_BT);
        //否则,设置聊天会话
        } 其他 {
            如果(mChatService == NULL)setupChat();
        }
    }

    @覆盖
    市民同步无效onResume(){
        super.onResume();
        如果(D)Log.e(TAG,+ ON RESUME +);

        //执行此检查在onResume()覆盖,其中BT是事实
        //不ONSTART()过程中启用,所以我们停下来启用它...
        // onResume()将被调用的时候ACTION_REQUEST_ENABLE活动的回报。
        如果(mChatService!= NULL){
            //只有在状态STATE_NONE,难道我们知道我们尚未启动
            如果(mChatService.getState()== BluetoothChatService.STATE_NONE){
              //启动蓝牙聊天服务
              mChatService.start();
            }
        }
    }

    私人无效setupChat(){
        Log.d(TAG,setupChat());

        //初始化数组适配器的对话线程
        mConversationArrayAdapter =新的ArrayAdapter<字符串>(这一点,R.layout.message);
        mConversationView =(ListView控件)findViewById(R.id.in);
        mConversationView.setAdapter(mConversationArrayAdapter);

        //初始化撰写场的监听器返回键
        mOutEditText =(EditText上)findViewById(R.id.edit_text_out);
        mOutEditText.setOnEditorActionListener(mWriteListener);

        //初始化发送按钮的侦听器的点击事件
        mSendButton =(按钮)findViewById(R.id.button_send);
        mSendButton.setOnClickListener(新OnClickListener(){
            公共无效的onClick(视图v){
                //发送一条消息使用编辑文本小窗口的内容
                TextView的视图=(TextView中)findViewById(R.id.edit_text_out);
                字符串消息= view.getText()的toString()。
                的sendMessage(消息);
            }
        });

        //初始化BluetoothChatService进行蓝牙连接
        mChatService =新BluetoothChatService(这一点,mHandler);

        //初始化缓冲区传出消息
        mOutStringBuffer =新的StringBuffer();
    }

    @覆盖
    市民同步无效的onPause(){
        super.onPause();
        如果(D)Log.e(TAG - 对暂停 - );
    }

    @覆盖
    公共无效的onStop(){
        super.onStop();
        如果(D)Log.e(TAG -  ON STOP  - );
    }

    @覆盖
    公共无效的onDestroy(){
        super.onDestroy();
        //停止蓝牙聊天服务
        如果(mChatService!= NULL)mChatService.stop();
        如果(D)Log.e(TAG ---ON DESTROY ---);
    }

    私人无效ensureDiscoverable(){
        如果(D)Log.d(TAG,确保发现);
        如果(mBluetoothAdapter.getScanMode()!=
            BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE){
            意图discoverableIntent =新的意图(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
            discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,300);
            startActivity(discoverableIntent);
        }
    }

    / **
     *发送消息。
     * @参数消息文本字符串发送。
     * /
    私人无效的sendMessage(字符串消息){
        //检查我们尝试任何事情之前,实际上是在连接
        如果(mChatService.getState()!= BluetoothChatService.STATE_CONNECTED){
            Toast.makeText(这一点,R.string.not_connected,Toast.LENGTH_SHORT).show();
            返回;
        }

        //检查是否有实际上的东西送
        如果(message.length()大于0){
            //获取消息的字节,并告诉BluetoothChatService写
            byte []的发送= message.getBytes();
            mChatService.write(发送);

            //复位输出字符串缓冲区为零,并清除在编辑文本字段
            mOutStringBuffer.setLength(0);
            mOutEditText.setText(mOutStringBuffer);
        }
    }

    //动作侦听的EditText小部件,听为返回键
    私人TextView.OnEditorActionListener mWriteListener =
        新TextView.OnEditorActionListener(){
        公共布尔onEditorAction(TextView的观点,诠释actionId,KeyEvent的事件){
            //如果动作是返回键一键式的事件,发送邮件
            如果(actionId == EditorInfo.IME_NULL&安培;&安培; event.getAction()== KeyEvent.ACTION_UP){
                字符串消息= view.getText()的toString()。
                的sendMessage(消息);
            }
            如果(D)Log.i(TAG,END onEditorAction);
            返回true;
        }
    };

    //,获取信息传回从BluetoothChatService的处理程序
    私人最终处理程序mHandler =新的处理程序(){
        @覆盖
        公共无效的handleMessage(信息MSG){
            开关(msg.what){
            案例MESSAGE_STATE_CHANGE:
                如果(D)Log.i(TAG,MESSAGE_STATE_CHANGE:+ msg.arg1);
                开关(msg.arg1){
                案例BluetoothChatService.STATE_CONNECTED:
                    mTitle.setText(R.string.title_connected_to);
                    mTitle.append(mConnectedDeviceName);
                    mConversationArrayAdapter.clear();
                    打破;
                案例BluetoothChatService.STATE_CONNECTING:
                    mTitle.setText(R.string.title_connecting);
                    打破;
                案例BluetoothChatService.STATE_LISTEN:
                案例BluetoothChatService.STATE_NONE:
                    mTitle.setText(R.string.title_not_connected);
                    打破;
                }
                打破;
            案例MESSAGE_WRITE:
                Log.i(TAG,写作!);
                byte []的writeBuf =(字节[])msg.obj;
                //构造从缓冲器的字符串
                字符串的WriteMessage =新的String(writeBuf);
                mConversationArrayAdapter.add(我:+的WriteMessage);
                打破;
            案例MESSAGE_READ:
                Log.i(TAG,读书);
                字符串readMessage =(字符串)msg.obj;

                //从缓冲区中的有效字节构造字符串

                mConversationArrayAdapter.add(mConnectedDeviceName +:+ readMessage);
                打破;
            案例MESSAGE_DEVICE_NAME:
                //保存所连接的设备的名称
                。mConnectedDeviceName = msg.getData()的getString(设备);
                Toast.makeText(getApplicationContext(),连接到
                               + mConnectedDeviceName,Toast.LENGTH_SHORT).show();
                打破;
            案例MESSAGE_TOAST:
                Toast.makeText(getApplicationContext(),msg.getData()的getString(TOAST),
                               Toast.LENGTH_SHORT).show();
                打破;
            }
        }
    };

    公共无效onActivityResult(INT申请code,INT结果code,意图数据){
        如果(D)Log.d(TAG,onActivityResult+结果code);
        开关(要求code){
        案例REQUEST_CONNECT_DEVICE_SECURE:
            //当DeviceListActivity返回与设备连接
            如果(结果code == Activity.RESULT_OK){
                connectDevice(数据,真正的);
            }
            打破;
        案例REQUEST_CONNECT_DEVICE_INSECURE:
            //当DeviceListActivity返回与设备连接
            如果(结果code == Activity.RESULT_OK){
                connectDevice(数据,FALSE);
            }
            打破;
        案例REQUEST_ENABLE_BT:
            //当请求启用蓝牙的回报
            如果(结果code == Activity.RESULT_OK){
                //蓝牙已经启用,因此建立了一个聊天会话
                setupChat();
            } 其他 {
                //用户没有启用蓝牙或发生错误
                Log.d(TAG,BT不启用);
                Toast.makeText(这一点,R.string.bt_not_enabled_leaving,Toast.LENGTH_SHORT).show();
                完();
            }
        }
    }

    私人无效connectDevice(意向数据,逻辑安全){
        //获取设备的MAC地址
        字符串的地址= data.getExtras()
            .getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
        //获取BluetoothDevice类对象
        BluetoothDevice类设备= mBluetoothAdapter.getRemoteDevice(地址);
        //尝试连接到该设备
        mChatService.connect(设备安全);
    }

    @覆盖
    公共布尔onCreateOptionsMenu(功能菜单){
        MenuInflater充气= getMenuInflater();
        inflater.inflate(R.menu.option_menu,菜单);
        返回true;
    }

    @覆盖
    公共布尔onOptionsItemSelected(菜单项项){
        意图serverIntent = NULL;
        开关(item.getItemId()){
        案例R.id.secure_connect_scan:
            //启动DeviceListActivity看到设备,也扫描
            serverIntent =新的意图(这一点,DeviceListActivity.class);
            startActivityForResult(serverIntent,REQUEST_CONNECT_DEVICE_SECURE)​​;
            返回true;
        案例R.id.insecure_connect_scan:
            //启动DeviceListActivity看到设备,也扫描
            serverIntent =新的意图(这一点,DeviceListActivity.class);
            startActivityForResult(serverIntent,REQUEST_CONNECT_DEVICE_INSECURE)​​;
            返回true;
        案例R.id.discoverable:
            //确保该设备是可发现由他人
            ensureDiscoverable();
            返回true;
        }
        返回false;
    }

}










包com.example.android.BluetoothChat;

进口java.io.IOException异常;

/ **
 *该类完成所有的设置和管理蓝牙工作
 *与其他设备连接。它有一个线程监听
 *传入连接,一个线程用于与设备连接,以及
 *螺纹连接时进行数据传输。
 * /
公共类BluetoothChatService {
    // 调试
    私有静态最后字符串变量=BluetoothChatService;
    私有静态最终布尔D =真;

    //创建服务器套接字时的SDP记录名称
    私有静态最后弦乐NAME_SECURE =BluetoothChatSecure;
    私有静态最后弦乐NAME_INSECURE =BluetoothChatInsecure;

    //唯一的UUID这个应用程序
    私有静态最后UUID MY_UUID_SECURE =
        UUID.fromString(00001101-0000-1000-8000-00805F9B34FB);
    私有静态最后UUID MY_UUID_INSECURE =
        UUID.fromString(00001101-0000-1000-8000-00805F9B34FB);

    //会员领域
    私人最终BluetoothAdapter mAdapter;
    私人最终处理程序mHandler;
    私人AcceptThread mSecureAcceptThread;
    私人AcceptThread mInsecureAcceptThread;
    私人ConnectThread mConnectThread;
    私人ConnectedThread mConnectedThread;
    私人诠释mState;

    //常数,用于指示当前连接状态
    公共静态最终诠释STATE_NONE = 0; //我们做什么
    公共静态最终诠释STATE_LISTEN = 1; //现在侦听传入连接
    公共静态最终诠释STATE_CONNECTING = 2; //现在开始传出连接
    公共静态最终诠释STATE_CONNECTED = 3; //现在连接到远程设备

    / **
     *构造函数。 prepares新BluetoothChat会话。
     * @参数方面的UI活动上下文
     *参数处理程序的处理程序,以回消息发送到用户界面活动
     * /
    公共BluetoothChatService(上下文的背景下,处理程序处理){
        mAdapter = BluetoothAdapter.getDefaultAdapter();
        mState = STATE_NONE;
        mHandler =处理程序;
    }

    / **
     *设置聊天连接的当前状态
     *参数状态定义当前连接状态的整数
     * /
    私人同步无效的setState(INT状态){
        如果(D)Log.d(TAG的setState()+ mState + - >中+的状态);
        mState =状态;

        //给这个新状态的处理程序,以便用户界面的活动可以更新
        mHandler.obtainMessage(BluetoothChat.MESSAGE_STATE_CHANGE,州,-1).sendToTarget();
    }

    / **
     *返回当前连接状态。 * /
    公共同步INT的getState(){
        返回mState;
    }

    / **
     *启动聊天服务。具体开始AcceptThread,开始
     *会话监听(服务器)模式。通过活动onResume()调用* /
    市民同步无效的start(){
        如果(D)Log.d(TAG,开始);

        //取消任何线程尝试建立连接
        如果(!mConnectThread = NULL){mConnectThread.cancel(); mConnectThread = NULL;}

        //取消任何线程当前正在运行的连接
        如果(!mConnectedThread = NULL){mConnectedThread.cancel(); mConnectedThread = NULL;}

        的setState(STATE_LISTEN);

        //开始,以一个BluetoothServerSocket听线程
        如果(mSecureAcceptThread == NULL){
            mSecureAcceptThread =新AcceptThread(真正的);
            mSecureAcceptThread.start();
        }
        如果(mInsecureAcceptThread == NULL){
            mInsecureAcceptThread =新AcceptThread(假);
            mInsecureAcceptThread.start();
        }
    }

    / **
     *启动ConnectThread发起到远程设备的连接。
     *参数设备的BluetoothDevice类连接
     *参数安全套接字安全类型 - 安全(真),不安全(假)
     * /
    市民同步无效连接(BluetoothDevice类设备,布尔收费){
        如果(D)Log.d(TAG,连接到+设备);

        //取消任何线程尝试建立连接
        如果(mState == STATE_CONNECTING){
            如果(!mConnectThread = NULL){mConnectThread.cancel(); mConnectThread = NULL;}
        }

        //取消任何线程当前正在运行的连接
        如果(!mConnectedThread = NULL){mConnectedThread.cancel(); mConnectedThread = NULL;}

        //启动线程与给定的设备连接
        mConnectThread =新ConnectThread(设备安全);
        mConnectThread.start();
        的setState(STATE_CONNECTING);
    }

    / **
     *启动ConnectedThread开始管理蓝牙连接
     *参数套接字的连接被提出的的BluetoothSocket
     * @参数设备已连接该BluetoothDevice类
     * /
    市民同步无效连接(的BluetoothSocket插座,BluetoothDevice类
            设备,最后弦乐socketType){
        如果(D)Log.d(TAG,连接器,插座类型:+ socketType);

        //取消已完成的连接线
        如果(!mConnectThread = NULL){mConnectThread.cancel(); mConnectThread = NULL;}

        //取消任何线程当前正在运行的连接
        如果(!mConnectedThread = NULL){mConnectedThread.cancel(); mConnectedThread = NULL;}

        //取消接受线程,因为我们只需要连接到一台设备
        如果(mSecureAcceptThread!= NULL){
            mSecureAcceptThread.cancel();
            mSecureAcceptThread = NULL;
        }
        如果(mInsecureAcceptThread!= NULL){
            mInsecureAcceptThread.cancel();
            mInsecureAcceptThread = NULL;
        }

        //启动线程来管理连接并进行传输
        mConnectedThread =新ConnectedThread(插座,socketType);
        mConnectedThread.start();

        //发送连接设备的名称回UI活动
        消息味精= mHandler.obtainMessage(BluetoothChat.MESSAGE_DEVICE_NAME);
        束束=新包();
        bundle.putString(BluetoothChat.DEVICE_NAME,device.getName());
        msg.setData(包);
        mHandler.sendMessage(MSG);

        的setState(STATE_CONNECTED);
    }

    / **
     *停止所有线程
     * /
    市民同步无效停止(){
        如果(D)Log.d(TAG,停);

        如果(mConnectThread!= NULL){
            mConnectThread.cancel();
            mConnectThread = NULL;
        }

        如果(mConnectedThread!= NULL){
            mConnectedThread.cancel();
            mConnectedThread = NULL;
        }

        如果(mSecureAcceptThread!= NULL){
            mSecureAcceptThread.cancel();
            mSecureAcceptThread = NULL;
        }

        如果(mInsecureAcceptThread!= NULL){
            mInsecureAcceptThread.cancel();
            mInsecureAcceptThread = NULL;
        }
        的setState(STATE_NONE);
    }

    / **
     *写的ConnectedThread在非同步的方式
     *参数了要写入的字节
     * @see ConnectedThread#写入(字节[])
     * /
    公共无效的write(byte []的输出){
        //创建临时对象
        ConnectedThreadř;
        //该ConnectedThread副本同步
        同步(本){
            如果(mState = STATE_CONNECTED!)回报;
            R = mConnectedThread;
        }
        //执行写操作不同步
        r.write(出);
    }

    / **
     *表明连接尝试失败,并通知用户界面活动。
     * /
    私人无效为connectionFailed(){
        //发送失败的消息回活动
        消息味精= mHandler.obtainMessage(BluetoothChat.MESSAGE_TOAST);
        束束=新包();
        bundle.putString(BluetoothChat.TOAST,无法连接设备);
        msg.setData(包);
        mHandler.sendMessage(MSG);

        //启动服务在重新启动监听模式
        BluetoothChatService.this.start();
    }

    / **
     *表明连接丢失,并通知用户界面活动。
     * /
    私人无效connectionLost(){
        //发送失败的消息回活动
        消息味精= mHandler.obtainMessage(BluetoothChat.MESSAGE_TOAST);
        束束=新包();
        bundle.putString(BluetoothChat.TOAST,设备连接丢失);
        msg.setData(包);
        mHandler.sendMessage(MSG);

        //启动服务在重新启动监听模式
        BluetoothChatService.this.start();
    }

    / **
     *此线程同时侦听传入连接运行。它的行为
     *像一个服务器端客户机。它运行,直到连接被接受
     *(或直到取消)。
     * /
    私有类AcceptThread继承Thread {
        //本地服务器套接字
        私人最终BluetoothServerSocket mmServerSocket;
        私人字符串mSocketType;

        公共AcceptThread(布尔安全){
            BluetoothServerSocket TMP = NULL;
            mSocketType =安全的? 安全:不安全;

            //创建一个新的监听服务器套接字
            尝试 {
                如果(安全){
                    TMP = mAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE,
                        MY_UUID_SECURE)​​;
                } 其他 {
                    TMP = mAdapter.listenUsingInsecureRfcommWithServiceRecord(
                            NAME_INSECURE,MY_UUID_INSECURE)​​;
                }
            }赶上(IOException异常E){
                Log.e(TAG,插座类型:+ mSocketType +听()失败,E);
            }
            mmServerSocket = TMP;
        }

        公共无效的run(){
            如果(D)Log.d(TAG,插座类型:+ mSocketType +
                    BEGIN mAcceptThread+本);
            的setName(AcceptThread+ mSocketType);

            的BluetoothSocket插座= NULL;

            //监听到服务器套接字,如果我们没有连接
            而(mState!= STATE_CONNECTED){
                尝试 {
                    //这是一个阻塞调用,只会返回一个
                    //连接成功或异常
                    插座= mmServerSocket.accept();
                }赶上(IOException异常E){
                    Log.e(TAG,插座类型:+ mSocketType +接受()失败,E);
                    打破;
                }

                //如果连接被接受
                如果(插座!= NULL){
                    同步(BluetoothChatService.this){
                        开关(mState){
                        案例STATE_LISTEN:
                        案例STATE_CONNECTING:
                            //情况正常。启动连接线。
                            连接(插座,socket.getRemoteDevice(),
                                    mSocketType);
                            打破;
                        案例STATE_NONE:
                        案例STATE_CONNECTED:
                            //要么没有准备或已连接。终止新的插座。
                            尝试 {
                                socket.close();
                            }赶上(IOException异常E){
                                Log.e(TAG,无法关闭不必要的插座,E);
                            }
                            打破;
                        }
                    }
                }
            }
            如果(D)Log.i(TAG,END mAcceptThread,插槽类型为:+ mSocketType);

        }

        公共无效取消(){
            如果(D)Log.d(TAG,插座式+ mSocketType +取消+本);
            尝试 {
                mmServerSocket.close();
            }赶上(IOException异常E){
                Log.e(TAG,服务器无法接近(),插座式+ mSocketType +,E);
            }
        }
    }


    / **
     *此线程同时尝试进行出站连接运行
     *与设备。它运行直通;连接任
     *成功或失败。
     * /
    私有类ConnectThread继承Thread {
        私人最终的BluetoothSocket mmSocket;
        私人最终BluetoothDevice类mmDevice;
        私人字符串mSocketType;

        公共ConnectThread(BluetoothDevice类设备,布尔收费){
            mmDevice =设备;
            的BluetoothSocket TMP = NULL;
            mSocketType =安全的? 安全:不安全;

            //获取的BluetoothSocket用于与连接
            //给BluetoothDevice类
            尝试 {
                如果(安全){
                    TMP = device.createRfcommSocketToServiceRecord(
                            MY_UUID_SECURE)​​;
                } 其他 {
                    TMP = device.createInsecureRfcommSocketToServiceRecord(
                            MY_UUID_INSECURE)​​;
                }
            }赶上(IOException异常E){
                Log.e(TAG,插座类型:+ mSocketType +创建()失败,E);
            }
            mmSocket = TMP;
        }

        公共无效的run(){
            Log.i(TAG,BEGIN mConnectThread SocketType:+ mSocketType);
            的setName(ConnectThread+ mSocketType);

            //随时取消的发现,因为它会减慢连接
            mAdapter.cancelDiscovery();

            //使到的BluetoothSocket连接
            尝试 {
                //这是一个阻塞调用,只会返回一个
                //连接成功或异常
                mmSocket.connect();
            }赶上(IOException异常E){
                //关闭套接字
                尝试 {
                    mmSocket
 

解决方案

的字符都被正确echo'd回可能表明波特率设置正确,该设备是看到你想要的字符的事实。这听起来,虽然是设备还是没有看到一个正确终止请求字符串(一个以回车结束)。

我提到这一点,因为你注意到添加/ R,这是不一样的东西\ R(CR字符)。例如,在Java中:

 的OutputStream出来;

字符串正确=ATRV \ R;
//此行将正确地写5个字节(十六进制):41 54 52 56 0D
out.write(correct.getBytes());

字符串不正确=ATRV / R;
//此行会错误地写6个字节(十六进制):41 54 52 56 2F 72
out.write(incorrect.getBytes());
 

该0X0D字符是什么ELM327正在寻找终止AT命令并解析它。

编辑:

如果您手动键入字符atrv \ R用你的键盘变成一个示例应用程序,存在同样的问题。该文本是除preTED为6个独特的字母(即'A','T','R','V','\',和'R'或十六进制 41 54 52 56 5C 72 )和'\ r'不是PTED为单个CR字符间$ P $。

您可能无法从您的样品code做到这一点,除非你添加一些特殊的code解析出组合,带'\',并与他们的特殊字符值替换。一个更好的解决办法是修改示例code,始终把'\ r'字符(记住...不同于单纯的'\'加一个'R'加入),以任何你当你打的类型发送按钮,这样你只需要在文本框中输入ATRV。这样的事情在你的 OnEditorActionListener code(再次,注意斜线方向,否则你会只添加两个字符):

 公共布尔onEditorAction(TextView的观点,诠释actionId,KeyEvent的事件){
    //如果动作是返回键一键式的事件,发送邮件
    如果(actionId == EditorInfo.IME_NULL&安培;&安培; event.getAction()== KeyEvent.ACTION_UP){
        //这会从盒子的原始文本
        字符串消息= view.getText()的toString()。
        //附加一个CR来发送每封邮件。加入的串被定义为文字,
        //所以Java解析是作为一个单独的CR字符。
        的sendMessage(信息+\ r);
    }
    如果(D)Log.i(TAG,END onEditorAction);
    返回true;
}
 

您也可以通过硬编码字符串命令,因为我在上面的例子中修改的样品。 Java的跨$ P $点的字符串字面值ATRV \ R正确,将是CR字符结束(使这是一个5个字符的字符串)。

I am currently trying to communicate with an ELM327 OBDII bluetooth dongle via the BluetoothChat Sample Application. I am able to connect as I have changed the UUID, however I am only able to recieve the startup commands and the prompt ">" to send a command, whenever I try to send a command I get the following

  • CAN OBDII:ELM327 v1.2a>
  • Me:ATRV
  • CAN OBDII:ATRV
  • CAN OBDII:>
  • CAN OBDII:?

Now I read on here to append "\r" to the commands, however when I do this I get the exact same response. I am using the sample application "BluetoothChat"

Main Class...

public class BluetoothChat extends Activity {
    // Debugging
    private static final String TAG = "BluetoothChat";
    private static final boolean D = true;

    // Message types sent from the BluetoothChatService Handler
    public static final int MESSAGE_STATE_CHANGE = 1;
    public static final int MESSAGE_READ = 2;
    public static final int MESSAGE_WRITE = 3;
    public static final int MESSAGE_DEVICE_NAME = 4;
    public static final int MESSAGE_TOAST = 5;

    // Key names received from the BluetoothChatService Handler
    public static final String DEVICE_NAME = "device_name";
    public static final String TOAST = "toast";

    // Intent request codes
    private static final int REQUEST_CONNECT_DEVICE_SECURE = 1;
    private static final int REQUEST_CONNECT_DEVICE_INSECURE = 2;
    private static final int REQUEST_ENABLE_BT = 3;

    // Layout Views
    private TextView mTitle;
    private ListView mConversationView;
    private EditText mOutEditText;
    private Button mSendButton;

    // Name of the connected device
    private String mConnectedDeviceName = null;
    // Array adapter for the conversation thread
    private ArrayAdapter<String> mConversationArrayAdapter;
    // String buffer for outgoing messages
    private StringBuffer mOutStringBuffer;
    // Local Bluetooth adapter
    private BluetoothAdapter mBluetoothAdapter = null;
    // Member object for the chat services
    private BluetoothChatService mChatService = null;


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(D) Log.e(TAG, "+++ ON CREATE +++");

        // Set up the window layout
        requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
        setContentView(R.layout.main);
        getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_title);

        // Set up the custom title
        mTitle = (TextView) findViewById(R.id.title_left_text);
        mTitle.setText(R.string.app_name);
        mTitle = (TextView) findViewById(R.id.title_right_text);

        // Get local Bluetooth adapter
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

        // If the adapter is null, then Bluetooth is not supported
        if (mBluetoothAdapter == null) {
            Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show();
            finish();
            return;
        }
    }

    @Override
    public void onStart() {
        super.onStart();
        if(D) Log.e(TAG, "++ ON START ++");

        // If BT is not on, request that it be enabled.
        // setupChat() will then be called during onActivityResult
        if (!mBluetoothAdapter.isEnabled()) {
            Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
        // Otherwise, setup the chat session
        } else {
            if (mChatService == null) setupChat();
        }
    }

    @Override
    public synchronized void onResume() {
        super.onResume();
        if(D) Log.e(TAG, "+ ON RESUME +");

        // Performing this check in onResume() covers the case in which BT was
        // not enabled during onStart(), so we were paused to enable it...
        // onResume() will be called when ACTION_REQUEST_ENABLE activity returns.
        if (mChatService != null) {
            // Only if the state is STATE_NONE, do we know that we haven't started already
            if (mChatService.getState() == BluetoothChatService.STATE_NONE) {
              // Start the Bluetooth chat services
              mChatService.start();
            }
        }
    }

    private void setupChat() {
        Log.d(TAG, "setupChat()");

        // Initialize the array adapter for the conversation thread
        mConversationArrayAdapter = new ArrayAdapter<String>(this, R.layout.message);
        mConversationView = (ListView) findViewById(R.id.in);
        mConversationView.setAdapter(mConversationArrayAdapter);

        // Initialize the compose field with a listener for the return key
        mOutEditText = (EditText) findViewById(R.id.edit_text_out);
        mOutEditText.setOnEditorActionListener(mWriteListener);

        // Initialize the send button with a listener that for click events
        mSendButton = (Button) findViewById(R.id.button_send);
        mSendButton.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                // Send a message using content of the edit text widget
                TextView view = (TextView) findViewById(R.id.edit_text_out);
                String message = view.getText().toString();
                sendMessage(message);
            }
        });

        // Initialize the BluetoothChatService to perform bluetooth connections
        mChatService = new BluetoothChatService(this, mHandler);

        // Initialize the buffer for outgoing messages
        mOutStringBuffer = new StringBuffer("");
    }

    @Override
    public synchronized void onPause() {
        super.onPause();
        if(D) Log.e(TAG, "- ON PAUSE -");
    }

    @Override
    public void onStop() {
        super.onStop();
        if(D) Log.e(TAG, "-- ON STOP --");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        // Stop the Bluetooth chat services
        if (mChatService != null) mChatService.stop();
        if(D) Log.e(TAG, "--- ON DESTROY ---");
    }

    private void ensureDiscoverable() {
        if(D) Log.d(TAG, "ensure discoverable");
        if (mBluetoothAdapter.getScanMode() !=
            BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
            Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
            discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
            startActivity(discoverableIntent);
        }
    }

    /**
     * Sends a message.
     * @param message  A string of text to send.
     */
    private void sendMessage(String message) {
        // Check that we're actually connected before trying anything
        if (mChatService.getState() != BluetoothChatService.STATE_CONNECTED) {
            Toast.makeText(this, R.string.not_connected, Toast.LENGTH_SHORT).show();
            return;
        }

        // Check that there's actually something to send
        if (message.length() > 0) {
            // Get the message bytes and tell the BluetoothChatService to write
            byte[] send = message.getBytes();
            mChatService.write(send);

            // Reset out string buffer to zero and clear the edit text field
            mOutStringBuffer.setLength(0);
            mOutEditText.setText(mOutStringBuffer);
        }
    }

    // The action listener for the EditText widget, to listen for the return key
    private TextView.OnEditorActionListener mWriteListener =
        new TextView.OnEditorActionListener() {
        public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {
            // If the action is a key-up event on the return key, send the message
            if (actionId == EditorInfo.IME_NULL && event.getAction() == KeyEvent.ACTION_UP) {
                String message = view.getText().toString();
                sendMessage(message);
            }
            if(D) Log.i(TAG, "END onEditorAction");
            return true;
        }
    };

    // The Handler that gets information back from the BluetoothChatService
    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case MESSAGE_STATE_CHANGE:
                if(D) Log.i(TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1);
                switch (msg.arg1) {
                case BluetoothChatService.STATE_CONNECTED:
                    mTitle.setText(R.string.title_connected_to);
                    mTitle.append(mConnectedDeviceName);
                    mConversationArrayAdapter.clear();
                    break;
                case BluetoothChatService.STATE_CONNECTING:
                    mTitle.setText(R.string.title_connecting);
                    break;
                case BluetoothChatService.STATE_LISTEN:
                case BluetoothChatService.STATE_NONE:
                    mTitle.setText(R.string.title_not_connected);
                    break;
                }
                break;
            case MESSAGE_WRITE:
                Log.i(TAG, "WRITING!");
                byte[] writeBuf = (byte[]) msg.obj;
                // construct a string from the buffer
                String writeMessage = new String(writeBuf);
                mConversationArrayAdapter.add("Me:  " + writeMessage);
                break;
            case MESSAGE_READ:
                Log.i(TAG, "READING");
                String readMessage = (String) msg.obj;

                // construct a string from the valid bytes in the buffer

                mConversationArrayAdapter.add(mConnectedDeviceName+":  " + readMessage);
                break;
            case MESSAGE_DEVICE_NAME:
                // save the connected device's name
                mConnectedDeviceName = msg.getData().getString(DEVICE_NAME);
                Toast.makeText(getApplicationContext(), "Connected to "
                               + mConnectedDeviceName, Toast.LENGTH_SHORT).show();
                break;
            case MESSAGE_TOAST:
                Toast.makeText(getApplicationContext(), msg.getData().getString(TOAST),
                               Toast.LENGTH_SHORT).show();
                break;
            }
        }
    };

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if(D) Log.d(TAG, "onActivityResult " + resultCode);
        switch (requestCode) {
        case REQUEST_CONNECT_DEVICE_SECURE:
            // When DeviceListActivity returns with a device to connect
            if (resultCode == Activity.RESULT_OK) {
                connectDevice(data, true);
            }
            break;
        case REQUEST_CONNECT_DEVICE_INSECURE:
            // When DeviceListActivity returns with a device to connect
            if (resultCode == Activity.RESULT_OK) {
                connectDevice(data, false);
            }
            break;
        case REQUEST_ENABLE_BT:
            // When the request to enable Bluetooth returns
            if (resultCode == Activity.RESULT_OK) {
                // Bluetooth is now enabled, so set up a chat session
                setupChat();
            } else {
                // User did not enable Bluetooth or an error occured
                Log.d(TAG, "BT not enabled");
                Toast.makeText(this, R.string.bt_not_enabled_leaving, Toast.LENGTH_SHORT).show();
                finish();
            }
        }
    }

    private void connectDevice(Intent data, boolean secure) {
        // Get the device MAC address
        String address = data.getExtras()
            .getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
        // Get the BLuetoothDevice object
        BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
        // Attempt to connect to the device
        mChatService.connect(device, secure);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.option_menu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        Intent serverIntent = null;
        switch (item.getItemId()) {
        case R.id.secure_connect_scan:
            // Launch the DeviceListActivity to see devices and do scan
            serverIntent = new Intent(this, DeviceListActivity.class);
            startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE_SECURE);
            return true;
        case R.id.insecure_connect_scan:
            // Launch the DeviceListActivity to see devices and do scan
            serverIntent = new Intent(this, DeviceListActivity.class);
            startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE_INSECURE);
            return true;
        case R.id.discoverable:
            // Ensure this device is discoverable by others
            ensureDiscoverable();
            return true;
        }
        return false;
    }

}










package com.example.android.BluetoothChat;

import java.io.IOException;

/**
 * This class does all the work for setting up and managing Bluetooth
 * connections with other devices. It has a thread that listens for
 * incoming connections, a thread for connecting with a device, and a
 * thread for performing data transmissions when connected.
 */
public class BluetoothChatService {
    // Debugging
    private static final String TAG = "BluetoothChatService";
    private static final boolean D = true;

    // Name for the SDP record when creating server socket
    private static final String NAME_SECURE = "BluetoothChatSecure";
    private static final String NAME_INSECURE = "BluetoothChatInsecure";

    // Unique UUID for this application
    private static final UUID MY_UUID_SECURE =
        UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
    private static final UUID MY_UUID_INSECURE =
        UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

    // Member fields
    private final BluetoothAdapter mAdapter;
    private final Handler mHandler;
    private AcceptThread mSecureAcceptThread;
    private AcceptThread mInsecureAcceptThread;
    private ConnectThread mConnectThread;
    private ConnectedThread mConnectedThread;
    private int mState;

    // Constants that indicate the current connection state
    public static final int STATE_NONE = 0;       // we're doing nothing
    public static final int STATE_LISTEN = 1;     // now listening for incoming connections
    public static final int STATE_CONNECTING = 2; // now initiating an outgoing connection
    public static final int STATE_CONNECTED = 3;  // now connected to a remote device

    /**
     * Constructor. Prepares a new BluetoothChat session.
     * @param context  The UI Activity Context
     * @param handler  A Handler to send messages back to the UI Activity
     */
    public BluetoothChatService(Context context, Handler handler) {
        mAdapter = BluetoothAdapter.getDefaultAdapter();
        mState = STATE_NONE;
        mHandler = handler;
    }

    /**
     * Set the current state of the chat connection
     * @param state  An integer defining the current connection state
     */
    private synchronized void setState(int state) {
        if (D) Log.d(TAG, "setState() " + mState + " -> " + state);
        mState = state;

        // Give the new state to the Handler so the UI Activity can update
        mHandler.obtainMessage(BluetoothChat.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();
    }

    /**
     * Return the current connection state. */
    public synchronized int getState() {
        return mState;
    }

    /**
     * Start the chat service. Specifically start AcceptThread to begin a
     * session in listening (server) mode. Called by the Activity onResume() */
    public synchronized void start() {
        if (D) Log.d(TAG, "start");

        // Cancel any thread attempting to make a connection
        if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}

        // Cancel any thread currently running a connection
        if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}

        setState(STATE_LISTEN);

        // Start the thread to listen on a BluetoothServerSocket
        if (mSecureAcceptThread == null) {
            mSecureAcceptThread = new AcceptThread(true);
            mSecureAcceptThread.start();
        }
        if (mInsecureAcceptThread == null) {
            mInsecureAcceptThread = new AcceptThread(false);
            mInsecureAcceptThread.start();
        }
    }

    /**
     * Start the ConnectThread to initiate a connection to a remote device.
     * @param device  The BluetoothDevice to connect
     * @param secure Socket Security type - Secure (true) , Insecure (false)
     */
    public synchronized void connect(BluetoothDevice device, boolean secure) {
        if (D) Log.d(TAG, "connect to: " + device);

        // Cancel any thread attempting to make a connection
        if (mState == STATE_CONNECTING) {
            if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}
        }

        // Cancel any thread currently running a connection
        if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}

        // Start the thread to connect with the given device
        mConnectThread = new ConnectThread(device, secure);
        mConnectThread.start();
        setState(STATE_CONNECTING);
    }

    /**
     * Start the ConnectedThread to begin managing a Bluetooth connection
     * @param socket  The BluetoothSocket on which the connection was made
     * @param device  The BluetoothDevice that has been connected
     */
    public synchronized void connected(BluetoothSocket socket, BluetoothDevice
            device, final String socketType) {
        if (D) Log.d(TAG, "connected, Socket Type:" + socketType);

        // Cancel the thread that completed the connection
        if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}

        // Cancel any thread currently running a connection
        if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}

        // Cancel the accept thread because we only want to connect to one device
        if (mSecureAcceptThread != null) {
            mSecureAcceptThread.cancel();
            mSecureAcceptThread = null;
        }
        if (mInsecureAcceptThread != null) {
            mInsecureAcceptThread.cancel();
            mInsecureAcceptThread = null;
        }

        // Start the thread to manage the connection and perform transmissions
        mConnectedThread = new ConnectedThread(socket, socketType);
        mConnectedThread.start();

        // Send the name of the connected device back to the UI Activity
        Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_DEVICE_NAME);
        Bundle bundle = new Bundle();
        bundle.putString(BluetoothChat.DEVICE_NAME, device.getName());
        msg.setData(bundle);
        mHandler.sendMessage(msg);

        setState(STATE_CONNECTED);
    }

    /**
     * Stop all threads
     */
    public synchronized void stop() {
        if (D) Log.d(TAG, "stop");

        if (mConnectThread != null) {
            mConnectThread.cancel();
            mConnectThread = null;
        }

        if (mConnectedThread != null) {
            mConnectedThread.cancel();
            mConnectedThread = null;
        }

        if (mSecureAcceptThread != null) {
            mSecureAcceptThread.cancel();
            mSecureAcceptThread = null;
        }

        if (mInsecureAcceptThread != null) {
            mInsecureAcceptThread.cancel();
            mInsecureAcceptThread = null;
        }
        setState(STATE_NONE);
    }

    /**
     * Write to the ConnectedThread in an unsynchronized manner
     * @param out The bytes to write
     * @see ConnectedThread#write(byte[])
     */
    public void write(byte[] out) {
        // Create temporary object
        ConnectedThread r;
        // Synchronize a copy of the ConnectedThread
        synchronized (this) {
            if (mState != STATE_CONNECTED) return;
            r = mConnectedThread;
        }
        // Perform the write unsynchronized
        r.write(out);
    }

    /**
     * Indicate that the connection attempt failed and notify the UI Activity.
     */
    private void connectionFailed() {
        // Send a failure message back to the Activity
        Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_TOAST);
        Bundle bundle = new Bundle();
        bundle.putString(BluetoothChat.TOAST, "Unable to connect device");
        msg.setData(bundle);
        mHandler.sendMessage(msg);

        // Start the service over to restart listening mode
        BluetoothChatService.this.start();
    }

    /**
     * Indicate that the connection was lost and notify the UI Activity.
     */
    private void connectionLost() {
        // Send a failure message back to the Activity
        Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_TOAST);
        Bundle bundle = new Bundle();
        bundle.putString(BluetoothChat.TOAST, "Device connection was lost");
        msg.setData(bundle);
        mHandler.sendMessage(msg);

        // Start the service over to restart listening mode
        BluetoothChatService.this.start();
    }

    /**
     * This thread runs while listening for incoming connections. It behaves
     * like a server-side client. It runs until a connection is accepted
     * (or until cancelled).
     */
    private class AcceptThread extends Thread {
        // The local server socket
        private final BluetoothServerSocket mmServerSocket;
        private String mSocketType;

        public AcceptThread(boolean secure) {
            BluetoothServerSocket tmp = null;
            mSocketType = secure ? "Secure":"Insecure";

            // Create a new listening server socket
            try {
                if (secure) {
                    tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE,
                        MY_UUID_SECURE);
                } else {
                    tmp = mAdapter.listenUsingInsecureRfcommWithServiceRecord(
                            NAME_INSECURE, MY_UUID_INSECURE);
                }
            } catch (IOException e) {
                Log.e(TAG, "Socket Type: " + mSocketType + "listen() failed", e);
            }
            mmServerSocket = tmp;
        }

        public void run() {
            if (D) Log.d(TAG, "Socket Type: " + mSocketType +
                    "BEGIN mAcceptThread" + this);
            setName("AcceptThread" + mSocketType);

            BluetoothSocket socket = null;

            // Listen to the server socket if we're not connected
            while (mState != STATE_CONNECTED) {
                try {
                    // This is a blocking call and will only return on a
                    // successful connection or an exception
                    socket = mmServerSocket.accept();
                } catch (IOException e) {
                    Log.e(TAG, "Socket Type: " + mSocketType + "accept() failed", e);
                    break;
                }

                // If a connection was accepted
                if (socket != null) {
                    synchronized (BluetoothChatService.this) {
                        switch (mState) {
                        case STATE_LISTEN:
                        case STATE_CONNECTING:
                            // Situation normal. Start the connected thread.
                            connected(socket, socket.getRemoteDevice(),
                                    mSocketType);
                            break;
                        case STATE_NONE:
                        case STATE_CONNECTED:
                            // Either not ready or already connected. Terminate new socket.
                            try {
                                socket.close();
                            } catch (IOException e) {
                                Log.e(TAG, "Could not close unwanted socket", e);
                            }
                            break;
                        }
                    }
                }
            }
            if (D) Log.i(TAG, "END mAcceptThread, socket Type: " + mSocketType);

        }

        public void cancel() {
            if (D) Log.d(TAG, "Socket Type" + mSocketType + "cancel " + this);
            try {
                mmServerSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "Socket Type" + mSocketType + "close() of server failed", e);
            }
        }
    }


    /**
     * This thread runs while attempting to make an outgoing connection
     * with a device. It runs straight through; the connection either
     * succeeds or fails.
     */
    private class ConnectThread extends Thread {
        private final BluetoothSocket mmSocket;
        private final BluetoothDevice mmDevice;
        private String mSocketType;

        public ConnectThread(BluetoothDevice device, boolean secure) {
            mmDevice = device;
            BluetoothSocket tmp = null;
            mSocketType = secure ? "Secure" : "Insecure";

            // Get a BluetoothSocket for a connection with the
            // given BluetoothDevice
            try {
                if (secure) {
                    tmp = device.createRfcommSocketToServiceRecord(
                            MY_UUID_SECURE);
                } else {
                    tmp = device.createInsecureRfcommSocketToServiceRecord(
                            MY_UUID_INSECURE);
                }
            } catch (IOException e) {
                Log.e(TAG, "Socket Type: " + mSocketType + "create() failed", e);
            }
            mmSocket = tmp;
        }

        public void run() {
            Log.i(TAG, "BEGIN mConnectThread SocketType:" + mSocketType);
            setName("ConnectThread" + mSocketType);

            // Always cancel discovery because it will slow down a connection
            mAdapter.cancelDiscovery();

            // Make a connection to the BluetoothSocket
            try {
                // This is a blocking call and will only return on a
                // successful connection or an exception
                mmSocket.connect();
            } catch (IOException e) {
                // Close the socket
                try {
                    mmSocket
解决方案

The fact that the characters are being correctly echo'd back probably indicates that the baud rate is set correctly and the device is seeing the characters you want. It sounds, though, like the device is still not seeing a properly terminated request string (one that ends with a carriage return).

I mention this because you noted appending "/r", which is not the same thing as "\r" (the CR character). For example, in Java:

OutputStream out;

String correct = "ATRV\r";
//This line will correctly write 5 bytes (in hex): 41 54 52 56 0D
out.write(correct.getBytes());

String incorrect = "ATRV/r";
//This line will incorrectly write 6 bytes (in hex): 41 54 52 56 2F 72
out.write(incorrect.getBytes());

The 0x0D character is what the ELM327 is looking for to terminate the AT command and parse it.

Edit:

If you are manually typing the characters "atrv\r" using your keyboard into a sample application, the same problem exists. The text is being interpreted as 6 unique letters (i.e. 'A', 'T', 'R', 'V', '\', and 'r' or hex 41 54 52 56 5C 72) and the '\r' is not interpreted as a single CR character.

You will likely not be able to do this from your sample code unless you add some special code to parse out combinations with '\' and replace them with their special character values. A better solution would be to modify the sample code to always append the '\r' character (remember...different from simply adding a '\' followed by an 'r') to anything you type when you hit the send button so you only have to type "ATRV" in the text box. Something like this in your OnEditorActionListener code (again, note the direction of the slash or you'll just add two characters):

public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {
    // If the action is a key-up event on the return key, send the message
    if (actionId == EditorInfo.IME_NULL && event.getAction() == KeyEvent.ACTION_UP) {
        //This gets the raw text from the box
        String message = view.getText().toString();
        //Append a CR to every message sent.  The added string is defined as a literal,
        // so Java parses is as a single CR character.
        sendMessage(message + "\r");
    }
    if(D) Log.i(TAG, "END onEditorAction");
    return true;
}

You could also modify your sample by hard-coding the string command as I have in the example above. Java interprets the String literal value "ATRV\r" correctly, placing that CR character at the end (making this a 5 character string).

这篇关于使用BluetoothChat与ELM327沟通的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-15 19:54