C# GPS Reader
Source Code: http://www.paul-abraham.com/ArticleDP/GPSReader.zip
In this brief article, I like to show you how to read data from a GPS mouse and persist it in a database. You need a GPS Mouse, Visual Studio and SqlServer to follow this article.
Recently, I need to find out which percentage I use my firm car for private trips. So, I have programmed a log book to record every trip and I like discuss the prototype of the log book application.
Follow subsequent steps in order to install the example application
- Download the zip file
- Create a database with the name “GPS” and run the GPSReader\Publish\CreateDB.sql script to create table and store procedures
- Adjust the “l(fā)ocalConnection” key on the App.config file which is used to connect to the SqlServer
- Connect the GPS mouse with computer. Normally, GPS devices have USB interface which writes data into a virtual com port. You can find out the particular port in the Device Manager under the section Ports(COM&LPT)
- compile the application(compiling order: BEC,DAT,SerialPort,BLT and GPSReader) , select the appropriate virtual com port and start
If you are curious to know how does GPS work ,then please refer following links
- http://www.pocketgps.co.uk/howgpsworks.php
- http://scign.jpl.nasa.gov/learn/gps2.htm
- http://www.american.edu/academic.depts/cas/mathstat/People/kalman/pdffiles/gps.pdf (very good article)
GPS devices offer data in form of sentences which are defined by NMEA-0183 protocol. There are lot of sentences in the NMEA protocol and it is infeasible to save the whole emitted information in a database, therefore we going deal with only one sentence. The $GPRMC sentence (Recommended minimum specific GNSS data) contents necessary minimum information for navigation purposes.
Example (signal not acquired): $GPRMC,235947.000,V,0000.0000,N,00000.0000,E,,,041299,,*1D
Example (signal acquired): $GPRMC,092204.999,A,4250.5589,S,14718.5084,E,0.00,89.68,211200,,*25
Field |
Example |
Comments |
Sentence ID |
$GPRMC |
|
UTC Time |
092204.999 |
hhmmss.sss |
Status |
A |
A = Valid, V = Invalid |
Latitude |
4250.5589 |
ddmm.mmmm |
N/S Indicator |
S |
N = North, S = South |
Longitude |
14718.5084 |
dddmm.mmmm |
E/W Indicator |
E |
E = East, W = West |
Speed over ground |
0.00 |
Knots |
Course over ground |
0.00 |
Degrees |
UTC Date |
211200 |
DDMMYY |
Magnetic variation |
|
Degrees |
Magnetic variation |
|
E = East, W = West |
Checksum |
*25 |
|
Terminator |
CR/LF |
|
Please refer the following link for further GPS sentences.
http://www.commlinx.com.au/NMEA_sentences.htm
The heart of the application is the BLGPSReader class. This class has a timer and its callback method (void CollectData(object oState)) will collect and persist received data in a particular time tact .
/// <summary>
/// Callback from tGPSTimer Timer
/// </summary>
/// <param name="oState"></param>
protected void CollectData(object oState)
{
try
{
if(this.gpsState.State == StateEnum.Receive)
{
// read from gps device
string strRead=this.serialPort.ReadAvailable();
strRead=strRead.Trim();
if(strRead!=String.Empty)
{
// add to extractor
this.oExtractor.Add(strRead);
string strGPSSentence=String.Empty;
// if a full sentence available, then notify clients and store in data base
while(this.oExtractor.Get(out strGPSSentence)==true)
{
this.NotifyClients(strGPSSentence);
WaitCallback oWaitCallback=new WaitCallback(this.blPersistManager.Persist);
BEC.PersistContent oPersistContent = new BEC.PersistContent(strGPSSentence,this.strMovObjId);
ThreadPool.QueueUserWorkItem(oWaitCallback,oPersistContent);
}
}
} //if(this.gpsState.State == StateEnum.Receive)
}
catch(Exception oException)
{
string strTest=oException.Message;
}
finally
{
if((this.gpsState.State != StateEnum.Stop))
{
this.tGPSTimer.Change(this.nReceiveInterval,0);
}
}
}
I am using SerialPort class, which you can download from the link http://www.gotdotnet.com/Community/UserSamples/Details.aspx?SampleGuid=b06e30f9-1301-4cc6-ac14-dfe325097c69, to read the GPS sentence from a specified com port.
An instance of GPSSentenceExtractor class is used to collect received partial sentence and you can retrieve full sentences using its Get(out strGPSSentence) method. We are using ThreadPool to persist GPS sentence so that this persisting process won’t block receiving process.
As you can see in the finally block, we change the timer to call this method again which ensures that this method won’t be executed simultaneously. I am using my own data access tier ( http://www.paul-abraham.com/ArticleDP/DATier.htm ) to persist GPS data.