Aktuellen Stand von SMSPLASH01 wieder hergeholt (separate LS100PortProxy Version für BSMD-AIS, da hier manuell <CR>'s in den Datenstrom eingebaut werden müssen)

This commit is contained in:
Daniel Schick 2018-04-06 18:26:24 +00:00
parent 09f8a9953f
commit e672bb8dee
33 changed files with 814 additions and 195 deletions

Binary file not shown.

View File

@ -0,0 +1,79 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{1B23254E-62EA-4AAF-803C-AAA0622B4570}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>LS100PortProxy</RootNamespace>
<AssemblyName>LS100PortProxy</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<TargetFrameworkProfile>
</TargetFrameworkProfile>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<RunCodeAnalysis>true</RunCodeAnalysis>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
<PlatformTarget>AnyCPU</PlatformTarget>
<OutputPath>bin\Debug\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
<PlatformTarget>AnyCPU</PlatformTarget>
<OutputPath>bin\Release\</OutputPath>
</PropertyGroup>
<ItemGroup>
<Reference Include="log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
<HintPath>packages\log4net.2.0.8\lib\net45-full\log4net.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="MultiplexManager.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config">
<SubType>Designer</SubType>
</None>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

Binary file not shown.

View File

@ -0,0 +1,35 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27428.2015
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LS100PortProxy", "LS100PortProxy.csproj", "{1B23254E-62EA-4AAF-803C-AAA0622B4570}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{1B23254E-62EA-4AAF-803C-AAA0622B4570}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1B23254E-62EA-4AAF-803C-AAA0622B4570}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1B23254E-62EA-4AAF-803C-AAA0622B4570}.Debug|x86.ActiveCfg = Debug|x86
{1B23254E-62EA-4AAF-803C-AAA0622B4570}.Debug|x86.Build.0 = Debug|x86
{1B23254E-62EA-4AAF-803C-AAA0622B4570}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1B23254E-62EA-4AAF-803C-AAA0622B4570}.Release|Any CPU.Build.0 = Release|Any CPU
{1B23254E-62EA-4AAF-803C-AAA0622B4570}.Release|x86.ActiveCfg = Release|x86
{1B23254E-62EA-4AAF-803C-AAA0622B4570}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {5F49C6E1-0B93-4637-83E3-685F3DF259C5}
EndGlobalSection
GlobalSection(SubversionScc) = preSolution
Svn-Managed = True
Manager = AnkhSVN - Subversion Support for Visual Studio
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,305 @@
//
// Class: MultiplexManager
// Current CLR: 4.0.30319.296
// System: Microsoft Visual Studio 10.0
// Author: dani
// Created: 4/8/2013 9:02:48 PM
//
// Copyright (c) 2013 Informatikbüro Daniel Schick. All rights reserved.
using System;
using System.Text;
using System.Collections.Generic;
using System.Threading;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Diagnostics;
using log4net;
namespace LS100PortProxy
{
public class MultiplexManager
{
private int ifIdx;
private int clientPort;
private int serverPort;
private string remoteServerAddress;
private bool shouldStop = false;
private Thread _acceptThread;
private Socket _serverSocket;
private List<ConnectionInfo> _connections = new List<ConnectionInfo>();
private TcpClient client;
private Thread _clientThread;
private NetworkStream clientStream;
private DateTime lastDataReceivedAt;
private ILog _log = LogManager.GetLogger(typeof(MultiplexManager));
private class Chunk
{
public int length;
public byte[] data;
public Chunk DeepClone()
{
Chunk newChunk = new Chunk();
newChunk.length = this.length;
newChunk.data = new byte[this.length];
Array.Copy(this.data, newChunk.data, this.length);
return newChunk;
}
}
private class ConnectionInfo
{
public Socket Socket;
public Thread Thread;
public Queue<Chunk> chunks = new Queue<Chunk>();
}
public MultiplexManager(int ifIdx, string address, int cPort, int sPort)
{
this.ifIdx = ifIdx;
this.remoteServerAddress = address;
this.clientPort = cPort;
this.serverPort = sPort;
}
public void StartServer()
{
this.SetupServerSocket();
_acceptThread = new Thread(AcceptConnections);
_acceptThread.IsBackground = true;
_acceptThread.Start();
}
public void StopServer()
{
this.shouldStop = true;
_serverSocket.Close();
_acceptThread.Join();
}
public static string ListIfs()
{
StringBuilder sb = new StringBuilder();
IPHostEntry localMachineInfo = Dns.GetHostEntry(Dns.GetHostName());
for(int i= 0;i< localMachineInfo.AddressList.Length; i++)
{
IPAddress address = localMachineInfo.AddressList[i];
sb.AppendLine(string.Format("# {0}: {1}", i, address.ToString()));
}
return sb.ToString();
}
private void SetupServerSocket()
{
// Resolving local machine information
IPHostEntry localMachineInfo = Dns.GetHostEntry(Dns.GetHostName());
IPEndPoint myEndpoint = new IPEndPoint(IPAddress.Any, serverPort);
//IPEndPoint myEndpoint = new IPEndPoint(localMachineInfo.AddressList[this.ifIdx], serverPort);
_log.InfoFormat("listening on {0}, port {1}", myEndpoint.Address, serverPort);
// Create the socket, bind it, and start listening
_serverSocket = new Socket(myEndpoint.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
_serverSocket.Blocking = true;
_serverSocket.Bind(myEndpoint);
_serverSocket.Listen(32);
}
private void AcceptConnections()
{
while (!shouldStop)
{ // Accept a connection
try
{
Socket socket = _serverSocket.Accept();
_log.InfoFormat("new connection from {0}", socket.RemoteEndPoint.ToString());
ConnectionInfo connection = new ConnectionInfo();
connection.Socket = socket; // Create the thread for the receives.
connection.Thread = new Thread(ProcessConnection);
connection.Thread.IsBackground = true;
connection.Thread.Start(connection);
// Store the socket
lock (_connections)
_connections.Add(connection);
}
catch (SocketException) { /* tu was */ }
Thread.Sleep(250);
}
this._serverSocket.Close();
}
private void ProcessConnection(object state)
{
ConnectionInfo connection = (ConnectionInfo)state;
try
{
while (!shouldStop)
{
// write all chunks in incoming chunk queue to this socket
if (connection.Socket.Poll(1000, SelectMode.SelectWrite))
{
while (connection.chunks.Count > 0)
{
Chunk aChunk = null;
lock (_connections)
{
aChunk = connection.chunks.Dequeue();
}
int bytesToSend = aChunk.length;
byte[] buffer = aChunk.data;
while (bytesToSend > 0)
{
//string testOutput = Encoding.ASCII.GetString(aChunk.data);
//string[] lines = testOutput.Split('\r');
//foreach(string line in lines)
// _log.Debug(line);
int actuallySentBytes = connection.Socket.Send(aChunk.data, aChunk.length, SocketFlags.None);
bytesToSend -= actuallySentBytes;
if (bytesToSend > 0)
{
byte[] newBuffer = new byte[bytesToSend];
Array.Copy(buffer, aChunk.length - bytesToSend, newBuffer, 0, bytesToSend);
buffer = newBuffer;
}
}
aChunk = null;
}
}
else
{
// dump queue in this case, packets cannot be sent..
lock (_connections)
{
connection.chunks.Clear();
}
}
Thread.Sleep(50);
}
}
catch (SocketException exc)
{
Console.WriteLine("Socket exception: " + exc.SocketErrorCode);
_log.WarnFormat("SocketException: {0}", exc.SocketErrorCode);
}
catch (Exception exc)
{ Console.WriteLine("Exception: " + exc); }
finally
{
_log.InfoFormat("removing connection to {0}", connection.Socket.RemoteEndPoint);
connection.Socket.Close();
lock (_connections)
_connections.Remove(connection);
GC.Collect();
}
}
internal void StartClient()
{
this._clientThread = new Thread(new ThreadStart(this.ClientConnection));
this._clientThread.Start();
}
private void ConnectClient()
{
try
{
if ((this.client != null) && (this.client.Connected)) return;
if (this.client != null)
{
this.client.Close();
GC.Collect();
}
this.client = new TcpClient(this.remoteServerAddress, this.clientPort);
this.clientStream = client.GetStream();
_log.InfoFormat("TCP stream connected ({0}:{1})", this.remoteServerAddress, this.clientPort);
}
catch (Exception ex)
{
_log.ErrorFormat("ConnectClient(): {0}", ex.Message);
}
}
private void ClientConnection()
{
while (!this.shouldStop)
{
try
{
if ((this.client == null) || !this.client.Connected) this.ConnectClient();
if ((this.client != null) && this.client.Connected && this.clientStream.CanRead)
{
while (this.clientStream.CanRead && !this.shouldStop)
{
Chunk chunk = new Chunk();
chunk.data = new byte[1024];
chunk.length = this.clientStream.Read(chunk.data, 0, 1024);
byte[] target = new byte[2048]; // einfach größer
int j = 0;
for (int i = 0; i < chunk.length; i++, j++)
{
target[j] = chunk.data[i];
if (chunk.data[i] == 10) // LF
{
target[j] = 13; // CR
j++;
target[j] = 10; //LF
}
}
if(j > chunk.length) // es wurden CR eingefügt
{
chunk.data = target;
chunk.length = j;
_log.DebugFormat("Chunk replaced, new length {0}", j);
}
if (chunk.length > 0 && (this._connections.Count > 0))
{
this.lastDataReceivedAt = DateTime.Now; // reset data timeout
// clone chunk for each connected client
lock (this._connections)
{
foreach (ConnectionInfo connectionInfo in _connections)
{
connectionInfo.chunks.Enqueue(chunk.DeepClone());
}
}
}
}
}
else
{
if ((DateTime.Now - lastDataReceivedAt) > TimeSpan.FromMinutes(10))
{
// close client connection if no data is received for 10 minutes
_log.Info("Server inactive for 10 minutes, disconnecting");
if(this.client != null)
this.client.Close();
this.client = null;
}
Thread.Sleep(120000); // try connect again in 2 minutes
}
Thread.Sleep(50);
}
catch (Exception ex)
{
_log.ErrorFormat("client-side exception: {0}", ex.Message);
if (this.client != null)
{
this.client.Close();
this.client = null;
}
Thread.Sleep(60000); // 60 Sekunden warten und neu verbinden
}
}
if(this.client != null)
this.client.Close();
}
}
}

View File

@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using log4net;
namespace LS100PortProxy
{
/// <summary>
/// http://msdn.microsoft.com/en-GB/library/bbx2eya8.aspx
/// Async server socket msdn
/// http://msdn.microsoft.com/en-us/library/5w7b7x5f.aspx
/// </summary>
class Program
{
static void Main(string[] args)
{
log4net.Config.XmlConfigurator.Configure();
ILog _log = LogManager.GetLogger("Main");
_log.Info("PortProxy started");
if ((args.Length != 4) && (args.Length != 0))
{
Console.WriteLine("Usage: <progname> <interface #> <remoteaddress> <clientport> <serverport>");
Console.WriteLine("<progname> -> outputs interfaces");
return;
}
if (args.Length == 0)
{
Console.WriteLine(MultiplexManager.ListIfs());
return;
}
int ifIdx = Convert.ToInt32(args[0]);
string address = args[1];
int clientPort = Convert.ToInt32(args[2]);
int serverPort = Convert.ToInt32(args[3]);
MultiplexManager manager = new MultiplexManager(ifIdx, address, clientPort, serverPort);
manager.StartServer();
manager.StartClient();
Console.WriteLine("Port proxy läuft. Beliebige Taste drücken um zu beenden...");
Console.ReadKey();
Console.WriteLine("stopping..");
manager.StopServer();
Console.WriteLine("stopped.");
_log.Info("PortProxy stopped");
}
}
}

View File

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("LS100PortProxy")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("LS100PortProxy")]
[assembly: AssemblyCopyright("Copyright © 2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("7ae7a332-a440-42d5-8d33-261e75424fe2")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,Log4net"/>
</configSections>
<log4net>
<root>
<level value="INFO"/>
<appender-ref ref="LogFileAppender"/>
<appender-ref ref="TraceAppender"/>
</root>
<appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender">
<param name="File" value="LS100PortProxy.log"/>
<param name="AppendToFile" value="true"/>
<rollingStyle value="Size"/>
<maxSizeRollBackups value="10"/>
<maximumFileSize value="10MB"/>
<staticLogFileName value="true"/>
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%date [%thread] %-5level [%logger] - %message%newline"/>
</layout>
</appender>
<appender name="TraceAppender" type="log4net.Appender.TraceAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%d [%t] %-5p %c %m%n"/>
</layout>
</appender>
</log4net>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1"/>
</startup>
</configuration>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="log4net" version="2.0.8" targetFramework="net461" />
</packages>

View File

@ -2,6 +2,7 @@
using System.Collections; using System.Collections;
using System.Text; using System.Text;
using System.Diagnostics; using System.Diagnostics;
using log4net;
namespace bsmd.AISService.AIS namespace bsmd.AISService.AIS
{ {
@ -27,6 +28,8 @@ namespace bsmd.AISService.AIS
private int commStateSelectedFlag; private int commStateSelectedFlag;
private int commState; private int commState;
private static ILog _log = LogManager.GetLogger(typeof(AIS_ClassB));
#endregion #endregion
#region Properties #region Properties
@ -42,14 +45,10 @@ namespace bsmd.AISService.AIS
{ {
get get
{ {
return string.Format("{0}-{1}-{2} {3}:{4}:{5}", return this.timestamp.ToString("yyyy-MM-ddTHH:mm:ss.000Z");
this.timestamp.Year, this.timestamp.Month, this.timestamp.Day,
this.timestamp.Hour, this.timestamp.Minute, this.timestamp.Second);
} }
} }
public double Cog public double Cog
{ {
get { return this.cog / 10.0f; } get { return this.cog / 10.0f; }
@ -141,7 +140,7 @@ namespace bsmd.AISService.AIS
} }
catch (Exception e) catch (Exception e)
{ {
Trace.WriteLine(string.Format("Error decoding AIS class B posreport: {0}", e.Message)); _log.WarnFormat("Error decoding AIS class B posreport: {0}", e.Message);
result = Status.PARSE_ERROR; result = Status.PARSE_ERROR;
} }

View File

@ -2,6 +2,7 @@
using System.Collections; using System.Collections;
using System.Text; using System.Text;
using System.Diagnostics; using System.Diagnostics;
using log4net;
namespace bsmd.AISService.AIS namespace bsmd.AISService.AIS
{ {
@ -35,6 +36,8 @@ namespace bsmd.AISService.AIS
private int assignedMode; private int assignedMode;
private int spare3; private int spare3;
private static ILog _log = LogManager.GetLogger(typeof(AIS_ClassBExt));
#endregion #endregion
#region Properties #region Properties
@ -120,7 +123,7 @@ namespace bsmd.AISService.AIS
catch (Exception e) catch (Exception e)
{ {
Trace.WriteLine(string.Format("Error decoding AIS class B Ext posreport: {0}", e.Message)); _log.WarnFormat("Error decoding AIS class B Ext posreport: {0}", e.Message);
result = Status.PARSE_ERROR; result = Status.PARSE_ERROR;
} }

View File

@ -1,7 +1,7 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Text; using System.Text;
using System.Diagnostics; using log4net;
namespace bsmd.AISService.AIS namespace bsmd.AISService.AIS
{ {
@ -17,6 +17,7 @@ namespace bsmd.AISService.AIS
private string callsign; private string callsign;
private int dimension; private int dimension;
private int spare; private int spare;
private static ILog _log = LogManager.GetLogger(typeof(AIS_ClassBStatic));
#endregion #endregion
@ -57,6 +58,10 @@ namespace bsmd.AISService.AIS
get { return this.shipType; } get { return this.shipType; }
} }
public int Dimension { get { return this.dimension; } }
public int Spare { get { return this.spare; } }
// Todo: Dimensions.. // Todo: Dimensions..
#endregion #endregion
@ -120,7 +125,7 @@ namespace bsmd.AISService.AIS
} }
catch (Exception e) catch (Exception e)
{ {
Trace.WriteLine(string.Format("Error decoding AIS class B static data: {0}", e.Message)); _log.WarnFormat("Error decoding AIS class B static data: {0}", e.Message);
result = Status.PARSE_ERROR; result = Status.PARSE_ERROR;
} }

View File

@ -1,7 +1,7 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Diagnostics; using System.Diagnostics;
using System.Text; using log4net;
namespace bsmd.AISService.AIS namespace bsmd.AISService.AIS
{ {
@ -23,6 +23,8 @@ namespace bsmd.AISService.AIS
private int raim; private int raim;
private int commstate; private int commstate;
private static ILog _log = LogManager.GetLogger(typeof(AIS_PosReport));
#region Properties #region Properties
public Guid Id { get { if (!this.id.HasValue) this.id = Guid.NewGuid(); return this.id.Value; } } public Guid Id { get { if (!this.id.HasValue) this.id = Guid.NewGuid(); return this.id.Value; } }
@ -38,9 +40,7 @@ namespace bsmd.AISService.AIS
{ {
get get
{ {
return string.Format("{0}-{1}-{2} {3}:{4}:{5}", return this.timestamp.ToString("yyyy-MM-ddTHH:mm:ss.000Z");
this.timestamp.Year, this.timestamp.Month, this.timestamp.Day,
this.timestamp.Hour, this.timestamp.Minute, this.timestamp.Second);
} }
} }
@ -181,7 +181,7 @@ namespace bsmd.AISService.AIS
} }
catch (Exception e) catch (Exception e)
{ {
Trace.WriteLine(string.Format("Error decoding AIS pos report: {0}", e.Message)); _log.WarnFormat("Error decoding AIS pos report: {0}", e.Message);
result = Status.PARSE_ERROR; result = Status.PARSE_ERROR;
} }

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Text; using System.Text;
using System.Timers; using System.Timers;
using System.Diagnostics; using System.Diagnostics;
using System.Threading;
namespace bsmd.AISService.AIS namespace bsmd.AISService.AIS
{ {
@ -25,8 +26,9 @@ public class AIS_QueueManager
private List<SerialDataHandler> serialHandlerList = new List<SerialDataHandler>(); private List<SerialDataHandler> serialHandlerList = new List<SerialDataHandler>();
private List<TelnetDataHandler> telnetHandlerList = new List<TelnetDataHandler>(); private List<TelnetDataHandler> telnetHandlerList = new List<TelnetDataHandler>();
private List<AIS_Target> dbUpdateQueue = new List<AIS_Target>(); private List<AIS_Target> dbUpdateQueue = new List<AIS_Target>();
private Timer dbUpdateTimer = new Timer(); private System.Timers.Timer dbUpdateTimer = new System.Timers.Timer();
private bool isStarted = false; private bool isStarted = false;
private Mutex dbSingleMutex = new Mutex();
#region Construction #region Construction
@ -78,37 +80,41 @@ public class AIS_QueueManager
void dbUpdateTimer_Elapsed(object sender, ElapsedEventArgs e) void dbUpdateTimer_Elapsed(object sender, ElapsedEventArgs e)
{ {
while (this.dbUpdateQueue.Count > 0)
if (dbSingleMutex.WaitOne(0))
{ {
AIS_Target currentTarget = null; while (this.dbUpdateQueue.Count > 0)
lock (this.dbUpdateQueue)
{ {
// Trace.WriteLine(string.Format("Update queue size: {0}", this.dbUpdateQueue.Count)); AIS_Target currentTarget = null;
currentTarget = this.dbUpdateQueue[0]; lock (this.dbUpdateQueue)
this.dbUpdateQueue.RemoveAt(0);
}
this.OnDBUpdateRequired(currentTarget);
}
// remove stale targets
lock (this.activeTargetList)
{
for(int i=0;i<this.activeTargetList.Count; i++)
{
if (!this.activeTargetList[i].LastUpdate.HasValue)
continue;
int diffmin = (int) (DateTime.Now - this.activeTargetList[i].LastUpdate.Value).TotalMinutes;
if (diffmin > this.configuration.TargetStaleMins)
{ {
this.activeTargetList.RemoveAt(i); // Trace.WriteLine(string.Format("Update queue size: {0}", this.dbUpdateQueue.Count));
i--; currentTarget = this.dbUpdateQueue[0];
this.dbUpdateQueue.RemoveAt(0);
}
this.OnDBUpdateRequired(currentTarget);
}
// remove stale targets
lock (this.activeTargetList)
{
for (int i = 0; i < this.activeTargetList.Count; i++)
{
if (!this.activeTargetList[i].LastUpdate.HasValue)
continue;
int diffmin = (int)(DateTime.Now - this.activeTargetList[i].LastUpdate.Value).TotalMinutes;
if (diffmin > this.configuration.TargetStaleMins)
{
this.activeTargetList.RemoveAt(i);
i--;
}
} }
} }
dbSingleMutex.ReleaseMutex();
} }
} }
void decoder_AISMessageReceived(AIS message) void decoder_AISMessageReceived(AIS message)

View File

@ -3,6 +3,8 @@ using System.Collections;
using System.Diagnostics; using System.Diagnostics;
using System.Text; using System.Text;
using log4net;
namespace bsmd.AISService.AIS namespace bsmd.AISService.AIS
{ {
public class AIS_StaticData : AIS public class AIS_StaticData : AIS
@ -32,6 +34,8 @@ namespace bsmd.AISService.AIS
private int dte; private int dte;
private int spare; private int spare;
private static ILog _log = LogManager.GetLogger(typeof(AIS_StaticData));
#endregion #endregion
#region Properties #region Properties
@ -120,22 +124,31 @@ namespace bsmd.AISService.AIS
} }
} }
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 public string DBETA
{ {
get get
{ {
if (this.eta.HasValue) if (this.eta.HasValue)
{ {
return string.Format("{0}-{1}-{2} {3}:{4}:{5}", return this.eta.Value.ToString("yyyy-MM-ddTHH:mm:ss.000Z");
this.eta.Value.Year, this.eta.Value.Month, this.eta.Value.Day,
this.eta.Value.Hour, this.eta.Value.Minute, this.eta.Value.Second);
} }
else else
{
return ""; return "";
}
} }
} }
#endregion #endregion
#region abstract method implementation #region abstract method implementation
@ -197,8 +210,8 @@ namespace bsmd.AISService.AIS
this.eta = new DateTime(DateTime.Now.Year, this.etamonth, this.etaday, this.etahour, this.etaminute, 0); this.eta = new DateTime(DateTime.Now.Year, this.etamonth, this.etaday, this.etahour, this.etaminute, 0);
} }
} }
catch(Exception) { catch(Exception e) {
Trace.WriteLine("ERROR creating ETA timestamp"); _log.WarnFormat("ETA timestamp creation failed: {0}", e.Message);
} }
this.maxpresetstaticdraught = AIS.GetInt(bits, 294, 301); this.maxpresetstaticdraught = AIS.GetInt(bits, 294, 301);
@ -219,7 +232,7 @@ namespace bsmd.AISService.AIS
} }
catch (Exception e) catch (Exception e)
{ {
Trace.WriteLine(string.Format("Error decoding AIS static data: {0}", e.Message)); _log.WarnFormat("Error decoding AIS static data: {0}", e.Message);
result = Status.PARSE_ERROR; result = Status.PARSE_ERROR;
} }
return result; return result;

