1

I have a navigation unit that is spiting out 3 messages at 200 Hz I am trying to capture these messages in the order they are sent and take certain data from within these messages and update variables that are being sent out serially in a byte array.

I am using sockets and a input stream to grab the data and is passed into a runnable class named socketReader. Another runnable class takes the variables and does some math and converts them to bytes and send them out serially.

This program will be ran for about 8 hours at a time and the data stream will be constant with the exception of the third message (GPS data) that will only be sent when there is a single.

            InputStream in = echoSocket.getInputStream();
            DataInputStream dis = new DataInputStream(in);

            OutputStream out = serialPort.getOutputStream();

            (new Thread(new SocketReader(dis))).start();
            (new Thread(new SerialWriter(out))).start();

What I am having trouble with is the socketReader class. So i know the headers in hex so I am reading the data from a DataInputStream to a byte buffer and into a stringBuilder where I put the data into more substrings and convert them to floats.

This does work, thou I am have trouble parsing the altHold logHold latHold string (and is commented out). Instead of 4 bytes (Single-precision floating-point ) of data they are 8 bytes (double-precision floating-point). But i feel like I am reinventing the wheel here. The data in the messages are least significant bit and I feel the way I am doing it is slowing down my program? Also it is not perfect It will run for a while the quit by falling out of it loops.

and currently I am only looking at two of the messages the third is not sent as frequency as the first two. Should I be using something other than DataInputStream?

    public static class SocketReader implements Runnable {  

    //Message headers
    final String mes1 = new String("FF5A0600");
    final String mes2 = new String("FF5A0800");
    final String mes3 = new String("FF5A1300");

    //These are the size of each message
    final int Stop1 = 82;
    final int Stop2 = 162;
    final int Stop3 = 150;

    StringBuilder rolHold = new StringBuilder();
    StringBuilder pitHold = new StringBuilder();
    StringBuilder yawHold = new StringBuilder();

    StringBuilder altHold = new StringBuilder();
    StringBuilder latHold = new StringBuilder();
    StringBuilder logHold = new StringBuilder();
    StringBuilder velNHold = new StringBuilder();
    StringBuilder velEHold = new StringBuilder();

    DataInputStream dis;

    public SocketReader( DataInputStream dis ) {
        this.dis = dis;
    }

    public void run() {

        byte[] buffer;

        //dis is a DataInputStream
        while (dis != null){

            buffer = new byte[ 1024 ];

            try {
                dis.readFully(buffer);
            } catch (IOException e1) {
                e1.printStackTrace();
            }

            StringBuilder sb = new StringBuilder();

            for (byte b: buffer){                   
                sb.append(String.format("%02X", b));
            }

            //Finds the first occurrence of the three messages
            //If the index is -1 there is no occurrence
            int index1 = sb.indexOf(mes1);
            int index2 = sb.indexOf(mes2);
            int index3 = sb.indexOf(mes3);


            while (index1 <= sb.lastIndexOf(mes1)  && (index1 != -1) && (index2 != -1) && (index2 != 0)){


                //this if statement deals with the first message
                //There are three sets of data pulled from message 1 {rolValue, pitValue, yawValue}         
                if (index1 < index2 && (index1 != -1)){

                    //reseting the Stringbuilders 
                    rolHold.setLength(0);
                    pitHold.setLength(0);
                    yawHold.setLength(0);

                    //the data is sent little-endian and is appended in reverse order
                    rolHold.append(sb.substring((index1 + 26),(index1 + 28)));
                    rolHold.append(sb.substring((index1 + 24),(index1 + 26)));
                    rolHold.append(sb.substring((index1 + 22),(index1 + 24)));
                    rolHold.append(sb.substring((index1 + 20),(index1 + 22)));
                    Long rol = Long.parseLong(rolHold.toString(), 16);
                    rolValue = Float.intBitsToFloat(rol.intValue());                            

                    pitHold.append(sb.substring((index1 + 34),(index1 + 36)));
                    pitHold.append(sb.substring((index1 + 32),(index1 + 34)));
                    pitHold.append(sb.substring((index1 + 30),(index1 + 32)));
                    pitHold.append(sb.substring((index1 + 28),(index1 + 30)));
                    Long pit = Long.parseLong(pitHold.toString(), 16);
                    pitValue = Float.intBitsToFloat(pit.intValue());        

                    yawHold.append(sb.substring((index1 + 42),(index1 + 44)));
                    yawHold.append(sb.substring((index1 + 40),(index1 + 42)));
                    yawHold.append(sb.substring((index1 + 38),(index1 + 40)));
                    yawHold.append(sb.substring((index1 + 36),(index1 + 38)));
                    Long yaw = Long.parseLong(yawHold.toString(), 16);
                    yawValue = Float.intBitsToFloat(yaw.intValue());


                    //increments the index1 to its next sequence of message 1
                    //-1 is returned if there is not another
                    index1 = sb.indexOf(mes1, (index1 + Stop1));
                }


                //this if statement deals with the second message
                //There are five sets of data pulled from message 2 {velNValue, velEValue, latValue, logValue, altValue}        
                if(index2 < index1 && (index2 != -1) && (index2 != 0)){ 


                    altHold.setLength(0);
                    latHold.setLength(0);   
                    logHold.setLength(0);
                    velNHold.setLength(0);  
                    velEHold.setLength(0);

                            velNHold.append(sb.substring((navIndex + 26),(navIndex + 28)));
                            velNHold.append(sb.substring((navIndex + 24),(navIndex + 26)));
                            velNHold.append(sb.substring((navIndex + 22),(navIndex + 24)));
                            velNHold.append(sb.substring((navIndex + 20),(navIndex + 22)));
                            Long velN = Long.parseLong(velNHold.toString(), 16);
                            velNValue = Float.intBitsToFloat(velN.intValue());



                            velEHold.append(sb.substring((navIndex + 34),(navIndex + 36)));
                            velEHold.append(sb.substring((navIndex + 32),(navIndex + 34)));
                            velEHold.append(sb.substring((navIndex + 30),(navIndex + 32)));
                            velEHold.append(sb.substring((navIndex + 28),(navIndex + 30)));
                            Long velE = Long.parseLong(velEHold.toString(), 16);
                            velEValue = Float.intBitsToFloat(velE.intValue());


    //                      latHold.append(sb.substring((navIndex + 82),(navIndex + 84)));
    //                      latHold.append(sb.substring((navIndex + 80),(navIndex + 82)));
    //                      latHold.append(sb.substring((navIndex + 78),(navIndex + 80)));
    //                      latHold.append(sb.substring((navIndex + 76),(navIndex + 78)));
    //                      latHold.append(sb.substring((navIndex + 74),(navIndex + 76)));
    //                      latHold.append(sb.substring((navIndex + 72),(navIndex + 74)));
    //                      latHold.append(sb.substring((navIndex + 70),(navIndex + 72)));
    //                      latHold.append(sb.substring((navIndex + 68),(navIndex + 70)));
    //                      Long lat = Long.parseLong(logHold.toString(), 16);
    //                      Float latValue = Float.intBitsToFloat(lat.intValue());                      
    //
    //                      logHold.append(sb.substring((navIndex + 98),(navIndex + 100)));
    //                      logHold.append(sb.substring((navIndex + 96),(navIndex + 98)));
    //                      logHold.append(sb.substring((navIndex + 94),(navIndex + 96)));
    //                      logHold.append(sb.substring((navIndex + 92),(navIndex + 94)));
    //                      logHold.append(sb.substring((navIndex + 90),(navIndex + 92)));
    //                      logHold.append(sb.substring((navIndex + 88),(navIndex + 90)));
    //                      logHold.append(sb.substring((navIndex + 86),(navIndex + 88)));
    //                      logHold.append(sb.substring((navIndex + 84),(navIndex + 86)));
    //                      Long log = Long.parseLong(logHold.toString(), 16);
    //                      Float logValue = Float.intBitsToFloat(log.intValue());
    //
    //
    //                      altHold.append(sb.substring((navIndex + 114),(navIndex + 116)));
    //                      altHold.append(sb.substring((navIndex + 112),(navIndex + 114)));
    //                      altHold.append(sb.substring((navIndex + 110),(navIndex + 112)));
    //                      altHold.append(sb.substring((navIndex + 108),(navIndex + 110)));
    //                      altHold.append(sb.substring((navIndex + 106),(navIndex + 108)));
    //                      altHold.append(sb.substring((navIndex + 104),(navIndex + 106)));
    //                      altHold.append(sb.substring((navIndex + 102),(navIndex + 104)));
    //                      altHold.append(sb.substring((navIndex + 100),(navIndex + 102)));
    //                      Long alt = Long.parseLong(altHold.toString(), 16);
    //                      Float altValue = Float.intBitsToFloat(alt.intValue());  



                    //increments the index2 to its next sequence of message 2
                    //-1 is returned if there is not another
                    index2 = sb.indexOf(mes2, (index2 +Stop2));

                }

            }
        }
    }
}

