SafeDispatch/AppServer/MainForm.cs

1575 lines
68 KiB
C#

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using System.Threading;
using RegLibDLL;
using System.Diagnostics;
using SafeMobileLib;
using System.Runtime.InteropServices;
using System.Collections;
using System.Net.Mail;
using System.IO;
using SharedUI;
using SafeMobileLib.Helpers;
using System.IO.Pipes;
using System.Threading.Tasks;
using System.Timers;
using Newtonsoft.Json;
using SafeMobileLib.WebsocketClient;
using System.Data;
using System.ComponentModel;
namespace AppServer
{
public partial class MainForm : Form
{
private static Int64 DB_NUMBER_OF_INSERTS = 100000;
public static readonly short FEEDBACK_INTERACTION_WAIT_TIME_SEC = 7;
public static Boolean isRunning = true;
public static Boolean error = false;
private Int32 regPort = 5680;
private RegLib regLib;
private bool errorOnScreen = false;
private Int32 ErrorCount = 0;
public MainClass m = null;
public static Boolean withConsole = false;
public static String fileName = "";
DBregistrationManager regManager;
DBRadioTypeManager radioTypeManager;
DBvehiclesManager vehManager;
public static DBsettingsManager dbSettings;
public static bool IS_SIERRA_WIRELESS = false;
private DBsubsOperationManager dbsub;
public static InterthreadMessageQueue<string> LocationQueue;
public static InterthreadMessageQueue<string> prevLocationQueue;
public static InterthreadMessageQueue<UnitDataToSend> websocketLocationQueue;
public static InterthreadMessageQueue<MailMessage> ReportEmailQueue;///need to use this queue
public volatile static Hashtable VehListWithGroupDetails = new Hashtable();
public volatile static Hashtable VehList = new Hashtable();
public volatile static Hashtable userReportTimeList = new Hashtable();
public volatile static Hashtable VehStolen = new Hashtable();
public volatile static Hashtable VehicleHashStat = new Hashtable();
public volatile static Boolean AIRTURKEYLIMIT = false;
public volatile static UdpMulticast udp;
public static Boolean UdpMulticastConnectionStatus = false;
public static volatile bool ZonesBussy = false;
/// <summary>
/// hash table used for gateway statuses (message 500, 501, 503)
/// </summary>
internal static volatile Hashtable RadioGWHash = new Hashtable();
internal static Hashtable userStateHash = new Hashtable();
public volatile static Boolean SendPOLLafterSMS = false;
public volatile static Int32 CountInsert =0;
public volatile static Boolean RegistrationAnswer = false;
public static uint recordings = 0;
public static String GPS_Queue_File = "gps_queue.txt";
public static List<GatewayRegistration> allGateways = new List<GatewayRegistration>();
[DllImportAttribute("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[DllImportAttribute("user32.dll")]
public static extern bool ReleaseCapture();
public const int WM_NCLBUTTONDOWN = 0xA1;
public const int HT_CAPTION = 0x2;
// background colors for each panel, they will change at runtime with ones from the UI
private Color softwareColor = Color.Teal;
private Color mapColor = Color.Crimson;
private Color featuresColor = Color.FromArgb(202,80,0);
// Type of panels with licenses
private enum LicensePanel { SOFTWARE, MAP, FEATURES };
private LicensePanel prevLicensePanel = LicensePanel.SOFTWARE;
public RADIOTYPE RadioType = RADIOTYPE.MOTO;
public static Int32 Job_ticking_count = 0;
public System.Timers.Timer gwCheckTimer = new System.Timers.Timer();
//Websocket
public static System.Timers.Timer sendWebsocketTimer = new System.Timers.Timer();
public static System.Timers.Timer checkWebsocketServerStatus = new System.Timers.Timer();
public static Boolean hasDBAccess;
public static String dbAccess;
private WebsocketThread websocket = null;
public delegate void UpdateLicensesUIInvokeCallBack();
public MainForm()
{
FireWallException fw = new FireWallException();
string name = System.AppDomain.CurrentDomain.FriendlyName;
string path = System.Windows.Forms.Application.ExecutablePath;
fw.checkFirewall(name, path);
//for loging
SM debug = new SM();
Version v = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
Console.WriteLine("Version: " + v.ToString());
LocationQueue = new InterthreadMessageQueue<string>();
prevLocationQueue = new InterthreadMessageQueue<string>();
ReportEmailQueue = new InterthreadMessageQueue<MailMessage>();
websocketLocationQueue = new InterthreadMessageQueue<UnitDataToSend>();
gwCheckTimer.Elapsed += new ElapsedEventHandler(CheckGatewayStatus);
gwCheckTimer.Interval = 10000;
gwCheckTimer.Enabled = true;
sendWebsocketTimer.Elapsed += new ElapsedEventHandler(SendLocationToWebSocketHandler);
sendWebsocketTimer.Interval = Program.cfg.websocketTimer;
checkWebsocketServerStatus.Elapsed += new ElapsedEventHandler(BroadcastWebSocketStatusOnMessageBus);
checkWebsocketServerStatus.Interval = 5000;
//test id app is already running
bool shoulLoadThisOne = testIfAlreadyRunning();
// the test for application that is already running will return false only if the app
// already running but doesn't require to be closed, meaning this instance should be closed
if (!shoulLoadThisOne)
{
Program.SHOULD_LOAD = false;
}
// continue with loading this instance because no other one is running
else
ContinueConstructor();
Thread t = new Thread(HandleUnitStatus);
t.IsBackground = true;
t.Start();
}
private void ContinueConstructor()
{
InitializeComponent();
// customize the new FeedbackRadMessageBox
FeedbackRadMessageBox.InteractionWaitSeconds = FEEDBACK_INTERACTION_WAIT_TIME_SEC;
FeedbackRadMessageBox.SetTheme("TelerikMetroBlue");
// register for restart event
FeedbackRadMessageBox.OnRestartRequest += delegate ()
{
Utils.WriteLine("AppServer needs to be restarted", ConsoleColor.Cyan);
RestartApp();
};
String dongleError = "";
regLib = new RegLibDLL.RegLib();
RegStatus regStatus = RegStatus.UNKNOWN;
if (regLib.demoMode)
{
regStatus = RegStatus.VALID_DEMO;
SM.Debug("AppServer in demo mode: " + regLib.remainingTime() + " seconds remaining");
if (regLib.remainingTime() <= 1)
{
regStatus = RegStatus.DEMO_EXPIRED;
error = true;
}
Job_ticking_count = (regLib.jobTicketingCount() > 0 && regLib.jobTicketingCount() <= regLib.safeDispatchCount()) ? regLib.jobTicketingCount() : 0;
}
else
{
if (!regLib.dongleDetected())
{
regStatus = RegStatus.DONGLE_MISSING;
dongleError = "Dongle missing.";
error = true;
}
else
{
regStatus = RegStatus.VALID_DONGLE;
if (!regLib.validData())
{
dongleError = "No valid data found on dongle";
regStatus = RegStatus.DONGLE_NOT_INITIALIZED;
error = true;
}
else
{
if (!regLib.isCorrectHID())
{
regStatus = RegStatus.DONGLE_INVALID_HID;
dongleError = "Incorrect dongle HID";
error = true;
}
else
{
Job_ticking_count = (regLib.jobTicketingCount() > 0 && regLib.jobTicketingCount() <= regLib.safeDispatchCount()) ? regLib.jobTicketingCount() : 0;
}
}
}
}
this.WindowState = FormWindowState.Minimized;
this.Visible = false;
notifyIcon1.Visible = true;
notifyIcon1.ShowBalloonTip(500);
try
{
Utils.WriteEventLog(Program.COMPANY, "AppServer ON", EventLogEntryType.Information, 3152);
}
catch (Exception ex)
{
SM.Debug("Unable to write log Event ex:" + ex.ToString());
}
ContextMenu contextMenu = new ContextMenu();
contextMenu.MenuItems.Add("Check for updates...", (s, e) => {
UpdateForm uf = new UpdateForm(App.APP_SERVER, true) { IsDevelop = Program.cfg.isDevelop };
uf.Show();
});
contextMenu.MenuItems.Add("Exit", (s, e) => CloseApp());
notifyIcon1.ContextMenu = contextMenu;
if (!error)
{
m = new MainClass(this);
// gestion reset event
m.OnRefreshHashRequest += delegate()
{
ReportEmailQueue = new InterthreadMessageQueue<MailMessage>();
Thread.Sleep(500);
m.Start();
// update UI
this.Invoke((MethodInvoker)delegate()
{
UpdateLicensesUI();
});
};
regPort = Program.cfg.regPort;
//test if we can connect to DB
testDBconnection();
//start main class
m.Start();
LocationThread LocationConnection = new LocationThread();
Thread LocThreadObj = new Thread(new ThreadStart(LocationConnection.handleConnection));
LocThreadObj.IsBackground = true;
LocThreadObj.Start();
RegistrationThread RegistrationConnection = new RegistrationThread(regPort, Program.cfg.DB_IP, Program.cfg.DB_schema, Program.cfg.DB_user,
Program.cfg.DB_passwd, Program.cfg.DB_port);
Thread LocationThreadObj = new Thread(new ThreadStart(RegistrationConnection.handleConnection));
LocationThreadObj.IsBackground = true;
LocationThreadObj.Start();
}
else
{
String dialogMessage = "Invalid dongle. Please insert a valid dongle and restart the Application Server";
String dialogTitle = "Application Server Invalid Dongle";
// display other messages based on the error type
switch(regStatus)
{
case RegStatus.DEMO_EXPIRED:
{
dialogMessage = $"Your demo period had expired. Please contact {Program.COMPANY} if you want to extend it.";
dialogTitle = "Application Server Demo Expired";
break;
}
case RegStatus.DONGLE_INVALID_HID:
{
dialogMessage = $"Your dongle has an invalid HID value. Please contact {Program.COMPANY} in order to reconfigure the dongle.";
dialogTitle = "Application Server Dongle Invalid HID";
break;
}
case RegStatus.DONGLE_MISSING:
{
dialogMessage = $"Your dongle is missing. Please connect the dongle if not connected, or change the port if already connected. Then restart Application Server.";
dialogTitle = "Application Server Dongle Missing";
break;
}
case RegStatus.DONGLE_NOT_INITIALIZED:
{
dialogMessage = $"Your dongle is not initialized or contains invalid data. Please contact {Program.COMPANY} in order to reconfigure the dongle.";
dialogTitle = "Application Server Demo Expired";
break;
}
}
FeedbackRadMessageBox.InteractionWaitSeconds = 15;
FeedbackRadMessageBox.ShowError(dialogMessage, dialogTitle);
FeedbackRadMessageBox.InteractionWaitSeconds = FEEDBACK_INTERACTION_WAIT_TIME_SEC;
Environment.Exit(0);
}
// update UI
UpdateLicensesUI();
//set DB Access Licence
dbAccess = regLib.dbAccessCount().ToString();
MainForm.hasDBAccess = (dbAccess.Equals("1") ? true : false);
Utils.WriteLine("3rd Party API WebSocket: " + hasDBAccess.ToString());
if (hasDBAccess)
{
ThreadStart action = () => {
ConfigureWebSocket();
};
Thread thread = new Thread(action) { IsBackground = true };
thread.Start();
}
softwareColor = circularUnits.ProgressCircleColor;
mapColor = circularGoogle.ProgressCircleColor;
featuresColor = circularLive.ProgressCircleColor;
// change the active panel in order to color the circular menus
ChangeFocusedLicensesGroup(LicensePanel.SOFTWARE);
}
private void ConfigureWebSocket()
{
if (!checkWebsocketServerStatus.Enabled)
checkWebsocketServerStatus.Enabled = true;
if (!sendWebsocketTimer.Enabled)
sendWebsocketTimer.Enabled = true;
BackgroundWorker webSocketWorker = new BackgroundWorker();
websocket = WebsocketThread.Instance;
websocket.host = Program.cfg.websocketUrl;
Utils.WriteLine("Setting 3rd Party API WebSocket host: " + Program.cfg.websocketUrl, ConsoleColor.Yellow);
//websocket.StartWebsocket();
webSocketWorker.DoWork += websocket.StartWebsocket;
webSocketWorker.RunWorkerAsync();
}
/// <summary>
/// Restart the application and close other notify icons
/// </summary>
public void RestartApp()
{
CloseNotifyIcon();
Program.isRunning = false;
Thread p = new Thread(new ThreadStart(delegate ()
{
Process.Start(System.Reflection.Assembly.GetExecutingAssembly().Location, String.Join(" ", Program.cmdArgs));
CloseApp();
}));
p.Start();
}
private void CloseApp()
{
Process oldProcess = Process.GetCurrentProcess();
oldProcess.Kill();
Application.Exit();
}
/// <summary>
/// Hide the notify icon method. This will cause the right bottom icon to be hide
/// </summary>
private void CloseNotifyIcon()
{
if (notifyIcon1 != null)
{
notifyIcon1.Visible = false;
notifyIcon1.Icon = null;
notifyIcon1.Dispose();
}
}
/// <summary>
/// Update the UI licenses circular controllers. This will read the dongle licenses
/// and the ones from the DB and the display them in the UI.
/// </summary>
private void UpdateLicensesUI()
{
Version v = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
String[] appname = this.Text.Split(' ');
this.Text = appname[0] + " " + v.ToString();
lbVersion.Text = "Version " + v.ToString();
//check radio type from database to set job ticketing to visible
if (Program.cfg == null)
return;
radioTypeManager = new DBRadioTypeManager(Program.cfg.DB_IP, Program.cfg.DB_schema, Program.cfg.DB_user, Program.cfg.DB_passwd, Program.cfg.DB_port);
dbSettings = new DBsettingsManager(Program.cfg.DB_IP, Program.cfg.DB_schema, Program.cfg.DB_user, Program.cfg.DB_passwd, Program.cfg.DB_port);
string radio_type = radioTypeManager.getRadioType();
if(radio_type == "")
{
// if radio_type isn't saved in db => check folder's name
System.IO.DirectoryInfo myDirectory = new DirectoryInfo(Environment.CurrentDirectory);
// get parent directory
string parentDirectory = myDirectory.Parent.FullName;
DirectoryInfo dInfo = new DirectoryInfo(parentDirectory);
DirectoryInfo[] subdirs = dInfo.GetDirectories();
foreach(DirectoryInfo folder in subdirs)
{
if (folder.Name == "Gateway") { radio_type = ((int)RADIOTYPE.MOTO).ToString(); break; }
else if (folder.Name == "Hytera") { radio_type = ((int)RADIOTYPE.HYT).ToString(); break; }
else if (folder.Name == "Momentum") { radio_type = ((int)RADIOTYPE.HARRIS).ToString(); break; }
else if (folder.Name == "Astro") { radio_type = ((int)RADIOTYPE.ATLAS).ToString(); break; }
else if (folder.Name == "Tetra") { radio_type = ((int)RADIOTYPE.TETRA).ToString(); break; }
else if (folder.Name == "Connect Plus") { radio_type = ((int)RADIOTYPE.CONECTPLUS).ToString(); break; }
else if (folder.Name == "Repeater_Gateway") { radio_type = ((int)RADIOTYPE.REPEATER_TRBO).ToString(); break; }
else if (folder.Name == "SMC_Gateway") { radio_type = ((int)RADIOTYPE.MOTO).ToString(); break; }
else if (folder.Name == "Simoco") { radio_type = ((int)RADIOTYPE.SIMOCO).ToString(); break; }
else if (folder.Name == "Sepura3T_SDR") { radio_type = ((int)RADIOTYPE.LISF).ToString(); break; }
}
//save radiotype in db
radioTypeManager.setRadioType(radio_type);
}
if (radio_type != "")
RadioType = (RADIOTYPE)Enum.Parse(typeof(RADIOTYPE), radio_type);
lbLicTicketing.Visible = circularTicketing.Visible = pbTicketing.Visible = labelTicketing.Visible = (RadioType == RADIOTYPE.MOTO || RadioType == RADIOTYPE.REPEATER_TRBO);
lbLicTelemetry.Visible = circularTelemetry.Visible = pbTicketing.Visible = labelTelemetry.Visible
= (RadioType == RADIOTYPE.MOTO || RadioType == RADIOTYPE.REPEATER_TRBO || RadioType == RADIOTYPE.HYT || RadioType == RADIOTYPE.HARRIS);
circularSDM.Visible = pbSDM.Visible = labelSDM.Visible = lbLicSDM.Visible = (RadioType == RADIOTYPE.SIMOCO);
// change logo icon depending on the system type
if (RadioType == RADIOTYPE.SIMOCO)
{
pbLogo.Image = AppServer.Properties.Resources.simoco;
}
else
{
pbLogo.Image = AppServer.Properties.Resources.safemobile;
}
if (error)
{
if (regLib.demoMode)
{
if (regLib.remainingTime() == 1)
{
lbRegistrationStatus.Text = "Demo invalidated, please contact " + Program.COMPANY;
lbRegistrationStatus.ForeColor = Color.DarkRed;
}
else
{
lbRegistrationStatus.Text = "Demo registration expired";
lbRegistrationStatus.ForeColor = Color.DarkRed;
}
}
}
else
{
if (regLib.demoMode)
{
lbRegistrationStatus.Text = "trial ends in " + (regLib.remainingTime() / 86400).ToString() + " days ";
lbRegistrationStatus.ForeColor = Color.Yellow;
}
regManager = new DBregistrationManager(Program.cfg.DB_IP, Program.cfg.DB_schema, Program.cfg.DB_user, Program.cfg.DB_passwd, Program.cfg.DB_port);
vehManager = new DBvehiclesManager(Program.cfg.DB_IP, Program.cfg.DB_schema, Program.cfg.DB_user, Program.cfg.DB_passwd, Program.cfg.DB_port);
dbsub = new DBsubsOperationManager(Program.cfg.DB_IP, Program.cfg.DB_schema, Program.cfg.DB_user, Program.cfg.DB_passwd, Program.cfg.DB_port);
uint gpsCount = regManager.getGPSCount();
uint smsCount = regManager.getSMSCount();
uint reportsCount = regManager.getReportsCount();
uint voiceCount = regManager.getVoiceCount();
uint zonesCount = regManager.getZonesCount();
uint telemetryCount = regManager.getTelemetryCount();
uint GoogleCount = regManager.getGoogleCount();
uint MapUSCount = regManager.getMapsUSCount();
uint OSMCount = regManager.getOSMCount();
uint ArcgisCount = regManager.getMapsArcgisCount();
allGateways = regManager.getAllGateways();
int gatewaysCount = allGateways.Count();
uint ticketingCount = regManager.getTicketingCount();
uint recordingsCount = recordings = regManager.getRecordingsCount();
int allSDCount = regManager.getAllSafeDispatches().Count();
#region VALUES
int nrOfUnits = regLib.getNumberOfUnits();
// detect if Sierra Wireless
IS_SIERRA_WIRELESS = dbsub.IsSierraWireless();
int totaldbunits = 0;
uint nrOfUnitsInDB = (uint)vehManager.getActiveVehiclesCount(nrOfUnits,IS_SIERRA_WIRELESS, out totaldbunits);
circularUnits.MinValue = (nrOfUnits > 0) ? 0 : -1;
circularUnits.MaxValue = regLib.getNumberOfUnits();
circularUnits.Value = (nrOfUnitsInDB > circularUnits.MaxValue
? circularUnits.MaxValue : nrOfUnitsInDB);
lbLicUnits.Text = circularUnits.Value + " of " + circularUnits.MaxValue;
int nrSD = regLib.safeDispatchCount();
circularSD.MinValue = (nrSD > 0) ? 0 : -1;
circularSD.MaxValue = regLib.safeDispatchCount();
circularSD.Value = (allSDCount > circularSD.MaxValue
? circularSD.MaxValue : allSDCount);
lbLicSD.Text = circularSD.Value + " of " + circularSD.MaxValue;
int sdmCount = regLib.SDMobileCount();
circularSDM.MinValue = (sdmCount > 0 && sdmCount <= regLib.safeDispatchCount()) ? 0 : -1;
circularSDM.MaxValue = ((sdmCount > regLib.safeDispatchCount()) ? 0 : sdmCount);
circularSDM.Value = 0;
lbLicSDM.Text = circularSDM.Value + " of " + circularSDM.MaxValue;
int nrGateways = regLib.gatewayCount();
circularGateways.MinValue = (nrGateways > 0 && nrGateways <= regLib.safeDispatchCount()) ? 0 : -1;
circularGateways.MaxValue = regLib.gatewayCount();
circularGateways.Value = (gatewaysCount > circularGateways.MaxValue
? circularGateways.MaxValue : gatewaysCount);
lbLicGateways.Text = circularGateways.Value + " of " + circularGateways.MaxValue;
// set values for maps licenses
int nrGoogle = regLib.mapType1Count();
circularGoogle.MinValue = (nrGoogle > 0 && nrGoogle <= regLib.safeDispatchCount()) ? 0 : -1;
circularGoogle.MaxValue = regLib.mapType1Count();
circularGoogle.Value = (GoogleCount > circularGoogle.MaxValue
? circularGoogle.MaxValue : GoogleCount);
lbLicGoogle.Text = circularGoogle.Value + " of " + circularGoogle.MaxValue;
int nrArcGis = regLib.mapType4Count();
circularArcGis.MinValue = (nrArcGis > 0 && nrArcGis <= regLib.safeDispatchCount()) ? 0 : -1;
circularArcGis.MaxValue = regLib.mapType4Count();
circularArcGis.Value = (ArcgisCount > circularArcGis.MaxValue
? circularArcGis.MaxValue : ArcgisCount);
lbLicArcGis.Text = circularArcGis.Value + " of " + circularArcGis.MaxValue;
int nrOSM = regLib.mapType3Count();
circularOSM.MinValue = (nrOSM > 0 && nrOSM <= regLib.safeDispatchCount()) ? 0 : -1;
circularOSM.MaxValue = regLib.mapType3Count();
circularOSM.Value = (OSMCount > circularOSM.MaxValue
? circularOSM.MaxValue : OSMCount);
lbLicOSM.Text = circularOSM.Value + " of " + circularOSM.MaxValue;
// set values for features licenses
int nrGPS = regLib.gpsCount();
circularLive.MinValue = (nrGPS > 0 && nrGPS <= regLib.safeDispatchCount()) ? 0 : -1;
circularLive.MaxValue = regLib.gpsCount();
circularLive.Value = (gpsCount > circularLive.MaxValue
? circularLive.MaxValue : gpsCount);
lbLicLive.Text = circularLive.Value + " of " + circularLive.MaxValue;
int nrVoice = regLib.voiceCount();
circularVoice.MinValue = (nrVoice > 0 && nrVoice <= regLib.safeDispatchCount()) ? 0 : -1;
//circularVoice.MaxValue = ((nrVoice > regLib.safeDispatchCount()) ? 0 : nrVoice);
circularVoice.MaxValue = regLib.voiceCount();
uint nrOfVoice = regManager.getVoiceCount();
circularVoice.Value = (nrOfVoice > circularVoice.MaxValue ?
circularVoice.MaxValue : nrOfVoice);
lbLicVoice.Text = circularVoice.Value + " of " + circularVoice.MaxValue;
int nrText = regLib.smsCount();
circularText.MinValue = (nrText > 0 && nrText <= regLib.safeDispatchCount()) ? 0 : -1;
circularText.MaxValue = regLib.smsCount();
circularText.Value = (smsCount > circularText.MaxValue
? circularText.MaxValue : smsCount);
lbLicText.Text = circularText.Value + " of " + circularText.MaxValue;
int nrTicketing = regLib.jobTicketingCount();
circularTicketing.MinValue = (nrTicketing > 0 && nrTicketing <= regLib.safeDispatchCount()) ? 0 : -1;
//circularTicketing.MaxValue = ((nrTicketing > regLib.safeDispatchCount()) ? 0 : nrTicketing);
circularTicketing.MaxValue = regLib.jobTicketingCount();
circularTicketing.Value = (ticketingCount > circularTicketing.MaxValue
? circularTicketing.MaxValue : ticketingCount);
lbLicTicketing.Text = circularTicketing.Value + " of " + circularTicketing.MaxValue;
int nrReports = regLib.reportsCount();
circularReports.MinValue = (nrReports > 0 && nrReports <= regLib.safeDispatchCount()) ? 0 : -1;
circularReports.MaxValue = nrReports;
circularReports.Value = (reportsCount > circularReports.MaxValue
? circularReports.MaxValue : reportsCount);
lbLicReports.Text = circularReports.Value + " of " + circularReports.MaxValue;
int nrZones = regLib.zonesCount();
circularZones.MinValue = (nrZones > 0 && nrZones <= regLib.safeDispatchCount()) ? 0 : -1;
circularZones.MaxValue = nrZones;
circularZones.Value = (zonesCount > circularZones.MaxValue
? circularZones.MaxValue : zonesCount);
lbLicEmail.Text = circularZones.Value + " of " + circularZones.MaxValue;
int nrTelem = regLib.telemetryCount();
circularTelemetry.MinValue = (nrTelem > 0 && nrTelem <= regLib.safeDispatchCount()) ? 0 : -1;
circularTelemetry.MaxValue = regLib.telemetryCount();
circularTelemetry.Value = (telemetryCount > circularTelemetry.MaxValue
? circularTelemetry.MaxValue : telemetryCount);
lbLicTelemetry.Text = circularTelemetry.Value + " of " + circularTelemetry.MaxValue;
int nrRecordings = regLib.recordingsCount();
circularRecordings.MinValue = (nrRecordings > 0 && nrRecordings <= regLib.safeDispatchCount()) ? 0 : -1;
circularRecordings.MaxValue = regLib.recordingsCount();
circularRecordings.Value = (recordingsCount > circularRecordings.MaxValue
? circularRecordings.MaxValue : recordingsCount);
lbLicRecordings.Text = circularRecordings.Value + " of " + circularRecordings.MaxValue;
#endregion
if (regLib.AIRTURKEYLIMIT)
{
AIRTURKEYLIMIT = true;
lbRegistrationRemaining.Text = "Demo 1.10.2014 - 1.05.2015";
}
if (gpsCount > regLib.gpsCount() || smsCount > regLib.smsCount() || reportsCount > regLib.reportsCount()
|| voiceCount > regLib.voiceCount() || zonesCount > regLib.zonesCount()
|| telemetryCount > regLib.telemetryCount()
|| GoogleCount > regLib.mapType1Count() || MapUSCount > regLib.mapType2Count()
|| OSMCount > regLib.mapType3Count() || ArcgisCount > regLib.mapType4Count()
|| ticketingCount > regLib.jobTicketingCount() || recordingsCount > regLib.recordingsCount())
{
regManager.resetSafeDispatchRegistrations();
lbRegistrationRemaining.Text = "Database licenses reset";
}
if(gatewaysCount > regLib.gatewayCount())
regManager.removeAllGatewayRegistrations();
}
}
/// <summary>
/// Intercept mouse move on all the items of the form
/// </summary>
/// <param name="sender">UI object which raised the event</param>
/// <param name="e">Mouse event parameters</param>
private void MainForm_MouseMove(object sender, MouseEventArgs e)
{
// move form window if mouse moved with mouse pressed
if (e.Button == MouseButtons.Left)
{
ReleaseCapture();
SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
}
// get mouse position relative to the form
var relativePoint = this.PointToClient(Cursor.Position);
// detect which panel is active
LicensePanel panel = LicensePanel.SOFTWARE;
if(relativePoint.Y >= dividerFeature.Location.Y)
panel = LicensePanel.FEATURES;
else if (relativePoint.Y > dividerMap.Location.Y)
panel = LicensePanel.MAP;
else
panel = LicensePanel.SOFTWARE;
// change UI only if prev panel is different
if (panel != prevLicensePanel)
{
// change the focused licenses panel
ChangeFocusedLicensesGroup(panel);
}
// save previous panel
prevLicensePanel = panel;
}
/// <summary>
/// Change the circle color according to the mouse position and the
/// focused panel of licenses
/// </summary>
/// <param name="panel">The corresponding panel which is active</param>
private void ChangeFocusedLicensesGroup(LicensePanel panel)
{
foreach(Control ctrl in this.Controls)
{
if(ctrl is CircularProgressBar.CircularProgressBar)
{
CircularProgressBar.CircularProgressBar circular = (CircularProgressBar.CircularProgressBar)ctrl;
circular.ProgressCircleColor = Color.DarkGray;
circular.InnerCircleColor = Color.DarkGray;
circular.OuterCircleColor = Color.DarkGray;
}
}
dividerSoftware.BackColor = Color.DarkGray;
dividerMap.BackColor = Color.DarkGray;
dividerFeature.BackColor = Color.DarkGray;
lbFeatureLicenses.ForeColor = Color.DarkGray;
lbMapLicenses.ForeColor = Color.DarkGray;
lbSoftwareLicenses.ForeColor = Color.DarkGray;
lbSoftwareLicenses.Text = "Software Licenses";
lbMapLicenses.Text = "Map Licenses";
lbFeatureLicenses.Text = "Feature Licenses";
pbFeatureLicenses.Image = Properties.Resources.feature;
pbSoftwareLicenses.Image = Properties.Resources.software;
pbMapLicenses.Image = Properties.Resources.maps;
// detect panel lower and higher Y coordinates
int minY = 0, maxY = 0;
Color toPrintColor = softwareColor;
switch (panel)
{
case LicensePanel.SOFTWARE:
{
// get panel coordinates and color in which needs to be printed
toPrintColor = softwareColor;
dividerSoftware.BackColor = softwareColor;
lbSoftwareLicenses.ForeColor = Color.FromArgb(211, 211, 211);
pbSoftwareLicenses.Image = Properties.Resources.software_over;
lbSoftwareLicenses.Text = "Software Licenses";
minY = 0;
maxY = dividerMap.Location.Y;
break;
}
case LicensePanel.MAP:
{
// get panel coordinates and color in which needs to be printed
toPrintColor = mapColor;
lbMapLicenses.ForeColor = Color.FromArgb(211, 211, 211);
pbMapLicenses.Image = Properties.Resources.maps_over;
dividerMap.BackColor = mapColor;
lbMapLicenses.Text = "Map Licenses";
minY = dividerMap.Location.Y;
maxY = dividerFeature.Location.Y;
break;
}
case LicensePanel.FEATURES:
{
// get panel coordinates and color in which needs to be printed
toPrintColor = featuresColor;
dividerFeature.BackColor = featuresColor;
lbFeatureLicenses.ForeColor = Color.FromArgb(211, 211, 211);
pbFeatureLicenses.Image = Properties.Resources.feature_over;
lbFeatureLicenses.Text = "Feature Licenses";
minY = dividerFeature.Location.Y;
maxY = 1000;
break;
}
}
foreach (Control ctrl in this.Controls)
{
if (ctrl is CircularProgressBar.CircularProgressBar)
{
CircularProgressBar.CircularProgressBar circular = (CircularProgressBar.CircularProgressBar)ctrl;
if (circular.Location.Y >= minY && circular.Location.Y < maxY)
{
circular.ProgressCircleColor = toPrintColor;
circular.InnerCircleColor = toPrintColor;
circular.OuterCircleColor = toPrintColor;
}
}
}
}
private void notifyIcon1_DoubleClick(object sender, EventArgs e)
{
this.Visible = true;
this.WindowState = FormWindowState.Normal;
notifyIcon1.Visible = false;
}
private void MainForm_Resize(object sender, EventArgs e)
{
if (this.WindowState == FormWindowState.Minimized)
{
this.Visible = false;
notifyIcon1.Visible = true;
}
}
private void MainForm_Load(object sender, EventArgs e)
{
LoadLocationQueueFromFile();
gwCheckTimer.Start();
#region SOFTWARE LICENSES
circularUnits.Controls.Add(labelUnits);
labelUnits.Location = new Point(29, 63);
labelUnits.BackColor = Color.Transparent;
circularUnits.Controls.Add(pbUnits);
pbUnits.Location = new Point(26, 14);
pbUnits.BackColor = Color.Transparent;
circularSD.Controls.Add(labelSD);
labelSD.Location = new Point(23, 63);
labelSD.BackColor = Color.Transparent;
circularSD.Controls.Add(pbSD);
pbSD.Location = new Point(26, 16);
pbSD.BackColor = Color.Transparent;
circularGateways.Controls.Add(labelGateways);
labelGateways.Location = new Point(23, 63);
labelGateways.BackColor = Color.Transparent;
circularGateways.Controls.Add(pbGateways);
pbGateways.Location = new Point(27, 16);
pbGateways.BackColor = Color.Transparent;
circularSDM.Controls.Add(labelSDM);
labelSDM.Location = new Point(22, 63);
labelSDM.BackColor = Color.Transparent;
circularSDM.Controls.Add(pbSDM);
pbSDM.Location = new Point(31, 21);
pbSDM.BackColor = Color.Transparent;
#endregion
#region MAPS
circularGoogle.Controls.Add(labelGoogle);
labelGoogle.Location = new Point(20, 63);
labelGoogle.BackColor = Color.Transparent;
circularGoogle.Controls.Add(pbGoogle);
pbGoogle.Location = new Point(27, 16);
pbGoogle.BackColor = Color.Transparent;
circularArcGis.Controls.Add(pbArcGis);
pbArcGis.Location = new Point(29, 21);
pbArcGis.BackColor = Color.Transparent;
circularArcGis.Controls.Add(labelArcGis);
labelArcGis.Location = new Point(25, 63);
labelArcGis.BackColor = Color.Transparent;
circularOSM.Controls.Add(pbOSM);
pbOSM.Location = new Point(29, 21);
pbOSM.BackColor = Color.Transparent;
circularOSM.Controls.Add(labelOSM);
labelOSM.Location = new Point(25, 63);
labelOSM.BackColor = Color.Transparent;
#endregion
#region FEATURE LICENSES
circularLive.Controls.Add(pbLive);
pbLive.Location = new Point(29, 21);
pbLive.BackColor = Color.Transparent;
circularLive.Controls.Add(labelLive);
labelLive.Location = new Point(24, 63);
labelLive.BackColor = Color.Transparent;
circularVoice.Controls.Add(pbVoice);
pbVoice.Location = new Point(29, 21);
pbVoice.BackColor = Color.Transparent;
circularVoice.Controls.Add(labelVoice);
labelVoice.Location = new Point(24, 63);
labelVoice.BackColor = Color.Transparent;
circularText.Controls.Add(pbText);
pbText.Location = new Point(29, 21);
pbText.BackColor = Color.Transparent;
circularText.Controls.Add(labelText);
labelText.Location = new Point(24, 63);
labelText.BackColor = Color.Transparent;
circularTicketing.Controls.Add(pbTicketing);
pbTicketing.Location = new Point(29, 21);
pbTicketing.BackColor = Color.Transparent;
circularTicketing.Controls.Add(labelTicketing);
labelTicketing.Location = new Point(24, 63);
labelTicketing.BackColor = Color.Transparent;
circularReports.Controls.Add(pbReports);
pbReports.Location = new Point(31, 21);
pbReports.BackColor = Color.Transparent;
circularReports.Controls.Add(labelReports);
labelReports.Location = new Point(24, 63);
labelReports.BackColor = Color.Transparent;
circularZones.Controls.Add(pbZones);
pbZones.Location = new Point(29, 21);
pbZones.BackColor = Color.Transparent;
circularZones.Controls.Add(labelZones);
labelZones.Location = new Point(22, 63);
labelZones.BackColor = Color.Transparent;
circularTelemetry.Controls.Add(pbTelemetry);
pbTelemetry.Location = new Point(27, 21);
pbTelemetry.BackColor = Color.Transparent;
circularTelemetry.Controls.Add(labelTelemetry);
labelTelemetry.Location = new Point(21, 63);
labelTelemetry.BackColor = Color.Transparent;
circularRecordings.Controls.Add(pbRecordings);
pbRecordings.Location = new Point(29, 21);
pbRecordings.BackColor = Color.Transparent;
circularRecordings.Controls.Add(labelRecordings);
labelRecordings.Location = new Point(24, 63);
labelRecordings.BackColor = Color.Transparent;
#endregion
if (!error)
{
this.Visible = false;
}
if(udp != null)
{
byte[] heartbeatMsg = SafeMobileLib.Utils.Convert_text_For_multicast("#0.0#507#");
udp.Send(heartbeatMsg, heartbeatMsg.Length);
}
// check for a new version if available
if(Program.cfg.autoupdate)
CheckForUpdate();
}
/// <summary>
/// Test if the App Server is already running
/// </summary>
private bool testIfAlreadyRunning()
{
Process[] processlist = Process.GetProcesses();
Process curentP = Process.GetCurrentProcess();
int count = 0;
foreach (Process theprocess in processlist)
{
if (theprocess.ProcessName == curentP.ProcessName)
{
count++;
}
}
if (count > 1)
{
SM.Debug("App already running!!!");
foreach (Process theprocess in processlist)
{
if (theprocess.ProcessName == curentP.ProcessName)
{
Console.WriteLine("Process: {0} ID: {1}", theprocess.ProcessName, theprocess.Id);
Console.WriteLine("Curent Process: {0} ID: {1}", curentP.ProcessName, curentP.Id);
if (theprocess.Id != curentP.Id)
{
Console.WriteLine("Killing Process: {0} ID: {1}", theprocess.ProcessName, theprocess.Id);
try
{
theprocess.Kill();
}
catch (NotSupportedException)
{
Utils.WriteLine("Process already killed!", ConsoleColor.Yellow);
}
catch (Exception ex)
{
Utils.WriteLine("Fatal error!\n" + ex.ToString(), ConsoleColor.Red);
}
}
}
}
Thread.Sleep(1000);
return true;
}
return true;
}
private void testDBconnection()
{
DBmanager DB = new DBmanager(Program.cfg.DB_IP, Program.cfg.DB_schema, Program.cfg.DB_user, Program.cfg.DB_passwd, Program.cfg.DB_port);
try
{
DB.InitConnection();
}
catch (Exception ex)
{
SM.Debug(ex.ToString());
FeedbackRadMessageBox.ShowError("DB connection failed!!!Please check database settings and restart appServer!!!", "AppServer - Database Error");
try
{
Utils.WriteEventLog(Program.COMPANY, "AppServer OFF test DB connection", EventLogEntryType.Information, 3152);
}
catch (Exception exe)
{
SM.Debug("Unable to write log Event ex:" + exe.ToString());
}
try
{
DB.CloseConnection();
DB.InitConnection();
}
catch (Exception exe)
{
try
{
udp.Send(SafeMobileLib.Utils.Convert_text_For_multicast("#0.0#210#4#AppServer stoped#"), SafeMobileLib.Utils.Convert_text_For_multicast("#0.0#210#4#AppServer stoped#").Length);
}
catch (Exception ex2)
{
SM.Debug("Error on sending Message to SD that APPServer has problem: " + ex2.ToString());
}
SM.Debug(exe.ToString());
notifyIcon1.Dispose();
// remove timers and other UI stuffs
MainForm_FormClosing(this, null);
// kill AppServer process
CloseApp();
}
}
}
private int heartbeatWaitStep = 0;
private void Check_dongle_timer_Tick(object sender, EventArgs e)
{
if (udp == null)
return;
// increment at each 1000 ms tick of the timer
heartbeatWaitStep++;
// send heartbeat message if step is larger than number of seconds
if(heartbeatWaitStep >= SafeMobileLib.Modules.AppServerMonitoring.APP_SERVER_HEARTBEAT_SEC)
{
byte[] heartbeatMsg = SafeMobileLib.Utils.Convert_text_For_multicast("#0.0#507#");
udp.Send(heartbeatMsg, heartbeatMsg.Length);
heartbeatWaitStep = 0;
}
if (!regLib.findDongle() && !errorOnScreen)
{
if (!regLib.demoMode)
{
ErrorCount++;
if (ErrorCount > 10)
{
errorOnScreen = true;
error = true;
try
{
udp.Send(SafeMobileLib.Utils.Convert_text_For_multicast("#0.0#210#2#Dongle missing Application server stopped#"), SafeMobileLib.Utils.Convert_text_For_multicast("#0.0#210#2#Dongle missing Application server stopped#").Length);
}
catch (Exception ex2)
{
SM.Debug("Error on sending Message to SD that APPServer has problem: " + ex2.ToString());
}
try
{
Utils.WriteEventLog(Program.COMPANY, "AppServer OFF Dongle missing", EventLogEntryType.Information, 3152);
}
catch (Exception exe)
{
SM.Debug("Unable to write log Event ex:" + exe.ToString());
}
String dialogMessage = "Invalid dongle. Please insert a valid dongle and restart the Application Server";
String dialogTitle = "Application Server Invalid Dongle";
FeedbackRadMessageBox.InteractionWaitSeconds = 60;
FeedbackRadMessageBox.ShowError(dialogMessage, dialogTitle);
FeedbackRadMessageBox.InteractionWaitSeconds = FEEDBACK_INTERACTION_WAIT_TIME_SEC;
// remove timers and other UI stuffs
MainForm_FormClosing(this, null);
// kill AppServer process
CloseApp();
}
}
}
else ErrorCount = 0;
if (CountInsert > DB_NUMBER_OF_INSERTS)// 50000) //100000
{
Utils.WriteLine("Insert number is " + CountInsert, ConsoleColor.Cyan);
// dump the gps queue to a file
// TODO
ProcessTick();
}
}
public static void LoadLocationQueueFromFile()
{
// restore location queue
if (File.Exists(GPS_Queue_File))
{
// empty the previous queue file
prevLocationQueue.Clear();
List<String> prevGpsMessages = SerializationHelper.DesirializeWithLinq(GPS_Queue_File);
prevLocationQueue.PostItems(prevGpsMessages);
Utils.WriteLine($"Loaded {prevGpsMessages.Count} positions from offline cached file", ConsoleColor.Yellow);
try
{
File.Delete(GPS_Queue_File);
}
catch (Exception ex)
{
// unable to delete previous queue file
Utils.WriteLine("Exception when deleting previous gps queue file : " + ex.ToString(), ConsoleColor.Red);
}
}
}
public static void DumpLocationQueueToFile()
{
// write location queue to a file
if (MainForm.LocationQueue.Count > 0 || MainForm.prevLocationQueue.Count > 0)
{
List<string> allPositions = MainForm.LocationQueue.ToList();
allPositions.AddRange(MainForm.prevLocationQueue.ToList());
SerializationHelper.SerializeWithLinq(allPositions, GPS_Queue_File);
Utils.WriteLine($"Wrote {allPositions.Count} GPS messages from the queue into a file", ConsoleColor.Yellow);
}
}
/// <summary>
/// Populate the Websocket Location Queue and call the timer method to send the data
/// </summary>
/// <param name="radioID"></param>
/// <param name="lat"></param>
/// <param name="lng"></param>
/// <param name="speed"></param>
/// <param name="unit_time"></param>
public static void CheckLocationQueueAndSendToWebSocket(string radioID, double lat, double lng, int speed, uint unit_time,
String heading, Status_for_tab status)
{
Int64 radioId = 0;
bool parseResult = Int64.TryParse(radioID.Trim(), out radioId);
// skip any unit that is not
if(parseResult && radioId < 12000 && radioId > 12999)
{
return;
}
UnitDataToSend data = new UnitDataToSend();
data.radio_id = radioID;
data.lat = lat;
data.lng = lng;
data.speed = speed;
data.unix_time = unit_time;
if(VehListWithGroupDetails.ContainsKey(radioID))
data.GroupName = ((Vehicles)VehListWithGroupDetails[radioID]).GroupName;
data.Heading = heading;
data.GpsState = status.ToString();
// get group name for the radioId
MainForm.websocketLocationQueue.PostItem(data);
if(!sendWebsocketTimer.Enabled)
sendWebsocketTimer.Enabled = true;
if (!checkWebsocketServerStatus.Enabled)
checkWebsocketServerStatus.Enabled = true;
}
private void BroadcastWebSocketStatusOnMessageBus(object source, ElapsedEventArgs e)
{
string message; //$"#0.0#{failoverStatusToMessBuss}#{configHelper.PCIp}#{msg}#{master}#";
string status = WebsocketThread.Instance.getClient().IsRunning ? "online" : "offline";
message = $"#0.0#{Utils.enumConvertToString(MessageBusCmds.WebsocketStatusToMsgBus)}#{status}#";
byte[] dataToSend = Utils.Convert_text_For_multicast(message);
udp.Send(dataToSend, dataToSend.Length);
}
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
// stop the dongle timer
Check_dongle_timer?.Stop();
//stop gatewaycheck
gwCheckTimer.Stop();
sendWebsocketTimer.Stop();
checkWebsocketServerStatus.Stop();
WebsocketThread._client?.Dispose();
// save all unhandled gps positions
DumpLocationQueueToFile();
if(Program.cfg.watchdog)
Program.KillWatchDog();
try
{
CloseNotifyIcon();
Utils.WriteEventLog(Program.COMPANY, "AppServer OFF on close", EventLogEntryType.Information, 3152);
}
catch (Exception ex)
{
SM.Debug("Unable to write log Event ex:" + ex.ToString());
}
try
{
udp.Send(Utils.Convert_text_For_multicast($"#0.0#{Utils.enumConvertToString(MessageBusCmds.WebsocketStatusToMsgBus)}#offline#"),
Utils.Convert_text_For_multicast($"#0.0#{Utils.enumConvertToString(MessageBusCmds.WebsocketStatusToMsgBus)}#offline#").Length);
udp.Send(Utils.Convert_text_For_multicast("#0.0#210#4#Application server stopped#"),
Utils.Convert_text_For_multicast("#0.0#210#4#Application server stopped#").Length);
}
catch (Exception ex2)
{
SM.Debug("Error on sending Message to SD that APPServer has problem: " + ex2.ToString());
}
isRunning = false;
}
public void ProcessTick()
{
try
{
try
{
udp.Send(SafeMobileLib.Utils.Convert_text_For_multicast("#0.0#210#5#Application server restart#"), SafeMobileLib.Utils.Convert_text_For_multicast("#0.0#210#5#Application server restart#").Length);
}
catch (Exception ex2)
{
SM.Debug("Error on sending Message to SD that APPServer has problem: " + ex2.ToString());
}
finally
{
RestartApp();
}
}
catch (Exception ex)
{
SM.Debug("Error on restart timer:" + ex.ToString());
// the process did not exist - probably already closed!
//TODO: --> LOG
}
}
private void pictClose_MouseEnter(object sender, EventArgs e)
{
pictClose.Image = global::AppServer.Properties.Resources.close_over;
this.Cursor = Cursors.Hand;
}
private void pictClose_MouseLeave(object sender, EventArgs e)
{
pictClose.Image = global::AppServer.Properties.Resources.close;
this.Cursor = Cursors.Arrow;
}
private void pictClose_MouseClick(object sender, MouseEventArgs e)
{
this.Close();
Process oldProcess = Process.GetCurrentProcess();
oldProcess.Kill();
System.Windows.Forms.Application.Exit();
}
private void pictMin_MouseEnter(object sender, EventArgs e)
{
pictMin.Image = global::AppServer.Properties.Resources.minimize_over;
this.Cursor = Cursors.Hand;
}
private void pictMin_MouseLeave(object sender, EventArgs e)
{
pictMin.Image = global::AppServer.Properties.Resources.minimize;
this.Cursor = Cursors.Arrow;
}
private void pictMin_MouseClick(object sender, MouseEventArgs e)
{
this.WindowState = FormWindowState.Minimized;
}
private void StartReport_Tick(object sender, EventArgs e)
{
foreach (DictionaryEntry item in userReportTimeList)
{
if (!((UserReportTime)item.Value).ReportExecuted)
{
if ((DateTime.Now.Hour == ((UserReportTime)item.Value).HH && (DateTime.Now.Minute == ((UserReportTime)item.Value).MM)))
{
((UserReportTime)item.Value).ReportExecuted = true;
Process notePad = new Process();
notePad.StartInfo.FileName = "ReportstoEmail.exe";
notePad.StartInfo.Arguments = ((UserReportTime)item.Value).UserID.ToString().Trim() + " " + ((UserReportTime)item.Value).UserName.Trim();
notePad.Start();
}
}
// put ReportExecuted on false 1 minute before event fired
if ((DateTime.Now.Hour == ((UserReportTime)item.Value).HH && (DateTime.Now.Minute == ((UserReportTime)item.Value).MM -1 )))
((UserReportTime)item.Value).ReportExecuted = false;
}
}
private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
{
if (notifyIcon1 != null)
{
notifyIcon1.Dispose();
}
}
//for ARS DB thread
public void HandleUnitStatus()
{
Thread.Sleep(500);
Utils.WriteLine("HandleUnitStatus thread...");
int count = 0;
DBsubsOperationManager dbsubsoperManage = new DBsubsOperationManager(Program.cfg.DB_IP, Program.cfg.DB_schema,
Program.cfg.DB_user, Program.cfg.DB_passwd, Program.cfg.DB_port);
while (isRunning)
{
while((++count % 5 != 0) && isRunning)
{
Thread.Sleep(100);
}
count = 0;
try
{
Dictionary<string, Status_for_tab> changedStatuses = new Dictionary<string, Status_for_tab>();
foreach (DictionaryEntry pair in MainForm.VehicleHashStat)
{
VehicleStatus vs = ((VehicleStatus)MainForm.VehicleHashStat[pair.Key]);
// change the status only if a last position is available or last Ars time is available
if(vs.lastPositionTime.Year > 2010 || vs.lastArsTime.Year > 2010)
{
//Utils.WriteLine("CHECKING UNIT STATUS : " + pair.Key + " | " + vs.curentStatus, ConsoleColor.Magenta);
switch (vs.curentStatus)
{
// NOTHING TO DO WHEN IN EMERGENCY
case Status_for_tab.EMERG:
break;
case Status_for_tab.DISABLE: break;
case Status_for_tab.ENABLE: break;
case Status_for_tab.OFF: break;
case Status_for_tab.MADEOFF: break;
case Status_for_tab.NOGPSFIX:
case Status_for_tab.GPS_OFF:
{
// check if the unit needs to be made off
if (CheckPositionMadeOff(vs))
{
// update status and push changes
vs.curentStatus = Status_for_tab.MADEOFF;
MulticastListener.PushStatus(pair.Key + "", vs.curentStatus);
}
break;
}
case Status_for_tab.MADEON:
case Status_for_tab.ON:
{
// check if the unit needs to be made off
if (CheckArsMadeOff(vs) && CheckPositionMadeOff(vs))
{
// update status and push changes
vs.curentStatus = Status_for_tab.MADEOFF;
MulticastListener.PushStatus(pair.Key + "", vs.curentStatus);
}
break;
}
case Status_for_tab.GPS_ON:
{
// check if the unit needs to be made off
if (CheckGpsPoor(vs))
{
// update status and push changes
vs.curentStatus = Status_for_tab.GPS_POOR;
MulticastListener.PushStatus(pair.Key + "", vs.curentStatus);
}
break;
}
case Status_for_tab.GPS_POOR:
{
// check if the unit needs to be made off
if (CheckGpsOff(vs))
{
// update status and push changes
vs.curentStatus = Status_for_tab.GPS_OFF;
MulticastListener.PushStatus(pair.Key + "", vs.curentStatus);
}
break;
}
}
}
if (vs.curentStatus != vs.previousStatus)
{
changedStatuses.Add(pair.Key + "", vs.curentStatus);
// force the previous status to become the same as the current status
vs.curentStatus = vs.curentStatus;
}
}
// update the statuses that changed
if (changedStatuses.Count > 0)
{
dbsubsoperManage.updateOnlyStatus(changedStatuses);
Utils.WriteLine(changedStatuses.Count + " units changed their states.", ConsoleColor.Green);
changedStatuses.Clear();
}
}
catch (ThreadAbortException tae)
{
Utils.WriteLine(tae.ToString(), ConsoleColor.Red);
}
catch (Exception ex)
{
Utils.WriteLine("HandleUnitStatus Exception: " + ex.ToString(), ConsoleColor.Red);
}
} // end while (true)
}
private bool CheckArsMadeOff(VehicleStatus vehicleStatus)
{
return (DateTime.Now - vehicleStatus.lastArsTime).TotalSeconds > vehicleStatus.made_off ? true : false;
}
private bool CheckPositionMadeOff(VehicleStatus vehicleStatus)
{
return (DateTime.Now - vehicleStatus.lastPositionTime).TotalSeconds > vehicleStatus.made_off ? true : false;
}
private bool CheckGpsPoor(VehicleStatus vehicleStatus)
{
//Utils.WriteLine((DateTime.Now - vehicleStatus.lastPositionTime).TotalSeconds + "");
return (DateTime.Now - vehicleStatus.lastPositionTime).TotalSeconds > vehicleStatus.gps_poor ? true : false;
}
private bool CheckGpsOff(VehicleStatus vehicleStatus)
{
return (DateTime.Now - vehicleStatus.lastPositionTime).TotalSeconds > vehicleStatus.gps_off ? true : false;
}
/// <summary>
/// If the WebsocketServer is online populate a Dataset, convert it to JSON and send it on the websocket
/// </summary>
/// <param name="source"></param>
/// <param name="e"></param>
private static void SendLocationToWebSocketHandler(object source, ElapsedEventArgs e)
{
Utils.WriteLine("Preparing " + MainForm.websocketLocationQueue.Count + " positions to be sent to websocket!!!",
ConsoleColor.DarkYellow);
if(WebsocketThread.Instance.getClient() == null)
{
Utils.WriteLine("WebSocket client url not set or websocket not active");
MainForm.websocketLocationQueue.Clear();
return;
}
if (MainForm.websocketLocationQueue.Count > 0 && WebsocketThread.Instance.getClient().IsRunning)
{
List<UnitDataToSend> allPositions = MainForm.websocketLocationQueue.ToList();
// send over websocket and clear list
WebsocketThread.SendJson(WebsocketThread.Instance.getClient(), WebSocketFormatter.ToJson(allPositions));
}
MainForm.websocketLocationQueue.Clear();
}
private static void CheckGatewayStatus(object source, ElapsedEventArgs e)
{
if (Program.cfg.gatewayType == "SDR" && !IsProcessRunning("SDRgateway"))
{
try
{
string Path = $@"{SafeMobileLib.Utils.GetRegValue("Path", "SafeMobile")}\Tetra_SDR\SDRgateway.exe";
System.Diagnostics.Process.Start(Path);
SafeMobileLib.Utils.WriteLine("Gateway started", ConsoleColor.Yellow);
}
catch(Exception ex)
{
Utils.WriteLine("Could not start Gateway because: " + ex.ToString() + Environment.NewLine + "Path to Gateway = " +
$@"{SafeMobileLib.Utils.GetRegValue("Path", "SafeMobile")}\Tetra_SDR\SDRgateway.exe", ConsoleColor.Red);
}
}
}
public static bool IsProcessRunning(string ProcessName)
{
try
{
Process[] pname = Process.GetProcessesByName(ProcessName);
if (pname.Length == 0)
return false;
else
return true;
}
catch
{
return false;
}
}
#region UPDATE
/// <summary>
/// Check for new version release on SafeMobile Portal
/// The check is done by comparing Current Assembly Version with the one
/// written in a xml file on the portal.
/// </summary>
private void CheckForUpdate()
{
App appType = App.APP_SERVER;
AutoUpdate au = new AutoUpdate(appType) { IsDevelop = Program.cfg.isDevelop };
au.OnNewVersionAvailable += delegate(string version)
{
notifyIcon1.Text = "New version available";
notifyIcon1.ShowBalloonTip(2500, $"{App.GetAppName(appType)} version {version} available",
$"Press to download and install the latest version of {App.GetAppName(appType)}.", ToolTipIcon.Info);
notifyIcon1.BalloonTipClicked += delegate (object sender, EventArgs e)
{
if (notifyIcon1.Text.Equals("New version available"))
{
UpdateForm uf = new UpdateForm(appType, true) { IsDevelop = Program.cfg.isDevelop };
uf.Show();
}
};
};
// call method to check for new updated
au.CheckUpdate();
}
#endregion
}
}