View File

@ -13,6 +13,8 @@ using System.IO;
using System.Text; using System.Text;
using System.Net.Sockets; using System.Net.Sockets;
using log4net;
namespace bsmd.AISService.AIS namespace bsmd.AISService.AIS
{ {
public class AIS_Telnet public class AIS_Telnet
@ -29,6 +31,8 @@ namespace bsmd.AISService.AIS
private int port; private int port;
private DateTime? lastRead; private DateTime? lastRead;
private static ILog _log = LogManager.GetLogger(typeof(AIS_Telnet));
#endregion #endregion
public AIS_Telnet(string theHostname, int thePort) public AIS_Telnet(string theHostname, int thePort)
@ -99,7 +103,7 @@ namespace bsmd.AISService.AIS
} }
catch (Exception ex) catch (Exception ex)
{ {
System.Diagnostics.Trace.WriteLine(string.Format("exception reading from tcp stream: {0}", ex.Message)); _log.ErrorFormat("exception reading from tcp stream: {0}", ex.Message);
result = ""; result = "";
} }
} }
@ -114,7 +118,7 @@ namespace bsmd.AISService.AIS
{ {
this.tcpSocket.Close(); this.tcpSocket.Close();
this.tcpSocket = null; this.tcpSocket = null;
System.Diagnostics.Trace.WriteLine("closing inactive TcpClient"); _log.Info("closing inactive TcpClient");
this.lastRead = DateTime.Now; // reset timer this.lastRead = DateTime.Now; // reset timer
} }
} }
@ -138,12 +142,11 @@ namespace bsmd.AISService.AIS
if ((this.tcpSocket != null) && (this.tcpSocket.Connected)) return; if ((this.tcpSocket != null) && (this.tcpSocket.Connected)) return;
this.tcpSocket = new TcpClient(this.hostname, this.port); this.tcpSocket = new TcpClient(this.hostname, this.port);
this.tcpStream = tcpSocket.GetStream(); this.tcpStream = tcpSocket.GetStream();
System.Diagnostics.Trace.WriteLine(string.Format("TCP stream connected ({0}:{1})", this.hostname, this.port)); _log.InfoFormat("TCP stream connected ({0}:{1})", this.hostname, this.port);
} }
catch (Exception ex) catch (Exception ex)
{ {
System.Diagnostics.Trace.WriteLine( _log.WarnFormat("AIS_Telnet: cannot connect to ({0}:{1}) : {2}", this.hostname, this.port, ex.Message);
string.Format("AIS_Telnet: cannot connect to ({0}:{1}) : {2}", this.hostname, this.port, ex.Message));
} }
} }
} }

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using log4net;
namespace bsmd.AISService.AIS namespace bsmd.AISService.AIS
{ {
@ -10,6 +11,8 @@ namespace bsmd.AISService.AIS
protected string data; protected string data;
protected string[] elements = null; protected string[] elements = null;
protected static ILog _log = LogManager.GetLogger(typeof(NMEA));
public enum Status public enum Status
{ {
OK, OK,
@ -60,7 +63,7 @@ namespace bsmd.AISService.AIS
} }
catch (Exception ex) catch (Exception ex)
{ {
System.Diagnostics.Trace.WriteLine(string.Format("Error decoding sentence: {0}, {1}", ex.Message, ex.StackTrace)); _log.ErrorFormat("Error decoding sentence: {0}, {1}", ex.Message, ex.StackTrace);
return null; return null;
} }
} }

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using log4net;
namespace bsmd.AISService.AIS namespace bsmd.AISService.AIS
{ {
@ -75,11 +76,11 @@ namespace bsmd.AISService.AIS
{ {
string fillbits_string = this.elements[6].Substring(0, this.elements[6].IndexOf('*')); string fillbits_string = this.elements[6].Substring(0, this.elements[6].IndexOf('*'));
if(!Int32.TryParse(fillbits_string, out this.fillbits)) if(!Int32.TryParse(fillbits_string, out this.fillbits))
System.Diagnostics.Trace.WriteLine("AIS_Sentence.Decode(): fillbits are no integer"); _log.Warn("AIS_Sentence.Decode(): fillbits are no integer");
} }
catch (ArgumentOutOfRangeException) catch (ArgumentOutOfRangeException)
{ {
System.Diagnostics.Trace.WriteLine("AIS_Sentence.Decode(): split() problem, trouble decoding fillbits"); _log.Warn("AIS_Sentence.Decode(): split() problem, trouble decoding fillbits");
} }
} }
} }

