I am attempting to communicate with an ELM327 OBD-II Bluetooth dongle using the Android BluetoothChat example. I can connect to the device without any trouble, and messages from BluetoothChat to the OBD-II device seem to be transmitted and received by the device correctly.
However, the response messages from the OBD-II 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 hexadecimal 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 OBD-II 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 Stack Overflow question).
Change 1 (in file 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 file 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;
}
};
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.