2144 lines
86 KiB
C#
2144 lines
86 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Text;
|
|
using System.Windows.Forms;
|
|
using Telerik.WinControls.UI;
|
|
using Nini.Config;
|
|
using System.Threading;
|
|
using MotoTRBO_GW;
|
|
using System.Net;
|
|
using System.Diagnostics;
|
|
using Telerik.WinControls;
|
|
using SafeMobileLib;
|
|
using System.Net.Sockets;
|
|
using System.Collections;
|
|
using MotoTRBO_XNL_Cmd;
|
|
using System.IO;
|
|
using SharedUI;
|
|
using NAudio.Wave;
|
|
using System.Runtime.InteropServices;
|
|
//using NetFwTypeLib;
|
|
|
|
namespace MotoTrbo_GW
|
|
{
|
|
|
|
public partial class Main : RadForm
|
|
{
|
|
// save the version of the application server in order to use it for the updater
|
|
public static String APP_SERVER_VERSION = "";
|
|
|
|
public static TimeSpan timeDifference = new TimeSpan(0);
|
|
|
|
public static int GWID = -1;
|
|
public static bool TESTMODE = false;
|
|
private static IConfigSource source = null;
|
|
public static string CFG_FILE = "GWconfig.ini";
|
|
public static string ApplicationServer, DBServer, DBSchema, DBUser, DBPass, DBPort;
|
|
// Audio related fields
|
|
private static AudioManager _audioManager = null;
|
|
BufferedWaveProvider _buffWaveProviderAsio = null;
|
|
public static AudioDriverType AudioDriver;
|
|
public static int bitdepth = 16;
|
|
public static int bitdepthInBytes = 2;
|
|
public static int sampleRate = 8000;
|
|
public static int recordedBufferMiliseconds = 32;
|
|
public static string asioDriverName = "";
|
|
private List<radioForm> _listOfRadioForms = new List<radioForm>();
|
|
private byte[] _bufferForAudio = null;
|
|
private bool _connectedToAsioBoard = false;
|
|
private System.Timers.Timer _timerCheckAsioBoard = null;
|
|
//
|
|
public static Boolean capacityPlus;
|
|
public static int pingInterval = 5000;
|
|
public static bool autoupdate = true;
|
|
public static bool isDevelope = false;
|
|
|
|
public static String masterRadioIP;
|
|
public static String messageBusIP;
|
|
public static String messageBusPort;
|
|
|
|
private controlVoiceMain voiceMainCTRL;
|
|
|
|
private LocationThread LocationConnection = null;
|
|
private ARSThread ARSConnection = null;
|
|
private EmergencyThread EmergencyConnection = null;
|
|
private SMSReceiveThread SMSReceiveConnection = null;
|
|
private SMSSendThread SMSSendConnection = null;
|
|
private TallysmanReceiveThread TallysmanReceiveConnection = null;
|
|
private TelemetryReceiveThread TelemetryReceiveConnection = null;
|
|
private static TallysmanSendThread TallysmanSendConnection = null;
|
|
private TelemetrySendThread TelemetrySendConnection = null;
|
|
private RemoteStunThread RemoteStunConnection = null;
|
|
|
|
public static Int32 SMSServicePort = 4007;
|
|
public static Int32 ARSServicePort = 4005;
|
|
public static Int32 LocationServicePort = 4001;
|
|
public static Int32 EmergencyServicePort = 8002;
|
|
public static Int32 TelemetryServicePort = 4008;
|
|
public static Int32 TallysmanServicePort = 4010;
|
|
//Non-IP Capable Peripheral Raw Data port
|
|
private static Int32 TallysmanSendPort = 4069;
|
|
//default time value for checking missign Id from database
|
|
public static int TallysmanRequestInterval = 1;
|
|
private static bool SEND_LOCATION_STOP = false;
|
|
|
|
|
|
private Thread LocationThreadObj = null;
|
|
private Thread SMSReceiveThreadObj = null;
|
|
private Thread SMSSendThreadObj = null;
|
|
private Thread TelemetryReceiveThreadObj = null;
|
|
private Thread TelemetrySendThreadObj = null;
|
|
private Thread TallysmanReceiveThreadObj = null;
|
|
private Thread TallysmanSendThreadObj = null;
|
|
private TcpClient client;
|
|
private Int32 registrationPort = 5680;
|
|
private Boolean registeredIP;
|
|
private BackgroundWorker bgWorkerRegistration;
|
|
private WaitingForm wf;
|
|
|
|
public static bool wait4ack = true;
|
|
public static int sms_sending_interval = 1200;
|
|
public static int number_of_retries = 5;
|
|
public static int retry_interval_sec = 180;
|
|
|
|
private RouteManager routeManager;
|
|
private Hashtable NetworkIDS_hash;
|
|
public string YourIPaddress = "";
|
|
|
|
private Hashtable SMSReceiveThreadObjArr;
|
|
private Hashtable RemoteStunThreadOBJArr;
|
|
private Hashtable RemoteStunConnectionArr;
|
|
|
|
private Hashtable EmergencyThreadObjArr;
|
|
private Hashtable EmergencyConnectionArr;
|
|
|
|
private Hashtable ARSThreadObjArr;
|
|
|
|
public static Dictionary<string, RadioConnection> RadioComArr;
|
|
|
|
public MessageBusHandler mbHandler;
|
|
public static List<GatewayID_IP> gatewayRadios;
|
|
//public static List<Group> GroupList;
|
|
|
|
public static Dictionary<Int32, SMSConfirm> smsConfirmForUnits = new Dictionary<int, SMSConfirm>();
|
|
|
|
private System.Windows.Forms.Timer StatusCheckTimer;
|
|
|
|
public static string LocalIP { get; private set; } = null;
|
|
|
|
//this variable is used to prevent multiple start/end call processing from dispatchers while a gateway is in a patch
|
|
public static Dictionary<string, bool> gatewayState = new Dictionary<string, bool>();
|
|
|
|
|
|
#region LINX
|
|
|
|
#if LINXB
|
|
|
|
|
|
LINX.TrboSipGateway _sipGateway = null;
|
|
|
|
private bool _connectedToAsterisk;
|
|
public bool ConnectedToAsterisk
|
|
{
|
|
get { return _connectedToAsterisk; }
|
|
private set
|
|
{
|
|
if (value != _connectedToAsterisk)
|
|
{
|
|
_connectedToAsterisk = value;
|
|
UpdateUIConnectionStatus(_connectedToAsterisk);
|
|
}
|
|
}
|
|
}
|
|
|
|
private int _minSipPort;
|
|
private int _maxSipPort;
|
|
|
|
#endif
|
|
|
|
#endregion
|
|
|
|
#region constructor + config file
|
|
public Main()
|
|
{
|
|
//SafeMobileLib.Utils.WriteLine("Blalalalalalalalalala");
|
|
SM debug = new SM();
|
|
|
|
LoadConfig();
|
|
InitializeComponent();
|
|
|
|
|
|
StatusCheckTimer = new System.Windows.Forms.Timer();
|
|
StatusCheckTimer.Interval = 60 * 1000;
|
|
StatusCheckTimer.Enabled = true;
|
|
StatusCheckTimer.Tick += new System.EventHandler(StatusCheckTimerTick);
|
|
|
|
RadMessageBox.SetThemeName("TelerikMetroBlue");
|
|
|
|
// customize the new FeedbackRadMessageBox
|
|
FeedbackRadMessageBox.InteractionWaitSeconds = 7;
|
|
FeedbackRadMessageBox.SetTheme("TelerikMetroBlue");
|
|
|
|
// register for restart event
|
|
FeedbackRadMessageBox.OnRestartRequest += delegate()
|
|
{
|
|
RestartApp();
|
|
};
|
|
|
|
|
|
if (TESTMODE)
|
|
this.Text = "!!!!Warning TEST MODE activated!!!!!";
|
|
|
|
// add firewall exception
|
|
try
|
|
{
|
|
FireWallException fw = new FireWallException();
|
|
string name = System.AppDomain.CurrentDomain.FriendlyName;
|
|
string path = Application.ExecutablePath;
|
|
fw.checkFirewall(name, path);
|
|
|
|
//bool result = fw.AuthorizeProgram(name, path, NET_FW_SCOPE_.NET_FW_SCOPE_ALL, NET_FW_IP_VERSION_.NET_FW_IP_VERSION_ANY);
|
|
//if (result) SafeMobileLib.Utils.WriteLine("Firewall exception added for:" + name + " path:" + path);
|
|
//else SafeMobileLib.Utils.WriteLine("Firewall exception ERROR for:" + name + " path:" + path);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
//SafeMobileLib.Utils.WriteLine("Firewall exception ERROR:",false);
|
|
SafeMobileLib.Utils.WriteLine(ex.ToString());
|
|
|
|
RadMessageBox.Show("MotoTRBO GW could not add an exception to Windows Firewall.\r\nPlese manually add this exception or close Windows Firewall. ",
|
|
"Windows Firewall exception.Please restart the application.");
|
|
}
|
|
|
|
//get version
|
|
Version v = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
|
|
lbVersion.Text = "Version: " + v.ToString();
|
|
tabVoice.Enabled = false;
|
|
|
|
if (capacityPlus)
|
|
{
|
|
cbCapacityPlus.Checked = true;
|
|
lbMasterIP.Text = "Master Radio IP:" + masterRadioIP;
|
|
}
|
|
else
|
|
{
|
|
cbCapacityPlus.Checked = false;
|
|
lbMasterIP.Text = "";
|
|
}
|
|
|
|
|
|
// Get the time from Internet and then save the difference in time between the local computer time
|
|
// and the internet one from time.nist.gov
|
|
Thread internetTimeThread = new Thread(new ThreadStart(delegate ()
|
|
{
|
|
timeDifference = (DT.GetNetworkTime()).Subtract(DateTime.UtcNow);
|
|
}));
|
|
internetTimeThread.Start();
|
|
|
|
wf = new WaitingForm();
|
|
wf.Show();
|
|
|
|
bgWorkerRegistration = new BackgroundWorker();
|
|
bgWorkerRegistration.DoWork += new DoWorkEventHandler(bgWorkerRegistration_DoWork);
|
|
bgWorkerRegistration.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorkerRegistration_RunWorkerCompleted);
|
|
bgWorkerRegistration.RunWorkerAsync();
|
|
|
|
}
|
|
|
|
private void AudioManager_AsioAudioAvailable(object sender, AsioAudioAvailableEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
if (e.OutputBuffers.Length != 0)
|
|
{
|
|
_bufferForAudio = NAudio.Utils.BufferHelpers.Ensure(_bufferForAudio, e.SamplesPerBuffer * bitdepthInBytes);
|
|
foreach (radioForm rf in _listOfRadioForms)
|
|
{
|
|
RadioComHandler rcHandler = rf.rcHandler;
|
|
if (rcHandler != null && rcHandler.buffWaveProvider != null)
|
|
{
|
|
rcHandler.buffWaveProvider.Read(_bufferForAudio, 0, _bufferForAudio.Length);
|
|
Marshal.Copy(_bufferForAudio, 0, e.OutputBuffers[rcHandler.OutDevIDProperty], _bufferForAudio.Length);
|
|
}
|
|
}
|
|
}
|
|
if (e.InputBuffers.Length != 0)
|
|
{
|
|
_bufferForAudio = NAudio.Utils.BufferHelpers.Ensure(_bufferForAudio, e.SamplesPerBuffer * bitdepthInBytes);
|
|
foreach (radioForm rf in _listOfRadioForms)
|
|
{
|
|
RadioComHandler rcHandler = rf.rcHandler;
|
|
if (rcHandler != null)
|
|
{
|
|
Marshal.Copy(e.InputBuffers[rcHandler.InDevIDProperty], _bufferForAudio, 0, e.SamplesPerBuffer * bitdepthInBytes);
|
|
rcHandler.VoiceReceivedFromRadio(_bufferForAudio, _bufferForAudio.Length);
|
|
}
|
|
}
|
|
}
|
|
if (!_connectedToAsioBoard)
|
|
{
|
|
_connectedToAsioBoard = true;
|
|
SafeMobileLib.Utils.WriteLine("---- ASIO: inside audio available event handler----");
|
|
//SafeMobileLib.Utils.WriteEventLog("SafeMobile", "Asio audio available", EventLogEntryType.Information, 21777);
|
|
}
|
|
e.WrittenToOutputBuffers = true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SafeMobileLib.Utils.WriteLine("Error AudioManager_AsioAudioAvailable: " + ex.ToString(), ConsoleColor.Red);
|
|
SafeMobileLib.Utils.WriteEventLog("SafeMobile", "Error AudioManager_AsioAudioAvailable: " + ex.ToString(), EventLogEntryType.Error, 21778);
|
|
}
|
|
}
|
|
|
|
private void AudioManager_PlaybackStopped(object sender, StoppedEventArgs e)
|
|
{
|
|
string msg = "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\nASIO playback stopped event\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!";
|
|
SafeMobileLib.Utils.WriteLine(msg, ConsoleColor.Red);
|
|
SafeMobileLib.Utils.WriteEventLog("SafeMobile", msg, EventLogEntryType.Warning, 21779);
|
|
|
|
}
|
|
|
|
private void _timerCheckAsioBoard_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
|
|
{
|
|
if (_connectedToAsioBoard)
|
|
{
|
|
_connectedToAsioBoard = false;
|
|
}
|
|
else
|
|
{
|
|
// Instantiate again the asio class
|
|
string msg = "ASIO board disconnected. Reconecting....";
|
|
SafeMobileLib.Utils.WriteLine(msg, ConsoleColor.Yellow);
|
|
SafeMobileLib.Utils.WriteEventLog("SafeMobile", msg, EventLogEntryType.Warning, 21780);
|
|
ClearAsioResources();
|
|
if (_audioManager == null)
|
|
{
|
|
try
|
|
{
|
|
InitAsioClassOnUIThread();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SafeMobileLib.Utils.WriteLine(ex.ToString(), ConsoleColor.Red);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Display a console message displaying the number of positions received in the last minute and the total number of positions
|
|
/// since the gateway was started
|
|
/// </summary>
|
|
private void StatusCheckTimerTick(object sender, EventArgs e)
|
|
{
|
|
SafeMobileLib.Utils.WriteEventLog("SafeMobile", "Received " + LocationThread.NumberOfPositionsSinceLastRead
|
|
+ " positions in last minute " + " [" + LocationThread.NumberOfPositions + " total]", EventLogEntryType.Information, 21522);
|
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Restart the application and close other notify icons
|
|
/// </summary>
|
|
private void RestartApp()
|
|
{
|
|
SafeMobileLib.Utils.WriteEventLog("SafeMobile", "Gateway is Restarting", EventLogEntryType.Warning, 21522);
|
|
|
|
CloseNotifyIcon();
|
|
|
|
Program.isRunning = false;
|
|
|
|
Thread p = new Thread(new ThreadStart(delegate ()
|
|
{
|
|
|
|
//oldProcess.WaitForExit(8000);
|
|
System.Diagnostics.Process.Start(System.Reflection.Assembly.GetExecutingAssembly().Location, Program.isConsoleEnabled ? " -c" : "");
|
|
|
|
Process oldProcess = Process.GetCurrentProcess();
|
|
oldProcess.Kill();
|
|
System.Environment.Exit(0);
|
|
|
|
}));
|
|
p.Start();
|
|
|
|
}
|
|
|
|
|
|
private void CloseNotifyIcon()
|
|
{
|
|
if (notifyIcon1 != null)
|
|
{
|
|
notifyIcon1.Visible = false;
|
|
notifyIcon1.Icon = null;
|
|
notifyIcon1.Dispose();
|
|
}
|
|
}
|
|
|
|
|
|
private void FetchAudioSettings()
|
|
{
|
|
DBsettingsManager dbSettings = new DBsettingsManager(DBServer, DBSchema, DBUser, DBPass, DBPort);
|
|
|
|
string tmpSamplaRate = dbSettings.getSettingValue(0, "sampleRate");
|
|
if (!string.IsNullOrEmpty(tmpSamplaRate))
|
|
sampleRate = int.Parse(tmpSamplaRate);
|
|
else
|
|
{
|
|
SafeMobileLib.Utils.WriteLine("Invalid sample rate", ConsoleColor.Red);
|
|
}
|
|
|
|
string tmpBitDepth = dbSettings.getSettingValue(0, "bitDepth");
|
|
if (!string.IsNullOrEmpty(tmpSamplaRate))
|
|
{
|
|
bitdepth = int.Parse(tmpBitDepth);
|
|
bitdepthInBytes = bitdepth / 8;
|
|
}
|
|
else
|
|
{
|
|
SafeMobileLib.Utils.WriteLine("Invalid bit depth", ConsoleColor.Red);
|
|
}
|
|
|
|
string tmpBufferMilliseconds = dbSettings.getSettingValue(0, "bufferMilliseconds");
|
|
if (!string.IsNullOrEmpty(tmpBufferMilliseconds))
|
|
recordedBufferMiliseconds = int.Parse(tmpBufferMilliseconds);
|
|
else
|
|
{
|
|
SafeMobileLib.Utils.WriteLine("Invalid bufferMilliseconds", ConsoleColor.Red);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
private void ContinueConstructor()
|
|
{
|
|
|
|
if (!registeredIP)
|
|
{
|
|
tabVoice.Enabled = false;
|
|
|
|
DialogResult result = FeedbackRadMessageBox.ShowExclamation("Please register your copy of MotoTrbo Gateway using the Administrative Module.\n Your IP address is:" + YourIPaddress, "Info");
|
|
if (result == DialogResult.OK)
|
|
Application.Exit();
|
|
}
|
|
else if (registeredIP && !App.isValidVersion(APP_SERVER_VERSION,
|
|
System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString()))
|
|
{
|
|
DialogResult dr = RadMessageBox.Show("Please update your version of software to the latest one required by Application Server. Do you wish to update now?",
|
|
"Update required...", MessageBoxButtons.YesNo, RadMessageIcon.Exclamation);
|
|
|
|
if (dr == DialogResult.Yes)
|
|
CheckForUpdate(true);
|
|
|
|
Application.Exit();
|
|
}
|
|
else
|
|
{
|
|
//new code
|
|
List <Gateway> listGW = new List<Gateway>();
|
|
try
|
|
{
|
|
|
|
if (!string.IsNullOrEmpty(DBServer))
|
|
{
|
|
listGW = getGWidFromDB(DBServer);
|
|
}
|
|
|
|
|
|
if (listGW.Count == 0)
|
|
{
|
|
DBServer = "127.0.0.1";
|
|
listGW = getGWidFromDB(DBServer);
|
|
}
|
|
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SafeMobileLib.Utils.WriteLine("Ex on find automat the gateway ID:" + ex.ToString());
|
|
}
|
|
|
|
|
|
try
|
|
{
|
|
if (listGW.Count == 0)
|
|
{
|
|
FeedbackRadMessageBox.ShowError("Gateway IP not present in DB\n\r Please go to Administrative module and register this GW with IP:!!!" + DBServer, "IP missing");
|
|
|
|
System.Environment.Exit(0);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
GWID = ((Gateway)listGW[0]).Id;
|
|
source = new IniConfigSource(Main.CFG_FILE);
|
|
source.Configs["Gateway"].Set("id", GWID);
|
|
// source.Configs["NAI"].Set("peerID", ((Gateway)listGW[0]).Peer_id);
|
|
source.Save();
|
|
|
|
SafeMobileLib.Utils.WriteLine("Gateway ID is " + GWID, ConsoleColor.Cyan);
|
|
|
|
//SafeMobileLib.Utils.WriteLine("ID:" + GWID + " saved to config file.");
|
|
btGWID.Text = GWID.ToString();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SafeMobileLib.Utils.WriteLine("DB error!!!");
|
|
SafeMobileLib.Utils.WriteLine(ex.ToString());
|
|
|
|
FeedbackRadMessageBox.ShowError("DB error.\n\rPlease turn down the firewall or add an exception for the Datebase in the firewall and try again!!!\n\r DB ip:" + DBServer,
|
|
"DB error");
|
|
|
|
|
|
System.Environment.Exit(0);
|
|
//System.Windows.Forms.Application.Exit();
|
|
return;
|
|
}
|
|
//end of new code
|
|
|
|
|
|
// Get Audio settings
|
|
FetchAudioSettings();
|
|
|
|
|
|
//int asio driver object
|
|
if (Main.AudioDriver == AudioDriverType.Asio)
|
|
{
|
|
try
|
|
{
|
|
if (_audioManager == null)
|
|
{
|
|
InitAsio();
|
|
InitAsioClassOnUIThread();
|
|
// Set up timer that checks if Asio board is connected
|
|
_timerCheckAsioBoard = new System.Timers.Timer(2000);
|
|
_timerCheckAsioBoard.Elapsed += _timerCheckAsioBoard_Elapsed;
|
|
_timerCheckAsioBoard.Start();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
//string msg = "Unable to instantiate asio driver. Please ensure your soundcard is connected or choose another driver from combobox.\n\r\n\r" + ex.Message;
|
|
string msg = "Unable to instantiate asio driver. Do you want this time to use the default windows drivers instead?";//+".\n\r\n\r" + ex.Message;
|
|
FeedbackRadMessageBox.InteractionWaitSeconds = 320;
|
|
DialogResult result = FeedbackRadMessageBox.Show("Asio drivers issue", msg, MessageBoxButtons.YesNo, RadMessageIcon.Exclamation);
|
|
|
|
if (result == DialogResult.Yes)
|
|
{
|
|
lblAsioDriverName.Visibility = cbAsio.Visibility = ElementVisibility.Hidden;
|
|
Main.AudioDriver = AudioDriverType.Windows;
|
|
}
|
|
else
|
|
{
|
|
MainPanel.Text = "Unable to instantiate asio driver.";
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*try
|
|
{
|
|
DBgroupsManager db4groups = new DBgroupsManager(DBServer, DBSchema, DBUser, DBPass, DBPort);
|
|
GroupList = db4groups.GetAllGroups();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SafeMobileLib.Utils.WriteLine("Error on load groups: "+ex.ToString());
|
|
}*/
|
|
|
|
tabVoice.Enabled = true;
|
|
radRibbonBar1.RibbonBarElement.QuickAccessToolBar.Visibility = Telerik.WinControls.ElementVisibility.Hidden;
|
|
radRibbonBar1.Expanded = false;
|
|
//test id app is already running
|
|
testIfAlreadyRunning();
|
|
//start message bus handler
|
|
mbHandler = new MessageBusHandler(messageBusIP, messageBusPort);
|
|
#region LINX
|
|
#if LINXB
|
|
mbHandler.RefreshDatabaseCommandReceived += MbHandler_RefreshDatabaseCommandReceived;
|
|
#endif
|
|
#endregion
|
|
|
|
routeManager = new RouteManager();
|
|
routeManager.OnRadioStatusUpdate += new RouteManager.RadioStatusUpdateDEl(routeManager_OnRadioStatusUpdate);
|
|
routeManager.Start();
|
|
|
|
SMSReceiveThreadObjArr =new Hashtable();
|
|
RemoteStunThreadOBJArr = new Hashtable();
|
|
RemoteStunConnectionArr = new Hashtable();
|
|
EmergencyThreadObjArr = new Hashtable();
|
|
EmergencyConnectionArr = new Hashtable();
|
|
ARSThreadObjArr = new Hashtable();
|
|
RadioComArr = new Dictionary<string, RadioConnection>();
|
|
|
|
StartLocationService();
|
|
|
|
StartARSService();
|
|
|
|
StartSMSService();
|
|
|
|
//StartEmergencyService();moved to routeManager_OnRadioStatusUpdate
|
|
|
|
StartTelemetryService();
|
|
|
|
StartTallysmanService();
|
|
|
|
StartRemoteStunService(); //for non Cap plus moved to routeManager_OnRadioStatusUpdate
|
|
|
|
LoadRadioTab(true);
|
|
|
|
#region LINX
|
|
#if LINXB
|
|
// Start sip registration
|
|
bool errorOnRegister = false;
|
|
_sipGateway = new LINX.TrboSipGateway(DBServer, DBSchema, DBUser, DBPass, DBPort, _minSipPort, _maxSipPort, out errorOnRegister);
|
|
|
|
_sipGateway.ConnectionStatusChanded += _sipGateway_ConnectionStatusChanded;
|
|
_sipGateway.LinxSendsInvite += _sipGateway_LinxSendsInvite;
|
|
_sipGateway.DialogCreated += _sipGateway_DialogCreated;
|
|
_sipGateway.DialogClosed += _sipGateway_DialogClosed;
|
|
_sipGateway.ErrorOnCreatingDialog += _sipGateway_ErrorOnCreatingDialog;
|
|
_sipGateway.VoiceReceived += _sipGateway_VoiceReceived;
|
|
//_sipGateway.LinxHangtimeEnded += _sipGateway_LinxHangtimeEnded;
|
|
_sipGateway.SmsFromLinxToRadio += _sipGateway_SmsReceived;
|
|
_sipGateway.ShowUIMessage += _sipGateway_ShowUIMessage;
|
|
|
|
ConnectedToAsterisk = _sipGateway.ConnectedToAstersisk;
|
|
|
|
if (errorOnRegister)
|
|
_sipGateway_ShowUIMessage("Not all the radios are connected to Linx server.Check sip ports range in config file");
|
|
|
|
#endif
|
|
|
|
#endregion
|
|
}
|
|
SafeMobileLib.Utils.WriteEventLog("SafeMobile", "Gateway turned on with ID " + GWID, EventLogEntryType.SuccessAudit, 21521);
|
|
}
|
|
|
|
|
|
private void InitAsioClassOnUIThread()
|
|
{
|
|
if (this.InvokeRequired)
|
|
{
|
|
this.Invoke((Action)(() => { InitAsioClass(); }));
|
|
}
|
|
else
|
|
InitAsioClass();
|
|
}
|
|
|
|
private void InitAsioClass()
|
|
{
|
|
_audioManager = new AudioManager(asioDriverName);
|
|
int channels = _audioManager.AsioDriverInputChannelCount;
|
|
_buffWaveProviderAsio = new BufferedWaveProvider(new NAudio.Wave.WaveFormat(sampleRate, bitdepth, channels));
|
|
_audioManager.AsioAudioAvailable += AudioManager_AsioAudioAvailable;
|
|
_audioManager.PlaybackStopped += AudioManager_PlaybackStopped;
|
|
_audioManager.Init(_buffWaveProviderAsio, channels, sampleRate);
|
|
_audioManager.Play();
|
|
}
|
|
|
|
|
|
|
|
|
|
#region TRBO Sip Gateway event handlers
|
|
|
|
#if LINXB
|
|
private void _sipGateway_ConnectionStatusChanded(bool connected)
|
|
{
|
|
this.ConnectedToAsterisk = connected;
|
|
}
|
|
|
|
private void _sipGateway_LinxSendsInvite(LINX.RadioSipInfo radioSipInfo, string callingLinxID)
|
|
{
|
|
// 1. Check if the corresponding base radio is available for call
|
|
int radioGwID = int.Parse(radioSipInfo.ContactInfo.GWandRadioGW.Split('.')[1]);
|
|
radioForm rf = voiceMainCTRL.radiosFormList.Find(radioF => radioF.RadioID == radioGwID);
|
|
if (rf != null)
|
|
{
|
|
if (rf.rcHandler != null)
|
|
{
|
|
|
|
/* I MOVED THIS PART IN A FUNCTION IN RADIOCOMHANDLER.CS
|
|
if (rf.rcHandler.IsPTTbussy)
|
|
{
|
|
// 2. If base radio is not available reject the invite.
|
|
radioSipInfo.SipClass.Decline(callingLinxID);
|
|
SafeMobileLib.Utils.WriteLine($@"Declined the inivite from sip id {callingLinxID} to radio {radioSipInfo.ContactInfo.Name}
|
|
because base station {radioGwID} is ptt busy", ConsoleColor.Green);
|
|
}
|
|
else
|
|
{
|
|
bool groupCall = radioSipInfo.ContactInfo.Type == ContactType.GROUP;
|
|
|
|
rf.rcHandler.LinxCallInfo = new LINX.LinxCall(callingLinxID, radioSipInfo.ContactInfo.SipId);
|
|
if (groupCall)
|
|
{
|
|
RadioComArr[rf.RadioIP].SendCallType(0, radioSipInfo.ContactInfo.Id); // group radio ptt
|
|
rf.rcHandler.RadioStatusProp = RADIO_STATUS.GroupCall_INIT;
|
|
}
|
|
else
|
|
{
|
|
RadioComArr[rf.RadioIP].SendCallType(1, radioSipInfo.ContactInfo.Id); // private radio ptt
|
|
rf.rcHandler.RadioStatusProp = RADIO_STATUS.PrivateCall_INIT;
|
|
}
|
|
|
|
// start the tCheckStatus timer
|
|
rf.rcHandler.StartCheckStatusTimer();
|
|
bool success = RadioComArr[rf.RadioIP].SendPTTon();
|
|
if (success)
|
|
{
|
|
// Linx Private Call - 1002
|
|
// Linx Group Call - 1003
|
|
rf.rcHandler.CallType = groupCall ? 1003 : 1002;
|
|
}
|
|
else
|
|
{
|
|
// Error on SendPTTon()
|
|
// Reject the invite
|
|
radioSipInfo.SipClass.Decline(callingLinxID);
|
|
SafeMobileLib.Utils.WriteLine($@"Declined the inivite from sip id {callingLinxID} to radio {radioSipInfo.ContactInfo.Name}
|
|
because base station {radioGwID} failed to send PTT", ConsoleColor.Red);
|
|
}
|
|
}*/
|
|
bool acceptInvite = rf.rcHandler.InviteFromLinx(callingLinxID, radioSipInfo.ContactInfo.SipId, radioSipInfo.ContactInfo.Id, radioSipInfo.ContactInfo.Type == ContactType.GROUP);
|
|
if (!acceptInvite)
|
|
radioSipInfo.SipClass.Decline(callingLinxID);
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
private void _sipGateway_DialogCreated(LINX.RadioSipInfo sipInfo, string linxID, bool fromRadioToLinx)
|
|
{
|
|
|
|
if (fromRadioToLinx)
|
|
{
|
|
// PTT initiated from radio
|
|
// Notify RadioComHandler class that the dialog has been established
|
|
int radioGwID = int.Parse(sipInfo.ContactInfo.GWandRadioGW.Split('.')[1]);
|
|
radioForm rf = voiceMainCTRL.radiosFormList.Find(radioF => radioF.RadioID == radioGwID);
|
|
if (rf != null)
|
|
{
|
|
if (rf.rcHandler != null)
|
|
{
|
|
rf.rcHandler.LinxReceivesPTTFromRadio(new LINX.LinxCall(linxID, sipInfo.ContactInfo.SipId));
|
|
}
|
|
}
|
|
|
|
}
|
|
SafeMobileLib.Utils.WriteLine($"Dialog created between linx with sipID {linxID} and radio {sipInfo.ContactInfo.Name}",
|
|
ConsoleColor.Green);
|
|
}
|
|
|
|
|
|
private void _sipGateway_DialogClosed(LINX.RadioSipInfo sipInfo, string linxID, bool fromRadioToLinx)
|
|
{
|
|
int radioGwID = int.Parse(sipInfo.ContactInfo.GWandRadioGW.Split('.')[1]);
|
|
radioForm rf = voiceMainCTRL.radiosFormList.Find(radioF => radioF.RadioID == radioGwID);
|
|
SafeMobileLib.Utils.WriteLine($"PTT ended between linx with sipID {linxID} and radio {sipInfo.ContactInfo.Name}",
|
|
ConsoleColor.Green);
|
|
if (rf != null)
|
|
{
|
|
if (rf.rcHandler != null)
|
|
{
|
|
if (rf.rcHandler.IsPTTbussy)
|
|
{
|
|
if (!fromRadioToLinx)
|
|
{
|
|
// Linx sent PTT
|
|
rf.rcHandler.CallType = sipInfo.ContactInfo.Type == ContactType.GROUP ? 1003 : 1002;
|
|
RadioComArr[rf.RadioIP].SendPTToff();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void _sipGateway_ErrorOnCreatingDialog(LINX.RadioSipInfo sipInfo, string linxID, bool fromRadioToLinx)
|
|
{
|
|
int radioGwID = int.Parse(sipInfo.ContactInfo.GWandRadioGW.Split('.')[1]);
|
|
radioForm rf = voiceMainCTRL.radiosFormList.Find(radioF => radioF.RadioID == radioGwID);
|
|
SafeMobileLib.Utils.WriteLine($"Error on creating dialog between {linxID} and radio {sipInfo.ContactInfo.Name}",
|
|
ConsoleColor.Red);
|
|
if (rf != null)
|
|
{
|
|
if (rf.rcHandler != null)
|
|
{
|
|
if (rf.rcHandler.IsPTTbussy)
|
|
{
|
|
if (!fromRadioToLinx)
|
|
{
|
|
// Linx sent PTT
|
|
rf.rcHandler.CallType = sipInfo.ContactInfo.Type == ContactType.GROUP ? 1003 : 1002;
|
|
RadioComArr[rf.RadioIP].SendPTToff();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void _sipGateway_VoiceReceived(LINX.RadioSipInfo sipInfo, byte[] buffer)
|
|
{
|
|
int radioGwID = int.Parse(sipInfo.ContactInfo.GWandRadioGW.Split('.')[1]);
|
|
radioForm rf = voiceMainCTRL.radiosFormList.Find(radioF => radioF.RadioID == radioGwID);
|
|
if (rf != null)
|
|
{
|
|
if (rf.rcHandler != null)
|
|
{
|
|
rf.rcHandler.buffWaveProvider.AddSamples(buffer, 0, buffer.Length);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
private void _sipGateway_SmsReceived(ContactLinx remoteRadioIDInfo, string message, int linxRadioID)
|
|
{
|
|
// Sms received from linx
|
|
// Just send it on mbus
|
|
int radioGwID = int.Parse(remoteRadioIDInfo.GWandRadioGW.Split('.')[1]);
|
|
radioForm rf = voiceMainCTRL.radiosFormList.Find(radioF => radioF.RadioID == radioGwID);
|
|
if (rf != null)
|
|
{
|
|
if (rf.rcHandler != null)
|
|
{
|
|
// Generate string command to send on message bus
|
|
// #seqID#Opcode#gatewayId.gatewayRadioId.remoteRadioId#message#scheduleTime#dispatcherID#
|
|
string seqID = Utils.GenerateSeqID(linxRadioID);
|
|
string cmd= $"#{(int)MessageBusCmds.SendSMSRequest}#{Main.GWID}.{rf.rcHandler.RadioID}.{remoteRadioIDInfo.Id}#Linx{linxRadioID}.{message}#{DateTime.Now.ToUniversalTime().DateTo70Format()}#{linxRadioID}#";
|
|
MessageBusHandler.SendOnMsgBuss(seqID, cmd);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
private void _sipGateway_ShowUIMessage(string message)
|
|
{
|
|
if (this.InvokeRequired)
|
|
{
|
|
this.Invoke((Action)(() => ShowMessageBox(message)));
|
|
}
|
|
else
|
|
ShowMessageBox(message);
|
|
|
|
}
|
|
|
|
private void ShowMessageBox(string message)
|
|
{
|
|
MessageBox.Show(message, "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
|
}
|
|
|
|
//private void _sipGateway_LinxHangtimeEnded(LINX.RadioSipInfo sipInfo, string linxID)
|
|
//{
|
|
// // Clear linx call info in radioComHandler class
|
|
// int radioGWID = int.Parse(sipInfo.ContactInfo.GWandRadioGW.Split('.')[1]);
|
|
// radioForm rf = voiceMainCTRL.radiosFormList.Find(radioF => radioF.RadioID == radioGWID);
|
|
// if (rf != null)
|
|
// {
|
|
// if (rf.rcHandler != null)
|
|
// {
|
|
// rf.rcHandler.LinxCallInfo = LINX.LinxCall.DefaultValue; // default value.
|
|
// }
|
|
// }
|
|
//}
|
|
#endif
|
|
|
|
#endregion
|
|
|
|
#region Private functions for sip
|
|
|
|
#if LINXB
|
|
private void RcHandler_LinxCallEstablished(object sender, EventArgs e)
|
|
{
|
|
// Radio call established, accept the invite from LINX
|
|
RadioComHandler rcHandler = (RadioComHandler)sender;
|
|
LINX.LinxCall linxCallInfo;
|
|
if ((linxCallInfo = rcHandler.LinxCallInfo) != LINX.LinxCall.DefaultValue)
|
|
{
|
|
_sipGateway.GetSipClass(linxCallInfo.RadioSipID).AcceptInvite(linxCallInfo.LinxSipID);
|
|
}
|
|
}
|
|
|
|
private void RcHandler_LinxCallFailed(object sender, EventArgs e)
|
|
{
|
|
// Radio call failed, decline the invite from LINX
|
|
RadioComHandler rcHandler = (RadioComHandler)sender;
|
|
LINX.LinxCall linxCallInfo;
|
|
if ((linxCallInfo = rcHandler.LinxCallInfo) != LINX.LinxCall.DefaultValue)
|
|
{
|
|
_sipGateway.GetSipClass(linxCallInfo.RadioSipID).Decline(linxCallInfo.LinxSipID);
|
|
SafeMobileLib.Utils.WriteLine("Will reset linx call info from main because base radio could not call portable", ConsoleColor.DarkRed);
|
|
rcHandler.ResetLinxCallInfoValue();
|
|
}
|
|
}
|
|
|
|
private void RcHandler_CallLinx(object sender, LINX.CallLinxEventArgs e)
|
|
{
|
|
RadioComHandler rcHandler = (RadioComHandler)sender;
|
|
// Call linx and send voice
|
|
LINX.LinxCall linxCallInfo;
|
|
if ((linxCallInfo = rcHandler.LinxCallInfo) != LINX.LinxCall.DefaultValue)
|
|
{
|
|
_sipGateway.SendInvite(linxCallInfo.RadioSipID, linxCallInfo.LinxSipID);
|
|
}
|
|
else
|
|
{
|
|
int? linxSipID = null;
|
|
// The call is not in response to a LINX call
|
|
// Check if is group or private call
|
|
// If group call, check if there is a LINX associated with this group call
|
|
// If private call, check if there is a LINX that receives private call from this unit
|
|
if (e.IsGroup)
|
|
{
|
|
// group call
|
|
// Check if there is a LINX associated with this group call
|
|
linxSipID = _sipGateway.GetLinxInRadioGroup(e.GroupID);
|
|
if (linxSipID.HasValue)
|
|
{
|
|
int radioSipID = -1;
|
|
if (_sipGateway.LinxSipIDisGroup(linxSipID.Value))
|
|
radioSipID = _sipGateway.GetSipIDFromRadioID(e.RadioID, false);
|
|
else
|
|
radioSipID = _sipGateway.GetSipIDFromRadioID(e.GroupID, true);
|
|
|
|
_sipGateway.SendInvite(radioSipID, linxSipID.Value.ToString());
|
|
rcHandler.GroupCallInitiatedByRadio = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// private call
|
|
// If private call, check if there is a LINX that receives private call from this unit
|
|
linxSipID = _sipGateway.GetLinxForPrivateCall(e.RadioID);
|
|
if (linxSipID.HasValue)
|
|
{
|
|
int radioSipID = _sipGateway.GetSipIDFromRadioID(e.RadioID, false);
|
|
_sipGateway.SendInvite(radioSipID, linxSipID.Value.ToString());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void RcHandler_RadioEndsPTTtoLinx(object sender, EventArgs e)
|
|
{
|
|
// Radio has ended ptt
|
|
RadioComHandler rcHandler = (RadioComHandler)sender;
|
|
LINX.LinxCall linxCallInfo;
|
|
if ((linxCallInfo = rcHandler.LinxCallInfo) != LINX.LinxCall.DefaultValue)
|
|
{
|
|
// get the sip class
|
|
SipComponent.SipClientClass2 sipClass = _sipGateway.GetSipClass(linxCallInfo.RadioSipID);
|
|
// end sip call if call is in progress or cancel invite
|
|
if (sipClass.InDialogWith(linxCallInfo.LinxSipID))
|
|
sipClass.Close(linxCallInfo.LinxSipID);
|
|
else
|
|
sipClass.CancelInvite(linxCallInfo.LinxSipID);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
private void RcHandler_RadioVoiceToLinx(object sender, LINX.RadioVoiceToLinxEventArgs e)
|
|
{
|
|
RadioComHandler rcHandler = (RadioComHandler)sender;
|
|
LINX.LinxCall linxCallInfo;
|
|
if ((linxCallInfo = rcHandler.LinxCallInfo) != LINX.LinxCall.DefaultValue)
|
|
{
|
|
_sipGateway.GetSipClass(linxCallInfo.RadioSipID).SendAudio(
|
|
linxCallInfo.LinxSipID, e.VoiceBuffer, e.BufferLength, SipComponent.AudioFormat.PCM);
|
|
}
|
|
}
|
|
|
|
private int? RcHandler_LinxIDForPrivateCallRequested(int radioID)
|
|
{
|
|
return _sipGateway.GetLinxForPrivateCall(radioID);
|
|
}
|
|
|
|
private int RcHandler_RadioSipIDRequested(int radioID, bool isGroup)
|
|
{
|
|
return _sipGateway.GetSipIDFromRadioID(radioID, isGroup);
|
|
}
|
|
|
|
private void UpdateUIConnectionStatus(bool connectedToAsterisk)
|
|
{
|
|
System.Drawing.Color color;
|
|
string textToDisplay;
|
|
if (connectedToAsterisk)
|
|
{
|
|
color = System.Drawing.Color.Green;
|
|
textToDisplay = "Connected to Asterisk";
|
|
}
|
|
else
|
|
{
|
|
color = System.Drawing.Color.Red;
|
|
textToDisplay = "Not connected to Asterisk";
|
|
}
|
|
|
|
if (this.InvokeRequired)
|
|
{
|
|
this.Invoke((Action)(() => { ChangeConnectionLabel(color, textToDisplay); }));
|
|
}
|
|
else
|
|
ChangeConnectionLabel(color, textToDisplay);
|
|
}
|
|
|
|
private void SMSReceiveConnection_PrivateCallRequestForLinxReceived(int remoteRadioID, int linxRadioID)
|
|
{
|
|
_sipGateway.PrivateCallRequestFromRadioReceived(remoteRadioID, linxRadioID);
|
|
}
|
|
|
|
private async void SMSReceiveConnection_SmsForLixReceived(string seqID, int remoteRadioID, int linxRadioID, string text)
|
|
{
|
|
bool smsReceivedByLinx = await _sipGateway.SendSmsToLinx(seqID, linxRadioID, remoteRadioID, text);
|
|
// Send confirmation on mBus
|
|
// #seqID#Opcode#state#
|
|
// #seqID#242#1# or #seqID#242#0#
|
|
int state = smsReceivedByLinx ? 1 : 0;
|
|
MessageBusHandler.SendOnMsgBuss(seqID, $"#{(int)MessageBusCmds.FieldRadioReceivedSmsAck}#{state}#");
|
|
}
|
|
|
|
private void MbHandler_RefreshDatabaseCommandReceived(object sender, EventArgs e)
|
|
{
|
|
_sipGateway?.ListOfSipIDHasChanged();
|
|
}
|
|
|
|
private void ChangeConnectionLabel(System.Drawing.Color color, string text)
|
|
{
|
|
lblConnectedToAsterisk.ForeColor = color;
|
|
lblConnectedToAsterisk.Text = text;
|
|
}
|
|
#endif
|
|
#endregion
|
|
|
|
#region asio events for main
|
|
private void InitAsio()
|
|
{
|
|
lblAsioDriverName.Visibility = cbAsio.Visibility = ElementVisibility.Visible;
|
|
LoadAsioDrivers();
|
|
}
|
|
|
|
private void LoadAsioDrivers()
|
|
{
|
|
string[] driverList = AudioManager.GetAsioDriverNames();
|
|
foreach (String obj in driverList)
|
|
{
|
|
SafeMobileLib.Utils.WriteLine(obj, ConsoleColor.DarkMagenta);
|
|
RadMenuItem tmp = new RadMenuItem(obj);
|
|
tmp.Name = obj;
|
|
cbAsio.Items.Add(tmp);
|
|
tmp.Click += new System.EventHandler(DriverChangeEvent);
|
|
}
|
|
if (cbAsio.Items.Count > 0)
|
|
{
|
|
for (int i = 0; i < cbAsio.Items.Count; i++)
|
|
{
|
|
if (((RadMenuItem)cbAsio.Items[i]).Text == asioDriverName)
|
|
{
|
|
((RadMenuItem)cbAsio.Items[i]).IsChecked = true;
|
|
cbAsio.Text = ((RadMenuItem)cbAsio.Items[i]).Text;
|
|
}
|
|
}
|
|
}
|
|
if(cbAsio.Items.Count == 1 && ((RadMenuItem)cbAsio.Items[0]).Text != asioDriverName)
|
|
{
|
|
((RadMenuItem)cbAsio.Items[0]).IsChecked = true;
|
|
cbAsio.Text = asioDriverName = ((RadMenuItem)cbAsio.Items[0]).Text;
|
|
source = new IniConfigSource(CFG_FILE);
|
|
source.Configs["Voice"].Set("driverName", cbAsio.Text);
|
|
source.Save();
|
|
}
|
|
}
|
|
|
|
private void DriverChangeEvent(object sender, EventArgs e)
|
|
{
|
|
if (((RadMenuItem)sender).Name != asioDriverName)
|
|
{
|
|
source = new IniConfigSource(CFG_FILE);
|
|
source.Configs["Voice"].Set("driverName", ((RadMenuItem)sender).Name);
|
|
source.Save();
|
|
FeedbackRadMessageBox.ShowInfo("Info: You need to restart gateway to work with selected driver", "");
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
void routeManager_OnRadioStatusUpdate(bool status, string ip)
|
|
{
|
|
SafeMobileLib.Utils.WriteLine(". . . . . . . . . . . routeManager_OnRadioStatusUpdate . . . . . . . . . .");
|
|
SafeMobileLib.Utils.WriteLine($". . . . . . . . . . . ip:{ip} status:{status}. . . . . . . . . .");
|
|
|
|
SafeMobileLib.Utils.WriteEventLog("SafeMobile", "Radio gateway " + ip + " is now " + (status ? "online" : "offline"),
|
|
EventLogEntryType.Information, 21521);
|
|
//if (capacityPlus)
|
|
//{
|
|
//return;
|
|
//}
|
|
if (status)
|
|
{
|
|
//start radio connection
|
|
RadioConnection rc = null;
|
|
|
|
rc = new RadioConnection(ip, EmergencyServicePort, "XNL_CMDS");
|
|
if (RadioComArr.ContainsKey(ip))
|
|
{
|
|
RadioComArr[ip].Stop();
|
|
RadioComArr.Remove(ip);
|
|
}
|
|
RadioComArr.Add(ip, rc);
|
|
rc.Start();
|
|
|
|
//start ARS
|
|
if (!capacityPlus)
|
|
{
|
|
int Network_ID = Convert.ToInt32(RouteManager.NetworkIDs_Hash[ip]);
|
|
RoutingUtils.UpdateRoutes_NonCapPlus(ip, RadioStuff.GetInterface(ip), Network_ID);
|
|
GatewayID_IP ID_IP = new GatewayID_IP();
|
|
ID_IP.remoteIP = ip;
|
|
ID_IP.localIP = RadioStuff.GetInterface(ip);
|
|
ID_IP.ID = Network_ID.ToString();
|
|
if (!ARSThreadObjArr.ContainsKey(ip))
|
|
{
|
|
ARSThread ARSConnection = new ARSThread(ID_IP, ARSServicePort, false, messageBusIP, messageBusPort);
|
|
/*ARSConnection.OnArsReceived += delegate (Int64 radioID, bool isON)
|
|
{
|
|
// nothing for now here
|
|
};*/
|
|
Thread ARSThreadObj = new Thread(new ThreadStart(ARSConnection.handleConnection));
|
|
ARSThreadObj.IsBackground = true;
|
|
ARSThreadObj.Start();
|
|
ARSThreadObjArr.Add(ip, ARSThreadObj);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//add route for cap plus
|
|
RoutingUtils.UpdateRoutes(masterRadioIP, true);
|
|
}
|
|
|
|
if (!capacityPlus)
|
|
{
|
|
//start SMS for current ip
|
|
if (!SMSReceiveThreadObjArr.ContainsKey(ip))
|
|
{
|
|
SMSReceiveThread SMSReceiveConnection = new SMSReceiveThread(ip, SMSServicePort, messageBusIP, messageBusPort);
|
|
Thread SMSReceiveThreadObj = new Thread(new ThreadStart(SMSReceiveConnection.handleConnection));
|
|
SMSReceiveThreadObj.IsBackground = true;
|
|
SMSReceiveThreadObj.Start();
|
|
|
|
#if LINXB
|
|
SMSReceiveConnection.SmsForLixReceived += SMSReceiveConnection_SmsForLixReceived;
|
|
SMSReceiveConnection.PrivateCallRequestForLinxReceived += SMSReceiveConnection_PrivateCallRequestForLinxReceived;
|
|
#endif
|
|
|
|
SMSReceiveThreadObjArr.Add(ip, SMSReceiveThreadObj);
|
|
}
|
|
}
|
|
|
|
int total_sleep = 0;
|
|
while (!rc.AuthDone && Program.isRunning)
|
|
{
|
|
SafeMobileLib.Utils.WriteLine("Sleeping auth not completed!!!!");
|
|
Thread.Sleep(100);
|
|
total_sleep++;
|
|
if (total_sleep > 50)//after 5sec retry a new auth
|
|
{
|
|
total_sleep = 0;
|
|
SafeMobileLib.Utils.WriteLine("Stopping current AUTH atempt and retry in 5 seconds");
|
|
rc.Stop();
|
|
int c = 0;
|
|
while(c < 50 && Program.isRunning)
|
|
{
|
|
c++;
|
|
Thread.Sleep(100);
|
|
}
|
|
|
|
rc = new RadioConnection(ip, EmergencyServicePort, "XNL_CMDS");
|
|
RadioComArr[ip] = rc;
|
|
rc.Start();
|
|
}
|
|
}
|
|
//start remote stun
|
|
if (!RemoteStunThreadOBJArr.ContainsKey(ip))
|
|
{
|
|
int radioID = Convert.ToInt32(RouteManager.RadioGW_IDs[ip]);
|
|
RemoteStunThread RemoteStunConnection = new RemoteStunThread(rc, ip, radioID, EmergencyServicePort, messageBusIP, messageBusPort);
|
|
Thread RemoteStunThreadOBJ = new Thread(new ThreadStart(RemoteStunConnection.handleConnection));
|
|
RemoteStunThreadOBJ.IsBackground = true;
|
|
RemoteStunThreadOBJ.Start();
|
|
|
|
RemoteStunThreadOBJArr.Add(ip, RemoteStunThreadOBJ);
|
|
RemoteStunConnectionArr.Add(ip, RemoteStunConnection);
|
|
}
|
|
|
|
//start emergency
|
|
if (!EmergencyThreadObjArr.ContainsKey(ip))
|
|
{
|
|
EmergencyThread EmergencyConnection = new EmergencyThread(rc, ip, EmergencyServicePort, messageBusIP, messageBusPort);
|
|
Thread EmergencyThreadObj = new Thread(new ThreadStart(EmergencyConnection.handleConnection));
|
|
EmergencyThreadObj.IsBackground = true;
|
|
EmergencyThreadObj.Start();
|
|
|
|
EmergencyThreadObjArr.Add(ip, EmergencyThreadObj);
|
|
EmergencyConnectionArr.Add(ip, EmergencyConnection);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
SafeMobileLib.Utils.WriteLine("routeManager_OnRadioStatusUpdate status:" + status + " ip:" + ip);
|
|
//remove connections from EMERGEBCY REMOTESTUN radioConnection HASHTABLES
|
|
PingOffFallowUP(ip);
|
|
}
|
|
}
|
|
|
|
|
|
private void PingOffFallowUP(string ip)
|
|
{
|
|
if (EmergencyThreadObjArr.ContainsKey(ip))
|
|
{
|
|
((EmergencyThread)EmergencyConnectionArr[ip]).Disconnect();
|
|
EmergencyThreadObjArr[ip] = null;
|
|
EmergencyThreadObjArr.Remove(ip);
|
|
EmergencyConnectionArr.Remove(ip);
|
|
}
|
|
if (RemoteStunThreadOBJArr.ContainsKey(ip))
|
|
{
|
|
((RemoteStunThread)RemoteStunConnectionArr[ip]).Disconnect();
|
|
RemoteStunThreadOBJArr[ip] = null;
|
|
RemoteStunThreadOBJArr.Remove(ip);
|
|
RemoteStunConnectionArr.Remove(ip);
|
|
}
|
|
if (RadioComArr.ContainsKey(ip))
|
|
{
|
|
RadioComArr[ip].Stop();
|
|
RadioComArr.Remove(ip);
|
|
}
|
|
}
|
|
|
|
#region bg worker registration events
|
|
void bgWorkerRegistration_DoWork(object sender, DoWorkEventArgs e)
|
|
{
|
|
registeredIP = getRegistration();
|
|
}
|
|
|
|
void bgWorkerRegistration_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
|
|
{
|
|
if (wf != null)
|
|
if (wf.IsInitialized)
|
|
if (wf.IsLoaded)
|
|
{
|
|
SafeMobileLib.Utils.WriteLine("Shuting down waiting form");
|
|
wf.Close();
|
|
}
|
|
|
|
if (appServerMissing)
|
|
{
|
|
FeedbackRadMessageBox.ShowError("Could not reach Application Server. Please check the connection and try again!!!", "Connection Error");
|
|
Application.Exit();
|
|
}
|
|
|
|
ContinueConstructor();
|
|
}
|
|
#endregion
|
|
|
|
|
|
private bool appServerMissing = false;
|
|
|
|
private Boolean getRegistration()
|
|
{
|
|
Boolean toReturn = false;
|
|
try
|
|
{
|
|
client = new TcpClient();
|
|
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse(Main.ApplicationServer), registrationPort);
|
|
client.Connect(serverEndPoint);
|
|
NetworkStream clientStream = client.GetStream();
|
|
YourIPaddress = (client.Client.LocalEndPoint.ToString().Split(":".ToCharArray()))[0];
|
|
|
|
Version v = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
|
|
|
|
UTF8Encoding encoding = new UTF8Encoding();
|
|
byte[] buffer = encoding.GetBytes("200");
|
|
//encryption doesn't work, to be added when working
|
|
//byte[] encodedBuffer = Encryption.Encrypt(buffer);
|
|
clientStream.Write(buffer, 0, buffer.Length);
|
|
SafeMobileLib.Utils.WriteLine("Sent registration request to server, waiting...");
|
|
byte[] message = new byte[128];
|
|
//set read timeout to 10s
|
|
clientStream.ReadTimeout = 10000;
|
|
|
|
int result = clientStream.Read(message, 0, message.Length);
|
|
//close waiting thread
|
|
|
|
//byte[] decodedMessage = Encryption.Decrypt(message);
|
|
|
|
String decodedString = encoding.GetString(message).Trim('\0');
|
|
String[] options = decodedString.Split(';');
|
|
|
|
SafeMobileLib.Utils.WriteLine($"Received registration from server {decodedString}")
|
|
;
|
|
if (options[0].Equals("201"))
|
|
{
|
|
if (options[1].StartsWith("invalid"))
|
|
{
|
|
toReturn = false;
|
|
}
|
|
else
|
|
{
|
|
APP_SERVER_VERSION = options[1].Replace("valid-", "");
|
|
messageBusIP = options[2];
|
|
messageBusPort = options[3];
|
|
DBServer = options[4];
|
|
DBSchema = options[5];
|
|
DBUser = options[6];
|
|
DBPass = options[7];
|
|
DBPort = options[8];
|
|
toReturn = true;
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SafeMobileLib.Utils.WriteLine("Exception in gateway:getRegistration():" + ex.ToString(), ConsoleColor.Red);
|
|
|
|
appServerMissing = true;
|
|
}
|
|
return toReturn;
|
|
}
|
|
|
|
/*private int getGWidFromDB(string currentIP)
|
|
{
|
|
DBgatewaysManager dbmanager = new DBgatewaysManager(Main.DBServer, Main.DBSchema, Main.DBUser, Main.DBPass, Main.DBPort);
|
|
List<Gateway> list = dbmanager.getAllGateways();
|
|
foreach (Gateway g in list)
|
|
{
|
|
if (g.Ip == currentIP)
|
|
{
|
|
SafeMobileLib.Utils.WriteLine("Gateway IP found in registration tabel. ID:"+g.Id);
|
|
return g.Id;
|
|
}
|
|
}
|
|
SafeMobileLib.Utils.WriteLine("Gateway IP not found in registration tabel!!!");
|
|
return -1;
|
|
}*/
|
|
|
|
private List<Gateway> getGWidFromDB(string currentIP)
|
|
{
|
|
DBgatewaysManager dbmanager = new DBgatewaysManager(Main.DBServer, Main.DBSchema, Main.DBUser, Main.DBPass, Main.DBPort);
|
|
List<Gateway> list = dbmanager.getAllGateways();
|
|
List<Gateway> listtoreturn = new List<Gateway>();
|
|
foreach (Gateway g in list)
|
|
{
|
|
if (g.Ip == currentIP)
|
|
{
|
|
SafeMobileLib.Utils.WriteLine("Gateway IP found in registration tabel. ID:" + g.Id);
|
|
listtoreturn.Add(g);
|
|
}
|
|
}
|
|
return listtoreturn;
|
|
}
|
|
|
|
void StartLocationService()
|
|
{
|
|
// create thread to listen UDP
|
|
LocationConnection = new LocationThread(LocationServicePort, messageBusIP, messageBusPort);
|
|
LocationThreadObj = new Thread(new ThreadStart(LocationConnection.handleConnection));
|
|
LocationThreadObj.IsBackground = true;
|
|
LocationThreadObj.Start();
|
|
}
|
|
|
|
void StartSMSService()
|
|
{
|
|
|
|
//create thread for sending SMSs to the radios
|
|
SMSSendConnection = new SMSSendThread(SMSServicePort, messageBusIP, messageBusPort);
|
|
SMSSendThreadObj = new Thread(new ThreadStart(SMSSendConnection.handleConnection));
|
|
SMSSendThreadObj.IsBackground = true;
|
|
SMSSendThreadObj.Start();
|
|
|
|
Thread.Sleep(1000);
|
|
if (capacityPlus)
|
|
{
|
|
SafeMobileLib.Utils.WriteLine("StartSMSService for cap plus");
|
|
SMSReceiveConnection = new SMSReceiveThread(masterRadioIP, SMSServicePort, messageBusIP, messageBusPort, SMSSendConnection.udpClientSMS);
|
|
SMSReceiveThreadObj = new Thread(new ThreadStart(SMSReceiveConnection.handleConnection));
|
|
SMSReceiveThreadObj.IsBackground = true;
|
|
SMSReceiveThreadObj.Start();
|
|
|
|
#if LINXB
|
|
SMSReceiveConnection.SmsForLixReceived += SMSReceiveConnection_SmsForLixReceived;
|
|
SMSReceiveConnection.PrivateCallRequestForLinxReceived += SMSReceiveConnection_PrivateCallRequestForLinxReceived;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void StartTelemetryService()
|
|
{
|
|
//create thread for receiving telemetry notifications from the radios
|
|
TelemetryReceiveConnection = new TelemetryReceiveThread(TelemetryServicePort, messageBusIP, messageBusPort);
|
|
TelemetryReceiveThreadObj = new Thread(new ThreadStart(TelemetryReceiveConnection.handleConnection));
|
|
TelemetryReceiveThreadObj.IsBackground = true;
|
|
TelemetryReceiveThreadObj.Start();
|
|
|
|
//create thread for sending telemetry commands to the radios
|
|
TelemetrySendConnection = new TelemetrySendThread(TelemetryServicePort, messageBusIP, messageBusPort);
|
|
TelemetrySendThreadObj = new Thread(new ThreadStart(TelemetrySendConnection.handleConnection));
|
|
TelemetrySendThreadObj.IsBackground = true;
|
|
TelemetrySendThreadObj.Start();
|
|
}
|
|
|
|
void StartTallysmanService()
|
|
{
|
|
//create thread for receiving tallysman notifications from the radios
|
|
TallysmanReceiveConnection = new TallysmanReceiveThread(TallysmanServicePort, messageBusIP, messageBusPort);
|
|
TallysmanReceiveThreadObj = new Thread(new ThreadStart(TallysmanReceiveConnection.handleConnection));
|
|
TallysmanReceiveThreadObj.IsBackground = true;
|
|
TallysmanReceiveThreadObj.Start();
|
|
|
|
//create thread for sending commands to the radios
|
|
|
|
TallysmanSendConnection = new TallysmanSendThread(TallysmanSendPort, messageBusIP, messageBusPort, TallysmanRequestInterval);
|
|
TallysmanSendThreadObj = new Thread(new ThreadStart(TallysmanSendConnection.handleConnection));
|
|
TallysmanSendThreadObj.IsBackground = true;
|
|
TallysmanSendThreadObj.Start();
|
|
|
|
}
|
|
|
|
public static void resetTallysmanCheckTimer(int newvalue)
|
|
{
|
|
TallysmanSendConnection.resetCheckTimer(newvalue);
|
|
}
|
|
|
|
void StartARSService()
|
|
{
|
|
if (capacityPlus)
|
|
{
|
|
SafeMobileLib.Utils.WriteLine("StartARSService for cap plus");
|
|
RoutingUtils.UpdateRoutes( masterRadioIP, true);
|
|
GatewayID_IP radioID_IP = new GatewayID_IP();
|
|
ARSConnection = new ARSThread(radioID_IP, ARSServicePort, true, messageBusIP, messageBusPort);
|
|
Thread ARSThreadObj = new Thread(new ThreadStart(ARSConnection.handleConnection));
|
|
ARSThreadObj.IsBackground = true;
|
|
ARSThreadObj.Start();
|
|
}
|
|
}
|
|
|
|
RadioConnection rc_cap_plus = null;
|
|
void StartRemoteStunService()
|
|
{
|
|
if (capacityPlus)
|
|
{
|
|
SafeMobileLib.Utils.WriteLine("StartRemoteStunService for cap plus");
|
|
|
|
//start radio connection
|
|
|
|
rc_cap_plus = new RadioConnection(masterRadioIP, EmergencyServicePort, "XNL_CMDS");
|
|
if (RadioComArr.ContainsKey(masterRadioIP))
|
|
{
|
|
RadioComArr[masterRadioIP].Stop();
|
|
RadioComArr.Remove(masterRadioIP);
|
|
}
|
|
RadioComArr.Add(masterRadioIP, rc_cap_plus);
|
|
rc_cap_plus.Start();
|
|
|
|
//start remote stun
|
|
if (!RemoteStunThreadOBJArr.ContainsKey(masterRadioIP))
|
|
{
|
|
int radioID = Convert.ToInt32(RouteManager.RadioGW_IDs[masterRadioIP]);
|
|
RemoteStunThread RemoteStunConnection = new RemoteStunThread(rc_cap_plus, masterRadioIP, radioID, EmergencyServicePort, messageBusIP, messageBusPort);
|
|
Thread RemoteStunThreadOBJ = new Thread(new ThreadStart(RemoteStunConnection.handleConnection));
|
|
RemoteStunThreadOBJ.IsBackground = true;
|
|
RemoteStunThreadOBJ.Start();
|
|
|
|
RemoteStunThreadOBJArr.Add(masterRadioIP, RemoteStunThreadOBJ);
|
|
RemoteStunConnectionArr.Add(masterRadioIP, RemoteStunConnection);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void LoadConfig()
|
|
{
|
|
try
|
|
{
|
|
if (!File.Exists(CFG_FILE))
|
|
{
|
|
SafeMobileLib.Utils.WriteLine("Config file doesn't exist. Creating it...", ConsoleColor.Yellow);
|
|
try
|
|
{
|
|
using (FileStream fs = File.Create(CFG_FILE)) { }
|
|
}
|
|
catch (Exception)
|
|
{
|
|
SafeMobileLib.Utils.WriteLine("Application ended!!!! " + CFG_FILE + " could not be created");
|
|
SafeMobileLib.Utils.WriteLine("Press any key to exit...");
|
|
Console.ReadKey();
|
|
System.Environment.Exit(0);
|
|
}
|
|
}
|
|
|
|
source = new IniConfigSource(CFG_FILE);
|
|
|
|
if (source.Configs["Gateway"] == null)
|
|
source.Configs.Add("Gateway");
|
|
|
|
GWID = GetInt32Value("Gateway", "id", -1);
|
|
registrationPort = GetInt32Value("Gateway", "regPort", 5680);
|
|
pingInterval = GetInt32Value("Gateway", "pingInterval", 10000);
|
|
TESTMODE = GetBooleanValue("Gateway", "testmode", false);
|
|
LocalIP = GetStringValue("Gateway", "localIP", "");
|
|
SMSServicePort = GetInt32Value("Gateway", "smsPort", 4007);
|
|
LocationServicePort = GetInt32Value("Gateway", "locationPort", 4001);
|
|
ARSServicePort = GetInt32Value("Gateway", "arsPort", 4005);
|
|
|
|
|
|
/*
|
|
GWID = Convert.ToInt32(source.Configs["Gateway"].Get("id"));
|
|
registrationPort = Convert.ToInt32(source.Configs["Gateway"].Get("regPort"));
|
|
pingInterval = Convert.ToInt32(source.Configs["Gateway"].Get("pingInterval"));
|
|
TESTMODE = Convert.ToBoolean(source.Configs["Gateway"].Get("testmode"));
|
|
*/
|
|
|
|
|
|
if (source.Configs["Database"] == null)
|
|
source.Configs.Add("Database");
|
|
|
|
ApplicationServer = GetStringValue("Server", "IP", "127.0.0.1");
|
|
if (ApplicationServer.Equals("localhost"))
|
|
ApplicationServer = "127.0.0.1";
|
|
|
|
//DBSchema = GetStringValue("Database", "Schema", "safedispatchdb");
|
|
//DBUser = GetStringValue("Database", "User", "postgres");
|
|
//DBPass = GetStringValue("Database", "Passwd", "wizdemo26");
|
|
//DBPort = GetStringValue("Database", "Port", "5432");
|
|
|
|
/*
|
|
DBServer = source.Configs["Database"].Get("IP");
|
|
if (DBServer.Equals("localhost"))
|
|
DBServer = "127.0.0.1";
|
|
|
|
DBSchema = source.Configs["Database"].Get("Schema");
|
|
DBUser = source.Configs["Database"].Get("User");
|
|
DBPort = source.Configs["Database"].Get("Port");
|
|
DBPass = source.Configs["Database"].Get("Passwd");
|
|
*/
|
|
|
|
|
|
if (source.Configs["ARS Service"] == null)
|
|
source.Configs.Add("ARS Service");
|
|
|
|
capacityPlus = GetBooleanValue("ARS Service", "CapacityPlusEnabled", false);
|
|
masterRadioIP = GetStringValue("ARS Service", "MasterRadioIP", "192.168.10.1");
|
|
GetBooleanValue("ARS Service", "Scan for SU presence at statup", false);
|
|
GetInt32Value("ARS Service", "Invalidate SU after", 200);
|
|
GetInt32Value("ARS Service", "Refresh status", 1);
|
|
GetBooleanValue("ARS Service", "Start service at startup", true);
|
|
asioDriverName = GetStringValue("Voice", "driverName", "N/A");
|
|
|
|
/*
|
|
capacityPlus = Convert.ToBoolean(source.Configs["ARS Service"].Get("CapacityPlusEnabled"));
|
|
masterRadioIP = source.Configs["ARS Service"].Get("MasterRadioIP");
|
|
*/
|
|
|
|
|
|
if (source.Configs["MessageBus"] == null)
|
|
source.Configs.Add("MessageBus");
|
|
|
|
//messageBusIP = GetStringValue("MessageBus", "ip", "224.30.0.1");
|
|
//messageBusPort = GetStringValue("MessageBus", "port", "17233");
|
|
|
|
/*
|
|
messageBusIP = source.Configs["MessageBus"].Get("ip");
|
|
messageBusPort = source.Configs["MessageBus"].Get("port");
|
|
*/
|
|
|
|
|
|
if (source.Configs["Tallysman"] == null)
|
|
source.Configs.Add("Tallysman");
|
|
|
|
TallysmanServicePort = (ushort)GetInt32Value("Tallysman", "port", 4010);
|
|
|
|
/*
|
|
try
|
|
{
|
|
TallysmanServicePort = Convert.ToUInt16(source.Configs["Tallysman"].Get("port"));
|
|
}
|
|
catch
|
|
{
|
|
TallysmanServicePort = 4010;
|
|
}*/
|
|
|
|
TallysmanRequestInterval = GetInt32Value("Tallysman", "checkInterval", -1);
|
|
|
|
if (source.Configs["SMS"] == null)
|
|
source.Configs.Add("SMS");
|
|
|
|
wait4ack = GetBooleanValue("SMS", "wait4ack", true);
|
|
sms_sending_interval = GetInt32Value("SMS", "sending_interval", 1200);
|
|
number_of_retries = GetInt32Value("SMS", "number_of_retries", 3);
|
|
retry_interval_sec = GetInt32Value("SMS", "retry_interval_sec", 180);
|
|
|
|
/*
|
|
wait4ack = Convert.ToBoolean(source.Configs["SMS"].Get("wait4ack"));
|
|
sms_sending_interval = Convert.ToInt32(source.Configs["SMS"].Get("sending_interval"));
|
|
number_of_retries = Convert.ToInt32(source.Configs["SMS"].Get("number_of_retries"));
|
|
|
|
if (source.Configs["SMS"].Contains("retry_interval_sec"))
|
|
retry_interval_sec = Convert.ToInt32(source.Configs["SMS"].Get("retry_interval_sec"));
|
|
*/
|
|
|
|
if (source.Configs["Update"] == null)
|
|
source.Configs.Add("Update");
|
|
|
|
autoupdate = GetBooleanValue("Update", "autoupdate", true);
|
|
|
|
if (source.Configs["Update"].Contains("develop"))
|
|
isDevelope = source.Configs["Update"].GetBoolean("develop");
|
|
|
|
GetStringValue("Update", "Version", "1.0.0.2");
|
|
GetBooleanValue("Update", "Enable", true);
|
|
|
|
/*
|
|
try
|
|
{
|
|
if (!source.Configs["Update"].Contains("autoupdate"))
|
|
source.Configs["Update"].Set("autoupdate", true);
|
|
|
|
autoupdate = source.Configs["Update"].GetBoolean("autoupdate");
|
|
|
|
if (source.Configs["Update"].Contains("develop"))
|
|
isDevelope = source.Configs["Update"].GetBoolean("develop");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SafeMobileLib.Utils.WriteLine("AUTOUPDATE " + ex.ToString(), ConsoleColor.Red);
|
|
}
|
|
*/
|
|
|
|
|
|
if (source.Configs["Voice"] == null)
|
|
source.Configs.Add("Voice");
|
|
|
|
GetBooleanValue("Voice", "onOFF", false);
|
|
GetStringValue("Voice", "SelectedOutDevice", "");
|
|
GetStringValue("Voice", "SelectedInDevice", "");
|
|
GetStringValue("Voice", "RadioIP", "192.168.10.40");
|
|
GetStringValue("Voice", "MulticastIP", "224.30.0.1");
|
|
GetInt32Value("Voice", "Port", 17234);
|
|
string audioDriver = GetStringValue("Voice", "driver", "windows");
|
|
if (audioDriver.ToLower() == "asio")
|
|
AudioDriver = AudioDriverType.Asio;
|
|
else
|
|
AudioDriver = AudioDriverType.Windows;
|
|
|
|
//GetInt32Value("Voice", "radioNr", 0);
|
|
|
|
|
|
/*
|
|
[Voice]
|
|
SelectedOutDevice = Speakers(USB VoIP Device)
|
|
SelectedInDevice = Microphone(USB VoIP Device)
|
|
RadioIP = 192.168.10.40
|
|
MulticastIP = 224.30.0.1
|
|
onOFF = false
|
|
port = 17234*/
|
|
|
|
source.Save();
|
|
|
|
SafeMobileLib.Utils.WriteLine("Gateway ID:" + GWID, ConsoleColor.Green);
|
|
SafeMobileLib.Utils.WriteLine("Ping Interval:" + pingInterval, ConsoleColor.Green);
|
|
|
|
|
|
#region LINX
|
|
#if LINXB
|
|
_minSipPort = GetInt32Value("LINX", "minSipPort", 3024);
|
|
_maxSipPort = GetInt32Value("LINX", "maxSipPort", 3999);
|
|
if (_maxSipPort <= _minSipPort)
|
|
{
|
|
// Error in config file. Get back to defaults
|
|
_minSipPort = 3024;
|
|
_maxSipPort = 3999;
|
|
}
|
|
|
|
|
|
SafeMobileLib.Utils.WriteLine($"Sip Ports Range: {_minSipPort} - {_maxSipPort}", ConsoleColor.Green);
|
|
|
|
#endif
|
|
#endregion
|
|
|
|
if (TESTMODE)
|
|
{
|
|
SafeMobileLib.Utils.WriteLine("WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW");
|
|
SafeMobileLib.Utils.WriteLine("WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW");
|
|
SafeMobileLib.Utils.WriteLine("WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW");
|
|
SafeMobileLib.Utils.WriteLine("---------------------------------------");
|
|
SafeMobileLib.Utils.WriteLine("!!!!Warning TEST MODE activated!!!!!");
|
|
SafeMobileLib.Utils.WriteLine("If this is a live GW please go to config and mask GATEWAY->testmode = false;");
|
|
SafeMobileLib.Utils.WriteLine("---------------------------------------");
|
|
SafeMobileLib.Utils.WriteLine("WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW");
|
|
SafeMobileLib.Utils.WriteLine("WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW");
|
|
SafeMobileLib.Utils.WriteLine("WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW");
|
|
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
SafeMobileLib.Utils.WriteLine("LoadConfig Exception" + e.ToString(), ConsoleColor.Red);
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Get an int value from the configuration file. The desired value is identifiec by
|
|
/// the key and the header under which is placed is pointed by the header. Also a default
|
|
/// value can be set in case the value doesn't exist and needs to be created before
|
|
/// beeing returned
|
|
/// </summary>
|
|
/// <param name="header">Header unde which the desired config parameter is placed</param>
|
|
/// <param name="key">The Key that designates the desired config parameter</param>
|
|
/// <param name="defaultValue">A default value that will be used and returned in case the
|
|
/// config file doesn't have a value for the parameter</param>
|
|
/// <returns>Parameter value from the config file, or the default value in case it doesn't
|
|
/// exist</returns>
|
|
private Int32 GetInt32Value(String header, String key, Int32 defaultValue)
|
|
{
|
|
if (!source.Configs[header].Contains(key))
|
|
source.Configs[header].Set(key, defaultValue);
|
|
|
|
return source.Configs[header].GetInt(key);
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Get a string value from the configuration file. The desired value is identifiec by
|
|
/// the key and the header under which is placed is pointed by the header. Also a default
|
|
/// value can be set in case the value doesn't exist and needs to be created before
|
|
/// beeing returned
|
|
/// </summary>
|
|
/// <param name="header">Header unde which the desired config parameter is placed</param>
|
|
/// <param name="key">The Key that designates the desired config parameter</param>
|
|
/// <param name="defaultValue">A default value that will be used and returned in case the
|
|
/// config file doesn't have a value for the parameter</param>
|
|
/// <returns>Parameter value from the config file, or the default value in case it doesn't
|
|
/// exist</returns>
|
|
private String GetStringValue(String header, String key, String defaultValue)
|
|
{
|
|
if (!source.Configs[header].Contains(key))
|
|
source.Configs[header].Set(key, defaultValue);
|
|
|
|
return source.Configs[header].GetString(key);
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Get a boolean value from the configuration file. The desired value is identifiec by
|
|
/// the key and the header under which is placed is pointed by the header. Also a default
|
|
/// value can be set in case the value doesn't exist and needs to be created before
|
|
/// beeing returned
|
|
/// </summary>
|
|
/// <param name="header">Header unde which the desired config parameter is placed</param>
|
|
/// <param name="key">The Key that designates the desired config parameter</param>
|
|
/// <param name="defaultValue">A default value that will be used and returned in case the
|
|
/// config file doesn't have a value for the parameter</param>
|
|
/// <returns>Parameter value from the config file, or the default value in case it doesn't
|
|
/// exist</returns>
|
|
private Boolean GetBooleanValue(String header, String key, Boolean defaultValue)
|
|
{
|
|
if (!source.Configs[header].Contains(key))
|
|
source.Configs[header].Set(key, defaultValue);
|
|
|
|
return source.Configs[header].GetBoolean(key);
|
|
}
|
|
|
|
|
|
private void 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)
|
|
{
|
|
SafeMobileLib.Utils.WriteLine("App already running!!!");
|
|
|
|
|
|
FeedbackRadMessageBox.ShowError("Aplication already running!!", "error");
|
|
|
|
foreach (Process theprocess in processlist)
|
|
{
|
|
if (theprocess.ProcessName == curentP.ProcessName)
|
|
{
|
|
SafeMobileLib.Utils.WriteLine($"Process: {theprocess.ProcessName} ID: {theprocess.Id}");
|
|
SafeMobileLib.Utils.WriteLine($"Curent Process: {curentP.ProcessName} ID: {curentP.Id}");
|
|
if (theprocess.Id != curentP.Id)
|
|
{
|
|
SafeMobileLib.Utils.WriteLine($"Killing Process: {theprocess.ProcessName} ID: {theprocess.Id}");
|
|
theprocess.Kill();
|
|
}
|
|
}
|
|
}
|
|
Thread.Sleep(1000);
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region tabs load functions
|
|
private void radRibbonBar1_CommandTabSelected(object sender, Telerik.WinControls.UI.CommandTabEventArgs args)
|
|
{
|
|
|
|
if (args.CommandTab == tabVoice)
|
|
{
|
|
SafeMobileLib.Utils.WriteLine("Why load Voice Tab here???", ConsoleColor.Magenta);
|
|
//LoadVoiceTab(true);
|
|
}
|
|
}
|
|
|
|
private void LoadRadioTab(bool mainTab)
|
|
{
|
|
if (mainTab)
|
|
{
|
|
voiceMainCTRL = new controlVoiceMain();
|
|
voiceMainCTRL.Dock = System.Windows.Forms.DockStyle.Fill;
|
|
MainPanel.Controls.Clear();
|
|
MainPanel.Controls.Add(voiceMainCTRL);
|
|
|
|
_listOfRadioForms = voiceMainCTRL.radiosFormList;
|
|
|
|
#if LINXB
|
|
foreach (radioForm radioF in voiceMainCTRL.radiosFormList)
|
|
{
|
|
radioF.StartedRadioComHandler += RadioF_StartedRadioComHandler;
|
|
radioF.StoppingRadioComHandler += RadioF_StoppingRadioComHandler;
|
|
}
|
|
#endif
|
|
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
private void btnVoiceAdd_Click(object sender, EventArgs e)
|
|
{
|
|
//voiceMainCTRL.AddNewRadio();
|
|
}
|
|
|
|
private void btnVoiceRemove_Click(object sender, EventArgs e)
|
|
{
|
|
//voiceMainCTRL.RemoveRadio();
|
|
}
|
|
|
|
private void Main_FormClosing(object sender, FormClosingEventArgs e)
|
|
{
|
|
|
|
wf?.Close();
|
|
|
|
Program.isRunning = false;
|
|
|
|
SafeMobileLib.Utils.WriteEventLog("SafeMobile", "Gateway Closing", EventLogEntryType.Information, 21523);
|
|
|
|
if (voiceMainCTRL != null)
|
|
{
|
|
voiceMainCTRL.SaveConfigForRadios();
|
|
try
|
|
{
|
|
// Clear voice resources
|
|
ClearAsioResources();
|
|
foreach (radioForm r in voiceMainCTRL.radiosFormList)
|
|
{
|
|
if (r.rcHandler != null)
|
|
{
|
|
//if (r.rcHandler.nVOice != null)
|
|
// r.rcHandler.nVOice.Dispose();
|
|
|
|
//if (r.rcHandler.waveOutClass != null)
|
|
//{
|
|
// r.rcHandler.waveOutClass.Dispose();
|
|
// r.rcHandler.waveOutClass = null;
|
|
//}
|
|
|
|
//if (r.rcHandler.waveInClass != null)
|
|
//{
|
|
// r.rcHandler.waveInClass.DataAvailable -= r.rcHandler.waveInClass_DataAvailable;
|
|
// r.rcHandler.waveInClass.Dispose();
|
|
// r.rcHandler.waveInClass = null;
|
|
//}
|
|
|
|
r.rcHandler.ClearVoiceResources();
|
|
}
|
|
}
|
|
|
|
#region LINX
|
|
#if LINXB
|
|
if (_sipGateway != null)
|
|
{
|
|
_sipGateway.Stop();
|
|
}
|
|
#endif
|
|
|
|
#endregion
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SafeMobileLib.Utils.WriteLine("Main_FormClosing: " + ex.ToString(), ConsoleColor.Red);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void ClearAsioResources()
|
|
{
|
|
if (_audioManager != null)
|
|
{
|
|
_audioManager.AsioAudioAvailable -= AudioManager_AsioAudioAvailable;
|
|
_audioManager.PlaybackStopped -= AudioManager_PlaybackStopped;
|
|
_audioManager.Dispose();
|
|
_audioManager = null;
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Close necessary things before closing the app
|
|
/// </summary>
|
|
private void CloseApp()
|
|
{
|
|
// close necessary things in the app
|
|
Main_FormClosing(null, null);
|
|
|
|
Process oldProcess = Process.GetCurrentProcess();
|
|
oldProcess.Kill();
|
|
Application.Exit();
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Update a specific config file parameter from a desired category.
|
|
/// </summary>
|
|
/// <param name="category">Category in which the parameter is located</param>
|
|
/// <param name="option">Parameter which needs to be updated</param>
|
|
/// <param name="value">New value for the desired parameter</param>
|
|
public static void UpdateConfigParameter(string category, string option, string value)
|
|
{
|
|
try
|
|
{
|
|
source = new IniConfigSource(CFG_FILE);
|
|
//DataBase
|
|
source.Configs[category].Set(option, value);
|
|
// Save the INI file
|
|
source.Save();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SafeMobileLib.Utils.WriteLine(ex.ToString());
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private void Main_Resize(object sender, EventArgs e)
|
|
{
|
|
if (this.WindowState == FormWindowState.Minimized)
|
|
{
|
|
this.Visible = false;
|
|
notifyIcon1.Visible = true;
|
|
}
|
|
}
|
|
|
|
private void notifyIcon1_DoubleClick(object sender, EventArgs e)
|
|
{
|
|
this.Visible = true;
|
|
this.WindowState = FormWindowState.Normal;
|
|
notifyIcon1.Visible = false;
|
|
}
|
|
|
|
private void radCheckBoxElement1_Click(object sender, EventArgs e)
|
|
{
|
|
try
|
|
{
|
|
if (!cbCapacityPlus.Checked)
|
|
{
|
|
CapacityPlusIP tmp = new CapacityPlusIP(masterRadioIP);
|
|
tmp.ShowDialog();
|
|
System.Threading.Timer tCheckSTATUS = new System.Threading.Timer(UncheckCapPlus, null, 500, System.Threading.Timeout.Infinite);
|
|
}
|
|
else
|
|
{
|
|
lbMasterIP.Text = "";
|
|
RestoreDefaulCapacityConfig();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SafeMobileLib.Utils.WriteLine("Error on click capacityPuls:"+ex.ToString(), ConsoleColor.Red);
|
|
}
|
|
}
|
|
|
|
private void Main_Load(object sender, EventArgs e)
|
|
{
|
|
ContextMenu contextMenu = new ContextMenu();
|
|
contextMenu.MenuItems.Add("Check for updates...", (s, e2) => {
|
|
UpdateForm uf = new UpdateForm(App.GW_TRBO, true) { IsDevelop = Main.isDevelope };
|
|
uf.Show();
|
|
});
|
|
contextMenu.MenuItems.Add("Exit", (s, e2) => CloseApp());
|
|
notifyIcon1.ContextMenu = contextMenu;
|
|
|
|
// check for a new version if available
|
|
if(Main.isDevelope)
|
|
CheckForUpdate(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(bool isModal)
|
|
{
|
|
App appType = App.GW_TRBO;
|
|
if (isModal)
|
|
{
|
|
UpdateForm uf = new UpdateForm(appType, true) { IsDevelop = Main.isDevelope };
|
|
uf.ShowDialog();
|
|
}
|
|
else
|
|
{
|
|
AutoUpdate au = new AutoUpdate(appType) { IsDevelop = Main.isDevelope };
|
|
|
|
au.OnNewVersionAvailable += delegate (string version)
|
|
{
|
|
if (APP_SERVER_VERSION.Split('.')[2].Equals(version.Split('.')[2]))
|
|
{
|
|
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 = Main.isDevelope };
|
|
uf.Show();
|
|
}
|
|
};
|
|
}
|
|
else
|
|
SafeMobileLib.Utils.WriteLine("New version available but AppServer is an old version stil");
|
|
};
|
|
|
|
// call method to check for new updated
|
|
au.CheckUpdate();
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
private void UncheckCapPlus(Object state)
|
|
{
|
|
try
|
|
{
|
|
cbCapacityPlus.Checked = false;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SafeMobileLib.Utils.WriteLine("Unable to uncheck capacityPuls:"+ex.ToString(), ConsoleColor.Red);
|
|
}
|
|
}
|
|
|
|
public void RestoreDefaulCapacityConfig()
|
|
{
|
|
source = new IniConfigSource(Main.CFG_FILE);
|
|
source.Configs["ARS Service"].Set("MasterRadioIP", "192.168.10.40");
|
|
source.Configs["ARS Service"].Set("CapacityPlusEnabled", "False");
|
|
source.Save();
|
|
}
|
|
|
|
internal static List<radioForm.sDevice> GetAsioInputDevices()
|
|
{
|
|
return _audioManager?.GetAsioInputDevices();
|
|
}
|
|
|
|
internal static List<radioForm.sDevice> GetAsioOutputDevices()
|
|
{
|
|
return _audioManager?.GetAsioOutputDevices();
|
|
}
|
|
|
|
private void Main_FormClosed(object sender, FormClosedEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
//System.Environment.Exit(0);
|
|
Application.Exit();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SafeMobileLib.Utils.WriteLine("Error on closing: "+ex.ToString(), ConsoleColor.Red);
|
|
}
|
|
}
|
|
|
|
private void settingsRibbon_Click(object sender, EventArgs e)
|
|
{
|
|
SettingsForm sf = new SettingsForm();
|
|
sf.ShowDialog();
|
|
}
|
|
|
|
private void RadioF_StoppingRadioComHandler(object sender, RadioComHandler rcHandler)
|
|
{
|
|
#if LINXB
|
|
// Remove event halders
|
|
rcHandler.LinxCallEstablished -= RcHandler_LinxCallEstablished;
|
|
rcHandler.CallLinx -= RcHandler_CallLinx;
|
|
rcHandler.RadioEndsPTTtoLinx -= RcHandler_RadioEndsPTTtoLinx;
|
|
rcHandler.RadioVoiceToLinx -= RcHandler_RadioVoiceToLinx;
|
|
rcHandler.RadioSipIDRequested -= RcHandler_RadioSipIDRequested;
|
|
rcHandler.LinxIDForPrivateCallRequested -= RcHandler_LinxIDForPrivateCallRequested;
|
|
rcHandler.LinxCallFailed -= RcHandler_LinxCallFailed;
|
|
#endif
|
|
}
|
|
|
|
private void RadioF_StartedRadioComHandler(object sender, RadioComHandler rcHandler)
|
|
{
|
|
|
|
#if LINXB
|
|
// Add event handlers
|
|
rcHandler.LinxCallEstablished += RcHandler_LinxCallEstablished;
|
|
rcHandler.CallLinx += RcHandler_CallLinx;
|
|
rcHandler.RadioEndsPTTtoLinx += RcHandler_RadioEndsPTTtoLinx;
|
|
rcHandler.RadioVoiceToLinx += RcHandler_RadioVoiceToLinx;
|
|
rcHandler.RadioSipIDRequested += RcHandler_RadioSipIDRequested;
|
|
rcHandler.LinxIDForPrivateCallRequested += RcHandler_LinxIDForPrivateCallRequested;
|
|
rcHandler.LinxCallFailed += RcHandler_LinxCallFailed;
|
|
#endif
|
|
}
|
|
|
|
|
|
}
|
|
|
|
public class ShapeNew : ShapedForm
|
|
{
|
|
public Boolean typeRadio = true;
|
|
public Int32 ID = 0;
|
|
public Boolean Selected = false;
|
|
public Boolean VoiceON = true;
|
|
}
|
|
|
|
public enum AudioDriverType
|
|
{
|
|
Windows,
|
|
Asio,
|
|
Unknown
|
|
}
|
|
} |