windows mobile gps 串口通信 NMEA命令和数据处理(2) (c#)(转)
下面是 GPS命名空间里面 的 NMEAProtocol 的这个类的代码
using System;
using System.Collections.Specialized;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections.Specialized;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
namespace GPS
{
public class NMEAProtocol
{
private const int NP_MAX_CMD_LEN = 8; // maximum command length (NMEA address)
private const int NP_MAX_DATA_LEN = 256; // maximum data length
private const int NP_MAX_CHAN = 36; // maximum number of channels
private const int NP_WAYPOINT_ID_LEN = 32; // waypoint max string len
{
public class NMEAProtocol
{
private const int NP_MAX_CMD_LEN = 8; // maximum command length (NMEA address)
private const int NP_MAX_DATA_LEN = 256; // maximum data length
private const int NP_MAX_CHAN = 36; // maximum number of channels
private const int NP_WAYPOINT_ID_LEN = 32; // waypoint max string len
private NMEAState nState; // Current state protocol parser is in
private byte checksum; // Calculated NMEA sentence checksum
private byte receivedChecksum; // Received NMEA sentence checksum (if exists)
private int index; // Index used for command and data
private byte[] command; // NMEA command
private byte[] data; // NMEA data
private byte checksum; // Calculated NMEA sentence checksum
private byte receivedChecksum; // Received NMEA sentence checksum (if exists)
private int index; // Index used for command and data
private byte[] command; // NMEA command
private byte[] data; // NMEA data
// number of NMEA commands received (processed or not processed)
public int CommandCount;
public int CommandCount;
public GPGGAData GPGGA;
public GPGSAData GPGSA = new GPGSAData();
public GPGSVData GPGSV = new GPGSVData();
public GPRMBData GPRMB;
public GPRMCData GPRMC;
public GPZDAData GPZDA;
public GPGSAData GPGSA = new GPGSAData();
public GPGSVData GPGSV = new GPGSVData();
public GPRMBData GPRMB;
public GPRMCData GPRMC;
public GPZDAData GPZDA;
public NMEAProtocol()
{
command = new byte[NP_MAX_CMD_LEN];
data = new byte[NP_MAX_DATA_LEN];
}
{
command = new byte[NP_MAX_CMD_LEN];
data = new byte[NP_MAX_DATA_LEN];
}
public void ParseBuffer(byte[] buffer)
{
foreach(byte b in buffer)
{
ProcessNMEA(b);
}
return;
}
{
foreach(byte b in buffer)
{
ProcessNMEA(b);
}
return;
}
public void ProcessNMEA(byte btData)
{
switch(nState)
{
///////////////////////////////////////////////////////////////////////
// Search for start of message '$'
case NMEAState.NP_STATE_SOM :
if(btData == '$')
{
checksum = 0; // reset checksum
index = 0; // reset index
nState = NMEAState.NP_STATE_CMD;
}
break;
{
switch(nState)
{
///////////////////////////////////////////////////////////////////////
// Search for start of message '$'
case NMEAState.NP_STATE_SOM :
if(btData == '$')
{
checksum = 0; // reset checksum
index = 0; // reset index
nState = NMEAState.NP_STATE_CMD;
}
break;
///////////////////////////////////////////////////////////////////////
// Retrieve command (NMEA Address)
case NMEAState.NP_STATE_CMD :
if(btData != ',' && btData != '*')
{
command[index++] = btData;
checksum ^= btData;
// Retrieve command (NMEA Address)
case NMEAState.NP_STATE_CMD :
if(btData != ',' && btData != '*')
{
command[index++] = btData;
checksum ^= btData;
// Check for command overflow
if(index >= NP_MAX_CMD_LEN)
{
nState = NMEAState.NP_STATE_SOM;
}
}
else
{
command[index] = (byte)'\0'; // terminate command
checksum ^= btData;
index = 0;
nState = NMEAState.NP_STATE_DATA; // goto get data state
}
break;
if(index >= NP_MAX_CMD_LEN)
{
nState = NMEAState.NP_STATE_SOM;
}
}
else
{
command[index] = (byte)'\0'; // terminate command
checksum ^= btData;
index = 0;
nState = NMEAState.NP_STATE_DATA; // goto get data state
}
break;
///////////////////////////////////////////////////////////////////////
// Store data and check for end of sentence or checksum flag
case NMEAState.NP_STATE_DATA:
if(btData == '*') // checksum flag?
{
data[index] = (byte)'\0';
nState = NMEAState.NP_STATE_CHECKSUM_1;
}
else // no checksum flag, store data
{
//
// Check for end of sentence with no checksum
//
if(btData == '\r')
{
data[index] = (byte) '\0';
ProcessCommand(EncodeToString( command), data);
nState = NMEAState.NP_STATE_SOM;
return;
}
// Store data and check for end of sentence or checksum flag
case NMEAState.NP_STATE_DATA:
if(btData == '*') // checksum flag?
{
data[index] = (byte)'\0';
nState = NMEAState.NP_STATE_CHECKSUM_1;
}
else // no checksum flag, store data
{
//
// Check for end of sentence with no checksum
//
if(btData == '\r')
{
data[index] = (byte) '\0';
ProcessCommand(EncodeToString( command), data);
nState = NMEAState.NP_STATE_SOM;
return;
}
//
// Store data and calculate checksum
//
checksum ^= btData;
data[index] = btData;
if(++index >= NP_MAX_DATA_LEN) // Check for buffer overflow
{
nState = NMEAState.NP_STATE_SOM;
}
}
break;
// Store data and calculate checksum
//
checksum ^= btData;
data[index] = btData;
if(++index >= NP_MAX_DATA_LEN) // Check for buffer overflow
{
nState = NMEAState.NP_STATE_SOM;
}
}
break;
///////////////////////////////////////////////////////////////////////
case NMEAState.NP_STATE_CHECKSUM_1:
if( (btData - '0') <= 9)
{
receivedChecksum = (byte)((btData - '0') << 4);
}
else
{
receivedChecksum = (byte)((btData - 'A' + 10) << 4);
}
case NMEAState.NP_STATE_CHECKSUM_1:
if( (btData - '0') <= 9)
{
receivedChecksum = (byte)((btData - '0') << 4);
}
else
{
receivedChecksum = (byte)((btData - 'A' + 10) << 4);
}
nState = NMEAState.NP_STATE_CHECKSUM_2;
break;
///////////////////////////////////////////////////////////////////////
case NMEAState.NP_STATE_CHECKSUM_2:
if( (btData - '0') <= 9)
{
receivedChecksum |= (byte)((btData - (byte)'0'));
}
else
{
receivedChecksum |= (byte)((btData - (byte)'A' + 10));
}
case NMEAState.NP_STATE_CHECKSUM_2:
if( (btData - '0') <= 9)
{
receivedChecksum |= (byte)((btData - (byte)'0'));
}
else
{
receivedChecksum |= (byte)((btData - (byte)'A' + 10));
}
if(checksum == receivedChecksum)
{
ProcessCommand(EncodeToString(command), data);
}
{
ProcessCommand(EncodeToString(command), data);
}
nState = NMEAState.NP_STATE_SOM;
break;
break;
///////////////////////////////////////////////////////////////////////
default :
nState = NMEAState.NP_STATE_SOM;
break;
}
}
default :
nState = NMEAState.NP_STATE_SOM;
break;
}
}
#region INMEAProtocol Members
public void ProcessGPRMB(GPRMBData gprmc)
{
// TODO: Add NMEAProtocol.ProcessGPRMB implementation
}
{
// TODO: Add NMEAProtocol.ProcessGPRMB implementation
}
public void ProcessGPZDA(GPZDAData gpzda)
{
// TODO: Add NMEAProtocol.ProcessGPZDA implementation
}
{
// TODO: Add NMEAProtocol.ProcessGPZDA implementation
}
public void ProcessGPRMC(string data)
{
string[] fields = Regex.Split(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.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 = Convert.ToDouble(fields[2]) / 100;
if (fields[3] == "S")
GPRMC.LatitudeHemisphere = Cardinal.South;
else
GPRMC.LatitudeHemisphere = Cardinal.North;
GPRMC.Latitude = Convert.ToDouble(fields[2]) / 100;
if (fields[3] == "S")
GPRMC.LatitudeHemisphere = Cardinal.South;
else
GPRMC.LatitudeHemisphere = Cardinal.North;
//Longitude
GPRMC.Longitude = Convert.ToDouble(fields[4]) / 100;
if (fields[5] == "E")
GPRMC.LatitudeHemisphere = Cardinal.East;
else
GPRMC.LatitudeHemisphere = Cardinal.West;
GPRMC.GroundSpeed = Convert.ToDouble(fields[6]);
//TODO: MagVar and Course
GPRMC.Count++;
}
GPRMC.Count++;
}
public void ProcessGPGSV(string data)
{
{
//parses the GPGSV stream to extract satellite information
string[] fields = Regex.Split(data,",");
uint totalNumberOfMessages = Convert.ToUInt32(fields[0]);
uint totalNumberOfMessages = Convert.ToUInt32(fields[0]);
//make sure the data is OK. valid range is 1..8 channels
if ((totalNumberOfMessages > 8) || (totalNumberOfMessages <= 0))
return;
if ((totalNumberOfMessages > 8) || (totalNumberOfMessages <= 0))
return;
GPGSV.TotalNumberOfMessages = totalNumberOfMessages;
//message number
int nMessageNumber = Convert.ToInt32(fields[1]);
//make sure it is 0..9...is there an inconsistency? 8/9?
if ((nMessageNumber > 9) || (nMessageNumber < 0))
return;
int nMessageNumber = Convert.ToInt32(fields[1]);
//make sure it is 0..9...is there an inconsistency? 8/9?
if ((nMessageNumber > 9) || (nMessageNumber < 0))
return;
//sats in view
GPGSV.SatellitesInView = Convert.ToInt32(fields[2]);
GPGSV.SatellitesInView = Convert.ToInt32(fields[2]);
//for(int iSat = 0; iSat < GPGSV.SatellitesInView; iSat++)
for (int iSat = 0; iSat < 4; iSat++)
{
Satellite sat = new Satellite();
for (int iSat = 0; iSat < 4; iSat++)
{
Satellite sat = new Satellite();
sat.Id = Convert.ToInt32(fields[3+iSat*4]);
sat.Elevation = Convert.ToInt32(fields[4+iSat*4]);
sat.Azimuth = Convert.ToInt32(fields[5+iSat*4]);
sat.SignalQuality = Convert.ToInt32(fields[6+iSat*4]);
sat.Used = IsSatelliteUsed(sat.Id);
GPGSV.Satellites.Add(sat);
}
GPGSV.Count ++;
}
sat.Elevation = Convert.ToInt32(fields[4+iSat*4]);
sat.Azimuth = Convert.ToInt32(fields[5+iSat*4]);
sat.SignalQuality = Convert.ToInt32(fields[6+iSat*4]);
sat.Used = IsSatelliteUsed(sat.Id);
GPGSV.Satellites.Add(sat);
}
GPGSV.Count ++;
}
private bool IsSatelliteUsed(int satelliteId)
{
if(null == GPGSA.SatsInSolution) return false;
{
if(null == GPGSA.SatsInSolution) return false;
foreach(int satId in GPGSA.SatsInSolution)
{
if (satId == satelliteId) return true;
}
return false;
}
{
if (satId == satelliteId) return true;
}
return false;
}
public void ProcessGPGSA(string data)
{
try
{
string[] fields = Regex.Split(data, ",");
{
try
{
string[] fields = Regex.Split(data, ",");
GPGSA.Mode = Convert.ToChar(fields[0]);
GPGSA.mFixMode = Convert.ToByte(fields[1]);
GPGSA.SatsInSolution = new int[12];
for (int i = 2; i <= 13; i++)
{
int satId = -1;
if (int.TryParse(fields[i], out satId))
{
if (satId != -1)
{
GPGSA.SatsInSolution[i - 2] = satId;
}
}
}
GPGSA.PDOP = Convert.ToDouble(fields[14]);
GPGSA.HDOP = Convert.ToDouble(fields[15]);
GPGSA.VDOP = Convert.ToDouble(fields[16]);
GPGSA.mFixMode = Convert.ToByte(fields[1]);
GPGSA.SatsInSolution = new int[12];
for (int i = 2; i <= 13; i++)
{
int satId = -1;
if (int.TryParse(fields[i], out satId))
{
if (satId != -1)
{
GPGSA.SatsInSolution[i - 2] = satId;
}
}
}
GPGSA.PDOP = Convert.ToDouble(fields[14]);
GPGSA.HDOP = Convert.ToDouble(fields[15]);
GPGSA.VDOP = Convert.ToDouble(fields[16]);
GPGSA.Count++;
}
catch (Exception e)
{
System.Diagnostics.Trace.WriteLine("Chaos in ProcessGPGSA! " + e.ToString());
}
}
}
catch (Exception e)
{
System.Diagnostics.Trace.WriteLine("Chaos in ProcessGPGSA! " + e.ToString());
}
}
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));
//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 = Convert.ToDouble(fields[1])/100;
if(fields[2]=="S")
GPGGA.LatitudeHemisphere = Cardinal.South;
else
GPGGA.LatitudeHemisphere = Cardinal.North;
GPGGA.Latitude = Convert.ToDouble(fields[1])/100;
if(fields[2]=="S")
GPGGA.LatitudeHemisphere = Cardinal.South;
else
GPGGA.LatitudeHemisphere = Cardinal.North;
//Longitude
GPGGA.Longitude = Convert.ToDouble(fields[3])/100;
if(fields[4]=="E")
GPGGA.LatitudeHemisphere = Cardinal.East;
else
GPGGA.LatitudeHemisphere = Cardinal.West;
GPGGA.Longitude = Convert.ToDouble(fields[3])/100;
if(fields[4]=="E")
GPGGA.LatitudeHemisphere = Cardinal.East;
else
GPGGA.LatitudeHemisphere = Cardinal.West;
//GPS Signal Quality
GPGGA.GPSQuality = (GPSQuality)Convert.ToUInt32( fields[5] );
GPGGA.GPSQuality = (GPSQuality)Convert.ToUInt32( fields[5] );
//Satellites
GPGGA.NumberOfSatellitesInUse = Convert.ToInt32(fields[6]);
GPGGA.NumberOfSatellitesInUse = Convert.ToInt32(fields[6]);
//HDOP
GPGGA.HDOP = Convert.ToDouble( fields[7] );
GPGGA.HDOP = Convert.ToDouble( fields[7] );
//Altitude
GPGGA.Altitude = Convert.ToDouble(fields[8]);
GPGGA.Altitude = Convert.ToDouble(fields[8]);
//increase message count
GPGGA.Count ++;
}
catch(Exception e)
{
System.Diagnostics.Trace.WriteLine("Chaos in ProcessGPGGA! " + e.ToString());
}
}
GPGGA.Count ++;
}
catch(Exception e)
{
System.Diagnostics.Trace.WriteLine("Chaos in ProcessGPGGA! " + e.ToString());
}
}
public bool IsSatUsedInSolution(int SatelliteID)
{
return IsSatelliteUsed(SatelliteID);
}
{
return IsSatelliteUsed(SatelliteID);
}
public void Reset()
{
// TODO: Add NMEAProtocol.Reset implementation
}
{
// TODO: Add NMEAProtocol.Reset implementation
}
private string EncodeToString(byte[] buffer)
{
string s = System.Text.ASCIIEncoding.GetEncoding(1252).GetString(buffer);
{
string s = System.Text.ASCIIEncoding.GetEncoding(1252).GetString(buffer);
// TRIM OFF NULLS!
//s = s.TrimEnd((char)'\0');
//return s;
//TRIM at the FIRST NULL
string[] strings = s.Split('\0');
return strings[0];
}
//s = s.TrimEnd((char)'\0');
//return s;
//TRIM at the FIRST NULL
string[] strings = s.Split('\0');
return strings[0];
}
public void ProcessCommand(string sCmd, byte[] bData)
{
string data = EncodeToString(bData);
switch(sCmd)
{
case "GPGGA":
ProcessGPGGA(data);
break;
{
string data = EncodeToString(bData);
switch(sCmd)
{
case "GPGGA":
ProcessGPGGA(data);
break;
case "GPGSA":
ProcessGPGSA(data);
break;
ProcessGPGSA(data);
break;
case "GPGSV":
ProcessGPGSV(data);
break;
ProcessGPGSV(data);
break;
case "GPRMC":
ProcessGPRMC(data);
break;
case "GPRMB":
//ProcessGPRMB(pData);
break;
case "GPZDA":
//ProcessGPZDA(pData);
break;
ProcessGPRMC(data);
break;
case "GPRMB":
//ProcessGPRMB(pData);
break;
case "GPZDA":
//ProcessGPZDA(pData);
break;
default:
break;
}
CommandCount = CommandCount + 1;
}
#endregion
}
}
break;
}
CommandCount = CommandCount + 1;
}
#endregion
}
}