View File

@ -48,7 +48,7 @@ namespace bsmd.AISService.AIS
} }
catch (FormatException) catch (FormatException)
{ {
Trace.WriteLine("NMEA [PNMLS] input format error"); _log.Warn("NMEA [PNMLS] input format error");
} }
} }

View File

@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using System.Diagnostics; using System.Diagnostics;
using log4net;
namespace bsmd.AISService.AIS namespace bsmd.AISService.AIS
{ {
@ -10,6 +11,8 @@ namespace bsmd.AISService.AIS
private Serial_IO serial_IO; private Serial_IO serial_IO;
private AIS_Decoder decoder; private AIS_Decoder decoder;
private static ILog _log = LogManager.GetLogger(typeof(SerialDataHandler));
public SerialDataHandler(Serial_IO io, AIS_Decoder decoder) public SerialDataHandler(Serial_IO io, AIS_Decoder decoder)
{ {
this.serial_IO = io; this.serial_IO = io;
@ -54,7 +57,7 @@ namespace bsmd.AISService.AIS
} }
else else
{ {
Trace.WriteLine("Serial data handler: NMEA decoder returned null sentence"); _log.Info("Serial data handler: NMEA decoder returned null sentence");
} }
} }

View File

@ -96,7 +96,6 @@ namespace bsmd.AISService.AIS
{ {
string line = this.port.ReadLine(); string line = this.port.ReadLine();
this.OnInputLineRead(line); this.OnInputLineRead(line);
//System.Diagnostics.Trace.WriteLine(line);
} }
catch (Exception) { } catch (Exception) { }
} }

