23#include <QApplication>
25#include <QRegularExpression>
29#include "moc_qgsnmeaconnection.cpp"
31using namespace Qt::StringLiterals;
41#define KNOTS_TO_KMH 1.852
62 numBytes =
mSource->bytesAvailable();
92 int endSentenceIndex = 0;
95 while ( ( endSentenceIndex =
mStringBuffer.indexOf(
"\r\n"_L1 ) ) && endSentenceIndex != -1 )
100 if ( endSentenceIndex == -1 )
105 if ( endSentenceIndex >= dollarIndex )
107 if ( dollarIndex != -1 )
109 const QString substring =
mStringBuffer.mid( dollarIndex, endSentenceIndex );
110 QByteArray ba = substring.toLocal8Bit();
111 const thread_local QRegularExpression rxSentence( u
"^\\$([A-Z]{2})([A-Z]{3})"_s );
112 const QRegularExpressionMatch sentenceMatch = rxSentence.match( substring );
113 const QString sentenceId = sentenceMatch.captured( 2 );
114 if ( sentenceId ==
"GGA"_L1 )
120 QgsDebugMsgLevel( u
"*******************GPS data received****************"_s, 2 );
122 else if ( sentenceId ==
"RMC"_L1 )
128 QgsDebugMsgLevel( u
"*******************GPS data received****************"_s, 2 );
130 else if ( sentenceId ==
"GSV"_L1 )
136 QgsDebugMsgLevel( u
"*******************GPS data received****************"_s, 2 );
138 else if ( sentenceId ==
"VTG"_L1 )
144 QgsDebugMsgLevel( u
"*******************GPS data received****************"_s, 2 );
146 else if ( sentenceId ==
"GSA"_L1 )
151 QgsDebugMsgLevel( u
"*******************GPS data received****************"_s, 2 );
153 else if ( sentenceId ==
"GST"_L1 )
159 QgsDebugMsgLevel( u
"*******************GPS data received****************"_s, 2 );
161 else if ( sentenceId ==
"HDT"_L1 )
167 QgsDebugMsgLevel( u
"*******************GPS data received****************"_s, 2 );
169 else if ( sentenceId ==
"HDG"_L1 )
175 QgsDebugMsgLevel( u
"*******************GPS data received****************"_s, 2 );
197 if ( nmea_parse_GPGGA( data, len, &result ) )
200 double longitude = result.lon;
201 if ( result.ew ==
'W' )
203 longitude = -longitude;
205 double latitude = result.lat;
206 if ( result.ns ==
'S' )
208 latitude = -latitude;
216 const QTime time( result.utc.hour, result.utc.min, result.utc.sec, result.utc.msec );
217 if ( time.isValid() )
230 if ( result.sig >= 0 && result.sig <= 8 )
247 if ( nmea_parse_GPGST( data, len, &result ) )
250 const double sig_lat = result.sig_lat;
251 const double sig_lon = result.sig_lon;
252 const double sig_alt = result.sig_alt;
259 mLastGPSInformation.hvacc = sqrt( ( pow( sig_lat, 2 ) + pow( sig_lon, 2 ) + pow( sig_alt, 2 ) ) / 3.0 );
266 if ( nmea_parse_GPHDT( data, len, &result ) )
275 if ( nmea_parse_HCHDG( data, len, &result ) )
278 if ( result.ew_variation ==
'E' )
288 if ( nmea_parse_GPRMC( data, len, &result ) )
290 double longitude = result.lon;
291 if ( result.ew ==
'W' )
293 longitude = -longitude;
295 double latitude = result.lat;
296 if ( result.ns ==
'S' )
298 latitude = -latitude;
303 if ( !std::isnan( result.direction ) )
307 const QDate date( result.utc.year + 1900, result.utc.mon + 1, result.utc.day );
308 const QTime time( result.utc.hour, result.utc.min, result.utc.sec, result.utc.msec );
309 if ( date.isValid() && time.isValid() )
325 if ( result.status ==
'A' || result.status ==
'D' )
327 if ( result.mode ==
'A' )
331 else if ( result.mode ==
'D' )
335 else if ( result.mode ==
'P' )
339 else if ( result.mode ==
'R' )
343 else if ( result.mode ==
'F' )
347 else if ( result.mode ==
'E' )
351 else if ( result.mode ==
'M' )
355 else if ( result.mode ==
'S' )
364 else if ( result.status ==
'V' )
380 if ( result.navstatus ==
'S' )
384 else if ( result.navstatus ==
'C' )
388 else if ( result.navstatus ==
'U' )
401 if ( nmea_parse_GPGSV( data, len, &result ) )
404 for (
int i = 0; i < NMEA_SATINPACK; ++i )
406 const nmeaSATELLITE currentSatellite = result.sat_data[i];
408 satelliteInfo.
azimuth = currentSatellite.azimuth;
409 satelliteInfo.
elevation = currentSatellite.elv;
410 satelliteInfo.
id = currentSatellite.id;
411 satelliteInfo.
inUse =
false;
416 satelliteInfo.
inUse =
true;
419 satelliteInfo.
signal = currentSatellite.sig;
420 satelliteInfo.
satType = result.talkerId[1];
422 if ( result.talkerId[0] ==
'G' )
424 if ( result.talkerId[1] ==
'P' )
428 else if ( result.talkerId[1] ==
'L' )
432 else if ( result.talkerId[1] ==
'A' )
436 else if ( result.talkerId[1] ==
'B' )
440 else if ( result.talkerId[1] ==
'Q' )
446 if ( satelliteInfo.
satType ==
'P' && satelliteInfo.
id > 32 )
450 satelliteInfo.
id = currentSatellite.id + 87;
453 bool idAlreadyPresent =
false;
459 if ( existingSatInView.
id == currentSatellite.id )
461 idAlreadyPresent =
true;
463 if ( existingSatInView.
signal == 0 )
465 existingSatInView.
signal = currentSatellite.sig;
467 else if ( currentSatellite.sig != 0 )
469 existingSatInView.
signal = ( existingSatInView.
signal + currentSatellite.sig ) / 2;
476 if ( !idAlreadyPresent && currentSatellite.azimuth > 0 && currentSatellite.elv > 0 )
487 if ( nmea_parse_GPVTG( data, len, &result ) )
490 if ( !std::isnan( result.dir ) )
506 if ( nmea_parse_GPGSA( data, len, &result ) )
516 bool mixedConstellation =
false;
517 for (
int i = 0; i < NMEA_MAXSAT; i++ )
519 if ( result.sat_prn[i] > 0 )
525 if ( ( result.talkerId[0] ==
'G' && result.talkerId[1] ==
'L' ) || result.sat_prn[i] > 64 )
527 else if ( result.sat_prn[i] >= 1 && result.sat_prn[i] <= 32 )
529 else if ( result.sat_prn[i] > 32 && result.sat_prn[i] <= 64 )
533 if ( result.sat_prn[i] > 0 )
537 mixedConstellation =
true;
541 commonConstellation = constellation;
546 if ( mixedConstellation )
549 switch ( result.fix_type )
GnssConstellation
GNSS constellation.
@ Gps
Global Positioning System (GPS).
@ Glonass
Global Navigation Satellite System (GLONASS).
@ Unknown
Unknown/other system.
@ Qzss
Quasi Zenith Satellite System (QZSS).
GpsQualityIndicator
GPS signal quality indicator.
@ RTK
Real-time-kynematic.
@ Simulation
Simulation mode.
@ FloatRTK
Float real-time-kynematic.
@ Manual
Manual input mode.
@ NotValid
Navigation status not valid.
QgsGpsInformation mLastGPSInformation
Last state of the gps related variables (e.g. position, time, ...).
void nmeaSentenceReceived(const QString &substring)
Emitted whenever the GPS device receives a raw NMEA sentence.
std::unique_ptr< QIODevice > mSource
Data source (e.g. serial device, socket, file,...).
QgsGpsConnection(QIODevice *dev)
Constructor.
Status mStatus
Connection status.
void stateChanged(const QgsGpsInformation &info)
Emitted whenever the GPS state is changed.
void processVtgSentence(const char *data, int len)
process VTG sentence
void processRmcSentence(const char *data, int len)
process RMC sentence
void parseData() override
Parse available data source content.
void processHchdgSentence(const char *data, int len)
process HCHDG sentence
void processGgaSentence(const char *data, int len)
process GGA sentence
void processGsvSentence(const char *data, int len)
process GSV sentence
void processGstSentence(const char *data, int len)
process GST sentence
void processHdtSentence(const char *data, int len)
process HDT sentence
void processGsaSentence(const char *data, int len)
process GSA sentence
QString mStringBuffer
Store data from the device before it is processed.
QgsNmeaConnection(QIODevice *device)
Constructs a QgsNmeaConnection with given device.
void processStringBuffer()
Splits mStringBuffer into sentences and calls libnmea.
Encapsulates information relating to a GPS satellite.
double elevation
Elevation of the satellite, in degrees.
bool inUse
true if satellite was used in obtaining the position fix.
int id
Contains the satellite identifier number.
double azimuth
The azimuth of the satellite to true north, in degrees.
QChar satType
satType value from NMEA message $GxGSV, where x: P = GPS; S = SBAS (GPSid> 32 then SBasid = GPSid + 8...
#define QgsDebugMsgLevel(str, level)