SkyTEM BMAG / Mbed 2 deprecated BMAGThrRev

Dependencies:   mbed WDT MODSERIAL BME280

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers NMEA.cpp Source File

NMEA.cpp

00001 #include "NMEA.h"
00002 
00003 //! NMEA, default constructor
00004 NMEA::NMEA(){    
00005     
00006     currentGGAString.resize(128);
00007     currentGPRMCString.resize(128);
00008     currentUTCFromGPRMC.resize(20);
00009     currentDATEFromGPRMC.resize(10);
00010     currentLongitude.resize(15);
00011     currentLatitude.resize(15);
00012     
00013     currentLongitude = "NaN";
00014     currentLatitude = "NaN";
00015     
00016     chkSumGps.resize(2);
00017     
00018     memset(tmpArrDeg,'\0',7);
00019     memset(tmpArrMin, '\0', 7);
00020     memset(tmpLongitude, '\0', 15);
00021     memset(tmpLatitude, '\0', 15);
00022        
00023     iterationIndex = 0;
00024     longitudeDD = 0.0;
00025     latitudeDD = 0.0;
00026     
00027     cnt_GPRMC = 0;
00028     
00029     north = false;
00030     south = false;
00031     east = false;
00032     west = false;    
00033 };
00034 
00035 //! ValidateData, method taking a text string for NMEA validation
00036 /*! 
00037     ValidateData validates that the NMEA data string isn't corrupted. 
00038     (Verification of crc)
00039        
00040     \param cstStr An NMEA ascii string.
00041     \return boolean return value, true if crc corresponds to own calculated crc, else false.
00042 */
00043 bool NMEA::ValidateData(string cstStr){
00044     
00045     //Temporary variables used locally only
00046     chkSum = 0;
00047     
00048     //If for some reason the index is wrong, and the first character is not 
00049     //the beginning dollar sign of a gps string, return false at once.
00050     if(cstStr[0] != '$'){
00051         return false;
00052     }
00053     
00054     iterationIndex = 0;
00055               
00056     //initializing calculated checksum
00057     chkSumGps = "  ";
00058     
00059     //Calculating checksum to verify string integrity
00060     for(char i = 1; i < cstStr.size(); i++){
00061         //If at end of line for crc check, break
00062         if(cstStr[i] == '*' || cstStr[i] == '\0'){
00063             iterationIndex = i;
00064             break;    
00065         }
00066         //XOR crc calculation
00067         chkSum ^= cstStr[i];
00068             
00069     }
00070     
00071     //Moving the checksum received into chkSumGps
00072     iterationIndex++;
00073     chkSumGps[0] = cstStr[iterationIndex];
00074     iterationIndex++;
00075     chkSumGps[1] = cstStr[iterationIndex];
00076     
00077     GpsCheck = strtol(chkSumGps.c_str(), NULL ,16);
00078 
00079     //Verify received and calculated crc equality
00080     if(GpsCheck == chkSum){
00081         return true;    
00082     }     
00083 
00084     //If unequal crc bytes found return false
00085     return false;    
00086 };
00087 
00088 //! StoreString, method taking a text string as argument for further handling
00089 /*! 
00090     StoreString, replaces current GPRMC or GGA string, with new valid GPRMC or GGA string.
00091     
00092     \param cstStr An NMEA ascii string.
00093 */
00094 void NMEA::StoreString(string cstStr){
00095     static std::string gga = "$GPGGA";
00096     static std::string rmc = "$GPRMC";
00097     
00098     //If received string is a GPGGA string
00099     //copy GPGGA string to currentGGAString
00100     if(cstStr.compare(0, 6, gga) == 0){
00101         
00102         //replace current valid gga string with new valid gga string
00103         currentGGAString.replace(0, 128, cstStr);  
00104                
00105     }
00106 
00107     //If received string is a GPRMC string
00108     //copy GPRMC string to currentGPRMCString
00109     if(cstStr.compare(0, 6, rmc) == 0){
00110         
00111         if(cnt_GPRMC > 1000){
00112             cnt_GPRMC = 0;    
00113         }
00114         cnt_GPRMC +=  1;
00115         
00116         //replace current valid rmc string with new valid rmc string
00117         currentGPRMCString.replace(0, 128, cstStr);
00118              
00119     }                 
00120         
00121 };
00122 
00123 
00124 //! ParseCurrentUTCFromGPRMC, grabs UTC timestamp from current stored GPRMC string.
00125 /*! 
00126     ParseCurrentUTCFromGPRMC, grabs UTC timestamp from current stored GPRMC string.
00127     Stores the UTC timestamp in local text string. 
00128     
00129     Depending on the format it will be saved as:
00130     HH:MM:SS.FFF
00131     In this case FFF are read values fom the string.
00132     eg. 14:10:22.007
00133     
00134     or
00135     
00136     HH:MM:SS.FFF
00137     In this case FFF are predetermined values set to 0.
00138     eg. 14:10:22.000
00139 */
00140 void NMEA::ParseCurrentUTCFromGPRMC(){
00141  
00142      //getting utc from GPRMC string, assigned to tmpStr
00143      getXFromNMEAString(1,currentGPRMCString);
00144      
00145      currentUTCFromGPRMC = "";
00146      currentUTCFromGPRMC.resize(20);
00147      
00148      //if time format == 10 characters
00149      if(strlen(tmpStr.c_str()) > 6){
00150          
00151         //HH
00152         currentUTCFromGPRMC[0] = tmpStr[0];
00153         currentUTCFromGPRMC[1] = tmpStr[1];
00154         currentUTCFromGPRMC[2] = ':';
00155      
00156         //MM
00157         currentUTCFromGPRMC[3] = tmpStr[2];
00158         currentUTCFromGPRMC[4] = tmpStr[3];
00159         currentUTCFromGPRMC[5] = ':';
00160      
00161         //SS
00162         currentUTCFromGPRMC[6] = tmpStr[4];
00163         currentUTCFromGPRMC[7] = tmpStr[5];
00164         currentUTCFromGPRMC[8] = '.';     
00165      
00166         //FFF
00167         currentUTCFromGPRMC[9] = tmpStr[7];
00168         currentUTCFromGPRMC[10] = tmpStr[8];
00169         currentUTCFromGPRMC[11] = tmpStr[9];   
00170      }
00171      
00172      //if time format == 6 characters
00173      if(strlen(tmpStr.c_str()) == 6){
00174          
00175         //HH
00176         currentUTCFromGPRMC[0] = tmpStr[0];
00177         currentUTCFromGPRMC[1] = tmpStr[1];
00178         currentUTCFromGPRMC[2] = ':';
00179      
00180         //MM
00181         currentUTCFromGPRMC[3] = tmpStr[2];
00182         currentUTCFromGPRMC[4] = tmpStr[3];
00183         currentUTCFromGPRMC[5] = ':';
00184      
00185         //SS
00186         currentUTCFromGPRMC[6] = tmpStr[4];
00187         currentUTCFromGPRMC[7] = tmpStr[5];
00188         currentUTCFromGPRMC[8] = '.';     
00189      
00190         //FFF
00191         currentUTCFromGPRMC[9] = '0';
00192         currentUTCFromGPRMC[10] = '0';
00193         currentUTCFromGPRMC[11] = '0';  
00194      }    
00195 
00196 };
00197 
00198 //ParseCurrentAltitudeFromGGA grabs current altitude from GGA string
00199 
00200 void NMEA::ParseCurrentAltitudeFromGGA(void) {
00201     getXFromNMEAString(9,currentGGAString);
00202     if (GGAFixVerification())
00203       currentAltitude= tmpStr;
00204     else  
00205       currentAltitude="NaN";
00206       
00207 }    
00208 
00209 //! ParseCurrentDateFromGPRMC, grabs current date from current GPRMC string.
00210 /*! 
00211     ParseCurrentDateFromGPRMC, grabs current date from current GPRMC string.
00212     Stores the Date in a local text string. 
00213     
00214     will be stored in the format:
00215     YYYY/MM/DD
00216 */
00217 int strtoint(string str, int index) {
00218 char value[3];
00219    value[0]=str[index]; 
00220    value[1]=str[index+1]; 
00221    value[2]=0; 
00222    return atoi(value);
00223 }     
00224 
00225 void NMEA::ParseCurrentDateFromGPRMC(){
00226     
00227     //Getting date from GPRMC string, assigning to tmpStr 
00228     getXFromNMEAString(9,currentGPRMCString);
00229   
00230     currentDATEFromGPRMC = "";
00231     currentDATEFromGPRMC.resize(20);  
00232     char tmpdate[20];
00233     //if date string is the expected length
00234     if(strlen(tmpStr.c_str()) == 6){
00235         int y=strtoint(tmpStr,4);
00236         int m=strtoint(tmpStr,2);
00237         int d=strtoint(tmpStr,0);
00238         struct tm t = { .tm_year=y, .tm_mon=m-1, .tm_mday=d };
00239         t.tm_mday += 1024*7; //rollover compentation
00240         mktime(&t);
00241         strftime (tmpdate,20,"%G/%m/%d",&t);
00242         for (int i=0; i<20; i++) currentDATEFromGPRMC[i]=tmpdate[i];
00243     } 
00244 };
00245 
00246 //! GGAFixVerification, returns gps fix indication.
00247 /*! 
00248     GGAFixVerification verifies gga fix status in current GGA string.
00249     
00250     \return boolean value indicating GGA fix if true, else false.
00251 */
00252 bool  NMEA::GGAFixVerification(){
00253 
00254     //accessing the string after the sixth comma, which is the gga fix column
00255     
00256     char commaCount = 0;
00257     char index = 0;
00258     char stringLength = strlen(currentGGAString.c_str());
00259     
00260     while((commaCount < 7) && (currentGGAString[index] != '\0') && (index < stringLength) ){
00261         if(currentGGAString[index] == ','){
00262             commaCount += 1;    
00263         }
00264         
00265         
00266         //if gga fix is 1 or 2, gga fix is sufficient, return true
00267         if(commaCount == 6){   
00268             if(currentGGAString[index+1] == '1'){
00269                 return true;    
00270             }
00271             
00272             if(currentGGAString[index+1] == '2'){
00273                 return true;    
00274             }
00275             
00276             break;
00277         }
00278         
00279         index += 1;
00280         
00281     }
00282               
00283     return false;
00284 };
00285 
00286 //! ParseCurrentLatitudeFromGPRMC, grabs current latitude from current GPRMC string.
00287 /*! 
00288     Converts the latitude into decimaldegrees and stores the current latitude.
00289 */
00290 void NMEA::ParseCurrentLatitudeFromGPRMC(){
00291     
00292     north = false;
00293     south = false;
00294     
00295     memset(tmpArrDeg,'\0',7);
00296     memset(tmpArrMin, '\0', 7);
00297     memset(tmpLatitude, '\0', 15);
00298     currentLatitude = "";
00299     currentLatitude.resize(20);
00300     
00301     
00302     //Getting Latitude from GPRMC string, assigning to tmpStr 
00303     getXFromNMEAString(3,currentGPRMCString);
00304     
00305     tmpArrDeg[0] = tmpStr[0];
00306     tmpArrDeg[1] = tmpStr[1];
00307     
00308     tmpArrMin[0] = tmpStr[2];
00309     tmpArrMin[1] = tmpStr[3];
00310     tmpArrMin[2] = tmpStr[4];
00311     tmpArrMin[3] = tmpStr[5];
00312     tmpArrMin[4] = tmpStr[6]; 
00313   
00314     //getting N/S
00315     getXFromNMEAString(4,currentGPRMCString);
00316     if(tmpStr[0] == 'N' || tmpStr[0] == 'n'){
00317         north = true;
00318         currentLatitude[0] = '+';        
00319     }
00320     
00321     if(tmpStr[0] == 'S' || tmpStr[0] == 's'){
00322         south = true;
00323         currentLatitude[0] = '-';          
00324     }
00325     
00326     
00327     latitudeDD = ((atof(tmpArrDeg) + (atof(tmpArrMin)/60))); 
00328     
00329     sprintf(tmpLatitude, "%0.6f",latitudeDD);
00330     for(int i = 0; i < strlen(tmpLatitude); i++){
00331         currentLatitude[i+1] = tmpLatitude[i];    
00332     }   
00333 };
00334     
00335 //! ParseCurrentLongitudeFromGPRMC, grabs current longitude from current GPRMC string.
00336 /*! 
00337     Converts the longitude into decimaldegrees and stores the current longitude.
00338 */
00339 void NMEA::ParseCurrentLongitudeFromGPRMC(){
00340     
00341     east = false;
00342     west = false;
00343     
00344     memset(tmpArrDeg,'\0',7);
00345     memset(tmpArrMin, '\0', 7);
00346     memset(tmpLongitude, '\0', 15);
00347     currentLongitude = "";
00348     currentLongitude.resize(20);
00349     
00350            
00351     //Getting Longitude from GPRMC string, assigning to tmpStr 
00352     getXFromNMEAString(5,currentGPRMCString);
00353      
00354     tmpArrDeg[0] = tmpStr[0];
00355     tmpArrDeg[1] = tmpStr[1];
00356     tmpArrDeg[2] = tmpStr[2];
00357     
00358     tmpArrMin[0] = tmpStr[3];
00359     tmpArrMin[1] = tmpStr[4];
00360     tmpArrMin[2] = tmpStr[5];
00361     tmpArrMin[3] = tmpStr[6];
00362     tmpArrMin[4] = tmpStr[7];
00363     tmpArrMin[5] = tmpStr[8];
00364     tmpArrMin[6] = tmpStr[9];
00365       
00366     //getting E/W
00367     getXFromNMEAString(6,currentGPRMCString);
00368     if(tmpStr[0] == 'E' || tmpStr[0] == 'e'){
00369         east = true;
00370         currentLongitude[0] = '+';
00371     }
00372     if(tmpStr[0] == 'W' || tmpStr[0] == 'w'){
00373         west = true;
00374         currentLongitude[0] = '-';       
00375     }     
00376 
00377     longitudeDD = ((atof(tmpArrDeg) + (atof(tmpArrMin)/60)));
00378     
00379     sprintf(tmpLongitude, "%0.6f",longitudeDD);
00380     for(int i = 0; i < strlen(tmpLongitude); i++){
00381         currentLongitude[i+1] = tmpLongitude[i];    
00382     }
00383     
00384 };
00385 
00386 
00387 //! getXFromNMEAString, grabs desired data column from NMEA string, stores it for further manipulation in tmpStr
00388 /*! 
00389     \param desiredCommaCount integer designating which column to store
00390     \param stringToParse string parameter containing the NMEA string.
00391 */
00392 void NMEA::getXFromNMEAString(int desiredCommaCount, string stringToParse){
00393     
00394     //clearing tmpStr
00395     tmpStr = "";
00396     tmpStr.resize(15);
00397     char stringLength = strlen(stringToParse.c_str());
00398     
00399     int commaCnt = 0;
00400     int index = 0;
00401     int idx = 0;    
00402     
00403     while(commaCnt < (desiredCommaCount+1) && (index < stringLength)){
00404         
00405         if(stringToParse[index] == ','){
00406             commaCnt += 1;
00407         }
00408         
00409         if((commaCnt == desiredCommaCount) && (stringToParse[index] != ',')){
00410             tmpStr[idx] = stringToParse[index];
00411             idx += 1;
00412         }
00413         
00414         index += 1;    
00415     }
00416     
00417 };
00418 
00419 //! getCurrentTime, getter method returning current time from gps
00420 /*! 
00421     \return returns current time from gps in format "HH:MM:SS.FFF"
00422 */
00423 string NMEA::getCurrentTime(void){
00424     return this->currentUTCFromGPRMC;    
00425 };