2

I am working on an Android App that receives Data from a OBD II Bluetooth Adapter. Setting up the Connection between App and Adapter works but when I send commands to the Adapter I wont get the right results. It either returns:

+CONNECTING<

or the command I just sent to the Adapter.

The App is coded in Visual Studio using Xamarin to develop for Android. The code shows just a simplified version of the app and just sents the code for the supported PIDs between 01 -1f.

BluetoothAdapter myAdapter;
BluetoothSocket socket = null; 
string rawData;
public BluetoothConnect()
    {

        myAdapter = BluetoothAdapter.DefaultAdapter;
        if (myAdapter == null)
        {
            //Device has no Bluetooth
        }
        if (!myAdapter.IsEnabled)
        {
            myAdapter.Enable();
        }
        BluetoothDevice d = myAdapter.GetRemoteDevice("AA:BB:CC:11:22:33");
        socket = d.CreateRfcommSocketToServiceRecord(UUID.FromString("00001101-0000-1000-8000-00805F9B34FB"));
        socket.Connect();

        byte[] cmd = Encoding.ASCII.GetBytes("AT D");
        socket.OutputStream.Write(cmd, 0, cmd.Length);
        ReadAnswer();
        socket.OutputStream.Flush();

        cmd = Encoding.ASCII.GetBytes("AT Z");
        socket.OutputStream.Write(cmd, 0, cmd.Length);
        socket.OutputStream.Flush();

        cmd = Encoding.ASCII.GetBytes("AT E0");
        socket.OutputStream.Write(cmd, 0, cmd.Length);
        ReadAnswer();
        socket.OutputStream.Flush();

        cmd = Encoding.ASCII.GetBytes("AT L0");
        socket.OutputStream.Write(cmd, 0, cmd.Length);
        ReadAnswer();
        socket.OutputStream.Flush();

        cmd = Encoding.ASCII.GetBytes("AT S0");
        socket.OutputStream.Write(cmd, 0, cmd.Length);
        ReadAnswer();
        socket.OutputStream.Flush();

        cmd = Encoding.ASCII.GetBytes("AT H0");
        socket.OutputStream.Write(cmd, 0, cmd.Length);
        ReadAnswer();
        socket.OutputStream.Flush();

        cmd = Encoding.ASCII.GetBytes("AT SP 0");
        socket.OutputStream.Write(cmd, 0, cmd.Length);
        ReadAnswer();
        socket.OutputStream.Flush();




        cmd = Encoding.ASCII.GetBytes("0100");
        socket.OutputStream.Write(cmd, 0, cmd.Length);

        ReadAnswer();


    }

    private void ReadAnswer() {
        try {
            rawData = "";
            int a = 0;

            System.Text.StringBuilder b = new   System.Text.StringBuilder();
            char c;
            while (((a = (byte)socket.InputStream.ReadByte()) > -1)) 
            {

                c = (char)a;
                if (c == '>')
                {
                    break;
                }
                b.Append(c);
            }

            rawData = b.ToString();
            Log.Info("-----------------------------------", "RawData: " + rawData);
            socket.InputStream.Flush();
        }
        catch(System.Exception e)
        {
            Log.Info("", "" + e.Message);
        }



    } 

I already tried different combinations of initialization Commands.

I could imagine that the problem has to do either with my method of reading the inputstream or with sending the commands but I can't figure out what to do, since I am new to Visual Studio, Xamarin and Android developing.

Hope you guys can give me some suggestions!

Caspar
  • 21
  • 1
  • 3
  • Try wrapping your bluetooth enablling and init socket connection code in in try catches. – Terrance Jun 25 '16 at 19:31
  • Verify that you have the correct permissions for bluetooth or use this to enable it without explicit consent. https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#enable() Is ASCII the correct encoding? – Terrance Jun 25 '16 at 19:33
  • @Terrance Thanks for the fast reply! Just tried your suggestions. The try catch constrcution works fine - no Exception. Checked the permission (enable Bluetooth and Bluetooth_Admin) - should be all I need for sending and reveiving. Tried the ASCII method in a seperate class and it seems that the method is working as supposed. – Caspar Jun 25 '16 at 22:35