View File

@ -12,6 +12,8 @@ using System.Collections.Generic;
using System.Threading; using System.Threading;
using System.Diagnostics; using System.Diagnostics;
using log4net;
namespace bsmd.AISService.AIS namespace bsmd.AISService.AIS
{ {
public class TelnetDataHandler public class TelnetDataHandler
@ -21,6 +23,8 @@ namespace bsmd.AISService.AIS
Thread readerThread; Thread readerThread;
bool requestStop; bool requestStop;
internal static ILog _log = LogManager.GetLogger(typeof(TelnetDataHandler));
public TelnetDataHandler(AIS_Telnet telnetConnection, AIS_Decoder aisDecoder) public TelnetDataHandler(AIS_Telnet telnetConnection, AIS_Decoder aisDecoder)
{ {
this.aisTelnet = telnetConnection; this.aisTelnet = telnetConnection;
@ -70,7 +74,7 @@ namespace bsmd.AISService.AIS
private void ReaderThread() private void ReaderThread()
{ {
NMEA.Status nmea_Status = NMEA.Status.OK; NMEA.Status nmea_Status = NMEA.Status.OK;
System.Diagnostics.Trace.WriteLine("starting telnet reader thread"); _log.Info("starting telnet reader thread");
while (!requestStop) while (!requestStop)
{ {
try try
@ -92,7 +96,7 @@ namespace bsmd.AISService.AIS
} }
else else
{ {
Trace.WriteLine("Serial data handler: NMEA decoder returned null/empty sentence"); _log.Info("Serial data handler: NMEA decoder returned null/empty sentence");
} }
} }
} }
@ -101,8 +105,7 @@ namespace bsmd.AISService.AIS
var st = new StackTrace(ex, true); var st = new StackTrace(ex, true);
var frame = st.GetFrame(0); var frame = st.GetFrame(0);
var line = frame.GetFileLineNumber(); var line = frame.GetFileLineNumber();
Trace.WriteLine(string.Format("Exception in telnet reader thread: {0}, top frame ln {1}", ex.Message, line)); _log.WarnFormat("Exception in telnet reader thread: {0}, top frame ln {1}", ex.Message, line);
Trace.WriteLine(ex.StackTrace);
} }
Thread.Sleep(100); Thread.Sleep(100);
} }

