20#include "moc_qgsnmeaconnection.cpp" 
   24#include <QApplication> 
   26#include <QRegularExpression> 
   37#define KNOTS_TO_KMH 1.852 
   53  if ( ! 
mSource->isSequential() ) 
 
   59    numBytes = 
mSource->bytesAvailable();
 
   66    QgsDebugMsgLevel( QStringLiteral( 
"Got %1 NMEA bytes" ).arg( numBytes ), 3 );
 
   70      QgsDebugMsgLevel( QStringLiteral( 
"Setting device status to DataReceived" ), 3 );
 
 
   89  int endSentenceIndex = 0;
 
   92  while ( ( endSentenceIndex = 
mStringBuffer.indexOf( QLatin1String( 
"\r\n" ) ) ) && endSentenceIndex != -1 )
 
   94    endSentenceIndex = 
mStringBuffer.indexOf( QLatin1String( 
"\r\n" ) );
 
   97    if ( endSentenceIndex == -1 )
 
  102    if ( endSentenceIndex >= dollarIndex )
 
  104      if ( dollarIndex != -1 )
 
  106        const QString substring = 
mStringBuffer.mid( dollarIndex, endSentenceIndex );
 
  107        QByteArray ba = substring.toLocal8Bit();
 
  108        const thread_local QRegularExpression rxSentence( QStringLiteral( 
"^\\$([A-Z]{2})([A-Z]{3})" ) );
 
  109        const QRegularExpressionMatch sentenceMatch = rxSentence.match( substring );
 
  110        const QString sentenceId = sentenceMatch.captured( 2 );
 
  111        if ( sentenceId == QLatin1String( 
"GGA" ) )
 
  117          QgsDebugMsgLevel( QStringLiteral( 
"*******************GPS data received****************" ), 2 );
 
  119        else if ( sentenceId == QLatin1String( 
"RMC" ) )
 
  125          QgsDebugMsgLevel( QStringLiteral( 
"*******************GPS data received****************" ), 2 );
 
  127        else if ( sentenceId == QLatin1String( 
"GSV" ) )
 
  133          QgsDebugMsgLevel( QStringLiteral( 
"*******************GPS data received****************" ), 2 );
 
  135        else if ( sentenceId == QLatin1String( 
"VTG" ) )
 
  141          QgsDebugMsgLevel( QStringLiteral( 
"*******************GPS data received****************" ), 2 );
 
  143        else if ( sentenceId == QLatin1String( 
"GSA" ) )
 
  148          QgsDebugMsgLevel( QStringLiteral( 
"*******************GPS data received****************" ), 2 );
 
  150        else if ( sentenceId == QLatin1String( 
"GST" ) )
 
  156          QgsDebugMsgLevel( QStringLiteral( 
"*******************GPS data received****************" ), 2 );
 
  158        else if ( sentenceId == QLatin1String( 
"HDT" ) )
 
  164          QgsDebugMsgLevel( QStringLiteral( 
"*******************GPS data received****************" ), 2 );
 
  166        else if ( sentenceId == QLatin1String( 
"HDG" ) )
 
  172          QgsDebugMsgLevel( QStringLiteral( 
"*******************GPS data received****************" ), 2 );
 
  177          QgsDebugMsgLevel( QStringLiteral( 
"unknown nmea sentence: %1" ).arg( substring ), 2 );
 
 
  194  if ( nmea_parse_GPGGA( data, len, &result ) )
 
  197    double longitude = result.lon;
 
  198    if ( result.ew == 
'W' )
 
  200      longitude = -longitude;
 
  202    double latitude = result.lat;
 
  203    if ( result.ns == 
'S' )
 
  205      latitude = -latitude;
 
  213    const QTime time( result.utc.hour, result.utc.min, result.utc.sec, result.utc.msec );
 
  214    if ( time.isValid() )
 
  227    if ( result.sig >= 0 && result.sig <= 8 )
 
 
  243  if ( nmea_parse_GPGST( data, len, &result ) )
 
  246    const double sig_lat = result.sig_lat;
 
  247    const double sig_lon = result.sig_lon;
 
  248    const double sig_alt = result.sig_alt;
 
 
  262  if ( nmea_parse_GPHDT( data, len, &result ) )
 
 
  271  if ( nmea_parse_HCHDG( data, len, &result ) )
 
  274    if ( result.ew_variation == 
'E' )
 
 
  284  if ( nmea_parse_GPRMC( data, len, &result ) )
 
  286    double longitude = result.lon;
 
  287    if ( result.ew == 
'W' )
 
  289      longitude = -longitude;
 
  291    double latitude = result.lat;
 
  292    if ( result.ns == 
'S' )
 
  294      latitude = -latitude;
 
  299    if ( !std::isnan( result.direction ) )
 
  303    const QDate date( result.utc.year + 1900, result.utc.mon + 1, result.utc.day );
 
  304    const QTime time( result.utc.hour, result.utc.min, result.utc.sec, result.utc.msec );
 
  305    if ( date.isValid() && time.isValid() )
 
  320    if ( result.status == 
'A' || result.status == 
'D' )
 
  322      if ( result.mode == 
'A' )
 
  327      else if ( result.mode == 
'D' )
 
  332      else if ( result.mode == 
'P' )
 
  337      else if ( result.mode == 
'R' )
 
  342      else if ( result.mode == 
'F' )
 
  347      else if ( result.mode == 
'E' )
 
  352      else if ( result.mode == 
'M' )
 
  357      else if ( result.mode == 
'S' )
 
  368    else if ( result.status == 
'V' )
 
  376  if ( result.navstatus == 
'S' )
 
  380  else if ( result.navstatus == 
'C' )
 
  384  else if ( result.navstatus == 
'U' )
 
 
  397  if ( nmea_parse_GPGSV( data, len, &result ) )
 
  400    for ( 
int i = 0; i < NMEA_SATINPACK; ++i )
 
  402      const nmeaSATELLITE currentSatellite = result.sat_data[i];
 
  404      satelliteInfo.
