Initial stab at an aggregator

This commit is contained in:
Morten Nielsen 2020-01-16 22:39:55 -08:00
parent 252193dd86
commit bde9a0aee2
2 changed files with 165 additions and 0 deletions

View file

@ -0,0 +1,108 @@
using NmeaParser.Nmea;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace NmeaParser
{
public class GnssMessageProcessor : MessageAggregator
{
public GnssMessageProcessor(NmeaDevice device) : base(device)
{
}
protected override void OnMessagesReceived(NmeaMessage[] messages)
{
base.OnMessagesReceived(messages);
// We prefer GNSS messages, so put thos first
var info = new PositionInformation();
messages = messages.OrderBy(rmc => rmc.TalkerId == Talker.GlobalNavigationSatelliteSystem ? -100 : (int)rmc.TalkerId).ToArray();
info.Longitude = double.NaN;
info.Latitude = double.NaN;
var RmcMessages = messages.OfType<Rmc>().Where(rmc => rmc.Active);
if (RmcMessages.Any())
{
var rmc = RmcMessages.First();
info.Latitude = rmc.Latitude;
info.Longitude = rmc.Longitude;
info.Speed = rmc.Speed;
info.TimeOfFix = rmc.FixTime;
}
var GsaMessages = messages.OfType<Gsa>().Where(gsa => gsa.Fix == Gsa.FixType.Fix3D);
if (!GsaMessages.Any())
GsaMessages = messages.OfType<Gsa>().Where(gsa => gsa.Fix == Gsa.FixType.Fix2D);
if (GsaMessages.Any())
{
var gsa = GsaMessages.First();
info.Hdop = gsa.Hdop;
info.Pdop = gsa.Pdop;
info.Vdop = gsa.Vdop;
info.SatelliteIds = gsa.SatelliteIDs;
}
var GsvMessages = messages.OfType<Gsv>();
if (GsvMessages.Any())
{
Gsv gsv = GsvMessages.First();
info.Satellites = gsv.SVs.ToArray();
}
var GstMessages = messages.OfType<Gst>();
if (GstMessages.Any())
{
Gst gst = GstMessages.First();
info.HorizontalAccuracy = (gst.SemiMajorError + gst.SemiMinorError) / 2;
info.VerticalAccuracy = gst.SigmaHeightError;
if (!info.TimeOfFix.HasValue)
{
info.TimeOfFix = DateTime.UtcNow.Date.Add(gst.FixTime);
}
}
var GgaMessages = messages.OfType<Gga>().Where(g=>g.Quality != Gga.FixQuality.Invalid);
if (GgaMessages.Any())
{
Gga gga = GgaMessages.First();
info.Latitude = gga.Latitude;
info.Longitude = gga.Longitude;
info.Altitude = gga.Altitude;
info.GeoidalSeparation = gga.GeoidalSeparation;
if (!info.TimeOfFix.HasValue)
{
info.TimeOfFix = DateTime.UtcNow.Date.Add(gga.FixTime);
}
}
var GnsMessages = messages.OfType<Gns>();
if (GnsMessages.Any())
{
Gns gns = GnsMessages.First();
if (!info.TimeOfFix.HasValue)
{
info.TimeOfFix = DateTime.UtcNow.Date.Add(gns.FixTime);
}
info.GeoidalSeparation = gns.GeoidalSeparation;
info.Latitude = gns.Latitude;
info.Longitude = gns.Longitude;
}
LocationUpdated?.Invoke(this, info);
}
public event EventHandler<PositionInformation> LocationUpdated;
}
public struct PositionInformation
{
public double? Longitude { get; internal set; }
public double? Latitude { get; internal set; }
public double? Altitude { get; internal set; }
public double? GeoidalSeparation { get; internal set; }
public double? Speed { get; internal set; }
public double? Pdop { get; internal set; }
public double? Hdop { get; internal set; }
public double? Vdop { get; internal set; }
public double? HorizontalAccuracy { get; internal set; }
public double? VerticalAccuracy { get; internal set; }
public DateTimeOffset? TimeOfFix { get; internal set; }
public int[] SatelliteIds { get; internal set; }
public SatelliteVehicle[] Satellites { get; internal set; }
}
}

View file

@ -0,0 +1,57 @@
using NmeaParser.Nmea;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace NmeaParser
{
/// <summary>
/// Aggregates a group of messages, and raises an event once all messages has completed transmission
/// </summary>
public class MessageAggregator
{
private readonly Dictionary<string, Nmea.NmeaMessage> _messages = new Dictionary<string, Nmea.NmeaMessage>();
/// <summary>
/// Initializes a new instance of the <see cref="MessageAggregator"/> class.
/// </summary>
/// <param name="device"></param>
public MessageAggregator(NmeaDevice device)
{
if (device == null)
throw new ArgumentNullException(nameof(device));
Device = device;
Device.MessageReceived += Device_MessageReceived;
}
private void Device_MessageReceived(object sender, NmeaMessageReceivedEventArgs e)
{
if(_messages.ContainsKey(e.Message.MessageType))
{
var messages = _messages.Values.ToArray();
_messages.Clear();
OnMessagesReceived(messages);
MessagesReceived?.Invoke(this, messages);
}
_messages.Add(e.Message.MessageType, e.Message);
}
/// <summary>
/// Called when a group of messages have been received.
/// </summary>
protected virtual void OnMessagesReceived(NmeaMessage[] messages)
{
}
/// <summary>
/// Raised when a group of messages have been received.
/// </summary>
public event EventHandler<Nmea.NmeaMessage[]> MessagesReceived;
/// <summary>
/// The device that's being listened to.
/// </summary>
public NmeaDevice Device { get; }
}
}