166 lines
5.7 KiB
C#
166 lines
5.7 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using NmeaParser;
|
|
using NmeaParser.Messages;
|
|
using skyscraper5.Skyscraper.Gps;
|
|
|
|
namespace skyscraper5.NmeaSharpWrapper
|
|
{
|
|
abstract class NmeaSharpWrapper : IGpsReceiver
|
|
{
|
|
public bool ProvidesAdditionalNmeaData => additionalNmeaData != null;
|
|
|
|
|
|
public bool HasLock => seenLock && seenLonLat;
|
|
|
|
private bool seenLock, seenLonLat;
|
|
private GpsCoordinate receivedCoordinate;
|
|
public GpsCoordinate Coordinate => receivedCoordinate;
|
|
public AdditionalNmeaData AdditionalNmeaData => additionalNmeaData;
|
|
|
|
|
|
public void Stop()
|
|
{
|
|
CancelRequest = true;
|
|
}
|
|
|
|
public void Start()
|
|
{
|
|
_thread = new Thread(ProcessorThread);
|
|
_thread.Priority = ThreadPriority.Lowest;
|
|
_thread.Name = String.Format("GPS Receiver: {0}", this.GetType().Name);
|
|
_thread.Start();
|
|
}
|
|
|
|
protected Thread _thread;
|
|
protected abstract void ProcessorThread();
|
|
protected bool CancelRequest { get; set; }
|
|
private AdditionalNmeaData additionalNmeaData;
|
|
|
|
protected void HandleNmeaMessage(object? sender, NmeaMessageReceivedEventArgs e)
|
|
{
|
|
HandleNmeaMessage(e.Message);
|
|
}
|
|
|
|
protected void HandleNmeaMessage(string s)
|
|
{
|
|
NmeaMessage nmeaMessage = NmeaMessage.Parse(s);
|
|
HandleNmeaMessage(nmeaMessage);
|
|
}
|
|
|
|
protected void HandleNmeaMessage(NmeaMessage message)
|
|
{
|
|
string messageMessageType = message.MessageType;
|
|
switch (messageMessageType)
|
|
{
|
|
case "GPGLL":
|
|
if (additionalNmeaData == null)
|
|
additionalNmeaData = new AdditionalNmeaData();
|
|
Gll gll = (Gll)message;
|
|
additionalNmeaData.ModeIndicator = gll.ModeIndicator.ToString();
|
|
additionalNmeaData.DataActive = gll.DataActive;
|
|
additionalNmeaData.FixTime = gll.FixTime;
|
|
receivedCoordinate = new GpsCoordinate((float)gll.Latitude, (float)gll.Longitude);
|
|
seenLonLat = true;
|
|
break;
|
|
case "GPVTG":
|
|
Vtg vtg = (Vtg)message;
|
|
if (additionalNmeaData == null)
|
|
additionalNmeaData = new AdditionalNmeaData();
|
|
additionalNmeaData.CourseMagnetic = vtg.CourseMagnetic;
|
|
additionalNmeaData.CourseTrue = vtg.CourseTrue;
|
|
additionalNmeaData.SpeedKnots = vtg.SpeedKnots;
|
|
additionalNmeaData.SpeedKph = vtg.SpeedKph;
|
|
break;
|
|
case "GPZDA":
|
|
Zda zda = (Zda)message;
|
|
if (additionalNmeaData == null)
|
|
additionalNmeaData = new AdditionalNmeaData();
|
|
additionalNmeaData.FixDateTime = zda.FixDateTime;
|
|
break;
|
|
case "GPGGA":
|
|
if (additionalNmeaData == null)
|
|
additionalNmeaData = new AdditionalNmeaData();
|
|
Gga gga = (Gga)message;
|
|
additionalNmeaData.Quality = gga.Quality.ToString();
|
|
additionalNmeaData.Altitude = gga.Altitude;
|
|
additionalNmeaData.AltitudeUnits = gga.AltitudeUnits;
|
|
additionalNmeaData.DpgsStationId = gga.DgpsStationId;
|
|
additionalNmeaData.FixTime = gga.FixTime;
|
|
additionalNmeaData.GeoidalSeparation = gga.GeoidalSeparation;
|
|
additionalNmeaData.GeoidalSeparationUnits = gga.GeoidalSeparationUnits;
|
|
additionalNmeaData.Hdop = gga.Hdop;
|
|
additionalNmeaData.NumberOfSatellites = gga.NumberOfSatellites;
|
|
additionalNmeaData.TimeSinceLastDgpsUpdate = gga.TimeSinceLastDgpsUpdate;
|
|
if (gga.Quality == Gga.FixQuality.GpsFix || gga.Quality == Gga.FixQuality.DgpsFix)
|
|
{
|
|
receivedCoordinate = new GpsCoordinate((float)gga.Latitude, (float)gga.Longitude);
|
|
seenLonLat = true;
|
|
seenLock = true;
|
|
}
|
|
break;
|
|
case "GPGSA":
|
|
if (additionalNmeaData == null)
|
|
additionalNmeaData = new AdditionalNmeaData();
|
|
Gsa gsa = (Gsa)message;
|
|
additionalNmeaData.Hdop = gsa.Hdop;
|
|
additionalNmeaData.Fix = gsa.Fix.ToString();
|
|
additionalNmeaData.Mode = gsa.Mode.ToString();
|
|
additionalNmeaData.Pdop = gsa.Pdop;
|
|
additionalNmeaData.SatelliteIDs = gsa.SatelliteIDs;
|
|
additionalNmeaData.Vdop = gsa.Vdop;
|
|
if (gsa.Fix == Gsa.FixType.Fix2D || gsa.Fix == Gsa.FixType.Fix3D)
|
|
seenLock = true;
|
|
break;
|
|
case "GPRMC":
|
|
if (additionalNmeaData == null)
|
|
additionalNmeaData = new AdditionalNmeaData();
|
|
Rmc rmc = (Rmc)message;
|
|
receivedCoordinate = new GpsCoordinate((float)rmc.Latitude, (float)rmc.Longitude);
|
|
seenLonLat = true;
|
|
additionalNmeaData.Active = rmc.Active;
|
|
additionalNmeaData.CourseTrue = rmc.Course;
|
|
additionalNmeaData.FixTime = rmc.FixTime.TimeOfDay;
|
|
additionalNmeaData.MagneticVariation = rmc.MagneticVariation;
|
|
additionalNmeaData.SpeedKnots = rmc.Speed;
|
|
break;
|
|
case "GPGSV":
|
|
if (additionalNmeaData == null)
|
|
additionalNmeaData = new AdditionalNmeaData();
|
|
Gsv gsv = (Gsv)message;
|
|
additionalNmeaData.GnssSignalId = gsv.GnssSignalId;
|
|
additionalNmeaData.SatellitesInView = gsv.SatellitesInView;
|
|
foreach (SatelliteVehicle vehicle in gsv.SVs)
|
|
additionalNmeaData.AddSatellite(vehicle.Id, vehicle.GnssSignalId, vehicle.Azimuth,
|
|
vehicle.Elevation, vehicle.SignalToNoiseRatio, vehicle.System.ToString(),
|
|
vehicle.TalkerId.ToString());
|
|
break;
|
|
case "GPGBS":
|
|
if (additionalNmeaData == null)
|
|
additionalNmeaData = new AdditionalNmeaData();
|
|
Gbs gbs = (Gbs)message;
|
|
additionalNmeaData.LatitudeError = gbs.LatitudeError;
|
|
additionalNmeaData.LongitudeError = gbs.LongitudeError;
|
|
additionalNmeaData.AltitudeError = gbs.AltitudeError;
|
|
additionalNmeaData.SatelliteId = gbs.SatelliteId;
|
|
additionalNmeaData.MissedDetectionProbability = gbs.MissedDetectionProbability;
|
|
additionalNmeaData.BiasEstimate = gbs.BiasEstimate;
|
|
additionalNmeaData.StandardDeviation = gbs.StandardDeviation;
|
|
break;
|
|
case "GSGPG":
|
|
case "GPG":
|
|
case "GPTXT":
|
|
//does not seem to contain anything?
|
|
break;
|
|
default:
|
|
throw new NotImplementedException(messageMessageType);
|
|
}
|
|
}
|
|
}
|
|
}
|