У меня есть программа C ++, работающая на Intel Edison, которая считывает некоторые данные GPS с последовательного порта и передает их обратно на консоль.
Эта часть работает нормально, но когда строки читаются в консоли, у них есть символы, которых там быть не должно, наприме𠫬é». Я предполагаю, что что-то напутано с кодировкой в консоли Eclipse / G ++, и он считает, что некоторые чтения являются символьными кодами.
Вот некоторый вывод из консоли Eclipse:
$GPVTG,,T,,M,0.041,N,0.075,K,A*24
$GPGGA,225153.00,5206.75433,N,12206.88881,W,1,10,1.03,582.1,M,-15.6,M,,*6F
$GPGSA,A,3,32,02,12,14,24,06,03,19,17,25,,,1.84,1.03,1.53*05
$GPGSV,3,1,11,ŽN
-> 02,51,176,30,03,10,027,17,06,60,088,33,12,68,295,36*79
$GPGSV,3,2,11,14,10,316,30,17,20,072,27,19,45,069,40,24,36,215,35*7E
$GPGSV,3,3,11,25,29,301,28,29,05,254,,32,07,305,33*40
$GPGLL,5206.75433,N,12206.88881,W,225153.00,A,A*78
.53*05
$GPGSV,3,1,11,ŽN
А вот некоторые из выводимых данных, считанные непосредственно с последовательного порта на Edison (cat /dev/ttyMFD1
):
$GPVTG,,T,,M,0.048,N,0.090,K,A*26
$GPGGA,225407.00,5206.75339,N,12206.88816,W,1,10,1.02,584.2,M,-15.6,M,,*6C
$GPGSA,A,3,32,02,12,14,24,06,03,19,17,25,,,1.80,1.02,1.49*0B
$GPGSV,3,1,11,02,52,176,15,03,10,026,20,06,59,086,29,12,69,295,41*76
$GPGSV,3,2,11,14,09,316,29,17,19,072,29,19,44,070,34,24,35,215,32*74
$GPGSV,3,3,11,25,30,301,29,29,06,254,,32,06,304,17*4C
$GPGLL,5206.75339,N,12206.88816,W,225407.00,A,A*7F
$GPRMC,225408.00,A,5206.75337,N,12206.88814,W,0.058,,170616,,,A*6F
Я перепробовал все параметры кодирования, доступные на общей вкладке конфигурации запуска, но все они дали странные результаты, даже китайские символы!
Соответствующий код char array[255];
инициализировать буфер, а затем прочитать последовательные данные в буфер и вывести их в консоль:
while(true){
dev->read(array,255);
std::cout<<"-> "<<array<<std::endl;
}
Учитывая этот блок:
-> 02,51,176,30,03,10,027,17,06,60,088,33,12,68,295,36*79
$GPGSV,3,2,11,14,10,316,30,17,20,072,27,19,45,069,40,24,36,215,35*7E
$GPGSV,3,3,11,25,29,301,28,29,05,254,,32,07,305,33*40
$GPGLL,5206.75433,N,12206.88881,W,225153.00,A,A*78
.53*05
$GPGSV,3,1,11,ŽN
добавив rn для представления двух символов CRLF, которые заканчивают строку данных NMEA, а затем просто посчитав количество символов между мусором, который я получаю
0123456789ABCDEF
0 02,51,176,30,03,
1 10,027,17,06,60,
2 088,33,12,68,295
3 ,36*79rn$GPGSV,3
4 ,2,11,14,10,316,
5 30,17,20,072,27,
6 19,45,069,40,24,
7 36,215,35*7Ern$G
8 PGSV,3,3,11,25,2
9 9,301,28,29,05,2
A 54,,32,07,305,33
B *40rn$GPGLL,5206
C .75433,N,12206.8
D 8881,W,225153.00
E ,A,A*78rn.53*05r
F n$GPGSV,3,1,11,
255 символов
Точно один из них:
dev->read(array,255);
Дешевый взлом это
char array[256];
а потом
dev->read(array,sizeof(array)-1);
array[sizeof(array)-1] = '\0';
Но я думаю, что вам лучше с чем-то вроде этого:
int len = receiveUntil(array,sizeof(array), "\r\n")
if (len >= 0)
{
// checksum and parse
}
discardUntil ("$");
где
receiveUntil
читает входящий поток в array
пока он не найдет конец предложения NMEA, тогда null завершится array
и возвращает количество прочитанных байтов или array
собирается переполниться, и в этом случае он возвращает -1.
discardUntil
выбрасывает все, пока не найдет начальный символ NMEA ‘$’
Бонусные баллы за замену receiveUntil
с функцией сброса array
когда он находит $
так что вы не пропустите ни одного сообщения, которое еще не было повреждено.
Оказывается, это не было проблемой с кодировкой. Я начал понимать, что это было что-то еще, когда я попытался сделать то же самое с NodeJS, и получил тот же результат.
Я забыл, что правильный способ считывания выходных данных с этого модуля GPS состоит в том, чтобы читать символы по одному, пока вы не нажмете терминатор перевода строки в конце строки, и затем работать с ним / войти в консоль.
Итак, мой код стал:
char array[255];
char c[1];
int i = 0;
while(true){
dev->read(c,1);
if(c[0] == '\n'){
i = 0;
std::cout<<"-> "<<array<<std::endl;
char *begin = array;
char *end = begin + sizeof(array);
std::fill(begin, end, 0);
}else{
array[i] = c[0];
++i;
}
}
Который сейчас работает отлично 🙂