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
  • 2
  • 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
  • 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
  • 12,047
  • 89
  • 66
  • I have used hwmnd's explain tool and have done some more debugging so I will update the question now that I know what the expressions are doing! :) – user3010383 Nov 11 '14 at 22:38
  • Feel free to mark my question correct and/or upvote for my efforts. Thanks! – jasonleonhard Nov 11 '14 at 22:39
  • i am using mcp2515 with nodemcu-32s and am able to receive the messages which have few ids like 2c4, 2c1, 340 etc on the internet i see 2c4 is for rpm and i have verified it too. My question is that no matter which library i use to request the supported pids i send a message like this sendmsgbuf(0x7DF, 0 (ext), 8 (len), then data with 21, 01, 00 etc) and then i get a reply like 7E8,03 ( i assume len), 7F(negative res), 01 (for request), 11 (sub function wrong). I want to know that my car dont support requesting pid’s from it? Or is there something else which i dont know. Thanks – Jahanzaib Khan Jul 04 '23 at 02:49