View File

@ -66,6 +66,7 @@ namespace bsmd.AISService
protected override void OnStop() protected override void OnStop()
{ {
this.qManager.Stop(); this.qManager.Stop();
_log.Info("AIS Service stopped.");
} }
protected void Init(string[] args) protected void Init(string[] args)
@ -74,7 +75,7 @@ namespace bsmd.AISService
if (configuration == null) if (configuration == null)
{ {
Console.WriteLine(string.Format("cannot read configuration {0}", config_filename)); _log.ErrorFormat("cannot read configuration {0}", config_filename);
return; return;
} }
@ -82,7 +83,7 @@ namespace bsmd.AISService
dbConnector.ConnectionString = configuration.DBConnectionString; dbConnector.ConnectionString = configuration.DBConnectionString;
if (!dbConnector.Open()) if (!dbConnector.Open())
{ {
Console.WriteLine("Error connecting to database"); _log.Error("Error connecting to database");
return; return;
} }
@ -90,14 +91,15 @@ namespace bsmd.AISService
this.qManager = new AIS_QueueManager(configuration, AISStation.CreateSerial_IOs(stationList), AISStation.CreateAIS_Telnets(stationList)); this.qManager = new AIS_QueueManager(configuration, AISStation.CreateSerial_IOs(stationList), AISStation.CreateAIS_Telnets(stationList));
qManager.DBUpdateRequired += new AIS_QueueManager.AISQueueChangedHandler(dbConnector.Update); qManager.DBUpdateRequired += new AIS_QueueManager.AISQueueChangedHandler(dbConnector.Update);
qManager.AISQueueChanged += new AIS_QueueManager.AISQueueChangedHandler(aisDecoder_AISMessageReceived); // qManager.AISQueueChanged += new AIS_QueueManager.AISQueueChangedHandler(aisDecoder_AISMessageReceived);
} }
/*
protected void aisDecoder_AISMessageReceived(AIS_Target target) protected void aisDecoder_AISMessageReceived(AIS_Target target)
{ {
Console.WriteLine(string.Format("{0}: {1} Pos:{2} {3} at {4}", target.Station, target.Name, target.Latitude, target.Longitude, target.LastUpdate)); Console.WriteLine(string.Format("{0}: {1} Pos:{2} {3} at {4}", target.Station, target.Name, target.Latitude, target.Longitude, target.LastUpdate));
} }
*/
} }
} }

View File

@ -4,7 +4,31 @@
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" > <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="bsmd.AISService.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" /> <section name="bsmd.AISService.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup> </sectionGroup>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,Log4net"/>
</configSections> </configSections>
<log4net>
<root>
<level value="ALL"/>
<appender-ref ref="LogFileAppender"/>
<appender-ref ref="TraceAppender"/>
</root>
<appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender">
<param name="File" value="C:\work\Logs\AISService.log"/>
<param name="AppendToFile" value="true"/>
<rollingStyle value="Size"/>
<maxSizeRollBackups value="10"/>
<maximumFileSize value="10MB"/>
<staticLogFileName value="true"/>
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%date [%thread] %-5level [%logger] - %message%newline"/>
</layout>
</appender>
<appender name="TraceAppender" type="log4net.Appender.TraceAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%d [%t] %-5p %c %m%n"/>
</layout>
</appender>
</log4net>
<startup> <startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" /> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup> </startup>

View File

