Esempio n. 1
0
extern "C" __declspec(dllexport) int GccReadGps(short &hour, short &min, short &sec, short &msec,                 // from GPRMC
                                                double &latitude, double &longitude,                              // from GPRMC
                                                int &num_sat, double &hdop, double &altitude,                 // from GPGGA
                                                double &geoid_sep, int &max_snr,                                   // from GPGSV
                                                double &speed, double &heading,                        // from GPRMC
												short &day, short &month, short &year)                 // from GPRMC
{
    if(__read_lock) { return 0; }
	
    const int BUF_SIZE = 4096;
    DWORD dwBytesRead;
    char buf[BUF_SIZE+1];
    int return_status = 0;
	FILE *file = NULL;

	if (logRawNmea)
	{
		file = fopen("\\tmp.txt", "a");
		fprintf(file, "File handle status: %d\n", (__hGpsPort != INVALID_HANDLE_VALUE ? 1 : 0));
	}

    // reset output vars
    hour = -1;       min = -1;         sec = -1;
    latitude = -32768.0; longitude = -32768.0;
    num_sat = -1;    hdop = -32768.0;      altitude = -32768.0;
    geoid_sep = -32768.0;     max_snr = -1;
	speed = -1.0;    heading = -1.0;
	day = -1;       month = -1;       year = -1;

    if(__hGpsPort == INVALID_HANDLE_VALUE)
    { 
		if (logRawNmea)
			fclose(file);
		return return_status;
	}

    // read file
    __read_lock = true;
    BOOL status = ReadFile(__hGpsPort,	 // handle of file to read
                           buf,		 // address of buffer that receives data
						   filemode ? 600 : BUF_SIZE,	 // number of bytes to read
                           &dwBytesRead, // address of number of bytes read
                           NULL		 // address of structure for data
                           );
    __read_lock = false;

	if (logRawNmea)
		fprintf(file, "GPS status: %d, read status: %d, bytes read: %d \n", GccGpsStatus(), (status ? 1 : 0), dwBytesRead);

    // clear errors if any
    if(status == false)
    {
        DWORD dwErrors;
        COMSTAT ComStat;
        ClearCommError(__hGpsPort,&dwErrors,&ComStat);
		if (logRawNmea)
			fclose(file);
		return return_status;
    }

    // terminate string
    buf[dwBytesRead] = '\0';

    // nothing read - return
    if(dwBytesRead == 0)
    {
        return_status |= READ_NO_ERRORS;
		if (logRawNmea)
			fclose(file);
		return return_status;
    }

    // has some data
    return_status |= READ_NO_ERRORS;
    return_status |= READ_HAS_DATA;

	if(filemode)
	{
		char* ptr = strstr(buf+1, "$GPGGA");
		if(ptr != NULL)
		{
			SetFilePointer(__hGpsPort, (ptr - buf) - dwBytesRead, NULL, FILE_CURRENT);
			dwBytesRead = ptr - buf;
			*ptr = '\0';
		}
	}

    // too much bytes indicate lack of computing power
    if(dwBytesRead > 600)
	{
		//MessageBeep(0);	//test
		if (logRawNmea)
			fprintf(file, "Warning: Too much Bytes read: %d\n", dwBytesRead);

		if(dwBytesRead == BUF_SIZE)
		{
			PurgeComm(__hGpsPort, PURGE_RXCLEAR);
			MessageBeep(1);	//test
		}
		__save_str = std::string(buf);
		__save_str = __save_str.erase(0, dwBytesRead - 600);	//remove old data (would be overwritten anyway)
	}
	else
	{
		// append to string stored from the last read
		__save_str += std::string(buf);
	}

    // chop into lines
    std::vector<std::string> lines;
    std::vector<std::string> words;

    ChopIntoLines(__save_str, lines);

    // check what to do with the last segment. If it is not complete - store.
    if(lines.size() && !filemode)		//in filemode would store "----- received 7 lines ----" without CRLF!
    {
        std::string &last_line = lines[lines.size()-1];
        if(last_line.size() > 3)
        {
            if(last_line[last_line.size()-3] != '*')
            {
                __save_str = last_line;
                lines.pop_back();
            }
        }
        else
        {
            __save_str = last_line;
            lines.pop_back();
        }
    }

	if (logRawNmea)
		fprintf(file, "------------ received %d lines ------------ \n", lines.size() );

    // parse lines
    for(unsigned int i = 0; i < lines.size(); i++)
    {
		if (logRawNmea)
			fprintf(file, "%s\n", lines[i].c_str());

        // process valid lines only, i.e. the one with correct checksum
        if(IsLineValid(lines[i]))
        {
            ChopIntoCommaSepWords(lines[i], words);
            if(words.size() == 0) { continue; } 

            if(words[0] == "$GPGSV")
            {
                ParseGPGSV(words);

				gpgsv_trust_count = 10;
            }
            else if(words[0] == "$GPGGA")
            {
                ParseGPGGA(words);

                return_status |= READ_HAS_GPGGA;

                //hour     = ___hour;     min       = ___min;       sec = ___sec;
                //latitude = ___latitude; longitude = ___longitude;
                hdop = ___hdop;    altitude = ___altitude;    geoid_sep = ___geoid_sep;
            }
            else if(words[0] == "$GPRMC")
            {
                ParseGPRMC(words);

                return_status |= READ_HAS_GPRMC;

				hour = ___hour;     min = ___min;       sec = ___sec;    msec = ___msec;
				latitude = ___latitude; longitude = ___longitude;
                speed = ___speed; heading = ___heading;
				day = ___day; month = ___month; year = ___year;
            }
        }
		else if (logRawNmea)
		{	fprintf(file, "^invalid line\n"); }
    }
	if(gpgsv_trust_count > 0)
	{
		max_snr = ___max_snr; num_sat  = ___num_sat;	//use last values of SNR and NUM to avoid blinking (for 10s)
		return_status |= READ_HAS_GPGSV;				//(some receivers deliver $GPGSV only every 2s or 5s)
		gpgsv_trust_count--;
	}

	if (logRawNmea)
		fclose(file);

    /*  debug write (if want to dump the read buffer, if line chopping did not work)
    if(dwBytesRead)
    {
        FILE *file = fopen("\\tmp.txt", "a");
        fwrite(buf, sizeof(char), dwBytesRead, file);
        fclose(file);
    }
    */

    return return_status;
}
Esempio n. 2
0
bool NMEA::Parse(char read)
{
	switch(read)
	{
	case '$':		
		//Null the pointers
		ChecksumIn = false;
		Checksum = 0;
		StrChecksum = 0;
		c = 0;
		break;

	default:
		sentence[c++] = read;
		if(ChecksumIn)
		{
			if(!StrChecksum)
				StrChecksum = 16 * ((read >= '0' && read <= '9') ? 
					( read - 48 ) : ( read - 65 + 10 ));
			else
				StrChecksum += ((read >= '0' && read <= '9') ? 
				( read - 48 ) : ( read - 65 + 10 ));
		}
		else if(read != ',')
			Checksum ^= read;
		break;

	case '*':		
		sentence[c++] = read;
		ChecksumIn = true;
		break;

	case '\r':		
		sentence[c++] = '\0';
		break;

	case '\n':
		if(Checksum == StrChecksum)
		{
			//Switch on hash value of NMEA sentance name EX GPGGA = 287(P+G+G+A)
			switch( sentence[1] + sentence[2] + sentence[3] + sentence[4] )
			{
			//TODO: Switch over to ENUMS in future to avoid magic numbers
			case 287:
				ParseGPGGA(sentence);
				break;
			case 299:
				ParseGPGSA(sentence);
				break;
			case 320:
				ParseGPGSV(sentence);
				break;
			case 306:
				ParseGPRMC(sentence);
				break;
			case 296:
				//GPRMB Not Implemented;
				break;
			default:
				/*Serial.print("Parse Failed: ");
				Serial.print(sentence[0]);
				Serial.print(sentence[1]);
				Serial.print(sentence[2]);
				Serial.print(sentence[3]);
				Serial.print(sentence[4]);
				Serial.print(sentence[5]);
				Serial.println( sentence[2] + sentence[3] + sentence[4] + sentence[5] , DEC );*/
				break;
			}
		}
		else
		{
			//TODO: Report bad checksum here
		}
		break;
	}

	//VS2008 code - Have to return something in VS2008
	return false;
}