1

I'm working on a OBD-ii Reader.

I am using a basic bluetooth chat to communicate with the OBD-ii device, regular expressions to capture the replies and displaying them in text views.

This is where I send the PID code's to request the data:

public void getData(int messagenumber) {

    final TextView TX = (TextView) findViewById(R.id.TXView2); 

    switch(messagenumber) {

        case 1:
            sendMessage("01 2F" + '\r'); //get Fuel %
            TX.setText("01 2F");
            Log.d("Case1: ", String.valueOf(messagenumber));    
            messagenumber++;
            Log.d("Case1: ", String.valueOf(messagenumber));    
            break;
        case 2:
            sendMessage("01 31" + '\r'); //get Mileage
            TX.setText("01 31");
            Log.d("Case2: ", String.valueOf(messagenumber));    
            messagenumber++;
            Log.d("Case2: ", String.valueOf(messagenumber));    
            break;
        case 3:
            sendMessage("01 0C" + '\r'); //get RPM
            TX.setText("01 0C");
            Log.d("Case3: ", String.valueOf(messagenumber));    
            messagenumber++;
            Log.d("Case3: ", String.valueOf(messagenumber));    
            break;

        default: ;       
    }
}

Then pick up the data here:

        switch (msg.what) {
        case MESSAGE_STATE_CHANGE:
            if(D) Log.i(TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1);
            switch (msg.arg1) {
            case BluetoothChatService.STATE_CONNECTED:
                setStatus(getString(R.string.title_connected_to, mConnectedDeviceName));
                mConversationArrayAdapter.clear();
                break;
            case BluetoothChatService.STATE_CONNECTING:
                setStatus(R.string.title_connecting);
                break;
            case BluetoothChatService.STATE_LISTEN:
            case BluetoothChatService.STATE_NONE:
                setStatus(R.string.title_not_connected);
                break;
            }
            break;
        case MESSAGE_WRITE:
            byte[] writeBuf = (byte[]) msg.obj;
            // construct a string from the buffer
            String writeMessage = new String(writeBuf);

            mConversationArrayAdapter.add("Me:  " + writeMessage);
            break;
        case MESSAGE_READ:
            byte[] readBuf = (byte[]) msg.obj;
            // construct a string from the valid bytes in the buffer               
            String readMessage = new String(readBuf, 0, msg.arg1);
            Log.d("BYTES: ", readMessage);

            // ------- ADDED CODE FOR OBD -------- //      
            dataRecieved = readMessage;
            RX.setText(dataRecieved);



           if((dataRecieved != null) && (dataRecieved.matches("\\s*[0-9A-Fa-f]{2} [0-9A-Fa-f]{2}\\s*\r?\n?" ))) {

                    dataRecieved = dataRecieved.trim();
                    String[] bytes = dataRecieved.split(" ");
                    Log.d("DR 1val: ",dataRecieved + "--!");


                    if((bytes[0] != null)&&(bytes[1] != null)) {

                         PID = Integer.parseInt(bytes[0].trim(), 16);
                         value = Integer.parseInt(bytes[1].trim(), 16); 
                        }


             if (PID == 47) {

            /*case 47: //PID(2F): Fuel % */

                int fuelValue = ((value*100)/255);

                String displayFuel = String.valueOf("PID: " + PID + "Val: " + value + "fuel: " + fuelValue + " %");
                Fuel.setText(displayFuel);
                /*break;
            default: ;*/
             }

        }
        else if((dataRecieved != null) && (dataRecieved.matches("\\s*[0-9A-Fa-f]{2} [0-9A-Fa-f]{2} [0-9A-Fa-f]{2}\\s*\r?\n?" ))) {

            dataRecieved = dataRecieved.trim();
            String[] bytes = dataRecieved.split(" ");
            Log.d("DR 2vals: ",dataRecieved + "--!");



            if((bytes[0] != null)&&(bytes[1] != null)&&(bytes[2] != null)) {

                PID = Integer.parseInt(bytes[0].trim(), 16);
                //if (PID == 12){
                value1 = Integer.parseInt(bytes[1].trim(), 16);
                value2 = Integer.parseInt(bytes[2].trim(), 16);
                /*}
                else if (PID == 49){
                //mileVal = Integer.parseInt(bytes[1].trim(), 16);
                }*/
            }   

                //PID(0C): RPM
            if (PID == 12) { 

                    int RPM_value = ((value1*256)+value2)/4;


                    String displayRPM = String.valueOf("PID: " + PID + "A: " + value1 + " B: " + value2 + "RPM: " + RPM_value);
                    Throttle.setText(displayRPM);

            }
            else if (PID == 49) {


                //PID(31): Distance Travelled   (A*256)+B 

                        int miles = (int) (((value1*256)+value2)*0.62137);

                        //String displayDistance = String.valueOf(miles + " miles");
                        String displayDistance = String.valueOf("PID: " + PID + "A: " + value1 + " B: " + value2 + "Miles: " + miles);
                        Distance.setText(displayDistance);

        }
        }

I then use this regular expression to listen for the > which means the OBD is finished processing the command and this should then go back to the start and request the PID codes again.

   else if((dataRecieved != null) && (dataRecieved.matches("\\s*[ .A-Za-z0-9\\?*>\r\n]*\\s*>\\s*\r*\n*" ))) {

            if(message_number == 4){
                message_number = 1;
            }
            getData(message_number++);
        }

When I run the application it takes a long time to start giving me any values, however they are accurate. I have a log of the data received from the OBD. My log however is coming out with some stuff I don't understand. I also notice that the textView that shows me the dataRecieved comes up with unknown characters and says STOPPED, then freezes and starts up again after a short while. Here is some of the log...

   D/TextLayoutCache(5146): Cache value 0x520da3b8 deleted, size = 136
   V/BluetoothSocket.cpp(5146): readNative
   D/TextLayoutCache(5146): Cache value 0x4dbd5e00 deleted, size = 176
   V/BluetoothSocket.cpp(5146): readNative
   V/BluetoothSocket.cpp(5146): readNative
   D/TextLayoutCache(5146): Cache value 0x4dfead50 deleted, size = 240
    D/TextLayoutCache(5146): Cache value 0x520dcb10 deleted, size = 240
   V/BluetoothSocket.cpp(5146): readNative
  D/BYTES:(5146): C 
  D/BYTES:(5146): 4 
  D/BYTES:(5146): 4 
  D/BYTES:(5146): 4 
user3010383
  • 91
  • 1
  • 1
  • 12
  • My [explain tool](http://www.regexdoc.com/re/explain.pl) breaks it down for a better understanding. First [regex](http://regexdoc.com/re/explain.pl?re=%5Cs*%5B0-9A-Fa-f%5D%7B2%7D+%5B0-9A-Fa-f%5D%7B2%7D%5Cs*%5Cr%3F%5Cn%3F&.submit=Explain%21&mode=SO&.cgifields=mode), second [regex](http://regexdoc.com/re/explain.pl?re=%5Cs*%5B+.A-Za-z0-9%5C%5C%3F*%3E%5Cr%5Cn%5D*%5Cs*%3E%5Cs*%5Cr*%5Cn*&.submit=Explain%21&mode=SO&.cgifields=mode) – hwnd Nov 11 '14 at 18:53
  • Thanks for that, helped a lot :) – user3010383 Nov 11 '14 at 22:37
  • FYI, you can ignore the cache value deleted warnings. See my answer to [this question](http://stackoverflow.com/questions/17449835/tag-textlayoutcache-text-cache-value-deleted/22267989). – Nick Westgate Jun 03 '15 at 01:57

1 Answers1

0

These sites will help you get started with regular expressions:

http://www.rexegg.com/regex-quickstart.html

http://www.cheatography.com/davechild/cheat-sheets/regular-expressions/

When trying to understand any code break it down into smaller steps:

dataRecieved = readMessage;

This is just setting dataRecieved equal to readMessage

The \s stands for White space and is a 'character class'

0-9 is a range, so is A-F, is a-f. Notice they are making it match both lower and upper case.

When looking at this \s*[ .A-Za-z0-9\ notice how there are \ something in between \ Regular Expressions usually have this area for your search terms and ranges.

if((dataRecieved != null) && (dataRecieved.matches("\\s*[0-9A-Fa-f]{2} [0-9A-Fa-f]{2}\\s*\r?\n?" ))) {

This line asks a conditional 'if' and has && so both must be true to evaluate to true for the whole conditional, or it returns false.

There is more but before I continue:

I recommend editing your question at this point and clarifying what you do understand and then asking questions about specific parts of the code. I did not hear in your question what part of the code exactly you are confused about, so it is hard to answer your question without explaining the whole thing at this point.

I hope this answer helps you get started

jasonleonhard
  • 6,357
  • 53
  • 49