@ -8,12 +8,14 @@ using System.Collections.Generic;
using System.Text; using System.Text;
using bsmd.AISService.AIS; using bsmd.AISService.AIS;
using log4net;
namespace bsmd.AISService.DB namespace bsmd.AISService.DB
{ {
internal class AISPosReport : AISBaseEntity {
private static ILog _log = LogManager.GetLogger(typeof(AISPosReport));
internal class AISPosReport : AISBaseEntity
{
/// <summary> /// <summary>
/// Saves a (class A or B) position report /// Saves a (class A or B) position report
/// </summary> /// </summary>
@ -51,8 +53,8 @@ namespace bsmd.AISService.DB
AIS_ClassB pr = target.LastPosReport as AIS_ClassB; AIS_ClassB pr = target.LastPosReport as AIS_ClassB;
aisStation.UpdateWithPositionReport(pr.MMSI, pr.Latitude, pr.Longitude, pr.Timestamp); aisStation.UpdateWithPositionReport(pr.MMSI, pr.Latitude, pr.Longitude, pr.Timestamp);
string query = string.Format("INSERT INTO aisposreport (Id, MMSI, NavStatus, ROT, COG, SOG, Accuracy, Longitude, Latitude, Heading, Timestamp, Reserved, Spare, Raim, CommState, Stationid) VALUES ('{0}', {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}, '{10}', {11},{12},{13},{14},'{15}')", string query = string.Format("INSERT INTO aisposreport (Id, MMSI, NavStatus, ROT, COG, SOG, Accuracy, Longitude, Latitude, Heading, Timestamp, Reserved, Spare, Raim, CommState, AISStationId) VALUES ('{0}', {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}, '{10}', {11}, {12}, {13}, {14}, '{15}')",
pr.MMSI, 0, 0, pr.CogVal, pr.SogVal, 0, pr.LongitudeVal, pr.LatitudeVal, pr.Id, pr.MMSI, 0, 0, pr.CogVal, pr.SogVal, 0, pr.LongitudeVal, pr.LatitudeVal,
pr.TrueHeading ?? 511, pr.DBTimestamp, pr.Reserved, pr.Spare, pr.Raim, pr.CommState, (aisStation != null) ? aisStation.Id : Guid.Empty); pr.TrueHeading ?? 511, pr.DBTimestamp, pr.Reserved, pr.Spare, pr.Raim, pr.CommState, (aisStation != null) ? aisStation.Id : Guid.Empty);
con.ExecuteNonQuery(query); con.ExecuteNonQuery(query);
@ -62,12 +64,12 @@ namespace bsmd.AISService.DB
if (target.LastPosReport is AIS_ClassBExt) if (target.LastPosReport is AIS_ClassBExt)
{ {
Trace.WriteLine("AIS class B ext not supported (yet)"); _log.Info("AIS class B ext not supported (yet)");
// TODO: Import ClassB Extended report!
} }
Trace.WriteLine(string.Format("save pos report: we should not be here.. class type: {0}", target)); _log.WarnFormat("save pos report: we should not be here.. class type: {0}", target);
return null; return null;
} }

View File

@ -6,6 +6,7 @@ using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using bsmd.AISService.AIS; using bsmd.AISService.AIS;
using log4net;
namespace bsmd.AISService.DB namespace bsmd.AISService.DB
{ {
@ -21,6 +22,7 @@ namespace bsmd.AISService.DB
} }
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"; 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";
private static ILog _log = LogManager.GetLogger(typeof(AISStaticData));
#region Fields #region Fields
@ -188,12 +190,12 @@ namespace bsmd.AISService.DB
/// </summary> /// </summary>
/// <param name="target">target to save</param> /// <param name="target">target to save</param>
/// <returns>id of insert operation (to update hotposition table)</returns> /// <returns>id of insert operation (to update hotposition table)</returns>
public static int? Save(AIS_Target target, DBConnector con, AISStation aisStation) public static Guid? Save(AIS_Target target, DBConnector con, AISStation aisStation)
{ {
if(target.LastStaticData == null) return null; if(target.LastStaticData == null) return null;
int mmsi = -1; int mmsi = -1;
int id = -1; Guid id = Guid.Empty;
if(target.LastStaticData is AIS_StaticData) { if(target.LastStaticData is AIS_StaticData) {
mmsi = ((AIS_StaticData)target.LastStaticData).MMSI; mmsi = ((AIS_StaticData)target.LastStaticData).MMSI;
@ -207,7 +209,7 @@ namespace bsmd.AISService.DB
if (result != null) // update if (result != null) // update
{ {
id = Convert.ToInt32(result); id = (Guid) result;
} }
#region Class A #region Class A
@ -216,87 +218,58 @@ namespace bsmd.AISService.DB
{ {
AIS_StaticData staticData = target.LastStaticData as AIS_StaticData; AIS_StaticData staticData = target.LastStaticData as AIS_StaticData;
if (id >= 0) if (id != Guid.Empty)
{ {
if (staticData.ETA.HasValue) query = string.Format("UPDATE aisstaticdata SET imonumber={0}, callsign='{1}', name='{2}', shiptype={3}, dimension={4}, typeofdevice={5}, maxpresetstaticdraught={6}, " +
{ "destination='{7}', dte={8}, spare={9}, mmsi={10}, eta={11}, classb={12}, breadth={13}, length={14}, aisstation_id='{15}' " +
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}", "WHERE Id='{16}'",
staticData.IMONumber, staticData.IMONumber,
staticData.Callsign.Replace("'","''"), (staticData.Callsign ?? "").Replace("'", "''"),
staticData.Name.Replace("'", "''"), (staticData.Name ?? "").Replace("'", "''"),
staticData.ShipTypeVal, staticData.ShipTypeVal,
staticData.DeviceName, staticData.DBDimension,
staticData.ShipType, staticData.DBTypeOfDevice,
staticData.DBETA, staticData.Draught,
staticData.Destination.Replace("'", "''"), (staticData.Destination ?? "").Replace("'", "''"),
staticData.Breadth, staticData.DTE,
staticData.Length, staticData.Spare,
staticData.Draught, staticData.MMSI,
aisStation.Id, staticData.ETA.HasValue ? string.Format("'{0}'", staticData.DBETA) : "NULL",
id); 0,
} staticData.Breadth,
else staticData.Length,
{ aisStation.Id,
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}", id);
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); con.ExecuteNonQuery(query);
} }
else else
{ {
if (staticData.ETA.HasValue) id = Guid.NewGuid();
{
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", query = string.Format("INSERT INTO aisstaticdata (Id, aisversion, imoNumber, callsign, name, shiptype, dimension, typeofdevice, maxpresetstaticdraught, destination, " +
staticData.IMONumber, "dte, spare, mmsi, eta, classb, breadth, length, aisstation_id) VALUES ('{0}', {1}, {2}, '{3}', '{4}', {5}, {6}, {7}, {8}, '{9}', {10}, {11}, {12}, {13}, {14}, {15}, {16}, '{17}')",
staticData.Callsign.Replace("'", "''"), id,
staticData.Name.Replace("'", "''"), 0,
staticData.ShipTypeVal, staticData.IMONumber,
staticData.DeviceName, (staticData.Callsign ?? "").Replace("'", "''"),
staticData.ShipType, (staticData.Name ?? "").Replace("'", "''"),
staticData.DBETA, staticData.ShipTypeVal,
staticData.Destination.Replace("'", "''"), staticData.DBDimension,
staticData.Breadth, staticData.DBTypeOfDevice,
staticData.Length, staticData.Draught,
staticData.Draught, (staticData.Destination ?? "").Replace("'", "''"),
aisStation.Id, staticData.DTE,
staticData.MMSI); staticData.Spare,
} staticData.MMSI,
else staticData.ETA.HasValue ? string.Format("'{0}'", staticData.DBETA) : "NULL",
{ 0,
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.Breadth,
staticData.IMONumber, staticData.Length,
staticData.Callsign.Replace("'", "''"), aisStation.Id.Value);
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); con.ExecuteNonQuery(query);
id = Convert.ToInt32(con.ExecuteScalar("SELECT LAST_INSERT_ID()"));
} }
} }
#endregion #endregion
@ -307,31 +280,32 @@ namespace bsmd.AISService.DB
{ {
AIS_ClassBStatic staticData = target.LastStaticData as AIS_ClassBStatic; AIS_ClassBStatic staticData = target.LastStaticData as AIS_ClassBStatic;
if (id >= 0) // Update if (id != Guid.Empty) // Update
{ {
query = string.Format("UPDATE aisstaticdata SET stationid={0}, shiptype={1}, classb=1", aisStation.Id, staticData.ShipTypeVal); query = string.Format("UPDATE aisstaticdata SET aisstation_id = '{0}', shiptype={1}, classb=1, dimension = {2}, spare = {3}",
if(staticData.Callsign != null) query += string.Format(", callsign='{0}'", staticData.Callsign); aisStation.Id, staticData.ShipTypeVal, staticData.Dimension, staticData.Spare);
if(staticData.Name != null) query += string.Format(", name='{0}'", staticData.Name); if(staticData.Callsign != null) query += string.Format(", callsign='{0}'", staticData.Callsign.Replace("'", "''"));
if(staticData.VendorId != null) query += string.Format(", typeofdevice='{0}'", staticData.VendorId); if(staticData.Name != null) query += string.Format(", name='{0}'", staticData.Name.Replace("'","''"));
if(staticData.ShipType != null) query += string.Format(", shipdescription='{0}'", staticData.ShipType); query += string.Format(" WHERE Id='{0}'", id);
query += string.Format(" WHERE id={0}", id);
con.ExecuteNonQuery(query); con.ExecuteNonQuery(query);
} }
else // Insert 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", id = Guid.NewGuid();
staticData.Callsign, query = string.Format("INSERT INTO aisstaticdata (Id, callsign, name, shiptype, classb, dimension, spare, aisstation_id, mmsi) VALUES ('{0}', '{1}', '{2}', {3}, {4}, {5}, {6}, '{7}', {8})",
staticData.Name, id,
(staticData.Callsign ?? "").Replace("'","''"),
(staticData.Name ?? "").Replace("'","''"),
staticData.ShipTypeVal, staticData.ShipTypeVal,
staticData.VendorId, 1,
staticData.ShipType, staticData.Dimension,
staticData.Spare,
aisStation.Id, aisStation.Id,
staticData.MMSI staticData.MMSI
); );
con.ExecuteNonQuery(query); con.ExecuteNonQuery(query);
id = Convert.ToInt32(con.ExecuteScalar("SELECT LAST_INSERT_ID()"));
} }
} }
@ -412,7 +386,7 @@ namespace bsmd.AISService.DB
result.Add(ship); result.Add(ship);
} }
reader.Close(); reader.Close();
Trace.WriteLine(string.Format("AISStaticData: {0} ships loaded from DB", result.Count)); _log.InfoFormat("AISStaticData: {0} ships loaded from DB", result.Count);
return result; return result;
} }

