GPS Library - Listed Here

R

Richard Jones

Hi I've been developing a generic GPS library that will shortly be in
the code drop of OpenNetCF under the namespace OpenNETCF.IO.Serial.GPS

To get the ball rolling. Listed below is the namespace. Would
really appreciate some upfront feedback from the group as to stability
of serial port communication (i.e correct com threasholds etc), how I
implement the threading etc.

So here goes....

using System;
using OpenNETCF.IO.Serial;
using System.Text;
using System.Collections;
using System.Threading;
using System.IO;


namespace OpenNETCF.IO.Serial.GPS
{

/// <summary>
/// Produced Under the Terms Of The OpennetCF License
///
/// By Richard Jones - (e-mail address removed)
///
/// </summary>
public class Misc // utility functions
{
public static decimal KnotsToMph(decimal Knots)
{
return Knots * 1.151m;
}

//TODO grabbed conversion from MSDN editor
//not sure what the actual unit for altitude is
public static decimal AltToFeet(decimal Alt)
{
return (Alt / 39.36m) * 12;
}

/// <summary>
/// convert decimal degrees to sexagesimal format
/// </summary>
/// <param name="thedata"></param>
/// <returns></returns>
///
public static string DecimalToSexagesimal(decimal inputdata)
{

// orignal input = the data 4533.3512

string strdata=Math.Abs(inputdata).ToString("00000.0000");

// degrees is 45
string degrees=strdata.Substring(0,3);


string minutes = strdata.Substring(3,2);
// minutes is 33

decimal decseconds = Convert.ToDecimal(strdata.Substring(5));
// decseconds = .3512

decseconds = Math.Round(decseconds*60,2);

// seconds = 21.07

return degrees+"°"+minutes+"'"+decseconds.ToString("00.00")+"\"";


}


}
public enum CardinalDirection
{
North = 0,
East = 1,
South = 2,
West = 4,
NorthWest = 5,
NorthEast = 6,
SouthWest = 7,
SouthEast = 8,
Stationary = 9
}

public enum States
{
Opening,
Running,
Stopping,
Stopped
}

public enum StatusType
{
NotSet,
OK, //A
Warning //V

}

public class GpsGPRMCEventArgs:EventArgs
{
#region private members
StatusType blfixextablished=StatusType.Warning;

decimal latitude=0;
string latitude_sexagesimal="";
CardinalDirection latitude_direction=CardinalDirection.North;

decimal longitude=0;
string longitude_sexagesimal="";
CardinalDirection longitude_direction=CardinalDirection.West;

decimal speedknots=0;
decimal track=0;
#endregion
#region properties
public string Latitude_Sexagesimal
{
get
{
return latitude_sexagesimal;
}
}

public string Longitude_Sexagesimal
{
get
{
return longitude_sexagesimal;
}

}

public string DirectionLongitude
{
get
{
return longitude_direction.ToString();
}
}

public string DirectionLatitude
{
get
{
return latitude_direction.ToString();
}
}

public decimal Latitude
{
get
{
return latitude;
}

}

public decimal Longitude
{
get
{
return longitude;
}

}

public decimal SpeedKnots
{
get
{
return speedknots;
}

}

public decimal SpeedMPH
{
get
{
return Math.Round(Misc.KnotsToMph(speedknots),1);
}

}

public decimal Track
{
get
{
return Math.Round(track,1);
}
}
#endregion

public GpsGPRMCEventArgs(string[] strdata, ref StatusType gpsstatus)
{

//if (strdata.Length!=12) return;

// 0 180432 UTC of position fix in hhmmss format (18 hours, 4
minutes and 32 seconds)

// 1 A Status (A - data is valid, V - warning)
blfixextablished=(strdata[1]=="A")?StatusType.OK:StatusType.Warning;

if (gpsstatus!=blfixextablished)
{
// status has changed so fire our event;
gpsstatus=blfixextablished;
}


//2 4027.027912 Geographic latitude in ddmm.mmmmmm format (40
degrees and 27.027912 minutes)
if (strdata[2].Length>0)
{
latitude=(decimal) Convert.ToDecimal(strdata[2]);
latitude_sexagesimal=Misc.DecimalToSexagesimal(latitude);
}

// 3 N Direction of latitude (N - North, S - South)
if (strdata[3].Length>0)
if (strdata[3][0]=='N')
latitude_direction=CardinalDirection.North;
else
latitude_direction=CardinalDirection.South;

// 4 08704.857070 Geographic longitude in dddmm.mmmmmm format (87
degrees and 4.85707 minutes)
if (strdata[4].Length>0)
{
longitude=(decimal) Convert.ToDecimal(strdata[4]);
longitude_sexagesimal=Misc.DecimalToSexagesimal(longitude);

}

