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
}
}