2017-01-30 2 views
1

У меня есть блок навигации, который выплескивает 3 сообщения на 200 Гц. Я пытаюсь захватить эти сообщения в том порядке, в котором они отправлены, и получить определенные данные из этих сообщений и обновить переменные, которые отправляется серийно в массив байтов.Поиск данных байта certian из InputStream

Я использую сокеты и входной поток для захвата данных и передается в класс runnable с именем socketReader. Другой класс runnable принимает переменные и выполняет некоторую математику и преобразует их в байты и отправляет их поочередно.

Эта программа будет работать около 8 часов за раз, и поток данных будет постоянным, за исключением третьего сообщения (данные GPS), которое будет отправлено только тогда, когда будет один.

  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(); 

У меня возникли проблемы с классом socketReader. Поэтому я знаю заголовки в шестнадцатеричном формате, поэтому я читаю данные из DataInputStream в байтовый буфер и в stringBuilder, где я помещаю данные в другие подстроки и преобразую их в float.

Это работает, у меня возникла проблема с разбором строки altHold logHold latHold (и прокомментирован). Вместо 4 байтов (с плавающей запятой с одинарной точностью) они равны 8 байтам (с плавающей запятой с двойной точностью). Но я чувствую, что я изобретаю колесо здесь. Данные в сообщениях являются наименее значимыми, и я чувствую, как я это делаю, это замедляет мою программу? Также он не идеален. Он будет работать некоторое время, когда он выйдет из него.

и в настоящее время я рассматриваю только два сообщения, третье которых не отправляется как частота, как первые два. Должен ли я использовать что-то другое, кроме 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)); 

       } 

      } 
     } 
    } 
} 

Я был бы признателен за вашу помощь или, если бы вы могли указать мне в правильном направлении, это было бы здорово. Если вам нужна дополнительная информация от меня, я был бы рад дать ее.

Спасибо!

ответ

1

Не рекомендуется (IMHO) использовать DataInputStream для чтения данных, не генерируемых DataOutputStream. Они используют собственный протокол для записи/чтения определенных типов данных (например, UTF String).

Это не проблема вышеуказанного кода, так как он только считывает байты с readFully(1024). Но использование этого метода может быть проблемой здесь: он считывает полный буфер (в конечном счете, блокирует), если соединение не закрыто (как правило, или исключение), то есть ваши сообщения должны иметь длину 1024 байта.

Также трудно понять преобразования, выполненные кодом. Это то, что я думаю, делается: byte to string (шестнадцатеричное представление), строки с порядком шестнадцатеричных значений изменены, преобразованы в long, преобразованы в float. Я сомневаюсь, что выполнение всей арифметики с помощью Strings - лучшее решение ...

В любом случае, я бы предложил использовать собственный метод, который задавал массив байтов и (начальный) индекс, возвращает вычисленный float/double (избегает повторения , легче понять и TEST), как:

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); 
} 

и а еще лучше ИМХО решение использует ByteBuffer завернуть или вместо byte[]. ByteBuffer может быть настроен на малочисленность и имеет методы для получения плавающего и двойного (example), а также для чтения из сокета тоже

Смежные вопросы