1

I want to send a String to an OBD2 Adapter, to read some information, for example the battery voltage. So I wrote this little program:

public class MainActivity extends Activity {
    private BluetoothAdapter mBluetoothAdapter = BluetoothAdapter
            .getDefaultAdapter();
    private ConnectedThread connected;
    private boolean isConnected = false;

    // private final BluetoothSocket mmSocket;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    // Button ruft die Methode verbindung auf!!!!
    public void verbinden(View view) {
        verbindung();
        Toast.makeText(getApplicationContext(), "Verbunden!", Toast.LENGTH_LONG).show();
    }

    // Senden Button
    public void senden(View view) {
        String message;
        EditText Message = (EditText) findViewById(R.id.TFKonsole);
        message = (Message.getText().toString());
        Toast.makeText(getApplicationContext(), "Nachricht gesendet!", Toast.LENGTH_LONG).show();


        for (int i = 0; i < message.length(); i++) {
            char c = message.charAt(i);
            String bereit = Integer.toHexString(c);
            System.out.println(bereit);
            byte[] send = bereit.getBytes();
            connected.write(send);
            //connected.write(abschluss);
        }
    }

    // Trennen Butto
    public void trennen(View view) {
        connected.cancel();
    }

    // Verbindung wird ausgeführt
    private void verbindung() {
        String address = "AA:BB:CC:11:22:33"; // Adresse vom Dongle(ITEM)
                                                // 00:0D:18:06:00:00 ADRESSE VOM
                                                // DONGEL (ANDREAS)
                                                // 00:0D:18:3A:67:89
                                                // B8:E8:56:41:74:09marco
                                                // 00:09:DD:42:5B:AA adresse
                                                // bluetoothstick
        BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
        ConnectThread connect = new ConnectThread(device);
        connect.start();
        // connected.write(null);
    }

    private class ConnectThread extends Thread {
        private final BluetoothSocket mmSocket;
        private final BluetoothDevice mmDevice;

        public ConnectThread(BluetoothDevice device) {

            // mBluetoothAdapter.cancelDiscovery();
            // Use a temporary object that is later assigned to mmSocket,
            // because mmSocket is final
            BluetoothSocket tmp = null;
            mmDevice = device;
            ParcelUuid[] i = device.getUuids();
            // Holt sich ein BluetoothSocket, um sich mit dem BluetoothDevice zu
            // verbinden
            try {
                // MY_UUID is the app's UUID string, also used by the server
                // code
                Method m = device.getClass().getMethod("createRfcommSocket",
                        new Class[] { int.class });
                tmp = (BluetoothSocket) m.invoke(device, 1);

            } catch (NoSuchMethodException e) {
                // TODO Auto-generated catch block
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            mmSocket = tmp;
        }

        public void run() {
            // Trenne die Verbindung, weil eine bestehende Verbindung viel
            // Speicher in anspruch nimmt
            // mBluetoothAdapter.cancelDiscovery();

            try {
                mBluetoothAdapter.cancelDiscovery();
                // Verbinde das Gerät über den Socket. Dies wird geblockt,
                // bis die Verbindung erfolgt oder eine Exception fliegt
                mmSocket.connect();
                isConnected = true;
                boolean k = mmSocket.isConnected();
                System.out.println(k + " Verbindung erfolgreich");
            } catch (IOException connectException) {
                connectException.printStackTrace();
                // Verbinden unmöglich; Schließe den Socket und beende die App
                boolean a = mmSocket.isConnected();
                System.out.println(a + " Verbindung fehlgeschlagen a");
                try {
                    mmSocket.close();
                } catch (IOException closeException) {
                    boolean b = mmSocket.isConnected();
                    System.out.println(b + " Verbindung fehlgeschlagen b");
                }
                return;
            }

            connected = new ConnectedThread(mmSocket);
            connected.run();
        }

        /** Will cancel an in-progress connection, and close the socket */
        public void cancel() {
            try {
                mmSocket.close();
            } catch (IOException e) {
            }
        }
    }

    private class ConnectedThread extends Thread {
        private final BluetoothSocket mmSocket;
        private final InputStream mmInStream;
        private final OutputStream mmOutStream;

        public ConnectedThread(BluetoothSocket socket) {
            mmSocket = socket;
            InputStream tmpIn = null;
            OutputStream tmpOut = null;

            // Get the input and output streams, using temp objects because
            // member streams are final
            try {
                tmpIn = socket.getInputStream();
                tmpOut = socket.getOutputStream();
            } catch (IOException e) {
                e.printStackTrace();
            }

            mmInStream = tmpIn;
            mmOutStream = tmpOut;
        }