1 Answers1

1

It's too old now but maybe someone needed. below code is tested with ELM327 developed in Xamarin.

 public void SendCommand( string command , Action<string> onDataRecevied )
    {
        if ( BthSocket.IsConnected )
        {
            byte[] cmd = Encoding.ASCII.GetBytes( command + " \r" );
            BthSocket.OutputStream.Write( cmd , 0 , cmd.Length );
            BthSocket.OutputStream.Flush();


            ReadData( out string d );
            if ( d != "" )
            {
                onDataRecevied( d );
            }



        }
    }

and to read data

public void ReadData( out string data )
    {
        StringBuilder res = new StringBuilder();

        try
        {
            byte b = 0;


            // read until '>' arrives OR end of stream reached
            char c;
            // -1 if the end of the stream is reached
            while ( ( b = ( ( byte )BthSocket.InputStream.ReadByte() ) ) > -1 )
            {
                c = ( char )b;
                if ( c == '>' ) // read until '>' arrives
                {
                    break;
                }
                res.Append( c );
            }

        }
        catch ( Exception e )
        {
            System.Console.WriteLine( e.ToString() );
        }

      data = res.ToString().Replace( "SEARCHING" , "" );

        /*
         * Data may have echo or informative text like "INIT BUS..." or similar.
         * The response ends with two carriage return characters. So we need to take
         * everything from the last carriage return before those two (trimmed above).
         */

        data = data.Replace( "\\s" , "" );

    }

and to init the device below are commands

 obd2.SendCommand( "AT Z" , ( obj ) => { LogMessage( txtData , obj ); } );
             obd2.SendCommand( "AT E0" , ( obj ) => { LogMessage( txtData , obj ); } );
             obd2.SendCommand( "AT E0" , ( obj ) => { LogMessage( txtData , obj ); } );
             obd2.SendCommand( "AT L0" , ( obj ) => { LogMessage( txtData , obj ); } );
             obd2.SendCommand( "AT S0" , ( obj ) => { LogMessage( txtData , obj ); } );
             obd2.SendCommand( "ATD" , ( obj ) => { LogMessage( txtData , obj ); } );
             obd2.SendCommand( "AT SP 6" , ( obj ) => { LogMessage( txtData , obj ); } );
             obd2.SendCommand( "AT H0" , ( obj ) => { LogMessage( txtData , obj ); } );
             obd2.SendCommand( "AT 1" , ( obj ) => { LogMessage( txtData , obj ); } );
             obd2.SendCommand( "ATST 96" , ( obj ) => { LogMessage( txtData , obj ); } );
             obd2.SendCommand( "AT H1" , ( obj ) => { LogMessage( txtData , obj ); } );
             obd2.SendCommand( "AT H0" , ( obj ) => { LogMessage( txtData , obj ); } );

this line data = res.ToString().Replace( "SEARCHING" , "" ); is imagine the following response 41 0c 00 0d. ELM sends strings!! So, ELM puts spaces between each "byte". And pay attention to the fact that I've put the word byte in quotes, because 41 is actually TWO bytes (two chars) in the socket. So, we must do some more processing.

Hope this helps.

Adeel Rizvi
  • 114
  • 2
  • 4
  • All those commands are necessary to init the device before send other commands to it? – gregoryp Mar 29 '21 at 00:20
  • @perozzo, yes these are the device initial commands, you can skip a few if you don't want to depend on the ELM version. here is the pdf which will tell you what each command does what : https://www.sparkfun.com/datasheets/Widgets/ELM327_AT_Commands.pdf – Adeel Rizvi Apr 18 '21 at 02:19