130 lines
3.3 KiB
C#
130 lines
3.3 KiB
C#
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();
|
|
|
|
/// <summary>
|
|
/// public method to decode input data strings into respective NMEA sentences
|
|
/// </summary>
|
|
/// <param name="data"></param>
|
|
/// <param name="status"></param>
|
|
/// <returns></returns>
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Factory method for nmea types
|
|
/// </summary>
|
|
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
|
|
|
|
}
|
|
}
|