I'm trying to write my own nmea parser,since i only need some info from the gps, and don't need to interpret all messages. The problem that i have is that my nmea message validator gives me an wrong checksum. Can someone see what i'm droing wrong?
I'm using the idea from Codepedia - Calculating and Validating nmea sentences.
// Returns True if a sentence's checksum matches the
// calculated checksum
// Calculates the checksum for a sentence
private static bool IsValid(string sentence)
{
if (sentence == "")
return false;
if (sentence.Length < 14)
return false;
try
{
string[] Words = GetWords(sentence);
Log.writeToLog(Words);
int checksum = 0;
string CheckToCompare = Words[Words.Length - 1];
StringBuilder sb = new StringBuilder();
for (int i = 1; i < (Words.Length - 2); i++)
{
sb.Append(Words[i]);
}
string sentecenToParse = sb.ToString();
foreach (char charY in sentecenToParse)
{
checksum ^= Convert.ToByte(charY);
}
Log.writeToLog("Checksum: " + checksum.ToString("X2"));
Log.writeToLog("Obtained CheckSum: " + CheckToCompare);
return String.Equals(checksum.ToString("X2"), CheckToCompare, StringComparison.OrdinalIgnoreCase);
}
catch (Exception exc)
{
Log.writeToLog("Exception caused by sentence:" + sentence);
Log.writeToLog("Exception error message: " + exc.Message);
return false;
}
}
// Divides a sentence into individual Words
public static string[] GetWords(string sentence)
{
char[] separator = { ',', '*' };
return sentence.Split(separator);
}
Run LOG
10:30:07 23-02-2011 Opening Port
10:30:08 23-02-2011 Opened Port
10:30:10 23-02-2011 Processing Data
10:30:12 23-02-2011 $GPGGA
10:30:12 23-02-2011 102957.92
10:30:12 23-02-2011 4104.8569
10:30:12 23-02-2011 N
10:30:12 23-02-2011 00836.4700
10:30:12 23-02-2011 W
10:30:12 23-02-2011 1
10:30:12 23-02-2011 4
10:30:12 23-02-2011 15.100
10:30:12 23-02-2011 157.133
10:30:12 23-02-2011 M
10:30:12 23-02-2011 52.386
10:30:12 23-02-2011 M
10:30:12 23-02-2011 0
10:30:12 23-02-2011 0
10:30:13 23-02-2011 79
10:30:13 23-02-2011 Checksum: 6D
10:30:13 23-02-2011 Obtained CheckSum: 79
10:30:13 23-02-2011 Invalid sentence
10:30:13 23-02-2011 $GPRMC
10:30:13 23-02-2011 102957.92
10:30:13 23-02-2011 A
10:30:13 23-02-2011 4104.8569
10:30:13 23-02-2011 N
10:30:13 23-02-2011 00836.4700
10:30:13 23-02-2011 W
10:30:13 23-02-2011 0.000
10:30:13 23-02-2011 5.822
10:30:13 23-02-2011 230211
10:30:13 23-02-2011 0
10:30:13 23-02-2011 W
10:30:14 23-02-2011 A
10:30:14 23-02-2011 2B
10:30:14 23-02-2011 Checksum: 4E
10:30:15 23-02-2011 Obtained CheckSum: 2B
10:30:15 23-02-2011 Invalid sentence
If you use this function from the page you linked:
And pass in your string, with $ a the start and * at the end (before the checksum), and commas between words, it works.
s1 = 79 and s2 = 2B as you would hope.
Isn't the problem that you are discarding all the
','
characters when you calculate the checksum. They should be included as far as I can see. So calculate the checksum on the original string which you have not removed the commas from and it might work better...For many cases making sure the checksum matches is just a waste of time. It's really only (marginally) useful when the source and sink of the NMEA sentences are separated by a serial cable which may be noisy. If the source and sink are within the same device, communicating via shared memory, the checksum will always be correct.
Here is an example that computes the checksum in one go (single parsing of sentence). https://code.google.com/p/avr-nmea-gps-library/ You probably can't do it any faster than this.