172 lines
6.0 KiB
C#
172 lines
6.0 KiB
C#
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<bool> 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<bool> 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
|
|
}
|
|
} |