369 lines
13 KiB
C#
369 lines
13 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Diagnostics;
|
|
using System.Text;
|
|
|
|
using log4net;
|
|
|
|
namespace bsmd.AIS2Service
|
|
{
|
|
internal class AIS_StaticData : AISClass
|
|
{
|
|
#region private members
|
|
|
|
private int ais_version;
|
|
private int imoNumber;
|
|
private string callsign;
|
|
private string name;
|
|
private int shiptype;
|
|
private int dimension;
|
|
private int a;
|
|
private int b;
|
|
private int c;
|
|
private int d;
|
|
|
|
private int typeofdevice;
|
|
private int etamonth;
|
|
private int etaday;
|
|
private int etahour;
|
|
private int etaminute;
|
|
private DateTime? eta;
|
|
|
|
private int maxpresetstaticdraught;
|
|
private string destination;
|
|
private int dte;
|
|
private int spare;
|
|
|
|
private static readonly ILog _log = LogManager.GetLogger(typeof(AIS_StaticData));
|
|
|
|
#endregion
|
|
|
|
#region Properties
|
|
|
|
public int ShipTypeVal { get { return this.shiptype; } }
|
|
|
|
public string Callsign
|
|
{
|
|
get { return this.callsign; }
|
|
}
|
|
|
|
public string Name
|
|
{
|
|
get { return this.name; }
|
|
}
|
|
|
|
public DateTime? ETA
|
|
{
|
|
get { return this.eta; }
|
|
}
|
|
|
|
public string Destination
|
|
{
|
|
get { return this.destination; }
|
|
}
|
|
|
|
public int IMONumber
|
|
{
|
|
get { return this.imoNumber; }
|
|
}
|
|
|
|
public string DeviceName
|
|
{
|
|
get
|
|
{
|
|
switch (typeofdevice)
|
|
{
|
|
case 1:
|
|
return "GPS";
|
|
case 2:
|
|
return "GLONASS";
|
|
case 3:
|
|
return "Combined GPS/GLONASS";
|
|
case 4:
|
|
return "Loran-C";
|
|
case 5:
|
|
return "Chayka";
|
|
case 6:
|
|
return "Integrated Navigation System";
|
|
case 7:
|
|
return "surveyed";
|
|
case 8:
|
|
return "Galileo";
|
|
default:
|
|
return "undefined";
|
|
}
|
|
}
|
|
}
|
|
|
|
public int Draught
|
|
{
|
|
get { return this.maxpresetstaticdraught; }
|
|
}
|
|
|
|
public int Breadth
|
|
{
|
|
get
|
|
{
|
|
return this.c + this.d;
|
|
}
|
|
}
|
|
|
|
public int Length
|
|
{
|
|
get
|
|
{
|
|
return this.a + this.b;
|
|
}
|
|
}
|
|
|
|
public string ShipType
|
|
{
|
|
get
|
|
{
|
|
return AIS_StaticData.GetShipType(this.shiptype);
|
|
}
|
|
}
|
|
|
|
public int DBShipType { get { return this.shiptype; } }
|
|
|
|
public int DBDimension { get { return this.dimension; } }
|
|
|
|
public int DBTypeOfDevice { get { return this.typeofdevice; } }
|
|
|
|
public int DTE { get { return this.dte; } }
|
|
|
|
public int Spare { get { return this.spare; } }
|
|
|
|
public string DBETA
|
|
{
|
|
get
|
|
{
|
|
if (this.eta.HasValue)
|
|
{
|
|
return this.eta.Value.ToString("yyyy-MM-ddTHH:mm:ss.000Z");
|
|
}
|
|
else
|
|
{
|
|
return "";
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region abstract method implementation
|
|
|
|
protected override Status Decode()
|
|
{
|
|
BitArray bits = DecodeBinary(_data);
|
|
Status result = Status.OK;
|
|
|
|
if (bits.Count < 424)
|
|
{
|
|
_log.WarnFormat("AISStaticData truncated: {0}/424", bits.Count);
|
|
result = Status.PARSE_ERROR;
|
|
}
|
|
else
|
|
{
|
|
try
|
|
{
|
|
int type = GetInt(bits, 0, 5);
|
|
if (type != 5)
|
|
{
|
|
result = Status.ILLEGAL_ARGUMENT;
|
|
}
|
|
else
|
|
{
|
|
_mmsi = GetInt(bits, 6, 37);
|
|
this.ais_version = GetInt(bits, 38, 39);
|
|
this.imoNumber = GetInt(bits, 40, 69);
|
|
|
|
StringBuilder sb_callsign = new StringBuilder(7);
|
|
for (int i = 0; i < 7; i++)
|
|
{
|
|
int cval = GetInt(bits, 70 + (6 * i), 75 + (6 * i));
|
|
char ch = GetAISChar(cval);
|
|
if (ch == '@') ch = ' ';
|
|
sb_callsign.Append(ch);
|
|
}
|
|
this.callsign = sb_callsign.ToString().Trim();
|
|
|
|
StringBuilder sb_name = new StringBuilder(20);
|
|
for (int i = 0; i < 20; i++)
|
|
{
|
|
int cval = GetInt(bits, 112 + (6 * i), 117 + (6 * i));
|
|
char ch = GetAISChar(cval);
|
|
if (ch == '@') ch = ' ';
|
|
sb_name.Append(ch);
|
|
}
|
|
this.name = sb_name.ToString().Trim();
|
|
|
|
this.shiptype = GetInt(bits, 232, 239);
|
|
this.dimension = GetInt(bits, 240, 269);
|
|
this.a = GetInt(bits, 240, 248);
|
|
this.b = GetInt(bits, 249, 257);
|
|
this.c = GetInt(bits, 258, 263);
|
|
this.d = GetInt(bits, 264, 269);
|
|
this.typeofdevice = GetInt(bits, 270, 273);
|
|
this.etamonth = GetInt(bits, 274, 277);
|
|
this.etaday = GetInt(bits, 278, 282);
|
|
this.etahour = GetInt(bits, 283, 287);
|
|
this.etaminute = GetInt(bits, 288, 293);
|
|
try
|
|
{
|
|
if ((this.etahour < 24) && (this.etaday > 0) && (this.etaminute < 60) && (this.etamonth > 0))
|
|
{
|
|
this.eta = new DateTime(DateTime.Now.Year, this.etamonth, this.etaday, this.etahour, this.etaminute, 0);
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
_log.WarnFormat("ETA timestamp creation failed: {0}", e.Message);
|
|
}
|
|
this.maxpresetstaticdraught = GetInt(bits, 294, 301);
|
|
|
|
StringBuilder sb_destination = new StringBuilder(20);
|
|
for (int i = 0; i < 20; i++)
|
|
{
|
|
int cval = GetInt(bits, 302 + (6 * i), 307 + (6 * i));
|
|
char ch = GetAISChar(cval);
|
|
if (ch == '@') break; //ch = ' '; // alles nach einem @ nicht mehr beachten
|
|
sb_destination.Append(ch);
|
|
}
|
|
this.destination = sb_destination.ToString().Trim();
|
|
|
|
this.dte = GetInt(bits, 422, 422);
|
|
this.spare = GetInt(bits, 423, 423);
|
|
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
_log.WarnFormat("Error decoding AIS static data: {0}", e.Message);
|
|
result = Status.PARSE_ERROR;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return string.Format("{0} - {1} [{2}]", base.ToString(), this.MMSI, this.Name);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region public static methods
|
|
|
|
public static string GetShipType(int shiptype)
|
|
{
|
|
if (shiptype > 199) return "preserved for future use";
|
|
if (shiptype > 99) return "preserved for regional use";
|
|
int dig1, dig2;
|
|
switch (shiptype)
|
|
{
|
|
case 50:
|
|
return "Pilot vessel";
|
|
case 51:
|
|
return "SAR vessel";
|
|
case 52:
|
|
return "Tug";
|
|
case 53:
|
|
return "Port tender";
|
|
case 54:
|
|
return "Vessel with anti-pollution facility or equipment";
|
|
case 55:
|
|
return "Law enforcment vessel";
|
|
case 56:
|
|
return "Spare [local vessel]";
|
|
case 57:
|
|
return "Spare [local vessel]";
|
|
case 58:
|
|
return "Medical transport";
|
|
case 59:
|
|
return "Ship according to Resolution No. 18 (Mob-83)";
|
|
default:
|
|
{
|
|
string comb = "";
|
|
dig1 = shiptype / 10;
|
|
dig2 = shiptype % 10;
|
|
switch (dig1)
|
|
{
|
|
case 1:
|
|
comb += "reserved for future use";
|
|
break;
|
|
case 2:
|
|
comb += "WIG";
|
|
break;
|
|
case 3:
|
|
comb += "Vessel";
|
|
switch (dig2)
|
|
{
|
|
case 0:
|
|
comb += " Fishing"; break;
|
|
case 1:
|
|
comb += " Towing"; break;
|
|
case 2:
|
|
comb += " Towing and length of tow exceeds 200m or breadth exceeds 25m"; break;
|
|
case 3:
|
|
comb += " Engaged in dredging or underwater operations"; break;
|
|
case 4:
|
|
comb += " Engaged in diving operations"; break;
|
|
case 5:
|
|
comb += " Engaged in military operations"; break;
|
|
case 6:
|
|
comb += " Sailing"; break;
|
|
case 7:
|
|
comb += " Pleasure craft"; break;
|
|
default:
|
|
comb += " reserved for future use";
|
|
break;
|
|
}
|
|
return comb;
|
|
case 4:
|
|
comb += "HSC";
|
|
break;
|
|
case 6:
|
|
comb += "Passenger ship";
|
|
break;
|
|
case 7:
|
|
comb += "Cargo ship";
|
|
break;
|
|
case 8:
|
|
comb += "Tanker";
|
|
break;
|
|
default:
|
|
case 9:
|
|
comb += "other";
|
|
break;
|
|
}
|
|
switch (dig2)
|
|
{
|
|
case 0: break;
|
|
case 1:
|
|
comb += " carrying DG, HS or MP IMO hazard or pollutant category A"; break;
|
|
case 2:
|
|
comb += " carrying DG, HS or MP IMO hazard or pollutant category B"; break;
|
|
case 3:
|
|
comb += " carrying DG, HS or MP IMO hazard or pollutant category C"; break;
|
|
case 4:
|
|
comb += " carrying DG, HS or MP IMO hazard or pollutant category D"; break;
|
|
case 5:
|
|
case 6:
|
|
case 7:
|
|
case 8:
|
|
comb += " reserved for future use"; break;
|
|
case 9:
|
|
comb += " no additional information"; break;
|
|
}
|
|
return comb;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
}
|
|
}
|