using GpsClient2.EventArguments; using GpsClient2.Exceptions; using GpsClient2.Model; using GpsClient2.NmeaMessages; using System; using System.ComponentModel; using System.IO.Ports; using System.Threading.Tasks; namespace GpsClient2 { public class ComPortGpsClient : BaseGpsClient { #region Private Properties private readonly NmeaParser _parser = new NmeaParser(); private SerialPort _serialPort; private DateTime? _previousReadTime; private readonly BackgroundWorker worker = new BackgroundWorker(); private ComPortInfo data = null; #endregion #region Constructors public ComPortGpsClient(ComPortInfo connectionData) : base(GpsType.ComPort, connectionData) { } public ComPortGpsClient(BaseGpsInfo connectionData) : base(GpsType.ComPort, connectionData) { } #endregion #region Connect and Disconnect public override bool Connect() { data = (ComPortInfo)GpsInfo; IsRunning = true; OnGpsStatusChanged(GpsStatus.Connecting); _serialPort = new SerialPort(data.ComPort, data.BaudRate, Parity.None, 8, StopBits.One); // Attach a method to be called when there // is data waiting in the port's buffer //_serialPort.DataReceived += port_DataReceived; try { // Begin communications _serialPort.Open(); OnGpsStatusChanged(GpsStatus.Connected); // Enter an application loop to keep this thread alive worker.DoWork += Worker_DoWork; worker.RunWorkerAsync(); return true; } catch { Disconnect(); throw; } } private async void Worker_DoWork(object sender, DoWorkEventArgs e) { while (_serialPort.IsOpen) { await Task.Delay(data.ReadFrequency); //Thread.Sleep(data.ReadFrequenty); processData(); } } public override bool Disconnect() { _serialPort.Close(); IsRunning = false; OnGpsStatusChanged(GpsStatus.Disabled); return true; } #endregion #region Location Callbacks private void port_DataReceived(object sender, SerialDataReceivedEventArgs e) { processData(); } private void processData() { try { var readString = _serialPort.ReadExisting().Trim(); foreach (string sentence in readString.Split(new string[] { Environment.NewLine }, StringSplitOptions.None)) { if (sentence.Length > 0 && sentence.StartsWith("$") && sentence.Contains("*")) { parseSentence(sentence.Trim()); } } } catch (Exception ex) { Console.WriteLine(" ==> " + ex.Message); } } private void parseSentence(string sentence) { if (sentence.StartsWith("$GPGSV")) { return; } // Ignore all $GPGSV messages //Console.WriteLine(sentence); try { OnRawGpsDataReceived(sentence); var result = _parser.Parse(sentence); if (result == null) { return; } if (typeof(GprmcMessage) != result.GetType()) return; if (_previousReadTime != null && GpsInfo.ReadFrequency != 0 && ((GprmcMessage)result).UpdateDate.Subtract(new TimeSpan(0, 0, 0, 0, GpsInfo.ReadFrequency)) <= _previousReadTime) return; OnGpsDataReceived(new GpsDataEventArgs((GprmcMessage)result)); } catch (UnknownTypeException ex) { Console.WriteLine(" ==> " + ex.Message + " : " + sentence); } catch (ArgumentException ex) { Console.WriteLine(" ==> " + ex.Message + " : " + sentence); } } #endregion #region "Find My GPS Device Methods" public async Task FindGps() { int[] bauds = { 9600, 4800 }; foreach (string comPort in SerialPort.GetPortNames()) { foreach (int baud in bauds) { if (await IsGpsPort(comPort, baud)) { GpsInfo = new ComPortInfo(comPort, baud); return true; } } } return false; } private static async Task IsGpsPort(string comPort, int baudRate) { bool result = await Task.Run(() => { Console.Write("Attempting to locate GPS on " + comPort + ":" + baudRate + "..."); SerialPort serial = new SerialPort(comPort, baudRate, Parity.None, 8, StopBits.One); serial.ReadTimeout = 3000; try { serial.Open(); Console.Write(" Connected. Listening for NMEA Sentences..."); } catch (Exception ex) { Console.WriteLine(" Error: " + ex.Message); return false; } string sData = ""; while (true) { string s; try { s = serial.ReadLine(); } catch (Exception ex) { serial.Close(); Console.WriteLine(" Error: " + ex.Message); return false; } if (string.IsNullOrEmpty(s)) { return false; } sData += s + Environment.NewLine; if (sData.Length > 1500) { if (sData.Contains("$GPRMC") || sData.Contains("$GPGGA") || sData.Contains("$GPGSA")) { Console.WriteLine(" This is a GPS device!"); serial.Close(); return true; } } } }); return result; } #endregion } }