alles tut soweit, SQLite Tabelle für Speicherung angelegt

This commit is contained in:
Daniel Schick 2022-10-09 22:19:52 +02:00
parent e98d4ae563
commit e8a3e6de16
8 changed files with 461 additions and 6 deletions

BIN
AIS/SQL/ais_initial.db Normal file

Binary file not shown.

View File

@ -1,4 +1,5 @@
using System;
using log4net;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
@ -66,6 +67,7 @@ namespace bsmd.AIS2Service
private AISType _type = AISType.AIS_NONE;
protected int _mmsi;
protected string _data;
private static readonly ILog _log = LogManager.GetLogger(typeof(AISClass));
#endregion
@ -92,8 +94,7 @@ namespace bsmd.AIS2Service
#region static methods
internal static AISClass Decode(string data, ref Status status)
{
AISClass result = null;
{
if (data == null || data.Length == 0)
{
@ -104,7 +105,7 @@ namespace bsmd.AIS2Service
BitArray bits = AISClass.DecodeChar(data[0]);
int type = AISClass.GetInt(bits, 0, 5);
result = AISClass.CreateMessage(type);
AISClass result = AISClass.CreateMessage(type);
if (result != null)
{
result._data = data;
@ -139,7 +140,10 @@ namespace bsmd.AIS2Service
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;
@ -161,6 +165,7 @@ namespace bsmd.AIS2Service
break;
default:
_log.InfoFormat("No decoder for AIS class {0}", (AISType)type);
break;
}
@ -221,6 +226,18 @@ namespace bsmd.AIS2Service
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);

View File

@ -119,7 +119,7 @@ namespace bsmd.AIS2Service
if(aisStatus == AISClass.Status.OK)
{
_outputAISClasses.Enqueue(decodedClass);
_log.InfoFormat("Enqueuing AIS message for MMSI {0}", decodedClass.MMSI);
_log.DebugFormat("Enqueuing {0} message for MMSI {1}", decodedClass.MessageType, decodedClass.MMSI);
}
else
{

View File

@ -14,6 +14,7 @@ namespace bsmd.AIS2Service
private static readonly ConcurrentQueue<string> _inputLines = new ConcurrentQueue<string>();
private static readonly ConcurrentQueue<AISClass> _decodedClasses = new ConcurrentQueue<AISClass>();
private static readonly ILog _log = LogManager.GetLogger(typeof(AISManager));
private static readonly List<AIS_Target> _sitRepList = new List<AIS_Target>();
public static void Start()
{

View File

@ -0,0 +1,103 @@
using log4net;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting.Metadata.W3cXsd2001;
using System.Text;
using System.Threading.Tasks;
namespace bsmd.AIS2Service
{
internal class AIS_BaseStationReport : AISClass
{
#region enums
public enum EPFDType
{
UNDEFINED,
GPS,
GLONASS,
COMBINED_GPS_GLONASS,
LORAN_C,
CHAYKA,
INTEGR_NAV_SYSTEM,
SURVEYED,
GALILEO
}
#endregion
#region fields
private uint _repeatIndicator;
private DateTime? _utcTimestamp;
private bool _accuracy;
private int _latitude;
private int _longitude;
private EPFDType _epfdType;
bool _raim;
private uint _radio;
private static readonly ILog _log = LogManager.GetLogger(typeof(AIS_BaseStationReport));
#endregion
#region Properties
public uint RepeatIndicator { get { return _repeatIndicator; } }
public DateTime? UTCTimestamp { get { return _utcTimestamp; } }
public bool Accuracy { get { return _accuracy; } }
public int Latitude { get { return _latitude; } }
public int Longitude { get { return _longitude; } }
public EPFDType EPFD { get { return _epfdType; } }
public bool Raim { get { return _raim; } }
public uint Radio { get { return _radio; } }
#endregion
#region abstract class implementation
protected override Status Decode()
{
Status result = Status.OK;
BitArray bits = DecodeBinary(_data);
try
{
_repeatIndicator = GetUInt(bits, 6, 7);
_mmsi = GetInt(bits, 8, 37);
uint year = GetUInt(bits, 38, 51);
uint month = GetUInt(bits, 52, 55);
uint day = GetUInt(bits, 56, 60);
uint hour = GetUInt(bits, 61, 65);
uint minute = GetUInt(bits, 66, 71);
uint second = GetUInt(bits, 72, 77);
_utcTimestamp = new DateTime((int) year, (int) month, (int) day, (int) hour, (int) minute, (int) second, DateTimeKind.Utc);
_accuracy = GetInt(bits, 78, 78) == 1;
_longitude = GetInt(bits, 79, 106);
_latitude = GetInt(bits, 107, 133);
int epfd = GetInt(bits, 134, 137);
_epfdType = (EPFDType) epfd;
_raim = GetInt(bits, 148, 148) == 1;
_radio = GetUInt(bits, 149, 167);
}
catch (Exception e)
{
_log.WarnFormat("Error decoding AIS base station report: {0}", e.Message);
result = Status.PARSE_ERROR;
}
return result;
}
#endregion
}
}

View File

@ -0,0 +1,318 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace bsmd.AIS2Service
{
public class AIS_Target
{
#region private members
public static TimeSpan dbUpdateInterval = new TimeSpan(0, 2, 0); // neue Position in DB schreiben (min Interval)
private int mmsi;
private bool isClassB = false;
private bool? isWatchkeeper = null;
private DateTime? lastUpdate;
private bool updateDB = false;
private string name;
private string station;
private string lastDBName;
private string callSign;
private bool selected = false;
private AISClass staticInfo;
private AISClass posReport;
private AISClass lastAdditionalData;
private AIS_Target.Type type = Type.OTHER;
private AIS_Target.NavStatus navStatus = AIS_Target.NavStatus.UNKNOWN;
#endregion
#region public defs
public enum Type
{
PASSENGER,
CARGO,
TANKER,
HSC,
WIG,
TUG,
YACHT,
OTHER
}
/// <summary>
/// vereinfacht
/// </summary>
public enum NavStatus
{
UNKNOWN,
UNDERWAY,
MOORED
}
#endregion
#region Construction
public AIS_Target(int mmsi)
{
this.mmsi = mmsi;
}
#endregion
#region Properties
public int MMSI
{
get { return this.mmsi; }
}
public DateTime? LastUpdate
{
get { return this.lastUpdate; }
}
public string Name
{
get {
if ((this.name == null) || (this.name.Length == 0))
return this.LastDBName;
return this.name;
}
set { this.name = value; }
}
public string Callsign
{
get { return this.callSign; }
set { this.callSign = value; }
}
public string LastDBName
{
get { return this.lastDBName; }
set { this.lastDBName = value; }
}
public string ReceivedFrom
{
get { return this.station; }
}
internal AISClass LastPosReport
{
get { return this.posReport; }
}
internal AISClass LastStaticData
{
get { return this.staticInfo; }
}
public double? Latitude
{
get
{
if (this.LastPosReport == null) return null;
if (this.LastPosReport is AIS_PosReport)
return ((AIS_PosReport)this.LastPosReport).Latitude;
if (this.LastPosReport is AIS_ClassB)
return ((AIS_ClassB)this.LastPosReport).Latitude;
if (this.LastPosReport is AIS_ClassBExt)
return ((AIS_ClassBExt)this.LastPosReport).Latitude;
return null;
}
}
public Type TargetType
{
get { return this.type; }
set { this.type = value; }
}
public NavStatus TargetNavStatus
{
get { return this.navStatus; }
}
public double? Longitude
{
get
{
if (this.LastPosReport == null) return null;
if (this.LastPosReport is AIS_PosReport)
return ((AIS_PosReport)this.LastPosReport).Longitude;
if (this.LastPosReport is AIS_ClassB)
return ((AIS_ClassB)this.LastPosReport).Longitude;
if (this.LastPosReport is AIS_ClassBExt)
return ((AIS_ClassBExt)this.LastPosReport).Longitude;
return null;
}
}
public bool? IsClassB
{
get
{
return this.isClassB;
}
}
public int? Heading
{
get
{
if (this.LastPosReport == null) return null;
if (this.LastPosReport is AIS_PosReport)
return ((AIS_PosReport)this.LastPosReport).TrueHeading;
if (this.LastPosReport is AIS_ClassB)
return ((AIS_ClassB)this.LastPosReport).TrueHeading;
if (this.LastPosReport is AIS_ClassBExt)
return ((AIS_ClassBExt)this.LastPosReport).TrueHeading;
return null;
}
}
public int? COG
{
get
{
if (this.LastPosReport == null) return null;
if (this.LastPosReport is AIS_PosReport)
return (int)((AIS_PosReport)this.LastPosReport).COG;
if (this.LastPosReport is AIS_ClassB)
return (int)((AIS_ClassB)this.LastPosReport).Cog;
if (this.LastPosReport is AIS_ClassBExt)
return (int) ((AIS_ClassBExt)this.LastPosReport).Cog;
return null;
}
}
public bool? IsWatchkeeperShip
{
get { return this.isWatchkeeper; }
set { this.isWatchkeeper = value; }
}
public bool Selected
{
get { return this.selected; }
set { this.selected = value; }
}
public string Station
{
get { return this.station; }
set { this.station = value; }
}
#endregion
#region public methods
public static AIS_Target.NavStatus GetCurrentNavstatus(int status)
{
AIS_Target.NavStatus result = NavStatus.UNKNOWN;
switch (status)
{
case 0:
case 8:
result = NavStatus.UNDERWAY;
break;
default:
result = NavStatus.MOORED;
break;
}
return result;
}
internal void Update(AISClass message)
{
switch (message.MessageType)
{
case AISClass.AISType.POSITION_REPORT:
case AISClass.AISType.POSITION_REPORT_ASSIGNED:
case AISClass.AISType.POSITION_REPORT_SPECIAL:
if ((this.lastUpdate.HasValue &&
(((AIS_PosReport)message).Timestamp - this.lastUpdate.Value) > AIS_Target.dbUpdateInterval)
|| (!this.lastUpdate.HasValue))
{
this.updateDB = true;
this.lastUpdate = ((AIS_PosReport)message).Timestamp;
}
this.posReport = message;
this.navStatus = AIS_Target.GetCurrentNavstatus(((AIS_PosReport)message).NavStatusVal);
// System.Diagnostics.Trace.WriteLine(string.Format("pos report at {0}", this.lastUpdate));
break;
case AISClass.AISType.POSITION_REPORT_B_EQUIP:
if ((this.lastUpdate.HasValue &&
(((AIS_ClassB)message).Timestamp - this.lastUpdate.Value) > AIS_Target.dbUpdateInterval)
|| (!this.lastUpdate.HasValue))
{
this.updateDB = true;
this.lastUpdate = ((AIS_ClassB)message).Timestamp;
this.isClassB = true;
this.type = Type.YACHT;
this.navStatus = NavStatus.UNDERWAY;
}
this.posReport = message;
break;
case AISClass.AISType.POSITION_REPORT_B_EQUIP_EXT:
if ((this.lastUpdate.HasValue &&
(((AIS_ClassBExt)message).Timestamp - this.lastUpdate.Value) > AIS_Target.dbUpdateInterval)
|| (!this.lastUpdate.HasValue))
{
this.updateDB = true;
this.lastUpdate = ((AIS_ClassBExt)message).Timestamp;
this.isClassB = true;
this.type = Type.YACHT;
this.navStatus = NavStatus.UNDERWAY;
}
this.posReport = message;
break;
case AISClass.AISType.STATIC_VOYAGE_DATA:
this.staticInfo = message;
this.name = ((AIS_StaticData)message).Name;
this.callSign = ((AIS_StaticData)message).Callsign;
//this.type = AIS_StaticData.GetShipTypeSimple(((AIS_StaticData)message).ShipTypeVal);
break;
case AISClass.AISType.CLASS_B_STATIC_DATA:
if (((AIS_ClassBStatic)message).IsPartA)
{
this.name = ((AIS_ClassBStatic)message).Name;
}
else
{
this.callSign = ((AIS_ClassBStatic)message).Callsign;
}
this.staticInfo = message;
this.type = Type.YACHT;
this.isClassB = true;
break;
default:
this.lastAdditionalData = message;
break;
}
}
#endregion
#region overrides
public override string ToString()
{
return string.Format("{0} [{1}]", this.Name, this.MMSI);
}
#endregion
}
}

View File

@ -12,6 +12,8 @@
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
@ -39,6 +41,9 @@
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
<Reference Include="System.Data.SQLite, Version=1.0.116.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=MSIL">
<HintPath>packages\Stub.System.Data.SQLite.Core.NetFramework.1.0.116.0\lib\net46\System.Data.SQLite.dll</HintPath>
</Reference>
<Reference Include="System.Web" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
@ -58,11 +63,13 @@
<Compile Include="AISClass.cs" />
<Compile Include="AISDecoder.cs" />
<Compile Include="AISManager.cs" />
<Compile Include="AIS_BaseStationReport.cs" />
<Compile Include="AIS_ClassB.cs" />
<Compile Include="AIS_ClassBExt.cs" />
<Compile Include="AIS_ClassBStatic.cs" />
<Compile Include="AIS_PosReport.cs" />
<Compile Include="AIS_StaticData.cs" />
<Compile Include="AIS_Target.cs" />
<Compile Include="IAISThread.cs" />
<Compile Include="NMEA.cs" />
<Compile Include="NMEA_AIS_Sentence.cs" />
@ -91,4 +98,11 @@
</EmbeddedResource>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="packages\Stub.System.Data.SQLite.Core.NetFramework.1.0.116.0\build\net46\Stub.System.Data.SQLite.Core.NetFramework.targets" Condition="Exists('packages\Stub.System.Data.SQLite.Core.NetFramework.1.0.116.0\build\net46\Stub.System.Data.SQLite.Core.NetFramework.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('packages\Stub.System.Data.SQLite.Core.NetFramework.1.0.116.0\build\net46\Stub.System.Data.SQLite.Core.NetFramework.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Stub.System.Data.SQLite.Core.NetFramework.1.0.116.0\build\net46\Stub.System.Data.SQLite.Core.NetFramework.targets'))" />
</Target>
</Project>

View File

@ -1,4 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="log4net" version="2.0.15" targetFramework="net48" />
<package id="Stub.System.Data.SQLite.Core.NetFramework" version="1.0.116.0" targetFramework="net48" />
<package id="System.Data.SQLite.Core" version="1.0.116.0" targetFramework="net48" />
</packages>