1
votes

I tried to create a simple android application to connect to my ELM327 device to get some car diagnostic data. But I wasn't able to set up the bluetooth connection b/t my android phone and my ELM327 device.

My code is very simple as below:

public class Bluetooth { protected BluetoothAdapter mBluetoothAdapter= BluetoothAdapter.getDefaultAdapter(); private ConnectThread mConnectThread = null; private AcceptThread mAcceptThread = null; private WorkerThread mWorkerThread = null; private BluetoothDevice mOBDDevice = null; private BluetoothSocket mSocket = null; private String uuid;

Bluetooth() {
    mBluetoothAdapter= BluetoothAdapter.getDefaultAdapter();
    Set<BluetoothDevice> pairedDevices;


    if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled())
        return;

    pairedDevices = mBluetoothAdapter.getBondedDevices();
    if (pairedDevices.size() > 0) {
        // There are paired devices. Get the name and address of each paired device.
        for (BluetoothDevice device : pairedDevices) {
            String deviceName = device.getName();
            String deviceHardwareAddress = device.getAddress(); // MAC address
            //TODO: check whether this is OBD and whether it is connected
            //by sending a command and check response
            if (deviceName.contains("OBD")) {
                mOBDDevice = device;
                uuid = device.getUuids()[0].toString();
                break;
            }
        }
    }
    mBluetoothAdapter.cancelDiscovery();
}

/**
 * Start the chat service. Specifically start AcceptThread to begin a session
 * in listening (server) mode. Called by the Activity onResume()
 */
public synchronized void connect()
{
    try {
        // Get a BluetoothSocket to connect with the given BluetoothDevice.
        // MY_UUID is the app's UUID string, also used in the server code.
        mSocket = mOBDDevice.createRfcommSocketToServiceRecord(UUID.fromString(uuid));
    } catch (IOException e) {
        Log.e(TAG, "Socket's create() method failed", e);
    }

    try {
        // Connect to the remote device through the socket. This call blocks
        // until it succeeds or throws an exception.
        mSocket.connect();
    } catch (IOException connectException) {
        // Unable to connect; close the socket and return.
        try {
            mSocket.close();
        } catch (IOException closeException) {
            Log.e(TAG, "Could not close the client socket", closeException);
        }
        return;
    }
}

}

In the mainactivity, I will first new a Bluetooth class then call bluetooth.connect():

mBluetooth = new Bluetooth(); mBluetooth.connect();

When I debug the program, I was able to get my ELM327 bluetooth device by querying all the bonded devices with a name of "OBD". I also was able to get the device's uuid and create a socket using createRfcommSocketToServiceRecord. But in the connect function, mSocket.connect() always fail with a return value of -1 and get a IOexception.

My questions are:

  1. When my android application connect to the ELM327 device, my android phone is the bluetooth client and my ELM327 device is the bluetooth server, is this understanding correct?
  2. Is there a server program running on my ELM327 device listening and accept incoming connection? Is this defined behavior of ELM327 protocol?
  3. Any idea why mSocket.connect()has failed? Any idea on how to look into this issue? Or any obvious error in my program? Thanks.
2
Bluetooth Serial can encompass a number of different protocols and/or device vendor quirks. Unfortunately even knowing your phone's make/model/OS version and your OBD2 manufacturer, your multiple questions may be too broad for StackOverflow. I would advise checking if an existing project like: github.com/fr3ts0n/AndrOBD would suit your needs, or as a base for your own expansion/investigation.Morrison Chang
Thank you Morrison for reply. I have tried a few smart phone and a few OBD2 model, neither works so far. It seems a common/general problem in my program, instead of phone/obd specific issue. I also refered to a similiar existing project github.com/pires/android-obd-reader. Although the codes are organized differently but the core calling sequence is the same with mine. I will also look into AndrOBD. Thank you.Junshan Eng

2 Answers

1
votes

problem solved. see source codes below:

public synchronized void connect() throws IOException {
        try {
            // Get a BluetoothSocket to connect with the given BluetoothDevice.
            // MY_UUID is the app's UUID string, also used in the server code.
            mSocket = mOBDDevice.createRfcommSocketToServiceRecord(UUID.fromString(uuid));
        } catch (IOException e) {
            Log.e(TAG, "Socket's create() method failed", e);
        }

        try {
            // Connect to the remote device through the socket. This call blocks
            // until it succeeds or throws an exception.
            mSocket.connect();
        } catch (IOException e1) {
            Log.e(TAG, "There was an error while establishing Bluetooth connection. Falling back..", e1);
            Class<?> clazz = mSocket.getRemoteDevice().getClass();
            Class<?>[] paramTypes = new Class<?>[]{Integer.TYPE};
            try {
                Method m = clazz.getMethod("createRfcommSocket", paramTypes);
                Object[] params = new Object[]{Integer.valueOf(1)};
                mFallbackSocket = (BluetoothSocket) m.invoke(mSocket.getRemoteDevice(), params);
                mFallbackSocket.connect();
                mSocket.close();
                mSocket = mFallbackSocket;
            } catch (Exception e2) {
                Log.e(TAG, "Couldn't fallback while establishing Bluetooth connection.", e2);
                mSocket.close();
                //throw new IOException();
            }
        }
        inputStream = mSocket.getInputStream();
        outputStream = mSocket.getOutputStream();
    }
0
votes

I don't know much about Android, although I know about OBD2 and the lot.

  1. It depends on the type of your adapter. If you have a WiFi adapter, you can consider the adapter being the server and you the client. You connect to a socket and then read from it. In the case of a Bluetooth adapter, it's different. If you connect via rfcomm, it's a serial protocol and neither is the server nor the client. If you connect via BTLE, the OBD2 dongle is the Peripheral and you are the Central.

  2. On WiFi adapters, yes. This behavior is not part of ELM327 though. ELM327 only specifies the serial commands. How you transfer these is not part of the spec, since it happens on the layer above (WiFi, rfcomm, BTLE, USB, etc.).

  3. Are you sure that rfcomm works via the socket interface? It's a serial interface, so I would have expected file-like operations.