azimuth = currentSatellite.azimuth;
 
  405      satelliteInfo.
elevation = currentSatellite.elv;
 
  406      satelliteInfo.
id = currentSatellite.id;
 
  407      satelliteInfo.
inUse = 
false;
 
  412          satelliteInfo.
inUse = 
true;
 
  415      satelliteInfo.
signal = currentSatellite.sig;
 
  416      satelliteInfo.
satType = result.talkerId[1];
 
  418      if ( result.talkerId[0] == 
'G' )
 
  420        if ( result.talkerId[1] == 
'P' )
 
  424        else if ( result.talkerId[1] == 
'L' )
 
  428        else if ( result.talkerId[1] == 
'A' )
 
  432        else if ( result.talkerId[1] == 
'B' )
 
  436        else if ( result.talkerId[1] == 
'Q' )
 
  442      if ( satelliteInfo.
satType == 
'P' && satelliteInfo.
id > 32 )
 
  446        satelliteInfo.
id = currentSatellite.id + 87;
 
  449      bool idAlreadyPresent = 
false;
 
  455          if ( existingSatInView.
id == currentSatellite.id )
 
  457            idAlreadyPresent = 
true;
 
  459            if ( existingSatInView.
signal == 0 )
 
  461              existingSatInView.
signal = currentSatellite.sig;
 
  463            else if ( currentSatellite.sig != 0 )
 
  465              existingSatInView.
signal = ( existingSatInView.
signal + currentSatellite.sig ) / 2;
 
  472      if ( !idAlreadyPresent && currentSatellite.azimuth > 0 && currentSatellite.elv > 0 )
 
 
  484  if ( nmea_parse_GPVTG( data, len, &result ) )
 
  487    if ( !std::isnan( result.dir ) )
 
 
  503  if ( nmea_parse_GPGSA( data, len, &result ) )
 
  513    bool mixedConstellation = 
false;
 
  514    for ( 
int i = 0; i < NMEA_MAXSAT; i++ )
 
  516      if ( result.sat_prn[ i ] > 0 )
 
  522        if ( ( result.talkerId[0] == 
'G' && result.talkerId[1] == 
'L' ) || result.sat_prn[i] > 64 )
 
  524        else if ( result.sat_prn[i] >= 1 && result.sat_prn[i] <= 32 )
 
  526        else if ( result.sat_prn[i] > 32 && result.sat_prn[i] <= 64 )
 
  530        if ( result.sat_prn[i] > 0 )
 
  532          if ( mixedConstellation
 
  534                    && commonConstellation != constellation ) )
 
  536            mixedConstellation = 
true;
 
  540            commonConstellation = constellation;
 
  545    if ( mixedConstellation )
 
  548    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 connections 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 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)