From 1129c6c4be7138844f1410f560e8081926de15ea Mon Sep 17 00:00:00 2001 From: Russ Kollmansberger Date: Sat, 27 Sep 2025 09:25:52 -0500 Subject: [PATCH] Added to Nuget, included bug fixes found along the way --- ComPortGpsClient.cs | 123 +++++++++++++++++++++++++++----- GpsClient2.nuspec | 14 ++++ Model/BaseGpsInfo.cs | 2 +- Model/ComPortInfo.cs | 8 ++- Model/WindowsLocationApiInfo.cs | 2 +- WindowsLocationApiGpsClient.cs | 2 +- 6 files changed, 127 insertions(+), 24 deletions(-) create mode 100644 GpsClient2.nuspec diff --git a/ComPortGpsClient.cs b/ComPortGpsClient.cs index b7792f4..a09f6b4 100644 --- a/ComPortGpsClient.cs +++ b/ComPortGpsClient.cs @@ -3,8 +3,9 @@ using GpsClient2.Exceptions; using GpsClient2.Model; using GpsClient2.NmeaMessages; using System; +using System.ComponentModel; using System.IO.Ports; -using System.Threading; +using System.Threading.Tasks; namespace GpsClient2 { public class ComPortGpsClient : BaseGpsClient { @@ -14,7 +15,8 @@ namespace GpsClient2 { private SerialPort _serialPort; private DateTime? _previousReadTime; - + private readonly BackgroundWorker worker = new BackgroundWorker(); + private ComPortInfo data = null; #endregion #region Constructors @@ -30,30 +32,36 @@ namespace GpsClient2 { #region Connect and Disconnect public override bool Connect() { - var data = (ComPortInfo)GpsInfo; + data = (ComPortInfo)GpsInfo; IsRunning = true; OnGpsStatusChanged(GpsStatus.Connecting); - _serialPort = new SerialPort(data.ComPort, 9600, Parity.None, 8, StopBits.One); + _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; + //_serialPort.DataReceived += port_DataReceived; try { // Begin communications _serialPort.Open(); OnGpsStatusChanged(GpsStatus.Connected); // Enter an application loop to keep this thread alive - while (_serialPort.IsOpen) { - Thread.Sleep(data.ReadFrequenty); - } + worker.DoWork += Worker_DoWork; + worker.RunWorkerAsync(); + return true; } catch { Disconnect(); throw; } + } - return true; + 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() { @@ -62,24 +70,103 @@ namespace GpsClient2 { 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(); - OnRawGpsDataReceived(readString); - var result = _parser.Parse(readString); - if (typeof(GprmcMessage) != result.GetType()) return; - if (_previousReadTime != null && GpsInfo.ReadFrequenty != 0 && ((GprmcMessage)result).UpdateDate.Subtract(new TimeSpan(0, 0, 0, 0, GpsInfo.ReadFrequenty)) <= _previousReadTime) return; - OnGpsDataReceived(new GpsDataEventArgs((GprmcMessage)result)); - } catch (UnknownTypeException ex) { - Console.WriteLine(ex.Message); + 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 } } \ No newline at end of file diff --git a/GpsClient2.nuspec b/GpsClient2.nuspec new file mode 100644 index 0000000..bd2cf8c --- /dev/null +++ b/GpsClient2.nuspec @@ -0,0 +1,14 @@ + + + + GpsClient2 + 1.0.7 + GpsClient2 + Russ Kollmansberger + Russ Kollmansberger + Package that allows users to receive and process GPS NMEA sentences or utilize Windows Location Services to report the device's current location. + Updated to include various bug fixes in COM GPS Client and spelling corrections. + NuGet,Package,Helper + MIT + + diff --git a/Model/BaseGpsInfo.cs b/Model/BaseGpsInfo.cs index f22cc9f..d12e714 100644 --- a/Model/BaseGpsInfo.cs +++ b/Model/BaseGpsInfo.cs @@ -2,6 +2,6 @@ public abstract class BaseGpsInfo { public GpsCoordinateSystem CoordinateSystem { get; set; } = GpsCoordinateSystem.GeoEtrs89; - public int ReadFrequenty { get; set; } + public int ReadFrequency { get; set; } } } diff --git a/Model/ComPortInfo.cs b/Model/ComPortInfo.cs index 5f950d0..83ae065 100644 --- a/Model/ComPortInfo.cs +++ b/Model/ComPortInfo.cs @@ -1,14 +1,16 @@ namespace GpsClient2.Model { public class ComPortInfo : BaseGpsInfo { public string ComPort { get; set; } = "ComPort1"; + public int BaudRate { get; set; } = 9600; public ComPortInfo() { - ReadFrequenty = 1000; + ReadFrequency = 1000; } - public ComPortInfo(string comPort, int readFrequenty = 1000) { + public ComPortInfo(string comPort, int baudRate = 9600, int readFrequency = 1000) { ComPort = comPort; - ReadFrequenty = readFrequenty; + BaudRate = baudRate; + ReadFrequency = readFrequency; } } } diff --git a/Model/WindowsLocationApiInfo.cs b/Model/WindowsLocationApiInfo.cs index 171e798..c400a0c 100644 --- a/Model/WindowsLocationApiInfo.cs +++ b/Model/WindowsLocationApiInfo.cs @@ -3,7 +3,7 @@ public int Timeout { get; set; } = 1000; public WindowsLocationApiInfo() { - ReadFrequenty = 0; + ReadFrequency = 0; } } } diff --git a/WindowsLocationApiGpsClient.cs b/WindowsLocationApiGpsClient.cs index 1f91c71..0a8741d 100644 --- a/WindowsLocationApiGpsClient.cs +++ b/WindowsLocationApiGpsClient.cs @@ -64,7 +64,7 @@ namespace GpsClient2 { } private void WatcherOnPositionChanged(object sender, GeoPositionChangedEventArgs e) { - if (_previousReadTime != null && GpsInfo.ReadFrequenty != 0 && e.Position.Timestamp.Subtract(new TimeSpan(0, 0, 0, 0, GpsInfo.ReadFrequenty)) <= _previousReadTime) return; + if (_previousReadTime != null && GpsInfo.ReadFrequency != 0 && e.Position.Timestamp.Subtract(new TimeSpan(0, 0, 0, 0, GpsInfo.ReadFrequency)) <= _previousReadTime) return; OnGpsDataReceived(new GpsDataEventArgs(e.Position.Location)); _previousReadTime = e.Position.Timestamp; }