git_bsmd/AIS/bsmd.AIS2Service/AISClass.cs

281 lines
7.0 KiB
C#

using log4net;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace bsmd.AIS2Service
{
internal abstract class AISClass
{
#region constant defs
protected const double ERAD = 6378.135;
protected const double DE2RA = 0.01745329252;
protected const double AVG_ERAD = 6371.0;
#endregion
#region enumerations
public enum Status
{
OK,
UNKNOWN_TYPE,
UNSUPPORTED,
ILLEGAL_ARGUMENT,
PARSE_ERROR
}
public enum AISType
{
AIS_NONE = 0,
POSITION_REPORT,
POSITION_REPORT_ASSIGNED,
POSITION_REPORT_SPECIAL,
BASE_STATION_REPORT,
STATIC_VOYAGE_DATA,
BINARY_ADDR_MSG,
BINARY_ACK,
BINARY_BCAST,
SAR_AIRCRAFT,
UTC_INQUIRY,
UTC_RESPONSE,
SAFETY_RELATED_MSG,
SAFETY_RELATED_ACK,
SAFETY_RELATED_BCAST,
INTERROGATION,
ASSIGN_MODE_CMD,
DGNSS_BCAST,
POSITION_REPORT_B_EQUIP,
POSITION_REPORT_B_EQUIP_EXT,
DATA_LINK_MAN,
AIDS_TO_NAV_REPORT,
CHANNEL_MNGNT,
GROUP_ASSIGNMENT,
CLASS_B_STATIC_DATA
};
#endregion
#region fields
private AISType _type = AISType.AIS_NONE;
protected int _mmsi;
protected string _data;
private static readonly ILog _log = LogManager.GetLogger(typeof(AISClass));
#endregion
#region Properties
public AISType MessageType
{
get { return this._type; }
}
public int MMSI
{
get { return _mmsi; }
}
#endregion
#region abstract method signatures
protected abstract Status Decode();
#endregion
#region static methods
internal static AISClass Decode(string data, ref Status status)
{
if (data == null || data.Length == 0)
{
status = Status.ILLEGAL_ARGUMENT;
return null;
}
BitArray bits = AISClass.DecodeChar(data[0]);
int type = AISClass.GetInt(bits, 0, 5);
AISClass result = AISClass.CreateMessage(type);
if (result != null)
{
result._data = data;
status = result.Decode();
}
else
{
status = Status.UNSUPPORTED;
}
return result;
}
/// <summary>
/// Factory method to create messages based on the message type
/// </summary>
protected static AISClass CreateMessage(int type)
{
AISClass result = null;
switch (type)
{
case 1:
result = new AIS_PosReport();
result._type = AISType.POSITION_REPORT;
break;
case 2:
result = new AIS_PosReport();
result._type = AISType.POSITION_REPORT_ASSIGNED;
break;
case 3:
result = new AIS_PosReport();
result._type = AISType.POSITION_REPORT_SPECIAL;
break;
case 4:
result = new AIS_BaseStationReport();
result._type = AISType.BASE_STATION_REPORT;
break;
case 5:
result = new AIS_StaticData();
result._type = AISType.STATIC_VOYAGE_DATA;
break;
case 18:
result = new AIS_ClassB();
result._type = AISType.POSITION_REPORT_B_EQUIP;
break;
case 19:
result = new AIS_ClassBExt();
result._type = AISType.POSITION_REPORT_B_EQUIP_EXT;
break;
case 24:
result = new AIS_ClassBStatic();
result._type = AISType.CLASS_B_STATIC_DATA;
break;
default:
_log.InfoFormat("No decoder for AIS class {0}", (AISType)type);
break;
}
return result;
}
#region static helpers
protected static BitArray DecodeChar(char c)
{
Byte b = Convert.ToByte(c);
return DecodeByte(b);
}
protected static BitArray DecodeByte(byte c)
{
c += 40;
if (c > 128) c += 32;
else c += 40;
c &= 63;
BitArray b = new BitArray(6);
for (int i = 0; i < 6; i++)
{
b[i] = ((c >> (5 - i)) & 1) == 1;
}
return b;
}
protected static BitArray DecodeBinary(string data)
{
BitArray result = new BitArray(data.Length * 6, false);
for (int i = 0; i < data.Length; i++)
{
BitArray charBits = DecodeChar(data[i]);
for (int j = 0; j < charBits.Count; j++)
result[i * 6 + j] = charBits[j];
}
return result;
}
protected static int GetInt(BitArray bits, int lo, int hi)
{
int result = 0;
int test = 1;
for (int i = hi; i >= lo; i--, test <<= 1)
{
if (bits[i]) result |= test;
}
return result;
}
protected static uint GetUInt(BitArray bits, int lo, int hi)
{
uint result = 0;
uint test = 1;
for (int i = hi; i >= lo; i--, test <<= 1)
{
if (bits[i]) result |= test;
}
return result;
}
protected static char GetAISChar(int val)
{
if (val < 32) return Convert.ToChar(val + 64);
if (val < 64) return Convert.ToChar(val);
return ' ';
}
#endregion
#region public static helpers
/// <summary>
/// mehr dazu hier:
/// http://www.codeguru.com/cpp/cpp/algorithms/general/article.php/c5115/
/// </summary>
public static double GetDistance(double lat1, double lon1, double lat2, double lon2)
{
lat1 *= DE2RA;
lon1 *= DE2RA;
lat2 *= DE2RA;
lon2 *= DE2RA;
double d = Math.Sin(lat1) * Math.Sin(lat2) + Math.Cos(lat1) * Math.Cos(lat2) * Math.Cos(lon1 - lon2);
return (AVG_ERAD * Math.Acos(d));
}
#endregion
#endregion
#region overrides
public override string ToString()
{
return Enum.GetName(typeof(AISClass.AISType), this.MessageType);
}
#endregion
}
}