        public void run() {
            byte[] buffer = new byte[1024]; // buffer store für den Stream
            int bytes; // bytes, die von read() zurückgegeben werden

            // Achte auf den InputStream, bis alles übertragen wurde
            // oder eine Exception fliegt
            while (true) {
                try {
                    // Lese von dem InputStream
                    bytes = mmInStream.read(buffer);
                    // Send the obtained bytes to the UI activity
                    // mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)
                    // .sendToTarget();

                    // Ausgabe im Textfeld
                    // setContentView(R.layout.activity_main);
                    final String sausgabe = new String(buffer);
                    final TextView ausgabe = (TextView) findViewById(R.id.textView1);


                    runOnUiThread(new Runnable() {

                        //Methode, um einen Thread aus einem anderen aufzurufen
                        @Override
                        public void run() {
                            // TODO Auto-generated method stub
                            ausgabe.setText("\n" + sausgabe);
                            Log.e("", "Aufruf");

                        }
                        // do something on UI thread Update UI
                    });

                } catch (IOException e) {
                    break;
                }
            }
        }

        /* Rufen sie diese Methode auf, um Daten zum Remote Gerät zu senden */
        public void write(byte[] bytes) {
            try {
                mmOutStream.write(bytes);
                // connected.write(null);
            } catch (IOException e) {
                e.printStackTrace();
                System.out.println("Senden fehlgeschlagen");
            }
        }

        /* Rufen sie diese Methode auf, um die Verbindung zu trennen */
        public void cancel() {
            try {
                Toast.makeText(getApplicationContext(), "Getrennt!", Toast.LENGTH_LONG).show();
                mmSocket.close();
                System.out.println("Getrennt");
            } catch (IOException e) {
                System.out.println("Trennen fehlgeschlagen");
            }
        }
    }
}


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.blue_final.MainActivity$PlaceholderFragment" >

    <Button
        android:id="@+id/BtnVerbinden"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:onClick="verbinden"
        android:text="verbinden" />

    <EditText
        android:id="@+id/TFKonsole"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/BtnVerbinden"
        android:layout_alignRight="@+id/BtnSenden"
        android:layout_below="@+id/BtnVerbinden"
        android:ems="10" />

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/BtnVerbinden"
        android:layout_alignBottom="@+id/BtnVerbinden"
        android:layout_alignParentRight="true"
        android:onClick="trennen"
        android:text="@string/gui_trennen" />

    <Button
        android:id="@+id/BtnSenden"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/TFKonsole"
        android:layout_toLeftOf="@+id/button1"
        android:onClick="senden"
        android:text="senden" />

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_alignRight="@+id/button1"
        android:layout_below="@+id/TFKonsole" />

</RelativeLayout>

If I press the Send button i get a ? (question mark). I think it´s something wrong with my for loop. The dongle only reads hex, but I can only send bytes. I hope you can help me =)

sjakobi
  • 3,546
  • 1
  • 25
  • 43
  • What data are you sending? Does it work if you use a terminal? – Eric Smekens Apr 27 '14 at 14:36
  • 1
    Hi Eric, I sending ATRV (for battery voltage). If I use a Terminal-Program (HTerm) I get 34 31 35 34 35 32 35 36. I think it´s realy a problem of my for loop. But I don´t see my mistake yet. If I try it without the for loop I get the result that I´ve wanted, somthing like this 41 54 52 56 but the OBDII needs an endingsign. In fact 0D in Hex. So, how I can send it to the Dongle? – user3510014 Apr 28 '14 at 18:31

2 Answers2

0

I think you have a problem on your foor loop

    for (int i = 0; i < message.length(); i++) {
                    char c = message.charAt(i);
                    String bereit = Integer.toHexString(c);
                    System.out.println(bereit);
                    byte[] send = bereit.getBytes();
                    connected.write(send);
                    //connected.write(abschluss);
    }

you're sending the entire message for each of the message positions.

0
for (int i = 0; i < message.length(); i++) {
                char c = message.charAt(i);
                String bereit = Integer.toHexString(c);
                System.out.println(bereit);
                byte[] send = bereit.getBytes();
                connected.write(send);
                //connected.write(abschluss);
}

As you see your write gets called every time for each character. That write calls:

mmOutStream.write(bytes);

I'm not sure, but could it be that every write gets closed with a \r? The '\r' is the carriage return (cr) which is indeed 0D in hex.

Or maybe it looks like your command is never understood because it doesn't receive the cr. Maybe it gives a timeout or something, because it keeps waiting for your cr? Anyway, try to send a '\r' after your loop.

    for (int i = 0; i < message.length(); i++) {
        char c = message.charAt(i);
        String bereit = Integer.toHexString(c);
        System.out.println(bereit);
        byte[] send = bereit.getBytes();
        connected.write(send);
    }
    //Send your '\r' here.

PS: You say you need to write in hex to the OBD-II dongle? You might want to try that in ASCII, as most of the documentation is in ASCII and the ELM327 protocol understands ASCII. Let me know your progress!

Eric Smekens
  • 1,602
  • 20
  • 32
  • Now I can send the endingsing with the following builder.append(message); ready.append(message); ready.append((char)Integer.parseInt(message , 16)); builder.append((char)Integer.parseInt("0D", 16)); message =ready.toString() + builder.toString(); The dongle understand ASCII but I´ll send Hex commands. At the moment I can´t read the Hex Comand like 01 05 (+ending sing) out of the textfield. Ideas? – user3510014 Apr 30 '14 at 12:56
  • What is the problem? Do you get an answer back from the dongle, or just the question mark if you send a command? – Eric Smekens Apr 30 '14 at 14:04