// 5 W Direction of longitude (E - East, W - West)

if (strdata[5].Length>0)
if (strdata[5][0]=='W')
longitude_direction=CardinalDirection.West;
else
longitude_direction=CardinalDirection.East;



//6 000.04 Speed over ground (0.04 knots)
if (strdata[6].Length>0)
speedknots=(decimal) Convert.ToDouble(strdata[6]);


// 7 181.9 Track made good (heading) (181.9º)
if (strdata[7].Length>0)
track=(decimal) Convert.ToDecimal(strdata[7]);

//8 131000 Date in ddmmyy format (October 13, 2000)

// 9 1.8 Magnetic variation (1.8º)

//10 W Direction of magnetic variation (E - East, W - West)

// 11 D Mode indication (A - autonomous, D - differential, N - data
not valid)
}
}

public class GpsSentenceEventArgs:EventArgs
{
private string sentence="";
private int counter=0;

public string Sentence
{
get
{
return sentence;
}
}

public int Counter
{
get
{
return counter;
}
}
public GpsSentenceEventArgs(string sentence,int counter)
{
this.counter=counter;
this.sentence=sentence;
}
}

public class GpsCommStateEventArgs:EventArgs
{

private States state;


public States State
{
get
{
return state;
}

}
public GpsCommStateEventArgs(States state)
{
this.state=state;
}
}
public class GpsStatusEventArgs
{

private StatusType gpsstatus;

public StatusType GpsStatus
{
get
{
return gpsstatus;
}
}
public GpsStatusEventArgs(StatusType gpsstatus)
{

this.gpsstatus=gpsstatus;
}
}
public class GPS
{
#region private members
Port cp;
OpenNETCF.IO.Serial.BaudRates
baudrate=OpenNETCF.IO.Serial.BaudRates.CBR_4800;
string comport="COM1:";

string strreceived="";
int sentencecount=0;
string storedgprmc="";

private States state=States.Stopped;
private Thread thrd;

private StatusType gpsstatus=StatusType.Warning;

private bool traceon=false;
private string tracefile=@"\gpslog.txt";
#endregion

#region public members
public void Start()
{
if (state!=States.Stopped) return;

ThreadStart runner = new ThreadStart(run);
thrd = new Thread(runner);
thrd.Priority=ThreadPriority.BelowNormal;
thrd.Start();
}

public void Stop()
{
if (state!=States.Running) return;
setstate=States.Stopping;
}

#endregion

#region protected methods
protected virtual void OnGpsGPRMC(GpsGPRMCEventArgs e)
{

if (GpsGPRMC != null) GpsGPRMC(this, e);

}

protected virtual void OnGpsSentence(GpsSentenceEventArgs e)
{

if (GpsSentence != null) GpsSentence(this, e);

}

protected virtual void OnGpsCommState(GpsCommStateEventArgs e)
{
if (GpsCommState!=null) GpsCommState(this, e);
}

protected virtual void OnGpsStatus(GpsStatusEventArgs e)
{
if (GpsStatus!=null) GpsStatus(this, e);
}
#endregion

#region events
public event GpsGPRMCEventHandler GpsGPRMC;
public event GpsSentenceEventHandler GpsSentence;
public event GpsCommStateEventHandler GpsCommState;
public event GpsStatusEventHandler GpsStatus;
#endregion

#region delegates
public delegate void GpsGPRMCEventHandler(object sender,
GpsGPRMCEventArgs e);
public delegate void GpsSentenceEventHandler(object sender,
GpsSentenceEventArgs e);
public delegate void GpsCommStateEventHandler(object sender,
GpsCommStateEventArgs e);
public delegate void GpsStatusEventHandler(object sender,
GpsStatusEventArgs e);
#endregion

#region properties

public bool TraceOn
{
set
{
traceon=value;
}
get
{
return traceon;
}
}

public string TraceFile
{
set
{
tracefile=value;
}
get
{
return tracefile;
}

}

public States State
{
get
{
return state;
}
}

public StatusType GpsState
{
get
{
return gpsstatus;
}
}

private States setstate
{
set
{
state=value;
this.OnGpsCommState(new GpsCommStateEventArgs(value));
}
}

public string ComPort
{
set
{
comport=value;
}
}

public OpenNETCF.IO.Serial.BaudRates BaudRate
{
set
{
baudrate=value;
}
}


#endregion

#region private members

private void run()
{
setstate=States.Opening;
// reset all private members
strreceived="";
sentencecount=0;
storedgprmc="";
gpsstatus=StatusType.NotSet;

DetailedPortSettings portSettings = new HandshakeNone();

cp = new Port(comport,portSettings);
cp.RThreshold = 8;
cp.InputLen = 8;
cp.Settings.BaudRate=this.baudrate;
cp.RThreshold=16;
cp.InputLen=64;

try
{
cp.Open();
}
catch
{
cp.Dispose();
setstate=States.Stopped;
return;
}

if (cp.IsOpen)
{
// just trash anything in the input buffer

if (cp.InBufferCount>0)
{
byte[] inputData = new byte[cp.InBufferCount];
inputData = cp.Input;
}

}

cp.OnError+=new OpenNETCF.IO.Serial.Port.CommErrorEvent(cp_OnError);
cp.DataReceived+=new
OpenNETCF.IO.Serial.Port.CommEvent(cp_DataReceived);
cp.PowerEvent+=new
OpenNETCF.IO.Serial.Port.CommEvent(cp_PowerEvent);

setstate=States.Running;
while (state==States.Running)
{
Thread.Sleep(10);
}

if (cp.IsOpen) cp.Close();
cp.Dispose();
setstate=States.Stopped;
}

/// <summary>
/// this is fired when the comport receives data
/// </summary>
private void cp_DataReceived()
{
if (state!=States.Running) return;

if (cp.InBufferCount==0) return;

byte[] inputData = new byte[cp.InBufferCount];

inputData = cp.Input;

string strret = Encoding.ASCII.GetString(inputData,
0,inputData.Length);

// belt and braces - double check if our received data is over 200
chars. trash the first part
if (strreceived.Length>200)
{
strreceived=strreceived.Substring(200);
}

this.strreceived+=strret;

int intcrl=strreceived.IndexOf("\r\n");
if (intcrl==-1) return;


string strdata=strreceived.Substring(0,intcrl);
// is this the last 2 chars ?
if (intcrl+2==strreceived.Length)
strreceived="";
else
strreceived=strreceived.Substring(intcrl+2);

nmea(strdata);
}




/// <summary>
/// processes our string of Nema data
/// </summary>
/// <param name="gps_data">string of input data</param>
/// <returns>Boolean to indicate if we were able to process string
of data ok</returns>
private bool nmea(string gps_data)
{

if (state!=States.Running) return false;
// GPS data can't be zero length
if (gps_data.Length==0) return false;


// GPS data can't be longer than 82 character
if (gps_data.Length>82) return false;

// first character must be a $
if (gps_data[0]!='$') return false;

// remove our leading character
string strdata=gps_data.Substring(1);

// see if the last block contains a * used to see if we have a
checksum
int intstarpos=strdata.IndexOf('*');
if (intstarpos>=0)
{
// we have a checksum so check it...
string strchecksum=strdata.Substring(intstarpos+1);

// remove checksum from end of string
strdata=strdata.Substring(0,strdata.Length-strchecksum.Length-1);

if (!checksum(strdata,strchecksum))
return false;
}

String[] strrecarray = strdata.Split(',');


// get the first block which is the sentance id
string strsentance=strrecarray[0];

ArrayList sbdata = new ArrayList();

// get the data block minus the first block
for (int i=1;i<strrecarray.Length;i++)
sbdata.Add(strrecarray);


// if all is well raise our main GPS event
string[] arrydata = (string[]) sbdata.ToArray(typeof(string));

// incremenet our counter
if (sentencecount==int.MaxValue) sentencecount=0;

sentencecount++;
OnGpsSentence(new GpsSentenceEventArgs(gps_data,sentencecount));

if (traceon)
{
StreamWriter sw = File.AppendText(tracefile);
sw.WriteLine(gps_data);
sw.Close();

}
switch (strsentance)
{
case "GPRMC": // Recommended minimum specific GPS/Transit data

// only fire our event if something has changed.
if (storedgprmc!=gps_data)
{
storedgprmc=gps_data;
StatusType oldstatus=this.gpsstatus;
OnGpsGPRMC(new GpsGPRMCEventArgs(arrydata,ref gpsstatus));

// see if our status has changed
if (oldstatus!=gpsstatus)
{
OnGpsStatus(new GpsStatusEventArgs(gpsstatus));
}
}
break;


// TODO The following cases are still to complete
case "GPGSA": // GPS DOP and active satellites
break;
case "GPGSV": // sats in view
//process_sat(arrydata);
break;

case "GPGGA": // GPS DOP and active satellites
break;
case "GPGLL": //Geographic position, Latitude and Longitude
break;
}

return true;

}

// TODO - Complete this method
private void process_sat(string[] arrydata)
{
if (arrydata.Length!=7) return;

/*
1 = Total number of messages of this type in this cycle
2 = Message number
3 = Total number of SVs in view
4 = SV PRN number
5 = Elevation in degrees, 90 maximum
6 = Azimuth, degrees from true north, 000 to 359
7 = SNR, 00-99 dB (null when not tracking)
*/

int satsinview=Convert.ToInt32(arrydata[0]);
int intmessage=Convert.ToInt32(arrydata[1]);

if (intmessage==1)
{

}
if (arrydata[0]==arrydata[2])
{
// fire the sat event
}

}


/// <summary>
/// this checksums all nema sequences
/// </summary>
/// <param name="strtocheck">string to check</param>
/// <param name="strchecksum">checksum</param>
/// <returns>true if checksum computes</returns>
private bool checksum(string strtocheck,string strchecksum)
{
int intor=0;
// go from first character upto last *
for(int i=0;(i<strtocheck.Length);i++)
intor=intor^ (int) (strtocheck);


int y = 0;

try
{
y = Convert.ToInt32(strchecksum,16);
}
catch
{
return false;
}
return (intor == y);
}

private void cp_OnError(string Description)
{
if (state!=States.Running) return;
this.setstate=States.Stopping;
}

private void cp_PowerEvent()
{
if (state!=States.Running) return;
this.setstate=States.Stopping;
}
#endregion

}
}
 
