264 lines
6.4 KiB
C#
264 lines
6.4 KiB
C#
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;
|
|
|
|
#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)
|
|
{
|
|
AISClass result = null;
|
|
|
|
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);
|
|
|
|
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 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:
|
|
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 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
|
|
}
|
|
}
|