diff --git a/src/NmeaParser.Shared/Nmea/Gps/GPGSA.cs b/src/NmeaParser.Shared/Nmea/Gps/GPGSA.cs
new file mode 100644
index 0000000..0a4120d
--- /dev/null
+++ b/src/NmeaParser.Shared/Nmea/Gps/GPGSA.cs
@@ -0,0 +1,105 @@
+//
+// 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
+{
+ ///
+ /// Global Positioning System Fix Data
+ ///
+ [NmeaMessageType(Type = "GPGSA")]
+ public class Gpgsa : NmeaMessage
+ {
+ public enum ModeSelection
+ {
+ Auto,
+ Manual,
+ }
+ public enum Mode : int
+ {
+ NotAvailable = 1,
+ _2D = 2,
+ _3D = 3
+ }
+
+ protected override void LoadMessage(string[] message)
+ {
+ GpsMode = message[0] == "A" ? ModeSelection.Auto : ModeSelection.Manual;
+ FixMode = (Mode)int.Parse(message[1]);
+
+ List svs = new List();
+ for (int i = 2; i < 14; i++)
+ {
+ int id = -1;
+ if (message[i].Length > 0 && int.TryParse(message[i], out id))
+ svs.Add(id);
+ }
+ SVs = svs.ToArray();
+
+ double tmp;
+ if (double.TryParse(message[14], NumberStyles.Float, CultureInfo.InvariantCulture, out tmp))
+ PDop = tmp;
+ else
+ PDop = double.NaN;
+
+ if (double.TryParse(message[15], NumberStyles.Float, CultureInfo.InvariantCulture, out tmp))
+ HDop = tmp;
+ else
+ HDop = double.NaN;
+
+ if (double.TryParse(message[16], NumberStyles.Float, CultureInfo.InvariantCulture, out tmp))
+ VDop = tmp;
+ else
+ VDop = double.NaN;
+ }
+
+ ///
+ /// Mode
+ ///
+ public ModeSelection GpsMode { get; private set; }
+
+ ///
+ /// Mode
+ ///
+ public Mode FixMode { get; private set; }
+
+ ///
+ /// IDs of SVs used in position fix
+ ///
+ public int[] SVs { get; private set; }
+
+ ///
+ /// Dilution of precision
+ ///
+ public double PDop { get; set; }
+
+ ///
+ /// Horizontal dilution of precision
+ ///
+ public double HDop { get; set; }
+
+ ///
+ /// Vertical dilution of precision
+ ///
+ public double VDop { get; set; }
+ }
+}
diff --git a/src/NmeaParser.Shared/Nmea/NmeaMessage.cs b/src/NmeaParser.Shared/Nmea/NmeaMessage.cs
index d3c7a40..32a29e3 100644
--- a/src/NmeaParser.Shared/Nmea/NmeaMessage.cs
+++ b/src/NmeaParser.Shared/Nmea/NmeaMessage.cs
@@ -48,7 +48,7 @@ namespace NmeaParser.Nmea
checksumTest ^= Convert.ToByte(message[i]);
}
if (checksum != checksumTest)
- throw new ArgumentException("Invalid nmea message: Checksum failure");
+ throw new ArgumentException(string.Format("Invalid nmea message: Checksum failure. Got {0:X2}, Expected {1:X2}", checksum, checksumTest));
}
string[] parts = message.Split(new char[] { ',' });
diff --git a/src/NmeaParser.Shared/NmeaParser.Shared.projitems b/src/NmeaParser.Shared/NmeaParser.Shared.projitems
index 5c35b1f..6aae2c1 100644
--- a/src/NmeaParser.Shared/NmeaParser.Shared.projitems
+++ b/src/NmeaParser.Shared/NmeaParser.Shared.projitems
@@ -12,6 +12,7 @@
+
diff --git a/src/NmeaParser.Tests/NmeaMessages.cs b/src/NmeaParser.Tests/NmeaMessages.cs
index 3aa5874..2f1e09a 100644
--- a/src/NmeaParser.Tests/NmeaMessages.cs
+++ b/src/NmeaParser.Tests/NmeaMessages.cs
@@ -147,5 +147,50 @@ namespace NmeaParser.Tests
Assert.AreEqual(4.0, rme.SphericalError);
Assert.AreEqual("M", rme.SphericalErrorUnits);
}
+
+ [TestMethod]
+ public void TestGpgsa_Empty()
+ {
+ string input = "$GPGSA,A,3,,,,,,16,18,,22,24,,,,,*14";
+ var msg = NmeaMessage.Parse(input);
+ Assert.IsInstanceOfType(msg, typeof(Gpgsa));
+ Gpgsa gsa = (Gpgsa)msg;
+ Assert.AreEqual(Gpgsa.ModeSelection.Auto, gsa.GpsMode);
+ Assert.AreEqual(Gpgsa.Mode._3D, gsa.FixMode);
+ Assert.AreEqual(4, gsa.SVs.Length);
+ Assert.AreEqual(16, gsa.SVs[0]);
+ Assert.AreEqual(18, gsa.SVs[1]);
+ Assert.AreEqual(22, gsa.SVs[2]);
+ Assert.AreEqual(24, gsa.SVs[3]);
+ Assert.AreEqual(double.NaN, gsa.PDop);
+ Assert.AreEqual(double.NaN, gsa.HDop);
+ Assert.AreEqual(double.NaN, gsa.VDop);
+ }
+ [TestMethod]
+ public void TestGpgsa()
+ {
+ string input = "$GPGSA,M,2,19,28,14,18,27,22,31,39,40,42,43,44,1.7,1.0,1.3*3C";
+ var msg = NmeaMessage.Parse(input);
+ Assert.IsInstanceOfType(msg, typeof(Gpgsa));
+ Gpgsa gsa = (Gpgsa)msg;
+ Assert.AreEqual(Gpgsa.ModeSelection.Manual, gsa.GpsMode);
+ Assert.AreEqual(Gpgsa.Mode._2D, gsa.FixMode);
+ Assert.AreEqual(12, gsa.SVs.Length);
+ Assert.AreEqual(19, gsa.SVs[0]);
+ Assert.AreEqual(28, gsa.SVs[1]);
+ Assert.AreEqual(14, gsa.SVs[2]);
+ Assert.AreEqual(18, gsa.SVs[3]);
+ Assert.AreEqual(27, gsa.SVs[4]);
+ Assert.AreEqual(22, gsa.SVs[5]);
+ Assert.AreEqual(31, gsa.SVs[6]);
+ Assert.AreEqual(39, gsa.SVs[7]);
+ Assert.AreEqual(40, gsa.SVs[8]);
+ Assert.AreEqual(42, gsa.SVs[9]);
+ Assert.AreEqual(43, gsa.SVs[10]);
+ Assert.AreEqual(44, gsa.SVs[11]);
+ Assert.AreEqual(1.7, gsa.PDop);
+ Assert.AreEqual(1.0, gsa.HDop);
+ Assert.AreEqual(1.3, gsa.VDop);
+ }
}
}