2

Я написал прослушиватель событий, которые предполагают, что любые сообщения определенного типа получат сообщение от получателя.catching <CR><LF> в массиве байтов

вот мое событие Слушатель:

class SerialPortReader implements SerialPortEventListener { 
    public void serialEvent(SerialPortEvent event) { 
     if (event.isRXCHAR() && event.getEventValue() > 0) {   
      try { 
       byte[] buffer = SP.readBytes(6); 
       String type = new String(buffer); 
       if (type.equals("$GPGGA")){ 
        String line = ""; 
        line = line + type; 
        buffer = SP.readBytes(66); 
        String values = new String(buffer); 
        line = line + values; 
        writer.write(line + "\n"); 
       } 
      } 
      catch (SerialPortException ex) {System.out.println(ex);} 
      catch (IOException ex) {System.out.println(ex);} 
     } 
    } 
} 

сейчас после того, как я проверить, что сообщение правильного типа я только что прочитал 80 байт от данных, что примерно размер сообщения. однако, иногда сообщение не заполнено и там для него короче, чем обычно. это структура сообщения: enter image description here

как вы можете видеть, в конце сообщения s с <CR><FL>. Я хотел бы изменить свой метод, чтобы он читал каждый байт за раз и прекратил чтение, когда он попал в конец сообщения. как я могу поймать <CR><FL> внутри массива байтов?

любая помощь будет оценена. Спасибо.

+0

Какой тип 'SP'? Если это InputStream, вы можете обернуть его в [BufferedReader] (https://docs.oracle.com/javase/7/docs/api/java/io/BufferedReader.html#readLine()) и вызвать readLine? – Fildor

+0

SP - это последовательный порт. этот метод является частью более крупной программы, которая связывается с приемником gps через последовательный порт. Я не могу вызвать readLine, потому что данные передаются из приемника в виде байтов. –

ответ

2

Это зависит от определения «сообщений»: они фиксированной длины или ограничены определенной последовательностью? В вашем текущем коде вы читаете «заголовок» длиной 6 байтов и «сообщение» длиной 66 байт. Тем не менее, похоже, что вы на самом деле не знаете длину априори, а вместо этого сообщение заканчивается новой строкой. Несколько указателей:

  • Вы читаете байты из потока, а затем превращаете их в строку, используя String(byte[]) ctor. В documentation указано, что для вашей платформы используется default charset, что может быть UTF-8, Latin-1 или независимо от регионального значения по умолчанию. Если вы общаетесь с устройством через последовательный порт, это, вероятно, не то, что вы хотите, так как у устройства, вероятно, будет одна конкретная кодировка для сообщений (возможно, ASCII?). Исследуйте эту точку и используйте либо this String ctor, либо, если вы хотите получать уведомления, если вход содержит недоказуемый мусор, CharsetDecoder class.
  • Если сообщения текстовые и с разделителями строк, вы обязательно должны использовать BufferedReader для чтения из потока. Предполагая, что ваш последовательный порт SP является InputStream, вы можете создать BufferedReader над ним, а затем вызвать метод readLine() на устройстве чтения. Читатель будет продолжать запрашивать байты из потока до тех пор, пока не увидит новую строку, а затем вернет вам всю строку в виде строки. Объекты Reader также инкапсулируют Charset, о котором я говорил раньше.
+0

Вы правы, я не знаю априорной длины сообщения, только если сообщение заполнено. ваш второй бюллетень выглядит как правильный путь для меня. плохо попробуйте это позже. Спасибо. –

+0

SP объявлен как «public static SerialPort SP» в начале другого класса.нет никаких дециляций входного потока где угодно. я не совсем понимаю, как создать BufferedReader над ним. @Javier Martin, не могли бы вы привести мне пример? Я думал, может быть, я могу проверить значение байта, '' должно быть 13 и '' равно 10, или наоборот. это сработает? –

+0

@DanyLavrov 'SerialPort', похоже, не javax.comm.SerialPort, не так ли? Можете ли вы рассказать нам, какую библиотеку вы используете? – Fildor

0

Мне удалось решить мою проблему. довольно простое решение:

String tmp = SP.readString(); 
String[] msgs = tmp.split("\r\n"); 

после чтения строки из последовательного порта, я просто разделить его на конце линии.