using System; using System.Collections.Generic; using System.Text; using log4net; namespace bsmd.AIS2Service { internal abstract class NMEA { protected string type = ""; protected string _data; protected string[] elements = null; protected static ILog _log = LogManager.GetLogger(typeof(NMEA)); public enum Status { OK, UNKNOWN_TYPE, CHECKSUM, ILLEGAL_ARGUMENT } protected abstract void Decode(); /// /// public method to decode input data strings into respective NMEA sentences /// /// /// /// public static NMEA Decode(string data, ref Status status) { try { if (data == null) { status = Status.ILLEGAL_ARGUMENT; return null; } if (data[0] != '$' && data[0] != '!') { status = Status.ILLEGAL_ARGUMENT; return null; // no NMEA sentence } string[] elements = data.Trim().Substring(1).Split(','); NMEA sentence = NMEA.CreateNMEAElement(elements[0]); if (sentence == null) { status = Status.UNKNOWN_TYPE; return null; } sentence.elements = elements; sentence._data = data.Trim(); ; if (!sentence.IsChecksumOK) { status = Status.CHECKSUM; return null; } sentence.Decode(); return sentence; } catch (Exception ex) { _log.ErrorFormat("Error decoding sentence: {0}, {1}", ex.Message, ex.StackTrace); return null; } } /// /// Factory method for nmea types /// protected static NMEA CreateNMEAElement(string type) { NMEA result = null; switch (type.ToUpper()) { case "AIVDM": case "AIVDO": result = new NMEA_AIS_Sentence(); break; case "PNMLS": result = new NMEA_PNMLS_Sentence(); break; default: _log.WarnFormat("ignoring unsupported NMEA type {0}", type); break; } if (result != null) result.type = type.ToUpper(); return result; } #region NMEA checksum protected bool IsChecksumOK { get { return _data.Substring(_data.IndexOf('*') + 1) == this.CalculateChecksum(); } } private string CalculateChecksum() { int checksum = Convert.ToByte(_data[1]); for (int i = 2; i < _data.IndexOf('*'); i++) { checksum ^= Convert.ToByte(_data[i]); } return checksum.ToString("X2"); } #endregion } }