using System; using System.Collections.Generic; using System.Text; using System.IO.Ports; using System.Diagnostics; namespace GpsTest { public abstract class SerialPortGpsProviderBase : IGpsDataProvider { /// <summary> /// Fire this event when A GPS line of data has been received /// </summary> public event GpsDataReceivedEventHandler GpsDataReceived; #region Attributes protected SerialPort comPort = new SerialPort(); #endregion public SerialPortGpsProviderBase() { } ~SerialPortGpsProviderBase() { Dispose(false); } #region IDisposable Members private bool m_disposed = false; public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (!m_disposed) { if (disposing) { // Dispose managed resources } // Dispose unmanaged resources comPort.Dispose(); } m_disposed = true; } #endregion public bool IsOpen() { return comPort.IsOpen; } public void Open() { //set up the delegate used to read data in....... comPort.DataReceived += new SerialDataReceivedEventHandler(comPort_DataReceived); try { //finally open the port.... comPort.Open(); Trace.WriteLine("Com port " + comPort.ToString() + " Open=" + comPort.IsOpen.ToString()); } catch (System.Exception ex) { Trace.WriteLine(DateTime.Now.ToString() + ": Failed to open COM port with exception: " + ex.Message); } } protected abstract void comPort_DataReceived(object sender, SerialDataReceivedEventArgs e); protected void FireGpsDataReceived(string data) { try { if ((data.Length > 0) && (GpsDataReceived != null)) { GpsDataReceived(this, new GpsDataLineEventArgs(data)); } } catch (System.Exception ex) { Trace.WriteLine(DateTime.Now + ": Failed to extract GPS data in comPort_DataReceived: " + ex.Message); } } public void Close() { try { //check we have a valid COM port to close... if (comPort.IsOpen) { comPort.Close(); Debug.WriteLine("Com port " + comPort.ToString() + " CLOSED"); } } catch (System.Exception ex) { Trace.WriteLine(DateTime.Now.ToString() + ": Failed to close COM port with exception: " + ex.Message); } } } }The actual provider just implements the code to read the data and parse it
using System; using System.Collections.Generic; using System.Text; using System.IO.Ports; using System.Diagnostics; namespace GpsTest { // First simple provider public class GpsSerialPortDataProvider : SerialPortGpsProviderBase { #region Attributes private const string comPortName = "COM14"; private const int baudRate = 4800; #endregion public GpsSerialPortDataProvider() { //set up the com port settings..... comPort.PortName = comPortName; comPort.BaudRate = baudRate; comPort.Parity = Parity.None; comPort.StopBits = StopBits.One; comPort.DataBits = 8; comPort.Handshake = Handshake.None; comPort.ReadTimeout = 1000; comPort.NewLine = "\r\n"; } ~GpsSerialPortDataProvider() { Dispose(false); } protected override void comPort_DataReceived( object sender, SerialDataReceivedEventArgs e) { //Read a line of GPS data (each is sent with a \r\n at the end) try { string data = comPort.ReadLine(); FireGpsDataReceived(data); } catch (System.Exception ex) { Trace.WriteLine(DateTime.Now + ": Failed to extract GPS data in comPort_DataReceived: " + ex.Message); } } } }Due to a driver fault on the device we were using we could not read the data a line at a time. We had to clear the buffer out every time we read it, so here is the alternative provider
using System; using System.Collections.Generic; using System.Text; using System.IO.Ports; using System.Diagnostics; namespace GpsTest { public class GpsSerialPortDataProvider3 : SerialPortGpsProviderBase { #region Attributes private const string comPortName = "COM14"; private const int baudRate = 4800; #endregion public GpsSerialPortDataProvider3() { //Setup the COM port comPort.PortName = comPortName; comPort.BaudRate = baudRate; //set up the other settings..... comPort.Parity = Parity.None; comPort.StopBits = StopBits.One; comPort.DataBits = 8; comPort.Handshake = Handshake.None; comPort.ReadTimeout = 1000; comPort.ReceivedBytesThreshold = 256; } ~GpsSerialPortDataProvider3() { Dispose(false); } private string buffer = ""; private object bufferLock = new object(); protected override void comPort_DataReceived(object sender, SerialDataReceivedEventArgs e) { //Read a line of GPS data (each is sent with a \r\n at the end) try { // Read out everything in the buffer string data = comPort.ReadExisting(); if (data.Length > 0) { string ready = string.Empty; lock (bufferLock) { buffer += data; // Do we have any complete lines in the buffer int ix = buffer.LastIndexOf("\r\n"); if (ix >= 0) { // Remove all the complete lines ready = buffer.Remove(ix); // Truncate the buffer any incomplete data at the end buffer = buffer.Remove(0, ix + 2); } } if (ready.Length > 0) // found some complete lines { // Extract them string[] lines = ready.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); foreach (string line in lines) { // Invoke the GpsDataReceived event with the complete line FireGpsDataReceived(line); } } } } catch (System.Exception ex) { Trace.WriteLine(DateTime.Now.ToString() + ": Failed to extract GPS data in comPort_DataReceived: " + ex.Message); } } } }