Как получить правильные данные NMEA с внешнего GPS?
В программе для Android пишу программу, которая работает с GPS. Поскольку не все аппараты имеют встроенный GPS решил дополнить программу возможностью подключения к внешним GPS приемникам через Bluetooth и получать от них данные в формате NMEA. С первой частью задачи справился, ко внешнему приемнику подключаюсь и получаю от него данные. Но данные приходят кусками, которые нужно разбить на корректные строки NMEA данных. А это и есть вторая часть задачи, которая вызвала у меня затруднение, даже не знаю с чего начать.
Как я уже писал, данные приходят кусками разной длины причем всегда разной. И вот из этой кучи нужно состряпать правильные строки, которые начинаются с символа "$" и заканчиваются "\n". Длина строки NMEA не может превышать 80 символов.
Помогите составить логику такого парсера, с этим у меня проблемы :((
Пример входящих кусков:
1 кусок:
N,05049.5692,E,0.06,232.87,091214,,*02\n
$GPGGA,200703.000,6140.6754,N,05049.5695,E,1,07,1.1,131.6,M,6.7,M,,0000*6D\n
$GPGSA,A,3,15,13,26,28,17,18,04,,,,,,1.9,1.1,1.5*3D\n
$GPRMC,200703.000,A,6140.6754,N,05049.5695,E,0.05,199.27,091214,,*0F\n
$GPGGA,200704.000,6140.6755,N,05049.5698,E,1,07,1.1,131.7,M,6.7,M,,0000*67\n
$GPGS
2 кусок:
A,A,3,15,13,26,28,17,18,04,,,,,,1.9,1.1,1.5*3D\n
$GPRMC,200704.000,A,6140.6755,N,05049.5698,E,0.02,81.10,091214,,*3F\n
$GPGGA,200705.000,6140.6755,N,05049.5701,E,1,07,1.1,131.8,M,6.7,M,,0000*68\n
$GPGSA,A,3,15,13,26,28,17,18,04,,,,,,1.9,1.1,1.5*3D\n
$GPRMC,200705.000,A,6140.6755,N,05049.5701,E,0.02,209.70,091214,,*0B\n
3 кусок:
$GP
4 кусок:
GGA,200706.000,6140.6756,N,05049.570
5 кусок:
4,E,1,07,1.1,131.9,M,6.7,M
6 кусок:
,,0000*6C
7 кусок:
,18,04,,,,,,1.9,1.1,1.5*3D\n$
8 кусок:
GPRMC,200706.000,A,6140.6756,N,05049.5704,E,0.02,181.59,091214,,*06\n
Проблема в том, что нельзя терять ни куска информации, а из-за того, что она не всегда приходит целыми строками надо как-то в процессе получения все склеивать и разбивать на правильные строки.
Вот так приходят данные:
byte[] readBuf = (byte[])msg.
String s = new String(readBuf);
Я предполагаю делать так: при каждом вхождении данных проверять, начинаются ли они с $, если да, ищем первое вхождения окончания строки, если находим получаем искомую строку, и таким же образом проверяем оставшиеся данные. Если в конце останется незаконченный кусок, запоминаем его и при следующем вхождении данные добавляем к нему, ну и опять проверяем. Правильно я мыслю?
Денис Афонин: Ну, можно и так; но я бы сделал что-то типа InputStream или Reader, которому мы подсовываем приходящие куски, а читаем оттуда уже готовые строки и проверяем их на наличие $ в начале.
Кстати, когда преобразуете byte[] в String, лучше всегда указывать кодировку явно.