http://blogs.msdn.com/coding4fun/archive/2006/10/31/912287.aspx and written by Scott Hanselman... how can he be wrong!?
The issue I came across was the precision was out by quite a bit, so the parsing was incorrect, for my device. I'm not sure if NMEA standard is 100% standard, so I'm just posting this code here in case other people have issues.
ProcessGPRMC and ProcessGPGGA both need to be updated, I have created a method to do this.
private static double DDMMSSToDecimalDegrees(string data)
{
var ddmmss = (Convert.ToDouble(data) / 100);
var degrees = (int)ddmmss;
var minutesseconds = ( (ddmmss - degrees) * 100 ) / 60.0;
return degrees + minutesseconds;
}
There is also the issue to do with North, Southern, Western and Eastern Hemisphere where the value has go to be negated. :)
So the update methods needs to look like this
public void ProcessGPGGA(string data)
{
try
{
string[] fields = Regex.Split(data, ",");
//Time: Hour, Minute, Second
//Time is Zulu
GPGGA.Hour = Convert.ToInt32(fields[0].Substring(0, 2));
GPGGA.Minute = Convert.ToInt32(fields[0].Substring(2, 2));
GPGGA.Second = Convert.ToInt32(fields[0].Substring(4, 2));
//Latitude
GPGGA.Latitude = DDMMSSToDecimalDegrees(fields[1]);
if (fields[2] == "S")
GPGGA.LatitudeHemisphere = Cardinal.South;
else
GPGGA.LatitudeHemisphere = Cardinal.North;
if (GPGGA.LatitudeHemisphere == Cardinal.South)
GPGGA.Latitude = GPGGA.Latitude * -1;
//Longitude
GPGGA.Longitude = DDMMSSToDecimalDegrees(fields[3]);
if (fields[4] == "W")
GPGGA.LongitudeHemisphere = Cardinal.West;
else
GPGGA.LongitudeHemisphere = Cardinal.East;
if (GPGGA.LongitudeHemisphere == Cardinal.West)
GPGGA.Longitude = GPGGA.Longitude * -1;
//GPS Signal Quality
GPGGA.GPSQuality = (GPSQuality)Convert.ToUInt32( fields[5] );
//Satellites
GPGGA.NumberOfSatellitesInUse = Convert.ToInt32(fields[6]);
//HDOP
GPGGA.HDOP = Convert.ToDouble( fields[7] );
//Altitude
GPGGA.Altitude = Convert.ToDouble(fields[8]);
//increase message count
GPGGA.Count ++;
}
catch(Exception e)
{
System.Diagnostics.Trace.WriteLine("Chaos in ProcessGPGGA! " + e.ToString());
}
}
public void ProcessGPRMC(string data)
{
string[] fields = Regex.Split(data, ",");
//Time: Hour, Minute, Second
//Time is Zulu
GPRMC.Hour = Convert.ToInt32(fields[0].Substring(0, 2));
GPRMC.Minute = Convert.ToInt32(fields[0].Substring(2, 2));
GPRMC.Second = Convert.ToInt32(fields[0].Substring(4, 2));
GPRMC.Day = Convert.ToInt32(fields[8].Substring(0, 2));
GPRMC.Month = Convert.ToInt32(fields[8].Substring(2, 2));
GPRMC.Year = Convert.ToInt32(fields[8].Substring(4, 2));
GPRMC.DataValid = Convert.ToChar(fields[1]);
//Latitude
GPRMC.Latitude = DDMMSSToDecimalDegrees(fields[2]);
if (fields[3] == "S")
GPRMC.LatitudeHemisphere = Cardinal.South;
else
GPRMC.LatitudeHemisphere = Cardinal.North;
if (GPRMC.LatitudeHemisphere == Cardinal.South)
GPRMC.Latitude = GPRMC.Latitude * -1;
//Longitude
GPRMC.Longitude = DDMMSSToDecimalDegrees(fields[4]);
if (fields[5] == "W")
GPRMC.LongitudeHemisphere = Cardinal.West;
else
GPRMC.LongitudeHemisphere = Cardinal.East;
if (GPRMC.LongitudeHemisphere == Cardinal.West)
GPRMC.Longitude = GPRMC.Longitude * -1;
GPRMC.GroundSpeed = Convert.ToDouble(fields[6]);
//TODO: MagVar and Course
GPRMC.Count++;
}
That's it for now, I haven't implemented the rest of the project. I'll post all the updated code when I get somewhere, github maybe?
Thanks for your post,it saved my day
ReplyDelete