C

Compulim

GPS may returns multiple sentence regarding the current physical location
(e.g. GPGLL, GPRMC, GPGGA).

For compatibility reason, I think you should process all of these sentences
and store the state locally in the object. And everytime you receive a
sentence, you should overwrite the state and check if any modifications
occurred. If yes, then fire a location changed event.


Compulim @ kasuei


Richard Jones said:
Hi I've been developing a generic GPS library that will shortly be in
the code drop of OpenNetCF under the namespace OpenNETCF.IO.Serial.GPS

To get the ball rolling. Listed below is the namespace. Would
really appreciate some upfront feedback from the group as to stability
of serial port communication (i.e correct com threasholds etc), how I
implement the threading etc.

So here goes....

using System;
using OpenNETCF.IO.Serial;
using System.Text;
using System.Collections;
using System.Threading;
using System.IO;


namespace OpenNETCF.IO.Serial.GPS
{

/// <summary>
/// Produced Under the Terms Of The OpennetCF License
///
/// By Richard Jones - (e-mail address removed)
///
/// </summary>
public class Misc // utility functions
{
public static decimal KnotsToMph(decimal Knots)
{
return Knots * 1.151m;
}

//TODO grabbed conversion from MSDN editor
//not sure what the actual unit for altitude is
public static decimal AltToFeet(decimal Alt)
{
return (Alt / 39.36m) * 12;
}

/// <summary>
/// convert decimal degrees to sexagesimal format
/// </summary>
/// <param name="thedata"></param>
/// <returns></returns>
///
public static string DecimalToSexagesimal(decimal inputdata)
{

// orignal input = the data 4533.3512

string strdata=Math.Abs(inputdata).ToString("00000.0000");

// degrees is 45
string degrees=strdata.Substring(0,3);


string minutes = strdata.Substring(3,2);
// minutes is 33

decimal decseconds = Convert.ToDecimal(strdata.Substring(5));
// decseconds = .3512

decseconds = Math.Round(decseconds*60,2);

// seconds = 21.07

return degrees+"°"+minutes+"'"+decseconds.ToString("00.00")+"\"";


}


}
public enum CardinalDirection
{
North = 0,
East = 1,
South = 2,
West = 4,
NorthWest = 5,
NorthEast = 6,
SouthWest = 7,
SouthEast = 8,
Stationary = 9
}

public enum States
{
Opening,
Running,
Stopping,
Stopped
}

public enum StatusType
{
NotSet,
OK, //A
Warning //V

}

public class GpsGPRMCEventArgs:EventArgs
{
#region private members
StatusType blfixextablished=StatusType.Warning;

decimal latitude=0;
string latitude_sexagesimal="";
CardinalDirection latitude_direction=CardinalDirection.North;

decimal longitude=0;
string longitude_sexagesimal="";
CardinalDirection longitude_direction=CardinalDirection.West;

decimal speedknots=0;
decimal track=0;
#endregion
#region properties
public string Latitude_Sexagesimal
{
get
{
return latitude_sexagesimal;
}
}

public string Longitude_Sexagesimal
{
get
{
return longitude_sexagesimal;
}

}

public string DirectionLongitude
{
get
{
return longitude_direction.ToString();
}
}

public string DirectionLatitude
{
get
{
return latitude_direction.ToString();
}
}

public decimal Latitude
{
get
{
return latitude;
}

}

public decimal Longitude
{
get
{
return longitude;
}

}

public decimal SpeedKnots
{
get
{
return speedknots;
}

}

public decimal SpeedMPH
{
get
{
return Math.Round(Misc.KnotsToMph(speedknots),1);
}

}

public decimal Track
{
get
{
return Math.Round(track,1);
}
}
#endregion

public GpsGPRMCEventArgs(string[] strdata, ref StatusType gpsstatus)
{

//if (strdata.Length!=12) return;

// 0 180432 UTC of position fix in hhmmss format (18 hours, 4
minutes and 32 seconds)

// 1 A Status (A - data is valid, V - warning)
blfixextablished=(strdata[1]=="A")?StatusType.OK:StatusType.Warning;

if (gpsstatus!=blfixextablished)
{
// status has changed so fire our event;
gpsstatus=blfixextablished;
}


//2 4027.027912 Geographic latitude in ddmm.mmmmmm format (40
degrees and 27.027912 minutes)
if (strdata[2].Length>0)
{
latitude=(decimal) Convert.ToDecimal(strdata[2]);
latitude_sexagesimal=Misc.DecimalToSexagesimal(latitude);
}

// 3 N Direction of latitude (N - North, S - South)
if (strdata[3].Length>0)
if (strdata[3][0]=='N')
latitude_direction=CardinalDirection.North;
else
latitude_direction=CardinalDirection.South;

// 4 08704.857070 Geographic longitude in dddmm.mmmmmm format (87
degrees and 4.85707 minutes)
if (strdata[4].Length>0)
{
longitude=(decimal) Convert.ToDecimal(strdata[4]);
longitude_sexagesimal=Misc.DecimalToSexagesimal(longitude);

}

