diff --git a/src/NmeaParser/Nmea/Class/Types.cs b/src/NmeaParser/Nmea/Class/Types.cs new file mode 100644 index 00000000..bbf74ee6 --- /dev/null +++ b/src/NmeaParser/Nmea/Class/Types.cs @@ -0,0 +1,197 @@ +namespace NmeaParser.Nmea.Class +{ + /// + /// Data reference in use + /// + public enum Reference + { + /// + /// True + /// + True, + + /// + /// Relative + /// + Relative, + + /// + /// Magnetic + /// + Magnetic, + + /// + /// No data available + /// + NaN + } + + /// + /// Speed reference in use + /// + public enum SpeedReference + { + /// + /// Bottom track + /// + BottomTrack, + + /// + /// Wather track + /// + WatherTrack, + + /// + /// Positioning System + /// + PosSystem, + + /// + /// No data available + /// + NaN + } + + /// + /// Data status + /// + public enum Validation + { + /// + /// Ok + /// + Ok, + + /// + /// Warning + /// + Warning, + + /// + /// Invalid + /// + Invalid, + + /// + /// No data available + /// + NaN + } + + /// + /// Unit + /// + public enum Unit + { + /// + /// Km/h + /// + Kmh, + + /// + /// Meter + /// + M, + + /// + /// Meters per second + /// + Msec, + + /// + /// Miles + /// + Mile, + + /// + /// Knot + /// + Knot, + + /// + /// Inches of mercury + /// + Inc, + + /// + /// Barometric pressure, bars + /// + Bar, + + /// + /// Air temperature, degrees C + /// + C, + + /// + /// Degrees + /// + Degrees, + + /// + /// Newtons + /// + Newtons, + + /// + /// Percent + /// + Percent, + + /// + /// No data available + /// + NaN + } + + /// + /// TransducerTypes + /// + public enum TransducerTypes + { + /// + /// Angular displacement + /// + AngularDisplacement, + + /// + /// Temperature + /// + Temperature, + + /// + /// Depth + /// + Depth, + + /// + /// Frequency + /// + Frequency, + + /// + /// Humidity + /// + Humidity, + + /// + /// Force + /// + Force, + + /// + /// Pressure + /// + Pressure, + + /// + /// Flow + /// + Flow, + + /// + /// No data available + /// + NaN + } +} \ No newline at end of file diff --git a/src/NmeaParser/Nmea/Cur.cs b/src/NmeaParser/Nmea/Cur.cs new file mode 100644 index 00000000..ffe34b0e --- /dev/null +++ b/src/NmeaParser/Nmea/Cur.cs @@ -0,0 +1,153 @@ +// ******************************************************************************* +// * Licensed under the Apache License, Version 2.0 (the "License"); +// * you may not use this file except in compliance with the License. +// * You may obtain a copy of the License at +// * +// * http://www.apache.org/licenses/LICENSE-2.0 +// * +// * 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.Diagnostics.CodeAnalysis; +using System.Globalization; +using NmeaParser.Nmea.Class; + +namespace NmeaParser.Messages +{ + /// + /// Water Current Layer + /// + /// + /// + /// 1.: Validity of the data, A= Valid, V= not valid + /// 2.: Data set number, 0 to 9 + /// 3.: Layer number + /// 4.: Current depth in meters + /// 5.: Current direction in degrees + /// 6.: Direction reference in use, True/Relative T/R + /// 7.: Current Speed in Knots + /// 8.: Reference layer depth in meters + /// 9.: Heading + /// 10.:Heading reference in use, True/Magnetic T/M + /// 11.:Speed reference, B : Bottom track, W: Water track, P : Positioning System + /// + /// + [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "StCur")] + [NmeaMessageType("--CUR")] + public class Cur : NmeaMessage + { + /// + /// Initializes a new instance of the class. + /// + /// The message type + /// The NMEA message values. + public Cur(string type, string[] message) : base(type, message) + { + if (message == null || message.Length < 9) + throw new ArgumentException("Invalid Cur", "message"); + + Validation = message[0] == "A" ? Validation.Ok : Validation.Warning; + + DataSetNo = double.TryParse(message[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var tmp) + ? tmp + : double.NaN; + + LayerNo = double.TryParse(message[2], NumberStyles.Float, CultureInfo.InvariantCulture, out tmp) + ? tmp + : double.NaN; + + CurrentDepthMeter = double.TryParse(message[3], NumberStyles.Float, CultureInfo.InvariantCulture, out tmp) + ? tmp + : double.NaN; + + CurrentDirDeg = double.TryParse(message[4], NumberStyles.Float, CultureInfo.InvariantCulture, out tmp) + ? tmp + : double.NaN; + + DirectionRefInUse = + message[5] == "T" ? Reference.True : Reference.Relative; + + CurrentSpeedKnots = double.TryParse(message[6], NumberStyles.Float, CultureInfo.InvariantCulture, out tmp) + ? tmp + : double.NaN; + + RefLayerDepthMeters = double.TryParse(message[7], NumberStyles.Float, CultureInfo.InvariantCulture, out tmp) + ? tmp + : double.NaN; + + Heading = double.TryParse(message[8], NumberStyles.Float, CultureInfo.InvariantCulture, out tmp) + ? tmp + : double.NaN; + + HeadingRefInUse = message[9] == "T" ? Reference.True : Reference.Magnetic; + + SpeedRefInUse = message[10] switch + { + "B" => SpeedReference.BottomTrack, + "W" => SpeedReference.WatherTrack, + "P" => SpeedReference.PosSystem, + _ => SpeedRefInUse + }; + } + + /// + /// Data Validation + /// + public Validation Validation { get; } + + /// + /// Data set number, 0 to 9 + /// + public double DataSetNo { get; } + + /// + /// Layer number + /// + public double LayerNo { get; } + + /// + /// Current depth in meters + /// + public double CurrentDepthMeter { get; } + + /// + /// Current direction in degrees + /// + public double CurrentDirDeg { get; } + + /// + /// Direction reference in use, True/Relative T/R + /// + public Reference DirectionRefInUse { get; } + + /// + /// Range to destination in nautical miles + /// + public double CurrentSpeedKnots { get; } + + /// + /// Reference layer depth in meters + /// + public double RefLayerDepthMeters { get; } + + /// + /// Heading + /// + public double Heading { get; } + + /// + /// Heading reference in use, True/Magnetic T/M + /// + public Reference HeadingRefInUse { get; } + + /// + /// Speed reference, B : Bottom track, W: Water track, P : Positioning System + /// + public SpeedReference SpeedRefInUse { get; } + } +} \ No newline at end of file diff --git a/src/NmeaParser/Nmea/Hdt.cs b/src/NmeaParser/Nmea/Hdt.cs new file mode 100644 index 00000000..dca564d1 --- /dev/null +++ b/src/NmeaParser/Nmea/Hdt.cs @@ -0,0 +1,64 @@ +// ******************************************************************************* +// * Licensed under the Apache License, Version 2.0 (the "License"); +// * you may not use this file except in compliance with the License. +// * You may obtain a copy of the License at +// * +// * http://www.apache.org/licenses/LICENSE-2.0 +// * +// * 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.Diagnostics.CodeAnalysis; +using System.Globalization; + +namespace NmeaParser.Messages +{ + /// + /// Heading from True North + /// + /// + /// + /// 1.: Heading in degrees + /// 2.: Indicates heading relative to True North + /// + /// + /// Actual vessel heading in degrees True produced by any device or system producing true heading + /// + /// + [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "HeHdt")] + [NmeaMessageType("--HDT")] + public class Hdt : NmeaMessage + { + /// + /// + /// + /// + /// + /// + public Hdt(string type, string[] message) : base(type, message) + { + if (message == null || message.Length < 2) + throw new ArgumentException("Invalid Hdt", "message"); + + HeadingInDeg = double.TryParse(message[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var tmp) + ? tmp + : double.NaN; + HeadingRelToTrueNorth = message[1] == "T"; + } + + /// + /// Heading in degrees + /// + public double HeadingInDeg { get; } + + /// + /// Indicates heading relative to True North + /// + public bool HeadingRelToTrueNorth { get; } + } +} \ No newline at end of file diff --git a/src/NmeaParser/Nmea/Mda.cs b/src/NmeaParser/Nmea/Mda.cs new file mode 100644 index 00000000..edd9e084 --- /dev/null +++ b/src/NmeaParser/Nmea/Mda.cs @@ -0,0 +1,221 @@ +// ******************************************************************************* +// * Licensed under the Apache License, Version 2.0 (the "License"); +// * you may not use this file except in compliance with the License. +// * You may obtain a copy of the License at +// * +// * http://www.apache.org/licenses/LICENSE-2.0 +// * +// * 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.Diagnostics.CodeAnalysis; +using System.Globalization; +using NmeaParser.Nmea.Class; + +namespace NmeaParser.Messages +{ + /// + /// Meteorological Composite. + /// + /// + /// + /// 1.: Barometric pressure, inches of mercury, to the nearest 0.01 inch + /// 2.: I = inches of mercury + /// 3.: Barometric pressure, bars, to the nearest .001 bar + /// 4.: B = bars + /// 5.: Air temperature, degrees C, to the nearest 0.1 degree C + /// 6.: C = degrees C + /// 7.: Water temperature, degrees C (this field left blank by WeatherStation) + /// 8.: C = degrees C(this field left blank by WeatherStation) + /// 9.: Relative humidity, percent, to the nearest 0.1 percent + /// 10.:Absolute humidity, percent(this field left blank by WeatherStation) + /// 11.:Dew point, degrees C, to the nearest 0.1 degree C + /// 12.:C = degrees C + /// 13.:Wind direction, degrees True, to the nearest 0.1 degree + /// 14.:T = true + /// 15.:Wind direction, degrees Magnetic, to the nearest 0.1 degree + /// 16.:M = magnetic + /// 17.:Wind speed, knots, to the nearest 0.1 knot + /// 18.:N = knots + /// 19.:Wind speed, meters per second, to the nearest 0.1 m/s + /// 20.:M = meters per second + /// + /// + /// Barometric pressure, air and water temperature, humidity, dew point and wind speed and direction relative to the surface of the earth. + /// + /// + /// + [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "GpMda")][NmeaMessageType("--MDA")] + public class Mda : NmeaMessage + { + /// + /// Initializes a new instance of the class. + /// + /// The message type + /// The NMEA message values. + public Mda(string type, string[] message) : base(type, message) + { + if (message == null || message.Length < 20) + throw new ArgumentException("Invalid Mda", "message"); + + BarometricPresI = double.TryParse(message[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var tmp) + ? tmp + : double.NaN; + BarometricPresIUnit = message[1] == "I" ? Unit.Inc : Unit.NaN; + + BarometricPresBar = double.TryParse(message[2], NumberStyles.Float, CultureInfo.InvariantCulture, out tmp) + ? tmp + : double.NaN; + BarometricPresBarUnit = message[3] == "B" ? Unit.Bar : Unit.NaN; + + AirTemp = double.TryParse(message[4], NumberStyles.Float, CultureInfo.InvariantCulture, out tmp) + ? tmp + : double.NaN; + AirTempUnit = message[5] == "C" ? Unit.C : Unit.NaN; + + WaterTemp = double.TryParse(message[6], NumberStyles.Float, CultureInfo.InvariantCulture, out tmp) + ? tmp + : double.NaN; + WaterTempUnit = message[7] == "C" ? Unit.C : Unit.NaN; + + RelativeHumidity = double.TryParse(message[8], NumberStyles.Float, CultureInfo.InvariantCulture, out tmp) + ? tmp + : double.NaN; + AbsoluteHumidity = double.TryParse(message[9], NumberStyles.Float, CultureInfo.InvariantCulture, out tmp) + ? tmp + : double.NaN; + + DewPoint = double.TryParse(message[10], NumberStyles.Float, CultureInfo.InvariantCulture, out tmp) + ? tmp + : double.NaN; + DewPointUnit = message[11] == "C" ? Unit.C : Unit.NaN; + + WindDirTrue = double.TryParse(message[12], NumberStyles.Float, CultureInfo.InvariantCulture, out tmp) + ? tmp + : double.NaN; + WindDirTrueReference = message[13] == "T" ? Reference.True : Reference.NaN; + + WindDirMag = double.TryParse(message[14], NumberStyles.Float, CultureInfo.InvariantCulture, out tmp) + ? tmp + : double.NaN; + WindDirMegReference = message[15] == "M" ? Reference.Magnetic : Reference.NaN; + + WindSpeedKnot = double.TryParse(message[16], NumberStyles.Float, CultureInfo.InvariantCulture, out tmp) + ? tmp + : double.NaN; + WindSpeedKnotUnit = message[17] == "N" ? Unit.Knot : Unit.NaN; + + WindSpeedMsec = double.TryParse(message[18], NumberStyles.Float, CultureInfo.InvariantCulture, out tmp) + ? tmp + : double.NaN; + WindSpeedMsecUnit = message[19] == "M" ? Unit.Msec : Unit.NaN; + + } + + /// + /// Barometric pressure, inches of mercury, to the nearest 0.01 inch + /// + public double BarometricPresI { get; } + + /// + /// Barometric pressure I = inches of mercury + /// + public Unit BarometricPresIUnit { get; } + + /// + /// Barometric pressure, bars, to the nearest .001 bar + /// + public double BarometricPresBar { get; } + + /// + /// Barometric pressure, bars, to the nearest .001 bar = bar + /// + public Unit BarometricPresBarUnit { get; } + + /// + /// Air temperature, degrees C, to the nearest 0.1 degree C + /// + public double AirTemp { get; } + + /// + /// Air temperature, degrees C, to the nearest 0.1 degree C C = degrees C + /// + public Unit AirTempUnit { get; } + + /// + /// Water temperature, degrees C (this field left blank by WeatherStation) + /// + public double WaterTemp { get; } + + /// + /// Water temperature, degrees C (this field left blank by WeatherStation) C = degrees C (this field left blank by WeatherStation) + /// + public Unit WaterTempUnit { get; } + + /// + /// Relative humidity, percent, to the nearest 0.1 percent + /// + public double RelativeHumidity { get; } + + /// + /// Absolute humidity, percent (this field left blank by WeatherStation) + /// + public double AbsoluteHumidity { get; } + + /// + /// Dew point, degrees C, to the nearest 0.1 degree C + /// + public double DewPoint { get; } + + /// + /// Dew point, degrees C, to the nearest 0.1 degree C C = degrees C + /// + public Unit DewPointUnit { get; } + + /// + /// Wind direction, degrees True, to the nearest 0.1 degree + /// + public double WindDirTrue { get; } + + /// + /// Wind direction, degrees True, to the nearest 0.1 degree Reference, R = Relative, T = True + /// + public Reference WindDirTrueReference { get; } + + /// + /// Wind direction, degrees Magnetic, to the nearest 0.1 degree + /// + public double WindDirMag { get; } + + /// + /// Wind direction, degrees True, to the nearest 0.1 degree Reference, R = Relative, T = True + /// + public Reference WindDirMegReference { get; } + + /// + /// Wind Speed N = knots + /// + public double WindSpeedKnot { get; } + + /// + /// Wind Speed Units, N = knots + /// + public Unit WindSpeedKnotUnit { get; } + + /// + /// Wind Speed M = meters per second + /// + public double WindSpeedMsec { get; } + + /// + /// Wind Speed Units, M = meters per second + /// + public Unit WindSpeedMsecUnit { get; } + } +} + diff --git a/src/NmeaParser/Nmea/Mwv.cs b/src/NmeaParser/Nmea/Mwv.cs new file mode 100644 index 00000000..b20aaab7 --- /dev/null +++ b/src/NmeaParser/Nmea/Mwv.cs @@ -0,0 +1,96 @@ +// ******************************************************************************* +// * Licensed under the Apache License, Version 2.0 (the "License"); +// * you may not use this file except in compliance with the License. +// * You may obtain a copy of the License at +// * +// * http://www.apache.org/licenses/LICENSE-2.0 +// * +// * 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.Diagnostics.CodeAnalysis; +using System.Globalization; +using NmeaParser.Nmea.Class; + +namespace NmeaParser.Messages +{ + /// + /// Relative (Apparent) Wind Speed and Angle + /// + /// + /// + /// 1.: Wind Angle, 0 to 360 degrees + /// 2.: Reference, R = Relative, T = True + /// 3.: Wind Speed + /// 4.: Wind Speed Units, K/M/N + /// 5.: Validation, A = Data Valid + /// 6.: Checksum + /// + /// + /// Wind angle in relation to the vessel's heading and wind speed measured relative to the moving vessel + /// + /// + /// + [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "GpMwv")][NmeaMessageType("--MWV")] + public class Mwv : NmeaMessage + { + /// + /// Initializes a new instance of the class. + /// + /// The message type + /// The NMEA message values. + public Mwv(string type, string[] message) : base(type, message) + { + if (message == null || message.Length < 5) + throw new ArgumentException("Invalid Mwv", "message"); + + WindAngle = double.TryParse(message[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var tmp) + ? tmp + : double.NaN; + Reference = message[1] == "R" ? Reference.Relative : Reference.True; + + WindSpeed = double.TryParse(message[2], NumberStyles.Float, CultureInfo.InvariantCulture, out tmp) + ? tmp + : double.NaN; + + WindSpeedUnit = message[3] switch + { + "K" => Unit.Kmh, + "M" => Unit.Mile, + "N" => Unit.Knot, + _ => WindSpeedUnit + }; + Validation = message[4] == "A" ? Validation.Ok : Validation.Warning; + } + + /// + /// Wind Angle, 0 to 360 degrees + /// + public double WindAngle { get; } + + /// + /// Reference, R = Relative, T = True + /// + public Reference Reference { get; } + + /// + /// Wind Speed + /// + public double WindSpeed { get; } + + /// + /// Wind Speed Units, K/M/N + /// + public Unit WindSpeedUnit { get; } + + /// + /// Validation, A = Data Valid + /// + public Validation Validation { get; } + } +} \ No newline at end of file diff --git a/src/NmeaParser/Nmea/Rot.cs b/src/NmeaParser/Nmea/Rot.cs new file mode 100644 index 00000000..7b3f7d61 --- /dev/null +++ b/src/NmeaParser/Nmea/Rot.cs @@ -0,0 +1,66 @@ +// ******************************************************************************* +// * Licensed under the Apache License, Version 2.0 (the "License"); +// * you may not use this file except in compliance with the License. +// * You may obtain a copy of the License at +// * +// * http://www.apache.org/licenses/LICENSE-2.0 +// * +// * 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.Diagnostics.CodeAnalysis; +using System.Globalization; +using NmeaParser.Nmea.Class; + +namespace NmeaParser.Messages +{ + /// + /// Rate and direction of turn + /// + /// + /// + /// 1.: Rate of turn, degrees/minute, "-" = bow turns to port + /// 2.: Status A = Data valid, V = Data invalid + /// + /// + /// Rate of turn and direction of turn. + /// + /// and are the recommended minimum data to be provided by a GNSS receiver. + /// + /// + [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "GpRot")][NmeaMessageType("--ROT")] + public class Rot : NmeaMessage + { + /// + /// Initializes a new instance of the class. + /// + /// The message type + /// The NMEA message values. + public Rot(string type, string[] message) : base(type, message) + { + if (message == null || message.Length < 2) + throw new ArgumentException("Invalid Rot", "message"); + + RateOfTurn = double.TryParse(message[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var tmp) + ? tmp + : double.NaN; + Validation = message[1] == "A" ? Validation.Ok : Validation.Warning; + } + + /// + /// Rate of turn, degrees/minutes, “–” indicates bow turns to port + /// + public double RateOfTurn { get; } + + /// + /// Status A = Data valid, V = Data invalid + /// + public Validation Validation { get; } + } +} + diff --git a/src/NmeaParser/NmeaParser.csproj b/src/NmeaParser/NmeaParser.csproj index f2fae536..43082e1f 100644 --- a/src/NmeaParser/NmeaParser.csproj +++ b/src/NmeaParser/NmeaParser.csproj @@ -1,7 +1,7 @@  - netstandard2.0;netstandard1.4;netcoreapp2.1;net451;monoandroid50;monoandroid70;xamarinios10;uap10.0.16299 + netstandard2.0;netstandard1.4;netcoreapp2.1;net451;uap10.0.16299 true true Debug;Release diff --git a/src/UnitTests/NmeaParser.Tests/NmeaMessages.cs b/src/UnitTests/NmeaParser.Tests/NmeaMessages.cs index 71197210..d375f6d7 100644 --- a/src/UnitTests/NmeaParser.Tests/NmeaMessages.cs +++ b/src/UnitTests/NmeaParser.Tests/NmeaMessages.cs @@ -21,8 +21,10 @@ using NmeaParser.Messages; using System.Threading.Tasks; using System.IO; +using System.IO.MemoryMappedFiles; using Microsoft.VisualStudio.TestTools.UnitTesting; using System.Reflection; +using NmeaParser.Nmea.Class; namespace NmeaParser.Tests { @@ -838,6 +840,71 @@ public void TestGlzda() Assert.AreEqual(new DateTimeOffset(2015, 09, 21, 22, 56, 27, 00, TimeSpan.Zero), zda.FixDateTime); } + [TestMethod] + public void TestHdt() + { + const string input = "$HEHDT,11.8,T*17"; + var msg = NmeaMessage.Parse(input); + Assert.IsInstanceOfType(msg, typeof(Hdt)); + Hdt hdt = (Hdt)msg; + Assert.AreEqual(11.8, hdt.HeadingInDeg); + Assert.IsTrue(hdt.HeadingRelToTrueNorth); + } + + [TestMethod] + public void TestMda() + { + const string input = "$WIMDA,30.3332,I,1.0272,B,5.5,C,1.2,C,22,33,2,C,172.7,T,170.2,M,3.8,N,2.0,M*0F"; + var msg = NmeaMessage.Parse(input); + Assert.IsInstanceOfType(msg, typeof(Mda)); + Mda mda = (Mda)msg; + Assert.AreEqual(30.3332, mda.BarometricPresI); + Assert.AreEqual(Unit.Inc, mda.BarometricPresIUnit); + Assert.AreEqual(1.0272, mda.BarometricPresBar); + Assert.AreEqual(Unit.Bar, mda.BarometricPresBarUnit); + Assert.AreEqual(5.5, mda.AirTemp); + Assert.AreEqual(Unit.C, mda.AirTempUnit); + Assert.AreEqual(1.2, mda.WaterTemp); + Assert.AreEqual(Unit.C, mda.WaterTempUnit); + Assert.AreEqual(22, mda.RelativeHumidity); + Assert.AreEqual(33, mda.AbsoluteHumidity); + Assert.AreEqual(2, mda.DewPoint); + Assert.AreEqual(Unit.C, mda.DewPointUnit); + Assert.AreEqual(172.7, mda.WindDirTrue); + Assert.AreEqual(Reference.True, mda.WindDirTrueReference); + Assert.AreEqual(170.2, mda.WindDirMag); + Assert.AreEqual(Reference.Magnetic, mda.WindDirMegReference); + Assert.AreEqual(3.8, mda.WindSpeedKnot); + Assert.AreEqual(Unit.Knot, mda.WindSpeedKnotUnit); + Assert.AreEqual(2.0, mda.WindSpeedMsec); + Assert.AreEqual(Unit.Msec, mda.WindSpeedMsecUnit); + } + + [TestMethod] + public void TestMwv() + { + const string input = "$WIMWV,132.8,R,1.2,N,A*28"; + var msg = NmeaMessage.Parse(input); + Assert.IsInstanceOfType(msg, typeof(Mwv)); + Mwv mwv = (Mwv)msg; + Assert.AreEqual(132.8, mwv.WindAngle); + Assert.AreEqual(Reference.Relative, mwv.Reference); + Assert.AreEqual(1.2, mwv.WindSpeed); + Assert.AreEqual(Unit.Knot, mwv.WindSpeedUnit); + Assert.AreEqual(Validation.Ok, mwv.Validation); + } + + [TestMethod] + public void TestRot() + { + const string input = "$TIROT,1.69,A*05"; + var msg = NmeaMessage.Parse(input); + Assert.IsInstanceOfType(msg, typeof(Rot)); + Rot rot = (Rot)msg; + Assert.AreEqual(1.69, rot.RateOfTurn); + Assert.AreEqual(Validation.Ok,rot.Validation); + } + [TestMethod] public void TestCustomMessageRegistration() {