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;
}
};
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.