522 lines
20 KiB
C#
522 lines
20 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using System.Data;
|
|
using System.ComponentModel;
|
|
using System.Diagnostics;
|
|
|
|
using bsmd.AISService.AIS;
|
|
|
|
namespace bsmd.AISService.DB
|
|
{
|
|
|
|
public class AISStaticData
|
|
{
|
|
|
|
public enum DisplayStringType
|
|
{
|
|
NAME,
|
|
MMSI,
|
|
CALLSIGN
|
|
}
|
|
|
|
private const string LoadDBShipsQuery = "SELECT aisposreport.MMSI, aisposreport.timestamp, aisposreport.latitude, aisposreport.longitude, aisposreport.stationid, aisposreport.cog, aisposreport.heading, aisposreport.navstatus, aisstaticdata.callsign, aisstaticdata.name, aisstaticdata.shiptype, aisstaticdata.classb, aisstaticdata.shipdescription FROM aisstaticdata JOIN hotposition ON aisstaticdata.mmsi = hotposition.mmsi JOIN aisposreport ON aisposreport.id = hotposition.pid ORDER BY aisstaticdata.name";
|
|
|
|
#region Fields
|
|
|
|
private int mmsi;
|
|
private string name;
|
|
private string callsign;
|
|
private DateTime? lastposition;
|
|
private double? lastLatitude;
|
|
private double? lastLongitude;
|
|
private int stationid;
|
|
private int navstatus;
|
|
private int shiptype;
|
|
private string shipdescription;
|
|
private int cog;
|
|
private int heading;
|
|
private bool isClassB;
|
|
private bool isWatchkeeper;
|
|
private bool isTimedOut = false;
|
|
private bool isSelected = false;
|
|
private static DisplayStringType displayStringType = DisplayStringType.NAME;
|
|
|
|
#endregion
|
|
|
|
#region Properties
|
|
|
|
public int MMSI
|
|
{
|
|
get { return this.mmsi; }
|
|
}
|
|
|
|
public string Name
|
|
{
|
|
get { return this.name; }
|
|
}
|
|
|
|
public string Callsign
|
|
{
|
|
get { return this.callsign; }
|
|
}
|
|
|
|
public DateTime? LastPositionReport
|
|
{
|
|
get { return this.lastposition; }
|
|
}
|
|
|
|
public double? LastLatitude
|
|
{
|
|
get { return this.lastLatitude; }
|
|
}
|
|
|
|
public double? LastLongitude
|
|
{
|
|
get { return this.lastLongitude; }
|
|
}
|
|
|
|
public bool IsClassB
|
|
{
|
|
get { return this.isClassB; }
|
|
}
|
|
|
|
public int ShipType
|
|
{
|
|
get { return this.shiptype; }
|
|
}
|
|
|
|
public string Description
|
|
{
|
|
get { return this.shipdescription; }
|
|
}
|
|
|
|
public bool IsWatchkeeperShip
|
|
{
|
|
get { return this.isWatchkeeper; }
|
|
set { this.isWatchkeeper = value; }
|
|
}
|
|
|
|
public int StationId
|
|
{
|
|
get { return this.stationid; }
|
|
}
|
|
|
|
public int Heading
|
|
{
|
|
get { return this.heading; }
|
|
}
|
|
|
|
public int COG
|
|
{
|
|
get { return this.cog; }
|
|
}
|
|
|
|
public int NavStatus
|
|
{
|
|
get { return this.navstatus; }
|
|
}
|
|
|
|
public bool Selected
|
|
{
|
|
get { return this.isSelected; }
|
|
set { this.isSelected = value; }
|
|
}
|
|
|
|
public static DisplayStringType DisplayStringTyp
|
|
{
|
|
get { return displayStringType; }
|
|
set { displayStringType = value; }
|
|
}
|
|
|
|
public bool IsTimedOut
|
|
{
|
|
get { return this.isTimedOut; }
|
|
set { this.isTimedOut = value; }
|
|
}
|
|
#endregion
|
|
|
|
#region public methods
|
|
|
|
public string ToHtmlString()
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
sb.Append(string.Format("<em>MMSI</em>: {0} <br />", this.MMSI));
|
|
sb.Append(string.Format("<em>Name</em>: <span style=\"font-size: bigger\">{0}</span><br />", this.Name));
|
|
sb.Append(string.Format("Latitude: {0}° <br />", this.LastLatitude.HasValue ? this.LastLatitude.Value.ToString("N3") : "?"));
|
|
sb.Append(string.Format("Longitude: {0}° <br />", this.LastLongitude.HasValue ? this.LastLongitude.Value.ToString("N3") : "?"));
|
|
sb.Append(string.Format("Last report: {0} <br />", this.LastPositionReport.HasValue ? this.LastPositionReport.Value.ToString() : "?"));
|
|
sb.Append(string.Format("Type: {0} [{1}]<br />", this.Description, this.ShipType));
|
|
sb.Append(string.Format("Navstatus: {0}<br />", this.NavStatus));
|
|
|
|
return sb.ToString();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region overrides
|
|
|
|
public override string ToString()
|
|
{
|
|
switch (displayStringType)
|
|
{
|
|
case DisplayStringType.NAME:
|
|
string result = "?";
|
|
if (this.name != null && this.name.Length > 0)
|
|
result = this.name;
|
|
return result;
|
|
case DisplayStringType.MMSI:
|
|
return this.mmsi.ToString();
|
|
case DisplayStringType.CALLSIGN:
|
|
if (this.Callsign == null || this.Callsign.Length == 0)
|
|
return "?";
|
|
return this.Callsign;
|
|
default:
|
|
return string.Format("{0} - {1}", this.name, this.mmsi);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region static methods
|
|
|
|
#region save a position report
|
|
|
|
/// <summary>
|
|
/// Saves a (class A or B) position report
|
|
/// </summary>
|
|
/// <param name="target">target to save</param>
|
|
/// <returns>id of insert operation (to update hotposition table)</returns>
|
|
public static int? Save(AIS_Target target, DBConnector con, AISStation aisStation)
|
|
{
|
|
if(target.LastStaticData == null) return null;
|
|
|
|
int mmsi = -1;
|
|
int id = -1;
|
|
|
|
if(target.LastStaticData is AIS_StaticData) {
|
|
mmsi = ((AIS_StaticData)target.LastStaticData).MMSI;
|
|
}
|
|
if(target.LastStaticData is AIS_ClassBStatic) {
|
|
mmsi = ((AIS_ClassBStatic)target.LastStaticData).MMSI;
|
|
}
|
|
|
|
string query = string.Format("SELECT id FROM aisstaticdata WHERE mmsi={0}", mmsi);
|
|
object result = con.ExecuteScalar(query);
|
|
|
|
if (result != null) // update
|
|
{
|
|
id = Convert.ToInt32(result);
|
|
}
|
|
|
|
#region Class A
|
|
|
|
if (target.LastStaticData is AIS_StaticData)
|
|
{
|
|
AIS_StaticData staticData = target.LastStaticData as AIS_StaticData;
|
|
|
|
if (id >= 0)
|
|
{
|
|
if (staticData.ETA.HasValue)
|
|
{
|
|
query = string.Format("UPDATE aisstaticdata SET imonumber={0}, callsign='{1}', name='{2}', shiptype={3}, typeofdevice='{4}', shipdescription='{5}', eta='{6}', destination='{7}', breadth={8}, length={9}, draught='{10}', stationid={11}, classb=0 WHERE id={12}",
|
|
staticData.IMONumber,
|
|
staticData.Callsign.Replace("'","''"),
|
|
staticData.Name.Replace("'", "''"),
|
|
staticData.ShipTypeVal,
|
|
staticData.DeviceName,
|
|
staticData.ShipType,
|
|
staticData.DBETA,
|
|
staticData.Destination.Replace("'", "''"),
|
|
staticData.Breadth,
|
|
staticData.Length,
|
|
staticData.Draught,
|
|
aisStation.Id,
|
|
id);
|
|
}
|
|
else
|
|
{
|
|
query = string.Format("UPDATE aisstaticdata SET imonumber={0}, callsign='{1}', name='{2}', shiptype={3}, typeofdevice='{4}', shipdescription='{5}', destination='{6}', breadth={7}, length={8}, draught='{9}', stationid={10}, classb=0 WHERE id={11}",
|
|
staticData.IMONumber,
|
|
staticData.Callsign.Replace("'", "''"),
|
|
staticData.Name.Replace("'", "''"),
|
|
staticData.ShipTypeVal,
|
|
staticData.DeviceName,
|
|
staticData.ShipType,
|
|
staticData.Destination.Replace("'", "''"),
|
|
staticData.Breadth,
|
|
staticData.Length,
|
|
staticData.Draught,
|
|
aisStation.Id,
|
|
id);
|
|
|
|
}
|
|
con.ExecuteNonQuery(query);
|
|
}
|
|
else
|
|
{
|
|
if (staticData.ETA.HasValue)
|
|
{
|
|
|
|
query = string.Format("INSERT INTO aisstaticdata SET imonumber={0}, callsign='{1}', name='{2}', shiptype={3}, typeofdevice='{4}', shipdescription='{5}', eta='{6}', destination='{7}', breadth={8}, length={9}, draught='{10}', stationid={11}, mmsi={12}, classb=0",
|
|
staticData.IMONumber,
|
|
staticData.Callsign.Replace("'", "''"),
|
|
staticData.Name.Replace("'", "''"),
|
|
staticData.ShipTypeVal,
|
|
staticData.DeviceName,
|
|
staticData.ShipType,
|
|
staticData.DBETA,
|
|
staticData.Destination.Replace("'", "''"),
|
|
staticData.Breadth,
|
|
staticData.Length,
|
|
staticData.Draught,
|
|
aisStation.Id,
|
|
staticData.MMSI);
|
|
}
|
|
else
|
|
{
|
|
query = string.Format("INSERT INTO aisstaticdata SET imonumber={0}, callsign='{1}', name='{2}', shiptype={3}, typeofdevice='{4}', shipdescription='{5}', destination='{6}', breadth={7}, length={8}, draught='{9}', stationid={10}, mmsi={11}, classb=0",
|
|
staticData.IMONumber,
|
|
staticData.Callsign.Replace("'", "''"),
|
|
staticData.Name.Replace("'", "''"),
|
|
staticData.ShipTypeVal,
|
|
staticData.DeviceName,
|
|
staticData.ShipType,
|
|
staticData.Destination.Replace("'", "''"),
|
|
staticData.Breadth,
|
|
staticData.Length,
|
|
staticData.Draught,
|
|
aisStation.Id,
|
|
staticData.MMSI);
|
|
}
|
|
|
|
con.ExecuteNonQuery(query);
|
|
|
|
id = Convert.ToInt32(con.ExecuteScalar("SELECT LAST_INSERT_ID()"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Class B
|
|
|
|
if (target.LastStaticData is AIS_ClassBStatic)
|
|
{
|
|
AIS_ClassBStatic staticData = target.LastStaticData as AIS_ClassBStatic;
|
|
|
|
if (id >= 0) // Update
|
|
{
|
|
query = string.Format("UPDATE aisstaticdata SET stationid={0}, shiptype={1}, classb=1", aisStation.Id, staticData.ShipTypeVal);
|
|
if(staticData.Callsign != null) query += string.Format(", callsign='{0}'", staticData.Callsign);
|
|
if(staticData.Name != null) query += string.Format(", name='{0}'", staticData.Name);
|
|
if(staticData.VendorId != null) query += string.Format(", typeofdevice='{0}'", staticData.VendorId);
|
|
if(staticData.ShipType != null) query += string.Format(", shipdescription='{0}'", staticData.ShipType);
|
|
query += string.Format(" WHERE id={0}", id);
|
|
|
|
con.ExecuteNonQuery(query);
|
|
}
|
|
else // Insert
|
|
{
|
|
query = string.Format("INSERT INTO aisstaticdata SET callsign='{0}', name='{1}', shiptype={2}, typeofdevice='{3}', shipdescription='{4}', stationid={5}, mmsi={6}, classb=1",
|
|
staticData.Callsign,
|
|
staticData.Name,
|
|
staticData.ShipTypeVal,
|
|
staticData.VendorId,
|
|
staticData.ShipType,
|
|
aisStation.Id,
|
|
staticData.MMSI
|
|
);
|
|
|
|
con.ExecuteNonQuery(query);
|
|
id = Convert.ToInt32(con.ExecuteScalar("SELECT LAST_INSERT_ID()"));
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
return id;
|
|
}
|
|
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// Loads shipname for display (until static data has been received)
|
|
/// </summary>
|
|
public static string LoadName(int mmsi, DBConnector con)
|
|
{
|
|
string query = string.Format("SELECT name FROM aisstaticdata where mmsi={0}", mmsi);
|
|
string result = con.ExecuteScalar(query) as string;
|
|
if (result == null) result = "";
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Loads callsign for display (until static data has been received)
|
|
/// </summary>
|
|
public static string LoadCallsign(int mmsi, DBConnector con)
|
|
{
|
|
string query = string.Format("SELECT callsign FROM aisstaticdata where mmsi={0}", mmsi);
|
|
string result = con.ExecuteScalar(query) as string;
|
|
if (result == null) result = "";
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// preload target with data from database until static data has been received
|
|
/// </summary>
|
|
/// <param name="target">target to load</param>
|
|
public static void PreloadTarget(AIS_Target target, DBConnector con)
|
|
{
|
|
if (target.MMSI == 0) return;
|
|
string query = string.Format("SELECT name, callsign, shiptype FROM aisstaticdata where mmsi={0}", target.MMSI);
|
|
IDataReader reader = con.ExecuteQuery(query);
|
|
if (reader.Read())
|
|
{
|
|
if (!reader.IsDBNull(0)) target.LastDBName = reader.GetString(0);
|
|
if (!reader.IsDBNull(1)) target.Callsign = reader.GetString(1);
|
|
if (!reader.IsDBNull(2))
|
|
target.TargetType = AIS_StaticData.GetShipTypeSimple(reader.GetInt32(2));
|
|
}
|
|
reader.Close();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Load all ships that have a position and static data from database
|
|
/// </summary>
|
|
public static List<AISStaticData> LoadDBShips(DBConnector con)
|
|
{
|
|
List<AISStaticData> result = new List<AISStaticData>();
|
|
IDataReader reader = con.ExecuteQuery(AISStaticData.LoadDBShipsQuery);
|
|
while (reader.Read())
|
|
{
|
|
AISStaticData ship = new AISStaticData();
|
|
ship.mmsi = reader.GetInt32(0);
|
|
ship.lastposition = reader.GetDateTime(1);
|
|
ship.lastLatitude = (double) Math.Round(reader.GetInt32(2) / 600000.0, 4);
|
|
ship.lastLongitude = (double) Math.Round(reader.GetInt32(3) / 600000.0, 4);
|
|
ship.stationid = reader.GetInt32(4);
|
|
ship.cog = reader.GetInt32(5);
|
|
ship.heading = reader.GetInt32(6);
|
|
ship.navstatus = reader.GetInt32(7);
|
|
if(!reader.IsDBNull(8))
|
|
ship.callsign = reader.GetString(8);
|
|
if(!reader.IsDBNull(9))
|
|
ship.name = reader.GetString(9);
|
|
ship.shiptype = reader.GetInt32(10);
|
|
if (reader.IsDBNull(11)) ship.isClassB = false;
|
|
else ship.isClassB = reader.GetBoolean(11);
|
|
ship.shipdescription = reader.GetString(12);
|
|
result.Add(ship);
|
|
}
|
|
reader.Close();
|
|
Trace.WriteLine(string.Format("AISStaticData: {0} ships loaded from DB", result.Count));
|
|
return result;
|
|
}
|
|
|
|
#endregion
|
|
|
|
}
|
|
|
|
#region Comparer Class for grid
|
|
|
|
public class AISStaticData_Comparer : IComparer<AISStaticData>
|
|
{
|
|
private SortPropertyEnum sortProperty = SortPropertyEnum.NAME;
|
|
private ListSortDirection sortDirection = ListSortDirection.Ascending;
|
|
|
|
public enum SortPropertyEnum
|
|
{
|
|
NONE,
|
|
MMSI,
|
|
NAME,
|
|
CALLSIGN,
|
|
LASTUPDATE,
|
|
DESCRIPTION
|
|
}
|
|
|
|
#region Properties
|
|
|
|
public ListSortDirection SortDirection
|
|
{
|
|
get { return this.sortDirection; }
|
|
set { this.sortDirection = value; }
|
|
}
|
|
|
|
public SortPropertyEnum SortProperty
|
|
{
|
|
get { return this.sortProperty; }
|
|
set { this.sortProperty = value; }
|
|
}
|
|
|
|
#endregion
|
|
|
|
public int Compare(AISStaticData x, AISStaticData y)
|
|
{
|
|
switch (this.sortProperty)
|
|
{
|
|
case SortPropertyEnum.NONE:
|
|
return 0;
|
|
case SortPropertyEnum.NAME:
|
|
{
|
|
string xName = x.Name;
|
|
if (xName == null) xName = "";
|
|
string yName = y.Name;
|
|
if (yName == null) yName = "";
|
|
if (this.sortDirection == ListSortDirection.Ascending)
|
|
return xName.CompareTo(yName);
|
|
else
|
|
return yName.CompareTo(xName);
|
|
}
|
|
case SortPropertyEnum.LASTUPDATE:
|
|
{
|
|
DateTime xTime = x.LastPositionReport ?? DateTime.MinValue;
|
|
DateTime yTime = y.LastPositionReport ?? DateTime.MinValue;
|
|
if (this.sortDirection == ListSortDirection.Ascending)
|
|
return xTime.CompareTo(yTime);
|
|
else
|
|
return yTime.CompareTo(xTime);
|
|
}
|
|
case SortPropertyEnum.MMSI:
|
|
{
|
|
if (this.sortDirection == ListSortDirection.Ascending)
|
|
return x.MMSI.CompareTo(y.MMSI);
|
|
else
|
|
return y.MMSI.CompareTo(x.MMSI);
|
|
}
|
|
case SortPropertyEnum.CALLSIGN:
|
|
{
|
|
string xCallsign = x.Callsign;
|
|
if (xCallsign == null) xCallsign = "";
|
|
string yCallsign = y.Callsign;
|
|
if (yCallsign == null) yCallsign = "";
|
|
if (this.sortDirection == ListSortDirection.Ascending)
|
|
return xCallsign.CompareTo(yCallsign);
|
|
else
|
|
return yCallsign.CompareTo(xCallsign);
|
|
}
|
|
case SortPropertyEnum.DESCRIPTION:
|
|
{
|
|
string xDescription = x.Description;
|
|
if (xDescription == null) xDescription = "";
|
|
string yDescription = y.Description;
|
|
if (yDescription == null) yDescription = "";
|
|
if (this.sortDirection == ListSortDirection.Ascending)
|
|
return xDescription.CompareTo(yDescription);
|
|
else
|
|
return yDescription.CompareTo(xDescription);
|
|
}
|
|
default:
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|