QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
qgsnmeaconnection.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsnmeaconnection.cpp - description
3  ---------------------
4  begin : November 30th, 2009
5  copyright : (C) 2009 by Marco Hugentobler
6  email : marco at hugis dot net
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "qgsnmeaconnection.h"
19 #include "qextserialport.h"
20 #include "qgslogger.h"
21 
22 #include <QIODevice>
23 #include <QApplication>
24 #include <QStringList>
25 
26 
27 //from libnmea
28 #include "parse.h"
29 #include "gmath.h"
30 #include "info.h"
31 
32 #define KNOTS_TO_KMH 1.852
33 
35 {
36 }
37 
39 {
40  //connection will be closed by base class
41 }
42 
44 {
45  if ( !mSource )
46  {
47  return;
48  }
49 
50  //print out the data as a test
51  qint64 numBytes = 0;
52  if ( ! mSource->isSequential() ) //necessary because of a bug in QExtSerialPort //SLM - bytesAvailable() works on Windows, so I reversed the logic (added ! ); this is what QIODevice docs say to do; the orig impl of win_qextserialport had an (unsigned int)-1 return on error - it should be (qint64)-1, which was fixed by ?
53  {
54  numBytes = mSource->size();
55  }
56  else
57  {
58  numBytes = mSource->bytesAvailable();
59  }
60 
61  QgsDebugMsg( "numBytes:" + QString::number( numBytes ) );
62 
63  if ( numBytes >= 6 )
64  {
65  if ( mStatus != GPSDataReceived )
66  {
68  }
69 
70  //append new data to the remaining results from last parseData() call
71  mStringBuffer.append( mSource->read( numBytes ) );
74  }
75 }
76 
78 {
79  int endSentenceIndex = 0;
80  int dollarIndex;
81 
82  while (( endSentenceIndex = mStringBuffer.indexOf( "\r\n" ) ) && endSentenceIndex != -1 )
83  {
84  endSentenceIndex = mStringBuffer.indexOf( "\r\n" );
85 
86  dollarIndex = mStringBuffer.indexOf( "$" );
87  if ( endSentenceIndex == -1 )
88  {
89  break;
90  }
91 
92 
93  if ( endSentenceIndex >= dollarIndex )
94  {
95  if ( dollarIndex != -1 )
96  {
97  QString substring = mStringBuffer.mid( dollarIndex, endSentenceIndex );
98  QByteArray ba = substring.toLocal8Bit();
99  if ( substring.startsWith( "$GPGGA" ) )
100  {
101  QgsDebugMsg( substring );
102  processGGASentence( ba.data(), ba.length() );
104  QgsDebugMsg( "*******************GPS data received****************" );
105  }
106  else if ( substring.startsWith( "$GPRMC" ) || substring.startsWith( "$GNRMC" ) )
107  {
108  QgsDebugMsg( substring );
109  processRMCSentence( ba.data(), ba.length() );
111  QgsDebugMsg( "*******************GPS data received****************" );
112  }
113  else if ( substring.startsWith( "$GPGSV" ) )
114  {
115  QgsDebugMsg( substring );
116  processGSVSentence( ba.data(), ba.length() );
118  QgsDebugMsg( "*******************GPS data received****************" );
119  }
120  else if ( substring.startsWith( "$GPVTG" ) )
121  {
122  QgsDebugMsg( substring );
123  processVTGSentence( ba.data(), ba.length() );
125  QgsDebugMsg( "*******************GPS data received****************" );
126  }
127  else if ( substring.startsWith( "$GPGSA" ) )
128  {
129  QgsDebugMsg( substring );
130  processGSASentence( ba.data(), ba.length() );
132  QgsDebugMsg( "*******************GPS data received****************" );
133  }
134  emit nmeaSentenceReceived( substring ); // added to be able to save raw data
135  }
136  }
137  mStringBuffer.remove( 0, endSentenceIndex + 2 );
138  }
139 }
140 
141 void QgsNMEAConnection::processGGASentence( const char* data, int len )
142 {
143  nmeaGPGGA result;
144  if ( nmea_parse_GPGGA( data, len, &result ) )
145  {
146  //update mLastGPSInformation
147  double longitude = result.lon;
148  if ( result.ew == 'W' )
149  {
150  longitude = -longitude;
151  }
152  double latitude = result.lat;
153  if ( result.ns == 'S' )
154  {
155  latitude = -latitude;
156  }
157 
163  }
164 }
165 
166 void QgsNMEAConnection::processRMCSentence( const char* data, int len )
167 {
168  nmeaGPRMC result;
169  if ( nmea_parse_GPRMC( data, len, &result ) )
170  {
171  double longitude = result.lon;
172  if ( result.ew == 'W' )
173  {
174  longitude = -longitude;
175  }
176  double latitude = result.lat;
177  if ( result.ns == 'S' )
178  {
179  latitude = -latitude;
180  }
185  mLastGPSInformation.status = result.status; // A,V
186 
187  //date and time
188  QDate date( result.utc.year + 1900, result.utc.mon + 1, result.utc.day );
189  QTime time( result.utc.hour, result.utc.min, result.utc.sec, result.utc.msec ); // added msec part
190  if ( date.isValid() && time.isValid() )
191  {
195  QgsDebugMsg( "utc time:" );
197  QgsDebugMsg( "local time:" );
199  }
200  }
201 }
202 
203 void QgsNMEAConnection::processGSVSentence( const char* data, int len )
204 {
205  nmeaGPGSV result;
206  if ( nmea_parse_GPGSV( data, len, &result ) )
207  {
208  //clear satellite information when a new series of packs arrives
209  if ( result.pack_index == 1 )
210  {
212  }
213 
214  // for determining when to graph sat info
216 
217  for ( int i = 0; i < NMEA_SATINPACK; ++i )
218  {
219  nmeaSATELLITE currentSatellite = result.sat_data[i];
220  QgsSatelliteInfo satelliteInfo;
221  satelliteInfo.azimuth = currentSatellite.azimuth;
222  satelliteInfo.elevation = currentSatellite.elv;
223  satelliteInfo.id = currentSatellite.id;
224  satelliteInfo.inUse = currentSatellite.in_use; // the GSA processing below does NOT set the sats in use
225  satelliteInfo.signal = currentSatellite.sig;
227  }
228 
229  }
230 }
231 
232 void QgsNMEAConnection::processVTGSentence( const char* data, int len )
233 {
234  nmeaGPVTG result;
235  if ( nmea_parse_GPVTG( data, len, &result ) )
236  {
237  mLastGPSInformation.speed = result.spk;
238  }
239 }
240 
241 void QgsNMEAConnection::processGSASentence( const char* data, int len )
242 {
243  nmeaGPGSA result;
244  if ( nmea_parse_GPGSA( data, len, &result ) )
245  {
247  mLastGPSInformation.hdop = result.HDOP;
248  mLastGPSInformation.pdop = result.PDOP;
249  mLastGPSInformation.vdop = result.VDOP;
252  for ( int i = 0; i < NMEA_MAXSAT; i++ )
253  {
254  mLastGPSInformation.satPrn.append( result.sat_prn[ i ] );
255  }
256  }
257 }
char ns
[N]orth or [S]outh
Definition: sentence.h:92
void nmeaSentenceReceived(const QString &substring)
Information about satellite.
Definition: info.h:70
void clear()
int nmea_parse_GPVTG(const char *buff, int buff_sz, nmeaGPVTG *pack)
QString toString(Qt::DateFormat format) const
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
int azimuth
Azimuth, degrees from true north, 000 to 359.
Definition: info.h:75
char ns
[N]orth or [S]outh
Definition: sentence.h:43
QString & append(QChar ch)
Status mStatus
Connection status.
void processRMCSentence(const char *data, int len)
double nmea_ndeg2degree(double val)
int hour
Hours since midnight - [0,23].
Definition: nmeatime.h:48
int mon
Months since January - [0,11].
Definition: nmeatime.h:46
int id
Satellite PRN number.
Definition: info.h:72
double lon
Longitude in NDEG - [degree][min].
Definition: sentence.h:44
GGA packet information structure (Global Positioning System Fix Data)
Definition: sentence.h:39
double lat
Latitude in NDEG - [degree][min].
Definition: sentence.h:91
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
int year
Years since 1900.
Definition: nmeatime.h:45
double spk
Ground speed, kilometers per hour.
Definition: sentence.h:114
VTG packet information structure (Track made good and ground speed)
Definition: sentence.h:106
int satinuse
Number of satellites in use (not those in view)
Definition: sentence.h:47
QList< QgsSatelliteInfo > satellitesInView
int nmea_parse_GPRMC(const char *buff, int buff_sz, nmeaGPRMC *pack)
void setTime(const QTime &time)
bool isValid() const
double lat
Latitude in NDEG - [degree][min].
Definition: sentence.h:42
int length() const
QString & remove(int position, int n)
void processStringBuffer()
Splits mStringBuffer into sentences and calls libnmea.
double direction
Track angle in degrees True.
Definition: sentence.h:96
virtual bool isSequential() const
QString mStringBuffer
Store data from the device before it is processed.
char ew
[E]ast or [W]est
Definition: sentence.h:45
char status
Status (A = active or V = void)
Definition: sentence.h:90
char ew
[E]ast or [W]est
Definition: sentence.h:94
int elv
Elevation in degrees, 90 maximum.
Definition: info.h:74
QList< int > satPrn
void setTimeSpec(Qt::TimeSpec spec)
void processGSASentence(const char *data, int len)
QString number(int n, int base)
void append(const T &value)
int day
Day of the month - [1,31].
Definition: nmeatime.h:47
double VDOP
Vertical dilution of precision.
Definition: sentence.h:68
virtual qint64 size() const
Abstract base class for connection to a GPS device.
QgsNMEAConnection(QIODevice *dev)
double elv
Antenna altitude above/below mean sea level (geoid)
Definition: sentence.h:49
QgsGPSInformation mLastGPSInformation
Last state of the gps related variables (e.g.
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
bool isValid() const
double speed
Speed over the ground in knots.
Definition: sentence.h:95
void setDate(const QDate &date)
qint64 read(char *data, qint64 maxSize)
int nmea_parse_GPGGA(const char *buff, int buff_sz, nmeaGPGGA *pack)
void processGGASentence(const char *data, int len)
virtual qint64 bytesAvailable() const
char fix_mode
Mode (M = Manual, forced to operate in 2D or 3D; A = Automatic, 3D/2D)
Definition: sentence.h:63
QByteArray toLocal8Bit() const
int nmea_parse_GPGSV(const char *buff, int buff_sz, nmeaGPGSV *pack)
QIODevice * mSource
Data source (e.g.
GSA packet information structure (Satellite status)
Definition: sentence.h:61
void parseData() override
Parse available data source content.
QString mid(int position, int n) const
int pack_index
Message number.
Definition: sentence.h:78
nmeaTIME utc
UTC of position.
Definition: sentence.h:89
int sig
Signal, 00-99 dB.
Definition: info.h:76
void stateChanged(const QgsGPSInformation &info)
void processGSVSentence(const char *data, int len)
void processVTGSentence(const char *data, int len)
double lon
Longitude in NDEG - [degree][min].
Definition: sentence.h:93
#define KNOTS_TO_KMH
char * data()
int pack_count
Total number of messages of this type in this cycle.
Definition: sentence.h:77
int sig
GPS quality indicator (0 = Invalid; 1 = Fix; 2 = Differential, 3 = Sensitive)
Definition: sentence.h:46
GSV packet information structure (Satellites in view)
Definition: sentence.h:75
int sec
Seconds after the minute - [0,59].
Definition: nmeatime.h:50
QDateTime toLocalTime() const
nmeaSATELLITE sat_data[NMEA_SATINPACK]
Definition: sentence.h:80
#define NMEA_SATINPACK
Definition: info.h:44
#define NMEA_MAXSAT
Definition: info.h:43
int msec
Thousandths part of second - [0,999].
Definition: nmeatime.h:51
int sat_prn[NMEA_MAXSAT]
PRNs of satellites used in position fix (null for unused fields)
Definition: sentence.h:65
int min
Minutes after the hour - [0,59].
Definition: nmeatime.h:49
int in_use
Used in position fix.
Definition: info.h:73
int fix_type
Type, used for navigation (1 = Fix not available; 2 = 2D; 3 = 3D)
Definition: sentence.h:64
double HDOP
Horizontal dilution of precision.
Definition: sentence.h:67
RMC packet information structure (Recommended Minimum sentence C)
Definition: sentence.h:87
double PDOP
Dilution of precision.
Definition: sentence.h:66
int nmea_parse_GPGSA(const char *buff, int buff_sz, nmeaGPGSA *pack)