git_bsmd/AIS/bsmd.AISService/AIS/NMEA.cs

120 lines
3.1 KiB
C#

using System;
using System.Collections.Generic;
using System.Text;
using log4net;
namespace bsmd.AISService.AIS
{
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 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":
result = new NMEA_AIS_Sentence();
break;
case "PNMLS":
result = new NMEA_PNMLS_Sentence();
break;
default:
break;
}
if (result != null)
result.type = type.ToUpper();
return result;
}
protected bool IsChecksumOK
{
get
{
return this.data.Substring(this.data.IndexOf('*') + 1) == this.CalculateChecksum();
}
}
private string CalculateChecksum()
{
int checksum = Convert.ToByte(this.data[1]);
for (int i = 2; i < this.data.IndexOf('*'); i++)
{
checksum ^= Convert.ToByte(this.data[i]);
}
return checksum.ToString("X2");
}
}
}