View File

@ -5,6 +5,7 @@ using System.Data;
using System.Globalization; using System.Globalization;
using bsmd.AISService.AIS; using bsmd.AISService.AIS;
using log4net;
namespace bsmd.AISService.DB namespace bsmd.AISService.DB
{ {
@ -13,7 +14,6 @@ namespace bsmd.AISService.DB
{ {
#region private members #region private members
private Guid station_Id;
private string name; private string name;
private bool active; private bool active;
private string comport; private string comport;
@ -30,6 +30,7 @@ namespace bsmd.AISService.DB
private DateTime? lastPosTimestamp; private DateTime? lastPosTimestamp;
private bool isDirty = false; private bool isDirty = false;
private Dictionary<int, double> targets = new Dictionary<int, double>(); private Dictionary<int, double> targets = new Dictionary<int, double>();
private static ILog _log = LogManager.GetLogger(typeof(AISStation));
#endregion #endregion
@ -101,7 +102,7 @@ namespace bsmd.AISService.DB
this.comport, this.comport,
this.name, this.name,
this.baudrate, this.baudrate,
this.station_Id); this.Id);
if (con.ExecuteNonQuery(query) == 1) if (con.ExecuteNonQuery(query) == 1)
{ {
@ -177,7 +178,7 @@ namespace bsmd.AISService.DB
while (reader.Read()) while (reader.Read())
{ {
AISStation station = new AISStation(); AISStation station = new AISStation();
station.station_Id = reader.GetGuid(0); station.Id = reader.GetGuid(0);
station.name = reader.GetString(1); station.name = reader.GetString(1);
station.active = reader.GetBoolean(2); station.active = reader.GetBoolean(2);
station.latitude = (double) reader.GetInt32(3) / 600000; station.latitude = (double) reader.GetInt32(3) / 600000;
@ -201,11 +202,11 @@ namespace bsmd.AISService.DB
public static AISStation CreateStation(string name, DBConnector con) public static AISStation CreateStation(string name, DBConnector con)
{ {
AISStation newStation = new AISStation(); AISStation newStation = new AISStation();
newStation.station_Id = Guid.NewGuid(); newStation.Id = Guid.NewGuid();
newStation.name = name; newStation.name = name;
newStation.active = true; newStation.active = true;
string query = string.Format("INSERT INTO aisstation SET Id='{0}', name='{1}',active=1", string query = string.Format("INSERT INTO aisstation SET Id='{0}', name='{1}',active=1",
newStation.station_Id, newStation.name); newStation.Id, newStation.name);
con.ExecuteNonQuery(query); con.ExecuteNonQuery(query);
return newStation; return newStation;
@ -243,8 +244,7 @@ namespace bsmd.AISService.DB
} }
catch (Exception ex) catch (Exception ex)
{ {
System.Diagnostics.Trace.WriteLine(string.Format("AIS_Telnet: cannot connect to host {0} port {1}: {2}", _log.WarnFormat("AIS_Telnet: cannot connect to host {0} port {1}: {2}", station.TelnetHost ?? "", station.TelnetPort, ex.Message);
station.TelnetHost ?? "", station.TelnetPort, ex.Message));
} }
} }
} }

View File

@ -9,6 +9,7 @@ using System.Data;
using System.Data.SqlClient; using System.Data.SqlClient;
using bsmd.AISService.AIS; using bsmd.AISService.AIS;
using log4net;
namespace bsmd.AISService.DB namespace bsmd.AISService.DB
{ {
@ -20,6 +21,7 @@ namespace bsmd.AISService.DB
private List<AISWatchkeeper> watchkeeperShips = null; private List<AISWatchkeeper> watchkeeperShips = null;
private List<AISStaticData> dbShips = null; private List<AISStaticData> dbShips = null;
private Dictionary<string, AISStation> updateStations = null; private Dictionary<string, AISStation> updateStations = null;
private static ILog _log = LogManager.GetLogger(typeof(DBConnector));
public DBConnector() { } public DBConnector() { }
@ -65,21 +67,48 @@ namespace bsmd.AISService.DB
if (!this.CheckConnection()) return null; if (!this.CheckConnection()) return null;
SqlCommand cmd = new SqlCommand(query, this.dbCon); SqlCommand cmd = new SqlCommand(query, this.dbCon);
return cmd.ExecuteReader(); SqlDataReader result = null;
try
{
result = cmd.ExecuteReader();
}
catch(SqlException ex)
{
_log.ErrorFormat("ExecuteQuery: {0}", ex.Message);
}
return result;
} }
public int ExecuteNonQuery(string query) public int ExecuteNonQuery(string query)
{ {
if (!this.CheckConnection()) return 0; if (!this.CheckConnection()) return 0;
SqlCommand cmd = new SqlCommand(query, this.dbCon); SqlCommand cmd = new SqlCommand(query, this.dbCon);
return cmd.ExecuteNonQuery(); int result = -1;
try
{
result = cmd.ExecuteNonQuery();
}
catch(SqlException ex)
{
_log.ErrorFormat("ExecuteNonQuery: [{0}] {1} ", query, ex.Message);
}
return result;
} }
public object ExecuteScalar(string query) public object ExecuteScalar(string query)
{ {
if (!this.CheckConnection()) return 0; if (!this.CheckConnection()) return 0;
SqlCommand cmd = new SqlCommand(query, this.dbCon); SqlCommand cmd = new SqlCommand(query, this.dbCon);
return cmd.ExecuteScalar(); object result = null;
try
{
result = cmd.ExecuteScalar();
}
catch(SqlException ex)
{
_log.ErrorFormat("ExecuteScalar: [{0}] {1} ", query, ex.Message);
}
return result;
} }
public bool Open() public bool Open()
@ -94,7 +123,7 @@ namespace bsmd.AISService.DB
} }
catch (SqlException anException) catch (SqlException anException)
{ {
Trace.WriteLine(string.Format("cannot open SQL DB connection: {0}", anException.Message)); _log.ErrorFormat("cannot open SQL DB connection: {0}", anException.Message);
} }
return false; return false;
} }
@ -120,9 +149,9 @@ namespace bsmd.AISService.DB
if (this.updateStations == null) if (this.updateStations == null)
{ {
this.updateStations = new Dictionary<string, AISStation>(); this.updateStations = new Dictionary<string, AISStation>();
Trace.WriteLine("loading stations.."); _log.Info("loading stations..");
List<AISStation> stations = AISStation.LoadStations(this); List<AISStation> stations = AISStation.LoadStations(this);
Trace.WriteLine(string.Format("{0} stations loaded", stations.Count)); _log.InfoFormat("{0} stations loaded", stations.Count);
foreach (AISStation station in stations) foreach (AISStation station in stations)
if (!updateStations.ContainsKey(station.Name)) if (!updateStations.ContainsKey(station.Name))
updateStations.Add(station.Name, station); updateStations.Add(station.Name, station);
@ -140,7 +169,7 @@ namespace bsmd.AISService.DB
} }
else else
{ {
Trace.WriteLine(string.Format("last pos report is null for target {0}", target.MMSI)); _log.InfoFormat("last pos report is null for target {0}", target.MMSI);
} }
if (target.LastStaticData != null) if (target.LastStaticData != null)
{ {
@ -153,8 +182,9 @@ namespace bsmd.AISService.DB
} }
target.UpdateDB = false; // reset update flag target.UpdateDB = false; // reset update flag
// Watchkeeper check
// Watchkeeper check
/*
if (this.watchkeeperShips == null) if (this.watchkeeperShips == null)
this.watchkeeperShips = AISWatchkeeper.GetWatchkeeperShips(this); this.watchkeeperShips = AISWatchkeeper.GetWatchkeeperShips(this);
@ -170,7 +200,7 @@ namespace bsmd.AISService.DB
if (!target.IsWatchkeeperShip.HasValue) // didn't find it if (!target.IsWatchkeeperShip.HasValue) // didn't find it
target.IsWatchkeeperShip = false; target.IsWatchkeeperShip = false;
} }
*/
} }
@ -200,7 +230,7 @@ namespace bsmd.AISService.DB
} }
catch (SqlException ex) catch (SqlException ex)
{ {
System.Diagnostics.Trace.WriteLine(ex.ToString()); _log.Error(ex.ToString());
} }
} }
return this.dbCon.State == System.Data.ConnectionState.Open; return this.dbCon.State == System.Data.ConnectionState.Open;

