/// <summary> /// </summary> /// <param name="sixState"></param> /// <exception cref="SixbitsExhaustedException"></exception> /// <exception cref="AisMessageException"></exception> public override void Parse(Sixbit sixState) { if (sixState.BitLength != 168) { throw new AisMessageException($"Message {MsgId} wrong length"); } base.Parse(sixState); /* Parse the Message 1 */ NavStatus = (int)sixState.Get(4); Rot = (int)sixState.Get(8); Sog = (int)sixState.Get(10); PosAcc = (int)sixState.Get(1); Pos = new Position { Longitude = sixState.Get(28), Latitude = sixState.Get(27) }; Cog = (int)sixState.Get(12); TrueHeading = (int)sixState.Get(9); UtcSec = (int)sixState.Get(6); Regional = (int)sixState.Get(4); Spare = (int)sixState.Get(1); Raim = (int)sixState.Get(1); SyncState = (int)sixState.Get(2); }
/// <summary> /// Assemble AIVDM/VDO sentences /// This function handles re-assembly and extraction of the 6-bit data /// from AIVDM/AIVDO sentences. /// Because the NMEA standard limits the length of a line to 80 characters /// some AIS messages, such as message 5, are output as a multipart VDM /// messages. /// This routine collects the 6-bit encoded data from these parts and /// returns a 1 when all pieces have been reassembled. /// It expects the sentences to: /// - Be in order, part 1, part 2, etc. /// - Be from a single sequence /// It will return an error if it receives a piece out of order or from /// a new sequence before the previous one is finished. /// </summary> /// <returns> /// - 0 Complete packet /// - 1 Incomplete packet /// - 2 NMEA 0183 checksum failed /// - 3 Not an AIS message /// - 4 Error with nmea_next_field /// - 5 Out of sequence packet /// </returns> /// <exception cref="ChecksumFailedException"></exception> /// <exception cref="StartNotFoundException"></exception> /// <exception cref="VDMSentenceException"></exception> public VdmStatus Add(string str) { int total; int num; int sequence; if (Nmea.CheckChecksum(str) != 0) { throw new ChecksumFailedException(); } var ptr = Nmea.FindStart(str); // Allow any sender type for VDM and VDO messages //if (!str.regionMatches(ptr + 3, "VDM", 0, 3) && !str.regionMatches(ptr + 3, "VDO", 0, 3)) var tag = str.Substring(ptr + 3, 3); if (!tag.Equals("VDM") && !tag.Equals("VDO")) { throw new VDMSentenceException("Not a VDM or VDO message"); } var fields = FieldSpliter.Split(str); //str.Split(",|\\*", true); if (fields.Length != 8) { throw new VDMSentenceException("Does not have 8 fields"); } // Get the message info for multipart messages try { total = int.Parse(fields[1]); num = int.Parse(fields[2]); } catch (FormatException) { throw new VDMSentenceException("total or num field is not an integer"); } if (!int.TryParse(fields[3], out sequence)) { sequence = 0; } // Are we looking for more message parts? if (Total > 0) { if (Sequence != sequence || Num != num - 1) { Total = 0; Sequence = 0; Num = 0; return((VdmStatus)5); //throw new VDMSentenceException("Out of sequence sentence"); } Num++; } else { Total = total; Num = num; Sequence = sequence; SixState = new Sixbit(); } Channel = fields[4].FirstOrDefault();//[0]; SixState.Add(fields[5]); if (total == 0 || Total == num) { Total = 0; Num = 0; Sequence = 0; // Get the message id try { MsgId = (int)SixState.Get(6); } catch (SixbitsExhaustedException) { throw new VDMSentenceException("Not enough bits for msgid"); } // Adjust bit count SixState.PadBits(int.Parse(fields[6])); // Found a complete packet return(0); } // No complete message yet return((VdmStatus)1); }