From 2fba15f6d99a2c64869dbe23de5bb32303d89684 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 31 Jul 2014 00:59:47 -0700 Subject: [PATCH] Simplified listening to multi part messages --- src/NmeaParser.Shared/IMultiPartMessage.cs | 7 +++- src/NmeaParser.Shared/NmeaDevice.cs | 45 +++++++++++++++++++-- src/SampleApp.WinDesktop/MainWindow.xaml.cs | 13 ++---- 3 files changed, 49 insertions(+), 16 deletions(-) diff --git a/src/NmeaParser.Shared/IMultiPartMessage.cs b/src/NmeaParser.Shared/IMultiPartMessage.cs index 4d68dd0..d586274 100644 --- a/src/NmeaParser.Shared/IMultiPartMessage.cs +++ b/src/NmeaParser.Shared/IMultiPartMessage.cs @@ -4,8 +4,8 @@ using System.Text; namespace NmeaParser { - interface IMultiPartMessage : IEnumerable - { + interface IMultiPartMessage : System.Collections.IEnumerable + { /// /// Total number of messages of this type in this cycle /// @@ -16,4 +16,7 @@ namespace NmeaParser /// int MessageNumber { get; } } + interface IMultiPartMessage : IMultiPartMessage, IEnumerable + { + } } diff --git a/src/NmeaParser.Shared/NmeaDevice.cs b/src/NmeaParser.Shared/NmeaDevice.cs index 9392f2a..5a7f116 100644 --- a/src/NmeaParser.Shared/NmeaDevice.cs +++ b/src/NmeaParser.Shared/NmeaDevice.cs @@ -40,6 +40,7 @@ namespace NmeaParser tcs = new System.Threading.CancellationTokenSource(); m_stream = await OpenStreamAsync(); StartParser(); + MultiPartMessageCache.Clear(); } private void StartParser() @@ -82,6 +83,7 @@ namespace NmeaParser } await closeTask.Task; await CloseStreamAsync(m_stream); + MultiPartMessageCache.Clear(); m_stream = null; } protected abstract Task CloseStreamAsync(Stream stream); @@ -98,7 +100,7 @@ namespace NmeaParser if (lineEnd > -1) { line = message.Substring(0, lineEnd).Trim(); - message = message.Substring(lineEnd); + message = message.Substring(lineEnd + 1); } } if (!string.IsNullOrEmpty(line)) @@ -118,10 +120,46 @@ namespace NmeaParser private void OnMessageReceived(Nmea.NmeaMessage msg) { + var args = new NmeaMessageReceivedEventArgs(msg); + if (msg is IMultiPartMessage) + { + args.IsMultiPart = true; + var multi = (IMultiPartMessage)msg; + if (MultiPartMessageCache.ContainsKey(msg.MessageType)) + { + var dic = MultiPartMessageCache[msg.MessageType]; + if (dic.ContainsKey(multi.MessageNumber - 1) && !dic.ContainsKey(multi.MessageNumber)) + { + dic[multi.MessageNumber] = msg; + } + else //Something is out of order. Clear cache + MultiPartMessageCache.Remove(msg.MessageType); + } + else if (multi.MessageNumber == 1) + { + MultiPartMessageCache[msg.MessageType] = new Dictionary(multi.TotalMessages); + MultiPartMessageCache[msg.MessageType][1] = msg; + } + if (MultiPartMessageCache.ContainsKey(msg.MessageType)) + { + var dic = MultiPartMessageCache[msg.MessageType]; + if (dic.Count == multi.TotalMessages) //We have a full list + { + MultiPartMessageCache.Remove(msg.MessageType); + args.MessageParts = dic.Values.ToArray(); + } + } + } + if (MessageReceived != null) - MessageReceived(this, new NmeaMessageReceivedEventArgs(msg)); + { + MessageReceived(this, args); + } } + private Dictionary> MultiPartMessageCache + = new Dictionary>(); + public event EventHandler MessageReceived; public void Dispose() @@ -147,10 +185,9 @@ namespace NmeaParser { internal NmeaMessageReceivedEventArgs(Nmea.NmeaMessage message) { Message = message; - MessageList = new[] { message }; } public Nmea.NmeaMessage Message { get; private set; } public bool IsMultiPart { get; internal set; } - public Nmea.NmeaMessage[] MessageList { get; internal set; } + public Nmea.NmeaMessage[] MessageParts { get; internal set; } } } diff --git a/src/SampleApp.WinDesktop/MainWindow.xaml.cs b/src/SampleApp.WinDesktop/MainWindow.xaml.cs index 9c43571..021c0b0 100644 --- a/src/SampleApp.WinDesktop/MainWindow.xaml.cs +++ b/src/SampleApp.WinDesktop/MainWindow.xaml.cs @@ -28,25 +28,18 @@ namespace SampleApp.WinDesktop var _ = device.OpenAsync(); } - Dictionary gpgsvList = new Dictionary(); private void device_MessageReceived(object sender, NmeaParser.NmeaMessageReceivedEventArgs args) { Dispatcher.BeginInvoke((Action) delegate() { - output.Text += args.Message.MessageType + ": " + args.ToString() + '\n'; + output.Text += args.Message.MessageType + ": " + args.Message.ToString() + '\n'; output.Select(output.Text.Length - 1, 0); //scroll to bottom - //Merge all gpgsv satellite messages if(args.Message is NmeaParser.Nmea.Gps.Gpgsv) { var gpgsv = (NmeaParser.Nmea.Gps.Gpgsv)args.Message; - if(gpgsv.MessageNumber == 1) - { - gpgsvList = new Dictionary(); //first one. Replace list - } - gpgsvList[gpgsv.MessageNumber] = gpgsv; - if(gpgsv.MessageNumber == gpgsv.TotalMessages) - satView.GpgsvMessages = gpgsvList.Values; + if(args.IsMultiPart && args.MessageParts != null) + satView.GpgsvMessages = args.MessageParts.OfType(); } }); }