// 5 W Direction of longitude (E - East, W - West)

if (strdata[5].Length>0)
if (strdata[5][0]=='W')
longitude_direction=CardinalDirection.West;
else
longitude_direction=CardinalDirection.East;



//6 000.04 Speed over ground (0.04 knots)
if (strdata[6].Length>0)
speedknots=(decimal) Convert.ToDouble(strdata[6]);


// 7 181.9 Track made good (heading) (181.9º)
if (strdata[7].Length>0)
track=(decimal) Convert.ToDecimal(strdata[7]);

//8 131000 Date in ddmmyy format (October 13, 2000)

// 9 1.8 Magnetic variation (1.8º)

//10 W Direction of magnetic variation (E - East, W - West)

// 11 D Mode indication (A - autonomous, D - differential, N - data
not valid)
}
}

public class GpsSentenceEventArgs:EventArgs
{
private string sentence="";
private int counter=0;

public string Sentence
{
get
{
return sentence;
}
}

public int Counter
{
get
{
return counter;
}
}
public GpsSentenceEventArgs(string sentence,int counter)
{
this.counter=counter;
this.sentence=sentence;
}
}

public class GpsCommStateEventArgs:EventArgs
{

private States state;


public States State
{
get
{
return state;
}

}
public GpsCommStateEventArgs(States state)
{
this.state=state;
}
}
public class GpsStatusEventArgs
{

private StatusType gpsstatus;

public StatusType GpsStatus
{
get
{
return gpsstatus;
}
}
public GpsStatusEventArgs(StatusType gpsstatus)
{

this.gpsstatus=gpsstatus;
}
}
public class GPS
{
#region private members
Port cp;
OpenNETCF.IO.Serial.BaudRates
baudrate=OpenNETCF.IO.Serial.BaudRates.CBR_4800;
string comport="COM1:";

string strreceived="";
int sentencecount=0;
string storedgprmc="";

private States state=States.Stopped;
private Thread thrd;

private StatusType gpsstatus=StatusType.Warning;

private bool traceon=false;
private string tracefile=@"\gpslog.txt";
#endregion

#region public members
public void Start()
{
if (state!=States.Stopped) return;

ThreadStart runner = new ThreadStart(run);
thrd = new Thread(runner);
thrd.Priority=ThreadPriority.BelowNormal;
thrd.Start();
}

public void Stop()
{
if (state!=States.Running) return;
setstate=States.Stopping;
}

#endregion

#region protected methods
protected virtual void OnGpsGPRMC(GpsGPRMCEventArgs e)
{

if (GpsGPRMC != null) GpsGPRMC(this, e);

}

protected virtual void OnGpsSentence(GpsSentenceEventArgs e)
{

if (GpsSentence != null) GpsSentence(this, e);

}

protected virtual void OnGpsCommState(GpsCommStateEventArgs e)
{
if (GpsCommState!=null) GpsCommState(this, e);
}

protected virtual void OnGpsStatus(GpsStatusEventArgs e)
{
if (GpsStatus!=null) GpsStatus(this, e);
}
#endregion

#region events
public event GpsGPRMCEventHandler GpsGPRMC;
public event GpsSentenceEventHandler GpsSentence;
public event GpsCommStateEventHandler GpsCommState;
public event GpsStatusEventHandler GpsStatus;
#endregion

#region delegates
public delegate void GpsGPRMCEventHandler(object sender,
GpsGPRMCEventArgs e);
public delegate void GpsSentenceEventHandler(object sender,
GpsSentenceEventArgs e);
public delegate void GpsCommStateEventHandler(object sender,
GpsCommStateEventArgs e);
public delegate void GpsStatusEventHandler(object sender,
GpsStatusEventArgs e);
#endregion

#region properties

public bool TraceOn
{
set
{
traceon=value;
}
get
{
return traceon;
}
}

public string TraceFile
{
set
{
tracefile=value;
}
get
{
return tracefile;
}

}

public States State
{
get
{
return state;
}
}

public StatusType GpsState
{
get
{
return gpsstatus;
}
}

private States setstate
{
set
{
state=value;
this.OnGpsCommState(new GpsCommStateEventArgs(value));
}
}

public string ComPort
{
set
{
comport=value;
}
}

public OpenNETCF.IO.Serial.BaudRates BaudRate
{
set
{
baudrate=value;
}
}


#endregion

#region private members

private void run()
{
setstate=States.Opening;
// reset all private members
strreceived="";
sentencecount=0;
storedgprmc="";
gpsstatus=StatusType.NotSet;

DetailedPortSettings portSettings = new HandshakeNone();

cp = new Port(comport,portSettings);
cp.RThreshold = 8;
cp.InputLen = 8;
cp.Settings.BaudRate=this.baudrate;
cp.RThreshold=16;
cp.InputLen=64;

try
{
cp.Open();
}
catch
{
cp.Dispose();
setstate=States.Stopped;
return;
}

if (cp.IsOpen)
{
// just trash anything in the input buffer

if (cp.InBufferCount>0)
{
byte[] inputData = new byte[cp.InBufferCount];
inputData = cp.Input;
}

}

cp.OnError+=new OpenNETCF.IO.Serial.Port.CommErrorEvent(cp_OnError);
cp.DataReceived+=new
OpenNETCF.IO.Serial.Port.CommEvent(cp_DataReceived);
cp.PowerEvent+=new
OpenNETCF.IO.Serial.Port.CommEvent(cp_PowerEvent);

setstate=States.Running;
while (state==States.Running)
{
Thread.Sleep(10);
}

if (cp.IsOpen) cp.Close();
cp.Dispose();
setstate=States.Stopped;
}

/// <summary>
/// this is fired when the comport receives data
/// </summary>
private void cp_DataReceived()
{
if (state!=States.Running) return;

if (cp.InBufferCount==0) return;

byte[] inputData = new byte[cp.InBufferCount];

inputData = cp.Input;

string strret = Encoding.ASCII.GetString(inputData,
0,inputData.Length);

// belt and braces - double check if our received data is over 200
chars. trash the first part
if (strreceived.Length>200)
{
strreceived=strreceived.Substring(200);
}

this.strreceived+=strret;

int intcrl=strreceived.IndexOf("\r\n");
if (intcrl==-1) return;


string strdata=strreceived.Substring(0,intcrl);
// is this the last 2 chars ?
if (intcrl+2==strreceived.Length)
strreceived="";
else
strreceived=strreceived.Substring(intcrl+2);

nmea(strdata);
}




/// <summary>
/// processes our string of Nema data
/// </summary>
/// <param name="gps_data">string of input data</param>
/// <returns>Boolean to indicate if we were able to process string
of data ok</returns>
private bool nmea(string gps_data)
{

if (state!=States.Running) return false;
// GPS data can't be zero length
if (gps_data.Length==0) return false;


// GPS data can't be longer than 82 character
if (gps_data.Length>82) return false;

// first character must be a $
if (gps_data[0]!='$') return false;

// remove our leading character
string strdata=gps_data.Substring(1);

// see if the last block contains a * used to see if we have a
checksum
int intstarpos=strdata.IndexOf('*');
if (intstarpos>=0)
{
// we have a checksum so check it...
string strchecksum=strdata.Substring(intstarpos+1);

// remove checksum from end of string
strdata=strdata.Substring(0,strdata.Length-strchecksum.Length-1);

if (!checksum(strdata,strchecksum))
return false;
}

String[] strrecarray = strdata.Split(',');


// get the first block which is the sentance id
string strsentance=strrecarray[0];

ArrayList sbdata = new ArrayList();

// get the data block minus the first block
for (int i=1;i<strrecarray.Length;i++)
sbdata.Add(strrecarray);


// if all is well raise our main GPS event
string[] arrydata = (string[]) sbdata.ToArray(typeof(string));

// incremenet our counter
if (sentencecount==int.MaxValue) sentencecount=0;

sentencecount++;
OnGpsSentence(new GpsSentenceEventArgs(gps_data,sentencecount));

if (traceon)
{
StreamWriter sw = File.AppendText(tracefile);
sw.WriteLine(gps_data);
sw.Close();

}
switch (strsentance)
{
case "GPRMC": // Recommended minimum specific GPS/Transit data

// only fire our event if something has changed.
if (storedgprmc!=gps_data)
{
storedgprmc=gps_data;
StatusType oldstatus=this.gpsstatus;
OnGpsGPRMC(new GpsGPRMCEventArgs(arrydata,ref gpsstatus));

// see if our status has changed
if (oldstatus!=gpsstatus)
{
OnGpsStatus(new GpsStatusEventArgs(gpsstatus));
}
}
break;


// TODO The following cases are still to complete
case "GPGSA": // GPS DOP and active satellites
break;
case "GPGSV": // sats in view
//process_sat(arrydata);
break;

case "GPGGA": // GPS DOP and active satellites
break;
case "GPGLL": //Geographic position, Latitude and Longitude
break;
}

return true;

}

// TODO - Complete this method
private void process_sat(string[] arrydata)
{
if (arrydata.Length!=7) return;

/*
1 = Total number of messages of this type in this cycle
2 = Message number
3 = Total number of SVs in view
4 = SV PRN number
5 = Elevation in degrees, 90 maximum
6 = Azimuth, degrees from true north, 000 to 359
7 = SNR, 00-99 dB (null when not tracking)
*/

int satsinview=Convert.ToInt32(arrydata[0]);
int intmessage=Convert.ToInt32(arrydata[1]);

if (intmessage==1)
{

}
if (arrydata[0]==arrydata[2])
{
// fire the sat event
}

}


/// <summary>
/// this checksums all nema sequences
/// </summary>
/// <param name="strtocheck">string to check</param>
/// <param name="strchecksum">checksum</param>
/// <returns>true if checksum computes</returns>
private bool checksum(string strtocheck,string strchecksum)
{
int intor=0;
// go from first character upto last *
for(int i=0;(i<strtocheck.Length);i++)
intor=intor^ (int) (strtocheck);


int y = 0;

try
{
y = Convert.ToInt32(strchecksum,16);
}
catch
{
return false;
}
return (intor == y);
}

private void cp_OnError(string Description)
{
if (state!=States.Running) return;
this.setstate=States.Stopping;
}

private void cp_PowerEvent()
{
if (state!=States.Running) return;
this.setstate=States.Stopping;
}
#endregion

}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top