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 LocationQueue; public static InterthreadMessageQueue prevLocationQueue; public static InterthreadMessageQueue websocketLocationQueue; public static InterthreadMessageQueue 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; /// /// hash table used for gateway statuses (message 500, 501, 503) /// 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 allGateways = new List(); [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 static Dictionary blackListAddress = new Dictionary(); public const int MAX_ATTEMPTS = 100; 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(); prevLocationQueue = new InterthreadMessageQueue(); ReportEmailQueue = new InterthreadMessageQueue(); websocketLocationQueue = new InterthreadMessageQueue(); 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(); 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); } public static void HandleTimeoutError(string mailAdr) { // add address to backlist if (!blackListAddress.ContainsKey(mailAdr)) blackListAddress.Add(mailAdr, MAX_ATTEMPTS); } public static bool IsBlacklistedAddress(string mailAdr) { if (!blackListAddress.ContainsKey(mailAdr)) return false; // avoid to send the email MAX_ATTEMPTS times => give another chance to try to send email when count = 0 int count = blackListAddress[mailAdr]; if (count == 0) { blackListAddress.Remove(mailAdr); return false; } blackListAddress[mailAdr] = count - 1; return true; } 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(); } /// /// Restart the application and close other notify icons /// 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(); } /// /// Hide the notify icon method. This will cause the right bottom icon to be hide /// private void CloseNotifyIcon() { if (notifyIcon1 != null) { notifyIcon1.Visible = false; notifyIcon1.Icon = null; notifyIcon1.Dispose(); } } private string get_radio_type() { string radio_type = string.Empty; // 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; } } return radio_type; } /// /// 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. /// private void UpdateLicensesUI() { Version v = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version; String[] appname = this.Text.Split(" ".ToCharArray()); 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 == "") { radio_type = get_radio_type(); //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 pbLogo.Image = (RadioType == RADIOTYPE.SIMOCO) ? AppServer.Properties.Resources.simoco : AppServer.Properties.Resources.safemobile; if (error) { if (regLib.demoMode) { lbRegistrationStatus.Text = (regLib.remainingTime() == 1) ? "Demo invalidated, please contact " + Program.COMPANY : "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(); } } /// /// Intercept mouse move on all the items of the form /// /// UI object which raised the event /// Mouse event parameters 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; } /// /// Change the circle color according to the mouse position and the /// focused panel of licenses /// /// The corresponding panel which is active 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(); } /// /// Test if the App Server is already running /// 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(); DB.CloseConnection(); } 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 { byte[] dataToSend = Utils.Convert_text_For_multicast("#0.0#210#4#AppServer stoped#"); udp.Send(dataToSend, dataToSend.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 { byte[] dataToSend = Utils.Convert_text_For_multicast("#0.0#210#2#Dongle missing Application server stopped#"); udp.Send(dataToSend, dataToSend.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 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 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); } } /// /// Populate the Websocket Location Queue and call the timer method to send the data /// /// /// /// /// /// 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 = "offline"; IWebsocketClient iWebsocketClient = WebsocketThread.Instance.getClient(); if( iWebsocketClient != null) status = iWebsocketClient.IsRunning ? "online" : "offline"; string message = $"#0.0#{Utils.enumConvertToString(MessageBusCmds.WebsocketStatusToMsgBus)}#{status}#"; byte[] dataToSend = Utils.Convert_text_For_multicast(message); if(dataToSend != null && dataToSend.Length > 0) 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 { byte[] dataToSend = Utils.Convert_text_For_multicast($"#0.0#{Utils.enumConvertToString(MessageBusCmds.WebsocketStatusToMsgBus)}#offline#"); udp.Send(dataToSend, dataToSend.Length); dataToSend = Utils.Convert_text_For_multicast("#0.0#210#4#Application server stopped#"); udp.Send(dataToSend, dataToSend.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 { byte[] dataToSend = Utils.Convert_text_For_multicast("#0.0#210#5#Application server restart#"); udp.Send(dataToSend, dataToSend.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 changedStatuses = new Dictionary(); 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; } /// /// If the WebsocketServer is online populate a Dataset, convert it to JSON and send it on the websocket /// /// /// 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 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 /// /// 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. /// 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 } }