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); } } } }