From b2e4d7c2a65545710bf8c1c46779266dedc657da Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 31 Jul 2014 00:37:30 -0700 Subject: [PATCH] Added $GPRTE. Implemented common interface for multi-part messages. --- src/NmeaParser.Shared/IMultiPartMessage.cs | 19 +++++ src/NmeaParser.Shared/Nmea/Gps/GPGSV.cs | 13 +++- src/NmeaParser.Shared/Nmea/Gps/GPRTE.cs | 76 +++++++++++++++++++ src/NmeaParser.Shared/NmeaDevice.cs | 15 +++- .../NmeaParser.Shared.projitems | 2 + src/NmeaParser.Tests/NmeaMessages.cs | 23 +++++- src/NmeaSampleData.txt | 3 +- .../SampleApp.Store.Shared/MainPage.xaml.cs | 6 +- src/SampleApp.WinDesktop/MainWindow.xaml.cs | 8 +- 9 files changed, 151 insertions(+), 14 deletions(-) create mode 100644 src/NmeaParser.Shared/IMultiPartMessage.cs create mode 100644 src/NmeaParser.Shared/Nmea/Gps/GPRTE.cs diff --git a/src/NmeaParser.Shared/IMultiPartMessage.cs b/src/NmeaParser.Shared/IMultiPartMessage.cs new file mode 100644 index 0000000..4d68dd0 --- /dev/null +++ b/src/NmeaParser.Shared/IMultiPartMessage.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NmeaParser +{ + interface IMultiPartMessage : IEnumerable + { + /// + /// Total number of messages of this type in this cycle + /// + int TotalMessages { get; } + + /// + /// Message number + /// + int MessageNumber { get; } + } +} diff --git a/src/NmeaParser.Shared/Nmea/Gps/GPGSV.cs b/src/NmeaParser.Shared/Nmea/Gps/GPGSV.cs index fa81e53..2deec37 100644 --- a/src/NmeaParser.Shared/Nmea/Gps/GPGSV.cs +++ b/src/NmeaParser.Shared/Nmea/Gps/GPGSV.cs @@ -27,7 +27,7 @@ namespace NmeaParser.Nmea.Gps /// GPS Satellites in view /// [NmeaMessageType(Type = "GPGSV")] - public sealed class Gpgsv : NmeaMessage + public sealed class Gpgsv : NmeaMessage, IMultiPartMessage { protected override void LoadMessage(string[] message) { @@ -65,6 +65,17 @@ namespace NmeaParser.Nmea.Gps /// Dilution of precision /// public SatelitteVehicle[] SVs { get; private set; } + + public IEnumerator GetEnumerator() + { + foreach(var sv in SVs) + yield return sv; + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } } public sealed class SatelitteVehicle diff --git a/src/NmeaParser.Shared/Nmea/Gps/GPRTE.cs b/src/NmeaParser.Shared/Nmea/Gps/GPRTE.cs new file mode 100644 index 0000000..2702489 --- /dev/null +++ b/src/NmeaParser.Shared/Nmea/Gps/GPRTE.cs @@ -0,0 +1,76 @@ +// +// Copyright (c) 2014 Morten Nielsen +// +// Licensed under the Microsoft Public License (Ms-PL) (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://opensource.org/licenses/Ms-PL.html +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NmeaParser.Nmea.Gps +{ + /// + /// Routes + /// + [NmeaMessageType(Type = "GPRTE")] + public sealed class Gprte : NmeaMessage, IMultiPartMessage + { + public enum WaypointListType + { + CompleteWaypointsList, + RemainingWaypointsList + } + protected override void LoadMessage(string[] message) + { + TotalMessages = int.Parse(message[0]); + MessageNumber = int.Parse(message[1]); + ListType = message[2] == "c" ? WaypointListType.CompleteWaypointsList : WaypointListType.RemainingWaypointsList; + RouteID = message[3]; + Waypoints = message.Skip(4).ToArray(); + } + + /// + /// Total number of messages of this type in this cycle + /// + public int TotalMessages { get; private set; } + + /// + /// Message number + /// + public int MessageNumber { get; private set; } + + public WaypointListType ListType { get; private set; } + + public string RouteID { get; set; } + + /// + /// Waypoints + /// + public string[] Waypoints { get; private set; } + + IEnumerator IEnumerable.GetEnumerator() + { + foreach (string waypoint in Waypoints) + yield return waypoint; + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return ((IEnumerable)this).GetEnumerator(); + } + } +} diff --git a/src/NmeaParser.Shared/NmeaDevice.cs b/src/NmeaParser.Shared/NmeaDevice.cs index b55b882..9392f2a 100644 --- a/src/NmeaParser.Shared/NmeaDevice.cs +++ b/src/NmeaParser.Shared/NmeaDevice.cs @@ -119,10 +119,10 @@ namespace NmeaParser private void OnMessageReceived(Nmea.NmeaMessage msg) { if (MessageReceived != null) - MessageReceived(this, msg); + MessageReceived(this, new NmeaMessageReceivedEventArgs(msg)); } - public event TypedEventHandler MessageReceived; + public event EventHandler MessageReceived; public void Dispose() { @@ -142,4 +142,15 @@ namespace NmeaParser } } } + + public sealed class NmeaMessageReceivedEventArgs : EventArgs + { + 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; } + } } diff --git a/src/NmeaParser.Shared/NmeaParser.Shared.projitems b/src/NmeaParser.Shared/NmeaParser.Shared.projitems index fd8fb05..a38561c 100644 --- a/src/NmeaParser.Shared/NmeaParser.Shared.projitems +++ b/src/NmeaParser.Shared/NmeaParser.Shared.projitems @@ -9,12 +9,14 @@ NmeaParser + + diff --git a/src/NmeaParser.Tests/NmeaMessages.cs b/src/NmeaParser.Tests/NmeaMessages.cs index 9ccc97e..e30445b 100644 --- a/src/NmeaParser.Tests/NmeaMessages.cs +++ b/src/NmeaParser.Tests/NmeaMessages.cs @@ -39,9 +39,9 @@ namespace NmeaParser.Tests var line = reader.ReadLine(); if(line.StartsWith("$")) { - var msg = NmeaMessage.Parse(line); - Assert.IsNotNull(msg); - Assert.IsNotInstanceOfType(msg, typeof(Nmea.UnknownMessage), "Type " + msg.MessageType + " not supported"); + var msg = NmeaMessage.Parse(line); + Assert.IsNotNull(msg); + Assert.IsNotInstanceOfType(msg, typeof(Nmea.UnknownMessage), "Type " + msg.MessageType + " not supported"); } } } @@ -330,5 +330,22 @@ namespace NmeaParser.Tests Assert.AreEqual(NmeaParser.Nmea.Gps.Garmin.Pgrmz.PositionFixDimension.GpsAltitude, rmz.FixDimension, "FixDimension"); } + [TestMethod] + public void TestGprte() + { + string input = "$GPRTE,2,1,c,0,W3IWI,DRIVWY,32CEDR,32-29,32BKLD,32-I95,32-US1,BW-32,BW-198*69"; + var msg = NmeaMessage.Parse(input); + Assert.IsInstanceOfType(msg, typeof(Gprte)); + Gprte gsv = (Gprte)msg; + Assert.AreEqual(2, gsv.TotalMessages); + Assert.AreEqual(1, gsv.MessageNumber); + Assert.AreEqual(NmeaParser.Nmea.Gps.Gprte.WaypointListType.CompleteWaypointsList, gsv.ListType); + Assert.AreEqual("0", gsv.RouteID); + Assert.AreEqual("0", gsv.RouteID); + Assert.AreEqual(9, gsv.Waypoints.Length); + Assert.AreEqual("W3IWI", gsv.Waypoints[0]); + Assert.AreEqual("32BKLD", gsv.Waypoints[4]); + Assert.AreEqual("BW-198", gsv.Waypoints[8]); + } } } diff --git a/src/NmeaSampleData.txt b/src/NmeaSampleData.txt index 153b71c..88cd669 100644 --- a/src/NmeaSampleData.txt +++ b/src/NmeaSampleData.txt @@ -15039,7 +15039,8 @@ $GPBOD,,T,,M,,*47 $PGRME,5.3,M,9.2,M,10.6,M*14 $PGRMZ,7867,f,3*25 -$GPRTE,1,1,c,*37$GPRMC,003108,A,3916.3063,N,11955.9906,W,0.0,163.5,260905,15.2,E,A*38 +$GPRTE,1,1,c,*37 +$GPRMC,003108,A,3916.3063,N,11955.9906,W,0.0,163.5,260905,15.2,E,A*38 $GPRMB,A,,,,,,,,,,,,A,A*0B $GPGGA,003108,3916.3063,N,11955.9906,W,1,08,1.7,2397.3,M,-22.5,M,,*44 $GPGSA,A,3,,04,07,08,09,,24,26,28,29,,,3.4,1.7,3.0*31 diff --git a/src/SampleApp.Store/SampleApp.Store.Shared/MainPage.xaml.cs b/src/SampleApp.Store/SampleApp.Store.Shared/MainPage.xaml.cs index c47a153..3b981a7 100644 --- a/src/SampleApp.Store/SampleApp.Store.Shared/MainPage.xaml.cs +++ b/src/SampleApp.Store/SampleApp.Store.Shared/MainPage.xaml.cs @@ -32,13 +32,13 @@ namespace SampleApp.Store var file = await Windows.Storage.StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///NmeaSampleData.txt")); var device = new NmeaParser.NmeaFileDevice(file); device.MessageReceived += device_MessageReceived; - device.OpenAsync(); + var _ = device.OpenAsync(); } - private void device_MessageReceived(NmeaParser.NmeaDevice sender, NmeaParser.Nmea.NmeaMessage args) + private void device_MessageReceived(object sender, NmeaParser.NmeaMessageReceivedEventArgs args) { Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { - output.Text += args.MessageType + ": " + args.ToString() + '\n'; + output.Text += args.Message.MessageType + ": " + args.Message.ToString() + '\n'; }); } } diff --git a/src/SampleApp.WinDesktop/MainWindow.xaml.cs b/src/SampleApp.WinDesktop/MainWindow.xaml.cs index 0fbcc95..9c43571 100644 --- a/src/SampleApp.WinDesktop/MainWindow.xaml.cs +++ b/src/SampleApp.WinDesktop/MainWindow.xaml.cs @@ -29,17 +29,17 @@ namespace SampleApp.WinDesktop } Dictionary gpgsvList = new Dictionary(); - private void device_MessageReceived(NmeaParser.NmeaDevice sender, NmeaParser.Nmea.NmeaMessage args) + private void device_MessageReceived(object sender, NmeaParser.NmeaMessageReceivedEventArgs args) { Dispatcher.BeginInvoke((Action) delegate() { - output.Text += args.MessageType + ": " + args.ToString() + '\n'; + output.Text += args.Message.MessageType + ": " + args.ToString() + '\n'; output.Select(output.Text.Length - 1, 0); //scroll to bottom //Merge all gpgsv satellite messages - if(args is NmeaParser.Nmea.Gps.Gpgsv) + if(args.Message is NmeaParser.Nmea.Gps.Gpgsv) { - var gpgsv = (NmeaParser.Nmea.Gps.Gpgsv)args; + var gpgsv = (NmeaParser.Nmea.Gps.Gpgsv)args.Message; if(gpgsv.MessageNumber == 1) { gpgsvList = new Dictionary(); //first one. Replace list