下面是 GPS命名空间里面 的 NMEAProtocol 的这个类的代码

using System;

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

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

// number of NMEA commands received (processed or not processed)

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 NMEAProtocol()

{

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;

}

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;

///

// 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;

///

// 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;

///

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));

}

if(checksum == receivedChecksum)

{

ProcessCommand(EncodeToString(command), data);

}

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

}

public void ProcessGPZDA(GPZDAData gpzda)

{

// TODO:  Add NMEAProtocol.ProcessGPZDA implementation

}

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 = 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++;

}

public void ProcessGPGSV(string data)

{

//parses the GPGSV stream to extract satellite information

string[] fields = Regex.Split(data,",");

uint totalNumberOfMessages = Convert.ToUInt32(fields[0]);

//make sure the data is OK. valid range is 1..8 channels

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;

//sats in view

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();

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 ++;

}

private bool IsSatelliteUsed(int satelliteId)

{

if(null == GPGSA.SatsInSolution) return false;

foreach(int satId in GPGSA.SatsInSolution)

{

if (satId == satelliteId) return true;

}

return false;

}

public void ProcessGPGSA(string 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.Count++;

}

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));

//Latitude

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;

//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 bool IsSatUsedInSolution(int SatelliteID)

{

return IsSatelliteUsed(SatelliteID);

}

public void Reset()

{

// TODO:  Add NMEAProtocol.Reset implementation

}

private string EncodeToString(byte[] 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];

}

public void ProcessCommand(string sCmd, byte[] bData)

{

string data = EncodeToString(bData);

switch(sCmd)

{

case "GPGGA":

ProcessGPGGA(data);

break;

case "GPGSA":

ProcessGPGSA(data);

break;

case "GPGSV":

ProcessGPGSV(data);

break;

case "GPRMC":

ProcessGPRMC(data);

break;

case "GPRMB":

//ProcessGPRMB(pData);

break;

case "GPZDA":

//ProcessGPZDA(pData);

break;

default:

break;

}

CommandCount = CommandCount + 1;

}

#endregion

}

}

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