From 0f850eb64963f73e483cfeb6a67f818c07911d59 Mon Sep 17 00:00:00 2001 From: josh-dadswell-hackney Date: Fri, 6 May 2022 22:51:31 +0100 Subject: [PATCH 1/3] Add Timestamp from NMEA message to each message type --- .../Features/AisMessageType18.feature.cs | 14 +++---- .../Net/Models/Abstractions/IAisMessage.cs | 2 +- .../Ais/Net/Models/Abstractions/ITimestamp.cs | 6 +++ .../Ais/Net/Models/AisMessageBase.cs | 2 +- .../Ais/Net/Models/AisMessageType18.cs | 5 ++- .../Ais/Net/Models/AisMessageType19.cs | 5 ++- .../Ais/Net/Models/AisMessageType1Through3.cs | 5 ++- .../Ais/Net/Models/AisMessageType24Part0.cs | 5 ++- .../Ais/Net/Models/AisMessageType24Part1.cs | 5 ++- .../Ais/Net/Models/AisMessageType5.cs | 5 ++- .../Parser/NmeaToAisMessageTypeProcessor.cs | 38 +++++++++++-------- 11 files changed, 55 insertions(+), 37 deletions(-) create mode 100644 Solutions/Ais.Net.Models/Ais/Net/Models/Abstractions/ITimestamp.cs diff --git a/Solutions/Ais.Net.Models.Specs/Features/AisMessageType18.feature.cs b/Solutions/Ais.Net.Models.Specs/Features/AisMessageType18.feature.cs index abd29f7..97f7296 100644 --- a/Solutions/Ais.Net.Models.Specs/Features/AisMessageType18.feature.cs +++ b/Solutions/Ais.Net.Models.Specs/Features/AisMessageType18.feature.cs @@ -26,7 +26,7 @@ public partial class AisMessageType18Feature private TechTalk.SpecFlow.ITestRunner testRunner; - private string[] _featureTags = ((string[])(null)); + private static string[] featureTags = ((string[])(null)); #line 1 "AisMessageType18.feature" #line hidden @@ -35,7 +35,7 @@ public partial class AisMessageType18Feature public virtual void FeatureSetup() { testRunner = TechTalk.SpecFlow.TestRunnerManager.GetTestRunner(); - TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Features", "AisMessageType18", null, ProgrammingLanguage.CSharp, ((string[])(null))); + TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Features", "AisMessageType18", null, ProgrammingLanguage.CSharp, featureTags); testRunner.OnFeatureStart(featureInfo); } @@ -47,28 +47,28 @@ public virtual void FeatureTearDown() } [NUnit.Framework.SetUpAttribute()] - public virtual void TestInitialize() + public void TestInitialize() { } [NUnit.Framework.TearDownAttribute()] - public virtual void TestTearDown() + public void TestTearDown() { testRunner.OnScenarioEnd(); } - public virtual void ScenarioInitialize(TechTalk.SpecFlow.ScenarioInfo scenarioInfo) + public void ScenarioInitialize(TechTalk.SpecFlow.ScenarioInfo scenarioInfo) { testRunner.OnScenarioInitialize(scenarioInfo); testRunner.ScenarioContext.ScenarioContainer.RegisterInstanceAs(NUnit.Framework.TestContext.CurrentContext); } - public virtual void ScenarioStart() + public void ScenarioStart() { testRunner.OnScenarioStart(); } - public virtual void ScenarioCleanup() + public void ScenarioCleanup() { testRunner.CollectScenarioErrors(); } diff --git a/Solutions/Ais.Net.Models/Ais/Net/Models/Abstractions/IAisMessage.cs b/Solutions/Ais.Net.Models/Ais/Net/Models/Abstractions/IAisMessage.cs index 1be37c8..2b1a6db 100644 --- a/Solutions/Ais.Net.Models/Ais/Net/Models/Abstractions/IAisMessage.cs +++ b/Solutions/Ais.Net.Models/Ais/Net/Models/Abstractions/IAisMessage.cs @@ -4,7 +4,7 @@ namespace Ais.Net.Models.Abstractions { - public interface IAisMessage : IVesselIdentity, IAisMessageType + public interface IAisMessage : IVesselIdentity, IAisMessageType, ITimestamp { } } \ No newline at end of file diff --git a/Solutions/Ais.Net.Models/Ais/Net/Models/Abstractions/ITimestamp.cs b/Solutions/Ais.Net.Models/Ais/Net/Models/Abstractions/ITimestamp.cs new file mode 100644 index 0000000..861a541 --- /dev/null +++ b/Solutions/Ais.Net.Models/Ais/Net/Models/Abstractions/ITimestamp.cs @@ -0,0 +1,6 @@ +namespace Ais.Net.Models.Abstractions; + +public interface ITimestamp +{ + public long? UnixTimestamp { get; } +} \ No newline at end of file diff --git a/Solutions/Ais.Net.Models/Ais/Net/Models/AisMessageBase.cs b/Solutions/Ais.Net.Models/Ais/Net/Models/AisMessageBase.cs index f3dadf5..5420ac9 100644 --- a/Solutions/Ais.Net.Models/Ais/Net/Models/AisMessageBase.cs +++ b/Solutions/Ais.Net.Models/Ais/Net/Models/AisMessageBase.cs @@ -6,5 +6,5 @@ namespace Ais.Net.Models { using Ais.Net.Models.Abstractions; - public record AisMessageBase(int MessageType, uint Mmsi) : IAisMessage; + public record AisMessageBase(int MessageType, uint Mmsi, long? UnixTimestamp) : IAisMessage; } \ No newline at end of file diff --git a/Solutions/Ais.Net.Models/Ais/Net/Models/AisMessageType18.cs b/Solutions/Ais.Net.Models/Ais/Net/Models/AisMessageType18.cs index d5ec527..6e6295f 100644 --- a/Solutions/Ais.Net.Models/Ais/Net/Models/AisMessageType18.cs +++ b/Solutions/Ais.Net.Models/Ais/Net/Models/AisMessageType18.cs @@ -24,8 +24,9 @@ public record AisMessageType18( uint RepeatIndicator, float? SpeedOverGround, uint TimeStampSecond, - uint TrueHeadingDegrees) : - AisMessageBase(MessageType: 18, Mmsi), + uint TrueHeadingDegrees, + long? UnixTimestamp) : + AisMessageBase(MessageType: 18, Mmsi, UnixTimestamp), IAisMessageType18, IAisIsAssigned, IRaimFlag, diff --git a/Solutions/Ais.Net.Models/Ais/Net/Models/AisMessageType19.cs b/Solutions/Ais.Net.Models/Ais/Net/Models/AisMessageType19.cs index 45f2796..b06d98c 100644 --- a/Solutions/Ais.Net.Models/Ais/Net/Models/AisMessageType19.cs +++ b/Solutions/Ais.Net.Models/Ais/Net/Models/AisMessageType19.cs @@ -27,8 +27,9 @@ public record AisMessageType19( uint Spare308, float? SpeedOverGround, uint TimeStampSecond, - uint TrueHeadingDegrees) : - AisMessageBase(MessageType: 19, Mmsi), + uint TrueHeadingDegrees, + long? UnixTimestamp) : + AisMessageBase(MessageType: 19, Mmsi, UnixTimestamp), IAisMessageType19, IAisIsAssigned, IAisIsDteNotReady, diff --git a/Solutions/Ais.Net.Models/Ais/Net/Models/AisMessageType1Through3.cs b/Solutions/Ais.Net.Models/Ais/Net/Models/AisMessageType1Through3.cs index 718431c..2e975df 100644 --- a/Solutions/Ais.Net.Models/Ais/Net/Models/AisMessageType1Through3.cs +++ b/Solutions/Ais.Net.Models/Ais/Net/Models/AisMessageType1Through3.cs @@ -23,8 +23,9 @@ public record AisMessageType1Through3( uint SpareBits145, float? SpeedOverGround, uint TimeStampSecond, - uint TrueHeadingDegrees) : - AisMessageBase(MessageType, Mmsi), + uint TrueHeadingDegrees, + long? UnixTimestamp) : + AisMessageBase(MessageType, Mmsi, UnixTimestamp), IAisMessageType1to3, IRaimFlag, IRepeatIndicator, diff --git a/Solutions/Ais.Net.Models/Ais/Net/Models/AisMessageType24Part0.cs b/Solutions/Ais.Net.Models/Ais/Net/Models/AisMessageType24Part0.cs index d57748b..3e9cf1b 100644 --- a/Solutions/Ais.Net.Models/Ais/Net/Models/AisMessageType24Part0.cs +++ b/Solutions/Ais.Net.Models/Ais/Net/Models/AisMessageType24Part0.cs @@ -10,8 +10,9 @@ public record AisMessageType24Part0( uint Mmsi, uint PartNumber, uint RepeatIndicator, - uint Spare160) : - AisMessageBase(MessageType: 24, Mmsi), + uint Spare160, + long? UnixTimestamp) : + AisMessageBase(MessageType: 24, Mmsi, UnixTimestamp), IAisMultipartMessage, IRepeatIndicator, IAisMessageType24Part0; diff --git a/Solutions/Ais.Net.Models/Ais/Net/Models/AisMessageType24Part1.cs b/Solutions/Ais.Net.Models/Ais/Net/Models/AisMessageType24Part1.cs index 86bc85d..fcdcdb7 100644 --- a/Solutions/Ais.Net.Models/Ais/Net/Models/AisMessageType24Part1.cs +++ b/Solutions/Ais.Net.Models/Ais/Net/Models/AisMessageType24Part1.cs @@ -21,8 +21,9 @@ public record AisMessageType24Part1( ShipType ShipType, uint UnitModelCode, string VendorIdRev3, - string VendorIdRev4) : - AisMessageBase(MessageType: 24, Mmsi), + string VendorIdRev4, + long? UnixTimestamp) : + AisMessageBase(MessageType: 24, Mmsi, UnixTimestamp), IAisMessageType24Part1, IAisMultipartMessage, ICallSign, diff --git a/Solutions/Ais.Net.Models/Ais/Net/Models/AisMessageType5.cs b/Solutions/Ais.Net.Models/Ais/Net/Models/AisMessageType5.cs index a9c2d19..ca4db07 100644 --- a/Solutions/Ais.Net.Models/Ais/Net/Models/AisMessageType5.cs +++ b/Solutions/Ais.Net.Models/Ais/Net/Models/AisMessageType5.cs @@ -26,8 +26,9 @@ public record AisMessageType5( uint RepeatIndicator, ShipType ShipType, uint Spare423, - string VesselName) : - AisMessageBase(MessageType: 5, Mmsi), + string VesselName, + long? UnixTimestamp) : + AisMessageBase(MessageType: 5, Mmsi, UnixTimestamp), IAisMessageType5, IAisIsDteNotReady, IAisPositionFixType, diff --git a/Solutions/Ais.Net.Receiver/Ais/Net/Receiver/Parser/NmeaToAisMessageTypeProcessor.cs b/Solutions/Ais.Net.Receiver/Ais/Net/Receiver/Parser/NmeaToAisMessageTypeProcessor.cs index 8799176..3470605 100644 --- a/Solutions/Ais.Net.Receiver/Ais/Net/Receiver/Parser/NmeaToAisMessageTypeProcessor.cs +++ b/Solutions/Ais.Net.Receiver/Ais/Net/Receiver/Parser/NmeaToAisMessageTypeProcessor.cs @@ -30,31 +30,31 @@ public void OnNext(in NmeaLineParser parsedLine, in ReadOnlySpan asciiPayl { case >= 1 and <= 3: { - this.ParseMessageTypes1Through3(asciiPayload, padding, messageType); + this.ParseMessageTypes1Through3(parsedLine, asciiPayload, padding, messageType); return; } case 5: { - this.ParseMessageType5(asciiPayload, padding); + this.ParseMessageType5(parsedLine, asciiPayload, padding); return; } case 18: { - this.ParseMessageType18(asciiPayload, padding); + this.ParseMessageType18(parsedLine, asciiPayload, padding); return; } case 19: { - this.ParseMessageType19(asciiPayload, padding); + this.ParseMessageType19(parsedLine, asciiPayload, padding); return; } case 24: { - this.ParseMessageType24(asciiPayload, padding); + this.ParseMessageType24(parsedLine, asciiPayload, padding); return; } } @@ -87,7 +87,7 @@ public void Progress( throw new NotImplementedException(); } - private void ParseMessageTypes1Through3(ReadOnlySpan asciiPayload, uint padding, int messageType) + private void ParseMessageTypes1Through3(NmeaLineParser nmeaLineParser, ReadOnlySpan asciiPayload, uint padding, int messageType) { var parser = new NmeaAisPositionReportClassAParser(asciiPayload, padding); @@ -108,12 +108,13 @@ private void ParseMessageTypes1Through3(ReadOnlySpan asciiPayload, uint pa SpareBits145: parser.SpareBits145, SpeedOverGround: parser.SpeedOverGroundTenths.FromTenths(), TimeStampSecond: parser.TimeStampSecond, - TrueHeadingDegrees: parser.TrueHeadingDegrees); + TrueHeadingDegrees: parser.TrueHeadingDegrees, + UnixTimestamp: nmeaLineParser.TagBlock.UnixTimestamp); this.messages.OnNext(message); } - private void ParseMessageType5(ReadOnlySpan asciiPayload, uint padding) + private void ParseMessageType5(NmeaLineParser nmeaLineParser, ReadOnlySpan asciiPayload, uint padding) { var parser = new NmeaAisStaticAndVoyageRelatedDataParser(asciiPayload, padding); @@ -137,12 +138,13 @@ private void ParseMessageType5(ReadOnlySpan asciiPayload, uint padding) DimensionToStern: parser.DimensionToStern, Draught10thMetres: parser.Draught10thMetres, Spare423: parser.Spare423, - PositionFixType: parser.PositionFixType); + PositionFixType: parser.PositionFixType, + UnixTimestamp: nmeaLineParser.TagBlock.UnixTimestamp); this.messages.OnNext(message); } - private void ParseMessageType18(ReadOnlySpan asciiPayload, uint padding) + private void ParseMessageType18(NmeaLineParser nmeaLineParser, ReadOnlySpan asciiPayload, uint padding) { var parser = new NmeaAisPositionReportClassBParser(asciiPayload, padding); @@ -164,12 +166,13 @@ private void ParseMessageType18(ReadOnlySpan asciiPayload, uint padding) TrueHeadingDegrees: parser.TrueHeadingDegrees, IsAssigned: parser.IsAssigned, RaimFlag: parser.RaimFlag, - RepeatIndicator: parser.RepeatIndicator); + RepeatIndicator: parser.RepeatIndicator, + UnixTimestamp: nmeaLineParser.TagBlock.UnixTimestamp); this.messages.OnNext(message); } - private void ParseMessageType19(ReadOnlySpan asciiPayload, uint padding) + private void ParseMessageType19(NmeaLineParser nmeaLineParser, ReadOnlySpan asciiPayload, uint padding) { var parser = new NmeaAisPositionReportExtendedClassBParser(asciiPayload, padding); @@ -197,12 +200,13 @@ private void ParseMessageType19(ReadOnlySpan asciiPayload, uint padding) SpeedOverGround: parser.SpeedOverGroundTenths.FromTenths(), TimeStampSecond: parser.TimeStampSecond, TrueHeadingDegrees: parser.TrueHeadingDegrees, - Position: Position.From10000thMins(parser.Latitude10000thMins, parser.Longitude10000thMins)); + Position: Position.From10000thMins(parser.Latitude10000thMins, parser.Longitude10000thMins), + UnixTimestamp: nmeaLineParser.TagBlock.UnixTimestamp); this.messages.OnNext(message); } - private void ParseMessageType24(ReadOnlySpan asciiPayload, uint padding) + private void ParseMessageType24(NmeaLineParser nmeaLineParser, ReadOnlySpan asciiPayload, uint padding) { uint part = NmeaAisStaticDataReportParser.GetPartNumber(asciiPayload, padding); @@ -219,7 +223,8 @@ private void ParseMessageType24(ReadOnlySpan asciiPayload, uint padding) Mmsi: parser.Mmsi, PartNumber: parser.PartNumber, RepeatIndicator: parser.RepeatIndicator, - Spare160: parser.Spare160); + Spare160: parser.Spare160, + UnixTimestamp: nmeaLineParser.TagBlock.UnixTimestamp); this.messages.OnNext(message); break; @@ -253,7 +258,8 @@ private void ParseMessageType24(ReadOnlySpan asciiPayload, uint padding) Spare162: parser.Spare162, UnitModelCode: parser.UnitModelCode, VendorIdRev3: vendorIdRev3Ascii.GetString(), - VendorIdRev4: vendorIdRev4Ascii.GetString()); + VendorIdRev4: vendorIdRev4Ascii.GetString(), + UnixTimestamp: nmeaLineParser.TagBlock.UnixTimestamp); this.messages.OnNext(message); break; From 05f38c8294c82b28d9dd48b054a10cae2d52ad4a Mon Sep 17 00:00:00 2001 From: josh-dadswell-hackney Date: Fri, 6 May 2022 22:56:33 +0100 Subject: [PATCH 2/3] revert mistake --- .../Features/AisMessageType18.feature.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Solutions/Ais.Net.Models.Specs/Features/AisMessageType18.feature.cs b/Solutions/Ais.Net.Models.Specs/Features/AisMessageType18.feature.cs index 97f7296..abd29f7 100644 --- a/Solutions/Ais.Net.Models.Specs/Features/AisMessageType18.feature.cs +++ b/Solutions/Ais.Net.Models.Specs/Features/AisMessageType18.feature.cs @@ -26,7 +26,7 @@ public partial class AisMessageType18Feature private TechTalk.SpecFlow.ITestRunner testRunner; - private static string[] featureTags = ((string[])(null)); + private string[] _featureTags = ((string[])(null)); #line 1 "AisMessageType18.feature" #line hidden @@ -35,7 +35,7 @@ public partial class AisMessageType18Feature public virtual void FeatureSetup() { testRunner = TechTalk.SpecFlow.TestRunnerManager.GetTestRunner(); - TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Features", "AisMessageType18", null, ProgrammingLanguage.CSharp, featureTags); + TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Features", "AisMessageType18", null, ProgrammingLanguage.CSharp, ((string[])(null))); testRunner.OnFeatureStart(featureInfo); } @@ -47,28 +47,28 @@ public virtual void FeatureTearDown() } [NUnit.Framework.SetUpAttribute()] - public void TestInitialize() + public virtual void TestInitialize() { } [NUnit.Framework.TearDownAttribute()] - public void TestTearDown() + public virtual void TestTearDown() { testRunner.OnScenarioEnd(); } - public void ScenarioInitialize(TechTalk.SpecFlow.ScenarioInfo scenarioInfo) + public virtual void ScenarioInitialize(TechTalk.SpecFlow.ScenarioInfo scenarioInfo) { testRunner.OnScenarioInitialize(scenarioInfo); testRunner.ScenarioContext.ScenarioContainer.RegisterInstanceAs(NUnit.Framework.TestContext.CurrentContext); } - public void ScenarioStart() + public virtual void ScenarioStart() { testRunner.OnScenarioStart(); } - public void ScenarioCleanup() + public virtual void ScenarioCleanup() { testRunner.CollectScenarioErrors(); } From d7293213f0400d07e3eafe15d12adeacbdef897b Mon Sep 17 00:00:00 2001 From: josh-dadswell-hackney Date: Wed, 22 Jun 2022 10:22:07 +0100 Subject: [PATCH 3/3] Parse message type 27 --- .../Models/Abstractions/IAisMessageType27.cs | 17 +++++++++++++ .../Ais/Net/Models/Abstractions/Position.cs | 2 ++ .../Ais/Net/Models/AisMessageExtensions.cs | 5 ++++ .../Ais/Net/Models/AisMessageType27.cs | 24 ++++++++++++++++++ .../Parser/NmeaToAisMessageTypeProcessor.cs | 25 +++++++++++++++++++ 5 files changed, 73 insertions(+) create mode 100644 Solutions/Ais.Net.Models/Ais/Net/Models/Abstractions/IAisMessageType27.cs create mode 100644 Solutions/Ais.Net.Models/Ais/Net/Models/AisMessageType27.cs diff --git a/Solutions/Ais.Net.Models/Ais/Net/Models/Abstractions/IAisMessageType27.cs b/Solutions/Ais.Net.Models/Ais/Net/Models/Abstractions/IAisMessageType27.cs new file mode 100644 index 0000000..5d9b04c --- /dev/null +++ b/Solutions/Ais.Net.Models/Ais/Net/Models/Abstractions/IAisMessageType27.cs @@ -0,0 +1,17 @@ +namespace Ais.Net.Models.Abstractions +{ + public interface IAisMessageType27 + { + float? CourseOverGroundDegrees { get; } + + bool NotGnssPosition { get; } + + NavigationStatus NavigationStatus { get; } + + Position? Position { get; } + + bool PositionAccuracy { get; } + + float? SpeedOverGround { get; } + } +} \ No newline at end of file diff --git a/Solutions/Ais.Net.Models/Ais/Net/Models/Abstractions/Position.cs b/Solutions/Ais.Net.Models/Ais/Net/Models/Abstractions/Position.cs index 443423f..0b7a46b 100644 --- a/Solutions/Ais.Net.Models/Ais/Net/Models/Abstractions/Position.cs +++ b/Solutions/Ais.Net.Models/Ais/Net/Models/Abstractions/Position.cs @@ -8,5 +8,7 @@ public record Position(double Latitude, double Longitude) { public static Position From10000thMins(int latitude, int longitude) => new (latitude.From10000thMinsToDegrees(), longitude.From10000thMinsToDegrees()); + public static Position From10thMins(int latitude, int longitude) => + new (latitude.From10thMinsToDegrees(), longitude.From10thMinsToDegrees()); } } \ No newline at end of file diff --git a/Solutions/Ais.Net.Models/Ais/Net/Models/AisMessageExtensions.cs b/Solutions/Ais.Net.Models/Ais/Net/Models/AisMessageExtensions.cs index d85a1a2..07dea59 100644 --- a/Solutions/Ais.Net.Models/Ais/Net/Models/AisMessageExtensions.cs +++ b/Solutions/Ais.Net.Models/Ais/Net/Models/AisMessageExtensions.cs @@ -14,6 +14,11 @@ public static double From10000thMinsToDegrees(this int value) { return value / 600000.0; } + + public static double From10thMinsToDegrees(this int value) + { + return value / 600.0; + } public static float? FromTenths(this uint value) { diff --git a/Solutions/Ais.Net.Models/Ais/Net/Models/AisMessageType27.cs b/Solutions/Ais.Net.Models/Ais/Net/Models/AisMessageType27.cs new file mode 100644 index 0000000..10d81e7 --- /dev/null +++ b/Solutions/Ais.Net.Models/Ais/Net/Models/AisMessageType27.cs @@ -0,0 +1,24 @@ +// +// Copyright (c) Endjin Limited. All rights reserved. +// + +namespace Ais.Net.Models +{ + using Ais.Net.Models.Abstractions; + + public record AisMessageType27( + float? CourseOverGroundDegrees, + bool NotGnssPosition, + uint Mmsi, + NavigationStatus NavigationStatus, + Position? Position, + bool PositionAccuracy, + bool RaimFlag, + uint RepeatIndicator, + float? SpeedOverGround, + long? UnixTimestamp) : + AisMessageBase(MessageType: 27, Mmsi, UnixTimestamp), + IAisMessageType27, + IRaimFlag, + IRepeatIndicator; +} \ No newline at end of file diff --git a/Solutions/Ais.Net.Receiver/Ais/Net/Receiver/Parser/NmeaToAisMessageTypeProcessor.cs b/Solutions/Ais.Net.Receiver/Ais/Net/Receiver/Parser/NmeaToAisMessageTypeProcessor.cs index 3470605..2c56111 100644 --- a/Solutions/Ais.Net.Receiver/Ais/Net/Receiver/Parser/NmeaToAisMessageTypeProcessor.cs +++ b/Solutions/Ais.Net.Receiver/Ais/Net/Receiver/Parser/NmeaToAisMessageTypeProcessor.cs @@ -57,6 +57,12 @@ public void OnNext(in NmeaLineParser parsedLine, in ReadOnlySpan asciiPayl this.ParseMessageType24(parsedLine, asciiPayload, padding); return; } + + case 27: + { + this.ParseMessageType27(parsedLine, asciiPayload, padding); + return; + } } } catch (Exception e) @@ -266,5 +272,24 @@ private void ParseMessageType24(NmeaLineParser nmeaLineParser, ReadOnlySpan asciiPayload, uint padding) + { + var parser = new NmeaAisLongRangeAisBroadcastParser(asciiPayload, padding); + + var message = new AisMessageType27( + Mmsi: parser.Mmsi, + Position: Position.From10thMins(parser.Latitude10thMins, parser.Longitude10thMins), + CourseOverGroundDegrees: parser.CourseOverGroundDegrees, + PositionAccuracy: parser.PositionAccuracy, + SpeedOverGround: parser.SpeedOverGroundTenths.FromTenths(), + RaimFlag: parser.RaimFlag, + RepeatIndicator: parser.RepeatIndicator, + NotGnssPosition: parser.NotGnssPosition, + NavigationStatus: parser.NavigationStatus, + UnixTimestamp: nmeaLineParser.TagBlock.UnixTimestamp); + + this.messages.OnNext(message); + } } } \ No newline at end of file