I would appreciate your help or if you could point me in the right direction that would be great too. If you need any more info from me I would be happy to give it.

Thanks!

user546749
  • 13
  • 4

1 Answers1

1

It is not recommended (IMHO) to use DataInputStream to read data not generated by DataOutputStream. They use an own protocol for writing/reading certain data types (e.g. UTF String).

This is not the problem of above code since it is only reading bytes with readFully(1024). But the use of this method could be a problem here: it reads the full buffer (eventually blocking) unless the connection is closed (normally or by Exception), that is, your messages must be 1024 bytes long.

Also it is hard to understand the transformations done by the code. That is what I think is being done: byte to string (hex representation), strings with order of hex values changed, converted to long, converted to float. I doubt that doing all the arithmetic with Strings is the best solution...

Anyway I would suggest to use a own method that given the byte array and (start)index, returns the calculated float/double (avoids repetition, is easier to understand and TEST), like:

private static float readFloat(byte[] buffer, int index) {
    // not done in a loop for demonstration 
    int bits =  (buffer[index+0] & 255) 
             + ((buffer[index+1] & 255) <<  8) 
             + ((buffer[index+2] & 255) << 16) 
             + ((buffer[index+3] & 255) << 24);
    return Float.intBitsToFloat(bits);
}

and a even better solution IMHO is using the ByteBuffer to wrap or instead of the byte[]. The ByteBuffer can be set to little-endian and has methods to get float and double (example), and would be an option for reading from the Socket too

Community
  • 1
  • 1
user85421
  • 28,957
  • 10
  • 64
  • 87