using System; using SafeMobileLib; using System.ServiceProcess; using SocketIOComponent; namespace AppServer { public class MainClass { public MulticastListener mListener; private RecordingsServer rServer; private MainForm parent; private String PostrgreSDService = "PostgreSD"; private String TCPServerService = "TCPClientService"; private String TCPClientService = "TCPServerService"; DBsettingsManager dbSettingsManager; public static bool isGPSCheckboxChecked = false; /// /// Listens and sends request on Soket.IO /// private SocketIOClass _socketIOClass = null; public MainClass(MainForm _parent) { // start the postgreSD service just to be sure it is up and running if (GetStatus(PostrgreSDService) == ServiceStatus.STOPPED || GetStatus(PostrgreSDService) == ServiceStatus.STOPPING || GetStatus(PostrgreSDService) == ServiceStatus.PAUSED || GetStatus(PostrgreSDService) == ServiceStatus.STATUS_CHANGING) ServiceControlUtils.startService(PostrgreSDService); // start the TCPServerService service just to be sure it is up and running if (GetStatus(TCPServerService) == ServiceStatus.STOPPED || GetStatus(TCPServerService) == ServiceStatus.STOPPING || GetStatus(TCPServerService) == ServiceStatus.PAUSED || GetStatus(TCPServerService) == ServiceStatus.STATUS_CHANGING) ServiceControlUtils.startService(TCPServerService); // start the TCPClientService service just to be sure it is up and running if (GetStatus(TCPClientService) == ServiceStatus.STOPPED || GetStatus(TCPClientService) == ServiceStatus.STOPPING || GetStatus(TCPClientService) == ServiceStatus.PAUSED || GetStatus(TCPClientService) == ServiceStatus.STATUS_CHANGING) ServiceControlUtils.startService(TCPClientService); string test = Environment.GetEnvironmentVariable("PGPASSWORD"); if (test == null) { SM.Debug("Setting Postgress Enviroment password!!!"); Environment.SetEnvironmentVariable("PGPASSWORD", "wizdemo26", EnvironmentVariableTarget.Machine); } rServer = new RecordingsServer(); parent = _parent; } private static bool listenerAdded = false; public void Start() { Utils.WriteLine("START", ConsoleColor.DarkCyan); if (!listenerAdded) { mListener = new MulticastListener(Program.cfg.msgBusIP, Program.cfg.msgBusPort, parent); mListener.OnRefreshHashRequest += mListener_OnRefreshHashRequest; mListener.OnDatabaseDown += MListener_OnDatabaseDown; mListener.OnEmergencyAckReceived += MListener_OnEmergencyAckReceived; mListener.OnPollRequestReceived += MListener_OnPollRequestReceived; listenerAdded = true; } mListener?.Start(); // Instantiate socketIOClass only if is null // to prevent multiple socket io classes in case of Appserver restart // If Linx version, start listening on Socket.IO // Check if socket.IO server and port are saved in database dbSettingsManager = new DBsettingsManager(Program.cfg.DB_IP, Program.cfg.DB_schema, Program.cfg.DB_user, Program.cfg.DB_passwd, Program.cfg.DB_port); string linxServerIP = dbSettingsManager.getSettingValue(0, "lanLinxServer"); // sipServerIP string webServicePort = dbSettingsManager.getSettingValue(0, "lanSigPort"); //webServicePort string uri = $"ws://{linxServerIP}:{webServicePort}"; if ((_socketIOClass != null && _socketIOClass.Uri != uri) || _socketIOClass == null) { Utils.WriteLine($"SocketIO on {linxServerIP}:{webServicePort}", ConsoleColor.DarkCyan); if (!string.IsNullOrEmpty(linxServerIP) && !string.IsNullOrEmpty(webServicePort)) { System.Net.IPAddress linxIP = null; int socketIoPort = -1; if (System.Net.IPAddress.TryParse(linxServerIP, out linxIP) && int.TryParse(webServicePort, out socketIoPort)) { _socketIOClass?.Disconect(); _socketIOClass = new SocketIOClass(uri); _socketIOClass.ArsReceived += ArsReceivedOnSocketIO; _socketIOClass.GpsReceived += GpsReceivedOnSocketIO; _socketIOClass.PollReceived += PollResponseReceivedOnSocketIO; _socketIOClass.EmergencyReceived += EmergencyReceivedOnSocketIO; } } } } #region SocketIO class event handlers private void GpsReceivedOnSocketIO(object sender, GpsReceivedEventArgs e) { if (e.Gps == null || e.Gps.UserID == null) return; string radioID = "0"; if (MulticastListener.MobileVehicleList.ContainsKey(e.Gps.UserID)) radioID = (String)MulticastListener.MobileVehicleList[e.Gps.UserID]; Utils.WriteLine($"GpsReceivedOnSocketIO - imei:{radioID}|sip:{e.Gps.SipID} [{e.Gps.Lat:0.0000},{e.Gps.Lng:0.0000}]", ConsoleColor.DarkGreen); // add location parameters to an array String[] toSendString = new String[4]; toSendString[0] = e.Gps.UnitTime / 1000 + ""; toSendString[1] = e.Gps.SpeedKmh + ""; toSendString[2] = e.Gps.Lat + ""; toSendString[3] = e.Gps.Lng + ""; // create the location message byte[] data = createLocationMessage((int)MessageBusCmds.LocationReceived, radioID.ToString(), toSendString); // add location to message bus MainForm.udp.Send(data, data.Length); } private void PollResponseReceivedOnSocketIO(object sender, GpsReceivedEventArgs e) { if (e.Gps == null || e.Gps.UserID == null) return; string radioID = "0"; if (MulticastListener.MobileVehicleList.ContainsKey(e.Gps.UserID)) radioID = (String)MulticastListener.MobileVehicleList[e.Gps.UserID]; Utils.WriteLine($"PollResponseReceivedOnSocketIO - imei:{radioID}|sip:{e.Gps.SipID} [{e.Gps.Lat:0.0000},{e.Gps.Lng:0.0000}]", ConsoleColor.DarkGreen); // add location parameters to an array String[] toSendString = new String[4]; toSendString[0] = e.Gps.UnitTime / 1000 + ""; toSendString[1] = e.Gps.SpeedKmh + ""; toSendString[2] = e.Gps.Lat + ""; toSendString[3] = e.Gps.Lng + ""; // create the location message byte[] data = createLocationMessage((int)MessageBusCmds.PollResponseReceived, radioID.ToString(), toSendString); // add location to message bus MainForm.udp.Send(data, data.Length); } /// /// Create a Location Message that can be sent on message bus /// /// GPS Location operation code /// Radio id of the unit /// Position data /// public static byte[] createLocationMessage(int opCode, string suid, String[] dataString) { string msg = ""; msg = "#1." + (Utils.GetSecondsLocalFromDT(DateTime.Now)) + DateTime.Now.Millisecond.ToString() + "#" + opCode + "#" + suid + "#"; msg = msg + dataString[0] + "#" + dataString[1] + "#" + dataString[2] + "#" + dataString[3]; int totalSize = 5 + msg.Length; string sizeMsg = String.Format("#{0:000}", totalSize); msg = sizeMsg + msg; Byte[] toSendMulticast = new Byte[totalSize]; System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding(); Byte[] toSendMulticastPartial = encoding.GetBytes(msg); for (int i = 0; i < toSendMulticastPartial.Length; i++) { toSendMulticast[i] = toSendMulticastPartial[i]; } toSendMulticast[totalSize - 1] = 35; return toSendMulticast; } /// /// Event handler for an emergency message received via SocketIO /// /// /// private void EmergencyReceivedOnSocketIO(object sender, EmergencyReceivedEventArgs e) { if (e.Emergency == null || e.Emergency.UserID == null) return; Utils.WriteLine("EmergencyReceivedOnSocketIO " + e.Emergency.SipID, ConsoleColor.DarkGreen); string radioID = "0"; if (e.Emergency.UserID == null) return; if (MulticastListener.MobileVehicleList.ContainsKey(e.Emergency.UserID)) radioID = (String)MulticastListener.MobileVehicleList[e.Emergency.UserID]; // handle the emergency received mListener?.onEmergencyReceivedHandler(e.Emergency.SequenceId, radioID, e.Emergency.EmergencyType, e.Emergency); } private void ArsReceivedOnSocketIO(object sender, ArsReceivedEventArgs e) { if (e.Ars == null || e.Ars.UserID == null) return; Utils.WriteLine("ArsReceivedOnSocketIO " + e.Ars.SipID, ConsoleColor.DarkGreen); // new ars received string radioID = "0"; if (MulticastListener.MobileVehicleList.ContainsKey(e.Ars.UserID)) radioID = (String)MulticastListener.MobileVehicleList[e.Ars.UserID]; if (MainForm.VehicleHashStat[radioID] != null) { ((VehicleStatus)MainForm.VehicleHashStat[radioID]).lastArsTime = DateTime.Now; // do not push any status update if the current status is emergency if (((VehicleStatus)MainForm.VehicleHashStat[radioID]).curentStatus == Status_for_tab.EMERG) return; DBsubsOperationManager dbsubsoperManage = new DBsubsOperationManager(Program.cfg.DB_IP, Program.cfg.DB_schema, Program.cfg.DB_user, Program.cfg.DB_passwd, Program.cfg.DB_port); dbsubsoperManage?.updateSUStatus(radioID, e.Ars.Ars ? 1 : 0); if (!e.Ars.Ars) { ((VehicleStatus)MainForm.VehicleHashStat[radioID]).curentStatus = Status_for_tab.OFF; MulticastListener.PushStatus(radioID, Status_for_tab.OFF); } else { if (MainForm.VehStolen.ContainsKey(radioID) && (int)MainForm.VehStolen[radioID] == 1) { Utils.WriteLine("ARS received on SocketIO for a stolen vehicle " + radioID, ConsoleColor.Cyan); } ((VehicleStatus)MainForm.VehicleHashStat[radioID]).curentStatus = Status_for_tab.ON; MulticastListener.PushStatus(radioID, Status_for_tab.ON); } } else mListener.dbuser.SetUserStateForSipID(Int32.Parse(e.Ars.SipID), e.Ars.Ars); } #endregion /// /// Callback for when an emergency ack is received over the MessageBus /// /// Unique identifier for the emergency ack /// The unit that needs to receive the emergency ack private void MListener_OnEmergencyAckReceived(string seqID, string radioID) { String scId = ""; String sipId = ""; if (MainForm.VehList.ContainsKey(radioID)) { scId = ((Vehicle_Data)MainForm.VehList[radioID]).sc_id + ""; sipId = ((Vehicle_Data)MainForm.VehList[radioID]).sip_id + ""; } EmergencyAckInfo emergAckInfo = new EmergencyAckInfo() { SequenceId = seqID, SipID = sipId, UserID = scId, WhoAckId = "0", WhoAckSipId = "0" }; _socketIOClass?.SendEmergencyAck(emergAckInfo); } /// /// Callback for when a poll request is received over the MessageBus /// /// Unique identifier for the poll request /// The unit that needs to receive the poll request private void MListener_OnPollRequestReceived(string seqID, string radioID) { String scId = ""; String sipId = ""; if (!MainForm.VehList.ContainsKey(radioID)) return; // do not continue to send the poll request over socketIO because the unit is not a mobile one if (((Vehicle_Data)MainForm.VehList[radioID]).type != 1) return; // get scId and sipId for required radioID scId = ((Vehicle_Data)MainForm.VehList[radioID]).sc_id + ""; sipId = ((Vehicle_Data)MainForm.VehList[radioID]).sip_id + ""; // pack the poll request PollRequestInfo pollReqInfo = new PollRequestInfo() { SequenceId = seqID, SipID = sipId, UserID = scId, }; // send the request over the socketIO _socketIOClass?.SendPollRequest(pollReqInfo); } private void MListener_OnDatabaseDown() { // DB is down ServiceControlUtils.startService("PostgreSD"); } void mListener_OnRefreshHashRequest() { Utils.WriteLine("DELEGATE ", ConsoleColor.Red); OnRefreshHashRequest?.Invoke(); isGPSCheckboxChecked = IsGPSCheckboxChecked(); try { DBemailServiceManager DB = new DBemailServiceManager(Program.cfg.DB_IP, Program.cfg.DB_schema, Program.cfg.DB_user, Program.cfg.DB_passwd, Program.cfg.DB_port); Program.cfg.enableEmailService = DB.GetEmailServiceSettings().Enable; if (Program.cfg.enableEmailService) { SM.Debug("EmailService on"); } else { SM.Debug("Email Service is not enabled"); } } catch (Exception ex) { Utils.WriteLine("mListener_OnRefreshHashRequest error: " + ex.ToString(), ConsoleColor.DarkMagenta); } } public Boolean IsGPSCheckboxChecked() { try { string EmergencyOnly = dbSettingsManager.getSettingValue(0, DBsettingsManager.EMERGENCY_ONLY_KEY); if (EmergencyOnly.Trim().Equals("false") || EmergencyOnly.Trim().Equals("")) { return false; } else { return true; } } catch (Exception ex) { Utils.WriteLine("Error GPSCheckboxChecked: " + ex.ToString(), ConsoleColor.Red); return false; } } public enum ServiceStatus { RUNNING, STOPPED, PAUSED, STOPPING, STARTING, STATUS_CHANGING, NOT_INSTALLED }; public static ServiceStatus GetStatus(string serviceName) { ServiceController sc = new ServiceController(serviceName); try { switch (sc.Status) { case ServiceControllerStatus.Running: return ServiceStatus.RUNNING; case ServiceControllerStatus.Stopped: return ServiceStatus.STOPPED; case ServiceControllerStatus.Paused: return ServiceStatus.PAUSED; case ServiceControllerStatus.StopPending: return ServiceStatus.STOPPING; case ServiceControllerStatus.StartPending: return ServiceStatus.STARTING; default: return ServiceStatus.STATUS_CHANGING; } } catch { return ServiceStatus.NOT_INSTALLED; } } public delegate void RefreshHashRequest(); public event RefreshHashRequest OnRefreshHashRequest; } }