22#include <QApplication>
34#define KNOTS_TO_KMH 1.852
50 if ( !
mSource->isSequential() )
56 numBytes =
mSource->bytesAvailable();
63 QgsDebugMsgLevel( QStringLiteral(
"Got %1 NMEA bytes" ).arg( numBytes ), 3 );
67 QgsDebugMsgLevel( QStringLiteral(
"Setting device status to DataReceived" ), 3 );
86 int endSentenceIndex = 0;
89 while ( ( endSentenceIndex =
mStringBuffer.indexOf( QLatin1String(
"\r\n" ) ) ) && endSentenceIndex != -1 )
91 endSentenceIndex =
mStringBuffer.indexOf( QLatin1String(
"\r\n" ) );
94 if ( endSentenceIndex == -1 )
99 if ( endSentenceIndex >= dollarIndex )
101 if ( dollarIndex != -1 )
103 const QString substring =
mStringBuffer.mid( dollarIndex, endSentenceIndex );
104 QByteArray ba = substring.toLocal8Bit();
105 if ( substring.startsWith( QLatin1String(
"$GPGGA" ) ) || substring.startsWith( QLatin1String(
"$GNGGA" ) ) )
111 QgsDebugMsgLevel( QStringLiteral(
"*******************GPS data received****************" ), 2 );
113 else if ( substring.startsWith( QLatin1String(
"$GPRMC" ) ) || substring.startsWith( QLatin1String(
"$GNRMC" ) ) )
119 QgsDebugMsgLevel( QStringLiteral(
"*******************GPS data received****************" ), 2 );
122 else if ( substring.startsWith( QLatin1String(
"$GPGSV" ) ) || substring.startsWith( QLatin1String(
"$GNGSV" ) ) || substring.startsWith( QLatin1String(
"$GLGSV" ) ) || substring.startsWith( QLatin1String(
"$GAGSV" ) ) || substring.startsWith( QLatin1String(
"$GBGSV" ) ) || substring.startsWith( QLatin1String(
"$GQGSV" ) ) )
128 QgsDebugMsgLevel( QStringLiteral(
"*******************GPS data received****************" ), 2 );
130 else if ( substring.startsWith( QLatin1String(
"$GPVTG" ) ) || substring.startsWith( QLatin1String(
"$GNVTG" ) ) )
136 QgsDebugMsgLevel( QStringLiteral(
"*******************GPS data received****************" ), 2 );
138 else if ( substring.startsWith( QLatin1String(
"$GPGSA" ) ) || substring.startsWith( QLatin1String(
"$GNGSA" ) ) || substring.startsWith( QLatin1String(
"$GLGSA" ) ) )
143 QgsDebugMsgLevel( QStringLiteral(
"*******************GPS data received****************" ), 2 );
145 else if ( substring.startsWith( QLatin1String(
"$GPGST" ) ) || substring.startsWith( QLatin1String(
"$GNGST" ) ) )
151 QgsDebugMsgLevel( QStringLiteral(
"*******************GPS data received****************" ), 2 );
153 else if ( substring.startsWith( QLatin1String(
"$GPHDT" ) ) || substring.startsWith( QLatin1String(
"$GNHDT" ) ) )
159 QgsDebugMsgLevel( QStringLiteral(
"*******************GPS data received****************" ), 2 );
161 else if ( substring.startsWith( QLatin1String(
"$HCHDG" ) ) )
167 QgsDebugMsgLevel( QStringLiteral(
"*******************GPS data received****************" ), 2 );
169 else if ( substring.startsWith( QLatin1String(
"$HCHDT" ) ) )
175 QgsDebugMsgLevel( QStringLiteral(
"*******************GPS data received****************" ), 2 );
180 QgsDebugMsgLevel( QStringLiteral(
"unknown nmea sentence: %1" ).arg( substring ), 2 );
192 if ( nmea_parse_GPGGA( data, len, &result ) )
195 double longitude = result.lon;
196 if ( result.ew ==
'W' )
198 longitude = -longitude;
200 double latitude = result.lat;
201 if ( result.ns ==
'S' )
203 latitude = -latitude;
211 const QTime time( result.utc.hour, result.utc.min, result.utc.sec, result.utc.msec );
212 if ( time.isValid() )
225 if ( result.sig >= 0 && result.sig <= 8 )
241 if ( nmea_parse_GPGST( data, len, &result ) )
244 const double sig_lat = result.sig_lat;
245 const double sig_lon = result.sig_lon;
246 const double sig_alt = result.sig_alt;
260 if ( nmea_parse_GPHDT( data, len, &result ) )
269 if ( nmea_parse_HCHDG( data, len, &result ) )
272 if ( result.ew_variation ==
'E' )
282 if ( nmea_parse_HCHDT( data, len, &result ) )
291 if ( nmea_parse_GPRMC( data, len, &result ) )
293 double longitude = result.lon;
294 if ( result.ew ==
'W' )
296 longitude = -longitude;
298 double latitude = result.lat;
299 if ( result.ns ==
'S' )
301 latitude = -latitude;
306 if ( !std::isnan( result.direction ) )
310 const QDate date( result.utc.year + 1900, result.utc.mon + 1, result.utc.day );
311 const QTime time( result.utc.hour, result.utc.min, result.utc.sec, result.utc.msec );
312 if ( date.isValid() && time.isValid() )
326 if ( result.status ==
'A' )
328 if ( result.mode ==
'A' )
333 else if ( result.mode ==
'D' )
338 else if ( result.mode ==
'P' )
343 else if ( result.mode ==
'R' )
348 else if ( result.mode ==
'F' )
353 else if ( result.mode ==
'E' )
358 else if ( result.mode ==
'M' )
363 else if ( result.mode ==
'S' )
381 if ( result.navstatus ==
'S' )
385 else if ( result.navstatus ==
'C' )
389 else if ( result.navstatus ==
'U' )
402 if ( nmea_parse_GPGSV( data, len, &result ) )
405 for (
int i = 0; i < NMEA_SATINPACK; ++i )
407 const nmeaSATELLITE currentSatellite = result.sat_data[i];
409 satelliteInfo.
azimuth = currentSatellite.azimuth;
410 satelliteInfo.
elevation = currentSatellite.elv;
411 satelliteInfo.
id = currentSatellite.id;
412 satelliteInfo.
inUse =
false;
417 satelliteInfo.
inUse =
true;
420 satelliteInfo.
signal = currentSatellite.sig;
421 satelliteInfo.
satType = result.pack_type;
423 if ( result.pack_type ==
'P' )
427 else if ( result.pack_type ==
'L' )
431 else if ( result.pack_type ==
'A' )
435 else if ( result.pack_type ==
'B' )
439 else if ( result.pack_type ==
'Q' )
444 if ( satelliteInfo.
satType ==
'P' && satelliteInfo.
id > 32 )
448 satelliteInfo.
id = currentSatellite.id + 87;
451 bool idAlreadyPresent =
false;
456 if ( existingSatInView.id == currentSatellite.id )
458 idAlreadyPresent =
true;
464 if ( !idAlreadyPresent && currentSatellite.azimuth > 0 && currentSatellite.elv > 0 )
476 if ( nmea_parse_GPVTG( data, len, &result ) )
479 if ( !std::isnan( result.dir ) )
495 if ( nmea_parse_GPGSA( data, len, &result ) )
505 bool mixedConstellation =
false;
506 for (
int i = 0; i < NMEA_MAXSAT; i++ )
508 if ( result.sat_prn[ i ] > 0 )
514 if ( result.pack_type ==
'L' || result.sat_prn[i] > 64 )
516 else if ( result.sat_prn[i] >= 1 && result.sat_prn[i] <= 32 )
518 else if ( result.sat_prn[i] > 32 && result.sat_prn[i] <= 64 )
522 if ( result.sat_prn[i] > 0 )
524 if ( mixedConstellation
526 && commonConstellation != constellation ) )
528 mixedConstellation =
true;
532 commonConstellation = constellation;
537 if ( mixedConstellation )
540 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.
Abstract base class for connection to a GPS device.
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,...)
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 processHchdtSentence(const char *data, int len)
process HCHDT 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 signal
Signal strength (0-99dB), or -1 if not available.
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)