Reading GPS data from virtual serial port on a Windows system
Dear forum,
I have the following problem: I try to read GPS data (a so called nmea-string)from a GPS-mouse via a virtual serial port into my application and to show this data in a QPlainTextEdit-widget. I do this using the following very simple function (connection to the serial port is allready opened):
Code:
void DialogPreferences::readData()
{
QByteArray rawData
= serial
->readAll
();
// read data from serial port ui->plainTextEdit->insertPlainText(rawData) // show data in QPlainTextEdit
qDebug() << rawData; // show same data in the console
}
The serial port is connected to the QPlainTextEdit widget via
Code:
connect(serial, SIGNAL(readyRead()), this, SLOT(readData()));
Output in the QPlainTextEdit-Widget:
$GPGGA,141559.000,5858.4209,N,00956.6503,E,2,8,1.7 5,29.4,M,41.2,M,0000,0000*64
$GPGLL,5858.4209,N,00956.6503,E,141559.000,A,D*54
$GPGSA,A,3,14,08,32,03,11,04,19,01,,,,,1.97,1.75,0 .91*04
$GPRMC,141559.000,A,5858.4209,N,00956.6503,E,0.36, 235.13,071015,,,D*62
This works as it should. But if I try to display the same data with qDebug() in the console, I get the following result:
"GPGGA,141559.000"
",5858.4209,N,0095"
"6.6503,E,2,8,1"
".75,29.4,M,41.2"
",M,0000,0000*64"
"\r\n$GPGLL,5858.42"
"09,N,00956.6503,"
"E,141559.000,"
"A,D*54\r\n$GPGSA,"
"A,3,14,08,32,03,"
"11,04,19,01,,,"
",,1.97,1.75,0.9"
"1*04\r\n$GPRMC,14"
"1559.000,A,5858"
".4209,N,00956."
"6503,E,0.36,235"
".13,071015,,,D*"
"62\r\n$GPVTG,235."
In the raw data the lines are seperated by a combination of \r\n. But obvisouly the array is splitted on, for me, arbitrary places, and I have no idea why! I need the line exact as shown in the QPlainText widget for further analysis, any suggenstions, how I can reach that?
Thanks in advance for your help!
vittorio
Re: Reading GPS data from virtual serial port on a Windows system
Oh it's really just that qDebug() starts a new line every time you call it, and the data does't arrive exactly in lines from the serial port. Collect everything in one string and split on \r\n and you should be fine.
Re: Reading GPS data from virtual serial port on a Windows system
To further explain - QPlainTextWidget::insertPlainText() updates the cursor position each time it is called. If you don't change the cursor position between calls, this has the effect of appending each new piece of text onto the end of whatever is already there. So your plain text widget has the appearance of showing a single string, when in fact it is the accumulation of each of the strings you see in the qDebug() output. The qDebug() output is showing you the sequence of what is actually being received by the serial port in each of the calls to the readData() slot.
As Cruz said, create a QString or QByteArray member variable and append onto it each time readData() is called. When you are done reading, split the string on the CRLF delimiters.
Re: Reading GPS data from virtual serial port on a Windows system
Quote:
Originally Posted by
d_stranz
Hi, thanks for your explanation! I think, I understand what happens, but another thing: the data I'm dealing with is a permanent stream coming in via the serial port. Simple said, each line represents a geographic coordinate, and for a moving system, this coordinates must be updated as soon as new data comes in. The strings are build following the nmea rules. The data I need are on a defined postition within this string. THis all is no problem, but I don't know how to create the correct strings in runtime, do you have any idea?
Re: Reading GPS data from virtual serial port on a Windows system
Quote:
I don't know how to create the correct strings
What strings do you need to create?
Re: Reading GPS data from virtual serial port on a Windows system
In that case you need to collect multiple segments of a line in a QByteArray and check every byte. When you receive a "\r\n", you have a complete line. Pass it on to your program for example by emiting a signal, and make sure to keep the rest of the bytes as you may have read the beginning of the next line after the \r\n.
Roughly like so:
Code:
void DialogPreferences::readData()
{
QByteArray rawData
= serial
->readAll
();
// read data from serial port
for (int i=0; i < rawData.size(); i++)
{
line << rawData[i];
if (line.size() >= 2 && line[line.size()-2] == '\r' && line[line.size()-1] == '\n')
{
emit(line);
line.clear();
}
}
}
But this is only quickly hacked pseudo code. Please debug it and complete it yourself.