SafeDispatch/ServiceGatewaySDR/SDRGatewayService.cs
2024-02-22 18:43:59 +02:00

497 lines
19 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using System.Runtime.InteropServices;
using SafeMobileLib;
using System.Text.RegularExpressions;
using SafeMobileLib.Registration;
using SafeMobileLib.Helpers;
using System.Configuration;
using System.Windows.Controls;
using SDRGatewayService.Enums;
using System.Threading;
namespace SDRGatewayService
{
//sc create SDRGatewayService binPath="E:\WorkSpace_cSharp\SafeDispatch_v4\ServiceGatewaySDR\bin\Debug\SDRGatewayService.exe" start= auto
//C:\Windows\Microsoft.NET\Framework64\v4.0.30319>InstallUtil.exe /u E:\WorkSpace_cSharp\Services\MyNewService\MyNewService\bin\Debug\SDRGatewayService.exe
public enum ServiceState
{
SERVICE_STOPPED = 0x00000001,
SERVICE_START_PENDING = 0x00000002,
SERVICE_STOP_PENDING = 0x00000003,
SERVICE_RUNNING = 0x00000004,
SERVICE_CONTINUE_PENDING = 0x00000005,
SERVICE_PAUSE_PENDING = 0x00000006,
SERVICE_PAUSED = 0x00000007,
}
[StructLayout(LayoutKind.Sequential)]
public struct ServiceStatus
{
public int dwServiceType;
public ServiceState dwCurrentState;
public int dwControlsAccepted;
public int dwWin32ExitCode;
public int dwServiceSpecificExitCode;
public int dwCheckPoint;
public int dwWaitHint;
};
public partial class SDRGatewayService : ServiceBase
{
public bool registered = false;
private int eventId = 1;
private SDR SDRConnector;
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool SetServiceStatus(IntPtr handle, ref ServiceStatus serviceStatus);
public SDRGatewayService(string[] args)
{
InitializeComponent();
string eventSourceName = "SDRGatewayServiceSource";
string logName = "SDRGatewayServiceLog";
if (args.Count() > 0)
{
eventSourceName = args[0];
}
if (args.Count() > 1)
{
logName = args[1];
}
eventLog1 = new System.Diagnostics.EventLog();
if (!System.Diagnostics.EventLog.SourceExists(eventSourceName))
{
System.Diagnostics.EventLog.CreateEventSource(eventSourceName, logName);
}
eventLog1.Source = eventSourceName;
eventLog1.Log = logName;
}
protected override void OnStart(string[] args)
{
// Update the service state to Start Pending.
ServiceStatus serviceStatus = new ServiceStatus();
serviceStatus.dwCurrentState = ServiceState.SERVICE_START_PENDING;
serviceStatus.dwWaitHint = 100000;
SetServiceStatus(this.ServiceHandle, ref serviceStatus);
// Set up a timer to trigger every minute.
System.Timers.Timer timer = new System.Timers.Timer();
timer.Interval = 20000; // 60 seconds
timer.Elapsed += new System.Timers.ElapsedEventHandler(this.OnTimer);
timer.Start();
// Update the service state to Running.
serviceStatus.dwCurrentState = ServiceState.SERVICE_RUNNING;
SetServiceStatus(this.ServiceHandle, ref serviceStatus);
this.OnRegistrationCompleted += OnRegistrationResponseHandler;
Register(true);
}
public void OnTimer(object sender, ElapsedEventArgs e)
{
if (!registered)
Register(true);
}
protected override void OnStop()
{
}
private void eventLog1_EntryWritten(object sender, EntryWrittenEventArgs e)
{
}
//#region Service COntrol
///// <summary>
///// Start a service by it's name
///// </summary>
///// <param name="ServiceName"></param>
//public void startService(string ServiceName)
//{
// ServiceController sc = new ServiceController();
// sc.ServiceName = ServiceName;
// Console.WriteLine("The {0} service status is currently set to {1}", ServiceName, sc.Status.ToString());
// if (sc.Status == ServiceControllerStatus.Stopped)
// {
// // Start the service if the current status is stopped.
// Console.WriteLine("Starting the {0} service ...", ServiceName);
// try
// {
// // Start the service, and wait until its status is "Running".
// sc.Start();
// sc.WaitForStatus(ServiceControllerStatus.Running);
// // Display the current service status.
// Console.WriteLine("The {0} service status is now set to {1}.", ServiceName, sc.Status.ToString());
// }
// catch (InvalidOperationException e)
// {
// Console.WriteLine("Could not start the {0} service.", ServiceName);
// Console.WriteLine(e.Message);
// }
// }
// else
// {
// Console.WriteLine("Service {0} already running.", ServiceName);
// }
//}
///// <summary>
///// Stop a service that is active
///// </summary>
///// <param name="ServiceName"></param>
//public void stopService(string ServiceName)
//{
// ServiceController sc = new ServiceController();
// sc.ServiceName = ServiceName;
// Console.WriteLine("The {0} service status is currently set to {1}", ServiceName, sc.Status.ToString());
// if (sc.Status == ServiceControllerStatus.Running)
// {
// // Start the service if the current status is stopped.
// Console.WriteLine("Stopping the {0} service ...", ServiceName);
// try
// {
// // Start the service, and wait until its status is "Running".
// sc.Stop();
// sc.WaitForStatus(ServiceControllerStatus.Stopped);
// // Display the current service status.
// Console.WriteLine("The {0} service status is now set to {1}.", ServiceName, sc.Status.ToString());
// }
// catch (InvalidOperationException e)
// {
// Console.WriteLine("Could not stop the {0} service.", ServiceName);
// Console.WriteLine(e.Message);
// }
// }
// else
// {
// Console.WriteLine("Cannot stop service {0} because it's already inactive.", ServiceName);
// }
//}
//public bool IsServiceRunning(string ServiceName)
//{
// ServiceController sc = new ServiceController();
// sc.ServiceName = ServiceName;
// if (sc.Status == ServiceControllerStatus.Running)
// {
// return true;
// }
// else
// {
// return false;
// }
//}
//#endregion
#region MainForm
private MessageBuss msgBuss;
private SMSmanager sms;
private PingThread pingThread;
private Gateway currentGateway = null;
UInt32 callOutNumber = 1;
byte cm_msg_id = 1;
public void MainForm()
{
Version v = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
Utils.WriteEventLog(Program.COMPANY, "Version: " + v.ToString() +Environment.NewLine +
"SDR gateway. SafeMobile 2012-2017", EventLogEntryType.Information, (int)EventId.EVENT_SDR);
ConfigurationManager.AppSettings.Set("SDR_Autoconnect", "true");
}
void pingThread_OnNewPingComplete(bool status, string ip)
{
if (status)
{
Utils.WriteLine("Ping to " + ip + " succeded");
}
else
{
Utils.WriteLine("Ping to " + ip + " failed");
}
}
/// <summary>
/// Verify if an IP address is a valid IP address
/// </summary>
/// <param name="ip">IP which needs to be checked</param>
/// <returns>True if the email is a valid one, or false otherwise</returns>
bool IsValidIP(string ip)
{
Match match = Regex.Match(ip, @"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}");
return match.Success;
}
delegate void PropertyChangedCallback(SDR.SDR_STATUS register);
void SDRConnector_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
Utils.WriteEventLog(Program.COMPANY, "New value for radio status: " + ((SDR)sender).registered, EventLogEntryType.Information, (int)EventId.EVENT_SDR);
}
private async void Register(bool registered)
{
RegistrationResponse regResponse = await RegistrationHelper.RegisterGateway(ConfigHelper.ServerIP, ConfigHelper.RegPort);
// raise event for registration completed
OnRegistrationCompleted?.Invoke(regResponse);
}
#region REGISTRATION HANDLER
private void OnRegistrationResponseHandler(RegistrationResponse regResponse)
{
switch (regResponse.RegistrationStatus)
{
case RegistrationCode.ServerUnreachable:
onRegistrationServerUnreachable();
break;
case RegistrationCode.Unauthorized:
onRegistraionUnauthorized();
break;
case RegistrationCode.Registered:
onRegistrationCompleted(regResponse);
registered = true;
break;
}
}
//need to add a way to reconnect.
private void onRegistrationServerUnreachable()
{
Utils.WriteEventLog(Program.COMPANY, "Application Server is unreachable. Please check internet connection and the application server IP in the configuration file.", EventLogEntryType.Error, (int)EventId.EVENT_SDR);
if(!ServiceControlUtils.IsServiceRunning("AppServerService"))
ServiceControlUtils.startService("AppServerService");
registered = false;
}
//need to add a way to reconnect.
private void onRegistraionUnauthorized()
{
Utils.WriteEventLog(Program.COMPANY, "Please register this gateway in the admin module.", EventLogEntryType.Error, (int)EventId.EVENT_SDR);
registered = false;
}
private void onRegistrationCompleted(RegistrationResponse response)
{
String currentIP = "127.0.0.1";
// this gateway is on other computer than the application server is
if (!ConfigHelper.ServerIP.Equals("127.0.0.1"))
currentIP = RegistrationHelper.GatewayIP;
// update values for Message bus, database received from AppServer
ConfigurationManager.AppSettings.Set("dbIP", response.DataBaseServerIP);
ConfigurationManager.AppSettings.Set("dbPassword", response.DataBasePassword);
ConfigurationManager.AppSettings.Set("dbPort", response.DataBasePort.ToString());
ConfigurationManager.AppSettings.Set("dbSchema", response.DataBaseName);
ConfigurationManager.AppSettings.Set("dbUser", response.DataBaseUser);
ConfigurationManager.AppSettings.Set("busIP", response.MessageBusIP);
ConfigurationManager.AppSettings.Set("busPort", response.MessageBusPort.ToString());
DBgatewaysManager gatewayManager = new DBgatewaysManager(ConfigHelper.DBip, ConfigHelper.DBSchema,
ConfigHelper.DBUser, ConfigHelper.DBPassword, ConfigHelper.DBPort);
// get current gateway
currentGateway = getGateway(currentIP, gatewayManager);
List<RadioGateway> radioGws = getRadioGWsFromDB(currentGateway.Id, gatewayManager);
// check if any sdr gateway is defined
if (radioGws.Count == 0)
{
onNoRadioGatewayDefined();
return;
}
else
{
RadioGateway currentRadioGw = radioGws[0];
// search for radioGws with same identifier as this gateway
foreach (RadioGateway rg in radioGws)
{
if (rg.Name.ToLower().Equals(ConfigHelper.GatewayName.ToLower()))
{
currentRadioGw = rg;
break;
}
}
// update values for current gateway
ConfigurationManager.AppSettings.Set("SDR_ISSI", currentRadioGw.Imei.ToString());
ConfigurationManager.AppSettings.Set("SDR_IP", currentRadioGw.Ip);
// remove all others gateways from the list
radioGws.Clear();
radioGws.Add(currentRadioGw);
}
if (ConfigHelper.SdrPing > 0)
{
pingThread = new PingThread(ConfigHelper.SdrIp, ConfigHelper.SdrPing);
pingThread.OnNewPingComplete += new PingThread.NewPingCompleteDEl(pingThread_OnNewPingComplete);
}
Utils.WriteEventLog(Program.COMPANY, "Starting application.", EventLogEntryType.Information, (int)EventId.EVENT_SDR);
SDRConnector = new SDR();
// set if the message needs to be stored on the server and resent once at X seconds
SDRConnector.setStoreAndForwardOption(ConfigHelper.SdrStoreTM == 1 ? true : false);
SDRConnector.PropertyChanged += new PropertyChangedEventHandler(SDRConnector_PropertyChanged);
//SDRConnector.Start();
msgBuss = new MessageBuss(ConfigHelper.MsgBusIp, ConfigHelper.MsgBusPort.ToString(), SDRConnector);
msgBuss.OnPollRequest += delegate (Int64 radioID, bool isLong, string seqNumber)
{
SDRConnector.Send_Imed_Loc_req((UInt32)radioID, isLong, seqNumber);
};
msgBuss.OnSDSRequest += delegate (Int64 radioID, Int64 gatewayID, Int64 gatewayRadioID, string message, int type, string seqID)
{
SDRConnector.SEND_SMS((uint)radioID, message);
Utils.WriteEventLog(Program.COMPANY, "SMSConfirm.getFromConfirmationQueue(hret.seq_no)=" + seqID, EventLogEntryType.Information, (int)EventId.EVENT_SDR);
string test = "#242#1#";
//send SMS ack to message bus
MessageBuss.SendOnMsgBuss(seqID, test);
};
msgBuss.OnUnitsUpdated += delegate ()
{
DBvehiclesManager dbVehManager = new DBvehiclesManager(ConfigHelper.DBip, ConfigHelper.DBSchema, ConfigHelper.DBUser, ConfigHelper.DBPassword, ConfigHelper.DBPort);
try
{
lock (SDR.dictionaryLock)
{
SDR.RadioIdToLastPosDictionary = dbVehManager.getImeiLastPosDictionary(true);
Utils.WriteEventLog(Program.COMPANY, "Received " + SDR.RadioIdToLastPosDictionary.Count + " units", EventLogEntryType.Information, (int)EventId.EVENT_SDR);
StringBuilder sb = new StringBuilder();
foreach (var item in SDR.RadioIdToLastPosDictionary)
{
sb.AppendFormat("{0:#############}, ", item.Key);
//Utils.Write(String.Format("{0:#############} |||| ", item.Key), ConsoleType.ALL);
}
string result = sb.ToString().TrimEnd();//when converting to string we also want to trim the redundant new line at the very end
Utils.WriteEventLog(Program.COMPANY ,result, EventLogEntryType.Information, (int)EventId.EVENT_SDR);
}
}
catch (Exception ex)
{
Utils.WriteEventLog(Program.COMPANY, "Unable to get assigned units " + ex.ToString(), EventLogEntryType.Error, (int)EventId.EVENT_SDR);
}
};
msgBuss.OnCallOutRequest += delegate (ulong destISSI, ushort callOutSeverity, string GeoName)
{
SDRConnector.SendCallOut((uint)destISSI, callOutSeverity, GeoName);
};
msgBuss.OnCallOutStopRequest += delegate (ulong destISSI, ushort callOutSeverity)
{
SDRConnector.SendCallOutStop((uint)destISSI, callOutSeverity);
};
sms = new SMSmanager(SDRConnector);
if (ConfigHelper.HasSdrAutoconnect)
SDRConnector.Start();
}
#endregion
#region GATEWAY - RADIO GATEWAY
private Gateway getGateway(String gatewayIP, DBgatewaysManager gatewayManager)
{
List<Gateway> allGateways = gatewayManager.getAllGateways();
foreach (Gateway g in allGateways)
{
if (g.Ip == gatewayIP)
{
Utils.WriteEventLog(Program.COMPANY, "Gateway IP found in registration tabel. ID: " + g.Id, EventLogEntryType.Information, (int)EventId.EVENT_SDR);
currentGateway = g;
ConfigurationManager.AppSettings.Set("id", g.Id.ToString());
ConfigurationManager.AppSettings.Set("thisIP", g.Ip.ToString());
// TODO update thegateway infos in the config file
return g;
}
}
return null;
}
private List<RadioGateway> getRadioGWsFromDB(Int64 gatewayID, DBgatewaysManager gatewayManager)
{
List<RadioGateway> list = gatewayManager.gelAllRadioGateways(gatewayID);
List<RadioGateway> listtoreturn = new List<RadioGateway>();
foreach (RadioGateway g in list)
listtoreturn.Add(g);
return listtoreturn;
}
private void onNoRadioGatewayDefined()
{
Utils.WriteEventLog(Program.COMPANY, "No SDR controller defined in the admin module for this computer. Please contact your administrator.",
EventLogEntryType.Error, (int)EventId.EVENT_SDR);
}
#endregion
private void CloseApp()
{
OnStop();
}
#region EVENTS
public delegate void RegistrationCompleted(RegistrationResponse response);
public event RegistrationCompleted OnRegistrationCompleted;
#endregion
}
#endregion
}