|
QGIS API Documentation
master-3f58142
|
00001 /*************************************************************************** 00002 qgsnmeaconnection.cpp - description 00003 --------------------- 00004 begin : November 30th, 2009 00005 copyright : (C) 2009 by Marco Hugentobler 00006 email : marco at hugis dot net 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * * 00011 * This program is free software; you can redistribute it and/or modify * 00012 * it under the terms of the GNU General Public License as published by * 00013 * the Free Software Foundation; either version 2 of the License, or * 00014 * (at your option) any later version. * 00015 * * 00016 ***************************************************************************/ 00017 00018 #include "qgsnmeaconnection.h" 00019 #include "qextserialport.h" 00020 #include "qgslogger.h" 00021 00022 #include <QIODevice> 00023 #include <QApplication> 00024 #include <QStringList> 00025 00026 00027 //from libnmea 00028 #include "parse.h" 00029 #include "gmath.h" 00030 #include "info.h" 00031 00032 #define KNOTS_TO_KMH 1.852 00033 00034 QgsNMEAConnection::QgsNMEAConnection( QIODevice* dev ): QgsGPSConnection( dev ) 00035 { 00036 } 00037 00038 QgsNMEAConnection::~QgsNMEAConnection() 00039 { 00040 //connection will be closed by base class 00041 } 00042 00043 void QgsNMEAConnection::parseData() 00044 { 00045 if ( !mSource ) 00046 { 00047 return; 00048 } 00049 00050 //print out the data as a test 00051 qint64 numBytes = 0; 00052 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 ? 00053 { 00054 numBytes = mSource->size(); 00055 } 00056 else 00057 { 00058 numBytes = mSource->bytesAvailable(); 00059 } 00060 00061 QgsDebugMsg( "numBytes:" + QString::number( numBytes ) ); 00062 00063 if ( numBytes >= 6 ) 00064 { 00065 if ( mStatus != GPSDataReceived ) 00066 { 00067 mStatus = DataReceived; 00068 } 00069 00070 //append new data to the remaining results from last parseData() call 00071 mStringBuffer.append( mSource->read( numBytes ) ); 00072 processStringBuffer(); 00073 emit stateChanged( mLastGPSInformation ); 00074 } 00075 } 00076 00077 void QgsNMEAConnection::processStringBuffer() 00078 { 00079 int endSentenceIndex = 0; 00080 int dollarIndex; 00081 00082 while (( endSentenceIndex = mStringBuffer.indexOf( "\r\n" ) ) && endSentenceIndex != -1 ) 00083 { 00084 endSentenceIndex = mStringBuffer.indexOf( "\r\n" ); 00085 00086 dollarIndex = mStringBuffer.indexOf( "$" ); 00087 if ( endSentenceIndex == -1 ) 00088 { 00089 break; 00090 } 00091 00092 00093 if ( endSentenceIndex >= dollarIndex ) 00094 { 00095 if ( dollarIndex != -1 ) 00096 { 00097 QString substring = mStringBuffer.mid( dollarIndex, endSentenceIndex ); 00098 QByteArray ba = substring.toLocal8Bit(); 00099 if ( substring.startsWith( "$GPGGA" ) ) 00100 { 00101 QgsDebugMsg( substring ); 00102 processGGASentence( ba.data(), ba.length() ); 00103 mStatus = GPSDataReceived; 00104 QgsDebugMsg( "*******************GPS data received****************" ); 00105 } 00106 else if ( substring.startsWith( "$GPRMC" ) ) 00107 { 00108 QgsDebugMsg( substring ); 00109 processRMCSentence( ba.data(), ba.length() ); 00110 mStatus = GPSDataReceived; 00111 QgsDebugMsg( "*******************GPS data received****************" ); 00112 } 00113 else if ( substring.startsWith( "$GPGSV" ) ) 00114 { 00115 QgsDebugMsg( substring ); 00116 processGSVSentence( ba.data(), ba.length() ); 00117 mStatus = GPSDataReceived; 00118 QgsDebugMsg( "*******************GPS data received****************" ); 00119 } 00120 else if ( substring.startsWith( "$GPVTG" ) ) 00121 { 00122 QgsDebugMsg( substring ); 00123 processVTGSentence( ba.data(), ba.length() ); 00124 mStatus = GPSDataReceived; 00125 QgsDebugMsg( "*******************GPS data received****************" ); 00126 } 00127 else if ( substring.startsWith( "$GPGSA" ) ) 00128 { 00129 QgsDebugMsg( substring ); 00130 processGSASentence( ba.data(), ba.length() ); 00131 mStatus = GPSDataReceived; 00132 QgsDebugMsg( "*******************GPS data received****************" ); 00133 } 00134 emit nmeaSentenceReceived( substring ); // added to be able to save raw data 00135 } 00136 } 00137 mStringBuffer.remove( 0, endSentenceIndex + 2 ); 00138 } 00139 } 00140 00141 void QgsNMEAConnection::processGGASentence( const char* data, int len ) 00142 { 00143 nmeaGPGGA result; 00144 if ( nmea_parse_GPGGA( data, len, &result ) ) 00145 { 00146 //update mLastGPSInformation 00147 double longitude = result.lon; 00148 if ( result.ew == 'W' ) 00149 { 00150 longitude = -longitude; 00151 } 00152 double latitude = result.lat; 00153 if ( result.ns == 'S' ) 00154 { 00155 latitude = -latitude; 00156 } 00157 00158 mLastGPSInformation.longitude = nmea_ndeg2degree( longitude ); 00159 mLastGPSInformation.latitude = nmea_ndeg2degree( latitude ); 00160 mLastGPSInformation.elevation = result.elv; 00161 mLastGPSInformation.quality = result.sig; 00162 mLastGPSInformation.satellitesUsed = result.satinuse; 00163 } 00164 } 00165 00166 void QgsNMEAConnection::processRMCSentence( const char* data, int len ) 00167 { 00168 nmeaGPRMC result; 00169 if ( nmea_parse_GPRMC( data, len, &result ) ) 00170 { 00171 double longitude = result.lon; 00172 if ( result.ew == 'W' ) 00173 { 00174 longitude = -longitude; 00175 } 00176 double latitude = result.lat; 00177 if ( result.ns == 'S' ) 00178 { 00179 latitude = -latitude; 00180 } 00181 mLastGPSInformation.longitude = nmea_ndeg2degree( longitude ); 00182 mLastGPSInformation.latitude = nmea_ndeg2degree( latitude ); 00183 mLastGPSInformation.speed = KNOTS_TO_KMH * result.speed; 00184 mLastGPSInformation.direction = result.direction; 00185 mLastGPSInformation.status = result.status; // A,V 00186 00187 //date and time 00188 QDate date( result.utc.year + 1900, result.utc.mon + 1, result.utc.day ); 00189 QTime time( result.utc.hour, result.utc.min, result.utc.sec, result.utc.msec ); // added msec part 00190 if ( date.isValid() && time.isValid() ) 00191 { 00192 mLastGPSInformation.utcDateTime.setTimeSpec( Qt::UTC ); 00193 mLastGPSInformation.utcDateTime.setDate( date ); 00194 mLastGPSInformation.utcDateTime.setTime( time ); 00195 QgsDebugMsg( "utc time:" ); 00196 QgsDebugMsg( mLastGPSInformation.utcDateTime.toString() ); 00197 QgsDebugMsg( "local time:" ); 00198 QgsDebugMsg( mLastGPSInformation.utcDateTime.toLocalTime().toString() ); 00199 } 00200 } 00201 } 00202 00203 void QgsNMEAConnection::processGSVSentence( const char* data, int len ) 00204 { 00205 nmeaGPGSV result; 00206 if ( nmea_parse_GPGSV( data, len, &result ) ) 00207 { 00208 //clear satellite informations when a new series of packs arrives 00209 if ( result.pack_index == 1 ) 00210 { 00211 mLastGPSInformation.satellitesInView.clear(); 00212 } 00213 00214 // for determining when to graph sat info 00215 mLastGPSInformation.satInfoComplete = ( result.pack_index == result.pack_count ); 00216 00217 for ( int i = 0; i < NMEA_SATINPACK; ++i ) 00218 { 00219 nmeaSATELLITE currentSatellite = result.sat_data[i]; 00220 QgsSatelliteInfo satelliteInfo; 00221 satelliteInfo.azimuth = currentSatellite.azimuth; 00222 satelliteInfo.elevation = currentSatellite.elv; 00223 satelliteInfo.id = currentSatellite.id; 00224 satelliteInfo.inUse = currentSatellite.in_use; // the GSA processing below does NOT set the sats in use 00225 satelliteInfo.signal = currentSatellite.sig; 00226 mLastGPSInformation.satellitesInView.append( satelliteInfo ); 00227 } 00228 00229 } 00230 } 00231 00232 void QgsNMEAConnection::processVTGSentence( const char* data, int len ) 00233 { 00234 nmeaGPVTG result; 00235 if ( nmea_parse_GPVTG( data, len, &result ) ) 00236 { 00237 mLastGPSInformation.speed = result.spk; 00238 } 00239 } 00240 00241 void QgsNMEAConnection::processGSASentence( const char* data, int len ) 00242 { 00243 nmeaGPGSA result; 00244 if ( nmea_parse_GPGSA( data, len, &result ) ) 00245 { 00246 mLastGPSInformation.satPrn.clear(); 00247 mLastGPSInformation.hdop = result.HDOP; 00248 mLastGPSInformation.pdop = result.PDOP; 00249 mLastGPSInformation.vdop = result.VDOP; 00250 mLastGPSInformation.fixMode = result.fix_mode; 00251 mLastGPSInformation.fixType = result.fix_type; 00252 for ( int i = 0; i < NMEA_MAXSAT; i++ ) 00253 { 00254 mLastGPSInformation.satPrn.append( result.sat_prn[ i ] ); 00255 } 00256 } 00257 }