View File

@ -22,6 +22,9 @@ namespace bsmd.AISService
/// </summary> /// </summary>
public static int Main(string[] args) public static int Main(string[] args)
{ {
log4net.Config.XmlConfigurator.Configure();
if (Environment.UserInteractive) if (Environment.UserInteractive)
{ {
if (args.Length > 0) if (args.Length > 0)
@ -85,7 +88,7 @@ namespace bsmd.AISService
if (ex.InnerException != null && ex.InnerException.GetType() == typeof(Win32Exception)) if (ex.InnerException != null && ex.InnerException.GetType() == typeof(Win32Exception))
{ {
Win32Exception wex = (Win32Exception)ex.InnerException; Win32Exception wex = (Win32Exception)ex.InnerException;
Console.WriteLine("Error(0x{0:X}): Service already installed!", wex.ErrorCode); Console.WriteLine("Error {0}: {1}", wex.ErrorCode, wex.Message);
return wex.ErrorCode; return wex.ErrorCode;
} }
else else

View File

@ -33,6 +33,7 @@
// //
// serviceProcessInstallerAIS // serviceProcessInstallerAIS
// //
this.serviceProcessInstallerAIS.Account = System.ServiceProcess.ServiceAccount.LocalSystem;
this.serviceProcessInstallerAIS.Password = null; this.serviceProcessInstallerAIS.Password = null;
this.serviceProcessInstallerAIS.Username = null; this.serviceProcessInstallerAIS.Username = null;
// //

View File

@ -118,7 +118,7 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<metadata name="serviceProcessInstallerAIS.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> <metadata name="serviceProcessInstallerAIS.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value> <value>17, 54</value>
</metadata> </metadata>
<metadata name="serviceInstallerAIS.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> <metadata name="serviceInstallerAIS.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>196, 17</value> <value>196, 17</value>

View File

@ -102,7 +102,9 @@
</Compile> </Compile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="App.config" /> <None Include="App.config">
<SubType>Designer</SubType>
</None>
<None Include="bsmd.AISService.licenseheader" /> <None Include="bsmd.AISService.licenseheader" />
<None Include="bsmdKey.snk" /> <None Include="bsmdKey.snk" />
<None Include="packages.config" /> <None Include="packages.config" />

Binary file not shown.