androidbluetoothobd-iielm327

BluetoothChat-to-ELM327 split response message


I am attempting to communicate with an ELM327 OBDII Bluetooth dongle using the Android BluetoothChat example. I can connect to the device without any trouble, and messages from BluetoothChat to the ODBII device seem to be transmitted and received by the device correctly.

However, the response messages from the OBDII device are often split into several messages, scrambled, or missing characters.

For example, it takes three tries of the ati command to receive the full expected response: Me: ati OBDII: a OBDII: 327 OBDII: 327 OBDII: 327 v1.5 > Me: ati OBDII: 1 OBDII: 1 OBDII: 1.5 >v OBDII: 1.5 > Me: ati OBDII: ELM327 v1.5 >

Similarly, sending 010c should trigger a one line response containing three hex pairs. Instead, I usually (but not always) get results like the following: Me: 010c OBDII: OBDII: 4 OBDII: 3C OBDII: 3 OBDII: 3C C OBDII: 3C OBDII: OBDII: OBDII: >

I have tried several different baud rates and different OBDII protocols, but changes from the default settings only seem to make matters worse. Is there a problem with my response message handling? Why is the response message splitting? The Bluetooth dongle works properly with available apps such as Torque, so I don't think the device is malfunctioning.

The code that I'm using is almost identical to the BluetoothChat project (source here). I have only modified the UUID for my Bluetooth device and added a carriage return to the outgoing message (as per this StackOverflow question).

Change 1 (in BluetoothChatService.java):

    // Unique UUID for this application
private static final UUID MY_UUID_SECURE =
    //UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");
    UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
private static final UUID MY_UUID_INSECURE =
    //UUID.fromString("8ce255c0-200a-11e0-ac64-0800200c9a66");
    UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

Change 2 (in BluetoothChat.java):

    // 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);
            sendMessage(message + "\r");
        }
        if(D) Log.i(TAG, "END onEditorAction");
        return true;
    }
};

ELM327 manual for reference


Solution

  • I found a solution to my message splitting problem in this BluetoothSPP project by user akexorcist on Github. The relevant function from class ConnectedThread is presented below:

         public void run() {
       byte[] buffer;
       ArrayList<Integer> arr_byte = new ArrayList<Integer>();
    
       // Keep listening to the InputStream while connected
       while (true) {
          try {
                int data = mmInStream.read();
                if(data == 0x0A) { 
                } else if(data == 0x0D) {
                    buffer = new byte[arr_byte.size()];
                    for(int i = 0 ; i < arr_byte.size() ; i++) {
                        buffer[i] = arr_byte.get(i).byteValue();
                    }
                   // Send the obtained bytes to the UI Activity
                   mHandler.obtainMessage(BluetoothState.MESSAGE_READ
                            , buffer.length, -1, buffer).sendToTarget();
                   arr_byte = new ArrayList<Integer>();
                } else {
                   arr_byte.add(data);
                }
           } catch (IOException e) {
               connectionLost();
               // Start the service over to restart listening mode
               BluetoothService.this.start(BluetoothService.this.isAndroid);
               break;
           }
       }
    }
    

    Apparently, though please correct me if I'm wrong, .read() cannot grab and maintain the format of whatever bytes appear on the stream without some assistance.