271 lines
6.9 KiB
C#
271 lines
6.9 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
|
|
// ship details suchbar hier: http://www.itu.int/cgi-bin/htsh/mars/ship_search.sh
|
|
|
|
namespace bsmd.AISService.AIS
|
|
{
|
|
public abstract class AIS
|
|
{
|
|
protected const double ERAD = 6378.135;
|
|
protected const double DE2RA = 0.01745329252;
|
|
protected const double AVG_ERAD = 6371.0;
|
|
|
|
|
|
#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 private members
|
|
|
|
private AISType type = AISType.AIS_NONE;
|
|
protected int userId;
|
|
protected string data;
|
|
private string station;
|
|
|
|
#endregion
|
|
|
|
#region Properties
|
|
|
|
public AISType MessageType
|
|
{
|
|
get { return this.type; }
|
|
}
|
|
|
|
public int MMSI
|
|
{
|
|
get { return this.userId; }
|
|
}
|
|
|
|
public string Station
|
|
{
|
|
get { return this.station; }
|
|
set { this.station = value; }
|
|
}
|
|
|
|
public bool IsNew { get; set; }
|
|
|
|
#endregion
|
|
|
|
#region abstract method signatures
|
|
|
|
protected abstract Status Decode();
|
|
|
|
#endregion
|
|
|
|
#region static methods
|
|
|
|
internal static AIS Decode(string data, ref Status status)
|
|
{
|
|
AIS result = null;
|
|
|
|
if (data == null || data.Length == 0)
|
|
{
|
|
status = Status.ILLEGAL_ARGUMENT;
|
|
return null;
|
|
}
|
|
|
|
BitArray bits = AIS.DecodeChar(data[0]);
|
|
int type = AIS.GetInt(bits, 0, 5);
|
|
|
|
result = AIS.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 AIS CreateMessage(int type)
|
|
{
|
|
AIS 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;
|
|
}
|
|
|
|
if (result != null) result.IsNew = true;
|
|
|
|
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 *= AIS.DE2RA;
|
|
lon1 *= AIS.DE2RA;
|
|
lat2 *= AIS.DE2RA;
|
|
lon2 *= AIS.DE2RA;
|
|
double d = Math.Sin(lat1) * Math.Sin(lat2) + Math.Cos(lat1) * Math.Cos(lat2) * Math.Cos(lon1 -lon2);
|
|
return (AIS.AVG_ERAD * Math.Acos(d));
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region overrides
|
|
|
|
public override string ToString()
|
|
{
|
|
return Enum.GetName(typeof(AIS.AISType), this.MessageType);
|
|
}
|
|
|
|
#endregion
|
|
|
|
}
|
|
}
|